This binding makes ESPHome devices available in openHAB through the ESPHome Home Assistant Native API. This is an alternative to using MQTT and/or running Home Assistant in addition to openHAB.
It does NOT provide any webpage for managing the ESP themselves. Use the ESPHome dashboard for that.
Benefits of using the native API over MQTT:
Read more here: https://esphome.io/components/api#advantages-over-mqtt
addons folder, or by installing from the Marketplace https://community.openhab.org/t/esphome-binding-for-the-native-api/146849Note: Remember to edit your things and add the
encryptionKey.
The binding uses mDNS to automatically discover devices on the network.
Configuration file to use: $OH_CONFDIR/services/runtime.cfg .
It is possible to set a default encryption key for all devices in the binding configuration. This is useful if you have a lot of devices using the same encryption key. If you are using file based config, add
binding.esphome:defaultEncryptionKey=<BASE64ENCODEDKEY>
The internal threadpool defaults to maximum numProcessors * 2 threads. If you have a lot of devices, you may want to increase this. You can do this by setting the maxPoolSize parameter in the binding configuration.
binding.esphome:maxPoolSize=20
The default operating mode is always connected. This means that the binding will attempt to reconnect to devices that are offline. This is the recommended mode for devices that are always connected to the network, such as those running on mains power.
To enable deep sleep mode, set deepSleep = true in the device configuration. In this mode, the binding will not attempt to reconnect to devices that are offline, and will instead wait for them to come back online. This is the recommended mode for battery-powered devices that use deep sleep to save power. Also set deepSleepTimeoutSeconds to a reasonable value to detect if the device isn't reachable.
device Thing Configuration| Name | Type | Description | Default | Required | Advanced |
|---|---|---|---|---|---|
deviceId |
text |
Expected name of ESPHome. Used to ensure that we're communicating with the correct device. Use value from esphome.name in ESPHome device configuration |
yes | no | |
hostname |
text |
Hostname or IP address of the device. Typically something like myboard.local or 192.168.0.123. It is recommended to configure your ESP with a static IP address and use that here, it will allow for quicker reconnects |
yes | no | |
port |
integer |
IP Port of the device | 6053 | no | no |
encryptionKey |
text |
Encryption key as defined in api: encryption: key: <BASE64ENCODEDKEY>. See https://esphome.io/components/api#configuration-variables. Can also be set on the binding level if your ESPs all use the same key. |
yes or via binding configuration | yes | |
allowActions |
boolean |
Allow the device to send actions and events. | false | no | no |
deepSleep |
boolean |
Enables deep sleep / passive connection mode. If your ESPHome device is configured with deep_sleep, enable this setting. |
false | no | yes |
deepSleepTimeoutSeconds |
integer |
Deep sleep timeout watchdog. If this number of seconds has passed, the thing status changes to OFFLINE. Set this to at least the number of seconds your device sleep. Set to 0 to disable |
3600 | no | yes |
pingInterval |
integer |
Seconds between sending ping requests to device to check if alive | 10 | no | yes |
maxPingTimeouts |
integer |
Number of missed ping requests before deeming device unresponsive. | 4 | no | yes |
reconnectInterval |
integer |
Seconds for 1st reconnect attempt when connection is lost or the device restarts. Random number between 0 and reconnectInterval / 2 is added to spread load. NOTE: The binding listens for mDNS announcements from devices coming online, and will reconnect automatically. If this works well on your setup (network wise), this value should be raised to avoid continous re-connect attempts for offline devices (ie devices running on battery) | 10 | no | yes |
maxReconnectInterval |
integer |
Maximum reconnect interval in seconds. Reconnect interval will increase exponentially until this value is reached. | 120 | no | yes |
connectTimeout |
integer |
Seconds until a connection attempt to a device is declared as failed. | 60 | no | yes |
logPrefix |
text |
Log prefix to use for this device. | deviceId | no | yes |
deviceLogLevel |
text |
ESPHome device log level to stream from the device. | NONE | no | yes |
enableBluetoothProxy |
boolean |
Allow this device to proxy Bluetooth traffic. Requires ESPHome device to be configured with bluetooth_proxy |
false | no | yes |
configFileFullPath |
string |
Fully qualified path to esphome yaml for this device. Used for firmware upgrades. | false | no | yes |
Channels are auto-generated based on actual device configuration. Bring the device online, and the binding will interrogate the device and create channels based on the device configuration.
Most channels are of STATE kind, meaning they are linked to an Item and hold a state (e.g., Temperature, Switch status).
The ESPHome event entity type is mapped to an openHAB TRIGGER channel. These channels do not hold a state and cannot be linked to an Item. Instead, they fire an event on the openHAB event bus when the device reports an event.
You can use these in rules like this:
configuration: {
}
triggers:
-id
:
"1"
label: My
Event
Channel
triggered
pluginId: core.ChannelEventTrigger
type: core.ChannelEventTrigger
configuration:
event: dag
channelUID: esphome:device:mydevice:scene_dag
Or in Rules DSL:
rule "ESPHome Event"
when
Channel "esphome:device:mydevice:scene_dag" triggered dag
then
logInfo("rules", "Event 'dag' was triggered")
end
esphome:device:garage-opener "Garage ESP32" [deviceId="garage-opener", hostname="garage-opener.local", encryptionKey="JVWAgubY1nCe3x/5xeyMBfaN9y68OOUMh5dACIeVmjk=",
pingInterval=10, maxPingTimeouts=4, reconnectInterval=10, maxReconnectInterval=120, connectTimeout=60, logPrefix="garage", deviceLogLevel="INFO"]
Number:Temperature Garage_Temperature "Temperature" <temperature> {channel="esphome:device:garage-opener:temperature"}
Number:Dimensionless Garage_Humidity "Humidity" <humidity> {channel="esphome:device:garage-opener:humidity"}
Switch Garage_Switch "Relay" <switch> {channel="esphome:device:garage-opener:relay_4"}
Openhab updates thing configuration based on mDNS messages. There is currently no way to avoid this, but there are 2 workarounds:
- Use a different thingUID from the one discovered, ie
esphome:device:fridge->esphome:device:fridge-esp- Use file based configuration as they are read-only > See https://github.com/seime/openhab-esphome/issues/1 . TLDR: A "feature" in openHAB.
I get errors like [WARN ] [phome.internal.handler.ESPHomeHandler] - [mydevice] Error initial connection no.seime.openhab.binding.esphome.internal.comm.ProtocolAPIError: Failed to connect to 'XXXX.local.' port 6053
See previous question
with log messages like [WARN ] [home.internal.handler.ESPHomeHandler] - [esphome-deviceId] Ping responses lacking. Waited 4 times 10 seconds, total of 40. Assuming connection lost and disconnecting [INFO ] [ESPHome Socket Reader] [home.internal.comm.ESPHomeConnection] - [esphome-deviceId] Disconnecting socket.
This can be caused by a flaky device or network connection. It can also be caused by device overload, causing it to drop messages. If you are using the have a lot of chatty devices or using the bluetooth proxy, the ESP might overload it's TCP send buffer. To check if this is your problem, set the
apicomponent logger toVERBOSEand look forCannot send message because of TCP buffer space. If this happens, get a more powerful ESP or reduce how often it sends data.
If you have the
uptimesensor in your ESPHome configuration, you can use that to monitor the device uptime. If the device uptime is increasing while openHAB reports the device as offline, it is likely a network issue.
Unit 'XXXX' unknown to openHAB, returning DecimalType for state '1234.0' on channel 'esphome:device:8dcf64d482:my_channel_name
The unit is reported by the ESPHome device, but it doesn't match anything known to openHAB.
Solution: Add a valid
unit_of_measurementto your entity in the ESPHome configuration. Useunit_of_measurement: ""to remove the unit altogether from the entity.
No device_class reported by sensor '<name of sensor>'. Add device_class to sensor configuration in ESPHome. Defaulting to plain Number without dimension
This is because the ESP sensor does not report a
device_class. This field is used to determine item and category type in openHAB. Solution: Specify adevice_classto your ESPHome configuration. Example:![]()
See https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes for valid device_class values (use lowercase values) Also note that you may override default device_class by specifyingdevice_class: ""to remove any device class from the sensor.
Also see https://community.openhab.org/t/esphome-binding-for-the-native-api/146849/1 for more information.
It is now possible to use the built-in Bluetooth proxy in ESPHome. This allows you to use ESPHome devices as proxies for other Bluetooth devices such as BTHome sensors or a range of other Bluetooth devices.
NOTE: Only beacons / devices broadcasting data are supported at the moment. Connectable devices will be supported in a future release.
NOTE: The proxy bridge CANNOT be created in the UI, you must file based configuration!
The feature is still experimental and may not work as expected.
bluetooth_proxy component. See https://esphome.io/components/bluetooth_proxybluetooth_proxy:
active: true
device in openHAB with enableBluetoothProxy = trueesphome:device:garage-opener "Garage ESP32" [ ... enableBluetoothProxy=true ]
esphomeThis is the standard configuration for any type of Bluetooth adapter in openHAB (not documented elsewhere)
| Name | Type | Description | Default | Required | Advanced |
|---|---|---|---|---|---|
backgroundDiscovery |
boolean |
Add discovered device automatically to tihe inbox in the background | false | no | no |
inactiveDeviceCleanupInterval |
integer |
Number of seconds of Bluetooth device inactivity before removing from inbox | 60 | no | no |
inactiveDeviceCleanupThreshold |
integer |
300 | no | no |
Bridge bluetooth:esphome:proxy "ESPHome BLE Advertisement listener" [backgroundDiscovery = false] {
bthome parasite1 "b-Parasite #4354" [address="XX:XX:XX:XX:18:91", expectedReportingIntervalSeconds = 600]
}
NOTE: Set backgroundDiscovery to true if you want to automatically add discovered devices to the inbox. If not use manual scanning from the inbox.
As an alternative to manually streaming device logs via ESPHome dashboard, you can have openHAB stream the device logs directly to openHAB - which will write them using the standard log system.
deviceLogLevel parameter on the thing configuration. Valid values: https://esphome.io/components/logger.html#log-levelsWARN, so you need to add a logger named ESPHOMEDEVICEwith level INFO to see actual log statements. Either add this to your log4j.xml file or use the Karaf console:log:set INFO ESPHOMEDEVICE
or
<Loggers>
...
<Logger level="DEBUG" name="ESPHOMEDEVICE"/>
</Loggers>
This will produce logs on level INFO in the openHAB logs like this:
[2024-04-04 15:06:25.822] [boiler] [D][dallas.sensor:143]: 'VV Temp bottom': Got Temperature=21.0°C
[2024-04-04 15:06:25.834] [boiler] [D][sensor:094]: 'VV Temp bottom': Sending state 21.00000 °C with 1 decimals of accuracy
[2024-04-04 15:06:25.850] [boiler] [D][dallas.sensor:143]: 'VV Temp middle': Got Temperature=71.7°C
[2024-04-04 15:06:25.863] [boiler] [D][sensor:094]: 'VV Temp middle': Sending state 71.68750 °C with 1 decimals of accuracy
To redirect device logs to a separate log file, edit your log4j.xml file and add the following in the <Appenders> section:
<RollingFile fileName="${sys:openhab.logdir}/esphomedevice.log"
filePattern="${sys:openhab.logdir}/esphomedevice.log.%i" name="ESPHOMEDEVICE">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] %m%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="32 MB"/>
</Policies>
</RollingFile>
And add the following in the Loggers section:
<Logger additivity="false" level="INFO" name="ESPHOMEDEVICE">
<AppenderRef ref="ESPHOMEDEVICE"/>
</Logger>
You can send state to the ESPHome device using the homeassistant sensor type. Only entity_id field is used.
You can listen for several types of OpenHAB events, default is ItemStateChangedEvent. The following are supported:
| entity_id | OH Event listened for | Item/Thing |
|---|---|---|
<whatever>.ItemName |
ItemStateChangedEvent |
ItemName |
ItemStateChangedEvent.ItemName |
ItemStateChangedEvent |
ItemName |
ItemStateEvent.ItemName |
ItemStateEvent |
ItemName |
ItemStateUpdatedEvent.ItemName |
ItemStateUpdatedEvent |
ItemName |
ItemStatePredictedEvent.ItemName |
ItemStatePredictedEvent |
ItemName |
GroupItemStateChangedEvent.ItemName |
GroupItemStateChangedEvent |
ItemName |
GroupStateUpdatedEvent.ItemName |
GroupStateUpdatedEvent |
ItemName |
ThingStatusInfoEvent.my_thing_uid |
ThingStatusInfoEvent |
my:thing:uid |
ThingStatusInfoChangedEvent.my_thing_uid |
ThingStatusInfoChangedEvent |
my:thing:uid |
NOTE: EntityID in HA is case-insensitive - meaning only lowercase is used. Whatever you add in
entity_idin the ESPHome yaml will be converted to lowercase. In OH item names are case-sensitive, so you can have 2 items likeMYITEMandMyItem, and we cannot distinguish between the 2. Avoid this setup.
NOTE2: In Thing UIDs, the
:is replaced with_
NOTE3: For Group events, it is the group state that is sent, not the individual item states.
Making state changes to OH temperature sensor available in ESPHome:
sensor:
- platform: homeassistant
name: "Outside temperature"
entity_id: ItemStateChangedEvent.MyTemperatureItem
device_class: temperature
Listening for commands sent from OH to some OH item and making it available in ESPHome:
binary_sensor:
- platform: homeassistant
name: "Flower watering activating"
entity_id: ItemCommandEvent.WaterValve_Switch
Making ESPHome device react when a Thing changes status, ie goes offline/online:
text_sensor:
- platform: homeassistant
name: "ThingStatusInfoChangedEvent"
entity_id: ThingStatusInfoChangedEvent.astro_moon_local
Time sync from your openHAB server is supported using the HomeAssistant time source component.
time:
- platform: homeassistant
id: openhab_time
To process actions and events sent via the Native API Component's actions, the binding adds three new trigger types accessible via UI rules:
Be sure to enable allowActions in the Thing configuration so that openHAB will request the device to send events. The event object has getData, getDataTemplate, and getVariables methods to access the appropriate information for action and event events. For tag scanned events, the event's payload is the tag ID. The event's source will be of the form no.seime.openhab.binding.openhab$<device_id>, where device_id is the ESPHome device ID that sent the event.
Unfortunately, these triggers are not available from Rules DSL, but some other openHAB automation languages may support setting triggers based on any event sent through the event bus. To listen for these events, they look like this:
| ESPHome Action | Topic | Event Type | Payload |
|---|---|---|---|
homeassistant.action |
openhab/esphome/action/<action> |
esphome.ActionEvent |
JSON object with "data", "data_template", and "variables" sub-objects. |
homeassistant.event |
openhab/esphome/event/<event> |
esphome.EventEvent |
JSON object with "data", "data_template", and "variables" sub-objects. |
homeassistant.tag_scanned |
openhab/esphome/tag_scanned |
esphome.TagScannedEvent |
The tag id. |
For JRuby, use the event trigger. For Python Scripting, use GenericEventTrigger.
The binding can now trigger firmware updates via a Thing action.
It finds the latest firmware version by checking https://github.com/esphome/esphome/releases/latest at startup and every 24 hours.
2 channels are automatically added to each thing:
latestFirmwareVersion (String) which contains the latest firmware version.firmwareUpdateAvailable (Contact) where OPEN indicates a newer esphome version is availableThe following configuration must be in place for firmware upgrade to work:
Thing configuration parameter configFileFullPath to the fully qualified path of the esphome yaml file.esphome binary. Parameter is esphomeExecutable if not done via MainUIbrew upgrade esphome. Parameter is esphomeUpgradeExecutable if not done via MainUI.Note: Point 2 and 3 really depend on what OS your machine is running and whether Docker is involved or not. If you get it working, feel free to add an example section below for your OS and Docker setup.
Note2: The upgrade process runs even if the device is running the latest esphome version available.
Most entity types and functions are now supported. However, there are some limitations:
The following entity types are not yet supported (please submit a PR of file a feature request!)
camera
voice
siren
water_heater
light - not all modes are supported. Please create a PR if you need a specific mode.
In addition, the Bluetooth proxy isn't fully ready yet.