Nice work, tx for the reaction and the links provided. I will dig into this solution with only using the manufacturer data string. Keep you posted!
Hi,
Thanks for work on this. I’ve scratching my head to make this esp32_ble:
example working but the
id(ble)->get_advertising()
always returns null.
Do i need another component like esp32_ble_server or do i need to init something else?
Thank you!
Hi @ashald
Your work is a very welcome oasis in a google search desert
I have tried to implement this to simulate a BLE temperature sensor to be received by a Viltron controller, the code works up to this line.
// Force esp_ble to use new data
id(ble).get_advertising()->start();
This causes a core panic. No Idea why and I don’t know how to decode a backtrace from esphome ,
If I rem the above line it boots normally, but obviously doesn’t transmit any ble signal
Logs are here:
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
[I][logger:262]: Log initialized
[C][ota:469]: There have been 0 suspected unsuccessful boot attempts.
[D][esp32.preferences:114]: Saving 1 preferences to flash...
[D][esp32.preferences:143]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[I][app:029]: Running through setup()...
[C][dht:011]: Setting up DHT...
[C][esp32_ble:027]: Setting up BLE...
[D][esp32_ble:043]: BLE setup complete
[C][wifi:038]: Setting up WiFi...
[C][wifi:039]: Local MAC: 30:AE:A4:8B:A8:4C
[D][wifi:387]: Starting scan...
[D][advertisement:068]: Refreshing advertisement
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400d86ca PS : 0x00060b30 A0 : 0x800dfb00 A1 : 0x3ffcd410
A2 : 0x00000000 A3 : 0x00000000 A4 : 0x3ffc3c44 A5 : 0x00000000
A6 : 0x00000000 A7 : 0x003fffff A8 : 0x00000000 A9 : 0x00000001
A10 : 0x3ffcd480 A11 : 0x00000000 A12 : 0x0000000c A13 : 0x3ffcd48c
A14 : 0x3ffc0230 A15 : 0x00000000 SAR : 0x0000001d EXCCAUSE: 0x0000001c
EXCVADDR: 0x0000007c LBEG : 0x400913cc LEND : 0x400913d7 LCOUNT : 0xffffffff
Backtrace:0x400d86c7:0x3ffcd4100x400dfafd:0x3ffcd470 0x400dfa4d:0x3ffcd4b0 0x401f3f47:0x3ffcd4d0 0x401f3f77:0x3ffcd4f0 0x401f3de1:0x3ffcd510 0x400df993:0x3ffcd530 0x400de7c2:0x3ffcd580 0x400e061e:0x3ffcd5b0 0x400e646e:0x3ffcd6c0
ELF file SHA256: 0000000000000000
Rebooting...
YAML is here
esphome:
name: ble-server
includes:
- ble-server-structs.h
esp32_ble:
id: ble
esp32:
board: esp32dev
framework:
type: arduino
time:
- platform: sntp
id: ntp
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "REDACTED"
ota:
password: "REDACTED"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "ble-server Fallback Hotspot"
password: "REDACTED"
captive_portal:
sensor:
- platform: dht
pin: GPIO16
temperature:
id: ble_server_temperature
name: "Ble Server Temperature"
filters:
- or:
- throttle: 10s
- delta: 0.2
device_class: temperature
state_class: measurement
unit_of_measurement: °C
humidity:
id: ble_server_humidity
name: "Ble Server Humidity"
filters:
- delta: 2
device_class: humidity
state_class: measurement
unit_of_measurement: "%"
update_interval: 10s
interval:
- interval: 10seconds
then:
- lambda: |-
ESP_LOGD("advertisement", "Refreshing advertisement");
// We allocate single instance in memory and refresh it in place
static manufacturer_data_t* advertisement = new manufacturer_data_t;
// Assuming there is a time component configured with identifier ntp
advertisement->data.timestamp = id(ntp).now().timestamp;
// Assuming there is a sensor component configured with identifier ble_server_temperature
advertisement->data.ble_server_temperature = (uint16_t) id(ble_server_temperature).state;
if (advertisement->company_id == 0) { // Execute once after boot for initial setup
ESP_LOGD("advertisement", "Initializing advertisement");
advertisement->company_id = 0xFFFF; // 0xFFFF reserved for local testing and non-commercial use
id(ble).get_advertising()->set_manufacturer_data((uint8_t*) advertisement, sizeof(manufacturer_data_t));
ESP_LOGD("main", "Advertisement initialized");
}
// Force esp_ble to use new data
id(ble).get_advertising()->start();
ESP_LOGD("advertisement", "Advertisement refreshed");
ble-server-structs.h
typedef struct payload {
time_t timestamp;
uint16_t ble_server_temperature;
} __attribute__((packed)) payload_t;
typedef struct manufacturer_data {
uint16_t company_id;
payload_t data;
} manufacturer_data_t;
Any idea what I am doing wrong?
Hi @anthonykeane, from a glance, you’re missing
esp32_ble_server:
from your YAML that would pull-in server-related BLE dependencies.
As a follow-up, I’d just mention that I found the above setup working perfectly when I have a constantly powered server, and a client that has to consume data quickly every now and then. If both transmitter and receiver have constant power, you might want to look into BTHome or ESP-Now based solutions - I think both are widely mentioned in ESPHome discord (#show-off) and docs.
@ashald Thank you, It works well now.
I really appreciate your help,
Any chance you could update the docs so the example has esp32_ble_server:
included?
Hi, I wanted to create an esp32 water level sensor to run from a battery.
I was hoping to use BLE and although I have enabled esp32_ble_server: in my yaml. Home assistant doesn’t find it. but my phone does.
My home assistant is a raspberry pi4 which does have Bluetooth and is added as a device within HA.
is there something I’m doing wrong? can someone point me in the right direction?
The “esp32_ble_server” is for other components to use it as a base for them to expose thier entity but that does not mean it shows up in HA. You could use “esphome-ble-controller” and a second esp connected to WIFI and main’s power to publish it to HA
Hi
Unfortunately this now fails I guess, because of some code changes around the BLE improv push
Any idea on how to get advertising of data working again without needing to go through client/server connection?
Thanks!
Ok. To follow up my earlier message, I have successfully managed to get advertising of state data within Manufacturer data working correctly. This allows sending data, and also reading of data on IOS which locks downs all advertised attributes except manufacturer data.
Using latest esphome 2023.10.6
No need for structs or additional files
Make sure ble_server enabled. Note here this has id: ble
esp32_ble_server:
id: ble
manufacturer_data: [0xFF, 0xFF, 0xF1, 0x00]
&&
time:
- platform: sntp
id: ntp
on_time:
- seconds: 0,10
then:
- lambda: |-
ESP_LOGD("main", "Advertisement updated");
float f_value = id(levelmetres).state;
uint8_t *float_data = (uint8_t*)&f_value;
ESP_LOGD("main", "Sending updated Level %f", id(levelmetres).state );
id(ble).set_manufacturer_data({ 0xFF, 0xFF, 0xF9, float_data[0], float_data[1], float_data[2], float_data[3]});
Using time, repeating every 10 seconds.
levelmetres = is a template level sensor.
The rest convert the float value to hex chars and updates the manufacturer data, with the values.
To read back convert the values after 0xF9 to float using Little endian.
Glenn
Hi, I can’t have esphome to compile. I get a error on get_advertising()
error: ‘class esphome::esp32_ble::ESP32BLE’ has no member named ‘get_advertising’; did you mean ‘advertising_’?
Is that still working for you?
How do you get this information with ESP32 esphome ble client?
It tells you in the docs how to set up devices, scan for devices, etc…
I understand the concept but Im not sure how to write a lambda code to “convert the values after 0xF9 to float using Little endian.”
That’s what I see in the Logs:
[13:59:43][VV][esp32_ble_tracker:440]: Address: 68:B6:B3:AF:9A:22 (PUBLIC)
[13:59:43][VV][esp32_ble_tracker:442]: RSSI: -58
[13:59:43][VV][esp32_ble_tracker:443]: Name: ‘’
[13:59:43][VV][esp32_ble_tracker:451]: Ad Flag: 6
[13:59:43][VV][esp32_ble_tracker:457]: Manufacturer data: F9.A4.55.F8.42 (5)
[13:59:43][VV][esp32_ble_tracker:473]: Adv data: 02.01.06.08.FF.FF.FF.F9.A4.55.F8.42 (12)
So the msg is being advertised, I know the MAC address. Seems like I need manufacture_id for ble_client which I assume is FFFF in this case. The manufacture data is there.
I see this example on esphome website that would update a template sensor with the BLE value above, just don’t know how to configure.
esp32_ble_tracker:
on_ble_manufacturer_data_advertise:
- mac_address: 68:B6:B3:AF:9A:22
manufacturer_id: FFFF
then:
- lambda: |-
if (x[0] != 0x7b || x[1] != 0x61) return;
int value = x[2] + (x[3] << 8);
id(ble_sensor).publish_state(value);
Thank you!
Yaml please, not gibberish.
I have tried this:
on_ble_manufacturer_data_advertise:
- mac_address: 68:B6:B3:AF:9A:22
manufacturer_id: FFFF
then:
- lambda: |-
int value = x[1] + (x[2] << 8) + (x[3] << 16) + (x[3] << 24);
id(ble_sensor).publish_state(value);
But Im getting wrong values:
[17:10:14][VV][esp32_ble_tracker:440]: Address: 68:B6:B3:AF:9A:22 (PUBLIC)
[17:10:14][VV][esp32_ble_tracker:442]: RSSI: -60
[17:10:14][VV][esp32_ble_tracker:443]: Name: ''
[17:10:14][VV][esp32_ble_tracker:451]: Ad Flag: 6
[17:10:14][VV][esp32_ble_tracker:457]: Manufacturer data: F9.74.A5.F7.42 (5)
[17:10:14][VV][esp32_ble_tracker:473]: Adv data: 02.01.06.08.FF.FF.FF.F9.74.A5.F7.42 (12)
[17:10:14][V][sensor:043]: 'Test Voltage': Received new state -134765200.000000
[17:10:14][D][sensor:094]: 'Test Voltage': Sending state -134765200.00000 V with 0 decimals of accuracy
[17:10:14][VV][api.service:140]: send_sensor_state_response: SensorStateResponse {
key: 3719805054
state: -1.34765e+08
missing_state: NO
}
Im picking up the BLE transmitted Hex values just not getting the decimal conversion right.
Thank you!
Have you asked the people in the discord server?
I got the answer from someone smart in another group. I was converting Int instead of Float. That’s what works for me:
on_ble_manufacturer_data_advertise:
- mac_address: #your MAC address
manufacturer_id: FFFF
then:
- lambda: |-
float value = *((float*)&x[1]);
id(ble_sensor).publish_state(value);
wasn’t that suggested to you right here?
I did write I understand but didn’t know how to do it, see below.
Nonetheless, you helped a lot with answers like this:
Fallingaway24Justin6d
It tells you in the docs how to set up devices, scan for devices, etc…
Or this:
Fallingaway24Justin6d
Have you asked the people in the discord server?
Thanks for pointing out that too, very helpful:
Fallingaway24Justin6d
wasn’t that suggested to you right here?
I just really want to thank you for the great help you provided. I didn’t know what I would do without you.
Hopefully my reply helps someone else that is not that good on coding.