From 2ccde8390f06d79acfd539b9d5c038b97b98e2c1 Mon Sep 17 00:00:00 2001 From: Bad Date: Sun, 21 Aug 2022 10:48:28 +0200 Subject: [PATCH 01/17] Move BTConfig_default to ZgatewayBT.ino as BTConfig_init() --- main/ZgatewayBT.ino | 25 ++++++++++++++++++++++++- main/config_BT.h | 18 ------------------ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 0d429ff46a..1a2bc2b148 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -61,7 +61,7 @@ QueueHandle_t BLEQueue; using namespace std; // Global struct to store live BT configuration data -BTConfig_s BTConfig = BTConfig_default; +BTConfig_s BTConfig; # define device_flags_init 0 << 0 # define device_flags_isDisc 1 << 0 @@ -93,6 +93,27 @@ static BLEdevice NO_DEVICE_FOUND = {{0}, TheengsDecoder::BLE_ID_NUM::UNKNOWN_MODEL}; static bool oneWhite = false; +void BTConfig_init() { + BTConfig.bleConnect = AttemptBLEConnect; + BTConfig.BLEinterval = TimeBtwRead; + BTConfig.BLEscanBeforeConnect = ScanBeforeConnect; + BTConfig.pubOnlySensors = PublishOnlySensors; + BTConfig.presenceEnable = HassPresence; + BTConfig.presenceTopic = subjectHomePresence; + BTConfig.presenceUseBeaconUuid = useBeaconUuidForPresence; + BTConfig.minRssi = abs(MinimumRSSI); + BTConfig.extDecoderEnable = UseExtDecoder; + BTConfig.extDecoderTopic = MQTTDecodeTopic; + BTConfig.filterConnectable = BLE_FILTER_CONNECTABLE; + BTConfig.pubKnownServiceData = pubKnownBLEServiceData; + BTConfig.pubUnknownServiceData = pubUnknownBLEServiceData; + BTConfig.pubKnownManufData = pubBLEManufacturerData; + BTConfig.pubUnknownManufData = pubUnknownBLEManufacturerData; + BTConfig.pubServiceDataUUID = pubBLEServiceUUID; + BTConfig.pubBeaconUuidForTopic = useBeaconUuidForTopic; +} + + void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { if (abs((int)data["rssi"] | 0) < BTConfig.minRssi && data.containsKey("id")) { String topic = data["id"].as(); @@ -672,6 +693,7 @@ void changelowpowermode(int newLowPowerMode) { } void setupBT() { + BTConfig_init(); Log.notice(F("BLE scans interval: %d" CR), BTConfig.BLEinterval); Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); @@ -733,6 +755,7 @@ unsigned long timebt = 0; struct decompose d[6] = {{0, 12, true}, {12, 2, false}, {14, 2, false}, {16, 2, false}, {28, 4, true}, {32, 60, false}}; void setupBT() { + BTConfig_init(); Log.notice(F("BLE interval: %d" CR), BTConfig.BLEinterval); Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); diff --git a/main/config_BT.h b/main/config_BT.h index 52c28aa035..bfc35302a7 100644 --- a/main/config_BT.h +++ b/main/config_BT.h @@ -162,24 +162,6 @@ struct BTConfig_s { bool pubUnknownManufData; // Publish the manufacturer's data (sometimes contains characters that aren't valid with receiving client) bool pubServiceDataUUID; // Publish the service UUID data bool pubBeaconUuidForTopic; // Use iBeacon UUID as topic, instead of sender (random) MAC address -} BTConfig_default = { - .bleConnect = AttemptBLEConnect, - .BLEinterval = TimeBtwRead, - .BLEscanBeforeConnect = ScanBeforeConnect, - .pubOnlySensors = PublishOnlySensors, - .presenceEnable = HassPresence, - .presenceTopic = subjectHomePresence, - .presenceUseBeaconUuid = useBeaconUuidForPresence, - .minRssi = abs(MinimumRSSI), - .extDecoderEnable = UseExtDecoder, - .extDecoderTopic = MQTTDecodeTopic, - .filterConnectable = BLE_FILTER_CONNECTABLE, - .pubKnownServiceData = pubKnownBLEServiceData, - .pubUnknownServiceData = pubUnknownBLEServiceData, - .pubKnownManufData = pubBLEManufacturerData, - .pubUnknownManufData = pubUnknownBLEManufacturerData, - .pubServiceDataUUID = pubBLEServiceUUID, - .pubBeaconUuidForTopic = useBeaconUuidForTopic, }; // Global struct to store live BT configuration data From c63b5500ec28cfdc587f0611007a54963504b5a4 Mon Sep 17 00:00:00 2001 From: Bad Date: Sun, 21 Aug 2022 10:49:44 +0200 Subject: [PATCH 02/17] Remove unused function declaration & typo --- main/ZgatewayBT.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 1a2bc2b148..d340b4d636 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -231,7 +231,6 @@ void pubBT(JsonObject& data) { bool ProcessLock = false; // Process lock when we want to use a critical function like OTA for example -BLEdevice* getDeviceByMac(const char* mac); void createOrUpdateDevice(const char* mac, uint8_t flags, int model, int mac_type = 0); BLEdevice* getDeviceByMac(const char* mac) { @@ -646,8 +645,7 @@ void coreTask(void* pvParameters) { } } -void lowPowerESP32() // low power mode -{ +void lowPowerESP32() { // low power mode Log.trace(F("Going to deep sleep for: %l s" CR), (BTConfig.BLEinterval / 1000)); deepSleep(BTConfig.BLEinterval * 1000); } From 752fb2b1422255ea0cf57302d7a6838ed194eba0 Mon Sep 17 00:00:00 2001 From: Bad Date: Sun, 21 Aug 2022 11:00:33 +0200 Subject: [PATCH 03/17] Move bleconnect outside of ifdef ESP32 --- main/ZgatewayBT.ino | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index d340b4d636..289cc46668 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -1222,6 +1222,13 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding # endif } + // Attempts to connect to elligible devices or not + if (BTdata.containsKey("bleconnect")) { + Log.trace(F("Do we initiate a connection to retrieve data" CR)); + Log.trace(F("Previous value: %T" CR), BTConfig.bleConnect); + BTConfig.bleConnect = (bool)BTdata["bleconnect"]; + Log.notice(F("New value bleConnect: %T" CR), BTConfig.bleConnect); + } // Scan interval set if (BTdata.containsKey("interval")) { Log.trace(F("BLE interval setup" CR)); @@ -1252,20 +1259,6 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding BTConfig.pubOnlySensors = (bool)BTdata["onlysensors"]; Log.notice(F("New value onlysensors: %T" CR), BTConfig.pubOnlySensors); } -# ifdef ESP32 - // Attempts to connect to elligible devices or not - if (BTdata.containsKey("bleconnect")) { - Log.trace(F("Do we initiate a connection to retrieve data" CR)); - Log.trace(F("Previous value: %T" CR), BTConfig.bleConnect); - BTConfig.bleConnect = (bool)BTdata["bleconnect"]; - Log.notice(F("New value bleConnect: %T" CR), BTConfig.bleConnect); - } - if (BTdata.containsKey("lowpowermode")) { - changelowpowermode((int)BTdata["lowpowermode"]); - } - - MQTTtoBTAction(BTdata); -# endif // MinRSSI set if (BTdata.containsKey("minrssi")) { // storing Min RSSI for further use if needed @@ -1282,6 +1275,13 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding BTConfig.presenceEnable = (bool)BTdata["hasspresence"]; Log.notice(F("New hasspresence: %T" CR), BTConfig.presenceEnable); } +# ifdef ESP32 + if (BTdata.containsKey("lowpowermode")) { + changelowpowermode((int)BTdata["lowpowermode"]); + } + + MQTTtoBTAction(BTdata); +# endif } } #endif From 8a110807a5e14d4acffb1db03836caec9f8cd105 Mon Sep 17 00:00:00 2001 From: Bad Date: Sun, 21 Aug 2022 11:06:18 +0200 Subject: [PATCH 04/17] Add new parameters to json payload on MQTTtoBT/config And move them to function BTConfig_fromJson() new parameters: [presenceEnable, presenceTopic, presenceUseBeaconUuid, extDecoderEnable, extDecoderTopic, filterConnectable, pubKnownServiceData, pubUnknownServiceData, pubKnownManufData, pubUnknownManufData, pubServiceDataUUID, pubBeaconUuidForTopic] --- main/ZgatewayBT.ino | 170 +++++++++++++++++++++++++++++++------------- 1 file changed, 121 insertions(+), 49 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 289cc46668..adca764bd7 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -113,6 +113,118 @@ void BTConfig_init() { BTConfig.pubBeaconUuidForTopic = useBeaconUuidForTopic; } +void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { + // Attempts to connect to elligible devices or not + if (BTdata.containsKey("bleconnect")) { + Log.trace(F("Do we initiate a connection to retrieve data" CR)); + Log.trace(F("Previous value: %T" CR), BTConfig.bleConnect); + BTConfig.bleConnect = (bool)BTdata["bleconnect"]; + Log.notice(F("New value bleConnect: %T" CR), BTConfig.bleConnect); + } + // Scan interval set + if (BTdata.containsKey("interval") && BTdata["interval"] != 0) { + Log.trace(F("Previous interval: %d ms" CR), BTConfig.BLEinterval); + BTConfig.BLEinterval = BTdata["interval"]; + Log.notice(F("New interval: %d ms" CR), BTConfig.BLEinterval); + } + + // Number of scan before a connect set + if (BTdata.containsKey("scanbcnct")) { + Log.trace(F("BLE scans number before a connect setup" CR)); + Log.trace(F("Previous number: %d" CR), BTConfig.BLEscanBeforeConnect); + BTConfig.BLEscanBeforeConnect = (unsigned int)BTdata["scanbcnct"]; + Log.notice(F("New scan number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); + } + // publish all BLE devices discovered or only the identified sensors (like temperature sensors) + if (BTdata.containsKey("onlysensors")) { + Log.trace(F("Do we publish only sensors" CR)); + Log.trace(F("Previous value: %T" CR), BTConfig.pubOnlySensors); + BTConfig.pubOnlySensors = (bool)BTdata["onlysensors"]; + Log.notice(F("New value onlysensors: %T" CR), BTConfig.pubOnlySensors); + } + // Home Assistant presence message + if (BTdata.containsKey("hasspresence") || BTdata.containsKey("presenceEnable")) { // TODO Check if should be only hasspresence or presenceEnable ; or split in 2 + // storing Min RSSI for further use if needed + Log.trace(F("Previous hasspresence: %T" CR), BTConfig.presenceEnable); + // set Min RSSI if present if not setting default value + BTConfig.presenceEnable = (BTdata.containsKey("hasspresence")) ? ((bool)BTdata["hasspresence"]) : ((bool)BTdata["presenceEnable"]); + Log.notice(F("New hasspresence: %T" CR), BTConfig.presenceEnable); + } + // Home Assistant presence message topic + if (BTdata.containsKey("presenceTopic")) { + Log.trace(F("Previous value: %s" CR), BTConfig.presenceTopic); + strncpy(BTConfig.presenceTopic, BTdata["presenceTopic"], parameters_size); + Log.notice(F("New value presenceTopic: %s" CR), BTConfig.presenceTopic); + } + // Home Assistant presence message use iBeacon UUID + if (BTdata.containsKey("presenceUseBeaconUuid")) { + Log.trace(F("Previous value: %T" CR), BTConfig.presenceUseBeaconUuid); + BTConfig.presenceUseBeaconUuid = (bool)BTdata["presenceUseBeaconUuid"]; + Log.notice(F("New value presenceUseBeaconUuid: %T" CR), BTConfig.presenceUseBeaconUuid); + } + // MinRSSI set + if (BTdata.containsKey("minrssi")) { + // storing Min RSSI for further use if needed + Log.trace(F("Previous minrssi: %d" CR), BTConfig.minRssi); + // set Min RSSI if present if not setting default value + BTConfig.minRssi = abs((int)BTdata["minrssi"]); + Log.notice(F("New minrssi: %d" CR), BTConfig.minRssi); + } + // Send undecoded device data + if (BTdata.containsKey("extDecoderEnable")) { + Log.trace(F("Previous value: %T" CR), BTConfig.extDecoderEnable); + BTConfig.extDecoderEnable = (bool)BTdata["extDecoderEnable"]; + Log.notice(F("New value extDecoderEnable: %T" CR), BTConfig.extDecoderEnable); + } + // Topic to send undecoded device data + if (BTdata.containsKey("extDecoderTopic")) { + Log.trace(F("Previous value: %s" CR), BTConfig.extDecoderTopic); + strncpy(BTConfig.extDecoderTopic, BTdata["extDecoderTopic"], parameters_size); + Log.notice(F("New value extDecoderTopic: %s" CR), BTConfig.extDecoderTopic); + } + // Sets whether to filter publishing + if (BTdata.containsKey("filterConnectable")) { + Log.trace(F("Previous value: %T" CR), BTConfig.filterConnectable); + BTConfig.filterConnectable = (bool)BTdata["filterConnectable"]; + Log.notice(F("New value filterConnectable: %T" CR), BTConfig.filterConnectable); + } + // Publish service data belonging to recognised sensors + if (BTdata.containsKey("pubKnownServiceData")) { + Log.trace(F("Previous value: %T" CR), BTConfig.pubKnownServiceData); + BTConfig.pubKnownServiceData = (bool)BTdata["pubKnownServiceData"]; + Log.notice(F("New value pubKnownServiceData: %T" CR), BTConfig.pubKnownServiceData); + } + // Publish service data belonging to unrecognised sensors + if (BTdata.containsKey("pubUnknownServiceData")) { + Log.trace(F("Previous value: %T" CR), BTConfig.pubUnknownServiceData); + BTConfig.pubUnknownServiceData = (bool)BTdata["pubUnknownServiceData"]; + Log.notice(F("New value pubUnknownServiceData: %T" CR), BTConfig.pubUnknownServiceData); + } + // Publish known manufacturer's data + if (BTdata.containsKey("pubKnownManufData")) { + Log.trace(F("Previous value: %T" CR), BTConfig.pubKnownManufData); + BTConfig.pubKnownManufData = (bool)BTdata["pubKnownManufData"]; + Log.notice(F("New value pubKnownManufData: %T" CR), BTConfig.pubKnownManufData); + } + // Publish unknown manufacturer's data + if (BTdata.containsKey("pubUnknownManufData")) { + Log.trace(F("Previous value: %T" CR), BTConfig.pubUnknownManufData); + BTConfig.pubUnknownManufData = (bool)BTdata["pubUnknownManufData"]; + Log.notice(F("New value pubUnknownManufData: %T" CR), BTConfig.pubUnknownManufData); + } + // Publish the service UUID data + if (BTdata.containsKey("pubServiceDataUUID")) { + Log.trace(F("Previous value: %T" CR), BTConfig.pubServiceDataUUID); + BTConfig.pubServiceDataUUID = (bool)BTdata["pubServiceDataUUID"]; + Log.notice(F("New value pubServiceDataUUID: %T" CR), BTConfig.pubServiceDataUUID); + } + // Use iBeacon UUID as topic, instead of sender (random) MAC address + if (BTdata.containsKey("pubBeaconUuidForTopic")) { + Log.trace(F("Previous value: %T" CR), BTConfig.pubBeaconUuidForTopic); + BTConfig.pubBeaconUuidForTopic = (bool)BTdata["pubBeaconUuidForTopic"]; + Log.notice(F("New value pubBeaconUuidForTopic: %T" CR), BTConfig.pubBeaconUuidForTopic); + } +} void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { if (abs((int)data["rssi"] | 0) < BTConfig.minRssi && data.containsKey("id")) { @@ -1222,59 +1334,19 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding # endif } - // Attempts to connect to elligible devices or not - if (BTdata.containsKey("bleconnect")) { - Log.trace(F("Do we initiate a connection to retrieve data" CR)); - Log.trace(F("Previous value: %T" CR), BTConfig.bleConnect); - BTConfig.bleConnect = (bool)BTdata["bleconnect"]; - Log.notice(F("New value bleConnect: %T" CR), BTConfig.bleConnect); - } - // Scan interval set - if (BTdata.containsKey("interval")) { - Log.trace(F("BLE interval setup" CR)); - unsigned int interval = BTdata["interval"]; - if (interval == 0) { + // Force scan now + if (BTdata.containsKey("interval") && BTdata["interval"] == 0) { + Log.notice(F("BLE forced scan" CR)); # ifdef ESP32 - atomic_store_explicit(&forceBTScan, 1, ::memory_order_seq_cst); // ask the other core to do the scan for us + atomic_store_explicit(&forceBTScan, 1, ::memory_order_seq_cst); // ask the other core to do the scan for us # else - BTforceScan(); + BTforceScan(); # endif - } else { - Log.trace(F("Previous interval: %d ms" CR), BTConfig.BLEinterval); - BTConfig.BLEinterval = interval; - Log.notice(F("New interval: %d ms" CR), BTConfig.BLEinterval); - } - } - // Number of scan before a connect set - if (BTdata.containsKey("scanbcnct")) { - Log.trace(F("BLE scans number before a connect setup" CR)); - Log.trace(F("Previous number: %d" CR), BTConfig.BLEscanBeforeConnect); - BTConfig.BLEscanBeforeConnect = (unsigned int)BTdata["scanbcnct"]; - Log.notice(F("New scan number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); - } - // publish all BLE devices discovered or only the identified sensors (like temperature sensors) - if (BTdata.containsKey("onlysensors")) { - Log.trace(F("Do we publish only sensors" CR)); - Log.trace(F("Previous value: %T" CR), BTConfig.pubOnlySensors); - BTConfig.pubOnlySensors = (bool)BTdata["onlysensors"]; - Log.notice(F("New value onlysensors: %T" CR), BTConfig.pubOnlySensors); - } - // MinRSSI set - if (BTdata.containsKey("minrssi")) { - // storing Min RSSI for further use if needed - Log.trace(F("Previous minrssi: %d" CR), BTConfig.minRssi); - // set Min RSSI if present if not setting default value - BTConfig.minRssi = abs((int)BTdata["minrssi"]); - Log.notice(F("New minrssi: %d" CR), BTConfig.minRssi); - } - // Home Assistant presence message - if (BTdata.containsKey("hasspresence")) { - // storing Min RSSI for further use if needed - Log.trace(F("Previous hasspresence: %T" CR), BTConfig.presenceEnable); - // set Min RSSI if present if not setting default value - BTConfig.presenceEnable = (bool)BTdata["hasspresence"]; - Log.notice(F("New hasspresence: %T" CR), BTConfig.presenceEnable); } + + // Load config from json if available + BTConfig_fromJson(BTdata); + # ifdef ESP32 if (BTdata.containsKey("lowpowermode")) { changelowpowermode((int)BTdata["lowpowermode"]); From 4eabc10abf3f68aa8db10cf88951389451522569 Mon Sep 17 00:00:00 2001 From: Bad Date: Sun, 21 Aug 2022 11:07:08 +0200 Subject: [PATCH 05/17] Add ignoreWBlist as new configuration parameter --- main/ZgatewayBT.ino | 15 +++++++++++---- main/config_BT.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index adca764bd7..72b71e4eed 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -111,6 +111,7 @@ void BTConfig_init() { BTConfig.pubUnknownManufData = pubUnknownBLEManufacturerData; BTConfig.pubServiceDataUUID = pubBLEServiceUUID; BTConfig.pubBeaconUuidForTopic = useBeaconUuidForTopic; + BTConfig.ignoreWBlist = false; } void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { @@ -224,6 +225,12 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { BTConfig.pubBeaconUuidForTopic = (bool)BTdata["pubBeaconUuidForTopic"]; Log.notice(F("New value pubBeaconUuidForTopic: %T" CR), BTConfig.pubBeaconUuidForTopic); } + // Disable Whitelist & Blacklist + if (BTdata.containsKey("ignoreWBlist")) { + Log.trace(F("Previous value: %T" CR), BTConfig.ignoreWBlist); + BTConfig.ignoreWBlist = (bool)BTdata["ignoreWBlist"]; + Log.notice(F("New value ignoreWBlist: %T" CR), BTConfig.ignoreWBlist); + } } void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { @@ -578,7 +585,7 @@ void procBLETask(void* pvParameters) { continue; } - if ((!oneWhite || isWhite(device)) && !isBlack(device)) { //if not black listed MAC we go AND if we have no white MAC or this MAC is white we go out + if (BTConfig.ignoreWBlist || ((!oneWhite || isWhite(device)) && !isBlack(device))) { // Only if WBlist is disabled OR ((no white MAC OR this MAC is white) AND not a black listed MAC) if (advertisedDevice->haveName()) BLEdata["name"] = (char*)advertisedDevice->getName().c_str(); if (advertisedDevice->haveManufacturerData()) { @@ -951,10 +958,10 @@ bool BTtoMQTT() { BLEdata["id"] = (const char*)mac.c_str(); BLEdevice* device = getDeviceByMac((char*)mac.c_str()); - if (isBlack(device)) + if (!BTConfig.ignoreWBlist && isBlack(device)) return false; //if black listed MAC we go out - if (oneWhite && !isWhite(device)) - return false; //if we have at least one white MAC and this MAC is not white we go out + if (!BTConfig.ignoreWBlist && oneWhite && !isWhite(device)) + return false; //if WBlist is enabled AND we have at least one white MAC AND this MAC is not white we go out BLEdata["rssi"] = (int)rssi; if (!BTConfig.pubOnlySensors && BTConfig.presenceEnable) diff --git a/main/config_BT.h b/main/config_BT.h index bfc35302a7..1bdfc2dd27 100644 --- a/main/config_BT.h +++ b/main/config_BT.h @@ -162,6 +162,7 @@ struct BTConfig_s { bool pubUnknownManufData; // Publish the manufacturer's data (sometimes contains characters that aren't valid with receiving client) bool pubServiceDataUUID; // Publish the service UUID data bool pubBeaconUuidForTopic; // Use iBeacon UUID as topic, instead of sender (random) MAC address + bool ignoreWBlist; // Disable Whitelist & Blacklist }; // Global struct to store live BT configuration data From e26dfce1011f552604b7d48cfe6fbfefd25e6ea9 Mon Sep 17 00:00:00 2001 From: Bad Date: Tue, 23 Aug 2022 14:38:36 +0200 Subject: [PATCH 06/17] Keep hasspresence keyword (do not use presenceEnable) --- main/ZgatewayBT.ino | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 72b71e4eed..21b32e14e5 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -144,11 +144,9 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { Log.notice(F("New value onlysensors: %T" CR), BTConfig.pubOnlySensors); } // Home Assistant presence message - if (BTdata.containsKey("hasspresence") || BTdata.containsKey("presenceEnable")) { // TODO Check if should be only hasspresence or presenceEnable ; or split in 2 - // storing Min RSSI for further use if needed + if (BTdata.containsKey("hasspresence")) { Log.trace(F("Previous hasspresence: %T" CR), BTConfig.presenceEnable); - // set Min RSSI if present if not setting default value - BTConfig.presenceEnable = (BTdata.containsKey("hasspresence")) ? ((bool)BTdata["hasspresence"]) : ((bool)BTdata["presenceEnable"]); + BTConfig.presenceEnable = (bool)BTdata["hasspresence"]; Log.notice(F("New hasspresence: %T" CR), BTConfig.presenceEnable); } // Home Assistant presence message topic From a9a31cdf20981ddbfa060f184f7b39c353a9c619 Mon Sep 17 00:00:00 2001 From: Bad Date: Sun, 21 Aug 2022 16:57:09 +0200 Subject: [PATCH 07/17] Documentation --- docs/integrate/openhab2.md | 2 +- docs/use/ble.md | 95 +++++++++++++++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/docs/integrate/openhab2.md b/docs/integrate/openhab2.md index 63c48d147c..82fac4e6d8 100644 --- a/docs/integrate/openhab2.md +++ b/docs/integrate/openhab2.md @@ -11,7 +11,7 @@ You need to set `OpenHABAutoDiscovery` to true into `config_mqttDiscovery.h` `#define OpenHABDiscovery true` ::: tip -If you are connecting to BLE devices it is highly recommended to set `BLE_FILTER_CONNECTABLE` to `1` in `config_BT.h`. Otherwise you may encounter incomplete data. +If you are connecting to BLE devices it is highly recommended to set `filterConnectable` to `true` in [BT configuration](../use/ble.md#advanced-filter-out-connectable-devices). Otherwise you may encounter incomplete data. ::: The things will appear in the inbox of the paperUI, add them and links the channels. You should see them into the control panel for further usage. diff --git a/docs/use/ble.md b/docs/use/ble.md index f40c91b307..bbbe0aaa01 100644 --- a/docs/use/ble.md +++ b/docs/use/ble.md @@ -75,7 +75,13 @@ A white list is a list of MAC addresses permitted to be published by OMG to set white list `mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"white-list":["01:23:14:55:16:15","4C:65:77:88:9C:79","4C:65:A6:66:3C:79"]}'` -Note: if you want to filter (white or black list) on BLE sensors that are auto discovered, you need to wait for the discovery before applying the white or black list +Note: if you want to filter (white or black list) on BLE sensors that are auto discovered, you need to wait for the discovery before applying the white or black list, or temporarily disable it: + +to temporarily disable white/black list +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"ignoreWBlist":true}'` + +to enable white/black list back +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"ignoreWBlist":false}'` ::: tip So as to keep your white/black list persistent you can publish it with the retain option of MQTT (-r with mosquitto_pub or retain check box of MQTT Explorer) @@ -148,6 +154,41 @@ Or by an MQTT command. `mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"hasspresence":true}'` +To change presence publication topic, use this MQTT command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"presenceTopic":"presence/"}'` + +To use iBeacon UUID for presence, instead of sender (random) MAC address, use this MQTT command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"presenceUseBeaconUuid":true}'` + +This will change usual payload for iBeacon from: +`{"id":"60:87:57:4C:9B:C2","mac_type":1,"rssi":-78,"distance":7.85288,"brand":"GENERIC","model":"iBeacon","model_id":"IBEACON","mfid":"4c00","uuid":"1de4b189115e45f6b44e509352269977","major":0,"minor":0,"txpower":-66}` +To: +`{"id":"1de4b189115e45f6b44e509352269977","mac_type":1,"rssi":-78,"distance":7.85288,"brand":"GENERIC","model":"iBeacon","model_id":"IBEACON","mfid":"4c00","uuid":"1de4b189115e45f6b44e509352269977","major":0,"minor":0,"txpower":-66,"mac":"60:87:57:4C:9B:C2"}` +Note: the MAC address is put in "mac" field. + +## Setting if the gateway uses iBeacon UUID as topic, instead of (random) MAC address + +By default, iBeacon are published like other devices, using a topic based on the MAC address of the sender. +But modern phones randomize their Bluetooth MAC address making it difficult to track iBeacon. + +For example, the 2 following messages corresponds to the same iBeacon, but with different MAC and topics: +``` +home/OpenMQTTGateway/BTtoMQTT/58782076BC24 {"id":"58:78:20:76:BC:24","mac_type":1,"rssi":-79,"brand":"GENERIC","model":"iBeacon","model_id":"IBEACON","mfid":"4c00","uuid":"1de4b189115e45f6b44e509352269977","major":0,"minor":0,"txpower":-66} +home/OpenMQTTGateway/BTtoMQTT/5210A84690AC {"id":"52:10:A8:46:90:AC","mac_type":1,"rssi":-77,"brand":"GENERIC","model":"iBeacon","model_id":"IBEACON","mfid":"4c00","uuid":"1de4b189115e45f6b44e509352269977","major":0,"minor":0,"txpower":-66} +``` + +To use iBeacon UUID as topic, use this MQTT command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubBeaconUuidForTopic":true}'` + +Resulting in such messages (for the same iBeacon as previously): +``` +home/OpenMQTTGateway/BTtoMQTT/1de4b189115e45f6b44e509352269977 {"id":"52:10:A8:46:90:AC","mac_type":1,"rssi":-76,"brand":"GENERIC","model":"iBeacon","model_id":"IBEACON","mfid":"4c00","uuid":"1de4b189115e45f6b44e509352269977","major":0,"minor":0,"txpower":-66} +home/OpenMQTTGateway/BTtoMQTT/1de4b189115e45f6b44e509352269977 {"id":"7B:63:C6:82:DC:57","mac_type":1,"rssi":-83,"brand":"GENERIC","model":"iBeacon","model_id":"IBEACON","mfid":"4c00","uuid":"1de4b189115e45f6b44e509352269977","major":0,"minor":0,"txpower":-66} +``` + ## Setting the minimum RSSI accepted to publish device data If you want to change the minimum RSSI value accepted for a device to be published, you can change it by MQTT. For example if you want to set -80 @@ -160,11 +201,61 @@ you can also accept all the devices by the following command: The default value is set into config_BT.h +## ADVANCED: Setting up an external decoder + +This advanced option is used to publish raw radio frames on a specific topic to be decoded by an external decoder instead of the integrated one. + +To enable external decoder: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"extDecoderEnable":true}'` + +To change the default external decoder topic to "undecoded": + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"extDecoderTopic":"undecoded"}'` + +## ADVANCED: Filtering out connectable devices + +[With OpenHAB integration](../integrate/openhab2.md), this configuration is highly recommended, otherwise you may encounter incomplete data. + +If you want to enable this feature: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"filterConnectable":true}'` + +## ADVANCED: Publishing known service data + +If you want to enable this feature: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubKnownServiceData":true}'` + +## ADVANCED: Publishing unknown service data + +If you want to change the default behaviour, in case you are having too heavy service data: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubUnknownServiceData":false}'` + +## ADVANCED: Publishing known manufacturer's data + +If you want to change the default behaviour: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubKnownManufData":true}'` + +## ADVANCED: Publishing unknown manufacturer's data + +If you want to change the default behaviour, in case you are having too heavy service data: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubUnknownManufData":false}'` + +## ADVANCED: Publishing the service UUID data + +If you want to change the default behaviour: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubServiceDataUUID":true}'` + ## Read/write BLE characteristics over MQTT (ESP32 only) The gateway can read and write BLE characteristics from devices and provide the results in an MQTT message. ::: tip -These actions will be taken on the next BLE connection, which occurs after scanning and after the scan count is reached, [see above to set this.](#setting-the-number-of-scans-between-connection-attempts) +These actions will be taken on the next BLE connection, which occurs after scanning and after the scan count is reached, [see above to set this](#setting-the-number-of-scans-between-connection-attempts). This can be overridden by providing an (optional) parameter `"immediate": true` within the command. This will cause the BLE scan to stop if currently in progress, allowing the command to be immediately processed. All other connection commands in queue will also be processed for the same device, commands for other devices will be deferred until the next normally scheduled connection. **Note** Some devices need to have the MAC address type specified. You can find this type by checking the log/MQTT data and looking for "mac_type". By default the type is 0 but some devices use different type values. You must specify the correct type to connect successfully. From 22835179ce285e533a219e3ad799d1f75181408e Mon Sep 17 00:00:00 2001 From: Bad Date: Sun, 21 Aug 2022 20:21:06 +0200 Subject: [PATCH 08/17] Typos & Optimizations arround RemoveJsonPropertyIf --- main/ZgatewayBT.ino | 21 +++++++-------------- main/config_BT.h | 2 +- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 21b32e14e5..9ed8026f66 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -1016,7 +1016,7 @@ void launchBTDiscovery() { p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::GAEN) { String macWOdots = String(p->macAdr); macWOdots.replace(":", ""); - if (!BTConfig.extDecoderEnable && // Do not decode if an external decoter 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::BLE_ID_MAX && p->sensorModel_id != TheengsDecoder::BLE_ID_NUM::HHCCJCY01HHCC) { // Exception on HHCCJCY01HHCC as this one is discoverable and connectable for battery retrieving @@ -1098,20 +1098,13 @@ void PublishDeviceData(JsonObject& BLEdata, bool processBLEData) { if (abs((int)BLEdata["rssi"] | 0) < BTConfig.minRssi) { // process only the devices close enough if (processBLEData) process_bledata(BLEdata); if (!BTConfig.pubOnlySensors || BLEdata.containsKey("model") || BLEdata.containsKey("distance")) { - if (!BTConfig.pubServiceDataUUID) - RemoveJsonPropertyIf(BLEdata, "servicedatauuid", BLEdata.containsKey("model") && BLEdata.containsKey("servicedatauuid")); - if (!BTConfig.pubKnownServiceData) - RemoveJsonPropertyIf(BLEdata, "servicedata", BLEdata.containsKey("model") && BLEdata.containsKey("servicedata")); - if (!BTConfig.pubKnownManufData) - RemoveJsonPropertyIf(BLEdata, "manufacturerdata", BLEdata.containsKey("model") && BLEdata.containsKey("manufacturerdata")); + RemoveJsonPropertyIf(BLEdata, "servicedatauuid", !BTConfig.pubServiceDataUUID && BLEdata.containsKey("model")); + RemoveJsonPropertyIf(BLEdata, "servicedata", !BTConfig.pubKnownServiceData && BLEdata.containsKey("model")); + RemoveJsonPropertyIf(BLEdata, "manufacturerdata", !BTConfig.pubKnownManufData && BLEdata.containsKey("model")); pubBT(BLEdata); } else { - if (!BTConfig.pubUnknownServiceData) { - Log.trace(F("Unknown service data, removing it" CR)); - RemoveJsonPropertyIf(BLEdata, "servicedata", BLEdata.containsKey("servicedata")); - } - if (!BTConfig.pubUnknownManufData) - RemoveJsonPropertyIf(BLEdata, "manufacturerdata", BLEdata.containsKey("model") && BLEdata.containsKey("manufacturerdata")); + RemoveJsonPropertyIf(BLEdata, "servicedata", !BTConfig.pubUnknownServiceData); + RemoveJsonPropertyIf(BLEdata, "manufacturerdata", !BTConfig.pubUnknownManufData && BLEdata.containsKey("model")); } } else if (BLEdata.containsKey("distance")) { pubBT(BLEdata); @@ -1156,7 +1149,7 @@ void process_bledata(JsonObject& BLEdata) { } } } - if (model_id < 0) { + if (!BTConfig.extDecoderEnable && model_id < 0) { Log.trace(F("No device found " CR)); } } diff --git a/main/config_BT.h b/main/config_BT.h index 1bdfc2dd27..81b31fc216 100644 --- a/main/config_BT.h +++ b/main/config_BT.h @@ -63,7 +63,7 @@ extern int btQueueLengthCount; # define BLE_FILTER_CONNECTABLE 0 // Sets whether to filter publishing of scanned devices that require a connection. #endif // Setting this to 1 prevents overwriting the publication of the device connection data with the advertised data (Recommended for use with OpenHAB). -#define MinimumRSSI -100 //default minimum rssi value, all the devices below -90 will not be reported +#define MinimumRSSI -100 //default minimum rssi value, all the devices below -100 will not be reported #ifndef Scan_duration # define Scan_duration 10000 //define the time for a scan From d1fd8a0e70ffae26901a18e81f419cc1cdae56c3 Mon Sep 17 00:00:00 2001 From: Bad Date: Thu, 25 Aug 2022 09:59:00 +0200 Subject: [PATCH 09/17] Template for BT config update --- main/ZgatewayBT.ino | 129 ++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 95 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 9ed8026f66..afb1d7f10c 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -114,120 +114,59 @@ void BTConfig_init() { BTConfig.ignoreWBlist = false; } +// DO NOT put a SPACE between `template` AND `<` OR IT WON'T COMPILE: (OpenMQTTGateway/main/main.ino:x:y: error: 'T' has not been declared) +template +void BTConfig_update(JsonObject& data, const char* key, T& var) { + if (data.containsKey(key)) { + if (var != data[key].as()) { + var = data[key].as(); + Log.notice(F("BT config %s changed: %s" CR), key, data[key].as()); + } else { + Log.notice(F("BT config %s unchanged: %s" CR), key, data[key].as()); + } + } +} + void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { // Attempts to connect to elligible devices or not - if (BTdata.containsKey("bleconnect")) { - Log.trace(F("Do we initiate a connection to retrieve data" CR)); - Log.trace(F("Previous value: %T" CR), BTConfig.bleConnect); - BTConfig.bleConnect = (bool)BTdata["bleconnect"]; - Log.notice(F("New value bleConnect: %T" CR), BTConfig.bleConnect); - } + BTConfig_update(BTdata, "bleconnect", BTConfig.bleConnect); // Scan interval set - if (BTdata.containsKey("interval") && BTdata["interval"] != 0) { - Log.trace(F("Previous interval: %d ms" CR), BTConfig.BLEinterval); - BTConfig.BLEinterval = BTdata["interval"]; - Log.notice(F("New interval: %d ms" CR), BTConfig.BLEinterval); - } - + if (BTdata.containsKey("interval") && BTdata["interval"] != 0) + BTConfig_update(BTdata, "interval", BTConfig.BLEinterval); // Number of scan before a connect set - if (BTdata.containsKey("scanbcnct")) { - Log.trace(F("BLE scans number before a connect setup" CR)); - Log.trace(F("Previous number: %d" CR), BTConfig.BLEscanBeforeConnect); - BTConfig.BLEscanBeforeConnect = (unsigned int)BTdata["scanbcnct"]; - Log.notice(F("New scan number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); - } + BTConfig_update(BTdata, "scanbcnct", BTConfig.BLEscanBeforeConnect); // publish all BLE devices discovered or only the identified sensors (like temperature sensors) - if (BTdata.containsKey("onlysensors")) { - Log.trace(F("Do we publish only sensors" CR)); - Log.trace(F("Previous value: %T" CR), BTConfig.pubOnlySensors); - BTConfig.pubOnlySensors = (bool)BTdata["onlysensors"]; - Log.notice(F("New value onlysensors: %T" CR), BTConfig.pubOnlySensors); - } + BTConfig_update(BTdata, "onlysensors", BTConfig.pubOnlySensors); // Home Assistant presence message - if (BTdata.containsKey("hasspresence")) { - Log.trace(F("Previous hasspresence: %T" CR), BTConfig.presenceEnable); - BTConfig.presenceEnable = (bool)BTdata["hasspresence"]; - Log.notice(F("New hasspresence: %T" CR), BTConfig.presenceEnable); - } + BTConfig_update(BTdata, "hasspresence", BTConfig.presenceEnable); // Home Assistant presence message topic - if (BTdata.containsKey("presenceTopic")) { - Log.trace(F("Previous value: %s" CR), BTConfig.presenceTopic); - strncpy(BTConfig.presenceTopic, BTdata["presenceTopic"], parameters_size); - Log.notice(F("New value presenceTopic: %s" CR), BTConfig.presenceTopic); - } + BTConfig_update(BTdata, "presenceTopic", BTConfig.presenceTopic); // Home Assistant presence message use iBeacon UUID - if (BTdata.containsKey("presenceUseBeaconUuid")) { - Log.trace(F("Previous value: %T" CR), BTConfig.presenceUseBeaconUuid); - BTConfig.presenceUseBeaconUuid = (bool)BTdata["presenceUseBeaconUuid"]; - Log.notice(F("New value presenceUseBeaconUuid: %T" CR), BTConfig.presenceUseBeaconUuid); - } + BTConfig_update(BTdata, "presenceUseBeaconUuid", BTConfig.presenceUseBeaconUuid); // MinRSSI set - if (BTdata.containsKey("minrssi")) { - // storing Min RSSI for further use if needed - Log.trace(F("Previous minrssi: %d" CR), BTConfig.minRssi); - // set Min RSSI if present if not setting default value - BTConfig.minRssi = abs((int)BTdata["minrssi"]); - Log.notice(F("New minrssi: %d" CR), BTConfig.minRssi); - } + BTConfig_update(BTdata, "minrssi", BTConfig.minRssi); // Send undecoded device data - if (BTdata.containsKey("extDecoderEnable")) { - Log.trace(F("Previous value: %T" CR), BTConfig.extDecoderEnable); - BTConfig.extDecoderEnable = (bool)BTdata["extDecoderEnable"]; - Log.notice(F("New value extDecoderEnable: %T" CR), BTConfig.extDecoderEnable); - } + BTConfig_update(BTdata, "extDecoderEnable", BTConfig.extDecoderEnable); // Topic to send undecoded device data - if (BTdata.containsKey("extDecoderTopic")) { - Log.trace(F("Previous value: %s" CR), BTConfig.extDecoderTopic); - strncpy(BTConfig.extDecoderTopic, BTdata["extDecoderTopic"], parameters_size); - Log.notice(F("New value extDecoderTopic: %s" CR), BTConfig.extDecoderTopic); - } + BTConfig_update(BTdata, "extDecoderTopic", BTConfig.extDecoderTopic); // Sets whether to filter publishing - if (BTdata.containsKey("filterConnectable")) { - Log.trace(F("Previous value: %T" CR), BTConfig.filterConnectable); - BTConfig.filterConnectable = (bool)BTdata["filterConnectable"]; - Log.notice(F("New value filterConnectable: %T" CR), BTConfig.filterConnectable); - } + BTConfig_update(BTdata, "filterConnectable", BTConfig.filterConnectable); // Publish service data belonging to recognised sensors - if (BTdata.containsKey("pubKnownServiceData")) { - Log.trace(F("Previous value: %T" CR), BTConfig.pubKnownServiceData); - BTConfig.pubKnownServiceData = (bool)BTdata["pubKnownServiceData"]; - Log.notice(F("New value pubKnownServiceData: %T" CR), BTConfig.pubKnownServiceData); - } + BTConfig_update(BTdata, "pubKnownServiceData", BTConfig.pubKnownServiceData); // Publish service data belonging to unrecognised sensors - if (BTdata.containsKey("pubUnknownServiceData")) { - Log.trace(F("Previous value: %T" CR), BTConfig.pubUnknownServiceData); - BTConfig.pubUnknownServiceData = (bool)BTdata["pubUnknownServiceData"]; - Log.notice(F("New value pubUnknownServiceData: %T" CR), BTConfig.pubUnknownServiceData); - } + BTConfig_update(BTdata, "pubUnknownServiceData", BTConfig.pubUnknownServiceData); // Publish known manufacturer's data - if (BTdata.containsKey("pubKnownManufData")) { - Log.trace(F("Previous value: %T" CR), BTConfig.pubKnownManufData); - BTConfig.pubKnownManufData = (bool)BTdata["pubKnownManufData"]; - Log.notice(F("New value pubKnownManufData: %T" CR), BTConfig.pubKnownManufData); - } + BTConfig_update(BTdata, "pubKnownManufData", BTConfig.pubKnownManufData); // Publish unknown manufacturer's data - if (BTdata.containsKey("pubUnknownManufData")) { - Log.trace(F("Previous value: %T" CR), BTConfig.pubUnknownManufData); - BTConfig.pubUnknownManufData = (bool)BTdata["pubUnknownManufData"]; - Log.notice(F("New value pubUnknownManufData: %T" CR), BTConfig.pubUnknownManufData); - } + BTConfig_update(BTdata, "pubUnknownManufData", BTConfig.pubUnknownManufData); // Publish the service UUID data - if (BTdata.containsKey("pubServiceDataUUID")) { - Log.trace(F("Previous value: %T" CR), BTConfig.pubServiceDataUUID); - BTConfig.pubServiceDataUUID = (bool)BTdata["pubServiceDataUUID"]; - Log.notice(F("New value pubServiceDataUUID: %T" CR), BTConfig.pubServiceDataUUID); - } + BTConfig_update(BTdata, "pubServiceDataUUID", BTConfig.pubServiceDataUUID); // Use iBeacon UUID as topic, instead of sender (random) MAC address - if (BTdata.containsKey("pubBeaconUuidForTopic")) { - Log.trace(F("Previous value: %T" CR), BTConfig.pubBeaconUuidForTopic); - BTConfig.pubBeaconUuidForTopic = (bool)BTdata["pubBeaconUuidForTopic"]; - Log.notice(F("New value pubBeaconUuidForTopic: %T" CR), BTConfig.pubBeaconUuidForTopic); - } + BTConfig_update(BTdata, "pubBeaconUuidForTopic", BTConfig.pubBeaconUuidForTopic); // Disable Whitelist & Blacklist - if (BTdata.containsKey("ignoreWBlist")) { - Log.trace(F("Previous value: %T" CR), BTConfig.ignoreWBlist); - BTConfig.ignoreWBlist = (bool)BTdata["ignoreWBlist"]; - Log.notice(F("New value ignoreWBlist: %T" CR), BTConfig.ignoreWBlist); + BTConfig_update(BTdata, "ignoreWBlist", (BTConfig.ignoreWBlist)); +} + } } From cbb081208929c80cac8bbd8f3177e48233b03103 Mon Sep 17 00:00:00 2001 From: Bad Date: Thu, 25 Aug 2022 09:59:52 +0200 Subject: [PATCH 10/17] Ensure BTConfig.minRssi sign does not matter --- main/ZgatewayBT.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index afb1d7f10c..74e13e147d 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -101,7 +101,7 @@ void BTConfig_init() { BTConfig.presenceEnable = HassPresence; BTConfig.presenceTopic = subjectHomePresence; BTConfig.presenceUseBeaconUuid = useBeaconUuidForPresence; - BTConfig.minRssi = abs(MinimumRSSI); + BTConfig.minRssi = MinimumRSSI; BTConfig.extDecoderEnable = UseExtDecoder; BTConfig.extDecoderTopic = MQTTDecodeTopic; BTConfig.filterConnectable = BLE_FILTER_CONNECTABLE; @@ -171,7 +171,7 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { } void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { - if (abs((int)data["rssi"] | 0) < BTConfig.minRssi && data.containsKey("id")) { + if (abs((int)data["rssi"] | 0) < abs(BTConfig.minRssi) && data.containsKey("id")) { String topic = data["id"].as(); topic.replace(":", ""); // Initially publish topic ends with MAC address if (BTConfig.pubBeaconUuidForTopic && !BTConfig.extDecoderEnable && data.containsKey("model_id") && data["model_id"].as() == "IBEACON") @@ -751,7 +751,7 @@ void setupBT() { Log.notice(F("BLE scans interval: %d" CR), BTConfig.BLEinterval); Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); - Log.notice(F("minrssi: %d" CR), BTConfig.minRssi); + Log.notice(F("minrssi: %d" CR), -abs(BTConfig.minRssi)); Log.notice(F("Low Power Mode: %d" CR), lowpowermode); atomic_init(&forceBTScan, 0); // in theory, we don't need this @@ -813,7 +813,7 @@ void setupBT() { Log.notice(F("BLE interval: %d" CR), BTConfig.BLEinterval); Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); - Log.notice(F("minrssi: %d" CR), BTConfig.minRssi); + Log.notice(F("minrssi: %d" CR), -abs(BTConfig.minRssi)); softserial.begin(HMSerialSpeed); softserial.print(F("AT+ROLE1" CR)); delay(100); @@ -1034,7 +1034,7 @@ void launchBTDiscovery() { # endif void PublishDeviceData(JsonObject& BLEdata, bool processBLEData) { - if (abs((int)BLEdata["rssi"] | 0) < BTConfig.minRssi) { // process only the devices close enough + if (abs((int)BLEdata["rssi"] | 0) < abs(BTConfig.minRssi)) { // process only the devices close enough if (processBLEData) process_bledata(BLEdata); if (!BTConfig.pubOnlySensors || BLEdata.containsKey("model") || BLEdata.containsKey("distance")) { RemoveJsonPropertyIf(BLEdata, "servicedatauuid", !BTConfig.pubServiceDataUUID && BLEdata.containsKey("model")); From 151f809dfef573a89fd42e170b5c6cc95073a64b Mon Sep 17 00:00:00 2001 From: Bad Date: Thu, 25 Aug 2022 10:00:22 +0200 Subject: [PATCH 11/17] Report configuration change on topic /commands/BTtoMQTT/config # Conflicts: # main/ZgatewayBT.ino --- main/ZgatewayBT.ino | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 74e13e147d..a72a1f538a 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -165,9 +165,35 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { BTConfig_update(BTdata, "pubBeaconUuidForTopic", BTConfig.pubBeaconUuidForTopic); // Disable Whitelist & Blacklist BTConfig_update(BTdata, "ignoreWBlist", (BTConfig.ignoreWBlist)); -} + StaticJsonDocument jsonBuffer; + JsonObject jo = jsonBuffer.to(); + jo["bleconnect"] = BTConfig.bleConnect; + jo["interval"] = BTConfig.BLEinterval; + jo["scanbcnct"] = BTConfig.BLEscanBeforeConnect; + jo["onlysensors"] = BTConfig.pubOnlySensors; + jo["hasspresence"] = BTConfig.presenceEnable; + jo["presenceTopic"] = BTConfig.presenceTopic; + jo["presenceUseBeaconUuid"] = BTConfig.presenceUseBeaconUuid; + jo["minrssi"] = -abs(BTConfig.minRssi); // Always export as negative value + jo["extDecoderEnable"] = BTConfig.extDecoderEnable; + jo["extDecoderTopic"] = BTConfig.extDecoderTopic; + jo["filterConnectable"] = BTConfig.filterConnectable; + jo["pubKnownServiceData"] = BTConfig.pubKnownServiceData; + jo["pubUnknownServiceData"] = BTConfig.pubUnknownServiceData; + jo["pubKnownManufData"] = BTConfig.pubKnownManufData; + jo["pubUnknownManufData"] = BTConfig.pubUnknownManufData; + jo["pubServiceDataUUID"] = BTConfig.pubServiceDataUUID; + jo["pubBeaconUuidForTopic"] = BTConfig.pubBeaconUuidForTopic; + jo["ignoreWBlist"] = BTConfig.ignoreWBlist; + + if (startup) { + Log.notice(F("BT config: ")); + serializeJsonPretty(jsonBuffer, Serial); + Serial.println(); + return; // Do not try to erase/write/send config at startup } + pub("/commands/BTtoMQTT/config", jo); } void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { From 4a27e82c3fa84187ce85b4e71de6989146de0a6b Mon Sep 17 00:00:00 2001 From: Bad Date: Fri, 26 Aug 2022 13:21:32 +0200 Subject: [PATCH 12/17] Add BT config bool commands (init, load, erase & save) to persist config parameters --- main/ZgatewayBT.ino | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index a72a1f538a..f1e06338f6 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -194,6 +194,44 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { return; // Do not try to erase/write/send config at startup } pub("/commands/BTtoMQTT/config", jo); + + if (BTdata.containsKey("erase") && BTdata["erase"].as()) { + // Erase config from NVS (non-volatile storage) + preferences.begin(Gateway_Short_Name, false); + preferences.remove("BTConfig"); + preferences.end(); + Log.notice(F("BT config erased" CR)); + return; // Erase prevails on save, so skiping save + } + + if (BTdata.containsKey("save") && BTdata["save"].as()) { + // Save config into NVS (non-volatile storage) + String conf = ""; + serializeJson(jsonBuffer, conf); + preferences.begin(Gateway_Short_Name, false); + preferences.putString("BTConfig", conf); + preferences.end(); + Log.notice(F("BT config saved" CR)); + } +} + +void BTConfig_load() { + StaticJsonDocument jsonBuffer; + preferences.begin(Gateway_Short_Name, true); + auto error = deserializeJson(jsonBuffer, preferences.getString("BTConfig", "{}")); + preferences.end(); + Log.notice(F("BT config loaded" CR)); + if (error) { + Log.error(F("BT config deserialization failed: %s, buffer capacity: %u" CR), error.c_str(), jsonBuffer.capacity()); + return; + } + if (jsonBuffer.isNull()) { + Log.warning(F("BT config is null" CR)); + return; + } + JsonObject jo = jsonBuffer.as(); + BTConfig_fromJson(jo, true); // Never send mqtt message with config + Log.notice(F("BT config loaded" CR)); } void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { @@ -774,6 +812,7 @@ void changelowpowermode(int newLowPowerMode) { void setupBT() { BTConfig_init(); + BTConfig_load(); Log.notice(F("BLE scans interval: %d" CR), BTConfig.BLEinterval); Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); @@ -836,6 +875,7 @@ struct decompose d[6] = {{0, 12, true}, {12, 2, false}, {14, 2, false}, {16, 2, void setupBT() { BTConfig_init(); + BTConfig_load(); Log.notice(F("BLE interval: %d" CR), BTConfig.BLEinterval); Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); @@ -1307,6 +1347,20 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding # endif } + /* + * Configuration modifications priorities: + * First `init=true` and `load=true` commands are executed (if both are present, INIT prevails on LOAD) + * Then parameters included in json are taken in account + * Finally `erase=true` and `save=true` commands are executed (if both are present, ERASE prevails on SAVE) + */ + if (BTdata.containsKey("init") && BTdata["init"].as()) { + // Restore the default (initial) configuration + BTConfig_init(); + } else if (BTdata.containsKey("load") && BTdata["load"].as()) { + // Load the saved configuration, if not initialised + BTConfig_load(); + } + // Load config from json if available BTConfig_fromJson(BTdata); From d71c678ad940468c06265d013955c04cb8d09d9e Mon Sep 17 00:00:00 2001 From: Bad Date: Fri, 26 Aug 2022 13:38:16 +0200 Subject: [PATCH 13/17] Documentation --- docs/use/ble.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/use/ble.md b/docs/use/ble.md index bbbe0aaa01..570a9d6327 100644 --- a/docs/use/ble.md +++ b/docs/use/ble.md @@ -251,6 +251,28 @@ If you want to change the default behaviour: `mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubServiceDataUUID":true}'` +## Store BLE configuration into the gateway + +Open MQTT Gateway has the capability to save the current configuration and reload it at startup. + +To store the running configuration into the gateway, use the command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"save":true}'` + +At any time, you can reload the stored configuration with the command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"load":true}'` + +If you want to erase the stored configuration, use the command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"erase":true}'` +Note that it will not change the running configuration, only ensure default configuration is used at next startup. + +By the way, if you want to load the default built-in configuration, use the command: + +`mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"init":true}'` +Note that it will not change the stored configuration, `erase` or `save` is still needed to overwrite the saved configuration. + ## Read/write BLE characteristics over MQTT (ESP32 only) The gateway can read and write BLE characteristics from devices and provide the results in an MQTT message. From cbf92dc8af671f74020c9998e82224e3b9924487 Mon Sep 17 00:00:00 2001 From: Bad Date: Sat, 27 Aug 2022 11:08:38 +0200 Subject: [PATCH 14/17] Fix pre-compilation issue --- main/ZgatewayBT.ino | 3 ++- platformio.ini | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index f1e06338f6..22d71b7acb 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -201,7 +201,7 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { preferences.remove("BTConfig"); preferences.end(); Log.notice(F("BT config erased" CR)); - return; // Erase prevails on save, so skiping save + return; // Erase prevails on save, so skipping save } if (BTdata.containsKey("save") && BTdata["save"].as()) { @@ -351,6 +351,7 @@ void pubBT(JsonObject& data) { bool ProcessLock = false; // Process lock when we want to use a critical function like OTA for example +BLEdevice* getDeviceByMac(const char* mac); // Declared here to avoid pre-compilation issue (misplaced auto declaration by pio) void createOrUpdateDevice(const char* mac, uint8_t flags, int model, int mac_type = 0); BLEdevice* getDeviceByMac(const char* mac) { diff --git a/platformio.ini b/platformio.ini index 980a1b6eef..ca313acfec 100644 --- a/platformio.ini +++ b/platformio.ini @@ -147,6 +147,7 @@ lib_deps = ${libraries.arduinolog} build_flags = -w ; supress all warnings +; -E ; generate precompiled source file (.pio/build/*/src/main.ino.cpp.o), use for precompilator debuging only (prevent compilation to succeed) ; '-DLOG_LEVEL=LOG_LEVEL_TRACE' ; Enable trace level logging monitor_speed = 115200 From 9392ad069260e5f9b1c5b06bf1d02a19b21df861 Mon Sep 17 00:00:00 2001 From: Bad Date: Sat, 27 Aug 2022 11:52:19 +0200 Subject: [PATCH 15/17] Fix Code Format --- main/ZgatewayBT.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 22d71b7acb..c4de728d96 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -114,8 +114,9 @@ void BTConfig_init() { BTConfig.ignoreWBlist = false; } -// DO NOT put a SPACE between `template` AND `<` OR IT WON'T COMPILE: (OpenMQTTGateway/main/main.ino:x:y: error: 'T' has not been declared) -template +template // Declared here to avoid pre-compilation issue (missing "template" in auto declaration by pio) +void BTConfig_update(JsonObject& data, const char* key, T& var); +template void BTConfig_update(JsonObject& data, const char* key, T& var) { if (data.containsKey(key)) { if (var != data[key].as()) { @@ -351,9 +352,9 @@ void pubBT(JsonObject& data) { bool ProcessLock = false; // Process lock when we want to use a critical function like OTA for example -BLEdevice* getDeviceByMac(const char* mac); // Declared here to avoid pre-compilation issue (misplaced auto declaration by pio) void createOrUpdateDevice(const char* mac, uint8_t flags, int model, int mac_type = 0); +BLEdevice* getDeviceByMac(const char* mac); // Declared here to avoid pre-compilation issue (misplaced auto declaration by pio) BLEdevice* getDeviceByMac(const char* mac) { Log.trace(F("getDeviceByMac %s" CR), mac); From 3d6ef47782c0618bae5220544b9eb9d1a9aec652 Mon Sep 17 00:00:00 2001 From: Bad Date: Wed, 31 Aug 2022 08:22:17 +0200 Subject: [PATCH 16/17] Use Preference only for ESP32 --- main/ZgatewayBT.ino | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index c4de728d96..cc44c560e4 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -196,6 +196,7 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { } pub("/commands/BTtoMQTT/config", jo); +# if defined(ESP32) if (BTdata.containsKey("erase") && BTdata["erase"].as()) { // Erase config from NVS (non-volatile storage) preferences.begin(Gateway_Short_Name, false); @@ -214,8 +215,10 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { preferences.end(); Log.notice(F("BT config saved" CR)); } +# endif } +# if defined(ESP32) void BTConfig_load() { StaticJsonDocument jsonBuffer; preferences.begin(Gateway_Short_Name, true); @@ -234,6 +237,7 @@ void BTConfig_load() { BTConfig_fromJson(jo, true); // Never send mqtt message with config Log.notice(F("BT config loaded" CR)); } +# endif void pubBTMainCore(JsonObject& data, bool haPresenceEnabled = true) { if (abs((int)data["rssi"] | 0) < abs(BTConfig.minRssi) && data.containsKey("id")) { @@ -877,7 +881,6 @@ struct decompose d[6] = {{0, 12, true}, {12, 2, false}, {14, 2, false}, {16, 2, void setupBT() { BTConfig_init(); - BTConfig_load(); Log.notice(F("BLE interval: %d" CR), BTConfig.BLEinterval); Log.notice(F("BLE scans number before connect: %d" CR), BTConfig.BLEscanBeforeConnect); Log.notice(F("Publishing only BLE sensors: %T" CR), BTConfig.pubOnlySensors); @@ -1358,10 +1361,13 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding if (BTdata.containsKey("init") && BTdata["init"].as()) { // Restore the default (initial) configuration BTConfig_init(); - } else if (BTdata.containsKey("load") && BTdata["load"].as()) { + } +# ifdef ESP32 + else if (BTdata.containsKey("load") && BTdata["load"].as()) { // Load the saved configuration, if not initialised BTConfig_load(); } +# endif // Load config from json if available BTConfig_fromJson(BTdata); From 9448238592f60e33571353d313f6c5c7b0fafc4c Mon Sep 17 00:00:00 2001 From: Bad Date: Wed, 31 Aug 2022 16:51:25 +0200 Subject: [PATCH 17/17] Update Doc --- docs/use/ble.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/use/ble.md b/docs/use/ble.md index 570a9d6327..9ce8352b24 100644 --- a/docs/use/ble.md +++ b/docs/use/ble.md @@ -251,7 +251,7 @@ If you want to change the default behaviour: `mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"pubServiceDataUUID":true}'` -## Store BLE configuration into the gateway +## Store BLE configuration into the gateway (only with ESP32 boards) Open MQTT Gateway has the capability to save the current configuration and reload it at startup. @@ -268,7 +268,7 @@ If you want to erase the stored configuration, use the command: `mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"erase":true}'` Note that it will not change the running configuration, only ensure default configuration is used at next startup. -By the way, if you want to load the default built-in configuration, use the command: +By the way, if you want to load the default built-in configuration (on any board, not only ESP32), use the command: `mosquitto_pub -t home/OpenMQTTGateway/commands/MQTTtoBT/config -m '{"init":true}'` Note that it will not change the stored configuration, `erase` or `save` is still needed to overwrite the saved configuration.