Am I dumb? - Condition with last_changed only works when testing

Hi,
I put a window sensor on my cat flap. In order to know whether the cats go in or out, I created an automation which checks whether motion sensors placed in front of my flatdoor have been triggered right before the cat flap was activated or not.
However, I realized when both of my cats go outside right after another, the first cat triggers the motion sensors, so the second cat is marked as going in. To fix this, I created an additional condition which also checks whether the cat flap has been activated between 1 and 20 seconds beforehand (I did not want to start with 0 seconds as I was not sure whether the current activation would also count here). I tried two possible templates which both generally work.

One checks whether the sensor has been triggered:

{{ (as_timestamp(now()) - as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed)) < 20 and (as_timestamp(now()) - as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed)) > 1 }}

The other checks whether the automation has been tiggered:

          {{ (as_timestamp(now()) -
          as_timestamp(state_attr("automation.catcounter_automation",
          "last_triggered")) < 20) and (as_timestamp(now()) -
          as_timestamp(state_attr("automation.catcounter_automation",
          "last_triggered")) > 1) }}

Either both of them work as expected when clicking on ‘test’ (a cat flap activation between 1 and 20 seconds leads to the condition being true). However, when I put one of them to use in the automation, the second cat flap activation leads to the result ‘false’ (which then becomes true, because I negated it on purpose). Which I do not understand. Am I dumb? Help would be appreciated a lot. Thanks!

Here is my full condition list:

if:
  - condition: or
    conditions:
      - condition: state
        entity_id: binary_sensor.wohnungstur_bewegungsmelder_occupancy
        state: 'on'
      - condition: state
        entity_id: camera.motion_frontend
        state: recording
  - condition: not
    conditions:
      - condition: template
        value_template: >-
          {{ (as_timestamp(now()) -
          as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed))
          < 20 and (as_timestamp(now()) -
          as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed))
          > 2 }}
    enabled: true

This is the tracing output:

if/condition/1

Executed: December 9, 2022 at 23:51:18
Result:

result: true

if/condition/1/conditions/0

Executed: December 9, 2022 at 23:51:18
Result:

result: false entities: - binary_sensor.katzenklappensensor_contact

Post the entire automation.

sure!

alias: Katzenklappenzähler
description: ""
trigger:
  - type: opened
    platform: device
    device_id: ***retracted***
    entity_id: binary_sensor.katzenklappensensor_contact
    domain: binary_sensor
condition: []
action:
  - if:
      - condition: or
        conditions:
          - condition: state
            entity_id: binary_sensor.wohnungstur_bewegungsmelder_occupancy
            state: "on"
          - condition: state
            entity_id: camera.motion_frontend
            state: recording
      - condition: not
        conditions:
          - condition: template
            value_template: >-
              {{ (as_timestamp(now()) -
              as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed))
              < 20 and (as_timestamp(now()) -
              as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed))
              > 1 }}
        enabled: true
    then:
      - service: input_text.set_value
        data:
          value: Rein
        target:
          entity_id: input_text.text1
      - service: google_sheets.append_sheet
        data:
          config_entry: ***retracted***
          worksheet: Katzenklappe
          data:
            Was: Katze rein
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: input_text.set_value
        data:
          value: ""
        target:
          entity_id: input_text.text1
    else:
      - service: input_text.set_value
        data:
          value: Raus
        target:
          entity_id: input_text.text1
      - service: google_sheets.append_sheet
        data:
          config_entry: ***retracted***
          worksheet: Katzenklappe
          data:
            Was: Katze raus
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: input_text.set_value
        data:
          value: ""
        target:
          entity_id: input_text.text1
mode: parallel
max: 6

When you click ‘test’, it only tests the condition, not the entire automation. The value of last_changed for binary_sensor.katzenklappensensor_contact represents the last time the binary_sensor’s state changed … which was the last time you opened it, probably several seconds or minutes ago.

The automation’s trigger listens for when ‘binary_sensor.katzenklappensensor_contact’ opens. When it opens, it means it changed state (closed to open) and its last_changed is updated to the current time. As a consequence, in the automation’s condition, the difference between the value of now() and last_changed will be a few microseconds because the binary _sensor just changed state mere moments earlier.

1 Like

Oh man, you just made me really facepalm. Thanks, that makes total sense. I bought you a coffee, thanks for your help!

Here is my solution for anyone who is interested. I just save the last_changed value I am interested in for the next catflap activation during the automation.

alias: Katzenklappenzähler
description: ""
trigger:
  - type: opened
    platform: device
    device_id: ***retracted***
    entity_id: binary_sensor.katzenklappensensor_contact
    domain: binary_sensor
condition: []
action:
  - if:
      - condition: or
        conditions:
          - condition: state
            entity_id: binary_sensor.wohnungstur_bewegungsmelder_occupancy
            state: "on"
          - condition: state
            entity_id: camera.motion_frontend
            state: recording
      - condition: not
        conditions:
          - condition: template
            value_template: >-
              {{ (as_timestamp(now()) -
              states('input_text.katzenklappe_last_changed')|float) < 20  }}
        enabled: true
    then:
      - service: input_text.set_value
        data:
          value: Rein
        target:
          entity_id: input_text.text1
      - service: google_sheets.append_sheet
        data:
          config_entry: ***retracted***
          worksheet: Katzenklappe
          data:
            Was: Katze rein
      - service: input_text.set_value
        data:
          value: >-
            {{
            as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed)
            }}
        target:
          entity_id: input_text.katzenklappe_last_changed
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: input_text.set_value
        data:
          value: ""
        target:
          entity_id: input_text.text1
    else:
      - service: input_text.set_value
        data:
          value: Raus
        target:
          entity_id: input_text.text1
      - service: google_sheets.append_sheet
        data:
          config_entry: ***retracted***
          worksheet: Katzenklappe
          data:
            Was: Katze raus
      - service: input_text.set_value
        data:
          value: >-
            {{as_timestamp(states.binary_sensor.katzenklappensensor_contact.last_changed)}}
        target:
          entity_id: input_text.katzenklappe_last_changed
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: input_text.set_value
        data:
          value: ""
        target:
          entity_id: input_text.text1
mode: parallel
max: 6
1 Like