Add Ble Xiaomi scale compatibility (#459)
* Add of Xiaomi Miscale v1 & v2 Discussed here: https://community.openmqttgateway.com/t/ble-scale-support/608/16
This commit is contained in:
1 parent
cba3ed7e75
commit
1f96635978
1 file changed
+136
-46
+136
-46
@@ -222,6 +222,33 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
devices.push_back(device);
|
devices.push_back(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MiScaleDiscovery(char * mac){
|
||||||
|
#define MiScaleparametersCount 1
|
||||||
|
trc(F("MiScaleDiscovery"));
|
||||||
|
char * MiScalesensor[MiScaleparametersCount][8] = {
|
||||||
|
{"sensor", "MiScale-weight", mac, "weight","{{ value_json.weight | is_defined }}","", "", "kg"} ,
|
||||||
|
//component type,name,availability topic,device class,value template,payload on, payload off, unit of measurement
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0;i<MiScaleparametersCount;i++){
|
||||||
|
trc(F("CreateDiscoverySensor"));
|
||||||
|
trc(MiScalesensor[i][1]);
|
||||||
|
String discovery_topic = String(subjectBTtoMQTT) + String(mac);
|
||||||
|
String unique_id = String(mac) + "-" + MiScalesensor[i][1];
|
||||||
|
createDiscovery(MiScalesensor[i][0],
|
||||||
|
(char *)discovery_topic.c_str(), MiScalesensor[i][1], (char *)unique_id.c_str(),
|
||||||
|
will_Topic, MiScalesensor[i][3], MiScalesensor[i][4],
|
||||||
|
MiScalesensor[i][5], MiScalesensor[i][6], MiScalesensor[i][7],
|
||||||
|
0,"","",true,"");
|
||||||
|
}
|
||||||
|
BLEdevice device;
|
||||||
|
strcpy( device.macAdr, mac );
|
||||||
|
device.isDisc = true;
|
||||||
|
device.isWhtL = false;
|
||||||
|
device.isBlkL = false;
|
||||||
|
devices.push_back(device);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
@@ -290,7 +317,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
BLEdata.set("servicedatauuid", (char *)advertisedDevice.getServiceDataUUID(j).toString().c_str());
|
BLEdata.set("servicedatauuid", (char *)advertisedDevice.getServiceDataUUID(j).toString().c_str());
|
||||||
#endif
|
#endif
|
||||||
pub((char *)mactopic.c_str(),BLEdata);
|
pub((char *)mactopic.c_str(),BLEdata);
|
||||||
if (strstr(BLEdata["servicedatauuid"].as<char*>(),"fe95") != NULL){
|
if (strstr(BLEdata["servicedatauuid"].as<char*>(),"fe95") != NULL){ //Mi FLora, Mi jia, Cleargrass, LYWDS02
|
||||||
trc("Processing BLE device data");
|
trc("Processing BLE device data");
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
pos = strpos(service_data,"209800");
|
pos = strpos(service_data,"209800");
|
||||||
@@ -300,7 +327,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(mac)) MiFloraDiscovery(mac);
|
if(!isDiscovered(mac)) MiFloraDiscovery(mac);
|
||||||
#endif
|
#endif
|
||||||
process_data(pos - 24,service_data,mac);
|
process_sensors(pos - 24,service_data,mac);
|
||||||
}
|
}
|
||||||
pos = -1;
|
pos = -1;
|
||||||
pos = strpos(service_data,"20aa01");
|
pos = strpos(service_data,"20aa01");
|
||||||
@@ -309,7 +336,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(mac)) MiJiaDiscovery(mac);
|
if(!isDiscovered(mac)) MiJiaDiscovery(mac);
|
||||||
#endif
|
#endif
|
||||||
process_data(pos - 26,service_data,mac);
|
process_sensors(pos - 26,service_data,mac);
|
||||||
}
|
}
|
||||||
pos = -1;
|
pos = -1;
|
||||||
pos = strpos(service_data,"205b04");
|
pos = strpos(service_data,"205b04");
|
||||||
@@ -319,7 +346,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(mac)) LYWSD02Discovery(mac);
|
if(!isDiscovered(mac)) LYWSD02Discovery(mac);
|
||||||
#endif
|
#endif
|
||||||
process_data(pos - 24,service_data,mac);
|
process_sensors(pos - 24,service_data,mac);
|
||||||
}
|
}
|
||||||
pos = -1;
|
pos = -1;
|
||||||
pos = strpos(service_data,"304703");
|
pos = strpos(service_data,"304703");
|
||||||
@@ -329,9 +356,25 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(mac)) CLEARGRASSTRHDiscovery(mac);
|
if(!isDiscovered(mac)) CLEARGRASSTRHDiscovery(mac);
|
||||||
#endif
|
#endif
|
||||||
process_data(pos - 26,service_data,mac);
|
process_sensors(pos - 26,service_data,mac);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (strstr(BLEdata["servicedatauuid"].as<char*>(),"181d") != NULL){ // Mi Scale V1
|
||||||
|
trc(F("Mi Scale V1 data reading"));
|
||||||
|
//example "servicedata":"a2ac2be307060207122b" /"a28039e3070602070e28"
|
||||||
|
#ifdef ZmqttDiscovery
|
||||||
|
if(!isDiscovered(mac)) MiScaleDiscovery(mac);
|
||||||
|
#endif
|
||||||
|
process_scale_v1(service_data,mac);
|
||||||
|
}
|
||||||
|
if (strstr(BLEdata["servicedatauuid"].as<char*>(),"181b") != NULL){ // Mi Scale V2
|
||||||
|
trc(F("Mi Scale V2 data reading"));
|
||||||
|
//example "servicedata":02c4e1070b1e13050c00002607 / 02a6e20705150a251df401443e /02a6e20705180c0d04d701943e
|
||||||
|
#ifdef ZmqttDiscovery
|
||||||
|
if(!isDiscovered(mac)) MiScaleDiscovery(mac);
|
||||||
|
#endif
|
||||||
|
process_scale_v2(service_data,mac);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
pub((char *)mactopic.c_str(),BLEdata); // publish device even if there is no service data
|
pub((char *)mactopic.c_str(),BLEdata); // publish device even if there is no service data
|
||||||
@@ -481,10 +524,10 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef subjectHomePresence
|
#ifdef subjectHomePresence
|
||||||
haRoomPresence(BLEdata);// this device has an rssi in consequence we can use it for home assistant room presence component
|
haRoomPresence(BLEdata);// this device has an rssi in consequence we can use it for home assistant room presence component
|
||||||
#endif
|
#endif
|
||||||
String Service_data(d[5].extract);
|
String service_data(d[5].extract);
|
||||||
Service_data = Service_data.substring(14);
|
service_data = service_data.substring(14);
|
||||||
#ifdef pubBLEServiceData
|
#ifdef pubBLEServiceData
|
||||||
BLEdata.set("servicedata", (char *)Service_data.c_str());
|
BLEdata.set("servicedata", (char *)service_data.c_str());
|
||||||
#endif
|
#endif
|
||||||
pub((char *)topic.c_str(),BLEdata);
|
pub((char *)topic.c_str(),BLEdata);
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
@@ -494,7 +537,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(d[0].extract)) MiFloraDiscovery(d[0].extract);
|
if(!isDiscovered(d[0].extract)) MiFloraDiscovery(d[0].extract);
|
||||||
#endif
|
#endif
|
||||||
bool result = process_data(pos - 38,(char *)Service_data.c_str(),d[0].extract);
|
bool result = process_sensors(pos - 38,(char *)service_data.c_str(),d[0].extract);
|
||||||
}
|
}
|
||||||
pos = -1;
|
pos = -1;
|
||||||
pos = strpos(d[5].extract,"20aa01");
|
pos = strpos(d[5].extract,"20aa01");
|
||||||
@@ -504,7 +547,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(d[0].extract)) MiJiaDiscovery(d[0].extract);
|
if(!isDiscovered(d[0].extract)) MiJiaDiscovery(d[0].extract);
|
||||||
#endif
|
#endif
|
||||||
bool result = process_data(pos - 40,(char *)Service_data.c_str(),d[0].extract);
|
bool result = process_sensors(pos - 40,(char *)service_data.c_str(),d[0].extract);
|
||||||
}
|
}
|
||||||
pos = -1;
|
pos = -1;
|
||||||
pos = strpos(d[5].extract,"205b04");
|
pos = strpos(d[5].extract,"205b04");
|
||||||
@@ -514,7 +557,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(d[0].extract)) LYWSD02Discovery(d[0].extract);
|
if(!isDiscovered(d[0].extract)) LYWSD02Discovery(d[0].extract);
|
||||||
#endif
|
#endif
|
||||||
bool result = process_data(pos - 38,(char *)Service_data.c_str(),d[0].extract);
|
bool result = process_sensors(pos - 38,(char *)service_data.c_str(),d[0].extract);
|
||||||
}
|
}
|
||||||
pos = -1;
|
pos = -1;
|
||||||
pos = strpos(d[5].extract,"304703");
|
pos = strpos(d[5].extract,"304703");
|
||||||
@@ -523,7 +566,17 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
#ifdef ZmqttDiscovery
|
#ifdef ZmqttDiscovery
|
||||||
if(!isDiscovered(d[0].extract)) CLEARGRASSTRHDiscovery(d[0].extract);
|
if(!isDiscovered(d[0].extract)) CLEARGRASSTRHDiscovery(d[0].extract);
|
||||||
#endif
|
#endif
|
||||||
bool result = process_data(pos - 40,(char *)Service_data.c_str(),d[0].extract);
|
bool result = process_sensors(pos - 40,(char *)service_data.c_str(),d[0].extract);
|
||||||
|
}
|
||||||
|
pos = -1;
|
||||||
|
pos = strpos(d[5].extract,"e30706");
|
||||||
|
if (pos != -1){
|
||||||
|
trc("Mi Scale data reading");
|
||||||
|
//example "servicedata":"a2ac2be307060207122b" /"a28039e3070602070e28"
|
||||||
|
#ifdef ZmqttDiscovery
|
||||||
|
if(!isDiscovered(d[0].extract)) MiScaleDiscovery(d[0].extract);
|
||||||
|
#endif
|
||||||
|
bool result = process_scale_v1((char *)service_data.c_str(),d[0].extract);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -540,7 +593,21 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool process_data(int offset, char * rest_data, char * mac_adress){
|
double value_from_service_data(char * service_data, int offset, int data_length){
|
||||||
|
char rev_data[data_length+1];
|
||||||
|
char data[data_length+1];
|
||||||
|
memcpy( rev_data, &service_data[offset], data_length );
|
||||||
|
rev_data[data_length] = '\0';
|
||||||
|
|
||||||
|
// reverse data order
|
||||||
|
revert_hex_data(rev_data, data, data_length);
|
||||||
|
double value = strtol(data, NULL, 16);
|
||||||
|
if (value > 65000 && data_length <= 4) value = value - 65535;
|
||||||
|
trc(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_sensors(int offset, char * rest_data, char * mac_adress){
|
||||||
|
|
||||||
trc(F("Creating BLE buffer"));
|
trc(F("Creating BLE buffer"));
|
||||||
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
|
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
|
||||||
@@ -553,7 +620,7 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
|||||||
case '2' :
|
case '2' :
|
||||||
case '3' :
|
case '3' :
|
||||||
case '4' :
|
case '4' :
|
||||||
data_length = ((rest_data[51 + offset] - '0') * 2)+1;
|
data_length = ((rest_data[51 + offset] - '0') * 2);
|
||||||
trc("data_length");
|
trc("data_length");
|
||||||
trc(data_length);
|
trc(data_length);
|
||||||
break;
|
break;
|
||||||
@@ -561,24 +628,10 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
|||||||
trc("can't read data_length");
|
trc("can't read data_length");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char rev_data[data_length];
|
|
||||||
char data[data_length];
|
|
||||||
memcpy( rev_data, &rest_data[52 + offset], data_length );
|
|
||||||
rev_data[data_length] = '\0';
|
|
||||||
|
|
||||||
// reverse data order
|
double value = 9999;
|
||||||
revert_hex_data(rev_data, data, data_length);
|
value = value_from_service_data(rest_data, 52 + offset, data_length);
|
||||||
double value = strtol(data, NULL, 16);
|
|
||||||
trc(value);
|
|
||||||
char val[12];
|
|
||||||
String mactopic(mac_adress);
|
|
||||||
mactopic = subjectBTtoMQTT + mactopic;
|
|
||||||
|
|
||||||
// second value
|
|
||||||
char val2[12];
|
|
||||||
trc("rest_data");
|
|
||||||
trc(rest_data);
|
|
||||||
// Mi flora provides tem(perature), (earth) moi(sture), fer(tility) and lux (illuminance)
|
// Mi flora provides tem(perature), (earth) moi(sture), fer(tility) and lux (illuminance)
|
||||||
// Mi Jia provides tem(perature), batt(erry) and hum(idity)
|
// Mi Jia provides tem(perature), batt(erry) and hum(idity)
|
||||||
// following the value of digit 47 we determine the type of data we get from the sensor
|
// following the value of digit 47 we determine the type of data we get from the sensor
|
||||||
@@ -587,11 +640,9 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
|||||||
BLEdata.set("fer", (double)value);
|
BLEdata.set("fer", (double)value);
|
||||||
break;
|
break;
|
||||||
case '4' :
|
case '4' :
|
||||||
if (value > 65000) value = value - 65535;
|
|
||||||
BLEdata.set("tem", (double)value/10);
|
BLEdata.set("tem", (double)value/10);
|
||||||
break;
|
break;
|
||||||
case '6' :
|
case '6' :
|
||||||
if (value > 65000) value = value - 65535;
|
|
||||||
BLEdata.set("hum", (double)value/10);
|
BLEdata.set("hum", (double)value/10);
|
||||||
break;
|
break;
|
||||||
case '7' :
|
case '7' :
|
||||||
@@ -601,33 +652,72 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
|||||||
BLEdata.set("moi", (double)value);
|
BLEdata.set("moi", (double)value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a' : // batteryLevel
|
case 'a' :
|
||||||
BLEdata.set("batt", (double)value);
|
BLEdata.set("batt", (double)value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd' : // temp+hum
|
case 'd' :
|
||||||
char tempAr[8];
|
|
||||||
// humidity
|
// humidity
|
||||||
memcpy(tempAr, data, 4);
|
value = value_from_service_data(rest_data, 52 + offset, 4);
|
||||||
tempAr[4] = '\0';
|
|
||||||
value = strtol(tempAr, NULL, 16);
|
|
||||||
if (value > 65000) value = value - 65535;
|
|
||||||
BLEdata.set("hum", (double)value/10);
|
|
||||||
// temperature
|
|
||||||
memcpy(tempAr, &data[4], 4);
|
|
||||||
tempAr[4] = '\0';
|
|
||||||
value = strtol(tempAr, NULL, 16);
|
|
||||||
if (value > 65000) value = value - 65535;
|
|
||||||
BLEdata.set("tem", (double)value/10);
|
BLEdata.set("tem", (double)value/10);
|
||||||
|
// temperature
|
||||||
|
value = value_from_service_data(rest_data, 56 + offset, 4);
|
||||||
|
BLEdata.set("hum", (double)value/10);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
trc("can't read values");
|
trc("can't read values");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
String mactopic(mac_adress);
|
||||||
|
mactopic = subjectBTtoMQTT + mactopic;
|
||||||
pub((char *)mactopic.c_str(),BLEdata);
|
pub((char *)mactopic.c_str(),BLEdata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool process_scale_v1(char * rest_data, char * mac_adress){
|
||||||
|
//example "servicedata":"a2ac2be307060207122b" /"a28039e3070602070e28"
|
||||||
|
trc("rest_data");
|
||||||
|
trc(rest_data);
|
||||||
|
|
||||||
|
trc(F("Creating BLE buffer"));
|
||||||
|
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
|
||||||
|
JsonObject& BLEdata = jsonBuffer.createObject();
|
||||||
|
|
||||||
|
double weight = value_from_service_data(rest_data, 2, 4)/200;
|
||||||
|
|
||||||
|
//Set Json value
|
||||||
|
BLEdata.set("weight", (double)weight);
|
||||||
|
|
||||||
|
// Publish weight
|
||||||
|
String mactopic(mac_adress);
|
||||||
|
mactopic = subjectBTtoMQTT + mactopic;
|
||||||
|
pub((char *)mactopic.c_str(),BLEdata);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_scale_v2(char * rest_data, char * mac_adress){
|
||||||
|
//example "servicedata":"a2ac2be307060207122b" /"a28039e3070602070e28"
|
||||||
|
trc("rest_data");
|
||||||
|
trc(rest_data);
|
||||||
|
|
||||||
|
trc(F("Creating BLE buffer"));
|
||||||
|
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
|
||||||
|
JsonObject& BLEdata = jsonBuffer.createObject();
|
||||||
|
|
||||||
|
double weight = value_from_service_data(rest_data, 22, 4)/200;
|
||||||
|
double impedance = value_from_service_data(rest_data, 18, 4);
|
||||||
|
|
||||||
|
//Set Json values
|
||||||
|
BLEdata.set("weight", (double)weight);
|
||||||
|
BLEdata.set("impedance", (double)impedance);
|
||||||
|
|
||||||
|
// Publish weight
|
||||||
|
String mactopic(mac_adress);
|
||||||
|
mactopic = subjectBTtoMQTT + mactopic;
|
||||||
|
pub((char *)mactopic.c_str(),BLEdata);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef subjectHomePresence
|
#ifdef subjectHomePresence
|
||||||
void haRoomPresence(JsonObject& HomePresence){
|
void haRoomPresence(JsonObject& HomePresence){
|
||||||
int BLErssi = HomePresence["rssi"];
|
int BLErssi = HomePresence["rssi"];
|
||||||
|
|||||||
Reference in new issue
Block a user