diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 492881f320..826514ebed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,6 +90,20 @@ jobs: run: | python -m pip install --upgrade pip pip install platformio + - name: Extract ESP32 platform version from platformio.ini + run: | + ESP32_VERSION=$(grep 'esp32_platform\s*=' platformio.ini | cut -d'@' -f2 | tr -d '[:space:]') + echo "ESP32_PLATFORM_VERSION=${ESP32_VERSION}" >> $GITHUB_ENV + - name: Trigger framework installation + run: platformio run -e esp32dev-all-test + - name: Replace libbtdm_app.a file + run: cp lib/esp32-bt-lib/esp32/libbtdm_app.a $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/libbtdm_app.a + - name: Verify file replacement + run: | + echo "Listing the file at the target location:" + ls -ltr $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/ + echo "Checking file checksum:" + md5sum $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/libbtdm_app.a - name: Run PlatformIO run: platformio run -e ${{ matrix.environments }} - name: Upload Assets diff --git a/.github/workflows/build_and_docs_to_dev.yml b/.github/workflows/build_and_docs_to_dev.yml index 0369a045a2..8a9ed55544 100644 --- a/.github/workflows/build_and_docs_to_dev.yml +++ b/.github/workflows/build_and_docs_to_dev.yml @@ -28,6 +28,20 @@ jobs: sed -i "s/version_tag/${{ steps.short-sha.outputs.sha }}/g" main/User_config.h scripts/latest_version_dev.json sed -i "s/version_tag/DEVELOPMENT SHA:${{ steps.short-sha.outputs.sha }} TEST ONLY/g" docs/.vuepress/config.js sed -i "s|base: '/'|base: '/dev/'|g" docs/.vuepress/config.js + - name: Extract ESP32 platform version from platformio.ini + run: | + ESP32_VERSION=$(grep 'esp32_platform\s*=' platformio.ini | cut -d'@' -f2 | tr -d '[:space:]') + echo "ESP32_PLATFORM_VERSION=${ESP32_VERSION}" >> $GITHUB_ENV + - name: Trigger framework installation + run: platformio run -e esp32dev-all-test + - name: Replace libbtdm_app.a file + run: cp lib/esp32-bt-lib/esp32/libbtdm_app.a $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/libbtdm_app.a + - name: Verify file replacement + run: | + echo "Listing the file at the target location:" + ls -ltr $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/ + echo "Checking file checksum:" + md5sum $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/libbtdm_app.a - name: Run PlatformIO run: | export PLATFORMIO_BUILD_FLAGS="'-DDEVELOPMENTOTA=true'" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 098d5b6566..62beb7b95f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,6 +20,20 @@ jobs: pip install platformio - name: Set version tag from git run: sed -i "s/version_tag/${GITHUB_REF#refs/tags/}/g" main/User_config.h scripts/latest_version.json + - name: Extract ESP32 platform version from platformio.ini + run: | + ESP32_VERSION=$(grep 'esp32_platform\s*=' platformio.ini | cut -d'@' -f2 | tr -d '[:space:]') + echo "ESP32_PLATFORM_VERSION=${ESP32_VERSION}" >> $GITHUB_ENV + - name: Trigger framework installation + run: platformio run -e esp32dev-all-test + - name: Replace libbtdm_app.a file + run: cp lib/esp32-bt-lib/esp32/libbtdm_app.a $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/libbtdm_app.a + - name: Verify file replacement + run: | + echo "Listing the file at the target location:" + ls -ltr $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/ + echo "Checking file checksum:" + md5sum $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/libbtdm_app.a - name: Run PlatformIO run: platformio run - name: Prepare Release Assets diff --git a/.gitignore b/.gitignore index 5f4cfe5ec4..5e077451a8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ node_modules *.ps1 main/certs/private* -lib \ No newline at end of file +lib/* +!lib/esp32-bt-lib diff --git a/lib/esp32-bt-lib/LICENSE b/lib/esp32-bt-lib/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/lib/esp32-bt-lib/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/README b/lib/esp32-bt-lib/README similarity index 100% rename from lib/README rename to lib/esp32-bt-lib/README diff --git a/lib/esp32-bt-lib/README.rst b/lib/esp32-bt-lib/README.rst new file mode 100644 index 0000000000..c554199031 --- /dev/null +++ b/lib/esp32-bt-lib/README.rst @@ -0,0 +1,10 @@ +ESP32 BT/BLE Stack Libraries +==================== + +This repository contains binary libraries supporting the ESP32 RF subsystems. It is used as a submodule within `Espressif IoT Development Framework`_ (ESP-IDF). + +Files in this repository are Copyright (C) 2015-2016 Espressif Systems. + +These binary libraries are provided under the same license as the parent esp-idf project - the Apache License 2.0 as provided in the file LICENSE. (The license text refers to this as "Object" form.) + +.. _Espressif IoT Development Framework: https://github.com/espressif/esp-idf diff --git a/lib/esp32-bt-lib/esp32/libbtdm_app.a b/lib/esp32-bt-lib/esp32/libbtdm_app.a new file mode 100644 index 0000000000..698cc64d36 Binary files /dev/null and b/lib/esp32-bt-lib/esp32/libbtdm_app.a differ diff --git a/main/User_config.h b/main/User_config.h index 5a3348c7c6..fe27ffce08 100644 --- a/main/User_config.h +++ b/main/User_config.h @@ -180,6 +180,12 @@ const byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0x54, 0x95}; //W5100 ethernet shield #ifndef GeneralTimeOut # define GeneralTimeOut 20 // time out if a task is stuck in seconds (should be more than TimeBetweenReadingRN8209/1000) and more than 3 seconds, the WDT will reset the ESP, used also for MQTT connection #endif +#ifndef QueueSemaphoreTimeOutTask +# define QueueSemaphoreTimeOutTask 3000 // time out for semaphore retrieval from a task +#endif +#ifndef QueueSemaphoreTimeOutLoop +# define QueueSemaphoreTimeOutLoop 100 // time out for semaphore retrieval from the loop +#endif #if defined(ESP8266) || defined(ESP32) // Uncomment to use a device running TheengsGateway to decode BLE data. (https://github.com/theengs/gateway) @@ -767,6 +773,10 @@ unsigned long lastDiscovery = 0; // Time of the last discovery to trigger automa # define isBlack(device) device->isBlkL # define isDiscovered(device) device->isDisc +/*--------------------Minimum freeHeap--------------------*/ +// Below this parameter we trigger a restart, this avoid stuck boards like seen in https://github.com/1technophile/OpenMQTTGateway/issues/1693 +# define MinimumMemory 40000 + /*----------------CONFIGURABLE PARAMETERS-----------------*/ struct SYSConfig_s { bool discovery; // HA discovery convention diff --git a/main/ZactuatorONOFF.ino b/main/ZactuatorONOFF.ino index 70067ade1f..540c2febec 100644 --- a/main/ZactuatorONOFF.ino +++ b/main/ZactuatorONOFF.ino @@ -304,6 +304,6 @@ void stateONOFFMeasures() { JsonObject ONOFFdata = jsonBuffer.to(); ONOFFdata["cmd"] = (int)digitalRead(ACTUATOR_ONOFF_GPIO); ONOFFdata["origin"] = subjectGTWONOFFtoMQTT; - enqueueJsonObject(ONOFFdata); + handleJsonEnqueue(ONOFFdata, QueueSemaphoreTimeOutTask); } #endif diff --git a/main/ZdisplaySSD1306.ino b/main/ZdisplaySSD1306.ino index 8b5b19999e..799690f093 100644 --- a/main/ZdisplaySSD1306.ino +++ b/main/ZdisplaySSD1306.ino @@ -467,7 +467,8 @@ String stateSSD1306Display() { DISPLAYdata["log-oled"] = (bool)logToOLEDDisplay; DISPLAYdata["json-oled"] = (bool)jsonDisplay; DISPLAYdata["origin"] = subjectSSD1306toMQTT; - enqueueJsonObject(DISPLAYdata); + handleJsonEnqueue(DISPLAYdata); + // apply Oled.display->setBrightness(round(displayBrightness * 2.55)); diff --git a/main/Zgateway2G.ino b/main/Zgateway2G.ino index df49cce6de..53530583dd 100644 --- a/main/Zgateway2G.ino +++ b/main/Zgateway2G.ino @@ -91,8 +91,7 @@ bool _2GtoMQTT() { A6l.deleteSMS(unreadSMSLocs[i]); // we delete the SMS received Log.trace(F("Adv data 2GtoMQTT" CR)); SMSdata["origin"] = subject2GtoMQTT; - enqueueJsonObject(SMSdata); - return true; + return handleJsonEnqueue(SMSdata); } return false; } diff --git a/main/ZgatewayBLEConnect.ino b/main/ZgatewayBLEConnect.ino index 4cbc05e41d..813ef2b510 100644 --- a/main/ZgatewayBLEConnect.ino +++ b/main/ZgatewayBLEConnect.ino @@ -121,7 +121,7 @@ bool zBLEConnect::processActions(std::vector& actions) { BLEdata["success"] = result; if (result || it.ttl <= 1) { buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } } } @@ -161,7 +161,7 @@ void LYWSD03MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pD BLEdata["volt"] = (float)(((pData[4] * 256) + pData[3]) / 1000.0); BLEdata["batt"] = (float)(((((pData[4] * 256) + pData[3]) / 1000.0) - 2.1) * 100); buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } else { Log.notice(F("Invalid notification data" CR)); return; @@ -226,7 +226,7 @@ void DT24_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, s BLEdata["tempc"] = (float)(m_data[24] * 256) + m_data[25]; BLEdata["tempf"] = (float)(convertTemp_CtoF((m_data[24] * 256) + m_data[25])); buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } else { Log.notice(F("Invalid notification data" CR)); return; @@ -303,7 +303,7 @@ void BM2_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* pData, si BLEdata["volt"] = volt; Log.trace(F("volt: %F" CR), volt); buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } else { Log.notice(F("Invalid notification data" CR)); return; @@ -361,7 +361,7 @@ void HHCCJCY01HHCC_connect::publishData() { BLEdata["id"] = (char*)mac_address.c_str(); BLEdata["batt"] = (int)batteryValue; buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } else { Log.notice(F("Failed getting characteristic" CR)); } @@ -393,7 +393,7 @@ void XMWSDJ04MMC_connect::notifyCB(NimBLERemoteCharacteristic* pChar, uint8_t* p BLEdata["volt"] = (float)((pData[4] | (pData[5] << 8)) / 1000.0); BLEdata["batt"] = (float)((((pData[4] | (pData[5] << 8)) / 1000.0) - 2.1) * 100); buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } else { Log.notice(F("Invalid notification data" CR)); return; @@ -490,7 +490,7 @@ bool SBS1_connect::processActions(std::vector& actions) { BLEdata["id"] = it.addr; BLEdata["state"] = result ? it.value : it.value == "on" ? "off" : "on"; buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } } } diff --git a/main/ZgatewayBT.ino b/main/ZgatewayBT.ino index e689410e6a..624ae0be15 100644 --- a/main/ZgatewayBT.ino +++ b/main/ZgatewayBT.ino @@ -103,23 +103,7 @@ void BTConfig_init() { BTConfig.ignoreWBlist = false; BTConfig.presenceAwayTimer = PresenceAwayTimer; BTConfig.movingTimer = MovingTimer; -} - -// Watchdog, if there was no change of BLE scanCount, restart the ESP -void btScanWDG() { - static unsigned long previousBtScanCount = 0; - static unsigned long lastBtScan = 0; - unsigned long now = millis(); - if (!ProcessLock && - previousBtScanCount == scanCount && - scanCount != 0 && - (now - lastBtScan > ((BTConfig.BLEinterval + BTConfig.scanDuration) < GeneralTimeOut ? GeneralTimeOut + 1000 : (BTConfig.BLEinterval + BTConfig.scanDuration)))) { - Log.error(F("BLE Scan watchdog triggered at : %ds" CR), lastBtScan / 1000); - ESPRestart(4); - } else { - previousBtScanCount = scanCount; - lastBtScan = now; - } + BTConfig.forcePassiveScan = false; } unsigned long timeBetweenConnect = 0; @@ -148,6 +132,7 @@ String stateBTMeasures(bool start) { jo["ignoreWBlist"] = BTConfig.ignoreWBlist; jo["presenceawaytimer"] = BTConfig.presenceAwayTimer; jo["movingtimer"] = BTConfig.movingTimer; + jo["forcepassivescan"] = BTConfig.forcePassiveScan; jo["bletaskstack"] = uxTaskGetStackHighWaterMark(xProcBLETaskHandle); jo["blecoretaskstack"] = uxTaskGetStackHighWaterMark(xCoreTaskHandle); @@ -160,7 +145,7 @@ String stateBTMeasures(bool start) { String output; serializeJson(jo, output); jo["origin"] = subjectBTtoMQTT; - enqueueJsonObject(jo); + handleJsonEnqueue(jo, QueueSemaphoreTimeOutTask); return (output); } @@ -224,6 +209,8 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { Config_update(BTdata, "presenceawaytimer", BTConfig.presenceAwayTimer); // Timer to trigger a device state as offline if not seen Config_update(BTdata, "movingtimer", BTConfig.movingTimer); + // Force passive scan + Config_update(BTdata, "forcepassivescan", BTConfig.forcePassiveScan); // MinRSSI set Config_update(BTdata, "minrssi", BTConfig.minRssi); // Send undecoded device data @@ -278,6 +265,7 @@ void BTConfig_fromJson(JsonObject& BTdata, bool startup = false) { jo["ignoreWBlist"] = BTConfig.ignoreWBlist; jo["presenceawaytimer"] = BTConfig.presenceAwayTimer; jo["movingtimer"] = BTConfig.movingTimer; + jo["forcepassivescan"] = BTConfig.forcePassiveScan; // Save config into NVS (non-volatile storage) String conf = ""; serializeJson(jsonBuffer, conf); @@ -418,7 +406,7 @@ void updateDevicesStatus() { BLEdata["id"] = p->macAdr; BLEdata["state"] = "offline"; buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); // We set the lastUpdate to 0 to avoid replublishing the offline state p->lastUpdate = 0; } @@ -432,7 +420,7 @@ void updateDevicesStatus() { BLEdata["id"] = p->macAdr; BLEdata["state"] = "offline"; buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); // We set the lastUpdate to 0 to avoid replublishing the offline state p->lastUpdate = 0; } @@ -668,7 +656,7 @@ void BLEscan() { BLEScan* pBLEScan = BLEDevice::getScan(); MyAdvertisedDeviceCallbacks myCallbacks; pBLEScan->setAdvertisedDeviceCallbacks(&myCallbacks); - if (millis() > (timeBetweenActive + BTConfig.intervalActiveScan) || BTConfig.intervalActiveScan == BTConfig.BLEinterval) { + if ((millis() > (timeBetweenActive + BTConfig.intervalActiveScan) || BTConfig.intervalActiveScan == BTConfig.BLEinterval) && !BTConfig.forcePassiveScan) { pBLEScan->setActiveScan(true); timeBetweenActive = millis(); } else { @@ -756,17 +744,18 @@ void BLEconnect() { void stopProcessing() { ProcessLock = true; // We stop the scan + Log.notice(F("Stopping BLE scan" CR)); BLEScan* pBLEScan = BLEDevice::getScan(); if (pBLEScan->isScanning()) { pBLEScan->stop(); } + Log.notice(F("Stopping BLE tasks" CR)); //Suspending, deleting tasks and stopping BT to free memory vTaskSuspend(xCoreTaskHandle); vTaskDelete(xCoreTaskHandle); vTaskSuspend(xProcBLETaskHandle); vTaskDelete(xProcBLETaskHandle); - if (BLEDevice::getInitialized()) BLEDevice::deinit(true); - Log.notice(F("BLE gateway stopped, free heap: %d" CR), ESP.getFreeHeap()); + Log.notice(F("BLE gateway stopped %T, free heap: %d" CR), ESP.getFreeHeap()); } void coreTask(void* pvParameters) { @@ -787,7 +776,7 @@ void coreTask(void* pvParameters) { timeBetweenConnect = millis(); BLEconnect(); } - dumpDevices(); + //dumpDevices(); Log.trace(F("CoreTask stack free: %u" CR), uxTaskGetStackHighWaterMark(xCoreTaskHandle)); xSemaphoreGive(semaphoreBLEOperation); } else { @@ -901,6 +890,7 @@ void setupBT() { Log.notice(F("Low Power Mode: %d" CR), lowpowermode); Log.notice(F("Presence Away Timer: %d" CR), BTConfig.presenceAwayTimer); Log.notice(F("Moving Timer: %d" CR), BTConfig.movingTimer); + Log.notice(F("Force passive scan: %T" CR), BTConfig.forcePassiveScan); atomic_init(&forceBTScan, 0); // in theory, we don't need this @@ -936,7 +926,7 @@ boolean valid_service_data(const char* data, int size) { void launchBTDiscovery(bool overrideDiscovery) { if (!overrideDiscovery && newDevices == 0) return; - if (xSemaphoreTake(semaphoreCreateOrUpdateDevice, pdMS_TO_TICKS(1000)) == pdFALSE) { + if (xSemaphoreTake(semaphoreCreateOrUpdateDevice, pdMS_TO_TICKS(QueueSemaphoreTimeOutTask)) == pdFALSE) { Log.error(F("Semaphore NOT taken" CR)); return; } @@ -1136,7 +1126,7 @@ void PublishDeviceData(JsonObject& BLEdata) { // If the device is not a sensor and pubOnlySensors is true we don't publish this payload if (!BTConfig.pubOnlySensors || BLEdata.containsKey("model") || BLEdata.containsKey("distance")) { // Identified device buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } else { Log.notice(F("Not a sensor device filtered" CR)); return; @@ -1152,7 +1142,7 @@ void PublishDeviceData(JsonObject& BLEdata) { BLEdata["mac"] = BLEdata["id"]; BLEdata["id"] = BLEdata["uuid"]; } - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); } else { Log.notice(F("Low rssi, device filtered" CR)); return; @@ -1298,7 +1288,7 @@ void immediateBTAction(void* pvParameters) { BLEdata["id"] = BLEactions.back().addr; BLEdata["success"] = false; buildTopicFromId(BLEdata, subjectBTtoMQTT); - enqueueJsonObject(BLEdata); + handleJsonEnqueue(BLEdata, QueueSemaphoreTimeOutTask); BLEactions.pop_back(); ProcessLock = false; } @@ -1397,8 +1387,8 @@ void MQTTtoBT(char* topicOri, JsonObject& BTdata) { // json object decoding WorBupdated |= updateWorB(BTdata, false); if (WorBupdated) { - if (xSemaphoreTake(semaphoreCreateOrUpdateDevice, pdMS_TO_TICKS(1000)) == pdTRUE) { - dumpDevices(); + if (xSemaphoreTake(semaphoreCreateOrUpdateDevice, pdMS_TO_TICKS(QueueSemaphoreTimeOutTask)) == pdTRUE) { + //dumpDevices(); xSemaphoreGive(semaphoreCreateOrUpdateDevice); } } diff --git a/main/ZgatewayGFSunInverter.ino b/main/ZgatewayGFSunInverter.ino index f9e339012c..16caa4eee1 100644 --- a/main/ZgatewayGFSunInverter.ino +++ b/main/ZgatewayGFSunInverter.ino @@ -59,7 +59,7 @@ void GFSunInverterDataHandler(GfSun2000Data data) { jdata["register"] = jregister; # endif jdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(jdata); + handleJsonEnqueue(jdata); } void GFSunInverterErrorHandler(int errorId, char* errorMessage) { @@ -72,7 +72,7 @@ void GFSunInverterErrorHandler(int errorId, char* errorMessage) { jdata["msg"] = errorMessage; jdata["id"] = errorId; jdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(jdata); + handleJsonEnqueue(jdata); } void setupGFSunInverter() { diff --git a/main/ZgatewayIR.ino b/main/ZgatewayIR.ino index 89f9b5eb1b..2882fcb9eb 100644 --- a/main/ZgatewayIR.ino +++ b/main/ZgatewayIR.ino @@ -169,7 +169,7 @@ void IRtoMQTT() { } else if (!isAduplicateSignal(MQTTvalue) && MQTTvalue != 0) { // conditions to avoid duplications of IR -->MQTT Log.trace(F("Adv data IRtoMQTT" CR)); IRdata["origin"] = subjectIRtoMQTT; - enqueueJsonObject(IRdata); + handleJsonEnqueue(IRdata); Log.trace(F("Store val: %D" CR), MQTTvalue); storeSignalValue(MQTTvalue); if (repeatIRwMQTT) { diff --git a/main/ZgatewayLORA.ino b/main/ZgatewayLORA.ino index f0416e99bb..0edacdba74 100644 --- a/main/ZgatewayLORA.ino +++ b/main/ZgatewayLORA.ino @@ -105,7 +105,7 @@ void createOrUpdateDeviceLORA(const char* id, const char* model, uint8_t flags) void launchLORADiscovery(bool overrideDiscovery) { if (!overrideDiscovery && newLORADevices == 0) return; - if (xSemaphoreTake(semaphorecreateOrUpdateDeviceLORA, pdMS_TO_TICKS(1000)) == pdFALSE) { + if (xSemaphoreTake(semaphorecreateOrUpdateDeviceLORA, pdMS_TO_TICKS(QueueSemaphoreTimeOutLoop)) == pdFALSE) { Log.error(F("[LORA] semaphorecreateOrUpdateDeviceLORA Semaphore NOT taken" CR)); return; } @@ -453,12 +453,11 @@ void LORAtoMQTT() { } else { LORAdataBuffer["origin"] = subjectLORAtoMQTT; } - enqueueJsonObject(LORAdata); - + handleJsonEnqueue(LORAdata); if (repeatLORAwMQTT) { Log.trace(F("Pub LORA for rpt" CR)); LORAdata["origin"] = subjectMQTTtoLORA; - enqueueJsonObject(LORAdata); + handleJsonEnqueue(LORAdata); } } } diff --git a/main/ZgatewayPilight.ino b/main/ZgatewayPilight.ino index 316c5ca753..563a8f4536 100644 --- a/main/ZgatewayPilight.ino +++ b/main/ZgatewayPilight.ino @@ -81,11 +81,11 @@ void pilightCallback(const String& protocol, const String& message, int status, RFPiLightdata["repeats"] = (int)repeats; RFPiLightdata["status"] = (int)status; RFPiLightdata["origin"] = subjectPilighttoMQTT; - enqueueJsonObject(RFPiLightdata); + handleJsonEnqueue(RFPiLightdata); if (repeatPilightwMQTT) { Log.trace(F("Pub Pilight for rpt" CR)); RFPiLightdata["origin"] = subjectMQTTtoPilight; - enqueueJsonObject(RFPiLightdata); + handleJsonEnqueue(RFPiLightdata); } } } @@ -108,7 +108,7 @@ void pilightRawCallback(const uint16_t* pulses, size_t length) { // Enqueue data RFPiLightdata["origin"] = subjectPilighttoMQTT; - enqueueJsonObject(RFPiLightdata); + handleJsonEnqueue(RFPiLightdata); } # endif @@ -273,7 +273,7 @@ void MQTTtoPilight(char* topicOri, JsonObject& Pilightdata) { if (msgLength > 0) { Log.trace(F("Adv data MQTTtoPilight push state via PilighttoMQTT" CR)); Pilightdata["origin"] = subjectGTWPilighttoMQTT; - enqueueJsonObject(Pilightdata); + handleJsonEnqueue(Pilightdata); success = true; } else { switch (msgLength) { diff --git a/main/ZgatewayRF.ino b/main/ZgatewayRF.ino index f5eeb8797d..a1cab918de 100644 --- a/main/ZgatewayRF.ino +++ b/main/ZgatewayRF.ino @@ -171,14 +171,14 @@ void RFtoMQTT() { RFtoMQTTdiscovery(MQTTvalue); # endif RFdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(RFdata); + handleJsonEnqueue(RFdata); // Casting "receivedSignal[o].value" to (unsigned long) because ArduinoLog doesn't support uint64_t for ESP's Log.trace(F("Store val: %u" CR), (unsigned long)MQTTvalue); storeSignalValue(MQTTvalue); if (repeatRFwMQTT) { Log.trace(F("Pub RF for rpt" CR)); RFdata["origin"] = subjectMQTTtoRF; - enqueueJsonObject(RFdata); + handleJsonEnqueue(RFdata); } } } diff --git a/main/ZgatewayRF2.ino b/main/ZgatewayRF2.ino index f10b78fad7..76c41871a5 100644 --- a/main/ZgatewayRF2.ino +++ b/main/ZgatewayRF2.ino @@ -133,7 +133,7 @@ void RF2toMQTT() { RF2toMQTTdiscovery(RF2data); # endif RF2data["origin"] = subjectRF2toMQTT; - enqueueJsonObject(RF2data); + handleJsonEnqueue(RF2data); } } diff --git a/main/ZgatewayRFM69.ino b/main/ZgatewayRFM69.ino index 998d4c37b9..c9aa0590ad 100644 --- a/main/ZgatewayRFM69.ino +++ b/main/ZgatewayRFM69.ino @@ -216,7 +216,7 @@ void MQTTtoRFM69(char* topicOri, JsonObject& RFM69data) { Log.notice(F(" OK " CR)); // Acknowledgement to the GTWRF topic RFM69data["origin"] = subjectGTWRFM69toMQTT; - enqueueJsonObject(RFM69data); + handleJsonEnqueue(RFM69data); } else { Log.error(F("MQTTtoRFM69 sending failed" CR)); } diff --git a/main/ZgatewayRTL_433.ino b/main/ZgatewayRTL_433.ino index ae87908a69..925c285ec9 100644 --- a/main/ZgatewayRTL_433.ino +++ b/main/ZgatewayRTL_433.ino @@ -108,7 +108,7 @@ void createOrUpdateDeviceRTL_433(const char* id, const char* model, uint8_t flag void launchRTL_433Discovery(bool overrideDiscovery) { if (!overrideDiscovery && newRTL_433Devices == 0) return; - if (xSemaphoreTake(semaphorecreateOrUpdateDeviceRTL_433, pdMS_TO_TICKS(1000)) == pdFALSE) { + if (xSemaphoreTake(semaphorecreateOrUpdateDeviceRTL_433, pdMS_TO_TICKS(QueueSemaphoreTimeOutLoop)) == pdFALSE) { Log.error(F("[rtl_433] semaphorecreateOrUpdateDeviceRTL_433 Semaphore NOT taken" CR)); return; } @@ -258,7 +258,7 @@ void rtl_433_Callback(char* message) { storeRTL_433Discovery(RFrtl_433_ESPdata, (char*)model.c_str(), (char*)uniqueid.c_str()); # endif RFrtl_433_ESPdata["origin"] = (char*)topic.c_str(); - enqueueJsonObject(RFrtl_433_ESPdata); + handleJsonEnqueue(RFrtl_433_ESPdata); storeSignalValue(MQTTvalue); pubOled((char*)topic.c_str(), RFrtl_433_ESPdata); } diff --git a/main/ZgatewaySRFB.ino b/main/ZgatewaySRFB.ino index cadfa32840..558fef16fa 100644 --- a/main/ZgatewaySRFB.ino +++ b/main/ZgatewaySRFB.ino @@ -121,13 +121,13 @@ void _rfbDecode() { if (!isAduplicateSignal(MQTTvalue) && MQTTvalue != 0) { // conditions to avoid duplications of RF -->MQTT Log.trace(F("Adv data SRFBtoMQTT" CR)); SRFBdata["origin"] = subjectSRFBtoMQTT; - enqueueJsonObject(SRFBdata); + handleJsonEnqueue(SRFBdata); Log.trace(F("Store val: %lu" CR), MQTTvalue); storeSignalValue(MQTTvalue); if (repeatSRFBwMQTT) { Log.trace(F("Publish SRFB for rpt" CR)); SRFBdata["origin"] = subjectMQTTtoSRFB; - enqueueJsonObject(SRFBdata); + handleJsonEnqueue(SRFBdata); } } _rfbAck(); diff --git a/main/ZgatewayWeatherStation.ino b/main/ZgatewayWeatherStation.ino index 2796d4cd24..e177aa21c5 100644 --- a/main/ZgatewayWeatherStation.ino +++ b/main/ZgatewayWeatherStation.ino @@ -41,7 +41,7 @@ void PairedDeviceAdded(byte newID) { RFdata["sensor"] = newID; RFdata["action"] = "paired"; RFdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(RFdata); + handleJsonEnqueue(RFdata); wsdr.pair(NULL, PairedDeviceAdded); } @@ -61,7 +61,7 @@ void sendWindSpeedData(byte id, float wind_speed, byte battery_status) { RFdata["wind_speed"] = wind_speed; RFdata["battery"] = bitRead(battery_status, 0) == 0 ? "OK" : "Low"; RFdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(RFdata); + handleJsonEnqueue(RFdata); Log.trace(F("Store wind speed val: %lu" CR), MQTTvalue); storeSignalValue(MQTTvalue); } @@ -76,7 +76,7 @@ void sendRainData(byte id, float rain_volume, byte battery_status) { RFdata["rain_volume"] = rain_volume; RFdata["battery"] = bitRead(battery_status, 1) == 0 ? "OK" : "Low"; RFdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(RFdata); + handleJsonEnqueue(RFdata); Log.trace(F("Store rain_volume: %lu" CR), MQTTvalue); storeSignalValue(MQTTvalue); } @@ -92,7 +92,7 @@ void sendWindData(byte id, int wind_direction, float wind_gust, byte battery_sta RFdata["wind_gust"] = wind_gust; RFdata["battery"] = bitRead(battery_status, 0) == 0 ? "OK" : "Low"; RFdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(RFdata); + handleJsonEnqueue(RFdata); Log.trace(F("Store wind data val: %lu" CR), MQTTvalue); storeSignalValue(MQTTvalue); } @@ -109,7 +109,7 @@ void sendTemperatureData(byte id, float temperature, int humidity, byte battery_ RFdata["humidity"] = humidity; RFdata["battery"] = bitRead(battery_status, 0) == 0 ? "OK" : "Low"; RFdata["origin"] = subjectRFtoMQTT; - enqueueJsonObject(RFdata); + handleJsonEnqueue(RFdata); Log.trace(F("Store temp val: %lu" CR), MQTTvalue); storeSignalValue(MQTTvalue); } diff --git a/main/ZmqttDiscovery.ino b/main/ZmqttDiscovery.ino index 3a5c386e22..f5a2886a0a 100644 --- a/main/ZmqttDiscovery.ino +++ b/main/ZmqttDiscovery.ino @@ -502,7 +502,7 @@ void pubMqttDiscovery() { "{\"discovery\":true,\"save\":true}", "{\"discovery\":false,\"save\":true}", "", //set,payload_on,payload_off,unit_of_meas, 0, //set off_delay Gateway_AnnouncementMsg, will_Message, true, subjectMQTTtoSYSset, //set,payload_avalaible,payload_not avalaible ,is a gateway entity, command topic - "", "", "", "", true, // device name, device manufacturer, device model, device MAC, retain, + "", "", "", "", false, // device name, device manufacturer, device model, device MAC, retain, stateClassNone, //State Class "false", "true" //state_off, state_on ); diff --git a/main/ZsensorADC.ino b/main/ZsensorADC.ino index 6c3d445bbc..00b4a68063 100644 --- a/main/ZsensorADC.ino +++ b/main/ZsensorADC.ino @@ -94,7 +94,7 @@ void MeasureADC() { ADCdata["mvolt_scaled"] = (int)voltage; // real scaled/calibrated value in mV # endif ADCdata["origin"] = ADCTOPIC; - enqueueJsonObject(ADCdata); + handleJsonEnqueue(ADCdata); persistedadc = val; } } diff --git a/main/ZsensorAHTx0.ino b/main/ZsensorAHTx0.ino index 5407fbaf9c..16af5ed273 100644 --- a/main/ZsensorAHTx0.ino +++ b/main/ZsensorAHTx0.ino @@ -104,7 +104,7 @@ void MeasureAHTTempHum() { Log.notice(F("Same Humidity. Don't send it" CR)); } AHTx0data["origin"] = AHTTOPIC; - enqueueJsonObject(AHTx0data); + handleJsonEnqueue(AHTx0data); } persisted_aht_tempc = ahtTempC.temperature; persisted_aht_hum = ahtHum.relative_humidity; diff --git a/main/ZsensorBH1750.ino b/main/ZsensorBH1750.ino index 41e31b8003..aca97bb309 100644 --- a/main/ZsensorBH1750.ino +++ b/main/ZsensorBH1750.ino @@ -101,7 +101,7 @@ void MeasureLightIntensity() { Log.trace(F("Same wattsm2 don't send it" CR)); } BH1750data["origin"] = subjectBH1750toMQTT; - enqueueJsonObject(BH1750data); + handleJsonEnqueue(BH1750data); } persistedll = Lux; persistedlf = ftcd; diff --git a/main/ZsensorBME280.ino b/main/ZsensorBME280.ino index 075d5c72d4..00887300a9 100644 --- a/main/ZsensorBME280.ino +++ b/main/ZsensorBME280.ino @@ -192,7 +192,7 @@ void MeasureTempHumAndPressure() { Log.trace(F("Same Altitude Feet don't send it" CR)); } BME280data["origin"] = BMETOPIC; - enqueueJsonObject(BME280data); + handleJsonEnqueue(BME280data); } persisted_bme_tempc = BmeTempC; diff --git a/main/ZsensorC37_YL83_HMRD.ino b/main/ZsensorC37_YL83_HMRD.ino index a6a58c13b6..b93addaee2 100644 --- a/main/ZsensorC37_YL83_HMRD.ino +++ b/main/ZsensorC37_YL83_HMRD.ino @@ -67,7 +67,7 @@ void MeasureC37_YL83_HMRDWater() { } if (C37_YL83_HMRDdata.size() > 0) { C37_YL83_HMRDdata["origin"] = C37_YL83_HMRD_TOPIC; - enqueueJsonObject(C37_YL83_HMRDdata); + handleJsonEnqueue(C37_YL83_HMRDdata); delay(10); # if defined(DEEP_SLEEP_IN_US) || defined(ESP32_EXT0_WAKE_PIN) if (sensorDigitalValue == 1) //No water detected, all good we can sleep diff --git a/main/ZsensorDHT.ino b/main/ZsensorDHT.ino index 37fe74a106..70c72c0278 100644 --- a/main/ZsensorDHT.ino +++ b/main/ZsensorDHT.ino @@ -69,7 +69,7 @@ void MeasureTempAndHum() { Log.trace(F("Same temp don't send it" CR)); } DHTdata["origin"] = DHTTOPIC; - enqueueJsonObject(DHTdata); + handleJsonEnqueue(DHTdata); } persistedh = h; persistedt = t; diff --git a/main/ZsensorDS1820.ino b/main/ZsensorDS1820.ino index 86c06323e9..4c55bc566a 100644 --- a/main/ZsensorDS1820.ino +++ b/main/ZsensorDS1820.ino @@ -158,7 +158,7 @@ void MeasureDS1820Temp() { } String origin = String(OW_TOPIC) + "/" + ds1820_addr[i]; DS1820data["origin"] = origin; - enqueueJsonObject(DS1820data); + handleJsonEnqueue(DS1820data); delay(10); # if defined(DEEP_SLEEP_IN_US) || defined(ESP32_EXT0_WAKE_PIN) ready_to_sleep = true; diff --git a/main/ZsensorGPIOInput.ino b/main/ZsensorGPIOInput.ino index 3c34c12243..41e9ef0283 100644 --- a/main/ZsensorGPIOInput.ino +++ b/main/ZsensorGPIOInput.ino @@ -94,7 +94,7 @@ void MeasureGPIOInput() { GPIOdata["gpio"] = "LOW"; } GPIOdata["origin"] = subjectGPIOInputtoMQTT; - enqueueJsonObject(GPIOdata); + handleJsonEnqueue(GPIOdata); # if defined(ZactuatorONOFF) && defined(ACTUATOR_TRIGGER) //Trigger the actuator if we are not at startup diff --git a/main/ZsensorHCSR04.ino b/main/ZsensorHCSR04.ino index 8db843621f..eed7840013 100644 --- a/main/ZsensorHCSR04.ino +++ b/main/ZsensorHCSR04.ino @@ -69,8 +69,7 @@ void MeasureDistance() { Log.trace(F("HC SR04 Distance hasn't changed" CR)); } distance = d; - HCSR04data["origin"] = subjectHCSR04; - enqueueJsonObject(HCSR04data); + handleJsonEnqueue(HCSR04data); } } } diff --git a/main/ZsensorHCSR501.ino b/main/ZsensorHCSR501.ino index 0af5950f01..984bd78486 100644 --- a/main/ZsensorHCSR501.ino +++ b/main/ZsensorHCSR501.ino @@ -65,7 +65,7 @@ void MeasureHCSR501() { digitalWrite(HCSR501_LED_NOTIFY_GPIO, pirState == HCSR501_LED_ON); # endif HCSR501data["origin"] = subjectHCSR501toMQTT; - enqueueJsonObject(HCSR501data); + handleJsonEnqueue(HCSR501data); } } #endif diff --git a/main/ZsensorHTU21.ino b/main/ZsensorHTU21.ino index 44dbb435c0..7b6445c4d2 100644 --- a/main/ZsensorHTU21.ino +++ b/main/ZsensorHTU21.ino @@ -101,7 +101,7 @@ void MeasureTempHum() { Log.notice(F("Same Humidity. Don't send it" CR)); } HTU21data["origin"] = HTUTOPIC; - enqueueJsonObject(HTU21data); + handleJsonEnqueue(HTU21data); } persisted_htu_tempc = HtuTempC; persisted_htu_hum = HtuHum; diff --git a/main/ZsensorINA226.ino b/main/ZsensorINA226.ino index 36932f41a3..ce2146eb03 100644 --- a/main/ZsensorINA226.ino +++ b/main/ZsensorINA226.ino @@ -73,7 +73,7 @@ void MeasureINA226() { INA226data["current"] = current; INA226data["power"] = power; INA226data["origin"] = subjectINA226toMQTT; - enqueueJsonObject(INA226data); + handleJsonEnqueue(INA226data); } } diff --git a/main/ZsensorLM75.ino b/main/ZsensorLM75.ino index 29d289a8d8..b30080a868 100644 --- a/main/ZsensorLM75.ino +++ b/main/ZsensorLM75.ino @@ -88,7 +88,7 @@ void MeasureTemp() { LM75data["tempc"] = (float)lm75TempC; LM75data["tempf"] = (float)lm75TempF; LM75data["origin"] = LM75TOPIC; - enqueueJsonObject(LM75data); + handleJsonEnqueue(LM75data); } else { Log.notice(F("Same Temp. Don't send it" CR)); } diff --git a/main/ZsensorMQ2.ino b/main/ZsensorMQ2.ino index 53e4401a3e..e3b00f01a6 100644 --- a/main/ZsensorMQ2.ino +++ b/main/ZsensorMQ2.ino @@ -67,7 +67,7 @@ void MeasureGasMQ2() { MQ2data["gas"] = analogRead(MQ2SENSORADCPIN); MQ2data["detected"] = digitalRead(MQ2SENSORDETECTPIN) == HIGH ? "false" : "true"; MQ2data["origin"] = subjectMQ2toMQTT; - enqueueJsonObject(MQ2data); + handleJsonEnqueue(MQ2data); } } #endif diff --git a/main/ZsensorRN8209.ino b/main/ZsensorRN8209.ino index 1b56282a19..61ad1a9cdc 100644 --- a/main/ZsensorRN8209.ino +++ b/main/ZsensorRN8209.ino @@ -91,7 +91,7 @@ void rn8209_loop(void* mode) { previousCurrent = current; if (RN8209data) { RN8209data["origin"] = subjectRN8209toMQTT; - enqueueJsonObject(RN8209data); + handleJsonEnqueue(RN8209data, QueueSemaphoreTimeOutTask); } } //esp_task_wdt_reset(); diff --git a/main/ZsensorSHTC3.ino b/main/ZsensorSHTC3.ino index 7deb25bb55..040551e706 100644 --- a/main/ZsensorSHTC3.ino +++ b/main/ZsensorSHTC3.ino @@ -61,7 +61,7 @@ void MeasureTempAndHum() { Log.trace(F("Same temp don't send it" CR)); } SHTC3data["origin"] = SHTC3TOPIC; - enqueueJsonObject(SHTC3data); + handleJsonEnqueue(SHTC3data); } persistedh = h; persistedt = t; diff --git a/main/ZsensorTEMT6000.ino b/main/ZsensorTEMT6000.ino index f639a09be6..a83e9be2cc 100644 --- a/main/ZsensorTEMT6000.ino +++ b/main/ZsensorTEMT6000.ino @@ -68,7 +68,7 @@ void MeasureLightIntensityTEMT6000() { TEMT6000data["ftcd"] = (float)(lux) / 10.764; TEMT6000data["wattsm2"] = (float)(lux) / 683.0; TEMT6000data["origin"] = subjectTEMT6000toMQTT; - enqueueJsonObject(TEMT6000data); + handleJsonEnqueue(TEMT6000data); } else { Log.trace(F("Same lux value, do not send" CR)); } diff --git a/main/ZsensorTSL2561.ino b/main/ZsensorTSL2561.ino index 2e35fe722a..c1063bee9e 100644 --- a/main/ZsensorTSL2561.ino +++ b/main/ZsensorTSL2561.ino @@ -105,7 +105,7 @@ void MeasureLightIntensityTSL2561() { TSL2561data["ftcd"] = (float)(event.light) / 10.764; TSL2561data["wattsm2"] = (float)(event.light) / 683.0; TSL2561data["origin"] = subjectTSL12561toMQTT; - enqueueJsonObject(TSL2561data); + handleJsonEnqueue(TSL2561data); } else { Log.trace(F("Same lux value, do not send" CR)); } diff --git a/main/ZwebUI.ino b/main/ZwebUI.ino index 3ba8fad57f..62c1206050 100644 --- a/main/ZwebUI.ino +++ b/main/ZwebUI.ino @@ -1589,7 +1589,7 @@ String stateWebUIStatus() { // WebUIdata["currentMessage"] = currentWebUIMessage; WebUIdata["origin"] = subjectWebUItoMQTT; - enqueueJsonObject(WebUIdata); + handleJsonEnqueue(WebUIdata); return output; } diff --git a/main/config_BT.h b/main/config_BT.h index 3857367f64..16ee27c1fc 100644 --- a/main/config_BT.h +++ b/main/config_BT.h @@ -165,6 +165,7 @@ struct BTConfig_s { bool ignoreWBlist; // Disable Whitelist & Blacklist unsigned long presenceAwayTimer; //Timer that trigger a tracker/PIR state as offline/off if not seen unsigned long movingTimer; //Timer that trigger a moving sensor state as offline if not seen + bool forcePassiveScan; //Force passive scan }; // Global struct to store live BT configuration data diff --git a/main/main.ino b/main/main.ino index 762b18d4b4..4908fc1d7a 100644 --- a/main/main.ino +++ b/main/main.ino @@ -92,6 +92,12 @@ struct JsonBundle { }; std::queue jsonQueue; + +# ifdef ESP32 +// Mutex to protect the queue +SemaphoreHandle_t xQueueMutex; +# endif + #endif StaticJsonDocument modulesBuffer; @@ -450,6 +456,30 @@ void enqueueJsonObject(const StaticJsonDocument& jsonDoc) { #endif } +#ifdef ESP32 +// Semaphore check before enqueueing a document +bool handleJsonEnqueue(const StaticJsonDocument& jsonDoc, int timeout) { + if (xSemaphoreTake(xQueueMutex, pdMS_TO_TICKS(timeout))) { + enqueueJsonObject(jsonDoc); + xSemaphoreGive(xQueueMutex); + return true; + } else { + Log.error(F("xQueueMutex not taken" CR)); + blockedMessages++; + return false; + } +} +#else +bool handleJsonEnqueue(const StaticJsonDocument& jsonDoc, int timeout) { + enqueueJsonObject(jsonDoc); +} +#endif + +// Semaphore check before enqueueing a document with default timeout QueueSemaphoreTimeOutLoop +bool handleJsonEnqueue(const StaticJsonDocument& jsonDoc) { + return handleJsonEnqueue(jsonDoc, QueueSemaphoreTimeOutLoop); +} + #if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) /* @@ -1029,6 +1059,7 @@ void setup() { Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY); // enable on ESP8266 to free some pin # endif # elif ESP32 + xQueueMutex = xSemaphoreCreateMutex(); # if DEFAULT_LOW_POWER_MODE != -1 // don't check preferences value if low power mode is not activated preferences.begin(Gateway_Short_Name, false); if (preferences.isKey("lowpowermode")) { @@ -1477,6 +1508,7 @@ bool wifi_reconnect_bypass() { 5 - User requested reboot 6 - OTA Update 7 - Parameters changed + 8 - not enough memory to pursue */ #if defined(ESP8266) || defined(ESP32) void ESPRestart(byte reason) { @@ -2042,7 +2074,6 @@ void loop() { stateMeasures(); # ifdef ZgatewayBT stateBTMeasures(false); - btScanWDG(); # endif # ifdef ZactuatorONOFF stateONOFFMeasures(); @@ -2348,6 +2379,9 @@ String stateMeasures() { uint32_t freeMem; uint32_t minFreeMem; freeMem = ESP.getFreeHeap(); + if (freeMem < MinimumMemory) { + ESPRestart(8); + } SYSdata["freemem"] = freeMem; SYSdata["mqttport"] = mqtt_port; SYSdata["mqttsecure"] = mqtt_secure; @@ -2428,7 +2462,7 @@ String stateMeasures() { SYSdata["modules"] = modules; SYSdata["origin"] = subjectSYStoMQTT; - enqueueJsonObject(SYSdata); + handleJsonEnqueue(SYSdata); pubOled(subjectSYStoMQTT, SYSdata); char jsonChar[100]; @@ -2665,7 +2699,8 @@ bool checkForUpdates() { latestVersion = jsondata["latest_version"].as(); jsondata["origin"] = subjectRLStoMQTT; jsondata["retain"] = true; - enqueueJsonObject(jsondata); + handleJsonEnqueue(jsondata); + Log.trace(F("Update file found on server" CR)); return true; } else { @@ -2735,7 +2770,7 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) { StaticJsonDocument jsondata; jsondata["release_summary"] = "Update in progress ..."; jsondata["origin"] = subjectRLStoMQTT; - enqueueJsonObject(jsondata); + handleJsonEnqueue(jsondata); const char* ota_cert = HttpsFwUpdateData["server_cert"]; if (!ota_cert && !strstr(url, "http:")) { @@ -2803,7 +2838,7 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) { jsondata["release_summary"] = "Update success !"; jsondata["installed_version"] = latestVersion; jsondata["origin"] = subjectRLStoMQTT; - enqueueJsonObject(jsondata); + handleJsonEnqueue(jsondata); ota_server_cert = ota_cert; # ifndef ESPWifiManualSetup saveConfig();