From 257b39da8136448ee10ed4e39e7b3d0c086f73a5 Mon Sep 17 00:00:00 2001 From: Amy Nagle Date: Wed, 9 Feb 2022 17:16:41 -0500 Subject: [PATCH] Add support for XMWSDJ04MMC (#1162) --- docs/prerequisites/devices.md | 3 +- main/ZgatewayBLEConnect.h | 9 ++++++ main/ZgatewayBLEConnect.ino | 54 +++++++++++++++++++++++++++++++++++ main/ZgatewayBT.ino | 27 +++++++++++++++++- main/config_BT.h | 1 + 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/docs/prerequisites/devices.md b/docs/prerequisites/devices.md index 0108e3b..067db91 100644 --- a/docs/prerequisites/devices.md +++ b/docs/prerequisites/devices.md @@ -54,10 +54,11 @@ Added to that it retrieves the measures from the devices below. By default the d | XIAOMI Mi Jia 2 (1)(c)|LYWSD03MMC|temperature/humidity/battery/volt| | XIAOMI Mi Jia 2 custom firmware (2)|LYWSD03MMC ATC|temperature/humidity/battery/volt| | XIAOMI Mi Jia 2 custom firmware (3)|LYWSD03MMC PVVX|temperature/humidity/battery/volt| -| XIAOMI MHO-C401 (1)(c)|MHO-C401|temperature/humidity/battery/volt| | XIAOMI Mi Lamp |MUE4094RT|presence| | XIAOMI Mi Scale v1 (1)|XMTZC04HM|weight| | XIAOMI Mi Scale v2 (1)|XMTZC05HM|weight| +| XIAOMI Mi Temp/Humidity v1 (1)(c)|MHO-C401|temperature/humidity/battery/volt| +| XIAOMI Mi Temp/Humidity v2 (1)(c)|XMWSDJ04MMC|temperature/humidity/battery/volt| | XIAOMI Mi band (1)||steps| Exhaustive list [here](https://compatible.openmqttgateway.com/index.php/devices/ble-devices/) diff --git a/main/ZgatewayBLEConnect.h b/main/ZgatewayBLEConnect.h index 34ca6db..feb9443 100644 --- a/main/ZgatewayBLEConnect.h +++ b/main/ZgatewayBLEConnect.h @@ -57,5 +57,14 @@ public: void publishData() override; }; +class XMWSDJ04MMC_connect : public zBLEConnect { + std::vector m_data; + void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify); + +public: + XMWSDJ04MMC_connect(NimBLEAddress& addr) : zBLEConnect(addr) {} + void publishData() override; +}; + #endif //ESP32 #endif //zBLEConnect_h diff --git a/main/ZgatewayBLEConnect.ino b/main/ZgatewayBLEConnect.ino index 9b27b45..cf42ca7 100644 --- a/main/ZgatewayBLEConnect.ino +++ b/main/ZgatewayBLEConnect.ino @@ -288,5 +288,59 @@ void HHCCJCY01HHCC_connect::publishData() { } } +/*-----------------------XMWSDJ04MMC HANDLING-----------------------*/ +void XMWSDJ04MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify) { + if (m_taskHandle == nullptr) { + return; // unexpected notification + } + if (!ProcessLock) { + Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str()); + + if (length == 6) { + Log.trace(F("Device identified creating BLE buffer" CR)); + JsonObject BLEdata = getBTJsonObject(); + String mac_address = m_pClient->getPeerAddress().toString().c_str(); + mac_address.toUpperCase(); + BLEdata["model"] = "XMWSDJ04MMC"; + BLEdata["id"] = (char*)mac_address.c_str(); + Log.trace(F("Device identified in CB: %s" CR), (char*)mac_address.c_str()); + BLEdata["tempc"] = (float)((pData[0] | (pData[1] << 8)) * 0.1); + BLEdata["tempf"] = (float)(convertTemp_CtoF((pData[0] | (pData[1] << 8)) * 0.1)); + BLEdata["hum"] = (float)((pData[2] | (pData[3] << 8)) * 0.1); + BLEdata["volt"] = (float)((pData[4] | (pData[5] << 8)) / 1000.0); + BLEdata["batt"] = (float)((((pData[4] | (pData[5] << 8)) / 1000.0) - 2.1) * 100); + + pubBT(BLEdata); + } else { + Log.notice(F("Invalid notification data" CR)); + return; + } + } else { + Log.trace(F("Callback process canceled by processLock" CR)); + } + + xTaskNotifyGive(m_taskHandle); +} + +void XMWSDJ04MMC_connect::publishData() { + NimBLEUUID serviceUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"); + NimBLEUUID charUUID("ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6"); + NimBLERemoteCharacteristic* pChar = getCharacteristic(serviceUUID, charUUID); + + if (pChar && pChar->canNotify()) { + Log.trace(F("Registering notification" CR)); + if (pChar->subscribe(true, std::bind(&XMWSDJ04MMC_connect::notifyCB, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4))) { + m_taskHandle = xTaskGetCurrentTaskHandle(); + if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(BLE_CNCT_TIMEOUT)) == pdFALSE) { + m_taskHandle = nullptr; + } + } else { + Log.notice(F("Failed registering notification" CR)); + } + } +} + # endif //ZgatewayBT #endif //ESP32 diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index dc1d67a..9c1f6c3 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -351,10 +351,25 @@ void MHO_C401Discovery(const char* mac, const char* sensorModel) { createDiscoveryFromList(mac, MHO_C401sensor, MHO_C401parametersCount, "MHO_C401", "Xiaomi", sensorModel); } +void XMWSDJ04MMCDiscovery(const char* mac, const char* sensorModel) { +# define XMWSDJ04MMCparametersCount 4 + Log.trace(F("XMWSDJ04MMCDiscovery" CR)); + const char* XMWSDJ04MMCsensor[XMWSDJ04MMCparametersCount][9] = { + {"sensor", "XMWSDJ04MMC-batt", mac, "battery", jsonBatt, "", "", "%", stateClassMeasurement}, + {"sensor", "XMWSDJ04MMC-volt", mac, "", jsonVolt, "", "", "V", stateClassMeasurement}, + {"sensor", "XMWSDJ04MMC-temp", mac, "temperature", jsonTempc, "", "", "°C", stateClassMeasurement}, + {"sensor", "XMWSDJ04MMC-hum", mac, "humidity", jsonHum, "", "", "%", stateClassMeasurement} + //component type,name,availability topic,device class,value template,payload on, payload off, unit of measurement + }; + + createDiscoveryFromList(mac, XMWSDJ04MMCsensor, XMWSDJ04MMCparametersCount, "XMWSDJ04MMC", "Xiaomi", sensorModel); +} + # else void LYWSD03MMCDiscovery(const char* mac, const char* sensorModel) {} void MHO_C401Discovery(const char* mac, const char* sensorModel) {} void DT24Discovery(const char* mac, const char* sensorModel_id) {} +void XMWSDJ04MMCDiscovery(const char* mac, const char* sensorModel_id) {} # endif # ifdef ESP32 @@ -494,6 +509,10 @@ void BLEconnect() { HHCCJCY01HHCC_connect BLEclient(addr); BLEclient.processActions(BLEactions); BLEclient.publishData(); + } else if (p->sensorModel_id == BLEconectable::id::XMWSDJ04MMC) { + XMWSDJ04MMC_connect BLEclient(addr); + BLEclient.processActions(BLEactions); + BLEclient.publishData(); } else { GENERIC_connect BLEclient(addr); if (BLEclient.processActions(BLEactions)) { @@ -511,7 +530,8 @@ void BLEconnect() { if (p->sensorModel_id != BLEconectable::id::DT24_BLE && p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC && p->sensorModel_id != BLEconectable::id::LYWSD03MMC && - p->sensorModel_id != BLEconectable::id::MHO_C401) { + p->sensorModel_id != BLEconectable::id::MHO_C401 && + p->sensorModel_id != BLEconectable::id::XMWSDJ04MMC) { // if irregulary connected to and connection failed clear the connect flag. p->connect = false; } @@ -869,6 +889,9 @@ void launchBTDiscovery() { if (p->sensorModel_id == BLEconectable::id::MHO_C401) { MHO_C401Discovery(macWOdots.c_str(), "MHO-C401"); } + if (p->sensorModel_id == BLEconectable::id::XMWSDJ04MMC) { + XMWSDJ04MMCDiscovery(macWOdots.c_str(), "XMWSDJ04MMC"); + } } p->isDisc = true; // we don't need the semaphore and all the search magic via createOrUpdateDevice } else { @@ -932,6 +955,8 @@ void process_bledata(JsonObject& BLEdata) { model_id = BLEconectable::id::DT24_BLE; else if (name.compare("MHO-C401") == 0) model_id = BLEconectable::id::MHO_C401; + else if (name.compare("XMWSDJ04MMC") == 0) + model_id = BLEconectable::id::XMWSDJ04MMC; if (model_id > 0) { Log.trace(F("Connectable device found: %s" CR), name.c_str()); diff --git a/main/config_BT.h b/main/config_BT.h index 55cb0b6..7fd1e08 100644 --- a/main/config_BT.h +++ b/main/config_BT.h @@ -180,6 +180,7 @@ public: LYWSD03MMC, MHO_C401, DT24_BLE, + XMWSDJ04MMC, MAX, }; };