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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#ifdef ESP32
|
||||
@@ -290,7 +317,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
BLEdata.set("servicedatauuid", (char *)advertisedDevice.getServiceDataUUID(j).toString().c_str());
|
||||
#endif
|
||||
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");
|
||||
int pos = -1;
|
||||
pos = strpos(service_data,"209800");
|
||||
@@ -300,7 +327,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(mac)) MiFloraDiscovery(mac);
|
||||
#endif
|
||||
process_data(pos - 24,service_data,mac);
|
||||
process_sensors(pos - 24,service_data,mac);
|
||||
}
|
||||
pos = -1;
|
||||
pos = strpos(service_data,"20aa01");
|
||||
@@ -309,7 +336,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(mac)) MiJiaDiscovery(mac);
|
||||
#endif
|
||||
process_data(pos - 26,service_data,mac);
|
||||
process_sensors(pos - 26,service_data,mac);
|
||||
}
|
||||
pos = -1;
|
||||
pos = strpos(service_data,"205b04");
|
||||
@@ -319,7 +346,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(mac)) LYWSD02Discovery(mac);
|
||||
#endif
|
||||
process_data(pos - 24,service_data,mac);
|
||||
process_sensors(pos - 24,service_data,mac);
|
||||
}
|
||||
pos = -1;
|
||||
pos = strpos(service_data,"304703");
|
||||
@@ -329,9 +356,25 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(mac)) CLEARGRASSTRHDiscovery(mac);
|
||||
#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{
|
||||
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
|
||||
haRoomPresence(BLEdata);// this device has an rssi in consequence we can use it for home assistant room presence component
|
||||
#endif
|
||||
String Service_data(d[5].extract);
|
||||
Service_data = Service_data.substring(14);
|
||||
String service_data(d[5].extract);
|
||||
service_data = service_data.substring(14);
|
||||
#ifdef pubBLEServiceData
|
||||
BLEdata.set("servicedata", (char *)Service_data.c_str());
|
||||
BLEdata.set("servicedata", (char *)service_data.c_str());
|
||||
#endif
|
||||
pub((char *)topic.c_str(),BLEdata);
|
||||
int pos = -1;
|
||||
@@ -494,7 +537,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(d[0].extract)) MiFloraDiscovery(d[0].extract);
|
||||
#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 = strpos(d[5].extract,"20aa01");
|
||||
@@ -504,7 +547,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(d[0].extract)) MiJiaDiscovery(d[0].extract);
|
||||
#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,"205b04");
|
||||
@@ -514,7 +557,7 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(d[0].extract)) LYWSD02Discovery(d[0].extract);
|
||||
#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 = strpos(d[5].extract,"304703");
|
||||
@@ -523,7 +566,17 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
#ifdef ZmqttDiscovery
|
||||
if(!isDiscovered(d[0].extract)) CLEARGRASSTRHDiscovery(d[0].extract);
|
||||
#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;
|
||||
}
|
||||
@@ -540,7 +593,21 @@ void CLEARGRASSTRHDiscovery(char * mac){
|
||||
}
|
||||
#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"));
|
||||
StaticJsonBuffer<JSON_MSG_BUFFER> jsonBuffer;
|
||||
@@ -553,7 +620,7 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
||||
case '2' :
|
||||
case '3' :
|
||||
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);
|
||||
break;
|
||||
@@ -561,24 +628,10 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
||||
trc("can't read data_length");
|
||||
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
|
||||
revert_hex_data(rev_data, data, data_length);
|
||||
double value = strtol(data, NULL, 16);
|
||||
trc(value);
|
||||
char val[12];
|
||||
String mactopic(mac_adress);
|
||||
mactopic = subjectBTtoMQTT + mactopic;
|
||||
double value = 9999;
|
||||
value = value_from_service_data(rest_data, 52 + offset, data_length);
|
||||
|
||||
// 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 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
|
||||
@@ -587,11 +640,9 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
||||
BLEdata.set("fer", (double)value);
|
||||
break;
|
||||
case '4' :
|
||||
if (value > 65000) value = value - 65535;
|
||||
BLEdata.set("tem", (double)value/10);
|
||||
break;
|
||||
case '6' :
|
||||
if (value > 65000) value = value - 65535;
|
||||
BLEdata.set("hum", (double)value/10);
|
||||
break;
|
||||
case '7' :
|
||||
@@ -601,33 +652,72 @@ bool process_data(int offset, char * rest_data, char * mac_adress){
|
||||
BLEdata.set("moi", (double)value);
|
||||
break;
|
||||
|
||||
case 'a' : // batteryLevel
|
||||
case 'a' :
|
||||
BLEdata.set("batt", (double)value);
|
||||
break;
|
||||
|
||||
case 'd' : // temp+hum
|
||||
char tempAr[8];
|
||||
case 'd' :
|
||||
// humidity
|
||||
memcpy(tempAr, data, 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;
|
||||
value = value_from_service_data(rest_data, 52 + offset, 4);
|
||||
BLEdata.set("tem", (double)value/10);
|
||||
// temperature
|
||||
value = value_from_service_data(rest_data, 56 + offset, 4);
|
||||
BLEdata.set("hum", (double)value/10);
|
||||
break;
|
||||
default:
|
||||
trc("can't read values");
|
||||
return false;
|
||||
}
|
||||
String mactopic(mac_adress);
|
||||
mactopic = subjectBTtoMQTT + mactopic;
|
||||
pub((char *)mactopic.c_str(),BLEdata);
|
||||
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
|
||||
void haRoomPresence(JsonObject& HomePresence){
|
||||
int BLErssi = HomePresence["rssi"];
|
||||
|
||||
Reference in new issue
Block a user