Hi all,
thanks to the first post getting all the information about the BT-Proto of the radoneye sensor. I have spent some time to programm a custom_sensor.h with radoeye for esp32 boards using esphome-Software. It is not done yet, but maybe a good start.
Best Michi
‘file: my_custom_sensor.h’
#include "esphome.h"
#include "BLEDevice.h"
//#include "BLEScan.h"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("00001523-1212-efde-1523-785feabcd123");
//service = dev.getServiceByUUID(btle.UUID('00001523-1212-efde-1523-785feabcd123'))
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("00001525-1212-efde-1523-785feabcd123");
static BLEUUID char24UUID("00001524-1212-efde-1523-785feabcd123");
//character = dev.getCharacteristics(startHnd=1, endHnd=0xFFFF, uuid=btle.UUID('00001525-1212-efde-1523-785feabcd123'))
static union { char c[4]; uint32_t b; float f; } radonval;
static union { char c[2]; uint16_t b; } pulsval;
static float radonnow;
static float radonday;
static float radonmonth;
static int puls;
static int puls10;
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLERemoteCharacteristic* p2RemoteCharacteristic;
static BLERemoteService* pRemoteService;
static BLEAdvertisedDevice* myDevice;
static String My_BLE_Address = "C1:96:0D:53:E9:A6";
//radon1 DA:B9:2C:5A:A9:75
//radon2 C1:96:0D:53:E9:A6
static BLEAddress *Server_BLE_Address;
static String Scanned_BLE_Address;
static boolean foundDevice = false; // Flag verifying if we found our device
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
ESP_LOGD("custom","Callback");
//ESP_LOGD("custom","Notify callback for characteristic %s", pBLERemoteCharacteristic->getUUID().toString().c_str());
//ESP_LOGD("custom"," of data length %i", length);
//ESP_LOGD("custom","data: %s",(char*)pData);
// Read the value of the characteristic.
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
ESP_LOGD("custom","onConnect");
}
void onDisconnect(BLEClient* pclient) {
connected = false;
ESP_LOGD("custom","onDisconnect");
}
};
bool connectToServer() {
ESP_LOGD("custom","Forming a connection to %s", myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
ESP_LOGD("custom"," - Created client");
pClient->setClientCallbacks(new MyClientCallback());
//myDevice->setAddress(BLEAddress("DA:B9:2C:5A:A9:75"))
// Connect to the remote BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
ESP_LOGD("custom"," - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
//BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
ESP_LOGD("custom","Failed to find our service UUID: %s", serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
ESP_LOGD("custom"," - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
ESP_LOGD("custom","Failed to find our characteristic UUID: %s", charUUID.toString().c_str());
pClient->disconnect();
return false;
}
ESP_LOGD("custom"," - Found our 1525 characteristic");
// Obtain a reference to the characteristic to write to in the service of the remote BLE server.
//dev.writeCharacteristic(11,b'\x50')
p2RemoteCharacteristic = pRemoteService->getCharacteristic(char24UUID);
if (p2RemoteCharacteristic == nullptr) {
ESP_LOGD("custom","Failed to find our characteristic 1524 UUID: %s", charUUID.toString().c_str());
pClient->disconnect();
return false;
}
if(p2RemoteCharacteristic->canWrite()) {
p2RemoteCharacteristic->writeValue(0x50);
ESP_LOGD("custom","write Value 0x50");
}
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
//ESP_LOGD("custom","BLE Advertised Device found");
if(foundDevice == false){ // Flag verifying if we found our device
Server_BLE_Address = new BLEAddress(advertisedDevice.getAddress()); // Update Server_BLE_Address if we didn't
Scanned_BLE_Address = Server_BLE_Address->toString().c_str();
if(Scanned_BLE_Address == My_BLE_Address) // Compares the scanned adress to what we are looking for
{
foundDevice = true; // Found our device
ESP_LOGD("custom","Found my MAC ");
}
}
// We have found a device, let us now see if it contains the service we are looking for.
//foundDevice == true &&
if ( advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
class MyCustomSensor : public PollingComponent, public Sensor {
public:
Sensor *radon_now = new Sensor();
Sensor *radon_day = new Sensor();
Sensor *radon_month = new Sensor();
// constructor
MyCustomSensor() : PollingComponent(300000) {}
void setup() override {
// This will be called by App.setup()
Serial.begin(115200);
ESP_LOGD("custom","Starting BLE Client for radoneye sensor.");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->start(5, false);
}
void update() override {
// This will be called every "update_interval" milliseconds.
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
ESP_LOGD("custom","We are now connected to the BLE Server.");
} else {
ESP_LOGD("custom","We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
// with the current time since boot.
if (connected) {
ESP_LOGD("custom","time %i", (int)millis()/1000);
//p2RemoteCharacteristic = pRemoteService->getCharacteristic(char24UUID);
if(p2RemoteCharacteristic->canWrite()) {
p2RemoteCharacteristic->writeValue(0x50);
ESP_LOGD("custom","Requested new values from sensor (write Value 0x50)");
} else{
ESP_LOGD("custom","Requested new values from sensor failed");
}
// Read the value of the characteristic.
if(pRemoteCharacteristic->canRead()) {
std::string value = pRemoteCharacteristic->readValue();
ESP_LOGD("custom","read results");
//ESP_LOGD("custom","byte0-7: %02X %02X %02X %02X %02X %02X %02X",value[0],value[1],value[2],value[3],value[4],value[5],value[6]);
//z.B. 50 10 8F C2 05 40 7B
radonval.c[0] = value[2];
radonval.c[1] = value[3];
radonval.c[2] = value[4];
radonval.c[3] = value[5];
radonnow = radonval.f * 37.0;
radonval.c[0] = value[6];
radonval.c[1] = value[7];
radonval.c[2] = value[8];
radonval.c[3] = value[9];
radonday = radonval.f * 37.0;
radonval.c[0] = value[10];
radonval.c[1] = value[11];
radonval.c[2] = value[12];
radonval.c[3] = value[13];
radonmonth = radonval.f * 37.0;
pulsval.c[0] = value[14];
pulsval.c[1] = value[15];
puls = pulsval.b;
pulsval.c[0] = value[16];
pulsval.c[1] = value[17];
puls10 = pulsval.b;
//ESP_LOGD("custom","Radon %X", radonval.b);
ESP_LOGD("custom","Radonnow %.0f Day %.0f Month %.0f Pulse %i Puls10min %i ", radonnow, radonday,radonmonth, puls, puls10);
}
//Publish Values to frontend
radon_now->publish_state(radonnow);
radon_day->publish_state(radonday);
radon_month->publish_state(radonmonth);
ESP_LOGD("custom","Publish new values to frontend");
// Set the characteristic's value to be the array of bytes that is actually a string.
//pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
}else if(doScan){
ESP_LOGD("custom","Not connected anymore");
setup();
//BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
}
}
};
and here the radon1.yaml:
esphome:
name: radon1
platform: ESP32
board: nodemcu-32s
includes:
- my_custom_sensor.h
wifi:
ssid: "yourssid"
password: "yourpasswd"
api:
logger:
ota:
sensor:
- platform: custom
lambda: |-
auto my_radon = new MyCustomSensor();
App.register_component(my_radon);
return {my_radon->radon_now, my_radon->radon_day, my_radon->radon_month};
sensors:
- name: "Radon now"
unit_of_measurement: Bq
accuracy_decimals: 0
- name: "Radon day"
unit_of_measurement: Bq
accuracy_decimals: 0
- name: "Radon month"
unit_of_measurement: Bq
accuracy_decimals: 0