[BT] Add BM2 voltage (#1495)
* [BT] Add BM2 voltage Voltage retrieval through a BLE connection, frequency of the BLE connection is defined by `intervalcnct` * Add doc Credits to https://github.com/KrystianD/bm2-battery-monitor
This commit is contained in:
1 parent
1cdf6558a9
commit
f35baa9da0
5 files changed
+112
-5
No files matched your search
@@ -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 1 in 1|temperature/battery|
|
||||||
| BlueMaestro|TempoDisc 3 in 1|temperature/humidity/dew point/battery|
|
| BlueMaestro|TempoDisc 3 in 1|temperature/humidity/dew point/battery|
|
||||||
| BlueMaestro|TempoDisc 4 in 1|temperature/humidity/pressure/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|CGG1|temperature/humidity/battery/voltage (depending on which CGG1 firmware is installed)|
|
||||||
| ClearGrass alarm clock|CGD1|temperature/humidity/battery|
|
| ClearGrass alarm clock|CGD1|temperature/humidity/battery|
|
||||||
| ClearGrass alarm clock|CGC1|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|
|
| ThermoPro|TP393|temperature/humidity|
|
||||||
| TPMS|TPMS|temperature/pressure/battery/alarm/count|
|
| TPMS|TPMS|temperature/pressure/battery/alarm/count|
|
||||||
| Vegtrug||temperature/moisture/luminance/fertility|
|
| 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 Ropot|HHCCPOT002|temperature/moisture/fertility|
|
||||||
| XIAOMI Mi Jia|LYWSDCGO|temperature/humidity/battery|
|
| XIAOMI Mi Jia|LYWSDCGO|temperature/humidity/battery|
|
||||||
| XIAOMI Mi Jia|LYWSD02|temperature/humidity/battery|
|
| XIAOMI Mi Jia|LYWSD02|temperature/humidity/battery|
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ public:
|
|||||||
void publishData() override;
|
void publishData() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BM2_connect : public zBLEConnect {
|
||||||
|
//std::vector<uint8_t> 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 {
|
class GENERIC_connect : public zBLEConnect {
|
||||||
std::vector<uint8_t> m_data;
|
std::vector<uint8_t> m_data;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
# include "ArduinoJson.h"
|
# include "ArduinoJson.h"
|
||||||
# include "ArduinoLog.h"
|
# include "ArduinoLog.h"
|
||||||
# include "ZgatewayBLEConnect.h"
|
# include "ZgatewayBLEConnect.h"
|
||||||
|
|
||||||
# define convertTemp_CtoF(c) ((c * 1.8) + 32)
|
# define convertTemp_CtoF(c) ((c * 1.8) + 32)
|
||||||
|
|
||||||
extern bool ProcessLock;
|
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-----------------------*/
|
/*-----------------------HHCCJCY01HHCC HANDLING-----------------------*/
|
||||||
void HHCCJCY01HHCC_connect::publishData() {
|
void HHCCJCY01HHCC_connect::publishData() {
|
||||||
NimBLEUUID serviceUUID("00001204-0000-1000-8000-00805f9b34fb");
|
NimBLEUUID serviceUUID("00001204-0000-1000-8000-00805f9b34fb");
|
||||||
|
|||||||
+25
-2
@@ -453,6 +453,18 @@ void DT24Discovery(const char* mac, const char* sensorModel_id) {
|
|||||||
createDiscoveryFromList(mac, DT24sensor, DT24parametersCount, "DT24", "ATorch", 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) {
|
void LYWSD03MMCDiscovery(const char* mac, const char* sensorModel) {
|
||||||
# define LYWSD03MMCparametersCount 4
|
# define LYWSD03MMCparametersCount 4
|
||||||
Log.trace(F("LYWSD03MMCDiscovery" CR));
|
Log.trace(F("LYWSD03MMCDiscovery" CR));
|
||||||
@@ -515,6 +527,7 @@ void LYWSD03MMCDiscovery(const char* mac, const char* sensorModel) {}
|
|||||||
void MHO_C401Discovery(const char* mac, const char* sensorModel) {}
|
void MHO_C401Discovery(const char* mac, const char* sensorModel) {}
|
||||||
void HHCCJCY01HHCCDiscovery(const char* mac, const char* sensorModel) {}
|
void HHCCJCY01HHCCDiscovery(const char* mac, const char* sensorModel) {}
|
||||||
void DT24Discovery(const char* mac, const char* sensorModel_id) {}
|
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) {}
|
void XMWSDJ04MMCDiscovery(const char* mac, const char* sensorModel_id) {}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@@ -654,6 +667,10 @@ void BLEconnect() {
|
|||||||
DT24_connect BLEclient(addr);
|
DT24_connect BLEclient(addr);
|
||||||
BLEclient.processActions(BLEactions);
|
BLEclient.processActions(BLEactions);
|
||||||
BLEclient.publishData();
|
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) {
|
} else if (p->sensorModel_id == TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC) {
|
||||||
HHCCJCY01HHCC_connect BLEclient(addr);
|
HHCCJCY01HHCC_connect BLEclient(addr);
|
||||||
BLEclient.processActions(BLEactions);
|
BLEclient.processActions(BLEactions);
|
||||||
@@ -682,6 +699,7 @@ void BLEconnect() {
|
|||||||
if (p->sensorModel_id != BLEconectable::id::DT24_BLE &&
|
if (p->sensorModel_id != BLEconectable::id::DT24_BLE &&
|
||||||
p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC &&
|
p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC &&
|
||||||
p->sensorModel_id != BLEconectable::id::LYWSD03MMC &&
|
p->sensorModel_id != BLEconectable::id::LYWSD03MMC &&
|
||||||
|
p->sensorModel_id != BLEconectable::id::BM2 &&
|
||||||
p->sensorModel_id != BLEconectable::id::MHO_C401 &&
|
p->sensorModel_id != BLEconectable::id::MHO_C401 &&
|
||||||
p->sensorModel_id != BLEconectable::id::XMWSDJ04MMC) {
|
p->sensorModel_id != BLEconectable::id::XMWSDJ04MMC) {
|
||||||
// if irregulary connected to and connection failed clear the connect flag.
|
// if irregulary connected to and connection failed clear the connect flag.
|
||||||
@@ -892,7 +910,7 @@ void launchBTDiscovery(bool overrideDiscovery) {
|
|||||||
if (!BTConfig.extDecoderEnable && // Do not decode if an external decoder is configured
|
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::UNKNOWN_MODEL &&
|
||||||
p->sensorModel_id < TheengsDecoder::BLE_ID_NUM::BLE_ID_MAX &&
|
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);
|
Log.trace(F("Looking for Model_id: %d" CR), p->sensorModel_id);
|
||||||
std::string properties = decoder.getTheengProperties(p->sensorModel_id);
|
std::string properties = decoder.getTheengProperties(p->sensorModel_id);
|
||||||
Log.trace(F("properties: %s" CR), properties.c_str());
|
Log.trace(F("properties: %s" CR), properties.c_str());
|
||||||
@@ -938,11 +956,14 @@ void launchBTDiscovery(bool overrideDiscovery) {
|
|||||||
} else {
|
} else {
|
||||||
if (p->sensorModel_id > BLEconectable::id::MIN &&
|
if (p->sensorModel_id > BLEconectable::id::MIN &&
|
||||||
p->sensorModel_id < BLEconectable::id::MAX ||
|
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
|
// Discovery of sensors from which we retrieve data only by connect
|
||||||
if (p->sensorModel_id == BLEconectable::id::DT24_BLE) {
|
if (p->sensorModel_id == BLEconectable::id::DT24_BLE) {
|
||||||
DT24Discovery(macWOdots.c_str(), "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) {
|
if (p->sensorModel_id == BLEconectable::id::LYWSD03MMC) {
|
||||||
LYWSD03MMCDiscovery(macWOdots.c_str(), "LYWSD03MMC");
|
LYWSD03MMCDiscovery(macWOdots.c_str(), "LYWSD03MMC");
|
||||||
}
|
}
|
||||||
@@ -1032,6 +1053,8 @@ void process_bledata(JsonObject& BLEdata) {
|
|||||||
model_id = BLEconectable::id::LYWSD03MMC;
|
model_id = BLEconectable::id::LYWSD03MMC;
|
||||||
else if (name.compare("DT24-BLE") == 0)
|
else if (name.compare("DT24-BLE") == 0)
|
||||||
model_id = BLEconectable::id::DT24_BLE;
|
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)
|
else if (name.compare("MHO-C401") == 0)
|
||||||
model_id = BLEconectable::id::MHO_C401;
|
model_id = BLEconectable::id::MHO_C401;
|
||||||
else if (name.compare("XMWSDJ04MMC") == 0)
|
else if (name.compare("XMWSDJ04MMC") == 0)
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ public:
|
|||||||
LYWSD03MMC,
|
LYWSD03MMC,
|
||||||
MHO_C401,
|
MHO_C401,
|
||||||
DT24_BLE,
|
DT24_BLE,
|
||||||
|
BM2,
|
||||||
XMWSDJ04MMC,
|
XMWSDJ04MMC,
|
||||||
MAX,
|
MAX,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user