Skip to content

Commit 186c4b0

Browse files
authored
Create BLE connect class and add derivatives (1technophile#979)
1 parent db88cab commit 186c4b0

File tree

4 files changed

+250
-157
lines changed

4 files changed

+250
-157
lines changed

main/ZgatewayBLEConnect.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef zBLEConnect_h
2+
#define zBLEConnect_h
3+
4+
#ifdef ESP32
5+
# include "ArduinoJson.h"
6+
# include "NimBLEDevice.h"
7+
8+
extern void pubBT(JsonObject& data);
9+
10+
class zBLEConnect {
11+
public:
12+
NimBLEClient* m_pClient;
13+
TaskHandle_t m_taskHandle = nullptr;
14+
zBLEConnect(NimBLEAddress& addr) { m_pClient = NimBLEDevice::createClient(addr); }
15+
virtual ~zBLEConnect() { NimBLEDevice::deleteClient(m_pClient); }
16+
virtual void publishData() {}
17+
virtual NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID& service, const NimBLEUUID& characteristic);
18+
};
19+
20+
class LYWSD03MMC_connect : public zBLEConnect {
21+
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
22+
23+
public:
24+
LYWSD03MMC_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
25+
void publishData() override;
26+
};
27+
28+
class DT24_connect : public zBLEConnect {
29+
std::vector<uint8_t> m_data;
30+
void notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify);
31+
32+
public:
33+
DT24_connect(NimBLEAddress& addr) : zBLEConnect(addr) {}
34+
void publishData() override;
35+
};
36+
37+
#endif //ESP32
38+
#endif //zBLEConnect_h

main/ZgatewayBLEConnect.ino

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#ifdef ESP32
2+
# include "User_config.h"
3+
# ifdef ZgatewayBT
4+
# include "ArduinoJson.h"
5+
# include "ArduinoLog.h"
6+
# include "ZgatewayBLEConnect.h"
7+
# include "config_BT.h"
8+
9+
# define convertTemp_CtoF(c) ((c * 1.8) + 32)
10+
11+
extern bool ProcessLock;
12+
extern std::vector<BLEdevice*> devices;
13+
14+
NimBLERemoteCharacteristic* zBLEConnect::getCharacteristic(const NimBLEUUID& service,
15+
const NimBLEUUID& characteristic) {
16+
BLERemoteCharacteristic* pRemoteCharacteristic = nullptr;
17+
if (!m_pClient) {
18+
Log.error(F("No BLE client" CR));
19+
} else if (!m_pClient->isConnected() && !m_pClient->connect()) {
20+
Log.error(F("Connect to: %s failed" CR), m_pClient->getPeerAddress().toString().c_str());
21+
} else {
22+
BLERemoteService* pRemoteService = m_pClient->getService(service);
23+
if (!pRemoteService) {
24+
Log.notice(F("Failed to find service UUID: %s" CR), service.toString().c_str());
25+
} else {
26+
Log.trace(F("Found service: %s" CR), service.toString().c_str());
27+
Log.trace(F("Client isConnected, freeHeap: %d" CR), ESP.getFreeHeap());
28+
pRemoteCharacteristic = pRemoteService->getCharacteristic(characteristic);
29+
if (!pRemoteCharacteristic) {
30+
Log.notice(F("Failed to find characteristic UUID: %s" CR), characteristic.toString().c_str());
31+
}
32+
}
33+
}
34+
35+
return pRemoteCharacteristic;
36+
}
37+
38+
/*-----------------------LYWSD03MMC && MHO_C401 HANDLING-----------------------*/
39+
void LYWSD03MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify) {
40+
if (m_taskHandle == nullptr) {
41+
return; // unexpected notification
42+
}
43+
if (!ProcessLock) {
44+
Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str());
45+
46+
if (length == 5) {
47+
Log.trace(F("Device identified creating BLE buffer" CR));
48+
JsonObject& BLEdata = getBTJsonObject();
49+
String mac_address = m_pClient->getPeerAddress().toString().c_str();
50+
mac_address.toUpperCase();
51+
for (std::vector<BLEdevice*>::iterator it = devices.begin(); it != devices.end(); ++it) {
52+
BLEdevice* p = *it;
53+
if ((strcmp(p->macAdr, (char*)mac_address.c_str()) == 0)) {
54+
if (p->sensorModel == LYWSD03MMC)
55+
BLEdata.set("model", "LYWSD03MMC");
56+
else if (p->sensorModel == MHO_C401)
57+
BLEdata.set("model", "MHO_C401");
58+
}
59+
}
60+
BLEdata.set("id", (char*)mac_address.c_str());
61+
Log.trace(F("Device identified in CB: %s" CR), (char*)mac_address.c_str());
62+
BLEdata.set("tempc", (float)((pData[0] | (pData[1] << 8)) * 0.01));
63+
BLEdata.set("tempf", (float)(convertTemp_CtoF((pData[0] | (pData[1] << 8)) * 0.01)));
64+
BLEdata.set("hum", (float)(pData[2]));
65+
BLEdata.set("volt", (float)(((pData[4] * 256) + pData[3]) / 1000.0));
66+
BLEdata.set("batt", (float)(((((pData[4] * 256) + pData[3]) / 1000.0) - 2.1) * 100));
67+
68+
pubBT(BLEdata);
69+
} else {
70+
Log.notice(F("Invalid notification data" CR));
71+
return;
72+
}
73+
} else {
74+
Log.trace(F("Callback process canceled by processLock" CR));
75+
}
76+
77+
xTaskNotifyGive(m_taskHandle);
78+
}
79+
80+
void LYWSD03MMC_connect::publishData() {
81+
NimBLEUUID serviceUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6");
82+
NimBLEUUID charUUID("ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6");
83+
NimBLERemoteCharacteristic* pChar = getCharacteristic(serviceUUID, charUUID);
84+
85+
if (pChar && pChar->canNotify()) {
86+
Log.trace(F("Registering notification" CR));
87+
if (pChar->subscribe(true, std::bind(&LYWSD03MMC_connect::notifyCB, this,
88+
std::placeholders::_1, std::placeholders::_2,
89+
std::placeholders::_3, std::placeholders::_4))) {
90+
m_taskHandle = xTaskGetCurrentTaskHandle();
91+
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(BLE_CNCT_TIMEOUT)) == pdFALSE) {
92+
m_taskHandle = nullptr;
93+
}
94+
} else {
95+
Log.notice(F("Failed registering notification" CR));
96+
}
97+
}
98+
}
99+
100+
/*-----------------------DT24 HANDLING-----------------------*/
101+
void DT24_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, size_t length, bool isNotify) {
102+
if (m_taskHandle == nullptr) {
103+
return; // unexpected notification
104+
}
105+
106+
if (!ProcessLock) {
107+
Log.trace(F("Callback from %s characteristic" CR), pChar->getUUID().toString().c_str());
108+
if (length == 20) {
109+
m_data.assign(pData, pData + length);
110+
return;
111+
} else if (m_data.size() == 20 && length == 16) {
112+
m_data.insert(m_data.end(), pData, pData + length);
113+
114+
// DT24-BLE data format
115+
// https://github.com/NiceLabs/atorch-console/blob/master/docs/protocol-design.md#dc-meter-report
116+
// Data comes as two packets ( 20 and 16 ), and am only processing first
117+
Log.trace(F("Device identified creating BLE buffer" CR));
118+
JsonObject& BLEdata = getBTJsonObject();
119+
String mac_address = m_pClient->getPeerAddress().toString().c_str();
120+
mac_address.toUpperCase();
121+
BLEdata.set("model", "DT24");
122+
BLEdata.set("id", (char*)mac_address.c_str());
123+
Log.trace(F("Device identified in CB: %s" CR), (char*)mac_address.c_str());
124+
BLEdata.set("volt", (float)(((m_data[4] * 256 * 256) + (m_data[5] * 256) + m_data[6]) / 10.0));
125+
BLEdata.set("current", (float)(((m_data[7] * 256 * 256) + (m_data[8] * 256) + m_data[9]) / 1000.0));
126+
BLEdata.set("power", (float)(((m_data[10] * 256 * 256) + (m_data[11] * 256) + m_data[12]) / 10.0));
127+
BLEdata.set("energy", (float)(((m_data[13] * 256 * 256 * 256) + (m_data[14] * 256 * 256) + (m_data[15] * 256) + m_data[16]) / 100.0));
128+
BLEdata.set("price", (float)(((m_data[17] * 256 * 256) + (m_data[18] * 256) + m_data[19]) / 100.0));
129+
130+
pubBT(BLEdata);
131+
} else {
132+
Log.notice(F("Invalid notification data" CR));
133+
return;
134+
}
135+
} else {
136+
Log.trace(F("Callback process canceled by processLock" CR));
137+
}
138+
139+
xTaskNotifyGive(m_taskHandle);
140+
}
141+
142+
void DT24_connect::publishData() {
143+
NimBLEUUID serviceUUID("ffe0");
144+
NimBLEUUID charUUID("ffe1");
145+
NimBLERemoteCharacteristic* pChar = getCharacteristic(serviceUUID, charUUID);
146+
147+
if (pChar && pChar->canNotify()) {
148+
Log.trace(F("Registering notification" CR));
149+
if (pChar->subscribe(true, std::bind(&DT24_connect::notifyCB, this,
150+
std::placeholders::_1, std::placeholders::_2,
151+
std::placeholders::_3, std::placeholders::_4))) {
152+
m_taskHandle = xTaskGetCurrentTaskHandle();
153+
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(BLE_CNCT_TIMEOUT)) == pdFALSE) {
154+
m_taskHandle = nullptr;
155+
}
156+
} else {
157+
Log.notice(F("Failed registering notification" CR));
158+
}
159+
}
160+
}
161+
# endif //ZgatewayBT
162+
#endif //ESP32

0 commit comments

Comments
 (0)