Passing duration to a timer in a script via a state attribute

Hello group,

I’m trying to pass a duration to a timer by accessing the attributes of a state object passed in to the script below from an automation. I’ve included the script below.

alias: Auto Light Motion Detected Script
description: Common mode control
fields:
  arg_binary_sensor:
    description: The sensor entity to act on
    example: binary_sensor.front_porch_cam_motion
sequence:
  - condition: and
    conditions:
      - '{{ is_state(state_attr(arg_binary_sensor, ''enable_entity''), ''on'')}}'
      - '{{ is_state(state_attr(arg_binary_sensor, ''timer_entity''), ''idle'')}}'
      - '{{ is_state(state_attr(arg_binary_sensor, ''switch_entity''), ''off'')}}'
      - condition: or
        conditions:
          - condition: state
            entity_id: sun.sun
            state: below_horizon
          - '{{ is_state(state_attr(arg_binary_sensor, ''daytime_enable''), ''on'')}}'
  - service: timer.start
    data:
      duration: '{{ state_attr(arg_binary_sensor, ''duration'') }}'
    target:
      entity_id: '{{ state_attr(arg_binary_sensor, ''timer_entity'') }}'
  - service: switch.turn_on
    data: {}
    target:
      entity_id: '{{ state_attr(arg_binary_sensor, ''switch_entity'') }}'
mode: queued
icon: mdi:lightbulb-auto
max: 10

This line is failing in the trace:

 duration: '{{ state_attr(arg_binary_sensor, ''duration'') }}'

The error message in the log is:

Logger: homeassistant.components.script.auto_light
Source: helpers/script.py:409
Integration: Script (documentation, issues)
First occurred: 1:23:33 AM (1 occurrences)
Last logged: 1:23:33 AM

Logger: homeassistant.components.script.auto_light
Source: helpers/script.py:409
Integration: Script (documentation, issues)
First occurred: 1:23:33 AM (1 occurrences)
Last logged: 1:23:33 AM

Auto Light Motion Detected Script: Error executing script. Invalid data for call_service at pos 2: offset input_number.systemvariabledurationdrivewayfloodsmotion should be format 'HH:MM', 'HH:MM:SS' or 'HH:MM:SS.F' for dictionary value @ data['duration']

Note that I recently changed the script to use the state attribute variable passed in from an automation instead of the reference to a common input number. Here is a diff of the change:

- service: timer.start
     data:
-      duration: '{{states(''input_number.durationlightsmotiondetect'')}}'
+      duration: '{{ state_attr(arg_binary_sensor, ''duration'') }}'
     target:
       entity_id: '{{ state_attr(arg_binary_sensor, ''timer_entity'') }}'
   - service: switch.turn_on

Regarding the change noted above, the previous version used a global input_number helper variable, and its value was in seconds.

When I use the state attribute, the error message seems to indicate it wants HH:MM, ‘HH:MM’, ‘HH:MM:SS’ or ‘HH:MM:SS.F’

The documentation for timer says it can accept seconds only as an argument for duration:

Duration in seconds or 00:00:00 until the timer finishes.

I’m puzzled as to why it is throwing an error on the state attribute version.

Any help would be appreciated.

Thanks,

Steve

Duration definitely accepts seconds only… download and post the script’s trace.

Here is the downloaded trace:

{
  "trace": {
    "last_step": "sequence/1",
    "run_id": "1b69d223f017ab189e7e9e243ac6aa05",
    "state": "stopped",
    "script_execution": "error",
    "timestamp": {
      "start": "2022-10-26T10:52:59.178877+00:00",
      "finish": "2022-10-26T10:52:59.198160+00:00"
    },
    "domain": "script",
    "item_id": "auto_light",
    "error": "offset input_number.systemvariabledurationfrontporchlightmotion should be format 'HH:MM', 'HH:MM:SS' or 'HH:MM:SS.F' for dictionary value @ data['duration']",
    "trace": {
      "sequence/0": [
        {
          "path": "sequence/0",
          "timestamp": "2022-10-26T10:52:59.182661+00:00",
          "changed_variables": {
            "this": {
              "entity_id": "script.auto_light",
              "state": "off",
              "attributes": {
                "last_triggered": "2022-10-26T10:51:14.576603+00:00",
                "mode": "queued",
                "current": 0,
                "max": 10,
                "icon": "mdi:lightbulb-auto",
                "friendly_name": "Auto Light Motion Detected Script"
              },
              "last_changed": "2022-10-26T10:51:14.606954+00:00",
              "last_updated": "2022-10-26T10:51:14.606954+00:00",
              "context": {
                "id": "01GG9YNVR1XR0DTBWHHQMGPNYW",
                "parent_id": "01GG9YNVQSY95FR7SEM01P430G",
                "user_id": null
              }
            },
            "arg_binary_sensor": "binary_sensor.front_porch_cam_motion",
            "context": {
              "id": "01GG9YS1WWRSK7BHCQKVMCN1T1",
              "parent_id": "01GG9YS1WMB50J3W0KMXM9S5AX",
              "user_id": null
            }
          },
          "result": {
            "result": true
          }
        }
      ],
      "sequence/0/conditions/0": [
        {
          "path": "sequence/0/conditions/0",
          "timestamp": "2022-10-26T10:52:59.183180+00:00",
          "result": {
            "result": true,
            "entities": [
              "binary_sensor.front_porch_cam_motion",
              "input_boolean.enabledrivewayfloodsonmotion"
            ]
          }
        }
      ],
      "sequence/0/conditions/1": [
        {
          "path": "sequence/0/conditions/1",
          "timestamp": "2022-10-26T10:52:59.184726+00:00",
          "result": {
            "result": true,
            "entities": [
              "binary_sensor.front_porch_cam_motion",
              "timer.frontporchlight"
            ]
          }
        }
      ],
      "sequence/0/conditions/2": [
        {
          "path": "sequence/0/conditions/2",
          "timestamp": "2022-10-26T10:52:59.186047+00:00",
          "result": {
            "result": true,
            "entities": [
              "binary_sensor.front_porch_cam_motion",
              "switch.front_porch_light_2"
            ]
          }
        }
      ],
      "sequence/0/conditions/3": [
        {
          "path": "sequence/0/conditions/3",
          "timestamp": "2022-10-26T10:52:59.187439+00:00",
          "result": {
            "result": true
          }
        }
      ],
      "sequence/0/conditions/3/conditions/0": [
        {
          "path": "sequence/0/conditions/3/conditions/0",
          "timestamp": "2022-10-26T10:52:59.187651+00:00",
          "result": {
            "result": true
          }
        }
      ],
      "sequence/0/conditions/3/conditions/0/entity_id/0": [
        {
          "path": "sequence/0/conditions/3/conditions/0/entity_id/0",
          "timestamp": "2022-10-26T10:52:59.187761+00:00",
          "result": {
            "result": true,
            "state": "below_horizon",
            "wanted_state": "below_horizon"
          }
        }
      ],
      "sequence/1": [
        {
          "path": "sequence/1",
          "timestamp": "2022-10-26T10:52:59.188171+00:00",
          "error": "offset input_number.systemvariabledurationfrontporchlightmotion should be format 'HH:MM', 'HH:MM:SS' or 'HH:MM:SS.F' for dictionary value @ data['duration']",
          "result": {
            "params": {
              "domain": "timer",
              "service": "start",
              "service_data": {
                "duration": "input_number.systemvariabledurationfrontporchlightmotion",
                "entity_id": [
                  "timer.frontporchlight"
                ]
              },
              "target": {
                "entity_id": [
                  "timer.frontporchlight"
                ]
              }
            },
            "running_script": false,
            "limit": 10
          }
        }
      ]
    },
    "config": {
      "alias": "Auto Light Motion Detected Script",
      "description": "Common mode control",
      "fields": {
        "arg_binary_sensor": {
          "description": "The sensor entity to act on",
          "example": "binary_sensor.front_porch_cam_motion"
        }
      },
      "sequence": [
        {
          "condition": "and",
          "conditions": [
            "{{ is_state(state_attr(arg_binary_sensor, 'enable_entity'), 'on')}}",
            "{{ is_state(state_attr(arg_binary_sensor, 'timer_entity'), 'idle')}}",
            "{{ is_state(state_attr(arg_binary_sensor, 'switch_entity'), 'off')}}",
            {
              "condition": "or",
              "conditions": [
                {
                  "condition": "state",
                  "entity_id": "sun.sun",
                  "state": "below_horizon"
                },
                "{{ is_state(state_attr(arg_binary_sensor, 'daytime_enable'), 'on')}}"
              ]
            }
          ]
        },
        {
          "service": "timer.start",
          "data": {
            "duration": "{{ state_attr(arg_binary_sensor, 'duration') }}"
          },
          "target": {
            "entity_id": "{{ state_attr(arg_binary_sensor, 'timer_entity') }}"
          }
        },
        {
          "service": "switch.turn_on",
          "data": {},
          "target": {
            "entity_id": "{{ state_attr(arg_binary_sensor, 'switch_entity') }}"
          }
        }
      ],
      "mode": "queued",
      "icon": "mdi:lightbulb-auto",
      "max": 10
    },
    "blueprint_inputs": null,
    "context": {
      "id": "01GG9YS1WWRSK7BHCQKVMCN1T1",
      "parent_id": "01GG9YS1WMB50J3W0KMXM9S5AX",
      "user_id": null
    }
  },
  "logbookEntries": []
}

This is the solution:

duration: '{{ states(state_attr(arg_binary_sensor, ''duration'')) }}' # inserted call to states() with state_attr() return value

Here is the complete working script

#
# Common control script for all lights triggered by motion
# This is passed the entity object for the motion sensor or switch which detected someting.
# In that entity, there needs to be 5 attributes defined.
#
# 1. enable_entity: A boolean which is an enable flag
# 2. timer_entity: A timer helper entity used to time the duration to light the lamp
# 3. switch entity: The entity which references the switch to turn on
# 4. duration: The duration to keep the lights turned on. This is used to load the appropriate timer.
# 5. daytime_enable: A boolean to allow the light to operate during daytime.

auto_light:
  alias: Auto Light Motion Detected Script
  description: Common mode control
  fields:
    arg_binary_sensor:
      description: The sensor entity to act on
      example: binary_sensor.front_porch_cam_motion
  sequence:
  - condition: and
    conditions:
    # Enabled
    - '{{ is_state(state_attr(arg_binary_sensor, ''enable_entity''), ''on'')}}'
    # Timer idle
    - '{{ is_state(state_attr(arg_binary_sensor, ''timer_entity''), ''idle'')}}'
    # Switch is off
    - '{{ is_state(state_attr(arg_binary_sensor, ''switch_entity''), ''off'')}}'
    - condition: or
      # Sun below horizon
      conditions:
      - condition: state
        entity_id: sun.sun
        state: below_horizon
      # Daytime override
      - '{{ is_state(state_attr(arg_binary_sensor, ''daytime_enable''), ''on'')}}'
        
  - service: timer.start
    data:
      duration: '{{ states(state_attr(arg_binary_sensor, ''duration'')) }}' # inserted call to states() with state_attr() return value
    target:
      entity_id: '{{ state_attr(arg_binary_sensor, ''timer_entity'') }}'
  - service: switch.turn_on
    data: {}
    target:
      entity_id: '{{ state_attr(arg_binary_sensor, ''switch_entity'') }}'
  mode: queued
  icon: mdi:lightbulb-auto
  max: 10

This seems odd:

duration: '{{ states(state_attr(arg_binary_sensor, ''duration'')) }}' 

If the value of the variable arg_binary_sensor is binary_sensor.front_porch_cam_motion then the template looks like this:

{{ states(state_attr('binary_sensor.front_porch_cam_motion', ''duration'')) }}

The first thing that’s processed is this:

state_attr('binary_sensor.front_porch_cam_motion', ''duration'')

It gets the value of the binary_sensor’s duration attribute. Let’s assume it’s an integer like 50. Therefore the next step to process is this:

states(50)

which is invalid and will report an error (because the states() function requires an entity_id, not an integer value).

So what is the actual value of the binary_sensor’s duration attribute? It can’t be an integer value because states() won’t accept it.

I agree. It is unusual, but the duration is correct if I measure the amount of the time the light stays on.
I don’t know why it is working, but it does produce the expected results. The duration is passed in as an input_number helper, not a constant. Could using the helper function instead of a straight constant be the reason why the extra call to states() is working?

You’re saying the value of the binary_sensor’s duration attribute is the entity_id of an Input Number helper?

What kind of integration is responsible for producing this binary sensor?

This is an unusual binary sensor. Can you post a screenshot of binary_sensor.front_porch_cam_motion as it appears in Developer Tools > States so we can see its attribute values.

QA1. No. It is a attribute of a binary sensor entity defined as a contact or motion sensor group OR as a standalone contact or motion sensor.

QA2. Either a binary sensor the Envisalink integration, or an onvif2mqtt server communicating via MQTT to HA.

Here is a screenshot of the sensor in Developer Tools > States:

There are basically three pieces of yaml code which are used to perform the automatic light turn-on/runoff function.

They are described below.

  1. A binary sensor consisting of multiple door contacts or motion sensors is defined as a group. Then the light switch_entity, enable_entity, timer_entity, duration, and daytime enable attributes are added via customize.yaml as follows:
# Garage to patio and lab to patio doors  
binary_sensor.patio_door_group:
  icon: mdi:door
  switch_entity: switch.patio_light_1
  enable_entity: input_boolean.enablebackporchlight
  timer_entity: timer.patiolight
  duration: input_number.systemvariabledurationpatiolightmotion
  daytime_enable: input_boolean.enabledaytimelighttriggersfortesting

  1. The “AutoLight” automation looks for state changes in a group of binary sensors. It then calls the script “Auto Light Motion Detected Script” below on any closed-to-open state change. It also checks the timer defined in customize.yaml, but that isn’t relevant here. This is the yaml code:
alias: AutoLight
description: Automation for motion controlled lighting
trigger:
  - platform: state
    id: patio_light_on
    entity_id:
      - binary_sensor.patio_door_group
    from: "off"
    to: "on"
  - platform: state
    id: front_porch_light_on
    entity_id:
      - binary_sensor.front_porch_cam_motion
    from: "off"
    to: "on"
  - platform: state
    id: driveway_light_on
    entity_id:
      - binary_sensor.driveway_cam2_motion
    from: "off"
    to: "on"
  - platform: state
    id: patio_light_off
    entity_id:
      - timer.patiolight
    from: active
    to: idle
  - platform: state
    id: front_porch_light_off
    entity_id:
      - timer.frontporchlight
    from: active
    to: idle
  - platform: state
    id: driveway_light_off
    entity_id:
      - timer.drivewayfloodlights
    from: active
    to: idle
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: patio_light_on
        sequence:
          - service: script.turn_on
            target:
              entity_id: script.auto_light
            data:
              variables:
                arg_binary_sensor: binary_sensor.patio_door_group
      - conditions:
          - condition: trigger
            id: front_porch_light_on
        sequence:
          - service: script.turn_on
            target:
              entity_id: script.auto_light
            data:
              variables:
                arg_binary_sensor: binary_sensor.front_porch_cam_motion
      - conditions:
          - condition: trigger
            id: driveway_light_on
        sequence:
          - service: script.turn_on
            target:
              entity_id: script.auto_light
            data:
              variables:
                arg_binary_sensor: binary_sensor.driveway_cam2_motion
      - conditions:
          - condition: trigger
            id: patio_light_off
        sequence:
          - service: switch.turn_off
            target:
              entity_id: switch.patio_light_1
            data: {}
      - conditions:
          - condition: trigger
            id: front_porch_light_off
        sequence:
          - service: switch.turn_off
            target:
              entity_id: switch.front_porch_light_2
            data: {}
      - conditions:
          - condition: trigger
            id: driveway_light_off
        sequence:
          - service: switch.turn_off
            target:
              entity_id: switch.driveway_flood_light
            data: {}
mode: queued

  1. The Autolight automation above calls the Auto Light Motion Detected Script below. It’s job is to elimitate repetition of code for turning on the desired light
alias: Auto Light Motion Detected Script
description: Common mode control
fields:
  arg_binary_sensor:
    description: The sensor entity to act on
    example: binary_sensor.front_porch_cam_motion
sequence:
  - condition: and
    conditions:
      - "{{ is_state(state_attr(arg_binary_sensor, 'enable_entity'), 'on')}}"
      - "{{ is_state(state_attr(arg_binary_sensor, 'timer_entity'), 'idle')}}"
      - "{{ is_state(state_attr(arg_binary_sensor, 'switch_entity'), 'off')}}"
      - condition: or
        conditions:
          - condition: state
            entity_id: sun.sun
            state: below_horizon
          - "{{ is_state(state_attr(arg_binary_sensor, 'daytime_enable'), 'on')}}"
  - service: timer.start
    data:
      duration: "{{ states(state_attr(arg_binary_sensor, 'duration')) }}"
    target:
      entity_id: "{{ state_attr(arg_binary_sensor, 'timer_entity') }}"
  - service: switch.turn_on
    data: {}
    target:
      entity_id: "{{ state_attr(arg_binary_sensor, 'switch_entity') }}"
mode: queued
icon: mdi:lightbulb-auto
max: 10

Actually, the answer is Yes. I asked if the value of the binary_sensor’s duration attribute is the entity_id of an Input Number helper. Your screenshot shows that duration does in fact contain the entity_id of an Input Number (input_number.systemvariablepatiolightmotion).

It explains why the following unusual template works, because the duration attribute doesn’t contain a numeric value but the entity_id of an input_number whose value is numeric.

{{ states(state_attr(arg_binary_sensor, ''duration'')) }}

FWIW, this is an unusual arrangement and, given that it wasn’t mentioned in your first post, no one could have guessed an attribute called duration would contain an entity_id instead of a number. If you ever have other automation questions involving this binary_sensor it’s advisable to post its screenshot (like the one above) so others understand its configuration.

1 Like