I have a called script that may stop or continue at different points, depending on some conditions, and return some information to the calling script whenever it stops, using the response_variable. But the problem is that if the stop command is within a conditional if, the calling script doesn’t get the response_variable, although it works perfectly when the stop command is on the the first level, not within a conditional.
I know it sounds like and XY problem, but I really want to understand this, as working around this limitation may make what I want to do much more complex. Is this a bug?
Here’s a simplified example of what I am talking about:
Calling script:
alias: test 1
sequence:
- service: script.test_2
data: {}
response_variable: test
- service: notify.mobile_app_myphone
data:
message: "{{ test.context_id }} {{ test.resultat }}"
mode: single
Called script:
alias: test 2
sequence:
- variables:
test:
context_id: asdlfkj1234lj
resultat: success
- if:
- condition: time
after: "10:00:00"
then:
- variables:
test:
context_id: asdlfkj1234lj
resultat: fail
- stop: ""
response_variable: test
- stop: ""
response_variable: test
mode: single
Is there a way to return the response_variable when the script is stopped in a conditional?
I understand that, but since the stop command is within the conditional, on the same level where the variable test.resultat: fail is defined, it should be able to see it.
Is the suggestion that the variable’s name needs to be wrapped in double quotes?
If you refer to the first post, it reports that the final stop works (and test is not wrapped in quotes). It’s the stop inside the if that is unable to pass the variable test and that’s due to scope constraints.
The workaround I have found for my problem consists in the called script to trigger a manual event that will include whatever information and variables I want, followed by the STOP command (with no response in that one).
In the calling script, I call the other in parallel, altogether with a wait for trigger - event that will capture the information sent by the called script. Note that whatever command following the wait for trigger must be at the same level of sequence than the wait for trigger (at least for my use case).
Here is a model of what I did:
- parallel:
- service: script.example
data:
some_variable: some information
- sequence:
- wait_for_trigger:
- platform: event
event_type: my_personal_event
event_data:
success: true
id: is_finished
- some other stuff etc:
I think there is a potential race condition here which might result in your solution unpredictably failing to work as expected.
In particular, you are not necessarily guaranteed that the wait_for_trigger will execute before script.example completes. The doc about “parallelizing actions” says that “There is no order guarantee. The actions will be started in parallel, but there is no guaranteed that they will be completed in the same order.”
So, it’s theoretically possible here that my_personal_event will fire before your wait_for_trigger can catch it, in which case the code will just hang waiting for the event. It’s like throwing the ball before your receiver is ready to catch it.
I don’t know how LIKELY it is in practice that you would hit that situation. But as I understand how a “parallel” block works, this example is not guaranteed to work the way you report it’s working for you in practice.
I hate to poke holes because I’m trying to find a solution for the same exact “can’t use response_variable from within a nested block” issue. I haven’t found one so far. But I point this out because race conditions can manifest unpredictably and be difficult to reproduce–which means that unless you are aware for the potential of a race condition, you might have a very hard time debugging the problem when it shows up.
I’ve got another solution for which may be of use to some. I’ve got a script to send a yes/no question to my smartphone and since this is always the same except for message and mapping IDs, I’ve created this script. If you don’t need to stop the script in some nested action and use wait_for_trigger you can do this: