ESPHome + Hubitat

Anyone has experience of using devices flashed with ESPHome binaries with Hubitat without any additional hubs (and without Home Assistant)?

1 Like

No, but I'm interested!

Did you find out anything?

Also interested!

No. I could not avoid ESPHome intrusion into this project. So I followed a few manuals about flashing the damn thing with ESPHome stuff and then I managed to make it work with Hubitat.

with the Maker API?

I've had good success implementing the native ESPHome socket protocol. Not an easy protocol to implement as it uses Google Protobuf RPC along with a custom ESPHome on-wire transmission format. The good news is that because Protobuf is a highly optimized binary format it results in tiny packets (a few bytes for most commands) direct communication but its over 1,000 lines of code so far!

Unfortunately Hubitat still does not support MDNS so until it does you'll need to hardcode the device IP address and I do not plan to support encrypted communications at this time.

ESPHome itself defines 64 types of command and my plan is to provide protocol support for all of them just like Home Assistant does.

There isn't a one-size fits all driver for ESPHome devices so my solution will be more of a "toolkit" with a common library and example "skeleton" drivers that can be customized to the particular device capabilities with the goal to make it quick and easy to get up and running.

In order to prioritize the creation of the skeleton drivers I'd like to know what kinds of things ESPHome is being used for, e.g. are you using it for sensors, or things like switches etc.

Thanks!

5 Likes

My list of popular devices would include Garage Door controllers, motion sensors, contact sensors, temperature sensors, humidity sensors, leak sensors, switches (e.g. to control a relay.) Hubitat has many of these available as "Generic Component ..." child drivers already. Thus, no need to reinvent those drivers :slight_smile:

2 Likes

I am looking at ESPHome for controlling ceiling fans, so am very interested in what you've got.

Dale

Right now things seem to working well and stable (famous last words) and I've just put a garage door opener and a bunch of lights and outlets on it to shake out any issues.

The intent of the solution is that people can make their own driver stubs using the library and examples I'm providing. I just put one together for a ESPHome fan but since I don't one of those it may need some adjustments.

Eventually I'll write up some proper instructions but if anyone is adventurous and wants to play the code is in my GitHub right now at hubitat-public/ESPHome at main ยท bradsjm/hubitat-public ยท GitHub

There are example drivers so far for Contact Sensors, Fans, Garage Door Openers, Motion Sensors, RGBCT Lights and Outlets w/optional metering.

  1. Make sure the ESPHome yaml for the device includes the "api:" section and does NOT enable encryption.
  2. Download the library (ESPHome-API-Library.groovy) and install it in the Hubitat library section.
  3. Download an example driver from the repository and install it in the drivers section.
  4. Create a new virtual device and choose the driver you just installed for it
  5. Open the new device and set the IP address of the ESPHome device and the password if applicable. Make sure the device is NOT using encryption (which is now the default I believe)
  6. Save the preferences and the driver will connect and attempt to download the entities and will default to the first one it finds
  7. If the wrong entity is in the preferences, use the dropdown to pick the correct one and save the changes again.
  8. If the driver doesn't do exactly what you need, you can edit the functionality to suit your device.
5 Likes

I just tried this, using your current drivers (ContactSensor/MeteringOutlet). It works very well. I was surprised. Took me forever to figure out how to flash EspHome via windows using python. And I'm still trying to completely understand the yaml syntax.

I got two entities created and compiled using "switch:" and "binary_sensor:" from examples on ESPHome site. After that, I got a pushbutton and an LED connected to 2 inputs and had that working in the web server of EspHome, then I added your app library and drivers and each of them worked.

Only problem is it can only see one entity on a single IP address, even while trying to make 2 devices using different drivers, if you have the same IP address its a single shot.

Nevertheless, this is a giant step forward to getting past tasmota via Hubitat, even with the new sync control, its very slow to respond (1-2 sec delay). Your method is instantaneous.

Please add more drivers or help make it more clear how to create one's own drivers from a Skeleton model.

Thanks again for doing this, I hope it progresses forward with great anticipation.

1 Like

Thanks, I've got 24 ESPHome devices in Hubitat right now and I feel the core library code is pretty solid and reliable at this point at about 90% + feature complete. I'm mostly watching for any edge cases where the driver doesn't re-connect itself. The retry code generally catches any dropped connections and re-sends the command when the connection is re-established.

You are right that the example drivers so far are entity specific, each one should have a dropdown list in the configuration that allows you to pick a single entity (e.g. switch or sensor). I still need to create an example that will create child devices so you can expose multiple entities from a single device.

While the protocol for ESPHome was slog to implement (recreating Google Protobuf from scratch), the speed is amazing, you are talking about only a total packet content of 3-4 bytes when sending commands and I've tried to optimize the speed of the code execution as best as I know how.

One thing to be aware of, if you change the name of an entity in the YAML, you will need to refresh the device and re-select the entity. There is a way to hard code the YAML so changing the entity name doesn't break things.

One day maybe Hubitat will support MDNS so we don't need to hardcode IP addresses and can auto-discover ESPHome devices like Home Assistant can...

Send me your YAML so I can see what you are doing so I can add an example driver.

4 Likes

Currently I have a VL53x01 tof sensor and running on a nodemcu which calculates the distance and turns on a GPIO when that distance is less than its target. I have that GPIO from the nodemcu connected to a Tasmota Sonoff touch switch using the RX pin as GPIO input. Then I have Hubitat driver by @garyjmilne which uses the sync capability of Tasmota to communicate when the nodemcu switch turns on and then I have it turn on the sonoff touch switch (light). The reason for passing result to Hubitat and not simply having the rule turn on power, is because I don't want the light turning on under certain conditions, which Hubitat knows though global variables. It all works pretty well, but its a 2 ESP system, one of which is only needed so that the distance calculations can be done and present a simple on/off state to tasmota. Then after doing some digging I found someone doing nearly the exact same use-case but in ESPHome. He has a yaml that uses the "lambda:" filter aspect to calculate when the minimum distance is breached and then set an output. This would be the end goal I'm hoping for, but then I would still need the hubitat driver to have one input (motion/contact/switch) and another (switch) for the light control. Here is his yaml settings from
kdorff
/**[distance-sensor-0.yaml]

## A standard "break beam sensor" uses a laser or LED with a device on both
## sides of an opening and is triggered when something breaks the beam
## (such as a customer walking through the beam). Some garage doors use them.
## Stores often use them at the entrace to ring a chime when a customer enters
## or leaves.
##
## This is my attempt at using a VL53L0X i2c Time of Flight sensor 
## as a break beam sensor in Home Assistant using ESPHome.
##
## The binary sensor 'breakbeam_sensor' is
## * A synthetic break beam that is controlled by changes 
##   to 'breakbeam_sensor_dist'.
## * Should only send changes when the 'beam is broken':
##   * 'breakbeam_sensor_dist' becomes < 'minTripDistance' (or)
##   *  'breakbeam_sensor_dist' becomes to greater than 'minTripDistance'
##
## The sensor 'breakbeam_sensor_dist' is the actual VL53L0X sensor. 
## * The maximum reliable "open" distance seems to be to about 1.5 meters.
## * This sensor is marked intnernal as to not send distance data to HA.
## * When distance first falls less that 'minTripDistance', 
##   'breakbeam_sensor' will turned on.
## * When the distance is first greater than 'minTripDistance', the
##   'breakbeam_sensor' will be turned off.
## * This will poll at 0.1s. This seems fast enough, but 1s was not.
## 

esphome:
  name: distance-sensor-0

esp8266:
  board: esp01_1m

# Logging (DEBUG is the standard level)
logger:
  level: INFO

# Enable Home Assistant API
api:

ota:
  password: "XXXXX"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Distance-Sensor-0"
    password: "XXXXX"

captive_portal:

# the vl53l0x is i2c
i2c:
  scan: true

##
## The virutal break beam sensor.
## The state of this will be controlled 
## by breakbeam_sensor_dist's lambda as necessary.
##
binary_sensor:
  - name: "Breakbeam Sensor"
    id: breakbeam_sensor
    platform: template
    device_class: motion

##
## The actual sensor. 
## This sensor's lambda will control the state of our 
## virtual break beam sensor, breakbeam_sensor.
##
sensor:
  - name: "Breakbeam Sensor Dist"
    id: breakbeam_sensor_dist
    platform: vl53l0x
    address: 0x29
    update_interval: 0.1s
    long_range: true
    internal: true
    #
    # Only send a value back if breakbeam_sensor changes.
    #
    filters:
      - lambda: !lambda |-
          /**
           * YOU MIGHT WANT TO CONFIGURE THIS.
           * Distance below which to trip the virtual break beam sensor.
           * '0.5' meters is about 20  inches.
           */
          static double minTripDistance = 0.5;

          if (x <= minTripDistance) {
            if (id(breakbeam_sensor).state == true) {
              // Beam was already broken
              return {};
            }
            // Beam was just broken
            id(breakbeam_sensor).publish_state(true);
            ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Detected");
            return {};
          }
          else {
            if (id(breakbeam_sensor).state == false) {
              // Beam was already un-broken
              return {};
            }
            // Beam was just un-broken
            id(breakbeam_sensor).publish_state(false);
            ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Cleared");
            return {};
          }
1 Like

So, basically what I need from Hubitat driver perspective, assuming all this YAML/Lambda stuff works on ESPHome, is one switch capacity and one motion/contact/binary sensor capacity, or maybe even a presence type capacity...

You should take a look at this PIR-Switch example. It combines a switch output with a motion sensor input.

Even though it says PIR (motion) it could be easily changed to some other type of sensor or additional sensors.

1 Like

I've just added a couple of driver examples for a multi (Parent with multiple Child devices). One for multiple contact (binary) sensors and the other for multiple switches to the repository.

I also added a folder called "Examples" containing somewhat generic ESPHome YAML configuration examples for the drivers.

2 Likes

Just FYI that there is a 1 second delay (smallest unit of delay) built into the rule for processing all of the other attribute values. If you only cared about 1 attribute then you could send that attribute right away without waiting for any delay. I think there is an example of how to do this in the Tasmota Broadcaster app as an available template.

1 Like

That is AWESOME! You real deal developers always amaze me. Now I have a driver that provides Sensor Entity and Switch Entity. I'm almost ready to rock and roll with my TOF sensor. Thank you

Just wanted to post a follow up. This guy is a genius. My Door Entry occupancy detector works like a charm thanks to this ESPHome integration into Hubitat. My final YAML configuration using the Motion/Switch Driver:

esphome:
  name: touch_switch

  # Automation turning on the blue status LED once T1 is booted up
  on_boot:
    priority: -10
    then:
      - light.turn_on: blue_led_light

esp8266:
  board: esp01_1m    

wifi:
  ssid: "xxxxxxx"
  password: "xxxxxxx"

# Enable logging
logger:
  level: INFO

# Enable Home Assistant API
api:

ota:

web_server:
  port: 80
  version: 2

# the vl53l0x is i2c
i2c:
  sda: GPIO3
  scl: GPIO1
  scan: true  

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO0
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Sonoff Touchpad 1"
    on_press:
      - switch.toggle: relay_1
  
  - platform: status
    name: "Sonoff Status"

  - name: "Breakbeam Sensor"
    id: breakbeam_sensor
    platform: template
    device_class: motion

switch:
  - platform: gpio
    name: "Sonoff Relay 1"
    pin: GPIO12
    id: relay_1

output:
  # Register the blue LED as a dimmable output ....
  - platform: esp8266_pwm
    id: blue_led
    pin: GPIO13
    inverted: true

light:
  # ... and then make a light out of it.
  - platform: monochromatic
    name: "Sonoff Blue LED"
    output: blue_led
    internal: true
    id: blue_led_light

sensor:
  - name: "Breakbeam Sensor Dist"
    id: breakbeam_sensor_dist
    platform: vl53l0x
    address: 0x29
    update_interval: 0.2s
    long_range: false
    internal: true
    filters:
      - lambda: !lambda |-
          /**
           * Minimum distance to trigger the virtual break beam sensor.
           * '0.5' meters is about 20  inches.
           */
          static double minTripDistance = 0.5;

          if (x <= minTripDistance) {
            if (id(breakbeam_sensor).state == true) {
              // Beam was already broken
              return {};
            }
            // Beam was just broken
            id(breakbeam_sensor).publish_state(true);
            ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Detected");
            return {};
          }
          else {
            if (id(breakbeam_sensor).state == false) {
              // Beam was already un-broken
              return {};
            }
            // Beam was just un-broken
            id(breakbeam_sensor).publish_state(false);
            ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Cleared");
            return {};
          }

Thanks again @jonathanb !!

1 Like

@garyjmilne I've installed the multiswitch driver, and it works well. Only problem is there is no state presented in HE. I can control the on/off, but it doesn't show up in device or logs or webcore with any action.