Skip to content

Commit 4ba2748

Browse files
committed
add of Xiaomi Mijia BT4.0 clock temperature and humidity sensor (LYWSD02)
and enable multiple services data readings for Mijia standard device. Indeed the new version seems to publish several service data compared to old ones. Please note that I'have update the library with the work of @fguiet see: nkolban/ESP32_BLE_Arduino#24
1 parent a11e336 commit 4ba2748

3 files changed

Lines changed: 145 additions & 82 deletions

File tree

ZgatewayBT.ino

Lines changed: 114 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -55,75 +55,86 @@ vector<BLEdevice> devices;
5555
static int taskCore = 0;
5656

5757
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
58-
void onResult(BLEAdvertisedDevice advertisedDevice) {
59-
trc(F("Creating BLE buffer"));
60-
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
61-
JsonObject& BLEdata = jsonBuffer.createObject();
62-
String mac_adress = advertisedDevice.getAddress().toString().c_str();
63-
BLEdata.set("id", (char *)mac_adress.c_str());
64-
mac_adress.replace(":","");
65-
mac_adress.toUpperCase();
66-
String mactopic = subjectBTtoMQTT + mac_adress;
67-
if (advertisedDevice.haveName()) BLEdata.set("name", (char *)advertisedDevice.getName().c_str());
68-
if (advertisedDevice.haveManufacturerData()) BLEdata.set("manufacturerdata", (char *)advertisedDevice.getManufacturerData().c_str());
69-
if (advertisedDevice.haveRSSI()) BLEdata.set("rssi", (int) advertisedDevice.getRSSI());
70-
if (advertisedDevice.haveTXPower()) BLEdata.set("txpower", (int8_t) advertisedDevice.getTXPower());
71-
#ifdef subjectHomePresence
72-
if (advertisedDevice.haveRSSI()) haRoomPresence(BLEdata);// this device has an rssi in consequence we can use it for home assistant room presence component
73-
#endif
74-
if (advertisedDevice.haveServiceData()){
75-
76-
char mac[mac_adress.length()+1];
77-
mac_adress.toCharArray(mac,mac_adress.length()+1);
78-
79-
trc(F("Get service data "));
80-
81-
std::string serviceData = advertisedDevice.getServiceData();
82-
int serviceDataLength = serviceData.length();
83-
String returnedString = "";
84-
for (int i=0; i<serviceDataLength; i++)
85-
{
86-
int a = serviceData[i];
87-
if (a < 16) {
88-
returnedString = returnedString + "0";
89-
}
90-
returnedString = returnedString + String(a,HEX);
91-
}
92-
char service_data[returnedString.length()+1];
93-
returnedString.toCharArray(service_data,returnedString.length()+1);
94-
service_data[returnedString.length()] = '\0';
95-
#ifdef pubBLEServiceData
96-
BLEdata.set("servicedata", service_data);
97-
BLEdata.set("servicedatauuid", (char *)advertisedDevice.getServiceDataUUID().toString().c_str());
98-
#endif
99-
if((!oneWhite() || isWhite(mac)) && !isBlack(mac)){ //if not black listed mac we go AND if we have no white mac or this mac is white we go out
100-
pub((char *)mactopic.c_str(),BLEdata);
101-
if (strstr(BLEdata["servicedatauuid"].as<char*>(),"fe95") != NULL){
102-
trc("Processing BLE device data");
103-
int pos = -1;
104-
pos = strpos(service_data,"209800");
105-
if (pos != -1){
106-
trc(F("mi flora data reading"));
107-
#ifdef ZmqttDiscovery
108-
if(!isDiscovered(mac)) MiFloraDiscovery(mac);
109-
#endif
110-
process_data(pos - 24,service_data,mac);
111-
}
112-
pos = -1;
113-
pos = strpos(service_data,"20aa01");
114-
if (pos != -1){
115-
trc(F("mi jia data reading"));
116-
#ifdef ZmqttDiscovery
117-
if(!isDiscovered(mac)) MiJiaDiscovery(mac);
118-
#endif
119-
process_data(pos - 26,service_data,mac);
120-
}
58+
void onResult(BLEAdvertisedDevice advertisedDevice) {
59+
trc(F("Creating BLE buffer"));
60+
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
61+
JsonObject& BLEdata = jsonBuffer.createObject();
62+
String mac_adress = advertisedDevice.getAddress().toString().c_str();
63+
BLEdata.set("id", (char *)mac_adress.c_str());
64+
mac_adress.replace(":","");
65+
mac_adress.toUpperCase();
66+
String mactopic = subjectBTtoMQTT + mac_adress;
67+
if (advertisedDevice.haveName()) BLEdata.set("name", (char *)advertisedDevice.getName().c_str());
68+
if (advertisedDevice.haveManufacturerData()) BLEdata.set("manufacturerdata", (char *)advertisedDevice.getManufacturerData().c_str());
69+
if (advertisedDevice.haveRSSI()) BLEdata.set("rssi", (int) advertisedDevice.getRSSI());
70+
if (advertisedDevice.haveTXPower()) BLEdata.set("txpower", (int8_t) advertisedDevice.getTXPower());
71+
#ifdef subjectHomePresence
72+
if (advertisedDevice.haveRSSI()) haRoomPresence(BLEdata);// this device has an rssi in consequence we can use it for home assistant room presence component
73+
#endif
74+
if (advertisedDevice.haveServiceData()){
75+
char mac[mac_adress.length()+1];
76+
mac_adress.toCharArray(mac,mac_adress.length()+1);
77+
trc(F("Get services data :"));
78+
int serviceDataCount = advertisedDevice.getServiceDataCount();
79+
trc(serviceDataCount);
80+
for (int j = 0; j < serviceDataCount;j++){
81+
std::string serviceData = advertisedDevice.getServiceData(j);
82+
int serviceDataLength = serviceData.length();
83+
String returnedString = "";
84+
for (int i=0; i<serviceDataLength; i++)
85+
{
86+
int a = serviceData[i];
87+
if (a < 16) {
88+
returnedString = returnedString + "0";
89+
}
90+
returnedString = returnedString + String(a,HEX);
91+
}
92+
char service_data[returnedString.length()+1];
93+
returnedString.toCharArray(service_data,returnedString.length()+1);
94+
service_data[returnedString.length()] = '\0';
95+
#ifdef pubBLEServiceData
96+
BLEdata.set("servicedata", service_data);
97+
BLEdata.set("servicedatauuid", (char *)advertisedDevice.getServiceDataUUID(j).toString().c_str());
98+
#endif
99+
if((!oneWhite() || isWhite(mac)) && !isBlack(mac)){ //if not black listed mac we go AND if we have no white mac or this mac is white we go out
100+
pub((char *)mactopic.c_str(),BLEdata);
101+
if (strstr(BLEdata["servicedatauuid"].as<char*>(),"fe95") != NULL){
102+
trc("Processing BLE device data");
103+
int pos = -1;
104+
pos = strpos(service_data,"209800");
105+
if (pos != -1){
106+
trc(F("mi flora data reading"));
107+
#ifdef ZmqttDiscovery
108+
if(!isDiscovered(mac)) MiFloraDiscovery(mac);
109+
#endif
110+
process_data(pos - 24,service_data,mac);
111+
}
112+
pos = -1;
113+
pos = strpos(service_data,"20aa01");
114+
if (pos != -1){
115+
trc(F("mi jia data reading"));
116+
#ifdef ZmqttDiscovery
117+
if(!isDiscovered(mac)) MiJiaDiscovery(mac);
118+
#endif
119+
process_data(pos - 26,service_data,mac);
120+
}
121+
pos = -1;
122+
pos = strpos(service_data,"205b04");
123+
if (pos != -1){
124+
trc(F("LYWSD02 data reading"));
125+
//example 70205b04b96ab883c8593f09041002e000
126+
#ifdef ZmqttDiscovery
127+
if(!isDiscovered(mac)) LYWSD02Discovery(mac);
128+
#endif
129+
process_data(pos - 24,service_data,mac);
121130
}
122131
}
132+
}
123133
}
124-
}
125-
};
126-
134+
}
135+
}
136+
};
137+
127138
void setupBT(){
128139
BLEinterval = TimeBtw_Read;
129140
trc(F("BLEinterval btw scans"));
@@ -302,6 +313,15 @@ vector<BLEdevice> devices;
302313
#endif
303314
boolean result = process_data(pos - 40,(char *)Service_data.c_str(),d[0].extract);
304315
}
316+
pos = -1;
317+
pos = strpos(d[5].extract,"205b04");
318+
if (pos != -1){
319+
trc("LYWSD02 data reading");
320+
#ifdef ZmqttDiscovery
321+
if(!isDiscovered(d[0].extract)) LYWSD02Discovery(d[0].extract);
322+
#endif
323+
boolean result = process_data(pos - 38,(char *)Service_data.c_str(),d[0].extract);
324+
}
305325
return true;
306326
}
307327
}
@@ -380,6 +400,34 @@ void MiJiaDiscovery(char * mac){
380400
device.isDisc = true;
381401
devices.push_back(device);
382402
}
403+
404+
void LYWSD02Discovery(char * mac){
405+
#define LYWSD02parametersCount 3
406+
trc(F("LYWSD02Discovery"));
407+
char * LYWSD02sensor[LYWSD02parametersCount][8] = {
408+
{"sensor", "LYWSD02-batt", mac, "battery","{{ value_json.batt | is_defined }}","", "", "V"} ,
409+
{"sensor", "LYWSD02-tem", mac,"temperature","{{ value_json.tem | is_defined }}","", "", "°C"} ,
410+
{"sensor", "LYWSD02-hum", mac,"humidity","{{ value_json.hum | is_defined }}","", "", "%"}
411+
//component type,name,availability topic,device class,value template,payload on, payload off, unit of measurement
412+
};
413+
414+
for (int i=0;i<LYWSD02parametersCount;i++){
415+
trc(F("CreateDiscoverySensor"));
416+
trc(LYWSD02sensor[i][1]);
417+
String discovery_topic = String(subjectBTtoMQTT) + String(mac);
418+
String unique_id = String(mac) + "-" + LYWSD02sensor[i][1];
419+
createDiscovery(LYWSD02sensor[i][0],
420+
(char *)discovery_topic.c_str(), LYWSD02sensor[i][1], (char *)unique_id.c_str(),
421+
will_Topic, LYWSD02sensor[i][3], LYWSD02sensor[i][4],
422+
LYWSD02sensor[i][5], LYWSD02sensor[i][6], LYWSD02sensor[i][7],
423+
0,"","",true,"");
424+
}
425+
BLEdevice device;
426+
strcpy( device.macAdr, mac );
427+
device.isDisc = true;
428+
devices.push_back(device);
429+
}
430+
383431
#endif
384432

385433
boolean process_data(int offset, char * rest_data, char * mac_adress){

lib/ESP32_BLE_Arduino/src/BLEAdvertisedDevice.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ BLEAdvertisedDevice::BLEAdvertisedDevice() {
2929
m_manufacturerData = "";
3030
m_name = "";
3131
m_rssi = -9999;
32-
m_serviceData = "";
3332
m_txPower = 0;
3433
m_pScan = nullptr;
3534

@@ -106,30 +105,42 @@ BLEScan* BLEAdvertisedDevice::getScan() {
106105
} // getScan
107106

108107

108+
/**
109+
* @brief Get the number of service data.
110+
* @return Number of service data discovered.
111+
*/
112+
int BLEAdvertisedDevice::getServiceDataCount() {
113+
if (m_haveServiceData)
114+
return m_serviceDataVector.size();
115+
else
116+
return 0;
117+
118+
} //getServiceDataCount
119+
109120
/**
110121
* @brief Get the service data.
111122
* @return The ServiceData of the advertised device.
112123
*/
113-
std::string BLEAdvertisedDevice::getServiceData() {
114-
return m_serviceData;
124+
std::string BLEAdvertisedDevice::getServiceData(int i) {
125+
return m_serviceDataVector[i];
115126
} //getServiceData
116127

117128

118129
/**
119130
* @brief Get the service data UUID.
120131
* @return The service data UUID.
121132
*/
122-
BLEUUID BLEAdvertisedDevice::getServiceDataUUID() {
123-
return m_serviceDataUUID;
133+
BLEUUID BLEAdvertisedDevice::getServiceDataUUID(int i) {
134+
return m_serviceDataUUIDs[i];
124135
} // getServiceDataUUID
125136

126137

127138
/**
128139
* @brief Get the Service UUID.
129140
* @return The Service UUID of the advertised device.
130141
*/
131-
BLEUUID BLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventually, is no longer useful
132-
return m_serviceUUIDs[0];
142+
BLEUUID BLEAdvertisedDevice::getServiceUUID(int i) {
143+
return m_serviceUUIDs[i];
133144
} // getServiceUUID
134145

135146
/**
@@ -458,7 +469,7 @@ void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
458469
*/
459470
void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
460471
m_haveServiceData = true; // Set the flag that indicates we have service data.
461-
m_serviceData = serviceData; // Save the service data that we received.
472+
m_serviceDataVector.push_back(serviceData); // Save the service data that we received.
462473
} //setServiceData
463474

464475

@@ -468,7 +479,8 @@ void BLEAdvertisedDevice::setServiceData(std::string serviceData) {
468479
*/
469480
void BLEAdvertisedDevice::setServiceDataUUID(BLEUUID uuid) {
470481
m_haveServiceData = true; // Set the flag that indicates we have service data.
471-
m_serviceDataUUID = uuid;
482+
m_serviceDataUUIDs.push_back(uuid);
483+
ESP_LOGD(LOG_TAG, "- addServiceDataUUID(): serviceDataUUID: %s", uuid.toString().c_str());
472484
} // setServiceDataUUID
473485

474486

@@ -499,7 +511,9 @@ std::string BLEAdvertisedDevice::toString() {
499511
free(pHex);
500512
}
501513
if (haveServiceUUID()) {
502-
ss << ", serviceUUID: " << getServiceUUID().toString();
514+
for (int i; i < m_serviceUUIDs.size(); i++) {
515+
ss << ", serviceUUID: " << getServiceUUID(i).toString();
516+
}
503517
}
504518
if (haveTXPower()) {
505519
ss << ", txPower: " << (int)getTXPower();

lib/ESP32_BLE_Arduino/src/BLEAdvertisedDevice.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ class BLEAdvertisedDevice {
3535
std::string getName();
3636
int getRSSI();
3737
BLEScan* getScan();
38-
std::string getServiceData();
39-
BLEUUID getServiceDataUUID();
40-
BLEUUID getServiceUUID();
38+
std::string getServiceData(int i);
39+
BLEUUID getServiceDataUUID(int i);
40+
BLEUUID getServiceUUID(int i);
41+
int getServiceDataCount();
4142
int8_t getTXPower();
4243
uint8_t* getPayload();
4344

@@ -91,9 +92,9 @@ class BLEAdvertisedDevice {
9192
BLEScan* m_pScan;
9293
int m_rssi;
9394
std::vector<BLEUUID> m_serviceUUIDs;
94-
int8_t m_txPower;
95-
std::string m_serviceData;
96-
BLEUUID m_serviceDataUUID;
95+
std::vector<BLEUUID> m_serviceDataUUIDs;
96+
std::vector<std::string> m_serviceDataVector;
97+
int8_t m_txPower;
9798
uint8_t* m_payload;
9899
};
99100

0 commit comments

Comments
 (0)