Using counters instead of variables, how to get the current count of the counter?

For a long time I used variables from the addon hass-variables, but now I tried to use counters instead of variables because the variables stopped to work. I tried to replace the state check of variables by the state check of counters, but the following usage is wrong:

  # - service_template: "{% if ((states('variable.counter_alarm_vorhof') | int) <= 10)\
      # \ or ((states('variable.counter_alarm_vorhof') | int % 6) == 1) %}\n  script.snapshot_telegram\n\
      # {% else %}\n  script.dummy_do_nothing\n{% endif %}\n"
    # data:
      # entity_id: camera.camera_vorhof
  - service_template: "{% if ((states('counter.alarm_vorhof') | int) <= 10)\
      \ or ((states('counter.alarm_vorhof') | int % 6) == 1) %}\n  script.snapshot_telegram\n\
      {% else %}\n  script.dummy_do_nothing\n{% endif %}\n"
    data:
      entity_id: camera.camera_vorhof

it looks like this usage is wrong:

states('counter.alarm_vorhof')

I get this kind of errors:

TypeError: a bytes-like object is required, not 'NoneType'
2021-06-06 23:33:40 ERROR (MainThread) [homeassistant.components.automation.bewegung_kamera_vorhof] While executing automation automation.bewegung_kamera_vorhof
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/automation/__init__.py", line 504, in async_trigger
    await self.action_script.async_run(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1212, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 348, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 366, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/trace.py", line 249, in async_wrapper
    await func(*args)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 692, in _async_repeat_step
    await async_run_sequence(iteration, extra_msg)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 674, in async_run_sequence
    await self._async_run_script(script)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 820, in _async_run_script
    await self._async_run_long_action(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 530, in _async_run_long_action
    long_task.result()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1212, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 348, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 366, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 569, in _async_call_service_step
    await self._async_run_long_action(service_task)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 530, in _async_run_long_action
    long_task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1481, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1516, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 278, in service_handler
    await script_entity.async_turn_on(
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 382, in async_turn_on
    await coro
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 404, in _async_run
    return await self.script.async_run(variables, context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1212, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 857, in async_run
    await super().async_run()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 348, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 366, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 566, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1481, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1516, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 213, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 658, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 726, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 695, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 639, in async_handle_snapshot_service
    await hass.async_add_executor_job(_write_image, snapshot_file, image)
  File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 636, in _write_image
    img_file.write(image_data)

in the documentation I don’t get the idea how to get the count:

There’s nothing wrong with it; that’s how you get the counter’s current value.

Post the entire automation.

1 Like

automations:

- alias: Garage offen
  id: garage_offen
  trigger:
  - entity_id: binary_sensor.door_window_sensor_158d00022f142f
    from: 'off'
    platform: state
    to: 'on'
  condition: []
  action:
  - service: notify.telegram
    data:
      message: Garage offen
  - service: script.alarm_garage
- alias: Garage geschlossen
  id: garage_geschlossen
  trigger:
  - entity_id: binary_sensor.door_window_sensor_158d00022f142f
    from: 'on'
    platform: state
    to: 'off'
  condition: []
  action:
  - service: notify.telegram
    data:
      message: Garage geschlossen
  - service: script.turn_off
    data:
      entity_id: script.alarm_garage_pause, script.alarm_garage
  - service: counter.reset
    entity_id: counter.alarm_garage
  # - service: variable.set_variable
    # data:
      # variable: counter_alarm_garage
      # value: 0

scripts:

snapshot_telegram:
  alias: Snapshot Telegram
  sequence:
  - data_template:
      entity_id: '{{ entity_id }}'
      filename: /config/camera/{{ entity_id }}.jpeg
    service: camera.snapshot
  - data_template:
      file: /config/camera/{{ entity_id }}.jpeg
    service: telegram_bot.send_photo
  mode: queued
  max: 20
alarm_garage_pause:
  alias: Alarm Garage Pause
  sequence:
  - delay: 00:00:10
  - service: script.turn_on
    data:
      entity_id: script.alarm_garage
alarm_garage:
  alias: Alarm Garage
  sequence:
  - condition: state
    entity_id: binary_sensor.door_window_sensor_158d00022f142f
    state: 'on'
  - service: counter.increment
    entity_id: counter.alarm_garage
  # - service: variable.set_variable
    # data:
      # variable: counter_alarm_garage
      # value_template: '{{ [((variable.state | int) + 1), 0] | max }}'
  - service_template: "{% if (states('counter.alarm_garage') | int % 3) ==\
      \ 1 %}\n  script.lights_alarm\n{% else %}\n  script.dummy_do_nothing\n{% endif\
      \ %}\n"
    data:
      store_name: alarm_garage
      entity_id: light.wohnzimmer_stehlampe, light.flur_decke
      duration: 00:00:02
  - service_template: "{% if ((states('counter.alarm_garage') | int) <= 10)\
      \ or ((states('counter.alarm_garage') | int % 6) == 1) %}\n  script.snapshot_telegram\n\
      {% else %}\n  script.dummy_do_nothing\n{% endif %}\n"
    data:
      entity_id: camera.camera_garage
  - service: script.turn_on
    data:
      entity_id: script.alarm_garage_pause

and there are several automations and scripts working similar.

I implemented this some years ago when there have not been variables in automations or scripts. It worked fine all the time and I don’t want to touch a running system. But starting with 2021.6. there are issues and I need to change.

Maybe I could or should use the new blueprints?

Currently, the automations only turn on and off some scripts, and the scripts are doing the work. The scripts are pairs of 2 scripts, one or the actions, another for the delay.

The main idea is always:

  • do some action when a trigger event happens
  • do some action while the trigger in “on”, but I want to be able to define delays
  • stop the action when the trigger is “off”

What isn’t working?

I’m using that integration and it works.

What version are you using? the one from rogro82 or wibias?

If the former then that one is no longer maintained. switch to the other one.

@finity I switched from rogro82 to wibias to be able to use also in 2021.6., But after upgrading to 2021.6. I get errors on this part which is commented out. And I have other issues with 2021.6. - it is permantly restarting. So I downgraded back to 2021.5.5 where the variables still work. But now I want to replace with counters because I use them mostly as counters.

Sorry, I don’t understand what you mean.

But I haven’t updated to 2021.6 yet so I guess I’ll have to hope the variables work after I do.

:grimacing:

This would be the modern way of composing the script. It employs choose (making the use of a dummy script unnecessary), variables to conveniently create a local global variable, the target option for passing the entity_id to a service call and the use of service instead of service_template because that was deprecated several versions ago.

alarm_garage:
  alias: Alarm Garage
  sequence:
  - condition: state
    entity_id: binary_sensor.door_window_sensor_158d00022f142f
    state: 'on'
  - service: counter.increment
    entity_id: counter.alarm_garage
  - variable:
      agc: "{{ states('counter.alarm_garage') | int }}"
  - choose:
    - conditions: "{{ agc % 3 == 1 }}"
      sequence:
      - service: script.lights_alarm
        data:
          store_name: alarm_garage
          entity_id: light.wohnzimmer_stehlampe, light.flur_decke
          duration: 00:00:02
  - choose:
    - conditions: "{{ agc <= 10 or agc % 6 == 1 }}"
      - sequence:
        - service: script.snapshot_telegram
          data:
            entity_id: camera.camera_garage
  - service: script.turn_on
    target:
      entity_id: script.alarm_garage_pause

How it works

  1. Confirms the binary_sensor is on. Proceeds if is, terminates if it isn’t.
  2. Increments the alarm_garage counter.
  3. Creates a variable called agc representing the counter’s value as an integer.
  4. If agc % 3 == 1 then it executes the lights_alarm script (and waits for it to finish before continuing). If it’s not then it does nothing.
  5. If agc <= 10 or agc % 6 == 1 then it executes the snapshot_telegram script (and waits for it to finish before continuing). If it’s not then it does nothing.
  6. Finally, it executes the alarm_garage_pause script (and does not wait for it to finish).
1 Like

This looks good! I will try to build my first blueprint based o this. Or I just create similar automations.

And regarding deprecated service_template: I will need to replace this in several places. Maybe this was the reason why my upgrade to 2021.6. did not work. My automations and scripts are full of service_template, data_template, value_template. Strange, that I did not read the deprecation note. And strange, that these scripts and automations still work. This will be a bigger task to review all my automations and scripts.

No. Those options are still supported and your existing scripts and automations are unaffected; however, the preference now is to use the new versions: service and data. You mentioned value_template but it remains unchanged; it was never deprecated and there’s no substitute for it.