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..9ce8352b24 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,83 @@ 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}'` + +## 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. + +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 (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. + ## 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. diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index 0d429ff46a..cc44c560e4 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,8 +93,154 @@ 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 = 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; + BTConfig.ignoreWBlist = false; +} + +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()) { + 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 + BTConfig_update(BTdata, "bleconnect", BTConfig.bleConnect); + // Scan interval set + if (BTdata.containsKey("interval") && BTdata["interval"] != 0) + BTConfig_update(BTdata, "interval", BTConfig.BLEinterval); + // Number of scan before a connect set + BTConfig_update(BTdata, "scanbcnct", BTConfig.BLEscanBeforeConnect); + // publish all BLE devices discovered or only the identified sensors (like temperature sensors) + BTConfig_update(BTdata, "onlysensors", BTConfig.pubOnlySensors); + // Home Assistant presence message + BTConfig_update(BTdata, "hasspresence", BTConfig.presenceEnable); + // Home Assistant presence message topic + BTConfig_update(BTdata, "presenceTopic", BTConfig.presenceTopic); + // Home Assistant presence message use iBeacon UUID + BTConfig_update(BTdata, "presenceUseBeaconUuid", BTConfig.presenceUseBeaconUuid); + // MinRSSI set + BTConfig_update(BTdata, "minrssi", BTConfig.minRssi); + // Send undecoded device data + BTConfig_update(BTdata, "extDecoderEnable", BTConfig.extDecoderEnable); + // Topic to send undecoded device data + BTConfig_update(BTdata, "extDecoderTopic", BTConfig.extDecoderTopic); + // Sets whether to filter publishing + BTConfig_update(BTdata, "filterConnectable", BTConfig.filterConnectable); + // Publish service data belonging to recognised sensors + BTConfig_update(BTdata, "pubKnownServiceData", BTConfig.pubKnownServiceData); + // Publish service data belonging to unrecognised sensors + BTConfig_update(BTdata, "pubUnknownServiceData", BTConfig.pubUnknownServiceData); + // Publish known manufacturer's data + BTConfig_update(BTdata, "pubKnownManufData", BTConfig.pubKnownManufData); + // Publish unknown manufacturer's data + BTConfig_update(BTdata, "pubUnknownManufData", BTConfig.pubUnknownManufData); + // Publish the service UUID data + BTConfig_update(BTdata, "pubServiceDataUUID", BTConfig.pubServiceDataUUID); + // Use iBeacon UUID as topic, instead of sender (random) MAC address + 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); + +# if defined(ESP32) + 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 skipping 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)); + } +# endif +} + +# if defined(ESP32) +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)); +} +# endif + 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") @@ -210,9 +356,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); 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); @@ -446,7 +592,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()) { @@ -625,8 +771,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); } @@ -672,10 +817,12 @@ 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); - 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 @@ -733,10 +880,11 @@ 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); - 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); @@ -818,10 +966,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) @@ -878,7 +1026,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 @@ -957,23 +1105,16 @@ 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")) { - 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); @@ -1018,7 +1159,7 @@ void process_bledata(JsonObject& BLEdata) { } } } - if (model_id < 0) { + if (!BTConfig.extDecoderEnable && model_id < 0) { Log.trace(F("No device found " CR)); } } @@ -1201,66 +1342,43 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding # endif } - // 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); + + /* + * 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(); } # 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); + 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); + +# ifdef ESP32 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 - 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); - } } } #endif diff --git a/main/config_BT.h b/main/config_BT.h index 52c28aa035..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 @@ -162,24 +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 -} 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, + bool ignoreWBlist; // Disable Whitelist & Blacklist }; // Global struct to store live BT configuration data 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