Automation Condition Fails after Trigger (Solved)

I’m trying to automate the power cycling of my cable modem and firewall router in the event that the Internet connection is lost for more than ten minutes. In the past, I’ve experienced outages after loss of power and when ISP has been re-configuring the modem. I’m using a Ping binary sensor to monitor the Internet connection by pinging Google DNS server (8.8.8.8) as described in Detect internet is down and reboot modem - #18 by AaronCake

# is the Internet up?    
binary_sensor:
  - platform: ping
    host: 8.8.8.8
    name: "dns.google"
    count: 2
    scan_interval: 300

Strategy: Whenever the connectivity sensor transitions from on to off or home-assistant is restarted, check to see if connectivity is restored within 10 minutes, else power cycle the cable modem and then the firewall router. Then send an appropriate notification.

The Automation:

alias: Lost Connection
description: Monitor Internet Connection
trigger:
  - platform: state
    entity_id:
      - binary_sensor.dns_google
    from: "on"
    to: "off"
    for:
      hours: 0
      minutes: 0
      seconds: 10
  - platform: homeassistant
    event: start
condition:
  - condition: state
    entity_id: binary_sensor.dns_google
    state: "off"
    for:
      hours: 0
      minutes: 10
      seconds: 0
action:
  - service: system_log.write
    data:
      level: warning
      message: Internet connection lost
      logger: Ping
  - type: turn_off
    device_id: 46dffef3544f957b1ee80028faa412a3
    entity_id: switch.cable_modem
    domain: switch
  - type: turn_off
    device_id: 9fb210fc476fc7687e58187cae82ff14
    entity_id: switch.edgerouterx
    domain: switch
  - delay:
      hours: 0
      minutes: 1
      seconds: 0
      milliseconds: 0
  - type: turn_on
    device_id: 46dffef3544f957b1ee80028faa412a3
    entity_id: switch.cable_modem
    domain: switch
  - delay:
      hours: 0
      minutes: 3
      seconds: 0
      milliseconds: 0
  - type: turn_on
    device_id: 9fb210fc476fc7687e58187cae82ff14
    entity_id: switch.edgerouterx
    domain: switch
  - delay:
      hours: 0
      minutes: 5
      seconds: 0
      milliseconds: 0
  - service: notify.all_users
    data:
      message: >-
        Internet connection was lost for ten minutes so cable modem and router
        were restarted.
      title: Cable Modem & Router Restarted
mode: single

The automation actions have been tested in Developer Tools and they properly reboot both cable modem and router, write to the logs, and send the notifications. The automation triggers have been tested by automation.trigger in Developer Tools and by disconnecting the cable modem input. Both trigger the automation, but it fails in the condition section with error message “Stopped because a condition failed at …”. Does anyone have a clue what I’m doing wrong?

Trace logs:

{
  "trace": {
    "last_step": "condition/0/entity_id/0",
    "run_id": "d09e10746223148f7c8ff306e640a46e",
    "state": "stopped",
    "script_execution": "failed_conditions",
    "timestamp": {
      "start": "2022-12-16T17:10:59.999902+00:00",
      "finish": "2022-12-16T17:11:00.000797+00:00"
    },
    "domain": "automation",
    "item_id": "1670963664418",
    "trigger": "state of binary_sensor.dns_google",
    "trace": {
      "trigger/0": [
        {
          "path": "trigger/0",
          "timestamp": "2022-12-16T17:11:00.000157+00:00",
          "changed_variables": {
            "this": {
              "entity_id": "automation.lostconnection",
              "state": "on",
              "attributes": {
                "last_triggered": "2022-12-16T02:29:45.073664+00:00",
                "mode": "single",
                "current": 0,
                "id": "1670963664418",
                "icon": "mdi:web",
                "friendly_name": "Lost Connection"
              },
              "last_changed": "2022-12-16T16:34:51.560332+00:00",
              "last_updated": "2022-12-16T16:34:51.560332+00:00",
              "context": {
                "id": "01GMDWKPH8R47NDQFP13KMX48F",
                "parent_id": null,
                "user_id": null
              }
            },
            "trigger": {
              "id": "0",
              "idx": "0",
              "alias": null,
              "platform": "state",
              "entity_id": "binary_sensor.dns_google",
              "from_state": {
                "entity_id": "binary_sensor.dns_google",
                "state": "on",
                "attributes": {
                  "round_trip_time_avg": 17.563,
                  "round_trip_time_max": 17.936,
                  "round_trip_time_mdev": "",
                  "round_trip_time_min": 17.19,
                  "device_class": "connectivity",
                  "friendly_name": "dns.google"
                },
                "last_changed": "2022-12-16T02:35:47.829121+00:00",
                "last_updated": "2022-12-16T17:05:48.024784+00:00",
                "context": {
                  "id": "01GMDYCBFRP806GDE6QEM6K8W5",
                  "parent_id": null,
                  "user_id": null
                }
              },
              "to_state": {
                "entity_id": "binary_sensor.dns_google",
                "state": "off",
                "attributes": {
                  "device_class": "connectivity",
                  "friendly_name": "dns.google"
                },
                "last_changed": "2022-12-16T17:10:49.994007+00:00",
                "last_updated": "2022-12-16T17:10:49.994007+00:00",
                "context": {
                  "id": "01GMDYNJCACFCCFNM1C28TY4N6",
                  "parent_id": null,
                  "user_id": null
                }
              },
              "for": {
                "__type": "<class 'datetime.timedelta'>",
                "total_seconds": 10
              },
              "attribute": null,
              "description": "state of binary_sensor.dns_google"
            }
          }
        }
      ],
      "condition/0": [
        {
          "path": "condition/0",
          "timestamp": "2022-12-16T17:11:00.000343+00:00",
          "result": {
            "result": false
          }
        }
      ],
      "condition/0/entity_id/0": [
        {
          "path": "condition/0/entity_id/0",
          "timestamp": "2022-12-16T17:11:00.000495+00:00",
          "result": {
            "result": false,
            "state": "off",
            "duration": "2022-12-16T17:01:00.000599+00:00"
          }
        }
      ]
    },
    "config": {
      "id": "1670963664418",
      "alias": "Lost Connection",
      "description": "Monitor Internet Connection",
      "trigger": [
        {
          "platform": "state",
          "entity_id": [
            "binary_sensor.dns_google"
          ],
          "from": "on",
          "to": "off",
          "for": {
            "hours": 0,
            "minutes": 0,
            "seconds": 10
          }
        },
        {
          "platform": "homeassistant",
          "event": "start"
        }
      ],
      "condition": [
        {
          "condition": "state",
          "entity_id": "binary_sensor.dns_google",
          "state": "off",
          "for": {
            "hours": 0,
            "minutes": 10,
            "seconds": 0
          }
        }
      ],
      "action": [
        {
          "service": "system_log.write",
          "data": {
            "level": "warning",
            "message": "Internet connection lost",
            "logger": "Ping"
          }
        },
        {
          "type": "turn_off",
          "device_id": "46dffef3544f957b1ee80028faa412a3",
          "entity_id": "switch.cable_modem",
          "domain": "switch"
        },
        {
          "type": "turn_off",
          "device_id": "9fb210fc476fc7687e58187cae82ff14",
          "entity_id": "switch.edgerouterx",
          "domain": "switch"
        },
        {
          "delay": {
            "hours": 0,
            "minutes": 1,
            "seconds": 0,
            "milliseconds": 0
          }
        },
        {
          "type": "turn_on",
          "device_id": "46dffef3544f957b1ee80028faa412a3",
          "entity_id": "switch.cable_modem",
          "domain": "switch"
        },
        {
          "delay": {
            "hours": 0,
            "minutes": 3,
            "seconds": 0,
            "milliseconds": 0
          }
        },
        {
          "type": "turn_on",
          "device_id": "9fb210fc476fc7687e58187cae82ff14",
          "entity_id": "switch.edgerouterx",
          "domain": "switch"
        },
        {
          "delay": {
            "hours": 0,
            "minutes": 5,
            "seconds": 0,
            "milliseconds": 0
          }
        },
        {
          "service": "notify.all_users",
          "data": {
            "message": "Internet connection was lost for ten minutes so cable modem and router were restarted.",
            "title": "Cable Modem & Router Restarted"
          }
        }
      ],
      "mode": "single"
    },
    "blueprint_inputs": null,
    "context": {
      "id": "01GMDYNW4Z9GBQQ3F7VDHG5J9Y",
      "parent_id": "01GMDYNJCACFCCFNM1C28TY4N6",
      "user_id": null
    }
  },
  "logbookEntries": []
}

Forgot to add that I’m running HAOS on a Raspberry Pi 4 behind a Ubiquiti EdgerouterX.
Home Assistant 2022.12.6
Supervisor 2022.11.2
Operating System 9.4
Frontend 20221213.0 - latest

You trigger at

Ten seconds.
Then the condition says:

Ten minutes.
That is not going to work

Aren’t the trigger and the condition independent statements?

Yes. But if something is on for ten seconds then the condition can’t possibly be true if the condition is that it should be on for ten minutes.

Sure they are different but they still need to be true in order for the automation to run.

Why do you even have a trigger of ten seconds of you actually want ten minutes?
You could just delete the condition and make the trigger ten minutes, right?

Initially I did not have the for: seconds: 10 on the trigger. I only added it to test if there was a race condition between the trigger and the condition test. The idea was that both triggers (start home assistant) and (dns.google transition from on to off) are point events. After either trigger, we test if the connection state remains off for at least 10 minutes before proceeding with the actions. I’ll try changing the trigger to 10 minutes and removing the timer from the condition.

Triggers don’t wait for the conditions to be true to start the actions.

triggers are instantaneous tests.

When triggered the automation checks to see if the conditions are satisfied at that instant in time.

If they are then the actions run. If the conditions aren’t true then the automation stops and then needs to wait for the next trigger condition to become true before it checks the conditions again.

if you have a trigger (when a device transitions from on to off) that checks that the same device has been off for 10 minutes there’s no way it can work because the device has only been off for milliseconds when the condition is checked.

you should change your first trigger to trigger when the binary sensor has been off for 10 minutes.

then you can leave the condition as is and then the HA restart trigger can check to see if the sensor has been off for 10 minutes or it won’t run the actions.

that way both scenarios are accounted for.

Ok I did not even see the home assistant start event in the automation.
Yes finity is correct

I would like to point out that I specifically warned against pinging 8.8.8.8 or any other public server to detect if your Internet connection is down.

Ping the first hop past your router or your ISPs DNS server instead.

If you ping 8.8.8.8 (or 1.1.1.1, or similar) you are just checking to see if Google’s DNS is up. On the off chance it is down (or there is a routing problem to it), your Internet connection will keep being reset.

Thanks for the explanation. I ran a series of tests and they confirm this behavior. I’ve been using HA for a couple of years but only for controlling lights while I’m away. This is my first attempt to solve an issue that occurred last year when the Internet went down and I had to call someone to reset the system. Obviously my naive understanding of how conditions worked was wrong. I set the trigger delay for 10 minutes and then tried several values for the condition. Basically any value of the condition less than 10 minutes would work. Interestingly setting both trigger and condition to 10 minutes would fail. I think that is because the condition test uses ‘>’ greater than instead of ‘>=’ greater than or equal to.

I added the trigger on home assistant start in an attempt to handle an edge condition where HA is down when the Internet outage begins. Apparently when HA starts it does not preserve the value of the ping binary_sensor but instead sets the state to either “unknown” or “off”. As a result the transition from “on” to “off” is not detected and the automation is not triggered. I saw this used for another type of sensor and only thought it would work because of my faulty understanding of the condition test.

I’ve been searching for a way to set the initial or default state of the binary_sensor to “on”. So far the only strategy I’ve found is to use rodpayne’s set_state.py python script triggered by the home assistant start. I would like to know how the Developers Tools Set State achieves the change without needing the python script.

You can also just remove from: on and whenever the state becomes off it will trigger

Well duh, that was just too simple. Thanks for pointing out the solution. Thanks also to @finity for explaining the nature of “conditions” and to @AaronCake for the example I was trying to follow. The upside is that I was able to learn a lot about Home Assistant automations.

I’m running Home Assistant behind a firewall. Do you have any suggestions about how to determine the first hop past the firewall? I can determine it manually by running traceroute -n and looking for the IP address, but it is subject to change at the whim of the ISP. I suppose I could write a script to parse the output of the traceroute whenever HA starts and then save the IP address in a variable that will be used as the ping target.

If you are on DHCP and your ISP switches your gateway whenever you reconnect, you can always ping your ISPs DNS servers. It’s reasonable to assume that if they are up, your Internet connection is up.

But in the same sense, even if your ISP has multiple gateways you should still be able to ping them all even if your assigned gateway changes based on your DHCP assignment.