From be668d75282dbfe84f310c412564568186339159 Mon Sep 17 00:00:00 2001 From: Florian <1technophile@users.noreply.github.com> Date: Thu, 2 Mar 2023 10:25:08 -0600 Subject: [PATCH 1/2] [BT] Add BM2 voltage Voltage retrieval through a BLE connection, frequency of the BLE connection is defined by `intervalcnct` --- main/ZgatewayBLEConnect.h | 9 +++++ main/ZgatewayBLEConnect.ino | 76 ++++++++++++++++++++++++++++++++++++- main/ZgatewayBT.ino | 27 ++++++++++++- main/config_BT.h | 1 + 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/main/ZgatewayBLEConnect.h b/main/ZgatewayBLEConnect.h index 556d6f335c..540560c147 100644 --- a/main/ZgatewayBLEConnect.h +++ b/main/ZgatewayBLEConnect.h @@ -41,6 +41,15 @@ class DT24_connect : public zBLEConnect { void publishData() override; }; +class BM2_connect : public zBLEConnect { + //std::vector m_data; + void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify); + +public: + BM2_connect(NimBLEAddress& addr) : zBLEConnect(addr) {} + void publishData() override; +}; + class GENERIC_connect : public zBLEConnect { std::vector m_data; diff --git a/main/ZgatewayBLEConnect.ino b/main/ZgatewayBLEConnect.ino index 11f1eb3ef7..0615683cc3 100644 --- a/main/ZgatewayBLEConnect.ino +++ b/main/ZgatewayBLEConnect.ino @@ -4,7 +4,6 @@ # include "ArduinoJson.h" # include "ArduinoLog.h" # include "ZgatewayBLEConnect.h" - # define convertTemp_CtoF(c) ((c * 1.8) + 32) extern bool ProcessLock; @@ -255,6 +254,81 @@ void DT24_connect::publishData() { } } +/*-----------------------BM2 HANDLING-----------------------*/ +void BM2_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 == 16) { + 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"] = "BM2 Battery Monitor"; + BLEdata["id"] = (char*)mac_address.c_str(); + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + unsigned char output[16]; + unsigned char iv[16] = {}; + unsigned char key[16] = { + 108, + 101, + 97, + 103, + 101, + 110, + 100, + 255, + 254, + 49, + 56, + 56, + 50, + 52, + 54, + 54, + }; + mbedtls_aes_setkey_dec(&aes, key, 128); + mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, 16, iv, (uint8_t*)&pData[0], output); + mbedtls_aes_free(&aes); + float volt = ((output[2] | (output[1] << 8)) >> 4) / 100.0f; + BLEdata["volt"] = volt; + Log.trace(F("volt: %F" CR), volt); + 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 BM2_connect::publishData() { + NimBLEUUID serviceUUID("fff0"); + NimBLEUUID charUUID("fff4"); + NimBLERemoteCharacteristic* pChar = getCharacteristic(serviceUUID, charUUID); + + if (pChar && pChar->canNotify()) { + Log.trace(F("Registering notification" CR)); + if (pChar->subscribe(true, std::bind(&BM2_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)); + } + } +} + /*-----------------------HHCCJCY01HHCC HANDLING-----------------------*/ void HHCCJCY01HHCC_connect::publishData() { NimBLEUUID serviceUUID("00001204-0000-1000-8000-00805f9b34fb"); diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 2d73fe0340..5898b0a39f 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -467,6 +467,18 @@ void DT24Discovery(const char* mac, const char* sensorModel_id) { createDiscoveryFromList(mac, DT24sensor, DT24parametersCount, "DT24", "ATorch", sensorModel_id); } +void BM2Discovery(const char* mac, const char* sensorModel_id) { +# define BM2parametersCount 2 + Log.trace(F("BM2Discovery" CR)); + const char* BM2sensor[BM2parametersCount][9] = { + {"sensor", "volt", mac, "voltage", jsonVolt, "", "", "V", stateClassMeasurement}, + {"sensor", "batt", mac, "battery", jsonBatt, "", "", "%", stateClassMeasurement} + //component type,name,availability topic,device class,value template,payload on, payload off, unit of measurement + }; + + createDiscoveryFromList(mac, BM2sensor, BM2parametersCount, "BM2", "Generic", sensorModel_id); +} + void LYWSD03MMCDiscovery(const char* mac, const char* sensorModel) { # define LYWSD03MMCparametersCount 4 Log.trace(F("LYWSD03MMCDiscovery" CR)); @@ -529,6 +541,7 @@ void LYWSD03MMCDiscovery(const char* mac, const char* sensorModel) {} void MHO_C401Discovery(const char* mac, const char* sensorModel) {} void HHCCJCY01HHCCDiscovery(const char* mac, const char* sensorModel) {} void DT24Discovery(const char* mac, const char* sensorModel_id) {} +void BM2Discovery(const char* mac, const char* sensorModel_id) {} void XMWSDJ04MMCDiscovery(const char* mac, const char* sensorModel_id) {} # endif @@ -668,6 +681,10 @@ void BLEconnect() { DT24_connect BLEclient(addr); BLEclient.processActions(BLEactions); BLEclient.publishData(); + } else if (p->sensorModel_id == BLEconectable::id::BM2) { + BM2_connect BLEclient(addr); + BLEclient.processActions(BLEactions); + BLEclient.publishData(); } else if (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC) { HHCCJCY01HHCC_connect BLEclient(addr); BLEclient.processActions(BLEactions); @@ -696,6 +713,7 @@ 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::BM2 && p->sensorModel_id != BLEconectable::id::MHO_C401 && p->sensorModel_id != BLEconectable::id::XMWSDJ04MMC) { // if irregulary connected to and connection failed clear the connect flag. @@ -906,7 +924,7 @@ void launchBTDiscovery(bool overrideDiscovery) { if (!BTConfig.extDecoderEnable && // Do not decode if an external decoder is configured p->sensorModel_id > TheengsDecoder::BLE_ID_NUM::UNKNOWN_MODEL && p->sensorModel_id < TheengsDecoder::BLE_ID_NUM::BLE_ID_MAX && - p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC) { // Exception on HHCCJCY01HHCC as this one is discoverable and connectable for battery retrieving + p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC && p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::BM2) { // Exception on HHCCJCY01HHCC and BM2 as these ones are discoverable and connectable Log.trace(F("Looking for Model_id: %d" CR), p->sensorModel_id); std::string properties = decoder.getTheengProperties(p->sensorModel_id); Log.trace(F("properties: %s" CR), properties.c_str()); @@ -952,11 +970,14 @@ void launchBTDiscovery(bool overrideDiscovery) { } else { if (p->sensorModel_id > BLEconectable::id::MIN && p->sensorModel_id < BLEconectable::id::MAX || - p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC) { + p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC || p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::BM2) { // Discovery of sensors from which we retrieve data only by connect if (p->sensorModel_id == BLEconectable::id::DT24_BLE) { DT24Discovery(macWOdots.c_str(), "DT24-BLE"); } + if (p->sensorModel_id == BLEconectable::id::BM2) { + BM2Discovery(macWOdots.c_str(), "BM2"); + } if (p->sensorModel_id == BLEconectable::id::LYWSD03MMC) { LYWSD03MMCDiscovery(macWOdots.c_str(), "LYWSD03MMC"); } @@ -1046,6 +1067,8 @@ void process_bledata(JsonObject& BLEdata) { model_id = BLEconectable::id::LYWSD03MMC; else if (name.compare("DT24-BLE") == 0) model_id = BLEconectable::id::DT24_BLE; + else if (name.compare("Battery Monitor") == 0) + model_id = BLEconectable::id::BM2; else if (name.compare("MHO-C401") == 0) model_id = BLEconectable::id::MHO_C401; else if (name.compare("XMWSDJ04MMC") == 0) diff --git a/main/config_BT.h b/main/config_BT.h index 5103a6640f..4fdeadb438 100644 --- a/main/config_BT.h +++ b/main/config_BT.h @@ -209,6 +209,7 @@ class BLEconectable { LYWSD03MMC, MHO_C401, DT24_BLE, + BM2, XMWSDJ04MMC, MAX, }; From 2cdeb96ba955f5314b08def1c7128bada7bf72bc Mon Sep 17 00:00:00 2001 From: Florian <1technophile@users.noreply.github.com> Date: Thu, 2 Mar 2023 11:01:35 -0600 Subject: [PATCH 2/2] Add doc --- docs/prerequisites/devices.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/prerequisites/devices.md b/docs/prerequisites/devices.md index bc6b6e3436..ed32e85c1c 100644 --- a/docs/prerequisites/devices.md +++ b/docs/prerequisites/devices.md @@ -28,7 +28,7 @@ Added to that it retrieves the measures from the devices below. By default the d | BlueMaestro|TempoDisc 1 in 1|temperature/battery| | BlueMaestro|TempoDisc 3 in 1|temperature/humidity/dew point/battery| | BlueMaestro|TempoDisc 4 in 1|temperature/humidity/pressure/battery| -| BM2 Battery Monitor|BM2|battery| +| BM2 Battery Monitor|BM2|battery/volt(c)| | ClearGrass|CGG1|temperature/humidity/battery/voltage (depending on which CGG1 firmware is installed)| | ClearGrass alarm clock|CGD1|temperature/humidity/battery| | ClearGrass alarm clock|CGC1|temperature/humidity/battery| @@ -84,7 +84,7 @@ Added to that it retrieves the measures from the devices below. By default the d | ThermoPro|TP393|temperature/humidity| | TPMS|TPMS|temperature/pressure/battery/alarm/count| | Vegtrug||temperature/moisture/luminance/fertility| -| XIAOMI Mi Flora|HHCCJCY01HHCC|temperature/moisture/luminance/fertility/battery(1)(c)| +| XIAOMI Mi Flora|HHCCJCY01HHCC|temperature/moisture/luminance/fertility/battery(c)| | XIAOMI Ropot|HHCCPOT002|temperature/moisture/fertility| | XIAOMI Mi Jia|LYWSDCGO|temperature/humidity/battery| | XIAOMI Mi Jia|LYWSD02|temperature/humidity/battery|