esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
411 stars 26 forks source link

Get result of homeassistant.service #2108

Open Ulrar opened 1 year ago

Ulrar commented 1 year ago

Describe the problem you have/What new integration you would like It's possible to call homeassistant services through the native API, but I don't see a way to know if that service call succeeded or failed.

Please describe your use case for this integration and alternatives you've tried: I use Shelly 1L flashed with ESPHome behind my switches to control my smart bulbs :

  - platform: gpio
    name: Switch 2
    pin:
      number: GPIO14
    internal: True
    filters:
      - delayed_on_off: 50ms
    on_state:
      - if:
          condition:
            binary_sensor.is_on: ha_connected
          then:
            - if:
                condition:
                  switch.is_off: relayid
                then:
                  - switch.turn_on: relayid
                else:
                  - homeassistant.service:
                      service: light.toggle
                      data:
                        entity_id: light.mylight
          else:
            - switch.toggle: relayid

The goal is to transparently fallback to electrically toggling the relay if HA is down, which works okay (see caveat below). But this does not address the case where HA is up and connected, but cannot control the light for any reason (maybe Z2M is down, or maybe the bulb didn't connect properly to the Zigbee network, it happens every once in a while).

It's possible for the service call to fail, which in the HA web UI does show an error, but as far as I can tell ESPHome does not know about. I'd love to be able to check the result of the service call, and toggle the relay if it failed. As far as I can tell there's no way either to subscribe to events from the HA event bus, which could be another way to go about this (listen for the light state change event) maybe.

Additional context

I also noticed that the status platform sensor isn't great to know if HA is connected, it can be stale if HA crashed and will be on if the logs are being tailed, regardless of HA's status. Not directly related to this but if someone has a better way of knowing if HA is connected I'd be grateful. I've seen someone use ping instead, but that doesn't sound like a good solution either, HA can be down even if the server pings.

nagyrobi commented 1 year ago

Yes I feel your situation. I'm in the same boat with my heating system which implements climates on ESPHome, but relies on receiving temperature sensor values from BTHome through HA from other bluetooth_proxy ESPHome nodes. During a HA update I experienced a crash which needed manual intervention, the heating system was not functional until then. So what I need is an "emergency" wired temperature sensor (which, cannot be placed as accurately as the BLE sensors, and can't have one in each room, also not talking about much weaker precision - but still usable as an emergency case) which could still be used when HA connection is lost.

I was thinking of making a dummy input_boolean in HA, which could be toggled each second by an automation there.

Then import it in ESPHome as a sensor, triggering on_value a script in restart mode running a delay of 2 or 3 seconds, followed by turning on a template binary sensor.

While connected to HA, the script will keep restarting before reaching the timeout. When HA is lost, timeout will expire due to script not being restarted and the binary sensor will turn on.

Or a global boolean value instead of binary sensor...

nagyrobi commented 1 year ago

Try like this:

Home Assistant:

input_boolean:
  esphome_watchdog: #a boolean to be sent from HA
    name: ESPHome watchdog
    icon: mdi:alert

automation:
  id: toggle_esphome_watchdog
  alias: "Toggle ESPHome watchdog every 5 seconds" #change the boolean's state every 5 seconds
  trace:
    stored_traces: 0
  trigger:
    - platform: time_pattern
      seconds: "/5"
  action:
    - service: input_boolean.toggle
      target:
        entity_id: input_boolean.esphome_watchdog

recorder:
  exclude:
    entities:
      - input_boolean.esphome_watchdog
      - automation.toggle_esphome_watchdog
#don't spam the state database with these entities...
logbook:
  exclude:
    entities:
      - input_boolean.esphome_watchdog
      - automation.toggle_esphome_watchdog

ESPHome node:

binary_sensor:
- platform: template #this entity will change to false when timeout occurs, assuming HA is down
  id: ha_connected
  name: ${friendly_name} HA connected

- platform: homeassistant #here we receive the boolean changes from HA
  name: "Watchdog received"
  internal: false
  disabled_by_default: true
  entity_id: input_boolean.esphome_watchdog
  on_state:
    then:
      - script.execute: watchdog_timeout

script:
- id: watchdog_timeout #we keep restarting this script every time the boolean changes (=5s)
  mode: restart
  then:
    - lambda: 'id(ha_connected).publish_state(true);'
    - delay: 7s #add +2 seconds for safety
    - lambda: 'id(ha_connected).publish_state(false);' #if we reach here, it means no boolean changes happened, we can assume HA is down
Ulrar commented 1 year ago

I do think it'd be something good to have as part of the API though, you could easily imagine having a separate binary sensor for HA and for other API clients, and for the HA one have a way to define a very short keepalive to make it get invalidated quickly. But your way should work for now, thanks for that ! That addresses at least one of my issues :)

nagyrobi commented 1 year ago

I do think it'd be something good to have as part of the API though

Agree, this is just a workaround. Also I think perhaps a dedicated input_boolean might not be necessarry, as long as you have some reliable sensors updating fast enough and use those to monitor HA being live... @0x3333 @poldim

Ulrar commented 1 year ago

There's actually something weird with this, when I disable the integration in HA I can see it disconnect from the esp, but the state keep streaming through anyway somehow :

[14:58:29][D][api.connection:159]: Home Assistant 2023.2.5 (...) requested disconnected
[14:58:30][D][homeassistant.binary_sensor:026]: 'input_boolean.esphome_keep_alive': Got state OFF
[14:58:30][D][binary_sensor:036]: 'Keepalive received': Sending state OFF
[14:58:30][D][script:077]: Script 'keepalive_timeout' restarting (mode: restart)
[14:58:35][D][homeassistant.binary_sensor:026]: 'input_boolean.esphome_keep_alive': Got state ON
[14:58:35][D][binary_sensor:036]: 'Keepalive received': Sending state ON
[14:58:35][D][script:077]: Script 'keepalive_timeout' restarting (mode: restart)

This seems to keep endlessly, I have no idea how but it makes me wonder about this method's reliability a bit since these updates should not be seen without the API, I'd expect

MirkEdge commented 1 year ago

I do think it'd be something good to have as part of the API though

Agree, this is just a workaround. Also I think perhaps a dedicated input_boolean might not be necessarry, as long as you have some reliable sensors updating fast enough and use those to monitor HA being live... @0x3333 @poldim

Hello @nagyrobi. I got the same problem. To be honest I faced up to HA just recently so it is not all familiar to me. However I tried to implement your solution. I paste the HA yaml code into configurations.yaml on the proper key region. but it doesn't recognize automation: field (property invalid) (I commented the key automation: !include automations.yaml to avoid dupliate key)

Where am I wrong?

zvirja commented 5 months ago

@nagyrobi Hello! I've found that since Home Assistant 2023.7 it's possible to have results for services: https://www.home-assistant.io/blog/2023/07/05/release-20237/#services-can-now-respond. They started to use it more and more and recently was a big issue around weather forecast: https://github.com/home-assistant/core/issues/112583. The current solution is quite clumsy as you have to define a dummy sensor in HA just to call the service.

Would it be possible for ESPHome to properly implement the feature, so it's possible to just invoke the service and get the result directly from ESPHome?

I am not sure sure if my request is related to this feature, so if not - I will be more than happy to raise a new Feature Request.

Thank you!

nagyrobi commented 5 months ago

Calling HA services from ESPHome seems indeed pretty outdated. For example it also fails accepting targets, which were introduced in 2020.

zvirja commented 5 months ago

@nagyrobi Should I create a new feature request for all that story? Do you think it's something which will be implemented in the nearby future?

nagyrobi commented 5 months ago

A feature request is a good reminder for the devs.