I have a script (let’s call it “child”) with a few optional variables. In that script I test if the optional variables are defined and if not so, then I use a default value that I also define within that script. The script is set up to deal with a specific entity and it is important that only entity is passed to it. So far so good and the script runs smoothly.
Now I also have a second script (let’s call it “parent”) that is there to enable the same procedure for multiple entities. So it accepts the same list of variables as “child”, however, potentially multiple entities, and then calls “child” for each entity separately. What I don’t know yet is how to test if a variable is defined within “parent” and if not, then simply not passing that variable at all to “child”, as the default value should obviously only be defined in one place and that is within “child”.
Minimal current setup looks like this (simplified!):
parentscript:
alias: "parent"
mode: queued
fields: # only for illustration purposes here, strongly simplified
entity_id # mandatory
variable2 # optional
sequence:
- repeat:
count: "{{ entity_id | length }}"
sequence:
- service: script.turn_on
entity_id: script.childscript
data_template:
variables:
name: "{{ entity_id[repeat.index - 1] }}"
# and here is the issue, I would like to do something like (in natural language)
# if variable2 is defined then pass
# variable2: "{{ variable2 }}"
# else pass nothing
The “child” script that works
childscript:
alias: "child"
mode: parallel
variables:
default_variable2: 0.5
fields: # only for illustration purposes here, strongly simplified
name # mandatory
variable2 # optional
sequence:
- service: xyz
data_template:
entity_id: "{{ name }}"
var: "{{ variable2 if variable2 is defined else default_variable2 }}"
Would appreciate if anybody could help out here. Thank you!
I’m just going to start by saying that the situation you’re presenting sounds like you’re making things particularly complicated for no reason, as whatever calls parent could just as easily call child directly.
But I’m not going to get into it any deeper because the “let’s call it this” and “let’s call it that” style of questions here often leads to someone spending hours trying to fix the problem you asked in post one, only for you to provide the ‘real’ code in post thirty-five and the solution no longer being suitable and someone having to spend even longer trying to fix it.
So, my suggestion is:
A - try and simplify your process
B - show us the REAL code and define a REAL example of usage
I know you probably don’t intend to waste anyone’s time, but threads that start like this one invariably do accidentally
indeed wanted to simplify things. The “child” script calls a specific google home device, saves the volume there, adjusts the volume, then broadcasts a message and then turns the volume back. The parent script is there to a play a specific message on multiple google home devices at the same time. Therefore the child script runs in parallel for multiple devices and the parent script runs in a queued mode to not have conflicts with multiple messages.
The full scripts (with additional complexity) - parent:
cast_msg_ghome:
alias: 'Broadcast a message on one or more devices'
description: 'Broadcasts a message on set of Google Home devices at a given volume, then restores the original volume of each device'
mode: queued
fields:
entity_id:
description: 'Entity ID of the device the message should be broadcasted to'
example: 'media_player.xyz'
msg:
description: 'Message to be broadcasted'
example: 'This is a message'
lang:
description: 'Language the message is in'
example: 'de'
vol:
description: 'Target volume for broadcasted message'
example: 0.5
sequence:
- repeat:
count: "{{ entity_id | length }}"
sequence:
- service: script.turn_on
entity_id: script.cast_msg_single_ghome
data_template:
variables:
device_name: "{{ entity_id[repeat.index - 1] }}"
msg: "{{ msg }}"
### this is where the optional variables would need to be put
And the “child” script:
cast_msg_single_ghome:
alias: 'Broadcast a message on a single device'
description: 'Broadcasts a message on a specific Google Home device at a given volume, then restores the original volume'
mode: parallel
variables:
timeout_value: 30
curr_vol:
name: 'Current volume'
min: 0
max: 1
default_lang: 'de'
default_vol: 0.7
fields:
device_name:
description: 'Entity ID of the device the message should be broadcasted to'
example: 'media_player.xyz'
msg:
description: 'Message to be broadcasted'
example: 'This is a message'
lang:
description: 'Language the message is in'
example: 'de'
vol:
description: 'Target volume for broadcasted message'
example: 0.5
sequence:
- service: media_player.play_media
data_template:
entity_id: "{{ device_name }}"
media_content_type: music
# media_content_id: "{{ states('input_text.base_url') + '/local/audio/250-milliseconds-of-silence.mp3' }}"
media_content_id: https://github.com/anars/blank-audio/raw/master/250-milliseconds-of-silence.mp3
- delay:
milliseconds: 250
- variables:
curr_vol: "{{ state_attr( device_name ,'volume_level') | float }}"
- service: media_player.volume_set
data_template:
entity_id: "{{ device_name }}"
volume_level: "{{ vol if vol is defined else default_vol }}"
- service: tts.google_say
data_template:
entity_id: "{{ device_name }}"
message: "{{ msg }}"
language: "{{ lang if lang is defined else default_lang }}"
- delay:
seconds: 2
- wait_template: "{{ not(is_state( device_name , 'playing')) }}"
timeout:
seconds: "{{ timeout_value }}"
- service: media_player.volume_set
data_template:
entity_id: "{{ device_name }}"
volume_level: "{{ curr_vol | float }}"
Not sure though if this really simplifies the problem Also, I don’t think I can combine the 2 scripts as long as I want the messages to be broadcasted in parallel on the given devices and the devices having different volume levels set to start with.
Okay, I did find a solution that works, even if not very elegant. If someone has a nicer solution, of course would be happy to learn how to not pass the respective variables depending on a test if it is defined at all or not. My solution:
I am passing the volume as follows in the “parent” script:
and then I am simply testing for it in the “child” script:
- service: media_player.volume_set
data_template:
entity_id: "{{ device_name }}"
volume_level: "{{ vol if vol is defined and vol>0 else default_vol }}"
Just got back to this thread so haven’t read the big post in the middle properly, but is there any reason to not put the sequence of the child script in the parent script? Isn’t it more likely that your ‘group’ messages would want to be sent to a group of devices at the same time rather than send the same message to multiple devices one after the other?
But yeah, having a ‘default’ if nothing is passed to a script is the way to do it.
Thanks for coming back! Yep, ideally they are sent at the same time, however, I have the complication that I am saving the original volume in the single_script, then change it, and then restore it. Since the original volume is specific for each device, I need to save it separately and that’s why I have a separate script for it. if there is a simpler approach, I am all for it