Has anyone succeeded in working with response_variables?

I stumbled acdross this example, but it doesn’t work, can anyone see what’s wrong with it?

add_five:
  variables:
    value_plus_five: >
      {{ {'value': value + 5} }}
  sequence:
  - stop: "returning value + 5"
    response_variable: value_plus_five

I believe you’d just call the script like this as well.

- service: script.add_five
  data:
    value: 3
  response_variable: result

What you have posted is working…

image

Then the next step would be something like:

alias: Test Response Variables
sequence:
  - service: script.add_five
    data:
      value: 3
    response_variable: result
  - service: persistent_notification.create
    data:
      message: The results of 'Add Five' is {{ result.value }}
mode: single

hi, yes I just found out, something went wrong during copying.

Is there a way to alter the response value in an if-then-else sequence? I’m trying something like this:

> alias: returnvarscript
> variables:
>   input_boolean: test
> sequence:
>   - service: input_boolean.turn_on
>     data: {}
>     target:
>       entity_id: input_boolean.test
>   - stop: returning
>     response_variable: test

You haven’t defined a variable named test, so it won’t be returned as a response. Also, the response data must contain a mapping of key/value pairs.

It is unclear what you are actually trying to do in your posted example.

Not using an if then action. You can by using if-elif-else in jinja. Actions have variable scope limitations, all your logic needs to be at the same “level”, i.e. not in a then or else on an if-then-else action.

To illustrate Petro’s point…

Using if/then in the Jinja template will work:

alias: Add Three or Five Jinja
sequence:
  - variables:
      if_then_add: |
        {% set x = value + 5 if value is odd else value + 3 %}
        {{ {'value': x} }}
  - stop: Addition complete
    response_variable: if_then_add
mode: single
fields:
  value:
    name: Value
    required: true
Using If/Then Actions does not work

Neither of the following will work.

alias: Add Three or Five If/Then Inside
sequence:
  - if:
      - condition: template
        value_template: "{{ value is odd }}"
    then:
      - variables:
          value_plus_three_or_five: |
            {{ {'value': value + 5} }}
      - stop: Added Five
        response_variable: value_plus_three_or_five
    else:
      - variables:
          value_plus_three_or_five: |
            {{ {'value': value + 3} }}
      - stop: Added Three
        response_variable: value_plus_three_or_five
mode: single
alias: Add Three or Five If/Then Outside
sequence:
  - if:
      - condition: template
        value_template: "{{ value is odd }}"
    then:
      - variables:
          value_plus_three_or_five: |
            {{ {'value': value + 5} }}
    else:
      - variables:
          value_plus_three_or_five: |
            {{ {'value': value + 3} }}
  - stop: Added to Value
    response_variable: value_plus_three_or_five
mode: single

well, that SHOULD work if you put the stop inside the if. It won’t work if the stop is after the if. So I just avoid dealing with it.

I thought so too, but I tested and got no response with the stop inside the if…

1 Like

ok, thank you for clearing this out! I guess I’ll take the easy route and use a helper input boolean instead of a script return variable that I can control during the execution of the script.

This basically means that the whole script visual editor is useless for scripts that return a value.

When programming functions it’s common to either have a bunch of returns or to define a variable, set it as you go along, and then return it at the end. Neither of these are possible using the HA visual script editor.

At the very least we need a way to call stop from within actions (preferably with a value rather than having to define a variable first) but ideally a way to modify sequence-level variables. Since the outer variables are available to read surely it must be close to possible to modify them, even if it’s just a property of a dict.

1 Like

I’ve also had issues based on the script mode btw.
For me using queued mode breaks the response variable…

alias: lock1
sequence:
  - variables:
      test:
        value: true
  - stop: Test
    response_variable: test
mode: queued

This script will not return a value in queued mode; tested from the dev tools call service UI. This could be a bug…

3 Likes

I can replicate this issue. Response is returned for single, restart and parallel, but not for queued.

Edit: It has been reported in this GitHub issue.

1 Like

I agree with this sentiment. I started converting to a more DRY automation base leveraging scripts and response variables. It’s counter intuitive for programmers that you can’t define a variable at top of scope and alter it somewhere nested scope and have that value bubble up the scope.

The result of this design is that you have a TON of repeated code everywhere, which diminishes the value of scripts.

2 Likes

Can someone explain why the response_variable is empty if I’m using a choose-sequence oder similar?

Can’t be a scope-issue… the variable “limit” is filled in the notify, but response_variable returns nothing…

alias: test
sequence:
  - variables:
      limit: |
        {{ {'value': 1200 } }}
  - choose:
      - conditions: []
        sequence:
          - service: notify.notify
            metadata: {}
            data:
              message: "{{ limit.value }}"
          - stop: Done
            response_variable: limit
mode: single

Can someone explain and give me a hint?
Thanks.

variable scope in automations does not get passed inside if statements, chooses, repeats, or any other nested actions.

with your simple script, this would work

alias: test
sequence:
  - variables:
      limit: |
        {{ {'value': 1200 } }}
  - choose:
      - conditions: []
        sequence:
          - service: notify.notify
            metadata: {}
            data:
              message: "{{ limit.value }}"
  - stop: Done
    response_variable: limit
mode: single

Thank you for your reply.
Yes, your script works but the choose-action will be pretty useless that way?!

My original script is longer and more complex with 3 choose options, this little script was shortened to show what I want.

To be honest, I don’t get it.
Why is the notification filled correctly with the value of the variable when the variable does not get passed inside nested actions?

How can I build an if/else/elsif in a script and return the result to a automation?

You have to build the if, then, else logic in the variables template itself. You can’t build/modify the variables in nested actions because it’s not possible.

alias: test
sequence:
  - variables:
      limit: >
        {% if ... %}
          {{ {'value': 1200 } }}
        {% else %}
          {{ ... }}
        {% endif }}
  - choose:
      - conditions: []
        sequence:
          - service: notify.notify
            metadata: {}
            data:
              message: "{{ limit.value }}"
  - stop: Done
    response_variable: limit
mode: single

Thank you for your help.
I still do not understand why that’s not possible, but that’s not the topic.

I’m pretty sure the responded variable isn’t usable in automations with nested actions too.
(I’ve tried and it doesn’t worked for me) I’m setting the value into an helper entity.
This I can use in nested-actions.

Just if anyone is trying the same thing:

service: input_number.set_value
data:
  value: "{{ limit.value |float }}"
target:
  entity_id: input_number.limit

That is the literal reason. If you don’t understand that statement, I suggest you read up on what scope means in the context of coding.

In a programming language, scope refers to the area where a function or variable is visible and accessible to other code . Below are some common terms associated with scope: Global scope refers to a global or public space. Local scope refers to a local or restricted region.

Each nested level has it’s own local scope, and it’s not shared between parent levels.

FYI the float is unnecessary here.

Hi, all!! can’t get working response_variable using in python script pro integration. so, from trace i see the variable is evaluated, but when i am using services in dev tool, by running this script i do not see response value, although it is defined in script UI. any help from any one? do i misunderstanding response_variable concept?

my script trace:

this:
  entity_id: script.1707049843680
  state: 'off'
  attributes:
    last_triggered: '2024-02-04T15:04:37.147150+00:00'
    mode: single
    current: 0
    friendly_name: Python test
  last_changed: '2024-02-04T15:04:37.560387+00:00'
  last_updated: '2024-02-04T15:04:37.560387+00:00'
  context:
    id: 01HNTACR0FF2HG9TZTQK7DFD2G
    parent_id: null
    user_id: 65d3de50a8c140c5850a620b71ad980c
context:
  id: 01HNTAHAX6V3D5QVNQAGE7EJKS
  parent_id: null
  user_id: 65d3de50a8c140c5850a620b71ad980c
value_testing:
  value: 43195

my script:

alias: Python test
sequence:
  - service: python_script.exec
    data:
      file: /config/custom_components/pyscript_old/get_equal_time_frames.py
      cache: false
      start_time: "08:00:05"
      min_period: "300"
      end_time: "20:00:00"
    response_variable: value_testing
fields: {}

my python script:

from datetime import datetime

logger.info(data)

# start time
#start_time = data['start_time']
#end_time = data['end_time']
#min_period = data['min_period']

# convert time string to datetime
#t1 = datetime.strptime(start_time, "%H:%M:%S")
t1 = datetime.strptime(data['start_time'], "%H:%M:%S")

logger.info('Start time:', t1.time())

#t2 = datetime.strptime(end_time, "%H:%M:%S")
t2 = datetime.strptime(data['end_time'], "%H:%M:%S")
logger.info('End time:', t2.time())

# get difference
delta = t2 - t1
logger.info(f"Time difference is {delta.total_seconds()} seconds")

value = delta.total_seconds()

call on service page: