Looking for some advice about the use of variables within scripts. I would like to set a variable to an entity ID. In this case a speaker.
I’ve read about the use of variables here and I can pass a variable from an automation into a script but I’d like to conditionally set an entity_id to a variable and use that to play on the required speaker.
I’ve looked through various examples but I’m sorry to say I can’t see something that fits. So:
Here is a field I am passing into the script. It contains the message:
announcement:
selector:
text: {}
name: Announcement
description: The announcement that should be played
required: true
A variable I am trying to set with an IF statement:
alias: Set the speaker according to location
if:
- condition: state
entity_id: input_select.steve_location
state: Downstairs
alias: Steve location is downstairs
then:
- variables:
target_speaker: media_player.home_pod_mini_kitchen
alias: Set the speaker variable to kitchen
else:
- variables:
target_speaker: media_player.google_home_speaker
alias: Set the speaker location to the google speaker
The service call I am trying to use:
alias: Play the announcement on the selected speaker
service: chime_tts.say
data:
final_delay: 0
volume_level: "{{ states ('input_number.announcement_volume') }}"
message: "{{ announcement }}"
tts_platform: cloud
chime_path: custom_chime_path_2
cache: true
target:
entity_id: "{{ target_speaker }}"
the issue is that a variable is valid only within the scope block where it was defined. and at the beginning of that scope block. so your target_speaker variable is defined within the “then” block and also within the “else” block and then gone.
could you post your entire automation for the second block (where you’re trying to define the variable). post that whole automation. it’ll be easier to show you how to do it that way.
The variable target_speaker is defined exclusively within the scope of the if and else sections and is undefined outside of them. That’s likely why the following line is responsible for the error message. It exists outside the bounds of where the target_speaker variable is defined.
It’s not hard to fix but we would first have to see the complete scripts/automations because it’s unclear from the examples you posted (which appear to be fragments of one or more scripts/automations).
Thanks, the blocks are the script. The idea is that it is called from an automation with a message sent to a field. The message is then played on speaker according to the value in the location input helper.
I vaguely remember a way to ‘export’ a variable, perhaps a response_variable so it available outside its own block. Is that right?
Perhaps it is better to use something like this instead:
i undestand that the blocks are parts of the script. it’d be helpful to have the whole automation. if you don’t want to post that for some reason, then work from what i posted above.
wrt response_variable. no. that’s how you return a value from a script to the calling automation.
either take a look at my two posts… the first explains what is going wrong with what you had. the second is a total guess as to what you’re trying to do. but to move it from a guess to make it work… post your code and i or someone else can tell you specifically
yes, that approach will work if you only want to use it in one place. your origianl question was about how to make the variable work… which is then useful to use in multiple places. the code i provided will do that.
if you want to do this approach, a more concise method (but equivalent to what you have) is to do this:
Here is a block within (a quite large automation) that calls the script. Presently there is an if statement here within the automation block that sets the speaker. I want to change it so the selection occurs within the script instead of the automation as I am calling the script from multiple automations. That way if I want to change the speakers I only have to do within the script.
alias: Select the speaker to send the announcement to
if:
- condition: state
entity_id: input_select.steve_location
state: Downstairs
alias: If Steve is downstairs play the announcement on the Kitchen speaker
then:
- service: script.play_an_announcement
metadata: {}
data:
announcement: Two hours to sunset
target_speaker: media_player.home_pod_mini_kitchen
alias: Play announcement down stairs
else:
- alias: Play announcement on google speaker
service: script.play_an_announcement
metadata: {}
data:
announcement: Two hours to sunset
target_speaker: media_player.google_home_speaker
ok. maybe i misunderstood then. in your original question you had asked about how to get the variable set first then use it later when you call the script.
sounds like now you want to move the whole logic into the script and out of the automation completely. if that’s the case and you’re willing to check input_select.steve_location inside the script then you should either do something like this if you only need to use it once:
Firstly, I apologise that my OP was unclear. Thanks very much for the information you’ve given. The example in your first code block looks right, I’ll give that a try. Thanks again for your help and patience, its very much appreciated.