From 8b647e8b8e67bd8e909fa31b7f4f3a0218c264e7 Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 26 Feb 2023 10:26:55 +0100 Subject: [PATCH 01/12] move mqtt loop into network task --- Config.h | 2 +- Network.cpp | 3 +- lib/espMqttClient/src/MqttClient.h | 2 +- lib/espMqttClient/src/espMqttClientAsync.cpp | 66 ++++++++++++++++++++ lib/espMqttClient/src/espMqttClientAsync.h | 30 +++++++++ main.cpp | 2 +- networkDevices/EthLan8720Device.cpp | 13 +++- networkDevices/EthLan8720Device.h | 6 +- networkDevices/W5500Device.cpp | 1 + networkDevices/WifiDevice.cpp | 13 +++- networkDevices/WifiDevice.h | 6 +- networkDevices/espMqttClientW5500.cpp | 2 +- 12 files changed, 129 insertions(+), 17 deletions(-) diff --git a/Config.h b/Config.h index 4e3be3c..f90b06b 100644 --- a/Config.h +++ b/Config.h @@ -1,6 +1,6 @@ #pragma once -#define NUKI_HUB_VERSION "8.12-pre-1" +#define NUKI_HUB_VERSION "8.12-pre-8" #define MQTT_QOS_LEVEL 1 #define MQTT_CLEAN_SESSIONS false \ No newline at end of file diff --git a/Network.cpp b/Network.cpp index 480867e..5674cb2 100644 --- a/Network.cpp +++ b/Network.cpp @@ -357,7 +357,8 @@ bool Network::reconnect() while(!_connectReplyReceived && millis() < timeout) { - delay(200); + delay(50); + _device->update(); if(_keepAliveCallback != nullptr) { _keepAliveCallback(); diff --git a/lib/espMqttClient/src/MqttClient.h b/lib/espMqttClient/src/MqttClient.h index db7b254..1d8f906 100644 --- a/lib/espMqttClient/src/MqttClient.h +++ b/lib/espMqttClient/src/MqttClient.h @@ -66,10 +66,10 @@ class MqttClient { void clearQueue(bool all = false); // Not MQTT compliant and may cause unpredictable results when `all` = true! const char* getClientId() const; #if defined(ARDUINO_ARCH_ESP32) + void loop(); protected: #endif - void loop(); #if defined(ARDUINO_ARCH_ESP32) explicit MqttClient(bool useTask, uint8_t priority = 1, uint8_t core = 1); bool _useTask; diff --git a/lib/espMqttClient/src/espMqttClientAsync.cpp b/lib/espMqttClient/src/espMqttClientAsync.cpp index bc53878..156572c 100644 --- a/lib/espMqttClient/src/espMqttClientAsync.cpp +++ b/lib/espMqttClient/src/espMqttClientAsync.cpp @@ -66,3 +66,69 @@ void espMqttClientAsync::onPollCb(void* a, AsyncClient* c) { } #endif + + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#if defined(ARDUINO_ARCH_ESP32) +espMqttClientSecureAsync::espMqttClientSecureAsync(uint8_t priority, uint8_t core) + : MqttClientSetup(false, priority, core) + , _client() { +#else + espMqttClientSecure::espMqttClientSecure() +: _client() { +#endif + _transport = &_client; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setInsecure() { + _client.client.setInsecure(); + return *this; +} + +#if defined(ARDUINO_ARCH_ESP32) +espMqttClientSecureAsync& espMqttClientSecureAsync::setCACert(const char* rootCA) { + _client.client.setCACert(rootCA); + return *this; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setCertificate(const char* clientCa) { + _client.client.setCertificate(clientCa); + return *this; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setPrivateKey(const char* privateKey) { + _client.client.setPrivateKey(privateKey); + return *this; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setPreSharedKey(const char* pskIdent, const char* psKey) { + _client.client.setPreSharedKey(pskIdent, psKey); + return *this; +} +#elif defined(ARDUINO_ARCH_ESP8266) +espMqttClientSecureAsync& espMqttClientSecureAsync::setFingerprint(const uint8_t fingerprint[20]) { + _client.client.setFingerprint(fingerprint); + return *this; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setTrustAnchors(const X509List *ta) { + _client.client.setTrustAnchors(ta); + return *this; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setClientRSACert(const X509List *cert, const PrivateKey *sk) { + _client.client.setClientRSACert(cert, sk); + return *this; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type) { + _client.client.setClientECCert(cert, sk, allowed_usages, cert_issuer_key_type); + return *this; +} + +espMqttClientSecureAsync& espMqttClientSecureAsync::setCertStore(CertStoreBase *certStore) { + _client.client.setCertStore(certStore); + return *this; +} +#endif +#endif \ No newline at end of file diff --git a/lib/espMqttClient/src/espMqttClientAsync.h b/lib/espMqttClient/src/espMqttClientAsync.h index f3f321d..3493989 100644 --- a/lib/espMqttClient/src/espMqttClientAsync.h +++ b/lib/espMqttClient/src/espMqttClientAsync.h @@ -16,6 +16,7 @@ the LICENSE file. #include "Transport/ClientAsync.h" #include "MqttClientSetup.h" +#include "Transport/ClientSecureSync.h" class espMqttClientAsync : public MqttClientSetup { public: @@ -38,3 +39,32 @@ class espMqttClientAsync : public MqttClientSetup { }; #endif + + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +class espMqttClientSecureAsync : public MqttClientSetup { +public: +#if defined(ARDUINO_ARCH_ESP32) + explicit espMqttClientSecureAsync(uint8_t priority = 1, uint8_t core = 1); +#else + espMqttClientSecure(); +#endif + espMqttClientSecureAsync& setInsecure(); +#if defined(ARDUINO_ARCH_ESP32) + espMqttClientSecureAsync& setCACert(const char* rootCA); + espMqttClientSecureAsync& setCertificate(const char* clientCa); + espMqttClientSecureAsync& setPrivateKey(const char* privateKey); + espMqttClientSecureAsync& setPreSharedKey(const char* pskIdent, const char* psKey); +#else + espMqttClientSecure& setFingerprint(const uint8_t fingerprint[20]); + espMqttClientSecure& setTrustAnchors(const X509List *ta); + espMqttClientSecure& setClientRSACert(const X509List *cert, const PrivateKey *sk); + espMqttClientSecure& setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type); + espMqttClientSecure& setCertStore(CertStoreBase *certStore); +#endif + +protected: + espMqttClientInternals::ClientSecureSync _client; +}; + +#endif \ No newline at end of file diff --git a/main.cpp b/main.cpp index a1a15c4..2a955a5 100644 --- a/main.cpp +++ b/main.cpp @@ -51,7 +51,7 @@ void networkTask(void *pvParameters) restartEsp(RestartReason::RestartTimer); } - delay(200); + delay(100); // Serial.println(uxTaskGetStackHighWaterMark(NULL)); } diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index 991599d..83aa9a5 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -25,7 +25,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientSecure(); + _mqttClientSecure = new espMqttClientSecureAsync(); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClient(); + _mqttClient = new espMqttClientAsync(); } if(_preferences->getBool(preference_mqtt_log_enabled)) @@ -110,7 +110,14 @@ ReconnectStatus EthLan8720Device::reconnect() void EthLan8720Device::update() { - + if(_useEncryption) + { + _mqttClientSecure->loop(); + } + else + { + _mqttClient->loop(); + } } void EthLan8720Device::onDisconnected() diff --git a/networkDevices/EthLan8720Device.h b/networkDevices/EthLan8720Device.h index ad60793..a74af82 100644 --- a/networkDevices/EthLan8720Device.h +++ b/networkDevices/EthLan8720Device.h @@ -4,7 +4,7 @@ #include #include #include "NetworkDevice.h" -#include "espMqttClient.h" +#include "espMqttClientAsync.h" class EthLan8720Device : public NetworkDevice { @@ -54,8 +54,8 @@ public: private: void onDisconnected(); - espMqttClient* _mqttClient = nullptr; - espMqttClientSecure* _mqttClientSecure = nullptr; + espMqttClientAsync* _mqttClient = nullptr; + espMqttClientSecureAsync* _mqttClientSecure = nullptr; bool _restartOnDisconnect = false; bool _startAp = false; diff --git a/networkDevices/W5500Device.cpp b/networkDevices/W5500Device.cpp index c8fb38b..93c3343 100644 --- a/networkDevices/W5500Device.cpp +++ b/networkDevices/W5500Device.cpp @@ -197,6 +197,7 @@ void W5500Device::initializeMacAddress(byte *mac) void W5500Device::update() { _maintainResult = Ethernet.maintain(); + _mqttClient.loop(); } int8_t W5500Device::signalStrength() diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index 1ccaf57..92188f1 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -25,7 +25,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientSecure(); + _mqttClientSecure = new espMqttClientSecureAsync(); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClient(); + _mqttClient = new espMqttClientAsync(); } if(_preferences->getBool(preference_mqtt_log_enabled)) @@ -142,7 +142,14 @@ ReconnectStatus WifiDevice::reconnect() void WifiDevice::update() { - + if(_useEncryption) + { + _mqttClientSecure->loop(); + } + else + { + _mqttClient->loop(); + } } void WifiDevice::onDisconnected() diff --git a/networkDevices/WifiDevice.h b/networkDevices/WifiDevice.h index 8d972cb..52a5c64 100644 --- a/networkDevices/WifiDevice.h +++ b/networkDevices/WifiDevice.h @@ -5,7 +5,7 @@ #include #include "NetworkDevice.h" #include "WiFiManager.h" -#include "espMqttClient.h" +#include "espMqttClientAsync.h" class WifiDevice : public NetworkDevice { @@ -58,8 +58,8 @@ private: void onDisconnected(); WiFiManager _wm; - espMqttClient* _mqttClient = nullptr; - espMqttClientSecure* _mqttClientSecure = nullptr; + espMqttClientAsync* _mqttClient = nullptr; + espMqttClientSecureAsync* _mqttClientSecure = nullptr; bool _restartOnDisconnect = false; bool _startAp = false; diff --git a/networkDevices/espMqttClientW5500.cpp b/networkDevices/espMqttClientW5500.cpp index 445cb71..eeb7e0b 100644 --- a/networkDevices/espMqttClientW5500.cpp +++ b/networkDevices/espMqttClientW5500.cpp @@ -1,7 +1,7 @@ #include "espMqttClientW5500.h" espMqttClientW5500::espMqttClientW5500(uint8_t priority, uint8_t core) -: MqttClientSetup(true, priority, core), +: MqttClientSetup(false, priority, core), _client() { _transport = &_client; From 8fd17206dd92c68e99cc3276fc64a417e1f971c3 Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 26 Feb 2023 11:55:35 +0100 Subject: [PATCH 02/12] print stack watermarks in sysinfo page --- Config.h | 2 +- WebCfgServer.cpp | 8 ++++++++ WebCfgServer.h | 4 ++++ main.cpp | 17 +++++++++++++---- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Config.h b/Config.h index f90b06b..538eb48 100644 --- a/Config.h +++ b/Config.h @@ -1,6 +1,6 @@ #pragma once -#define NUKI_HUB_VERSION "8.12-pre-8" +#define NUKI_HUB_VERSION "8.12-pre-9" #define MQTT_QOS_LEVEL 1 #define MQTT_CLEAN_SESSIONS false \ No newline at end of file diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index e186297..652c1b1 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -785,6 +785,14 @@ void WebCfgServer::buildInfoHtml(String &response) response.concat(esp_get_free_heap_size()); response.concat("\n"); + response.concat("Stack watermarks: nw: "); + response.concat(uxTaskGetStackHighWaterMark(networkTaskHandle)); + response.concat(", nuki: "); + response.concat(uxTaskGetStackHighWaterMark(nukiTaskHandle)); + response.concat(", pd: "); + response.concat(uxTaskGetStackHighWaterMark(presenceDetectionTaskHandle)); + response.concat("\n"); + response.concat("Restart reason FW: "); response.concat(getRestartReason()); response.concat( "\n"); diff --git a/WebCfgServer.h b/WebCfgServer.h index 007f140..ec05e06 100644 --- a/WebCfgServer.h +++ b/WebCfgServer.h @@ -7,6 +7,10 @@ #include "NukiOpenerWrapper.h" #include "Ota.h" +extern TaskHandle_t networkTaskHandle; +extern TaskHandle_t nukiTaskHandle; +extern TaskHandle_t presenceDetectionTaskHandle; + enum class TokenType { None, diff --git a/main.cpp b/main.cpp index 2a955a5..39780c9 100644 --- a/main.cpp +++ b/main.cpp @@ -32,6 +32,10 @@ unsigned long restartTs = (2^32) - 5 * 60000; RTC_NOINIT_ATTR int restartReason; RTC_NOINIT_ATTR uint64_t restartReasonValid; +TaskHandle_t networkTaskHandle = nullptr; +TaskHandle_t nukiTaskHandle = nullptr; +TaskHandle_t presenceDetectionTaskHandle = nullptr; + void networkTask(void *pvParameters) { while(true) @@ -53,7 +57,12 @@ void networkTask(void *pvParameters) delay(100); -// Serial.println(uxTaskGetStackHighWaterMark(NULL)); +// if(wmts < millis()) +// { +// Serial.print("# "); +// Serial.println(uxTaskGetStackHighWaterMark(NULL)); +// wmts = millis() + 60000; +// } } } @@ -96,9 +105,9 @@ void setupTasks() { // configMAX_PRIORITIES is 25 - xTaskCreatePinnedToCore(networkTask, "ntw", 8192, NULL, 3, NULL, 1); - xTaskCreatePinnedToCore(nukiTask, "nuki", 4096, NULL, 2, NULL, 1); - xTaskCreatePinnedToCore(presenceDetectionTask, "prdet", 768, NULL, 5, NULL, 1); + xTaskCreatePinnedToCore(networkTask, "ntw", 8192, NULL, 3, &networkTaskHandle, 1); + xTaskCreatePinnedToCore(nukiTask, "nuki", 4096, NULL, 2, &nukiTaskHandle, 1); + xTaskCreatePinnedToCore(presenceDetectionTask, "prdet", 768, NULL, 5, &presenceDetectionTaskHandle, 1); } uint32_t getRandomId() From b14ea6326ec71b9f91d39a9ab8c530d699df8d0b Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 26 Feb 2023 14:34:08 +0100 Subject: [PATCH 03/12] upadte esp mqtt client --- CMakeLists.txt | 1 + Config.h | 2 +- lib/espMqttClient/docs/index.md | 17 +- .../largepayload-esp8266.ino | 8 +- .../examples/ota-esp8266/ota-esp8266.ino | 8 +- .../examples/simple-esp32/simple-esp32.ino | 7 +- .../simple-esp8266/simple-esp8266.ino | 8 +- .../simpleAsync-esp32/simpleAsync-esp32.ino | 7 +- .../simpleAsync-esp8266.ino | 8 +- .../examples/tls-esp32/tls-esp32.ino | 7 +- .../examples/tls-esp8266/tls-esp8266.ino | 8 +- lib/espMqttClient/src/Config.h | 6 +- lib/espMqttClient/src/Logging.h | 3 +- lib/espMqttClient/src/MqttClient.cpp | 153 ++++++++++++++---- lib/espMqttClient/src/MqttClient.h | 30 ++-- lib/espMqttClient/src/espMqttClientAsync.cpp | 66 -------- lib/espMqttClient/src/espMqttClientAsync.h | 30 ---- .../test_client_native/test_client_native.cpp | 85 ++++++++++ networkDevices/EthLan8720Device.cpp | 8 +- networkDevices/EthLan8720Device.h | 6 +- networkDevices/W5500Device.cpp | 2 +- networkDevices/WifiDevice.cpp | 8 +- networkDevices/WifiDevice.h | 6 +- networkDevices/espMqttClientW5500.cpp | 5 + networkDevices/espMqttClientW5500.h | 2 + networkDevices/espMqttClientWifi.cpp | 97 +++++++++++ networkDevices/espMqttClientWifi.h | 69 ++++++++ 27 files changed, 454 insertions(+), 203 deletions(-) create mode 100644 networkDevices/espMqttClientWifi.cpp create mode 100644 networkDevices/espMqttClientWifi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ee604d..dab8e13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ file(GLOB SRCFILES networkDevices/EthLan8720Device.cpp networkDevices/ClientSyncW5500.cpp networkDevices/espMqttClientW5500.cpp + networkDevices/espMqttClientWifi.cpp QueryCommand.h NukiWrapper.cpp NukiOpenerWrapper.cpp diff --git a/Config.h b/Config.h index 538eb48..f1d34de 100644 --- a/Config.h +++ b/Config.h @@ -1,6 +1,6 @@ #pragma once -#define NUKI_HUB_VERSION "8.12-pre-9" +#define NUKI_HUB_VERSION "8.12-pre-10" #define MQTT_QOS_LEVEL 1 #define MQTT_CLEAN_SESSIONS false \ No newline at end of file diff --git a/lib/espMqttClient/docs/index.md b/lib/espMqttClient/docs/index.md index 8b8efb9..84d1122 100644 --- a/lib/espMqttClient/docs/index.md +++ b/lib/espMqttClient/docs/index.md @@ -312,11 +312,13 @@ Publish a packet with a callback for payload handling. Return the packet ID (or The callback has the following signature: `size_t callback(uint8_t* data, size_t maxSize, size_t index)`. When the library needs payload data, the callback will be invoked. It is the callback's job to write data indo `data` with a maximum of `maxSize` bytes, according the `index` and return the amount of bytes written. ```cpp -void clearQueue() +void clearQueue(bool deleteSessionData = false) ``` -When disconnected, clears all queued messages. -Keep in mind that this also deletes any session data and therefore is no MQTT compliant. +Clears all queued messages. +Keep in mind that this may also delete any session data and therefore is not MQTT compliant. + +- **`deleteSessionData`**: When true, delete all outgoing messages. Not MQTT compliant! ```cpp void loop() @@ -361,12 +363,19 @@ Set this to 1 if you use the async version on ESP8266. For the regular client th ### EMC_ALLOW_NOT_CONNECTED_PUBLISH 1 By default, you can publish when the client is not connected. If you don't want this, set this to 0. +Regardless of this setting, after you called `disconnect()`, no messages can be published until fully disconnected. + +### EMC_WAIT_FOR_CONNACK 1 + +espMqttClient waits for the CONNACK (connection acknowledge) packet before starting to send other packets. +The MQTT specification allows to start sending before the broker acknowledges the connection but some brokers +don't allow this (AWS for example doesn't). ### EMC_CLIENTID_LENGTH 18 + 1 The (maximum) length of the client ID. (Keep in mind that this is a c-string. You need to have 1 position available for the null-termination.) -### EMC_TASK_STACK_SIZE 5000 +### EMC_TASK_STACK_SIZE 5120 Only used on ESP32. Sets the stack size (in words) of the MQTT client worker task. diff --git a/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino b/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino index f719080..aff6fac 100644 --- a/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino +++ b/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino @@ -1,5 +1,4 @@ #include -#include #include #define WIFI_SSID "yourSSID" @@ -11,7 +10,6 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClient mqttClient; -Ticker reconnectTimer; size_t fetchPayload(uint8_t* dest, size_t len, size_t index) { Serial.printf("filling buffer at index %zu\n", index); @@ -45,8 +43,6 @@ void onWiFiConnect(const WiFiEventStationModeGotIP& event) { void onWiFiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); - reconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi - reconnectTimer.once(5, connectToWiFi); } void onMqttConnect(bool sessionPresent) { @@ -60,7 +56,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -75,6 +71,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); wifiConnectHandler = WiFi.onStationModeGotIP(onWiFiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWiFiDisconnect); diff --git a/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino b/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino index 07bb1aa..5152d9b 100644 --- a/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino +++ b/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino @@ -1,6 +1,5 @@ #include #include -#include #include #define WIFI_SSID "yourSSID" @@ -14,7 +13,6 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClient mqttClient; -Ticker reconnectTimer; bool disconnectFlag = false; bool restartFlag = false; @@ -35,8 +33,6 @@ void onWiFiConnect(const WiFiEventStationModeGotIP& event) { void onWiFiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); - reconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi - reconnectTimer.once(5, connectToWiFi); } void onMqttConnect(bool sessionPresent) { @@ -57,7 +53,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { } if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -114,6 +110,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); wifiConnectHandler = WiFi.onStationModeGotIP(onWiFiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWiFiDisconnect); diff --git a/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino b/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino index 581db1f..27dc6b9 100644 --- a/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino +++ b/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino @@ -1,5 +1,4 @@ #include -#include #include #define WIFI_SSID "yourSSID" @@ -9,7 +8,6 @@ #define MQTT_PORT 1883 espMqttClient mqttClient; -Ticker reconnectTimer; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -32,7 +30,6 @@ void WiFiEvent(WiFiEvent_t event) { break; case SYSTEM_EVENT_STA_DISCONNECTED: Serial.println("WiFi lost connection"); - reconnectTimer.once(5, connectToWiFi); break; default: break; @@ -60,7 +57,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -109,6 +106,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); WiFi.onEvent(WiFiEvent); mqttClient.onConnect(onMqttConnect); diff --git a/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino b/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino index 0747ec6..39e725d 100644 --- a/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino +++ b/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino @@ -1,5 +1,4 @@ #include -#include #include #define WIFI_SSID "yourSSID" @@ -11,7 +10,6 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClient mqttClient; -Ticker reconnectTimer; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -30,8 +28,6 @@ void onWiFiConnect(const WiFiEventStationModeGotIP& event) { void onWiFiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); - reconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi - reconnectTimer.once(5, connectToWiFi); } void onMqttConnect(bool sessionPresent) { @@ -55,7 +51,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -104,6 +100,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); wifiConnectHandler = WiFi.onStationModeGotIP(onWiFiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWiFiDisconnect); diff --git a/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino b/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino index c4d9aa0..a556789 100644 --- a/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino +++ b/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino @@ -1,5 +1,4 @@ #include -#include #include #define WIFI_SSID "yourSSID" @@ -9,7 +8,6 @@ #define MQTT_PORT 1883 espMqttClientAsync mqttClient; -Ticker reconnectTimer; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -32,7 +30,6 @@ void WiFiEvent(WiFiEvent_t event) { break; case SYSTEM_EVENT_STA_DISCONNECTED: Serial.println("WiFi lost connection"); - reconnectTimer.once(5, connectToWiFi); break; default: break; @@ -60,7 +57,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -109,6 +106,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); WiFi.onEvent(WiFiEvent); mqttClient.onConnect(onMqttConnect); diff --git a/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino b/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino index 2ed6b53..76c20a9 100644 --- a/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino +++ b/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino @@ -1,5 +1,4 @@ #include -#include #include #define WIFI_SSID "yourSSID" @@ -11,7 +10,6 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClientAsync mqttClient; -Ticker reconnectTimer; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -30,8 +28,6 @@ void onWiFiConnect(const WiFiEventStationModeGotIP& event) { void onWiFiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); - reconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi - reconnectTimer.once(5, connectToWiFi); } void onMqttConnect(bool sessionPresent) { @@ -55,7 +51,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -104,6 +100,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); wifiConnectHandler = WiFi.onStationModeGotIP(onWiFiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWiFiDisconnect); diff --git a/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino b/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino index 73a6db4..551d241 100644 --- a/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino +++ b/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino @@ -1,5 +1,4 @@ #include -#include #include #define WIFI_SSID "yourSSID" @@ -16,7 +15,6 @@ const char rootCA[] = \ "-----END CERTIFICATE-----\n"; espMqttClientSecure mqttClient; -Ticker reconnectTimer; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -39,7 +37,6 @@ void WiFiEvent(WiFiEvent_t event) { break; case SYSTEM_EVENT_STA_DISCONNECTED: Serial.println("WiFi lost connection"); - reconnectTimer.once(5, connectToWiFi); break; default: break; @@ -64,7 +61,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -113,6 +110,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); WiFi.onEvent(WiFiEvent); //mqttClient.setInsecure(); diff --git a/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino b/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino index b5b6567..b196a8c 100644 --- a/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino +++ b/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino @@ -1,5 +1,4 @@ #include -#include #include #define WIFI_SSID "yourSSID" @@ -14,7 +13,6 @@ const uint8_t fingerprint[] = {0xee, 0xbc, 0x4b, 0xf8, 0x57, 0xe3, 0xd3, 0xe4, 0 WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClientSecure mqttClient; -Ticker reconnectTimer; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -33,8 +31,6 @@ void onWiFiConnect(const WiFiEventStationModeGotIP& event) { void onWiFiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); - reconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi - reconnectTimer.once(5, connectToWiFi); } void onMqttConnect(bool sessionPresent) { @@ -58,7 +54,7 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - reconnectTimer.once(5, connectToMqtt); + connectToMqtt(); } } @@ -107,6 +103,8 @@ void setup() { Serial.println(); Serial.println(); + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); wifiConnectHandler = WiFi.onStationModeGotIP(onWiFiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWiFiDisconnect); diff --git a/lib/espMqttClient/src/Config.h b/lib/espMqttClient/src/Config.h index 540bb2f..aba7795 100644 --- a/lib/espMqttClient/src/Config.h +++ b/lib/espMqttClient/src/Config.h @@ -40,13 +40,17 @@ the LICENSE file. #define EMC_ALLOW_NOT_CONNECTED_PUBLISH 1 #endif +#ifndef EMC_WAIT_FOR_CONNACK +#define EMC_WAIT_FOR_CONNACK 1 +#endif + #ifndef EMC_CLIENTID_LENGTH // esp8266abc123 and esp32abcdef123456 #define EMC_CLIENTID_LENGTH 23 + 1 #endif #ifndef EMC_TASK_STACK_SIZE -#define EMC_TASK_STACK_SIZE 5000 +#define EMC_TASK_STACK_SIZE 5120 #endif #ifndef EMC_USE_WATCHDOG diff --git a/lib/espMqttClient/src/Logging.h b/lib/espMqttClient/src/Logging.h index 7c6f33e..a1d85fa 100644 --- a/lib/espMqttClient/src/Logging.h +++ b/lib/espMqttClient/src/Logging.h @@ -9,13 +9,14 @@ the LICENSE file. #pragma once #if defined(ARDUINO_ARCH_ESP32) - // Logging is en/disabled by Arduino framework macros #include #if defined(DEBUG_ESP_MQTT_CLIENT) + // Logging is en/disabled by Arduino framework macros #define emc_log_i(...) log_i(__VA_ARGS__) #define emc_log_e(...) log_e(__VA_ARGS__) #define emc_log_w(...) log_w(__VA_ARGS__) #else + // Logging is disabled #define emc_log_i(...) #define emc_log_e(...) #define emc_log_w(...) diff --git a/lib/espMqttClient/src/MqttClient.cpp b/lib/espMqttClient/src/MqttClient.cpp index 6b3758c..9868c27 100644 --- a/lib/espMqttClient/src/MqttClient.cpp +++ b/lib/espMqttClient/src/MqttClient.cpp @@ -76,7 +76,7 @@ MqttClient::MqttClient() MqttClient::~MqttClient() { disconnect(true); - _clearQueue(true); + _clearQueue(2); #if defined(ARDUINO_ARCH_ESP32) vSemaphoreDelete(_xSemaphore); if (_useTask) { @@ -144,9 +144,11 @@ bool MqttClient::disconnect(bool force) { uint16_t MqttClient::publish(const char* topic, uint8_t qos, bool retain, const uint8_t* payload, size_t length) { #if !EMC_ALLOW_NOT_CONNECTED_PUBLISH if (_state != State::connected) { + #else + if (_state > State::connected) { + #endif return 0; } - #endif uint16_t packetId = (qos > 0) ? _getNextPacketId() : 1; EMC_SEMAPHORE_TAKE(); if (!_addPacket(packetId, topic, payload, length, qos, retain)) { @@ -166,9 +168,11 @@ uint16_t MqttClient::publish(const char* topic, uint8_t qos, bool retain, const uint16_t MqttClient::publish(const char* topic, uint8_t qos, bool retain, espMqttClientTypes::PayloadCallback callback, size_t length) { #if !EMC_ALLOW_NOT_CONNECTED_PUBLISH if (_state != State::connected) { + #else + if (_state > State::connected) { + #endif return 0; } - #endif uint16_t packetId = (qos > 0) ? _getNextPacketId() : 1; EMC_SEMAPHORE_TAKE(); if (!_addPacket(packetId, topic, callback, length, qos, retain)) { @@ -180,8 +184,8 @@ uint16_t MqttClient::publish(const char* topic, uint8_t qos, bool retain, espMqt return packetId; } -void MqttClient::clearQueue(bool all) { - _clearQueue(all); +void MqttClient::clearQueue(bool deleteSessionData) { + _clearQueue(deleteSessionData ? 2 : 0); } const char* MqttClient::getClientId() const { @@ -214,6 +218,31 @@ void MqttClient::loop() { _state = State::connectingMqtt; } break; + case State::connectingMqtt: + #if EMC_WAIT_FOR_CONNACK + _sendPacket(); + _checkIncoming(); + _checkPing(); + break; + #else + // receipt of CONNACK packet will set state to CONNECTED + // client however is allowed to send packets before CONNACK is received + // so we fall through to 'connected' + [[fallthrough]]; + #endif + case State::connected: + [[fallthrough]]; + case State::disconnectingMqtt2: + if (_transport->connected()) { + // CONNECT packet is first in the queue + _checkOutbox(); + _checkIncoming(); + _checkPing(); + } else { + _state = State::disconnectingTcp1; + _disconnectReason = DisconnectReason::TCP_DISCONNECTED; + } + break; case State::disconnectingMqtt1: EMC_SEMAPHORE_TAKE(); if (_outbox.empty()) { @@ -226,25 +255,9 @@ void MqttClient::loop() { } } EMC_SEMAPHORE_GIVE(); - // fall through to 'connected' to send out DISCONN packet - [[fallthrough]]; - case State::disconnectingMqtt2: - [[fallthrough]]; - case State::connectingMqtt: - // receipt of CONNACK packet will set state to CONNECTED - // client however is allowed to send packets before CONNACK is received - // so we fall through to 'connected' - [[fallthrough]]; - case State::connected: - if (_transport->connected()) { - // CONNECT packet is first in the queue - _checkOutgoing(); - _checkIncoming(); - _checkPing(); - } else { - _state = State::disconnectingTcp1; - _disconnectReason = DisconnectReason::TCP_DISCONNECTED; - } + _checkOutbox(); + _checkIncoming(); + _checkPing(); break; case State::disconnectingTcp1: _transport->stop(); @@ -252,7 +265,7 @@ void MqttClient::loop() { break; case State::disconnectingTcp2: if (_transport->disconnected()) { - _clearQueue(false); + _clearQueue(0); _state = State::disconnected; if (_onDisconnectCallback) _onDisconnectCallback(_disconnectReason); } @@ -294,6 +307,15 @@ uint16_t MqttClient::_getNextPacketId() { return packetId; } +void MqttClient::_checkOutbox() { + while (_sendPacket() > 0) { + if (!_advanceOutbox()) { + break; + } + } +} + +/* void MqttClient::_checkOutgoing() { EMC_SEMAPHORE_TAKE(); Packet* packet = _outbox.getCurrent(); @@ -330,6 +352,57 @@ void MqttClient::_checkOutgoing() { } EMC_SEMAPHORE_GIVE(); } +*/ + +int MqttClient::_sendPacket() { + EMC_SEMAPHORE_TAKE(); + Packet* packet = _outbox.getCurrent(); + + int32_t wantToWrite = 0; + int32_t written = 0; + if (packet && (wantToWrite == written)) { + // mixing signed with unsigned here but safe because of MQTT packet size limits + wantToWrite = packet->available(_bytesSent); + if (wantToWrite == 0) { + EMC_SEMAPHORE_GIVE(); + return 0; + } + written = _transport->write(packet->data(_bytesSent), wantToWrite); + if (written < 0) { + emc_log_w("Write error, check connection"); + EMC_SEMAPHORE_GIVE(); + return -1; + } + _lastClientActivity = millis(); + _bytesSent += written; + emc_log_i("tx %zu/%zu (%02x)", _bytesSent, packet->size(), packet->packetType()); + } + EMC_SEMAPHORE_GIVE(); + return written; +} + +bool MqttClient::_advanceOutbox() { + EMC_SEMAPHORE_TAKE(); + Packet* packet = _outbox.getCurrent(); + if (packet && _bytesSent == packet->size()) { + if ((packet->packetType()) == PacketType.DISCONNECT) { + _state = State::disconnectingTcp1; + _disconnectReason = DisconnectReason::USER_OK; + } + if (packet->removable()) { + _outbox.removeCurrent(); + } else { + // handle with care! millis() returns unsigned 32 bit, token is void* + packet->token = reinterpret_cast(millis()); + if ((packet->packetType()) == PacketType.PUBLISH) packet->setDup(); + _outbox.next(); + } + packet = _outbox.getCurrent(); + _bytesSent = 0; + } + EMC_SEMAPHORE_GIVE(); + return packet; +} void MqttClient::_checkIncoming() { int32_t remainingBufferLength = _transport->read(_rxBuffer, EMC_RX_BUFFER_SIZE); @@ -355,7 +428,7 @@ void MqttClient::_checkIncoming() { } break; case PacketType.PUBLISH: - if (_state == State::disconnectingMqtt1 || _state == State::disconnectingMqtt2) break; // stop processing incoming once user has called disconnect + if (_state >= State::disconnectingMqtt1) break; // stop processing incoming once user has called disconnect _onPublish(); break; case PacketType.PUBACK: @@ -427,8 +500,9 @@ void MqttClient::_onConnack() { if (_parser.getPacket().variableHeader.fixed.connackVarHeader.returnCode == 0x00) { _pingSent = false; // reset after keepalive timeout disconnect _state = State::connected; + _advanceOutbox(); if (_parser.getPacket().variableHeader.fixed.connackVarHeader.sessionPresent == 0) { - _clearQueue(true); + _clearQueue(1); } if (_onConnectCallback) { _onConnectCallback(_parser.getPacket().variableHeader.fixed.connackVarHeader.sessionPresent); @@ -636,15 +710,11 @@ void MqttClient::_onUnsuback() { } } -void MqttClient::_clearQueue(bool clearSession) { - emc_log_i("clearing queue (clear session: %s)", clearSession ? "true" : "false"); +void MqttClient::_clearQueue(int clearData) { + emc_log_i("clearing queue (clear session: %d)", clearData); EMC_SEMAPHORE_TAKE(); espMqttClientInternals::Outbox::Iterator it = _outbox.front(); - if (clearSession) { - while (it) { - _outbox.remove(it); - } - } else { + if (clearData == 0) { // keep PUB (qos > 0, aka packetID != 0), PUBREC and PUBREL // Spec only mentions PUB and PUBREL but this lib implements method B from point 4.3.3 (Fig. 4.3) // and stores the packet id in the PUBREC packet. So we also must keep PUBREC. @@ -652,12 +722,25 @@ void MqttClient::_clearQueue(bool clearSession) { espMqttClientInternals::MQTTPacketType type = it.get()->packetType(); if (type == PacketType.PUBREC || type == PacketType.PUBREL || - (type == PacketType.PUBLISH && it.get()->packetId() != 0)) { + (type == PacketType.PUBLISH && it.get()->packetId() != 0)) { ++it; } else { _outbox.remove(it); } } + } else if (clearData == 1) { + // keep PUB + while (it) { + if (it.get()->packetType() == PacketType.PUBLISH) { + ++it; + } else { + _outbox.remove(it); + } + } + } else { // clearData == 2 + while (it) { + _outbox.remove(it); + } } EMC_SEMAPHORE_GIVE(); } diff --git a/lib/espMqttClient/src/MqttClient.h b/lib/espMqttClient/src/MqttClient.h index 1d8f906..f95b966 100644 --- a/lib/espMqttClient/src/MqttClient.h +++ b/lib/espMqttClient/src/MqttClient.h @@ -63,13 +63,13 @@ class MqttClient { uint16_t publish(const char* topic, uint8_t qos, bool retain, const uint8_t* payload, size_t length); uint16_t publish(const char* topic, uint8_t qos, bool retain, const char* payload); uint16_t publish(const char* topic, uint8_t qos, bool retain, espMqttClientTypes::PayloadCallback callback, size_t length); - void clearQueue(bool all = false); // Not MQTT compliant and may cause unpredictable results when `all` = true! + void clearQueue(bool deleteSessionData = false); // Not MQTT compliant and may cause unpredictable results when `deleteSessionData` = true! const char* getClientId() const; #if defined(ARDUINO_ARCH_ESP32) - void loop(); protected: #endif + void loop(); #if defined(ARDUINO_ARCH_ESP32) explicit MqttClient(bool useTask, uint8_t priority = 1, uint8_t core = 1); bool _useTask; @@ -106,15 +106,15 @@ class MqttClient { // state is protected to allow state changes by the transport system, defined in child classes // eg. to allow AsyncTCP enum class State { - disconnected, - connectingTcp1, - connectingTcp2, - connectingMqtt, - connected, - disconnectingMqtt1, - disconnectingMqtt2, - disconnectingTcp1, - disconnectingTcp2 + disconnected = 0, + connectingTcp1 = 1, + connectingTcp2 = 2, + connectingMqtt = 3, + connected = 4, + disconnectingMqtt1 = 5, + disconnectingMqtt2 = 6, + disconnectingTcp1 = 7, + disconnectingTcp2 = 8 }; std::atomic _state; @@ -161,7 +161,9 @@ class MqttClient { return false; } - void _checkOutgoing(); + void _checkOutbox(); + int _sendPacket(); + bool _advanceOutbox(); void _checkIncoming(); void _checkPing(); @@ -174,7 +176,9 @@ class MqttClient { void _onSuback(); void _onUnsuback(); - void _clearQueue(bool clearSession); + void _clearQueue(int clearData); // 0: keep session, + // 1: keep only PUBLISH qos > 0 + // 2: delete all void _onError(uint16_t packetId, espMqttClientTypes::Error error); #if defined(ARDUINO_ARCH_ESP32) diff --git a/lib/espMqttClient/src/espMqttClientAsync.cpp b/lib/espMqttClient/src/espMqttClientAsync.cpp index 156572c..bc53878 100644 --- a/lib/espMqttClient/src/espMqttClientAsync.cpp +++ b/lib/espMqttClient/src/espMqttClientAsync.cpp @@ -66,69 +66,3 @@ void espMqttClientAsync::onPollCb(void* a, AsyncClient* c) { } #endif - - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#if defined(ARDUINO_ARCH_ESP32) -espMqttClientSecureAsync::espMqttClientSecureAsync(uint8_t priority, uint8_t core) - : MqttClientSetup(false, priority, core) - , _client() { -#else - espMqttClientSecure::espMqttClientSecure() -: _client() { -#endif - _transport = &_client; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setInsecure() { - _client.client.setInsecure(); - return *this; -} - -#if defined(ARDUINO_ARCH_ESP32) -espMqttClientSecureAsync& espMqttClientSecureAsync::setCACert(const char* rootCA) { - _client.client.setCACert(rootCA); - return *this; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setCertificate(const char* clientCa) { - _client.client.setCertificate(clientCa); - return *this; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setPrivateKey(const char* privateKey) { - _client.client.setPrivateKey(privateKey); - return *this; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setPreSharedKey(const char* pskIdent, const char* psKey) { - _client.client.setPreSharedKey(pskIdent, psKey); - return *this; -} -#elif defined(ARDUINO_ARCH_ESP8266) -espMqttClientSecureAsync& espMqttClientSecureAsync::setFingerprint(const uint8_t fingerprint[20]) { - _client.client.setFingerprint(fingerprint); - return *this; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setTrustAnchors(const X509List *ta) { - _client.client.setTrustAnchors(ta); - return *this; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setClientRSACert(const X509List *cert, const PrivateKey *sk) { - _client.client.setClientRSACert(cert, sk); - return *this; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type) { - _client.client.setClientECCert(cert, sk, allowed_usages, cert_issuer_key_type); - return *this; -} - -espMqttClientSecureAsync& espMqttClientSecureAsync::setCertStore(CertStoreBase *certStore) { - _client.client.setCertStore(certStore); - return *this; -} -#endif -#endif \ No newline at end of file diff --git a/lib/espMqttClient/src/espMqttClientAsync.h b/lib/espMqttClient/src/espMqttClientAsync.h index 3493989..f3f321d 100644 --- a/lib/espMqttClient/src/espMqttClientAsync.h +++ b/lib/espMqttClient/src/espMqttClientAsync.h @@ -16,7 +16,6 @@ the LICENSE file. #include "Transport/ClientAsync.h" #include "MqttClientSetup.h" -#include "Transport/ClientSecureSync.h" class espMqttClientAsync : public MqttClientSetup { public: @@ -39,32 +38,3 @@ class espMqttClientAsync : public MqttClientSetup { }; #endif - - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -class espMqttClientSecureAsync : public MqttClientSetup { -public: -#if defined(ARDUINO_ARCH_ESP32) - explicit espMqttClientSecureAsync(uint8_t priority = 1, uint8_t core = 1); -#else - espMqttClientSecure(); -#endif - espMqttClientSecureAsync& setInsecure(); -#if defined(ARDUINO_ARCH_ESP32) - espMqttClientSecureAsync& setCACert(const char* rootCA); - espMqttClientSecureAsync& setCertificate(const char* clientCa); - espMqttClientSecureAsync& setPrivateKey(const char* privateKey); - espMqttClientSecureAsync& setPreSharedKey(const char* pskIdent, const char* psKey); -#else - espMqttClientSecure& setFingerprint(const uint8_t fingerprint[20]); - espMqttClientSecure& setTrustAnchors(const X509List *ta); - espMqttClientSecure& setClientRSACert(const X509List *cert, const PrivateKey *sk); - espMqttClientSecure& setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type); - espMqttClientSecure& setCertStore(CertStoreBase *certStore); -#endif - -protected: - espMqttClientInternals::ClientSecureSync _client; -}; - -#endif \ No newline at end of file diff --git a/lib/espMqttClient/test/test_client_native/test_client_native.cpp b/lib/espMqttClient/test/test_client_native/test_client_native.cpp index 01a3896..7afd7e1 100644 --- a/lib/espMqttClient/test/test_client_native/test_client_native.cpp +++ b/lib/espMqttClient/test/test_client_native/test_client_native.cpp @@ -43,6 +43,8 @@ void test_connect() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_TRUE(onConnectCalledTest); TEST_ASSERT_FALSE(sessionPresentTest); + + mqttClient.onConnect(nullptr); } /* @@ -93,6 +95,8 @@ void test_subscribe() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_TRUE(subscribeTest); + + mqttClient.onSubscribe(nullptr); } /* @@ -133,6 +137,9 @@ void test_publish() { TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos2Test); TEST_ASSERT_EQUAL_INT(2, publishSendTest); TEST_ASSERT_EQUAL_INT(3, publishReceiveTest); + + mqttClient.onPublish(nullptr); + mqttClient.onMessage(nullptr); } void test_publish_empty() { @@ -165,6 +172,9 @@ void test_publish_empty() { TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos2Test); TEST_ASSERT_EQUAL_INT(2, publishSendEmptyTest); TEST_ASSERT_EQUAL_INT(3, publishReceiveEmptyTest); + + mqttClient.onPublish(nullptr); + mqttClient.onMessage(nullptr); } /* @@ -200,6 +210,9 @@ void test_receive1() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_GREATER_THAN_INT(0, publishReceive1Test); + + mqttClient.onMessage(nullptr); + mqttClient.onSubscribe(nullptr); } /* @@ -235,6 +248,9 @@ void test_receive2() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_EQUAL_INT(1, publishReceive2Test); + + mqttClient.onMessage(nullptr); + mqttClient.onSubscribe(nullptr); } @@ -261,6 +277,8 @@ void test_unsubscribe() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_TRUE(unsubscribeTest); + + mqttClient.onUnsubscribe(nullptr); } /* @@ -288,6 +306,71 @@ void test_disconnect() { TEST_ASSERT_TRUE(onDisconnectCalled); TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::DisconnectReason::USER_OK, reasonTest); TEST_ASSERT_TRUE(mqttClient.disconnected()); + + mqttClient.onDisconnect(nullptr); +} + +void test_pub_before_connect() { + std::atomic onConnectCalledTest(false); + std::atomic publishSendTest(0); + bool sessionPresentTest = true; + mqttClient.setServer(broker, broker_port) + .setCleanSession(true) + .setKeepAlive(5) + .onConnect([&](bool sessionPresent) mutable { + sessionPresentTest = sessionPresent; + onConnectCalledTest = true; + }) + .onPublish([&](uint16_t packetId) mutable { + (void) packetId; + publishSendTest++; + }); + uint16_t sendQos0Test = mqttClient.publish("test/test", 0, false, "test0"); + uint16_t sendQos1Test = mqttClient.publish("test/test", 1, false, "test1"); + uint16_t sendQos2Test = mqttClient.publish("test/test", 2, false, "test2"); + mqttClient.connect(); + uint32_t start = millis(); + while (millis() - start < 2000) { + if (onConnectCalledTest) { + break; + } + std::this_thread::yield(); + } + TEST_ASSERT_TRUE(mqttClient.connected()); + TEST_ASSERT_TRUE(onConnectCalledTest); + TEST_ASSERT_FALSE(sessionPresentTest); + start = millis(); + while (millis() - start < 10000) { + std::this_thread::yield(); + } + + TEST_ASSERT_EQUAL_UINT16(1, sendQos0Test); + TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos1Test); + TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos2Test); + TEST_ASSERT_EQUAL_INT(2, publishSendTest); + + mqttClient.onConnect(nullptr); + mqttClient.onPublish(nullptr); +} + +void final_disconnect() { + std::atomic onDisconnectCalled(false); + mqttClient.onDisconnect([&](espMqttClientTypes::DisconnectReason reason) mutable { + (void) reason; + onDisconnectCalled = true; + }); + mqttClient.disconnect(); + uint32_t start = millis(); + while (millis() - start < 2000) { + if (onDisconnectCalled) { + break; + } + std::this_thread::yield(); + } + if (mqttClient.connected()) { + mqttClient.disconnect(true); + } + mqttClient.onDisconnect(nullptr); } int main() { @@ -307,6 +390,8 @@ int main() { RUN_TEST(test_receive2); RUN_TEST(test_unsubscribe); RUN_TEST(test_disconnect); + RUN_TEST(test_pub_before_connect); + final_disconnect(); exitProgram = true; t.join(); return UNITY_END(); diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index 83aa9a5..3c5a75d 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -25,7 +25,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientSecureAsync(); + _mqttClientSecure = new espMqttClientWifiSecure(); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClientAsync(); + _mqttClient = new espMqttClientWifi(); } if(_preferences->getBool(preference_mqtt_log_enabled)) @@ -112,11 +112,11 @@ void EthLan8720Device::update() { if(_useEncryption) { - _mqttClientSecure->loop(); + _mqttClientSecure->update(); } else { - _mqttClient->loop(); + _mqttClient->update(); } } diff --git a/networkDevices/EthLan8720Device.h b/networkDevices/EthLan8720Device.h index a74af82..1d23615 100644 --- a/networkDevices/EthLan8720Device.h +++ b/networkDevices/EthLan8720Device.h @@ -4,7 +4,7 @@ #include #include #include "NetworkDevice.h" -#include "espMqttClientAsync.h" +#include "espMqttClientWifi.h" class EthLan8720Device : public NetworkDevice { @@ -54,8 +54,8 @@ public: private: void onDisconnected(); - espMqttClientAsync* _mqttClient = nullptr; - espMqttClientSecureAsync* _mqttClientSecure = nullptr; + espMqttClientWifi* _mqttClient = nullptr; + espMqttClientWifiSecure* _mqttClientSecure = nullptr; bool _restartOnDisconnect = false; bool _startAp = false; diff --git a/networkDevices/W5500Device.cpp b/networkDevices/W5500Device.cpp index 93c3343..db414ab 100644 --- a/networkDevices/W5500Device.cpp +++ b/networkDevices/W5500Device.cpp @@ -197,7 +197,7 @@ void W5500Device::initializeMacAddress(byte *mac) void W5500Device::update() { _maintainResult = Ethernet.maintain(); - _mqttClient.loop(); + _mqttClient.update(); } int8_t W5500Device::signalStrength() diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index 92188f1..7ddf5ae 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -25,7 +25,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientSecureAsync(); + _mqttClientSecure = new espMqttClientWifiSecure(); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClientAsync(); + _mqttClient = new espMqttClientWifi(); } if(_preferences->getBool(preference_mqtt_log_enabled)) @@ -144,11 +144,11 @@ void WifiDevice::update() { if(_useEncryption) { - _mqttClientSecure->loop(); + _mqttClientSecure->update(); } else { - _mqttClient->loop(); + _mqttClient->update(); } } diff --git a/networkDevices/WifiDevice.h b/networkDevices/WifiDevice.h index 52a5c64..53414e2 100644 --- a/networkDevices/WifiDevice.h +++ b/networkDevices/WifiDevice.h @@ -5,7 +5,7 @@ #include #include "NetworkDevice.h" #include "WiFiManager.h" -#include "espMqttClientAsync.h" +#include "espMqttClientWifi.h" class WifiDevice : public NetworkDevice { @@ -58,8 +58,8 @@ private: void onDisconnected(); WiFiManager _wm; - espMqttClientAsync* _mqttClient = nullptr; - espMqttClientSecureAsync* _mqttClientSecure = nullptr; + espMqttClientWifi* _mqttClient = nullptr; + espMqttClientWifiSecure* _mqttClientSecure = nullptr; bool _restartOnDisconnect = false; bool _startAp = false; diff --git a/networkDevices/espMqttClientW5500.cpp b/networkDevices/espMqttClientW5500.cpp index eeb7e0b..aa4bd84 100644 --- a/networkDevices/espMqttClientW5500.cpp +++ b/networkDevices/espMqttClientW5500.cpp @@ -6,3 +6,8 @@ espMqttClientW5500::espMqttClientW5500(uint8_t priority, uint8_t core) { _transport = &_client; } + +void espMqttClientW5500::update() +{ + loop(); +} diff --git a/networkDevices/espMqttClientW5500.h b/networkDevices/espMqttClientW5500.h index f880ed7..76c3520 100644 --- a/networkDevices/espMqttClientW5500.h +++ b/networkDevices/espMqttClientW5500.h @@ -11,6 +11,8 @@ public: espMqttClient(); #endif + void update(); + protected: #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) espMqttClientInternals::ClientSyncW5500 _client; diff --git a/networkDevices/espMqttClientWifi.cpp b/networkDevices/espMqttClientWifi.cpp new file mode 100644 index 0000000..4ce1c87 --- /dev/null +++ b/networkDevices/espMqttClientWifi.cpp @@ -0,0 +1,97 @@ +/* +Copyright (c) 2022 Bert Melis. All rights reserved. + +This work is licensed under the terms of the MIT license. +For a copy, see or +the LICENSE file. +*/ + +#include "espMqttClientWifi.h" + +#if defined(ARDUINO_ARCH_ESP32) +espMqttClientWifi::espMqttClientWifi(uint8_t priority, uint8_t core) + : MqttClientSetup(false, priority, core) + , _client() { +#else + espMqttClient::espMqttClient() +: _client() { +#endif + _transport = &_client; +} + +void espMqttClientWifi::update() +{ + loop(); +} + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#if defined(ARDUINO_ARCH_ESP32) +espMqttClientWifiSecure::espMqttClientWifiSecure(uint8_t priority, uint8_t core) + : MqttClientSetup(false, priority, core) + , _client() { +#else + espMqttClientSecure::espMqttClientSecure() +: _client() { +#endif + _transport = &_client; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setInsecure() { + _client.client.setInsecure(); + return *this; +} + +#if defined(ARDUINO_ARCH_ESP32) +espMqttClientWifiSecure& espMqttClientWifiSecure::setCACert(const char* rootCA) { + _client.client.setCACert(rootCA); + return *this; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setCertificate(const char* clientCa) { + _client.client.setCertificate(clientCa); + return *this; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setPrivateKey(const char* privateKey) { + _client.client.setPrivateKey(privateKey); + return *this; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setPreSharedKey(const char* pskIdent, const char* psKey) { + _client.client.setPreSharedKey(pskIdent, psKey); + return *this; +} + +void espMqttClientWifiSecure::update() +{ + loop(); +} + +#elif defined(ARDUINO_ARCH_ESP8266) +espMqttClientWifiSecure& espMqttClientWifiSecure::setFingerprint(const uint8_t fingerprint[20]) { + _client.client.setFingerprint(fingerprint); + return *this; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setTrustAnchors(const X509List *ta) { + _client.client.setTrustAnchors(ta); + return *this; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setClientRSACert(const X509List *cert, const PrivateKey *sk) { + _client.client.setClientRSACert(cert, sk); + return *this; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type) { + _client.client.setClientECCert(cert, sk, allowed_usages, cert_issuer_key_type); + return *this; +} + +espMqttClientWifiSecure& espMqttClientWifiSecure::setCertStore(CertStoreBase *certStore) { + _client.client.setCertStore(certStore); + return *this; +} +#endif + +#endif diff --git a/networkDevices/espMqttClientWifi.h b/networkDevices/espMqttClientWifi.h new file mode 100644 index 0000000..e78527c --- /dev/null +++ b/networkDevices/espMqttClientWifi.h @@ -0,0 +1,69 @@ +/* +Copyright (c) 2022 Bert Melis. All rights reserved. + +API is based on the original work of Marvin Roger: +https://github.com/marvinroger/async-mqtt-client + +This work is licensed under the terms of the MIT license. +For a copy, see or +the LICENSE file. +*/ + +#pragma once + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#include "Transport/ClientSync.h" +#include "Transport/ClientSecureSync.h" +#elif defined(__linux__) +#include "Transport/ClientPosix.h" +#endif + +#include "MqttClientSetup.h" + +class espMqttClientWifi : public MqttClientSetup { +public: +#if defined(ARDUINO_ARCH_ESP32) + explicit espMqttClientWifi(uint8_t priority = 1, uint8_t core = 1); +#else + espMqttClient(); +#endif + + void update(); + +protected: +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) + espMqttClientInternals::ClientSync _client; +#elif defined(__linux__) + espMqttClientInternals::ClientPosix _client; +#endif +}; + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +class espMqttClientWifiSecure : public MqttClientSetup { +public: +#if defined(ARDUINO_ARCH_ESP32) + explicit espMqttClientWifiSecure(uint8_t priority = 1, uint8_t core = 1); +#else + espMqttClientSecure(); +#endif + espMqttClientWifiSecure& setInsecure(); +#if defined(ARDUINO_ARCH_ESP32) + espMqttClientWifiSecure& setCACert(const char* rootCA); + espMqttClientWifiSecure& setCertificate(const char* clientCa); + espMqttClientWifiSecure& setPrivateKey(const char* privateKey); + espMqttClientWifiSecure& setPreSharedKey(const char* pskIdent, const char* psKey); +#else + espMqttClientSecure& setFingerprint(const uint8_t fingerprint[20]); + espMqttClientSecure& setTrustAnchors(const X509List *ta); + espMqttClientSecure& setClientRSACert(const X509List *cert, const PrivateKey *sk); + espMqttClientSecure& setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type); + espMqttClientSecure& setCertStore(CertStoreBase *certStore); +#endif + + void update(); + +protected: + espMqttClientInternals::ClientSecureSync _client; +}; + +#endif From aa224e8c7d91ac5eb90c090949118743d6a73129 Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 26 Feb 2023 23:04:21 +0100 Subject: [PATCH 04/12] upgrad esp mqtt lib --- CMakeLists.txt | 1 - lib/espMqttClient/docs/index.md | 13 ++- .../largepayload-esp8266.ino | 20 +++- .../examples/ota-esp8266/ota-esp8266.ino | 35 +++++-- .../examples/simple-esp32/simple-esp32.ino | 21 +++- .../simple-esp8266/simple-esp8266.ino | 20 +++- .../simpleAsync-esp32/simpleAsync-esp32.ino | 21 +++- .../simpleAsync-esp8266.ino | 21 +++- .../examples/tls-esp32/tls-esp32.ino | 29 ++++-- .../examples/tls-esp8266/tls-esp8266.ino | 20 +++- lib/espMqttClient/src/MqttClient.cpp | 18 +++- lib/espMqttClient/src/MqttClient.h | 8 +- lib/espMqttClient/src/MqttClientSetup.h | 5 + lib/espMqttClient/src/Outbox.h | 4 + lib/espMqttClient/src/espMqttClient.cpp | 8 +- lib/espMqttClient/src/espMqttClient.h | 4 +- main.cpp | 4 +- networkDevices/EthLan8720Device.cpp | 8 +- networkDevices/EthLan8720Device.h | 6 +- networkDevices/W5500Device.cpp | 2 +- networkDevices/WifiDevice.cpp | 8 +- networkDevices/WifiDevice.h | 6 +- networkDevices/espMqttClientWifi.cpp | 97 ------------------- networkDevices/espMqttClientWifi.h | 69 ------------- 24 files changed, 219 insertions(+), 229 deletions(-) delete mode 100644 networkDevices/espMqttClientWifi.cpp delete mode 100644 networkDevices/espMqttClientWifi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dab8e13..7ee604d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,6 @@ file(GLOB SRCFILES networkDevices/EthLan8720Device.cpp networkDevices/ClientSyncW5500.cpp networkDevices/espMqttClientW5500.cpp - networkDevices/espMqttClientWifi.cpp QueryCommand.h NukiWrapper.cpp NukiOpenerWrapper.cpp diff --git a/lib/espMqttClient/docs/index.md b/lib/espMqttClient/docs/index.md index 84d1122..2335054 100644 --- a/lib/espMqttClient/docs/index.md +++ b/lib/espMqttClient/docs/index.md @@ -66,7 +66,7 @@ espMqttClientAsync() ``` Instantiate a new espMqttClient or espMqttSecure object. -On ESP32, two optional parameters are available: `espMqttClient(uint8_t priority = 1, uint8_t core = 1)`. This will change the priority of the MQTT client task and the core on which it runs (higher priority = more cpu-time). +On ESP32, three optional parameters are available: `espMqttClient(bool internalTask = true, uint8_t priority = 1, uint8_t core = 1)`. By default, espMqttclient creates its own task to manage TCP. By setting `internalTask` to false, no task will be created and you will be responsible yourself to call `espMqttClient.loop()`. `priority` changes the priority of the MQTT client task and the core on which it runs (higher priority = more cpu-time). For the asynchronous version, use `espMqttClientAsync`. @@ -150,6 +150,15 @@ Set the server. - **`host`**: Host of the server, expects a null-terminated char array (c-string) - **`port`**: Port of the server +```cpp +espMqttClient& setTimeout(uint16_t timeout) +``` + +Set the timeout for packets that need acknowledgement. Defaults to 10 seconds. +When no acknowledgement has been received from the broker after sending a packet, the client will retransmit **all** the packets in the queue. + +* **`timeout`**: Timeout in seconds + #### Options for TLS connections All common options from WiFiClientSecure to setup an encrypted connection are made available. These include: @@ -324,7 +333,7 @@ Keep in mind that this may also delete any session data and therefore is not MQT void loop() ``` -This is the worker function of the MQTT client. For ESP8266 you must call this function in the Arduino loop. For ESP32 this function is only used internally and is not available in the API. +This is the worker function of the MQTT client. For ESP8266 you must call this function in the Arduino loop. For ESP32 you have to call this function yourself **only if you have disabled the internal task** (see the constructors). ```cpp const char* getClientId() const diff --git a/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino b/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino index aff6fac..ce4123f 100644 --- a/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino +++ b/lib/espMqttClient/examples/largepayload-esp8266/largepayload-esp8266.ino @@ -1,4 +1,6 @@ #include +#include + #include #define WIFI_SSID "yourSSID" @@ -10,6 +12,8 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClient mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; size_t fetchPayload(uint8_t* dest, size_t len, size_t index) { Serial.printf("filling buffer at index %zu\n", index); @@ -33,7 +37,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void onWiFiConnect(const WiFiEventStationModeGotIP& event) { @@ -56,7 +66,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -85,5 +96,10 @@ void setup() { } void loop() { + static uint32_t currentMillis = millis(); + mqttClient.loop(); + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } } \ No newline at end of file diff --git a/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino b/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino index 5152d9b..f82b36c 100644 --- a/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino +++ b/lib/espMqttClient/examples/ota-esp8266/ota-esp8266.ino @@ -1,5 +1,7 @@ #include #include +#include + #include #define WIFI_SSID "yourSSID" @@ -13,6 +15,8 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClient mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; bool disconnectFlag = false; bool restartFlag = false; @@ -23,7 +27,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void onWiFiConnect(const WiFiEventStationModeGotIP& event) { @@ -53,7 +63,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { } if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -125,16 +136,22 @@ void setup() { } void loop() { - mqttClient.loop(); - - if (disconnectFlag) { - // it's safe to call this multiple times - mqttClient.disconnect(); - } - if (restartFlag) { Serial.println("Rebooting... See you next time!"); Serial.flush(); ESP.reset(); } + + static uint32_t currentMillis = millis(); + + mqttClient.loop(); + + if (!disconnectFlag && reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } + + if (disconnectFlag) { + // it's safe to call this multiple times + mqttClient.disconnect(); + } } \ No newline at end of file diff --git a/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino b/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino index 27dc6b9..4698587 100644 --- a/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino +++ b/lib/espMqttClient/examples/simple-esp32/simple-esp32.ino @@ -1,4 +1,6 @@ #include +#include + #include #define WIFI_SSID "yourSSID" @@ -8,6 +10,8 @@ #define MQTT_PORT 1883 espMqttClient mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -16,7 +20,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void WiFiEvent(WiFiEvent_t event) { @@ -57,7 +67,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -122,5 +133,9 @@ void setup() { } void loop() { - // nothing to do here + static uint32_t currentMillis = millis(); + + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } } diff --git a/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino b/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino index 39e725d..6eda510 100644 --- a/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino +++ b/lib/espMqttClient/examples/simple-esp8266/simple-esp8266.ino @@ -1,4 +1,6 @@ #include +#include + #include #define WIFI_SSID "yourSSID" @@ -10,6 +12,8 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClient mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -18,7 +22,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void onWiFiConnect(const WiFiEventStationModeGotIP& event) { @@ -51,7 +61,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -117,5 +128,10 @@ void setup() { } void loop() { + static uint32_t currentMillis = millis(); + mqttClient.loop(); + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } } \ No newline at end of file diff --git a/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino b/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino index a556789..afd2445 100644 --- a/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino +++ b/lib/espMqttClient/examples/simpleAsync-esp32/simpleAsync-esp32.ino @@ -1,4 +1,6 @@ #include +#include + #include #define WIFI_SSID "yourSSID" @@ -8,6 +10,8 @@ #define MQTT_PORT 1883 espMqttClientAsync mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -16,7 +20,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void WiFiEvent(WiFiEvent_t event) { @@ -57,7 +67,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -122,5 +133,9 @@ void setup() { } void loop() { - // nothing to do here + static uint32_t currentMillis = millis(); + + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } } diff --git a/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino b/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino index 76c20a9..08c88b1 100644 --- a/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino +++ b/lib/espMqttClient/examples/simpleAsync-esp8266/simpleAsync-esp8266.ino @@ -1,4 +1,6 @@ #include +#include + #include #define WIFI_SSID "yourSSID" @@ -10,6 +12,8 @@ WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClientAsync mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -18,7 +22,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void onWiFiConnect(const WiFiEventStationModeGotIP& event) { @@ -51,7 +61,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -117,5 +128,9 @@ void setup() { } void loop() { - // nothing to do here + static uint32_t currentMillis = millis(); + + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } } \ No newline at end of file diff --git a/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino b/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino index 551d241..b759aff 100644 --- a/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino +++ b/lib/espMqttClient/examples/tls-esp32/tls-esp32.ino @@ -1,4 +1,6 @@ #include +#include + #include #define WIFI_SSID "yourSSID" @@ -15,6 +17,8 @@ const char rootCA[] = \ "-----END CERTIFICATE-----\n"; espMqttClientSecure mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -23,7 +27,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void WiFiEvent(WiFiEvent_t event) { @@ -61,7 +71,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -130,15 +141,21 @@ void setup() { } void loop() { + static uint32_t currentMillis = millis(); + + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } + static uint32_t lastMillis = 0; - if (millis() - lastMillis > 5000) { - lastMillis = millis(); + if (currentMillis - lastMillis > 5000) { + lastMillis = currentMillis; Serial.printf("heap: %u\n", ESP.getFreeHeap()); } static uint32_t millisDisconnect = 0; - if (millis() - millisDisconnect > 60000) { - millisDisconnect = millis(); + if (currentMillis - millisDisconnect > 60000) { + millisDisconnect = currentMillis; mqttClient.disconnect(); } } diff --git a/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino b/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino index b196a8c..5be5b11 100644 --- a/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino +++ b/lib/espMqttClient/examples/tls-esp8266/tls-esp8266.ino @@ -1,4 +1,6 @@ #include +#include + #include #define WIFI_SSID "yourSSID" @@ -13,6 +15,8 @@ const uint8_t fingerprint[] = {0xee, 0xbc, 0x4b, 0xf8, 0x57, 0xe3, 0xd3, 0xe4, 0 WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; espMqttClientSecure mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; void connectToWiFi() { Serial.println("Connecting to Wi-Fi..."); @@ -21,7 +25,13 @@ void connectToWiFi() { void connectToMqtt() { Serial.println("Connecting to MQTT..."); - mqttClient.connect(); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } } void onWiFiConnect(const WiFiEventStationModeGotIP& event) { @@ -54,7 +64,8 @@ void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); if (WiFi.isConnected()) { - connectToMqtt(); + reconnectMqtt = true; + lastReconnect = millis(); } } @@ -121,5 +132,10 @@ void setup() { } void loop() { + static uint32_t currentMillis = millis(); + mqttClient.loop(); + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } } \ No newline at end of file diff --git a/lib/espMqttClient/src/MqttClient.cpp b/lib/espMqttClient/src/MqttClient.cpp index 9868c27..af7f1f9 100644 --- a/lib/espMqttClient/src/MqttClient.cpp +++ b/lib/espMqttClient/src/MqttClient.cpp @@ -42,6 +42,7 @@ MqttClient::MqttClient() , _willPayloadLength(0) , _willQos(0) , _willRetain(false) +, _timeout(10000) , _state(State::disconnected) , _generatedClientId{0} , _packetId(0) @@ -373,6 +374,9 @@ int MqttClient::_sendPacket() { EMC_SEMAPHORE_GIVE(); return -1; } + // handle with care! millis() returns unsigned 32 bit, token is void* + static_assert(sizeof(uint32_t) <= sizeof(void*), "the size of uint32_t must be smaller than or equal to the size of a pointer"); + packet->token = reinterpret_cast(millis()); _lastClientActivity = millis(); _bytesSent += written; emc_log_i("tx %zu/%zu (%02x)", _bytesSent, packet->size(), packet->packetType()); @@ -392,8 +396,7 @@ bool MqttClient::_advanceOutbox() { if (packet->removable()) { _outbox.removeCurrent(); } else { - // handle with care! millis() returns unsigned 32 bit, token is void* - packet->token = reinterpret_cast(millis()); + // we already set 'dup' here, in case we have to retry if ((packet->packetType()) == PacketType.PUBLISH) packet->setDup(); _outbox.next(); } @@ -496,6 +499,17 @@ void MqttClient::_checkPing() { } } +void MqttClient::_checkTimeout() { + espMqttClientInternals::Outbox::Iterator it = _outbox.front(); + if (it && _bytesSent == 0) { // check that we're not busy sending + if (millis() - *((uint32_t*)&(it.get()->token)) > _timeout) { // NOLINT(readability/casting) + // TODO(bertmelis): fix ugly casting hack + emc_log_w("Packet ack timeout, retrying"); + _outbox.resetCurrent(); + } + } +} + void MqttClient::_onConnack() { if (_parser.getPacket().variableHeader.fixed.connackVarHeader.returnCode == 0x00) { _pingSent = false; // reset after keepalive timeout disconnect diff --git a/lib/espMqttClient/src/MqttClient.h b/lib/espMqttClient/src/MqttClient.h index f95b966..382997c 100644 --- a/lib/espMqttClient/src/MqttClient.h +++ b/lib/espMqttClient/src/MqttClient.h @@ -65,17 +65,13 @@ class MqttClient { uint16_t publish(const char* topic, uint8_t qos, bool retain, espMqttClientTypes::PayloadCallback callback, size_t length); void clearQueue(bool deleteSessionData = false); // Not MQTT compliant and may cause unpredictable results when `deleteSessionData` = true! const char* getClientId() const; - #if defined(ARDUINO_ARCH_ESP32) + void loop(); protected: - #endif - void loop(); #if defined(ARDUINO_ARCH_ESP32) explicit MqttClient(bool useTask, uint8_t priority = 1, uint8_t core = 1); bool _useTask; #else - - protected: MqttClient(); #endif espMqttClientInternals::Transport* _transport; @@ -102,6 +98,7 @@ class MqttClient { uint16_t _willPayloadLength; uint8_t _willQos; bool _willRetain; + uint32_t _timeout; // state is protected to allow state changes by the transport system, defined in child classes // eg. to allow AsyncTCP @@ -166,6 +163,7 @@ class MqttClient { bool _advanceOutbox(); void _checkIncoming(); void _checkPing(); + void _checkTimeout(); void _onConnack(); void _onPublish(); diff --git a/lib/espMqttClient/src/MqttClientSetup.h b/lib/espMqttClient/src/MqttClientSetup.h index a96bd48..40c68af 100644 --- a/lib/espMqttClient/src/MqttClientSetup.h +++ b/lib/espMqttClient/src/MqttClientSetup.h @@ -68,6 +68,11 @@ class MqttClientSetup : public MqttClient { return static_cast(*this); } + T& setTimeout(uint16_t timeout) { + _timeout = timeout * 1000; // s to ms conversion, will also do 16 to 32 bit conversion + return static_cast(*this); + } + T& onConnect(espMqttClientTypes::OnConnectCallback callback) { _onConnectCallback = callback; return static_cast(*this); diff --git a/lib/espMqttClient/src/Outbox.h b/lib/espMqttClient/src/Outbox.h index 5e1edcf..7f0d543 100644 --- a/lib/espMqttClient/src/Outbox.h +++ b/lib/espMqttClient/src/Outbox.h @@ -138,6 +138,10 @@ class Outbox { return nullptr; } + void resetCurrent() { + _current = _first; + } + Iterator front() const { Iterator it; it._node = _first; diff --git a/lib/espMqttClient/src/espMqttClient.cpp b/lib/espMqttClient/src/espMqttClient.cpp index 34e789b..bda3038 100644 --- a/lib/espMqttClient/src/espMqttClient.cpp +++ b/lib/espMqttClient/src/espMqttClient.cpp @@ -9,8 +9,8 @@ the LICENSE file. #include "espMqttClient.h" #if defined(ARDUINO_ARCH_ESP32) -espMqttClient::espMqttClient(uint8_t priority, uint8_t core) -: MqttClientSetup(true, priority, core) +espMqttClient::espMqttClient(bool internalTask, uint8_t priority, uint8_t core) +: MqttClientSetup(internalTask, priority, core) , _client() { #else espMqttClient::espMqttClient() @@ -21,8 +21,8 @@ espMqttClient::espMqttClient() #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32) -espMqttClientSecure::espMqttClientSecure(uint8_t priority, uint8_t core) -: MqttClientSetup(priority, core) +espMqttClientSecure::espMqttClientSecure(bool internalTask, uint8_t priority, uint8_t core) +: MqttClientSetup(internalTask, priority, core) , _client() { #else espMqttClientSecure::espMqttClientSecure() diff --git a/lib/espMqttClient/src/espMqttClient.h b/lib/espMqttClient/src/espMqttClient.h index 9ee2279..a2aba97 100644 --- a/lib/espMqttClient/src/espMqttClient.h +++ b/lib/espMqttClient/src/espMqttClient.h @@ -23,7 +23,7 @@ the LICENSE file. class espMqttClient : public MqttClientSetup { public: #if defined(ARDUINO_ARCH_ESP32) - explicit espMqttClient(uint8_t priority = 1, uint8_t core = 1); + explicit espMqttClient(bool internalTask = true, uint8_t priority = 1, uint8_t core = 1); #else espMqttClient(); #endif @@ -40,7 +40,7 @@ class espMqttClient : public MqttClientSetup { class espMqttClientSecure : public MqttClientSetup { public: #if defined(ARDUINO_ARCH_ESP32) - explicit espMqttClientSecure(uint8_t priority = 1, uint8_t core = 1); + explicit espMqttClientSecure(bool internalTask = true, uint8_t priority = 1, uint8_t core = 1); #else espMqttClientSecure(); #endif diff --git a/main.cpp b/main.cpp index 39780c9..19b37eb 100644 --- a/main.cpp +++ b/main.cpp @@ -106,8 +106,8 @@ void setupTasks() // configMAX_PRIORITIES is 25 xTaskCreatePinnedToCore(networkTask, "ntw", 8192, NULL, 3, &networkTaskHandle, 1); - xTaskCreatePinnedToCore(nukiTask, "nuki", 4096, NULL, 2, &nukiTaskHandle, 1); - xTaskCreatePinnedToCore(presenceDetectionTask, "prdet", 768, NULL, 5, &presenceDetectionTaskHandle, 1); + xTaskCreatePinnedToCore(nukiTask, "nuki", 3328, NULL, 2, &nukiTaskHandle, 1); + xTaskCreatePinnedToCore(presenceDetectionTask, "prdet", 896, NULL, 5, &presenceDetectionTaskHandle, 1); } uint32_t getRandomId() diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index 3c5a75d..5311625 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -25,7 +25,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientWifiSecure(); + _mqttClientSecure = new espMqttClientSecure(); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClientWifi(); + _mqttClient = new espMqttClient(); } if(_preferences->getBool(preference_mqtt_log_enabled)) @@ -112,11 +112,11 @@ void EthLan8720Device::update() { if(_useEncryption) { - _mqttClientSecure->update(); + _mqttClientSecure->loop(); } else { - _mqttClient->update(); + _mqttClient->loop(); } } diff --git a/networkDevices/EthLan8720Device.h b/networkDevices/EthLan8720Device.h index 1d23615..ad60793 100644 --- a/networkDevices/EthLan8720Device.h +++ b/networkDevices/EthLan8720Device.h @@ -4,7 +4,7 @@ #include #include #include "NetworkDevice.h" -#include "espMqttClientWifi.h" +#include "espMqttClient.h" class EthLan8720Device : public NetworkDevice { @@ -54,8 +54,8 @@ public: private: void onDisconnected(); - espMqttClientWifi* _mqttClient = nullptr; - espMqttClientWifiSecure* _mqttClientSecure = nullptr; + espMqttClient* _mqttClient = nullptr; + espMqttClientSecure* _mqttClientSecure = nullptr; bool _restartOnDisconnect = false; bool _startAp = false; diff --git a/networkDevices/W5500Device.cpp b/networkDevices/W5500Device.cpp index db414ab..93c3343 100644 --- a/networkDevices/W5500Device.cpp +++ b/networkDevices/W5500Device.cpp @@ -197,7 +197,7 @@ void W5500Device::initializeMacAddress(byte *mac) void W5500Device::update() { _maintainResult = Ethernet.maintain(); - _mqttClient.update(); + _mqttClient.loop(); } int8_t W5500Device::signalStrength() diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index 7ddf5ae..a3a04a5 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -25,7 +25,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientWifiSecure(); + _mqttClientSecure = new espMqttClientSecure(); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClientWifi(); + _mqttClient = new espMqttClient(); } if(_preferences->getBool(preference_mqtt_log_enabled)) @@ -144,11 +144,11 @@ void WifiDevice::update() { if(_useEncryption) { - _mqttClientSecure->update(); + _mqttClientSecure->loop(); } else { - _mqttClient->update(); + _mqttClient->loop(); } } diff --git a/networkDevices/WifiDevice.h b/networkDevices/WifiDevice.h index 53414e2..8d972cb 100644 --- a/networkDevices/WifiDevice.h +++ b/networkDevices/WifiDevice.h @@ -5,7 +5,7 @@ #include #include "NetworkDevice.h" #include "WiFiManager.h" -#include "espMqttClientWifi.h" +#include "espMqttClient.h" class WifiDevice : public NetworkDevice { @@ -58,8 +58,8 @@ private: void onDisconnected(); WiFiManager _wm; - espMqttClientWifi* _mqttClient = nullptr; - espMqttClientWifiSecure* _mqttClientSecure = nullptr; + espMqttClient* _mqttClient = nullptr; + espMqttClientSecure* _mqttClientSecure = nullptr; bool _restartOnDisconnect = false; bool _startAp = false; diff --git a/networkDevices/espMqttClientWifi.cpp b/networkDevices/espMqttClientWifi.cpp deleted file mode 100644 index 4ce1c87..0000000 --- a/networkDevices/espMqttClientWifi.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright (c) 2022 Bert Melis. All rights reserved. - -This work is licensed under the terms of the MIT license. -For a copy, see or -the LICENSE file. -*/ - -#include "espMqttClientWifi.h" - -#if defined(ARDUINO_ARCH_ESP32) -espMqttClientWifi::espMqttClientWifi(uint8_t priority, uint8_t core) - : MqttClientSetup(false, priority, core) - , _client() { -#else - espMqttClient::espMqttClient() -: _client() { -#endif - _transport = &_client; -} - -void espMqttClientWifi::update() -{ - loop(); -} - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#if defined(ARDUINO_ARCH_ESP32) -espMqttClientWifiSecure::espMqttClientWifiSecure(uint8_t priority, uint8_t core) - : MqttClientSetup(false, priority, core) - , _client() { -#else - espMqttClientSecure::espMqttClientSecure() -: _client() { -#endif - _transport = &_client; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setInsecure() { - _client.client.setInsecure(); - return *this; -} - -#if defined(ARDUINO_ARCH_ESP32) -espMqttClientWifiSecure& espMqttClientWifiSecure::setCACert(const char* rootCA) { - _client.client.setCACert(rootCA); - return *this; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setCertificate(const char* clientCa) { - _client.client.setCertificate(clientCa); - return *this; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setPrivateKey(const char* privateKey) { - _client.client.setPrivateKey(privateKey); - return *this; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setPreSharedKey(const char* pskIdent, const char* psKey) { - _client.client.setPreSharedKey(pskIdent, psKey); - return *this; -} - -void espMqttClientWifiSecure::update() -{ - loop(); -} - -#elif defined(ARDUINO_ARCH_ESP8266) -espMqttClientWifiSecure& espMqttClientWifiSecure::setFingerprint(const uint8_t fingerprint[20]) { - _client.client.setFingerprint(fingerprint); - return *this; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setTrustAnchors(const X509List *ta) { - _client.client.setTrustAnchors(ta); - return *this; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setClientRSACert(const X509List *cert, const PrivateKey *sk) { - _client.client.setClientRSACert(cert, sk); - return *this; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type) { - _client.client.setClientECCert(cert, sk, allowed_usages, cert_issuer_key_type); - return *this; -} - -espMqttClientWifiSecure& espMqttClientWifiSecure::setCertStore(CertStoreBase *certStore) { - _client.client.setCertStore(certStore); - return *this; -} -#endif - -#endif diff --git a/networkDevices/espMqttClientWifi.h b/networkDevices/espMqttClientWifi.h deleted file mode 100644 index e78527c..0000000 --- a/networkDevices/espMqttClientWifi.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2022 Bert Melis. All rights reserved. - -API is based on the original work of Marvin Roger: -https://github.com/marvinroger/async-mqtt-client - -This work is licensed under the terms of the MIT license. -For a copy, see or -the LICENSE file. -*/ - -#pragma once - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#include "Transport/ClientSync.h" -#include "Transport/ClientSecureSync.h" -#elif defined(__linux__) -#include "Transport/ClientPosix.h" -#endif - -#include "MqttClientSetup.h" - -class espMqttClientWifi : public MqttClientSetup { -public: -#if defined(ARDUINO_ARCH_ESP32) - explicit espMqttClientWifi(uint8_t priority = 1, uint8_t core = 1); -#else - espMqttClient(); -#endif - - void update(); - -protected: -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) - espMqttClientInternals::ClientSync _client; -#elif defined(__linux__) - espMqttClientInternals::ClientPosix _client; -#endif -}; - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -class espMqttClientWifiSecure : public MqttClientSetup { -public: -#if defined(ARDUINO_ARCH_ESP32) - explicit espMqttClientWifiSecure(uint8_t priority = 1, uint8_t core = 1); -#else - espMqttClientSecure(); -#endif - espMqttClientWifiSecure& setInsecure(); -#if defined(ARDUINO_ARCH_ESP32) - espMqttClientWifiSecure& setCACert(const char* rootCA); - espMqttClientWifiSecure& setCertificate(const char* clientCa); - espMqttClientWifiSecure& setPrivateKey(const char* privateKey); - espMqttClientWifiSecure& setPreSharedKey(const char* pskIdent, const char* psKey); -#else - espMqttClientSecure& setFingerprint(const uint8_t fingerprint[20]); - espMqttClientSecure& setTrustAnchors(const X509List *ta); - espMqttClientSecure& setClientRSACert(const X509List *cert, const PrivateKey *sk); - espMqttClientSecure& setClientECCert(const X509List *cert, const PrivateKey *sk, unsigned allowed_usages, unsigned cert_issuer_key_type); - espMqttClientSecure& setCertStore(CertStoreBase *certStore); -#endif - - void update(); - -protected: - espMqttClientInternals::ClientSecureSync _client; -}; - -#endif From c0b3cda876eba8d6227725fa1136e6eb0bb8c217 Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 27 Feb 2023 16:32:58 +0100 Subject: [PATCH 05/12] set interTask flag for mqtt --- networkDevices/EthLan8720Device.cpp | 4 ++-- networkDevices/WifiDevice.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index 5311625..add2e49 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -25,7 +25,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientSecure(); + _mqttClientSecure = new espMqttClientSecure(false); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClient(); + _mqttClient = new espMqttClient(false); } if(_preferences->getBool(preference_mqtt_log_enabled)) diff --git a/networkDevices/WifiDevice.cpp b/networkDevices/WifiDevice.cpp index a3a04a5..610b8a2 100644 --- a/networkDevices/WifiDevice.cpp +++ b/networkDevices/WifiDevice.cpp @@ -25,7 +25,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) { Log->println(F("MQTT over TLS.")); Log->println(_ca); - _mqttClientSecure = new espMqttClientSecure(); + _mqttClientSecure = new espMqttClientSecure(false); _mqttClientSecure->setCACert(_ca); if(crtLength > 1 && keyLength > 1) // length is 1 when empty { @@ -38,7 +38,7 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences) } else { Log->println(F("MQTT without TLS.")); - _mqttClient = new espMqttClient(); + _mqttClient = new espMqttClient(false); } if(_preferences->getBool(preference_mqtt_log_enabled)) From 3d81554ad2924bb3166ce2a7b973f1333093db6d Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 27 Feb 2023 16:36:56 +0100 Subject: [PATCH 06/12] change text --- WebCfgServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index 652c1b1..17209d1 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -1113,7 +1113,7 @@ const std::vector> WebCfgServer::getNetworkDetectionOp { std::vector> options; - options.push_back(std::make_pair("1", "Disable W5500 (Wifi only)")); + options.push_back(std::make_pair("1", "Wifi only")); options.push_back(std::make_pair("2", "Detect W5500 (GPIO CS=5; SCK=18; MISO=19; MOSI=23; RST=33)")); options.push_back(std::make_pair("3", "M5Stack Atom POE (W5500)")); options.push_back(std::make_pair("4", "Olimex ESP32-POE / ESP-POE-ISO")); From 709135d8cac06718279cf6a808aa6702d75edeb6 Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 2 Mar 2023 19:50:38 +0100 Subject: [PATCH 07/12] add support for WT32-ETH01 --- Network.cpp | 68 +++++++++++++++-------------- Network.h | 3 +- WebCfgServer.cpp | 1 + networkDevices/EthLan8720Device.cpp | 13 ++++-- networkDevices/EthLan8720Device.h | 20 ++++++++- 5 files changed, 67 insertions(+), 38 deletions(-) diff --git a/Network.cpp b/Network.cpp index 5674cb2..3ce6995 100644 --- a/Network.cpp +++ b/Network.cpp @@ -56,53 +56,55 @@ void Network::setupDevice() } else { - if(hardwareDetect == 1) + Log->print(F("Network device: ")); + switch (hardwareDetect) { - Log->println(F("W5500 hardware is disabled, using Wifi.")); - _networkDeviceType = NetworkDeviceType::WiFi; - } - else if(hardwareDetect == 2) - { - Log->print(F("Using PIN ")); - Log->print(hardwareDetectGpio); - Log->println(F(" for network device selection")); + case 1: + Log->println(F("Wifi only")); + _networkDeviceType = NetworkDeviceType::WiFi; + break; + case 2: + Log->print(F("Using PIN ")); + Log->print(hardwareDetectGpio); + Log->println(F(" for network device selection")); - pinMode(hardwareDetectGpio, INPUT_PULLUP); - _networkDeviceType = digitalRead(hardwareDetectGpio) == HIGH ? NetworkDeviceType::WiFi : NetworkDeviceType::W5500; - } - else if(hardwareDetect == 3) - { - Log->println(F("W5500 on M5Stack Atom POE")); - _networkDeviceType = NetworkDeviceType::W5500; - } - else if(hardwareDetect == 4) - { - Log->println(F("Olimex ESP32-POE / ESP-POE-ISO")); - _networkDeviceType = NetworkDeviceType::LAN8720; - } - else - { - Log->println(F("Unknown hardware selected, falling back to Wifi.")); - _networkDeviceType = NetworkDeviceType::WiFi; + pinMode(hardwareDetectGpio, INPUT_PULLUP); + _networkDeviceType = digitalRead(hardwareDetectGpio) == HIGH ? NetworkDeviceType::WiFi : NetworkDeviceType::W5500; + break; + case 3: + Log->println(F("W5500 on M5Stack Atom POE")); + _networkDeviceType = NetworkDeviceType::W5500; + break; + case 4: + Log->println(F("Olimex ESP32-POE / ESP-POE-ISO")); + _networkDeviceType = NetworkDeviceType::Olimex_LAN8720; + break; + case 5: + Log->println(F("WT32-ETH01")); + _networkDeviceType = NetworkDeviceType::WT32_LAN8720; + break; + default: + Log->println(F("Unknown hardware selected, falling back to Wifi.")); + _networkDeviceType = NetworkDeviceType::WiFi; + break; } } - switch(_networkDeviceType) + switch (_networkDeviceType) { case NetworkDeviceType::W5500: - Log->println(F("Network device: W5500")); _device = new W5500Device(_hostname, _preferences, hardwareDetect); break; - case NetworkDeviceType::LAN8720: - Log->println(F("Network device: LAN8720")); - _device = new EthLan8720Device(_hostname, _preferences); + case NetworkDeviceType::Olimex_LAN8720: + _device = new EthLan8720Device(_hostname, _preferences, ETH_PHY_ADDR, 12, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLOCK_GPIO17_OUT); + break; + case NetworkDeviceType::WT32_LAN8720: + _device = new EthLan8720Device(_hostname, _preferences, 1, 16); break; case NetworkDeviceType::WiFi: - Log->println(F("Network device: Builtin WiFi")); _device = new WifiDevice(_hostname, _preferences); break; default: - Log->println(F("Unknown network device type, defaulting to WiFi")); _device = new WifiDevice(_hostname, _preferences); break; } diff --git a/Network.h b/Network.h index 7b99131..c30cc8b 100644 --- a/Network.h +++ b/Network.h @@ -10,7 +10,8 @@ enum class NetworkDeviceType { WiFi, W5500, - LAN8720 + Olimex_LAN8720, + WT32_LAN8720 }; #define JSON_BUFFER_SIZE 1024 diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index 17209d1..91de67a 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -1117,6 +1117,7 @@ const std::vector> WebCfgServer::getNetworkDetectionOp options.push_back(std::make_pair("2", "Detect W5500 (GPIO CS=5; SCK=18; MISO=19; MOSI=23; RST=33)")); options.push_back(std::make_pair("3", "M5Stack Atom POE (W5500)")); options.push_back(std::make_pair("4", "Olimex ESP32-POE / ESP-POE-ISO")); + options.push_back(std::make_pair("5", "WT32-ETH01")); return options; } diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index add2e49..fe9abc4 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -10,8 +10,15 @@ #include "espMqttClient.h" #include "../RestartReason.h" -EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _preferences) -: NetworkDevice(hostname) +EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _preferences, uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t ethtype, eth_clock_mode_t clock_mode, bool use_mac_from_efuse) +: NetworkDevice(hostname), + _phy_addr(phy_addr), + _power(power), + _mdc(mdc), + _mdio(mdio), + _type(ethtype), + _clock_mode(clock_mode), + _use_mac_from_efuse(use_mac_from_efuse) { _restartOnDisconnect = _preferences->getBool(preference_restart_on_disconnect); @@ -62,7 +69,7 @@ void EthLan8720Device::initialize() { delay(250); - _hardwareInitialized = ETH.begin(ETH_PHY_ADDR, 12, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLOCK_GPIO17_OUT); + _hardwareInitialized = ETH.begin(_phy_addr, _power, _mdc, _mdio, _type, _clock_mode, _use_mac_from_efuse); if(_restartOnDisconnect) { diff --git a/networkDevices/EthLan8720Device.h b/networkDevices/EthLan8720Device.h index ad60793..1a32c5b 100644 --- a/networkDevices/EthLan8720Device.h +++ b/networkDevices/EthLan8720Device.h @@ -5,11 +5,21 @@ #include #include "NetworkDevice.h" #include "espMqttClient.h" +#include class EthLan8720Device : public NetworkDevice { + public: - EthLan8720Device(const String& hostname, Preferences* _preferences); + EthLan8720Device(const String& hostname, + Preferences* _preferences, + uint8_t phy_addr = ETH_PHY_ADDR, + int power = ETH_PHY_POWER, + int mdc = ETH_PHY_MDC, + int mdio = ETH_PHY_MDIO, + eth_phy_type_t ethtype = ETH_PHY_TYPE, + eth_clock_mode_t clock_mode = ETH_CLK_MODE, + bool use_mac_from_efuse = false); const String deviceName() const override; @@ -63,6 +73,14 @@ private: bool _useEncryption = false; bool _hardwareInitialized = false; + uint8_t _phy_addr; + int _power; + int _mdc; + int _mdio; + eth_phy_type_t _type; + eth_clock_mode_t _clock_mode; + bool _use_mac_from_efuse; + char _ca[TLS_CA_MAX_SIZE] = {0}; char _cert[TLS_CERT_MAX_SIZE] = {0}; char _key[TLS_KEY_MAX_SIZE] = {0}; From d6c02238005eb4b5ff96d62b4f9165d5fe5997ec Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 2 Mar 2023 20:11:30 +0100 Subject: [PATCH 08/12] print IP address for LAN8720 devices --- Config.h | 2 +- networkDevices/EthLan8720Device.cpp | 15 +++++++++++++-- networkDevices/EthLan8720Device.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Config.h b/Config.h index f1d34de..647bba9 100644 --- a/Config.h +++ b/Config.h @@ -1,6 +1,6 @@ #pragma once -#define NUKI_HUB_VERSION "8.12-pre-10" +#define NUKI_HUB_VERSION "8.12-pre-11" #define MQTT_QOS_LEVEL 1 #define MQTT_CLEAN_SESSIONS false \ No newline at end of file diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index fe9abc4..98f2e60 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -69,6 +69,7 @@ void EthLan8720Device::initialize() { delay(250); + WiFi.setHostname(_hostname.c_str()); _hardwareInitialized = ETH.begin(_phy_addr, _power, _mdc, _mdio, _type, _clock_mode, _use_mac_from_efuse); if(_restartOnDisconnect) @@ -102,7 +103,17 @@ bool EthLan8720Device::supportsEncryption() bool EthLan8720Device::isConnected() { - return ETH.linkUp(); + bool connected = ETH.linkUp(); + + if(_lastConnected == false && connected == true) + { + Serial.print("Ethernet connected. IP address: "); + Serial.println(ETH.localIP().toString()); + } + + _lastConnected = connected; + + return connected; } ReconnectStatus EthLan8720Device::reconnect() @@ -111,7 +122,7 @@ ReconnectStatus EthLan8720Device::reconnect() { return ReconnectStatus::CriticalFailure; } - delay(3000); + delay(200); return isConnected() ? ReconnectStatus::Success : ReconnectStatus::Failure; } diff --git a/networkDevices/EthLan8720Device.h b/networkDevices/EthLan8720Device.h index 1a32c5b..005fe6b 100644 --- a/networkDevices/EthLan8720Device.h +++ b/networkDevices/EthLan8720Device.h @@ -72,6 +72,7 @@ private: char* _path; bool _useEncryption = false; bool _hardwareInitialized = false; + bool _lastConnected = false; uint8_t _phy_addr; int _power; From 130fd23235e167c4990d6106bbb9a7f2039a1081 Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 2 Mar 2023 20:15:16 +0100 Subject: [PATCH 09/12] print ip address for W5500 devices --- networkDevices/EthLan8720Device.cpp | 2 +- networkDevices/W5500Device.cpp | 12 +++++++++++- networkDevices/W5500Device.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index 98f2e60..f9eb6a4 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -107,7 +107,7 @@ bool EthLan8720Device::isConnected() if(_lastConnected == false && connected == true) { - Serial.print("Ethernet connected. IP address: "); + Serial.print(F("Ethernet connected. IP address: ")); Serial.println(ETH.localIP().toString()); } diff --git a/networkDevices/W5500Device.cpp b/networkDevices/W5500Device.cpp index 93c3343..08eec47 100644 --- a/networkDevices/W5500Device.cpp +++ b/networkDevices/W5500Device.cpp @@ -164,7 +164,17 @@ bool W5500Device::supportsEncryption() bool W5500Device::isConnected() { - return Ethernet.linkStatus() == EthernetLinkStatus::LinkON && _maintainResult == 0 && _hasDHCPAddress; + bool connected = (Ethernet.linkStatus() == EthernetLinkStatus::LinkON && _maintainResult == 0 && _hasDHCPAddress); + + if(_lastConnected == false && connected == true) + { + Serial.print(F("Ethernet connected. IP address: ")); + Serial.println(Ethernet.localIP().toString()); + } + + _lastConnected = connected; + + return connected; } void W5500Device::initializeMacAddress(byte *mac) diff --git a/networkDevices/W5500Device.h b/networkDevices/W5500Device.h index d6dbd16..12a964d 100644 --- a/networkDevices/W5500Device.h +++ b/networkDevices/W5500Device.h @@ -71,6 +71,7 @@ private: bool _hasDHCPAddress = false; char* _path; W5500Variant _variant; + bool _lastConnected = false; byte _mac[6]; }; \ No newline at end of file From 5681ad537c8a09d1193680ba758afbb3b243ac85 Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 2 Mar 2023 20:26:22 +0100 Subject: [PATCH 10/12] inject device name for LAN8720 devices --- Network.cpp | 4 ++-- networkDevices/EthLan8720Device.cpp | 17 +++++++++-------- networkDevices/EthLan8720Device.h | 4 +++- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Network.cpp b/Network.cpp index 3ce6995..c06ae1a 100644 --- a/Network.cpp +++ b/Network.cpp @@ -96,10 +96,10 @@ void Network::setupDevice() _device = new W5500Device(_hostname, _preferences, hardwareDetect); break; case NetworkDeviceType::Olimex_LAN8720: - _device = new EthLan8720Device(_hostname, _preferences, ETH_PHY_ADDR, 12, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLOCK_GPIO17_OUT); + _device = new EthLan8720Device(_hostname, _preferences, "Olimex (LAN8720)", ETH_PHY_ADDR, 12, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_TYPE, ETH_CLOCK_GPIO17_OUT); break; case NetworkDeviceType::WT32_LAN8720: - _device = new EthLan8720Device(_hostname, _preferences, 1, 16); + _device = new EthLan8720Device(_hostname, _preferences, "WT32-ETH01", 1, 16); break; case NetworkDeviceType::WiFi: _device = new WifiDevice(_hostname, _preferences); diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index f9eb6a4..d02acf3 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -10,8 +10,9 @@ #include "espMqttClient.h" #include "../RestartReason.h" -EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _preferences, uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t ethtype, eth_clock_mode_t clock_mode, bool use_mac_from_efuse) +EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* preferences, const std::string& deviceName, uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t ethtype, eth_clock_mode_t clock_mode, bool use_mac_from_efuse) : NetworkDevice(hostname), + _deviceName(deviceName), _phy_addr(phy_addr), _power(power), _mdc(mdc), @@ -20,11 +21,11 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere _clock_mode(clock_mode), _use_mac_from_efuse(use_mac_from_efuse) { - _restartOnDisconnect = _preferences->getBool(preference_restart_on_disconnect); + _restartOnDisconnect = preferences->getBool(preference_restart_on_disconnect); - size_t caLength = _preferences->getString(preference_mqtt_ca,_ca,TLS_CA_MAX_SIZE); - size_t crtLength = _preferences->getString(preference_mqtt_crt,_cert,TLS_CERT_MAX_SIZE); - size_t keyLength = _preferences->getString(preference_mqtt_key,_key,TLS_KEY_MAX_SIZE); + size_t caLength = preferences->getString(preference_mqtt_ca, _ca, TLS_CA_MAX_SIZE); + size_t crtLength = preferences->getString(preference_mqtt_crt, _cert, TLS_CERT_MAX_SIZE); + size_t keyLength = preferences->getString(preference_mqtt_key, _key, TLS_KEY_MAX_SIZE); _useEncryption = caLength > 1; // length is 1 when empty @@ -48,12 +49,12 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere _mqttClient = new espMqttClient(false); } - if(_preferences->getBool(preference_mqtt_log_enabled)) + if(preferences->getBool(preference_mqtt_log_enabled)) { _path = new char[200]; memset(_path, 0, sizeof(_path)); - String pathStr = _preferences->getString(preference_mqtt_lock_path); + String pathStr = preferences->getString(preference_mqtt_lock_path); pathStr.concat(mqtt_topic_log); strcpy(_path, pathStr.c_str()); Log = new MqttLogger(this, _path, MqttLoggerMode::MqttAndSerial); @@ -62,7 +63,7 @@ EthLan8720Device::EthLan8720Device(const String& hostname, Preferences* _prefere const String EthLan8720Device::deviceName() const { - return "Olimex LAN8720"; + return _deviceName.c_str(); } void EthLan8720Device::initialize() diff --git a/networkDevices/EthLan8720Device.h b/networkDevices/EthLan8720Device.h index 005fe6b..c601a1d 100644 --- a/networkDevices/EthLan8720Device.h +++ b/networkDevices/EthLan8720Device.h @@ -12,7 +12,8 @@ class EthLan8720Device : public NetworkDevice public: EthLan8720Device(const String& hostname, - Preferences* _preferences, + Preferences* preferences, + const std::string& deviceName, uint8_t phy_addr = ETH_PHY_ADDR, int power = ETH_PHY_POWER, int mdc = ETH_PHY_MDC, @@ -74,6 +75,7 @@ private: bool _hardwareInitialized = false; bool _lastConnected = false; + const std::string _deviceName; uint8_t _phy_addr; int _power; int _mdc; From 0eff99087ce4e77ccb1d2f0d5aa9ad8d4b95072a Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 2 Mar 2023 20:36:41 +0100 Subject: [PATCH 11/12] set hostname for 8720 devices --- networkDevices/EthLan8720Device.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/networkDevices/EthLan8720Device.cpp b/networkDevices/EthLan8720Device.cpp index d02acf3..ddcd960 100644 --- a/networkDevices/EthLan8720Device.cpp +++ b/networkDevices/EthLan8720Device.cpp @@ -72,6 +72,7 @@ void EthLan8720Device::initialize() WiFi.setHostname(_hostname.c_str()); _hardwareInitialized = ETH.begin(_phy_addr, _power, _mdc, _mdio, _type, _clock_mode, _use_mac_from_efuse); + ETH.setHostname(_hostname.c_str()); if(_restartOnDisconnect) { From 9f78b2ece9c497309a9b67dfffaef905528a4f4f Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 2 Mar 2023 21:12:53 +0100 Subject: [PATCH 12/12] update readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30423d7..ce389ac 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ As an alternative to Wifi, the following ESP32 modules with wired ethernet are s [M5Stack Atom POE](https://docs.m5stack.com/en/atom/atom_poe)
[Olimex ESP32-POE](https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware)
[Olimex ESP32-POE-ISO](https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/open-source-hardware)
+[WT32-ETH01](http://www.wireless-tag.com/portfolio/wt32-eth01/)
## Installation @@ -34,7 +35,10 @@ https://github.com/technyon/nuki_hub/releases The firmware uses the Wifi Manager to configure the WiFi network. Power up the ESP32, a new Access Point should appear. Connect to this access point and in a browser navigate to "192.168.4.1". Use the web interface configure your Wifi network. After configuring the Wifi, the ESP should automatically connect to your network. Use the web interface to setup the MQTT broker; just navigate to the IP-Address assigned to the ESP32 via DHCP (often found in the web interface of the internet router).
-To configure MQTT, enter the adress of your MQTT broker and eventually a username and a password if required. The firmware supports SSL encryption for MQTT, however most people and especially home users don't use this. In that case leave all fields about "MQTT SSL" blank. +To configure MQTT, enter the adress of your MQTT broker and eventually a username and a password if required. The firmware supports SSL encryption for MQTT, however most people and especially home users don't use this. In that case leave all fields about "MQTT SSL" blank.
+If a PIN has been configured using the smartphone app, it's recommended to supply this PIN to NUKI Hub. +Certain functionality is not available without configuring the PIN, like changing the config or keypad coded. +To do so, navigate to "Credentials" in the web interface. This will only supply the PIN to NUK Hub, it will on no way reconfigure the PIN on the lock. ## Pairing