Files
OpenMQTTGateway/main/gatewayBLEConnect.h
Florian fd433c220e [BLE] Add BM6 Battery Monitor connection support (#2274)
* [BLE] Add BM6 Battery Monitor connection support

Implement BLE connection support for BM6 Battery Monitor devices,
following the BM2 pattern with BM6-specific protocol handling.

Key features:
- Encrypted command/response using AES-128 CBC
- Read voltage, temperature, and State of Charge (SoC)
- Home Assistant MQTT Discovery support
- Device tracker integration

Technical implementation:
- Add BM6_connect class with encrypted command handling
- Encryption key (static const): "leagend\xff\xfe0100009"
- Parse hex string positions for voltage (15-17), temp (8-9), SoC (12-13)
- Add discovery with 3 sensors (voltage, temperature, battery %)
- Validate message signature (D15507)
- Add canWrite() check before writing to characteristic
- Empty stub for non-ESP32 builds

Code quality improvements:
- Extract AES key as static constant to avoid duplication
- Use shared jsonVoltBM template for both BM2 and BM6
- Clean up commented-out reasoning in parsing logic

Based on reverse engineering from:
https://github.com/JeffWDH/bm6-battery-monitor

Files modified:
- main/gatewayBLEConnect.h: Add BM6_connect class
- main/gatewayBLEConnect.cpp: Implement BM6 connection logic
- main/gatewayBT.cpp: Add detection, connection, and discovery handlers
- main/config_mqttDiscovery.h: Rename jsonVoltBM2 to jsonVoltBM

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Add BM6 to exceptions

---------

Co-authored-by: Florian <1technophile@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-24 17:16:03 -06:00

113 lines
3.4 KiB
C++

#ifndef zBLEConnect_h
#define zBLEConnect_h
#ifdef ESP32
# include "NimBLEDevice.h"
# include "TheengsCommon.h"
# include "config_BT.h"
class zBLEConnect {
public:
NimBLEClient* m_pClient;
TaskHandle_t m_taskHandle = nullptr;
zBLEConnect(NimBLEAddress& addr) {
m_pClient = NimBLEDevice::createClient(addr);
m_pClient->setConnectTimeout(5000);
}
virtual ~zBLEConnect() { NimBLEDevice::deleteClient(m_pClient); }
virtual bool writeData(BLEAction* action);
virtual bool readData(BLEAction* action);
virtual bool processActions(std::vector<BLEAction>& actions);
virtual void publishData() {}
virtual NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID& service, const NimBLEUUID& characteristic);
};
class LYWSD03MMC_connect : public zBLEConnect {
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
LYWSD03MMC_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
void publishData() override;
};
class DT24_connect : public zBLEConnect {
std::vector<uint8_t> m_data;
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
DT24_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
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 BM6_connect : public zBLEConnect {
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
BM6_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
void publishData() override;
};
class GENERIC_connect : public zBLEConnect {
std::vector<uint8_t> m_data;
public:
GENERIC_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
};
class HHCCJCY01HHCC_connect : public zBLEConnect {
std::vector<uint8_t> m_data;
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
HHCCJCY01HHCC_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
void publishData() override;
};
class XMWSDJ04MMC_connect : public zBLEConnect {
std::vector<uint8_t> m_data;
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
XMWSDJ04MMC_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
void publishData() override;
};
class SBS1_connect : public zBLEConnect {
uint8_t m_notifyVal;
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
SBS1_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
bool processActions(std::vector<BLEAction>& actions) override;
};
class SBBT_connect : public zBLEConnect {
uint8_t m_notifyVal;
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
SBBT_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
bool processActions(std::vector<BLEAction>& actions) override;
};
class SBCU_connect : public zBLEConnect {
uint8_t m_notifyVal;
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
public:
SBCU_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
bool processActions(std::vector<BLEAction>& actions) override;
};
#endif //ESP32
#endif //zBLEConnect_h