Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/prerequisites/devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ OpenMQTTGateway is able to scan all the BLE devices that advertise their data so
| XIAOMI Mi band (1)||steps|
| iNode Energy Meter (1)||power/energy/battery|
| Thermobeacon|WS02|temperature/humidity/volt|
| ATorch Battery Capacity Monitor|DT24|volt/amp/watt|

Exhaustive list [here](https://compatible.openmqttgateway.com/index.php/devices/ble-devices/)

Expand Down
89 changes: 89 additions & 0 deletions main/ZgatewayBT.ino
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,21 @@ void WS02Discovery(const char* mac, const char* sensorModel) {
createDiscoveryFromList(mac, WS02sensor, WS02parametersCount, "WS02", "SensorBlue", sensorModel);
}

void DT24Discovery(const char* mac, const char* sensorModel) {
# define DT24parametersCount 5
Log.trace(F("DT24Discovery" CR));
const char* DT24sensor[DT24parametersCount][8] = {
{"sensor", "DT24-volt", mac, "power", jsonVolt, "", "", "V"},
{"sensor", "DT24-amp", mac, "power", jsonCurrent, "", "", "A"},
{"sensor", "DT24-watt", mac, "power", jsonPower, "", "", "W"},
{"sensor", "DT24-watt-hour", mac, "power", jsonEnergy, "", "", "kWh"},
{"sensor", "DT24-price", mac, "", jsonMsg, "", "", ""}
//component type,name,availability topic,device class,value template,payload on, payload off, unit of measurement
};

createDiscoveryFromList(mac, DT24sensor, DT24parametersCount, "DT24", "ATorch", sensorModel);
}

# else
void MiFloraDiscovery(const char* mac, const char* sensorModel) {}
void VegTrugDiscovery(const char* mac, const char* sensorModel) {}
Expand All @@ -572,6 +587,7 @@ void LYWSD03MMCDiscovery(const char* mac, const char* sensorModel) {}
void MHO_C401Discovery(const char* mac, const char* sensorModel) {}
void INodeEMDiscovery(const char* mac, const char* sensorModel) {}
void WS02Discovery(const char* mac, const char* sensorModel) {}
void DT24Discovery(const char* mac, const char* sensorModel) {}
# endif

# ifdef ESP32
Expand Down Expand Up @@ -700,6 +716,8 @@ void notifyCB(
if (!ProcessLock) {
Log.trace(F("Callback from %s characteristic" CR), pBLERemoteCharacteristic->getUUID().toString().c_str());

// This logic needs refactoring and should be changed to a device/model approach based on the sensor macAdr lookup. Growing this beyond 2 devices will get too cumbersome

if (length == 5) {
Log.trace(F("Device identified creating BLE buffer" CR));
JsonObject& BLEdata = getBTJsonObject();
Expand All @@ -722,6 +740,34 @@ void notifyCB(
BLEdata.set("volt", (float)(((pData[4] * 256) + pData[3]) / 1000.0));
BLEdata.set("batt", (float)(((((pData[4] * 256) + pData[3]) / 1000.0) - 2.1) * 100));

pubBT(BLEdata);
} else if (length == 20) {
// DT24-BLE data format
// https://github.com/NiceLabs/atorch-console/blob/master/docs/protocol-design.md#dc-meter-report
// Data comes as two packets ( 20 and 16 ), and am only processing first
Log.trace(F("Device identified creating BLE buffer" CR));
JsonObject& BLEdata = getBTJsonObject();
String mac_adress = pBLERemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress().toString().c_str();
mac_adress.toUpperCase();
for (vector<BLEdevice*>::iterator it = devices.begin(); it != devices.end(); ++it) {
BLEdevice* p = *it;
if ((strcmp(p->macAdr, (char*)mac_adress.c_str()) == 0)) {
if (p->sensorModel == LYWSD03MMC)
BLEdata.set("model", "LYWSD03MMC");
else if (p->sensorModel == MHO_C401)
BLEdata.set("model", "MHO_C401");
else if (p->sensorModel == DT24)
BLEdata.set("model", "DT24");
}
}
BLEdata.set("id", (char*)mac_adress.c_str());
Log.trace(F("Device identified in CB: %s" CR), (char*)mac_adress.c_str());
BLEdata.set("volt", (float)(((pData[4] * 256 * 256) + (pData[5] * 256) + pData[6]) / 10.0));
BLEdata.set("amp", (float)(((pData[7] * 256 * 256) + (pData[8] * 256) + pData[9]) / 1000.0));
BLEdata.set("watt", (float)(((pData[10] * 256 * 256) + (pData[11] * 256) + pData[12]) / 10.0));
BLEdata.set("watt hour", (float)(((pData[13] * 256 * 256 * 256) + (pData[14] * 256 * 256) + (pData[15] * 256) + pData[16]) / 100.0));
BLEdata.set("price", (float)(((pData[17] * 256 * 256) + (pData[18] * 256) + pData[19]) / 100.0));

pubBT(BLEdata);
} else {
Log.notice(F("Device not identified" CR));
Expand Down Expand Up @@ -772,6 +818,40 @@ void BLEconnect() {
}
}
NimBLEDevice::deleteClient(pClient);
} else if (p->sensorModel == DT24) {
Log.trace(F("Model to connect found: %s" CR), p->macAdr);
NimBLEClient* pClient;
pClient = BLEDevice::createClient();
BLEUUID serviceUUID("ffe0");
BLEUUID charUUID("ffe1");
BLEAddress sensorAddress(p->macAdr);
if (!pClient->connect(sensorAddress)) {
Log.notice(F("Failed to find client: %s" CR), p->macAdr);
} else {
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (!pRemoteService) {
Log.notice(F("Failed to find service UUID: %s" CR), serviceUUID.toString().c_str());
} else {
Log.trace(F("Found service: %s" CR), serviceUUID.toString().c_str());
// Obtain a reference to the characteristic in the service of the remote BLE server.
if (pClient->isConnected()) {
Log.trace(F("Client isConnected, freeHeap: %d" CR), ESP.getFreeHeap());
BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (!pRemoteCharacteristic) {
Log.notice(F("Failed to find characteristic UUID: %s" CR), charUUID.toString().c_str());
} else {
if (pRemoteCharacteristic->canNotify()) {
Log.trace(F("Registering notification" CR));
pRemoteCharacteristic->subscribe(true, notifyCB);
delay(BLE_CNCT_TIMEOUT);
} else {
Log.notice(F("Failed registering notification" CR));
}
}
}
}
}
NimBLEDevice::deleteClient(pClient);
}
}
Log.notice(F("BLE Connect end" CR));
Expand Down Expand Up @@ -1075,6 +1155,7 @@ void launchBTDiscovery() {
if (p->sensorModel == LYWSD03MMC || p->sensorModel == LYWSD03MMC_ATC || p->sensorModel == LYWSD03MMC_PVVX) LYWSD03MMCDiscovery(macWOdots.c_str(), "LYWSD03MMC");
if (p->sensorModel == MHO_C401) MHO_C401Discovery(macWOdots.c_str(), "MHO_C401");
if (p->sensorModel == INODE_EM) INodeEMDiscovery(macWOdots.c_str(), "INODE_EM");
if (p->sensorModel == DT24) DT24Discovery(macWOdots.c_str(), "DT24-BLE");
p->isDisc = true; // we don't need the semaphore and all the search magic via createOrUpdateDevice
} else {
if (!isDiscovered(p)) {
Expand Down Expand Up @@ -1310,6 +1391,14 @@ JsonObject& process_bledata(JsonObject& BLEdata) {
createOrUpdateDevice(mac, device_flags_init, IBT4XS);
return process_inkbird_4xs(BLEdata);
}
Log.trace(F("Is it a DT24?" CR));
if (strcmp(name, "DT24-BLE") == 0) {
Log.trace(F("DT24 data reading data reading" CR));
BLEdata.set("model", "DT24");
if (device->sensorModel == -1)
createOrUpdateDevice(mac, device_flags_init, DT24);
return BLEdata;
}
}
Log.trace(F("Is it a iNode Energy Meter?" CR));
if (strlen(manufacturerdata) == 26 && ((long)value_from_hex_data(manufacturerdata, 0, 4, true) & 0xFFF9) == 0x8290) {
Expand Down
1 change: 1 addition & 0 deletions main/config_BT.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ enum ble_sensor_model {
WS02,
IBSTH2,
IBT4XS,
DT24,
};

/*-------------------PIN DEFINITIONS----------------------*/
Expand Down