myhomeiot / esphome-components Goto Github PK
View Code? Open in Web Editor NEWA collection of my ESPHome components
License: Other
A collection of my ESPHome components
License: Other
I'm trying to use GL.iNet GL-S10 (https://blakadder.com/gl-s10/) as a BLE gateways and no BLE packets received at all. Regular ESP32 board based BLE Gateway working just fine.
Same time ble device_tracker binary sensor (tracking NUT mini) working fine on GL-S10's
- platform: ble_presence
mac_address: 7E:FE:3E:EC:59:FB
name: ${board_name}_White
device_class: presence
Config used for devices https://github.com/to4ko/myconfig/blob/master/esphome/esp32_poe_ble_hs.yaml
BLE device_tracker's binary Sensors
BLE Proxy working also
I just came across the option discovery: true
I think this is pretty much the default behavior anyone would expect of a BLE gateway. And it's a lot more easy to understand than the currently documented method with the text_sensor.
I think this option should be mentioned in the documentation and examples.
My minimal config is this.
ble_gateway:
id: $device_name
discovery: true
on_ble_advertise:
then:
- homeassistant.service:
service: ble_monitor.parse_data
data:
packet: !lambda return packet;
gateway_id: $device_name
Add this to any esphome device and receive BLE advertisements. Simple.
Hi, great work on this, exactly what I was looking for!
One question though. Is there any modification needed on the HA ble_monitor component to get the battery values ?
I used your example to publish them to the parse service but I don't see the battery sensor appearing in HA.
In my setup, I use ESPHome to capture BLE advertisements and send them to Home Assistant using the homeassistant.event action. Occasionally, due to network instability or restarting Home Assistant, the event fails to send, leading to data loss. Having a retry mechanism would ensure that events are reliably sent to Home Assistant, improving the overall robustness of the system.
e.g.
ble_gateway:
devices:
- mac_address: 01:23:45:67:89:AB
- mac_address: !secret lywsd03mmc_mac
on_ble_advertise:
then:
homeassistant.event:
event: esphome.on_ble_advertise
data:
packet: !lambda return packet;
retry:
attempts: 5
delay: 500ms
Is it possible?
(sorry for the dumb question, i started studying esphome few days ago)
now i can extend the bluetooth coverage to receive data from sensors far away very easily but...
what if i want to send a command form home assistant to a bluetooth bot that is far away too?! is it possible using something similar?!
thanks
Hi @myhomeiot
Firstly, thanks very much for the gateway functionality - I am using it extensively with BLE sensors and it works great!
And now I am trying to use the BLE client for another device, but can't quite work out if what I'm trying to do is already possible, and I just haven't worked out how to, or if I'm in fact making a feature request!
The device is a BLE swimming pool sensor called Blue Connect, and I am able to retrieve data from it using a BLE tool on my phone, but it involves the following procedure...
That is what it looks like from my phone.
UUID F3300002-FOA2-9B06-0C59-1BC4763B5C00 is the one that I write TRUE / 0x01 to and then I get the answer notified on F3300003-F0A2-9B06-0C59-1BC4763B5C00
Do you think this is possible with BLE client?
Thanks
Is there any reason why this shouldn't work?
on_ble_advertise:
then:
- logger.log: BLE !lambda return packet;
- homeassistant.service:
service: ble_monitor.parse_data
data:
packet: !lambda return packet;
gateway_id: $device_name
It seems a bit unnecessary to rely on a homeassistant automation to listen to the event first
Hi @myhomeiot,
Thanks a lot for the awesome job. ๐๐
When compiling on esphome 2022.7.0-dev for a Lolin C3 Mini it throws an error: ValueError: invalid literal for int() with base 10: '0-dev'. Do you have any suggestions to make it work?
Thank you in advance.
INFO Reading configuration /config/esphome/ble-gateway04.yaml...
WARNING The selected Arduino framework version is not the recommended one. If there are connectivity or build issues please remove the manual version.
WARNING The selected Arduino framework version is not the recommended one. If there are connectivity or build issues please remove the manual version.
INFO Detected timezone 'Europe/Bucharest'
INFO Generating C++ source...
Traceback (most recent call last):
File "/usr/local/bin/esphome", line 33, in <module>
sys.exit(load_entry_point('esphome', 'console_scripts', 'esphome')())
File "/esphome/esphome/__main__.py", line 931, in main
return run_esphome(sys.argv)
File "/esphome/esphome/__main__.py", line 918, in run_esphome
rc = POST_CONFIG_ACTIONS[args.command](args, config)
File "/esphome/esphome/__main__.py", line 330, in command_compile
exit_code = write_cpp(config)
File "/esphome/esphome/__main__.py", line 163, in write_cpp
generate_cpp_contents(config)
File "/esphome/esphome/__main__.py", line 175, in generate_cpp_contents
CORE.flush_tasks()
File "/esphome/esphome/core/__init__.py", line 613, in flush_tasks
self.event_loop.flush_tasks()
File "/esphome/esphome/coroutine.py", line 245, in flush_tasks
next(task.iterator)
File "/esphome/esphome/__main__.py", line 155, in wrapped
await coro(conf)
File "/config/esphome/.esphome/external_components/4e725a3b/components/myhomeiot_ble_client/__init__.py", line 57, in to_code
reversed = versiontuple(const.__version__) >= versiontuple("2021.9.0")
File "/config/esphome/.esphome/external_components/4e725a3b/components/myhomeiot_ble_client/__init__.py", line 52, in versiontuple
return tuple(map(int, (v.split("."))))
ValueError: invalid literal for int() with base 10: '0-dev'
esp32:
board: lolin_c3_mini
framework:
type: arduino
version: 2.0.3
platform_version: 4.4.0
Is there an example of using a direct HA service call instead of an automation?
Would it be? Is there an advantage to one or the other?
on_ble_advertise:
then:
homeassistant.service:
event: ble_monitor.parse_data
data:
packet: !lambda return packet;
Hi everyone.
Wow this is really cool! I am fairly new to ESPHome and am struggling to publish the raw packet to mqtt (and not home-assistant). How will I go about it?
I am using esphome with Passive BLE Monitor gateway.
I tried sending the my mac address to the esphome, so I think it should do a round trip, and create an entity somewhere?
but its not created anything
2024-04-23 15:34:04.319 INFO (MainThread) [custom_components.ble_monitor.ble_parser] Unknown advertisement received for mac: 2A:03:4E:CF:0F:38service data: []manufacturer specific data: [b'\t\xff\x03*8\x0f\xcfN\x03*']local name: BBQ ProbeE 92696UUID16: 2584,UUID128: None
# ESPHome
ble_gateway:
id: blegateway
on_ble_advertise:
then:
homeassistant.event:
event: esphome.on_ble_advertise
data:
packet: !lambda return packet;
binary_sensor:
- platform: homeassistant
id: ble_gateway_discovery
entity_id: binary_sensor.ble_gateway
attribute: discovery
on_state:
then:
lambda: id(blegateway).set_discovery(x);
text_sensor:
- platform: homeassistant
id: ble_gateway_devices
entity_id: binary_sensor.ble_gateway
attribute: devices
on_value:
then:
lambda: id(blegateway).set_devices(x);
switch:
- platform: template
id: switch_ble_gateway_discovery
name: BLE Gateway Discovery
icon: mdi:bluetooth-connect
lambda: return id(blegateway).get_discovery();
turn_on_action: [lambda: id(blegateway).set_discovery(true);]
turn_off_action: [lambda: id(blegateway).set_discovery(false);]
disabled_by_default: true
entity_category: config
# Home Assistant
input_boolean:
settings_ble_gateway:
name: BLE Gateway
icon: mdi:bluetooth
settings_ble_gateway_discovery:
name: BLE Gateway Discovery
icon: mdi:bluetooth-connect
input_text:
settings_ble_gateway_add_device:
name: BLE Gateway Add Device
icon: mdi:bluetooth-connect
initial: ''
template:
- binary_sensor:
- name: BLE Gateway
icon: mdi:bluetooth
state: "{{ is_state('input_boolean.settings_ble_gateway', 'on') }}"
attributes:
discovery: "{{ is_state('input_boolean.settings_ble_gateway_discovery', 'on') }}"
# devices: "{{ states | selectattr('entity_id', 'search', '^(device_tracker|sensor).ble_') | selectattr('attributes.mac address', 'defined') | map(attribute='attributes.mac address') | unique | sort | join('') | replace(':', '') ~ (states('input_text.settings_ble_gateway_add_device') | replace(':', '') | trim) if is_state('binary_sensor.ble_gateway', 'on') }}"
# Important note: In Passive BLE Monitor version 7.8.2 and later 'attributes.mac address' was changed to 'attributes.mac_address', please update your config
# devices: "{{ states | selectattr('entity_id', 'search', '^(device_tracker|sensor).ble_') | selectattr('attributes.mac_address', 'defined') | map(attribute='attributes.mac_address') | unique | sort | join('') | replace(':', '') ~ (states('input_text.settings_ble_gateway_add_device') | replace(':', '') | trim) if is_state('binary_sensor.ble_gateway', 'on') }}"
# Note: In Home Assistant 2022.x, Passive BLE Monitor version 8.x and later you can use device attribute identifiers
devices: >-
{% set devices = namespace(items = []) %}
{% for s in states | selectattr('entity_id', 'search', '^(device_tracker|sensor).ble_') | map(attribute='entity_id') %}
{% set devices.items = devices.items + ([device_id(s)] if device_id(s) else []) %}
{% endfor %}
{% set ns = namespace(items = []) %}
{% for s in devices.items | unique %}
{% set ns.items = ns.items + [(device_attr(s, 'identifiers') | first)[1]] %}
{% endfor %}
{{ ns.items | unique | sort | join('') | replace(':', '') ~ (states('input_text.settings_ble_gateway_add_device') | replace(':', '') | trim) if is_state('binary_sensor.ble_gateway', 'on') }}```
How does one identify the uuids to be used ?
In a config with the "native" ble_client, I currently have this in the sensor section:
ble_client:
- mac_address: FF:D1:01:5E:87:70
id: Oras6160FZ_Bathroom
sensor:
- platform: ble_client
type: characteristic
ble_client_id: Oras6160FZ_Bathroom
name: "oras_ValveCounter"
service_uuid: "2BE32DB1-5F6B-4CBD-8803-38D6DFB16490"
characteristic_uuid: "2BE32DB1-5F6B-4CBD-8873-8D6DFB164900"
update_interval: 300s
notify: false
lambda: |-
uint8_t* pdata = (uint8_t*) x.data();
unsigned long int totConsumption = pdata[0];
totConsumption += ( pdata[1]<<8);
totConsumption += ( pdata[2]<<16);
totConsumption += ( pdata[3]<<24);
id(oras_totConsumption).publish_state(totConsumption);
id(oras_totConsumption_m3).publish_state((float)totConsumption/(float)1000);
ESP_LOGI("ble_adv", "Total water consumption %ld", totConsumption);
unsigned long int totOpening = pdata[4];
totOpening += ( pdata[5]<<8);
totOpening += ( pdata[6]<<16);
totOpening += ( pdata[7]<<24);
ESP_LOGI("ble_adv", "Total valve openings %ld", totOpening);
ESP_LOGI("ble_adv", " - Setting bleStatus to true");
id(bleStatus).publish_state(true);
return (float)totOpening;
icon: 'mdi:faucet'
filters:
- filter_out: nan
What would be the correct way to rewrite this to use myhomeiot_ble_client ?
And if multiple services/characteristics needs to be queried on the same device - what would be the approach ?
Don't working on ESPHome v2021.9.0, need downgrade
Hi,
I've been trying to set up an ESP32 classic with your code, so that I can void using directly connected USB Bluetooth dongles.
I have a Home Assistant instance, and the ESP32 yaml below - but am getting the API error shown at the bottom of this post....are you able to offer any suggestions as to what I am doing wrong?
api:
encryption:
key: xxxxxxxxxx
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
esphome:
name: screek-ble-monitor-1a
friendly_name: BLE Monitor Gateway 1A
name_add_mac_suffix: True
project:
name: Screek.BLE Monitor Gateway
version: 1A
external_components:
- source: github://myhomeiot/esphome-components
logger:
esp32:
variant: ESP32
board: esp32dev
framework:
type: arduino
version: 2.0.7
platform_version: 6.0.1
captive_portal:
improv_serial:
esp32_ble_tracker:
sensor:
- platform: uptime
name: Uptime
id: sys_uptime
update_interval: 10s
- platform: wifi_signal
name: RSSI
id: wifi_rssi
update_interval: 10s
entity_category: "diagnostic"
- platform: template
id: esp_memory
icon: mdi:memory
name: ESP Free Memory
lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024;
unit_of_measurement: 'kB'
state_class: measurement
entity_category: "diagnostic"
ble_gateway:
id: blegateway
on_ble_advertise:
then:
homeassistant.event:
event: esphome.on_ble_advertise
data:
packet: !lambda return packet;
binary_sensor:
- platform: homeassistant
id: ble_gateway_discovery
entity_id: binary_sensor.ble_gateway
attribute: discovery
on_state:
then:
lambda: id(blegateway).set_discovery(x);
- platform: status
name: Online
id: ink_ha_connected
text_sensor:
- platform: homeassistant
id: ble_gateway_devices
entity_id: binary_sensor.ble_gateway
attribute: devices
on_value:
then:
lambda: id(blegateway).set_devices(x);
switch:
- platform: template
id: switch_ble_gateway_discovery
name: BLE Gateway Discovery
icon: mdi:bluetooth-connect
lambda: return id(blegateway).get_discovery();
turn_on_action: [lambda: id(blegateway).set_discovery(true);]
turn_off_action: [lambda: id(blegateway).set_discovery(false);]
disabled_by_default: true
entity_category: config
button:
- platform: restart
# disabled_by_default: True
icon: mdi:power-cycle
name: "ESP Reboot"
- platform: factory_reset
disabled_by_default: True
name: Factory Reset
id: factory_reset_al
INFO ESPHome 2024.6.3
INFO Reading configuration /config/esphome/esp32-bluetooth-proxy-0f0bd4.yaml...
WARNING The selected Arduino framework version is not the recommended one. If there are connectivity or build issues please remove the manual version.
WARNING The selected Arduino framework version is not the recommended one. If there are connectivity or build issues please remove the manual version.
INFO Starting log output from screek-ble-monitor-1a.local using esphome API
WARNING Can't connect to ESPHome API for screek-ble-monitor-1a.local: Error resolving IP address: [Errno -5] No address associated with hostname (APIConnectionError)
INFO Trying to connect to screek-ble-monitor-1a.local in the background
Hi,
I've a sensor connected on passive ble, with a usb bluetooth connected on my home assistant and working fine various weeks ago.
I try connect this sensor on BLE gateway, but send the first time value and not send anymore any values.
Maybe i've put or done anything wrong and need your help.
It's my esp32 board: https://pt.aliexpress.com/item/1005006220389074.html?spm=a2g0o.order_list.order_list_main.45.3e1bcaa4BezpRe&gatewayAdapt=glo2bra
My esphome code on esp32:
substitutions:
devicename: esp32-blegateway
upper_devicename: esp32-blegateway
esphome:
name: $devicename
external_components:
- source: github://myhomeiot/esphome-components
esp32:
board: esp32dev
framework:
type: arduino
mqtt:
broker: x.x.x.x
username: !secret esphomemqttlogin
password: !secret esphomemqttpass
port: 1883
wifi:
ssid: !secret esphomewifi
password: !secret esphomewifipass
reboot_timeout: 5min
fast_connect: on
domain: !secret esphomedomain
logger:
api:
encryption:
key: !secret esphomeapiha
ota:
password: !secret esphomeota
web_server:
port: 80
esp32_ble_tracker:
ble_gateway:
id: blegateway
on_ble_advertise:
then:
homeassistant.event:
event: esphome.on_ble_advertise
data:
packet: !lambda return packet;
# gateway_id: ${device_id}
binary_sensor:
- platform: homeassistant
id: ble_gateway_discovery
entity_id: binary_sensor.ble_gateway
attribute: discovery
on_state:
then:
lambda: id(blegateway).set_discovery(x);
text_sensor:
- platform: homeassistant
id: ble_gateway_devices
entity_id: binary_sensor.ble_gateway
attribute: devices
on_value:
then:
lambda: id(blegateway).set_devices(x);
switch:
- platform: template
id: switch_ble_gateway_discovery
name: BLE Gateway Discovery
icon: mdi:bluetooth-connect
lambda: return id(blegateway).get_discovery();
turn_on_action: [lambda: id(blegateway).set_discovery(true);]
turn_off_action: [lambda: id(blegateway).set_discovery(false);]
disabled_by_default: true
entity_category: config
Put this on home assistant:
input_boolean:
settings_ble_gateway:
name: BLE Gateway
icon: mdi:bluetooth
settings_ble_gateway_discovery:
name: BLE Gateway Discovery
icon: mdi:bluetooth-connect
input_text:
settings_ble_gateway_add_device:
name: BLE Gateway Add Device
icon: mdi:bluetooth-connect
initial: ''
template:
- binary_sensor:
- name: BLE Gateway
icon: mdi:bluetooth
state: "{{ is_state('input_boolean.settings_ble_gateway', 'on') }}"
attributes:
discovery: "{{ is_state('input_boolean.settings_ble_gateway_discovery', 'on') }}"
# devices: "{{ states | selectattr('entity_id', 'search', '^(device_tracker|sensor).ble_') | selectattr('attributes.mac address', 'defined') | map(attribute='attributes.mac address') | unique | sort | join('') | replace(':', '') ~ (states('input_text.settings_ble_gateway_add_device') | replace(':', '') | trim) if is_state('binary_sensor.ble_gateway', 'on') }}"
# Important note: In Passive BLE Monitor version 7.8.2 and later 'attributes.mac address' was changed to 'attributes.mac_address', please update your config
# devices: "{{ states | selectattr('entity_id', 'search', '^(device_tracker|sensor).ble_') | selectattr('attributes.mac_address', 'defined') | map(attribute='attributes.mac_address') | unique | sort | join('') | replace(':', '') ~ (states('input_text.settings_ble_gateway_add_device') | replace(':', '') | trim) if is_state('binary_sensor.ble_gateway', 'on') }}"
# Note: In Home Assistant 2022.x, Passive BLE Monitor version 8.x and later you can use device attribute identifiers
devices: >-
{% set devices = namespace(items = []) %}
{% for s in states | selectattr('entity_id', 'search', '^(device_tracker|sensor).ble_') | map(attribute='entity_id') %}
{% set devices.items = devices.items + ([device_id(s)] if device_id(s) else []) %}
{% endfor %}
{% set ns = namespace(items = []) %}
{% for s in devices.items | unique %}
{% set ns.items = ns.items + [(device_attr(s, 'identifiers') | first)[1]] %}
{% endfor %}
{{ ns.items | unique | sort | join('') | replace(':', '') ~ (states('input_text.settings_ble_gateway_add_device') | replace(':', '') | trim) if is_state('binary_sensor.ble_gateway', 'on') }}
And create this automation on Home assistant:
- id: ESPHome BLE Advertise
alias: ESPHome BLE Advertise
mode: queued
trigger:
- platform: event
event_type: esphome.on_ble_advertise
action:
- service: ble_monitor.parse_data
data:
packet: "{{ trigger.event.data.packet }}"
What ti's wrong on my configuration?
Thank you for help.
After update my ESP32 device from 2023.10.6 to 2023.11.2 both ble_gateway and myhomeiot_ble_client stopped working.
The compilation process was successful, without any errors.
The log shows neither received packets nor client connections. It shows nothing... silence...
I'm using the device to read Mi Flora (HHCCJCY01) and Hygro thermometer clock (LYWSD02).
Ble client is used to read the battery status of Mi Flora.
Hi!
Is there a way to combine ble_client with ble_gateway?
I have miflora sensors which are being passively read via ble_gateway, I am forwarding all of their BLE data processing to Home Assistant. This is working quite well.
What is missing? The battery information. For miflora devices you need to do a read of the battery data; the firmware did at one point broadcast this information but because of the battery drain, later firmware versions for miflora plant sensors removed this feature.
Your ble_client code I think would be an awesome solution to this since you can specify intervals and you are not limited to the number of client limitations that the builtin esphome ble stack has.
So far, I haven't been able to figure out how to make it work. Do you have an example?
An optimal solution would be for the client and gateway code to use the same device list, or better, have the ble_client only make requests of devices it has seen.
Do you have anything you can share about using ble_client with ble_gateway?
Thanks!
FWIW, I have 3 esp32 tracking ~48 miflora sensors.
I use the Passive BLE Monitor component and have the Switchbot Mini Plug that uses the ESP32-C3 and can be flashed with the Tasmota32 firmware that supports this device. Any chance that the BLE Gateway component will support this firmware?
Hi!
It would be great to have a feature not only read values from BLE client devices, but sending commands. I have some BLE key finders and they have a feature to beep if I would like to find them. Now I can only trigger it via app.
Could you extend the myhomeiot_ble_client with a functionality to connect to the device, write command, disconnect if a button is pressed like with ble_client.ble_write?
button:
Thank you!
Hi @myhomeiot,
Currently the battery percentage doesn't get passed to BLE Monitor.
The last time it did, seems to have been when I was using the arduino framework, a few months back. Unless I'm wrong and something changed in BLE Monitor.
The other values are getting passed just fine. Tried with both "ble_monitor.parse_data" and "esphome.on_ble_advertise".
Any ideea why it might happen?
Thanks in advance for your help.
Here are the logs:
[15:30:35][I][app:102]: ESPHome version 2023.3.0 compiled on Mar 17 2023, 15:28:06
[15:30:58][I][myhomeiot_ble_client:032]: [C4:7C:8D:6D:3D:92] Connecting
[15:31:00][I][myhomeiot_ble_client:087]: [C4:7C:8D:6D:3D:92] Connected successfully, app_id (4)
[15:31:00][I][myhomeiot_ble_client:139]: Battery (72%), firmware (3.3.5)
[15:31:00][I][myhomeiot_ble_client:042]: [C4:7C:8D:6D:3D:92] Disconnecting
[15:31:00][I][esp-idf:000]: W (36256) BT_HCI: hci cmd send: disconnect: hdl 0x0, rsn:0x13
[15:31:00][I][esp-idf:000]: W (36263) BT_APPL: gattc_conn_cb: if=3 st=0 id=3 rsn=0x16
[15:31:00][I][esp-idf:000]: W (36268) BT_APPL: gattc_conn_cb: if=4 st=0 id=4 rsn=0x16
[15:31:00][I][esp-idf:000]: W (36273) BT_APPL: gattc_conn_cb: if=5 st=0 id=5 rsn=0x16
[15:31:00][I][esp-idf:000]: W (36276) BT_APPL: gattc_conn_cb: if=6 st=0 id=6 rsn=0x16
[15:31:00][W][api.connection:083]: Home Assistant 2023.3.5 (192.168.45.201): Connection closed
[15:31:00][I][esp-idf:000]: W (36316) BT_HCI: hcif disc complete: hdl 0x0, rsn 0x16
[15:31:30][I][myhomeiot_ble_client:032]: [C4:7C:8D:6D:47:9D] Connecting
[15:31:31][I][myhomeiot_ble_client:087]: [C4:7C:8D:6D:47:9D] Connected successfully, app_id (4)
[15:31:31][I][myhomeiot_ble_client:163]: Battery (95%), firmware (3.3.5)
[15:31:31][I][myhomeiot_ble_client:042]: [C4:7C:8D:6D:47:9D] Disconnecting
[15:31:31][I][esp-idf:000]: W (67372) BT_HCI: hci cmd send: disconnect: hdl 0x0, rsn:0x13
[15:31:31][I][esp-idf:000]: W (67384) BT_APPL: gattc_conn_cb: if=3 st=0 id=3 rsn=0x16
[15:31:31][I][esp-idf:000]: W (67388) BT_APPL: gattc_conn_cb: if=4 st=0 id=4 rsn=0x16
[15:31:31][I][esp-idf:000]: W (67391) BT_APPL: gattc_conn_cb: if=5 st=0 id=5 rsn=0x16
[15:31:31][I][esp-idf:000]: W (67396) BT_APPL: gattc_conn_cb: if=6 st=0 id=6 rsn=0x16
[15:31:32][W][api.connection:083]: Home Assistant 2023.3.5 (192.168.45.201): Connection closed
[15:31:32][I][esp-idf:000]: W (67427) BT_HCI: hcif disc complete: hdl 0x0, rsn 0x16
Here's my config:
external_components:
- source: github://myhomeiot/esphome-components
substitutions:
devicename: ble_gateway04
friendly_name: BLE-GATEWAY04
gateway_id: ble_gateway04
esphome:
name: ble-gateway04
friendly_name: ${friendly_name}
esp32:
board: mhetesp32minikit
framework:
type: esp-idf
sdkconfig_options:
CONFIG_BT_BLE_42_FEATURES_SUPPORTED: y
CONFIG_ESP_TASK_WDT: y
CONFIG_ESP_TASK_WDT_TIMEOUT_S: "10"
preferences:
flash_write_interval: 1min
logger:
level: INFO
api:
reboot_timeout: 1h
encryption:
key: !secret api_encryption_key
ota:
safe_mode: true
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "${friendly_name} Fallback"
#password: !secret esphome_fallback_password
time:
- platform: homeassistant
id: homeassistant_time
mdns:
disabled: false
esp32_ble:
esp32_ble_tracker:
bluetooth_proxy:
active: true
cache_services: true
ble_gateway:
id: $gateway_id
discovery: true
devices:
- mac_address: A4:C1:38:75:D6:49
- mac_address: A4:C1:38:2E:C1:14
- mac_address: A4:C1:38:97:A6:7D
- mac_address: 8C:F6:81:A0:1F:ED
- mac_address: 8C:F6:81:91:BF:C8
- mac_address: 8C:F6:81:A0:37:2A
- mac_address: 8C:F6:81:91:D0:20
- mac_address: 2C:11:65:23:9A:5B
- mac_address: C4:7C:8D:6D:30:EE
- mac_address: C4:7C:8D:6E:1A:78
- mac_address: C4:7C:8D:6D:47:9F
- mac_address: C4:7C:8D:6E:1A:67
- mac_address: C4:7C:8D:6D:44:D3
- mac_address: C4:7C:8D:6D:3D:92
- mac_address: C4:7C:8D:6D:30:89
- mac_address: C4:7C:8D:6D:30:A8
- mac_address: C4:7C:8D:6D:30:FD
- mac_address: C4:7C:8D:6E:1D:EF
- mac_address: C4:7C:8D:6D:30:87
- mac_address: C4:7C:8D:6D:3D:8D
- mac_address: C4:7C:8D:6D:30:86
- mac_address: C4:7C:8D:6D:30:6E
- mac_address: C4:7C:8D:6D:30:70
- mac_address: C4:7C:8D:6E:19:8C
- mac_address: C4:7C:8D:6D:47:9D
- mac_address: C4:7C:8D:6D:30:D2
- mac_address: C4:7C:8D:6E:1A:66
- mac_address: C4:7C:8D:6D:3D:7F
- mac_address: C4:7C:8D:6E:1E:B0
- mac_address: 68:AB:BC:4F:E5:C7
- mac_address: 68:AB:BC:4F:0A:56
- mac_address: B4:60:ED:F3:3A:0B
- mac_address: EC:4D:3E:BE:A7:6D
- mac_address: ED:DE:34:3F:48:0C
- mac_address: EF:A8:A8:06:8C:E6
- mac_address: 0C:95:41:D2:D8:B0
- mac_address: F6:92:88:5A:32:DF
- mac_address: EC:6B:41:D1:6B:F8
- mac_address: D8:71:4D:6A:7D:FE
- mac_address: D0:F0:18:44:1A:DE
- mac_address: D0:F0:18:44:1A:E2
- mac_address: D0:F0:18:78:0D:08
on_ble_advertise:
then:
homeassistant.service:
service: ble_monitor.parse_data
data:
packet: !lambda return packet;
gateway_id: $gateway_id
# then
# homeassistant.event:
# event: esphome.on_ble_advertise
# data:
# packet: !lambda return packet;
# gateway_id: $gateway_id
myhomeiot_ble_host:
myhomeiot_ble_client:
- mac_address: C4:7C:8D:6D:3D:92 #Ficus Microcarpa Bonsai
service_uuid: '1204'
characteristic_uuid: '1A02'
update_interval: 24h
on_value:
then:
homeassistant.event:
event: esphome.on_ble_advertise
# homeassistant.service:
# service: ble_monitor.parse_data
data:
packet: !lambda |-
if (x.size() < 2)
{
ESP_LOGE("myhomeiot_ble_client", "payload has wrong size (%d)", x.size());
return "";
};
ESP_LOGI("myhomeiot_ble_client", "Battery (%d%%), firmware (%s)", x[0], std::string(x.begin(), x.end()).substr(2).c_str());
char buffer[70 + 1];
const uint8_t *remote_bda = xthis.remote_bda();
snprintf(buffer, sizeof(buffer), "043E2002010000%02X%02X%02X%02X%02X%02X14020106030295FE0C1695FE41209800000A1001%02X00",
remote_bda[5], remote_bda[4], remote_bda[3], remote_bda[2], remote_bda[1], remote_bda[0], x[0]);
return std::string(buffer).c_str();
gateway_id: $gateway_id
- mac_address: C4:7C:8D:6D:47:9D #Tradescantia Pallida
service_uuid: '1204'
characteristic_uuid: '1A02'
update_interval: 24h
on_value:
then:
homeassistant.event:
event: esphome.on_ble_advertise
# homeassistant.service:
# service: ble_monitor.parse_data
data:
packet: !lambda |-
if (x.size() < 2)
{
ESP_LOGE("myhomeiot_ble_client", "payload has wrong size (%d)", x.size());
return "";
};
ESP_LOGI("myhomeiot_ble_client", "Battery (%d%%), firmware (%s)", x[0], std::string(x.begin(), x.end()).substr(2).c_str());
char buffer[70 + 1];
const uint8_t *remote_bda = xthis.remote_bda();
snprintf(buffer, sizeof(buffer), "043E2002010000%02X%02X%02X%02X%02X%02X14020106030295FE0C1695FE41209800000A1001%02X00",
remote_bda[5], remote_bda[4], remote_bda[3], remote_bda[2], remote_bda[1], remote_bda[0], x[0]);
return std::string(buffer).c_str();
gateway_id: $gateway_id
binary_sensor:
- platform: status
name: "${friendly_name} Status"
- platform: homeassistant
id: ${devicename}_discovery
name: ${friendly_name} Discovery
entity_id: binary_sensor.${devicename}
attribute: discovery
on_state:
then:
lambda: id($gateway_id).set_discovery(x);
text_sensor:
- platform: homeassistant
id: ${devicename}_devices
name: ${friendly_name} Devices
entity_id: binary_sensor.${devicename}
attribute: devices
on_value:
then:
lambda: id($gateway_id).set_devices(x);
- platform: wifi_info
ip_address:
name: ${friendly_name} IP Address
ssid:
name: ${friendly_name} Connected SSID
bssid:
name: ${friendly_name} Connected BSSID
mac_address:
name: ${friendly_name} MAC Wifi Address
- platform: version
name: ${friendly_name} ESPHome Version
switch:
- platform: template
id: switch_${devicename}_discovery
name: ${friendly_name} Discovery
icon: mdi:bluetooth-connect
lambda: return id($gateway_id).get_discovery();
turn_on_action: [lambda: id($gateway_id).set_discovery(true);]
turn_off_action: [lambda: id($gateway_id).set_discovery(false);]
disabled_by_default: true
entity_category: config
button:
- platform: restart
name: ${friendly_name} Restart
id: ${devicename}_reset
entity_category: diagnostic
- platform: factory_reset
name: ${friendly_name} Factory Reset
id: ${devicename}_fatory_reset
internal: true
entity_category: diagnostic
- platform: safe_mode
name: ${friendly_name} Safe Mode Boot
id: ${devicename}_safe_mode_boot
entity_category: diagnostic
sensor:
- platform: uptime
name: ${friendly_name} Device Uptime
id: ${devicename}_device_uptime
- platform: wifi_signal
name: ${friendly_name} Wifi Signal
id: ${devicename}_wifi_signal
update_interval: 60s
- platform: internal_temperature
name: ${friendly_name} Internal Temperature
id: ${devicename}_internal_temperature
update_interval: 60s
I would like to be able to also transmit the packet by UUID beacon and not just by mac address in BLE Gateway. Was there such a plan?
I'm getting this error:
unknown tag !<!lambda> at line 44, column 41:
... packet: !lambda return packet;
when trying to set up a BLE Gateway in my component's yaml:
esp32_ble_tracker:
ble_gateway:
id: blegateway
on_ble_advertise:
then:
homeassistant.event:
event: esphome.on_ble_advertise
data:
packet: !lambda return packet;
Hi, I just started experimenting with BLE. I wanted to provide some feedback on my one and only device. ;) The Govee H5075 seemingly worked fine with passive BLE monitoring in home assistant, so I was hopeful.
I tried the ESP and was not having any luck. It took me a while to understand that Home Assistant WAS getting the data packet, but it was just dropping it.
It looks like the ESP data packet is about 30 bytes longer or so than what just using passive was using. I have not yet looked into why on the passive side yet (there is a lot more code there to sift thru). However, looking at the much smaller ble_gateway.cpp file. I noticed this.
esphome-components/components/ble_gateway/ble_gateway.cpp
Lines 27 to 31 in aa1b7a8
Looking at this line, basically the valid data is all up to scan_result.bda[2].
Scan_result.bda[1] and [0] seems to be garbage to me. However, because the 2 garbage structs are sent to passive in the data packet, and the way that passive reads the last bda[1] (which is the garbage one and ignores the good one bda[2]), the packet gets dropped.
Thus, I wonder if there might be something else that this function above could do to mitigate these kinds of errors. It seems that bda[0] to bda[5] are all written out regardless if the values are valid or not?
I hope this makes sense to someone. I am just starting out, so thank you for the attention!
Jae
Heho.
I'm trying to get the ble_gateway to work, but if discovery is disabled (which is default) the on_ble_advertise doesn't trigger.
How to enable discovery by default? Without it the examples in you documentation do nothing.
esphome:
name: esphome-kueche-ble-gateway:
external_components:
- source: github://myhomeiot/esphome-components
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: ""
wifi:
ssid: !secret wifi24_username
password: !secret wifi24_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esphome-Kueche-Ble-Gateway"
password: ""
captive_portal:
esp32_ble_tracker:
# ESPHome
ble_gateway:
id: blegateway
on_ble_advertise:
then:
homeassistant.event:
event: esphome.on_ble_advertise
data:
packet: !lambda return packet;
gateway_id: ${device_id}
binary_sensor:
- platform: homeassistant
id: ble_gateway_discovery
entity_id: binary_sensor.ble_gateway
attribute: discovery
on_state:
then:
lambda: id(blegateway).set_discovery(x);
text_sensor:
- platform: homeassistant
id: ble_gateway_devices
entity_id: binary_sensor.ble_gateway
attribute: devices
on_value:
then:
lambda: id(blegateway).set_devices(x);
switch:
- platform: template
id: switch_ble_gateway_discovery
name: BLE Gateway Discovery
icon: mdi:bluetooth-connect
lambda: return id(blegateway).get_discovery();
turn_on_action: [lambda: id(blegateway).set_discovery(true);]
turn_off_action: [lambda: id(blegateway).set_discovery(false);]
disabled_by_default: true
Hi @myhomeiot,
When trying to read the value of the battery characteristic of a soocare.toothbrush.x3 I see the below warning and the value is not read: [W] | [myhomeiot_ble_client:194] | [EF:A8:A8:06:8C:E6] READ_CHAR_EVT error reading char at handle (33), status (5)
With nRF Connect I can see the value is 17%. Is % the cause of the issue, and how can I remove it?
Thank in advance.
23:01:25 | [I] | [myhomeiot_ble_client:032] | [EF:A8:A8:06:8C:E6] Connecting |
---|---|---|---|
23:01:25 | [I] | [myhomeiot_ble_client:087] | [EF:A8:A8:06:8C:E6] Connected successfully, app_id (1) |
23:01:25 | [W] | [myhomeiot_ble_client:194] | [EF:A8:A8:06:8C:E6] READ_CHAR_EVT error reading char at handle (33), status (5) |
23:01:25 | [I] | [myhomeiot_ble_client:042] | [EF:A8:A8:06:8C:E6] Disconnecting |
The configuration is:
myhomeiot_ble_client:
- mac_address: EF:A8:A8:06:8C:E6
service_uuid: '180F'
characteristic_uuid: '2A19'
update_interval: 24h
on_value:
then:
lambda: |-
id(mihai_s_toothbrush_battery).publish_state(x[0]);
Hi,
Can this component be used to send out advertisement packets using BLE? I want to be able to read some sensor values and then broadcast them out as a standard BLE advertisement packet. It looks like it could do something like that, but I've very new to ESPHome.
Thanks,
Rob Smart
Hello,
I've been working on integrating a few iBeacon devices into the Passive BLE Monitor within Home Assistant, using UUIDs for identification. However, I noticed an issue where these devices only function correctly when the discovery mode is enabled.
Upon further investigation, I suspect this issue is related to the ble_gateway component primarily filtering on MAC addresses. Hence, the UUID-based iBeacons do not seem to automatically update as expected.
I believe this behavior might not be immediately clear for other users as well, especially those who are working with iBeacons or other BLE devices identified by UUID. Therefore, I suggest that the documentation could benefit from an update to provide clarity on this specific behavior.
Moreover, I'd like to propose a feature request: Would it be possible to enhance the ble_gateway component to allow automatic updates for UUID-based devices in the same manner as it does for MAC-based devices? This feature could significantly improve the usability and versatility of the Passive BLE Monitor integration.
Hi, I noticed your example for the delonghi.
I compiled the code without problems adapting it to my machine and it seems to connect correctly. None of the switches seem to work though:
Could it be a machine setting? Or did something change with a firmware update?
Does it work without problems for you?
and thus is my configuration:
`substitutions:
name: "cucina"
delonghi_mac: !secret delonghi_mac
delonghi_name_prefix: Coffee Machine
delonghi_id_prefix: coffee_machine
delonghi_service_uuid: 00035b03-58e6-07dd-021a-08123a000300
delonghi_characteristic_uuid: 00035b03-58e6-07dd-021a-08123a000301
delonghi_update_interval: '5000'
packages:
esphome.bluetooth-proxy: github://esphome/bluetooth-proxies/esp32-generic.yaml@main
globals:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
esphome:
name: ${name}
name_add_mac_suffix: false
on_loop:
then:
- lambda: |-
if (!id(delonghi_millis)) {
id(binary_sensor_${delonghi_id_prefix}connected).publish_initial_state(false);
id(binary_sensor${delonghi_id_prefix}).publish_initial_state(false);
id(delonghi_millis) = millis();
}
static unsigned char CMD_HEALTH_CHECK[] = {0x0d, 0x05, 0x75, 0x0f, 0xda, 0x25};
if (id(binary_sensor_${delonghi_id_prefix}connected).state && (millis() - id(delonghi_millis) > ${delonghi_update_interval})) {
auto chr = id(ble_client${delonghi_id_prefix}).get_characteristic(
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_service_uuid}"),
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_characteristic_uuid}"));
if (chr) {
ESP_LOGD("${delonghi_id_prefix}", ">>> %s", format_hex_pretty(CMD_HEALTH_CHECK, sizeof(CMD_HEALTH_CHECK)).c_str());
chr->write_value(CMD_HEALTH_CHECK, sizeof(CMD_HEALTH_CHECK));
}
id(delonghi_millis) = millis();
}
esp32_ble_tracker:
mqtt:
topic_prefix: dinamica
discovery: false
broker: 192.168.1.2
port: 1883
username: michele
password: hd0806681
ble_client:
binary_sensor:
platform: template
id: binary_sensor_${delonghi_id_prefix}_connected
name: ${delonghi_name_prefix}
device_class: connectivity
entity_category: diagnostic
platform: template
id: binary_sensor_${delonghi_id_prefix}
internal: true
sensor:
switch:
platform: ble_client
id: switch_${delonghi_id_prefix}enable
name: ${delonghi_name_prefix} Enable
ble_client_id: ble_client${delonghi_id_prefix}
disabled_by_default: true
entity_category: config
platform: template
id: switch_${delonghi_id_prefix}
name: ${delonghi_name_prefix}
icon: mdi:coffee
lambda: return id(binary_sensor_${delonghi_id_prefix}).state;
turn_on_action:
platform: template
id: button_${delonghi_id_prefix}americano
name: ${delonghi_name_prefix} Americano
icon: mdi:coffee-to-go-outline
on_press:
then:
- lambda: |-
if (!id(binary_sensor${delonghi_id_prefix}connected).state)
return;
static unsigned char CMD_AMERICANO_ON[] = {0x0d, 0x12, 0x83, 0xf0, 0x06, 0x01, 0x01, 0x00, 0x28, 0x02, 0x03, 0x0f, 0x00, 0x6e, 0x00, 0x00, 0x06, 0x47, 0x8b};
static unsigned char CMD_AMERICANO_OFF[] = {0x0d, 0x08, 0x83, 0xf0, 0x06, 0x02, 0x06, 0x18, 0x71};
auto chr = id(ble_client${delonghi_id_prefix}).get_characteristic(
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_service_uuid}"),
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_characteristic_uuid}"));
if (chr)
chr->write_value(CMD_AMERICANO_ON, sizeof(CMD_AMERICANO_ON));
platform: template
id: button_${delonghi_id_prefix}coffe
name: ${delonghi_name_prefix} Coffe
icon: mdi:coffee-to-go-outline
on_press:
then:
- lambda: |-
if (!id(binary_sensor${delonghi_id_prefix}connected).state)
return;
static unsigned char COFFE_ON[] = {0x0d, 0x0f, 0x83, 0xf0, 0x02, 0x01, 0x01, 0x00, 0x67, 0x02, 0x02, 0x00, 0x00, 0x06, 0x77, 0xff};
static unsigned char COFFE_OFF[] = {0x0d, 0x08, 0x83, 0xf0, 0x02, 0x02, 0x06, 0xc4, 0xb1};
auto chr = id(ble_client${delonghi_id_prefix}).get_characteristic(
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_service_uuid}"),
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_characteristic_uuid}"));
if (chr)
chr->write_value(COFFE_ON, sizeof(COFFE_ON));
platform: template
id: button_${delonghi_id_prefix}espresso
name: ${delonghi_name_prefix} Espresso
icon: mdi:coffee-to-go-outline
on_press:
then:
- lambda: |-
if (!id(binary_sensor${delonghi_id_prefix}connected).state)
return;
static unsigned char ESPRESSO_ON[] = {0x0d, 0x11, 0x83, 0xf0, 0x01, 0x01, 0x01, 0x00, 0x28, 0x02, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xfc};
static unsigned char ESPRESSO_OFF[] = {0x0d, 0x08, 0x83, 0xf0, 0x01, 0x02, 0x06, 0x9d, 0xe1};
auto chr = id(ble_client${delonghi_id_prefix}).get_characteristic(
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_service_uuid}"),
esp32_ble_tracker::ESPBTUUID::from_raw("${delonghi_characteristic_uuid}"));
if (chr)
chr->write_value(ESPRESSO_ON, sizeof(ESPRESSO_ON));
text_sensor:
platform: ble_client
id: text_sensor_${delonghi_id_prefix}
internal: true
ble_client_id: ble_client_${delonghi_id_prefix}
service_uuid: ${delonghi_service_uuid}
characteristic_uuid: ${delonghi_characteristic_uuid}
notify: true
update_interval: never
on_notify:
then:
lambda: |-
static unsigned char packet[19];
static uint8_t index = 0;
id(delonghi_millis) = millis();
ESP_LOGD("${delonghi_id_prefix}", "%s", format_hex_pretty((uint8_t *) x.c_str(), x.size()).c_str());
if (index + x.size() > sizeof(packet))
ESP_LOGE("${delonghi_id_prefix}", "Packet longer than (%d) bytes", sizeof(packet));
else {
memcpy(&packet[index], x.c_str(), x.size());
index += x.size();
if (index > 0 && packet[0] != 0xD0)
ESP_LOGE("${delonghi_id_prefix}", "Packet has wrong signature (0x%02X)", packet[0]);
else if (index >= 2 && index >= packet[1] + 1) {
ESP_LOGD("${delonghi_id_prefix}", "<<< %s", format_hex_pretty(packet, index).c_str());
uint16_t deviser = 0x1D0F, i3, i4, i5, crc = packet[index - 2] << 8 | packet[index - 1];
for (int i = 0; i < index - 2; i++) {
i3 = (((deviser << 8) | (deviser >> 8)) & 0x0000FFFF) ^ packet[i];
i4 = i3 ^ ((i3 & 0xFF) >> 4);
i5 = i4 ^ ((i4 << 12) & 0x0000FFFF);
deviser = i5 ^ (((i5 & 0xFF) << 5) & 0x0000FFFF);
}
if (deviser != crc)
ESP_LOGE("${delonghi_id_prefix}", "CRC error, expected (0x%04X) received (0x%04X)", deviser, crc);
else {
switch (packet[2]) {
case 0x75:
id(binary_sensor_${delonghi_id_prefix}).publish_state(packet[9] != 0);
id(sensor_${delonghi_id_prefix}_alarm).publish_state((int32_t) packet[7] +
(int32_t)(packet[8] << 8) + (int32_t)(packet[12] << 16) + (int32_t)(packet[13] << 24));
break;
default:
ESP_LOGW("${delonghi_id_prefix}", "Unknown packet type (0x%02X)", packet[2]);
}
}
}
else
return;
}
index = 0;`
I implemented your code for firmware and battery.
Only changed 2 things:
This is the result:
How can I debug the issue of battery sensor ?
P.S.> From battery point of view, is better to go with "flower_care_battery_ble_advertise.yaml" than "flower_care.yaml" like I did ?
Thx in advance,
Simone
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.