diff --git a/Config.h b/Config.h index c8f1bf40..16d3db53 100644 --- a/Config.h +++ b/Config.h @@ -1,6 +1,6 @@ #pragma once -#define NUKI_HUB_VERSION "8.32" +#define NUKI_HUB_VERSION "8.33-pre-6" #define GITHUB_LATEST_RELEASE_URL "https://github.com/technyon/nuki_hub/releases/latest" #define GITHUB_LATEST_RELEASE_API_URL "https://api.github.com/repos/technyon/nuki_hub/releases/latest" diff --git a/lib/espMqttClient/CMakeLists.txt b/lib/espMqttClient/CMakeLists.txt new file mode 100644 index 00000000..37022275 --- /dev/null +++ b/lib/espMqttClient/CMakeLists.txt @@ -0,0 +1,17 @@ +set(COMPONENT_SRCDIRS + "src" "src/Packets" "src/Transport" +) + +set(COMPONENT_ADD_INCLUDEDIRS + "src" "src/Packets" "src/Transport" +) + +set(COMPONENT_REQUIRES + "arduino-esp32" + "AsyncTCP" +) + +register_component() + +target_compile_definitions(${COMPONENT_TARGET} PUBLIC -DESP32) +target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti) diff --git a/lib/espMqttClient/README.md b/lib/espMqttClient/README.md index 586d3339..28403067 100644 --- a/lib/espMqttClient/README.md +++ b/lib/espMqttClient/README.md @@ -15,12 +15,13 @@ Aims to be a non-blocking, fully compliant MQTT 3.1.1 client. - TCP and TCP/TLS using standard WiFiClient and WiFiClientSecure connections - Virtually unlimited incoming and outgoing payload sizes - Readable and understandable code -- Fully async clients available via [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) or [ESPAsnycTCP](https://github.com/me-no-dev/ESPAsyncTCP) (no TLS supported) +- Fully async clients available via [AsyncTCP](https://github.com/esphome/AsyncTCP) or [ESPAsnycTCP](https://github.com/esphome/ESPAsyncTCP) (no TLS supported) - Supported platforms: - Espressif ESP8266 and ESP32 using the Arduino framework + - Espressif ESP32 using the ESP IDF, see [esp idf component](https://docs.espressif.com/projects/arduino-esp32/en/latest/esp-idf_component.html) - Basic Linux compatibility*. This includes WSL on Windows - > Linux compatibility is mainly for automatic testing. It relies on a quick and dirty Arduino-style `Client` with a POSIX TCP client underneath and Arduino-style `IPAddress` class. These are lacking many features needed for proper Linux support. + > Linux compatibility is mainly for automatic testing. It relies on a quick and dirty Arduino-style `Client` with a POSIX TCP client underneath and Arduino-style `ClientPosixIPAddress` class. These are lacking many features needed for proper Linux support. # Documentation diff --git a/lib/espMqttClient/component.mk b/lib/espMqttClient/component.mk new file mode 100644 index 00000000..bb5bb161 --- /dev/null +++ b/lib/espMqttClient/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS := src +COMPONENT_SRCDIRS := src +CXXFLAGS += -fno-rtti diff --git a/lib/espMqttClient/docs/index.md b/lib/espMqttClient/docs/index.md index cae13f8a..077686b8 100644 --- a/lib/espMqttClient/docs/index.md +++ b/lib/espMqttClient/docs/index.md @@ -10,7 +10,7 @@ - TCP and TCP/TLS using standard WiFiClient and WiFiClientSecure connections - Virtually unlimited incoming and outgoing payload sizes - Readable and understandable code -- Fully async clients available via [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) or [ESPAsnycTCP](https://github.com/me-no-dev/ESPAsyncTCP) (no TLS supported) +- Fully async clients available via [AsyncTCP](https://github.com/esphome/AsyncTCP) or [ESPAsnycTCP](https://github.com/esphome/ESPAsyncTCP) (no TLS supported) - Supported platforms: - Espressif ESP8266 and ESP32 using the Arduino framework - Basic Linux compatibility*. This includes WSL on Windows @@ -232,25 +232,25 @@ Add a publish acknowledged event handler. Function signature: `void(uint16_t pac bool connected() ``` -Returns if the client is currently fully connected to the broker or not. During connecting or disconnecting, it will return false. +Returns `true` if the client is currently fully connected to the broker. During connecting or disconnecting, it will return `false`. ```cpp bool disconnected() ``` -Returns if the client is currently disconnected to the broker or not. During disconnecting or connecting, it will return false. +Returns `true` if the client is currently disconnected from the broker. During disconnecting or connecting, it will return `false`. ```cpp -void connect() +bool connect() ``` -Connect to the server. +Start the connect procedure. Returns `true` if successful. A positive return value doesn not mean the client is already connected. ```cpp -void disconnect(bool force = false) +bool disconnect(bool force = false) ``` -Disconnect from the server. +Start the disconnect procedure, return `true` if successful. A positive return value doesn not mean the client is already disconnected. When disconnecting with `force` false, the client first tries to handle all the outgoing messages in the queue and disconnect cleanly afterwards. During this time, no incoming PUBLISH messages are handled. - **`force`**: Whether to force the disconnection. Defaults to `false` (clean disconnection). @@ -341,10 +341,20 @@ const char* getClientId() const Retuns the client ID. +```cpp +size_t queueSize(); +``` + +Returns the amount of elements, regardless of type, in the queue. + # Compile time configuration A number of constants which influence the behaviour of the client can be set at compile time. You can set these options in the `Config.h` file or pass the values as compiler flags. Because these options are compile-time constants, they are used for all instances of `espMqttClient` you create in your program. +### EMC_TX_TIMEOUT 10000 + +Timeout in milliseconds before a (qos > 0) message will be retransmitted. + ### EMC_RX_BUFFER_SIZE 1440 The client copies incoming data into a buffer before parsing. This sets the buffer size. @@ -388,6 +398,10 @@ The (maximum) length of the client ID. (Keep in mind that this is a c-string. Yo Only used on ESP32. Sets the stack size (in words) of the MQTT client worker task. +### EMC_MULTIPLE_CALLBACKS + +This macro is by default not enabled so you can add a single callbacks to an event. Assigning a second will overwrite the existing callback. When enabling multiple callbacks, multiple callbacks (with uint32_t id) can be assigned. Removing is done by referencing the id. + ### EMC_USE_WATCHDOG 0 (ESP32 only) diff --git a/lib/espMqttClient/examples/notask-esp32/notask-esp32.ino b/lib/espMqttClient/examples/notask-esp32/notask-esp32.ino new file mode 100644 index 00000000..27bc675d --- /dev/null +++ b/lib/espMqttClient/examples/notask-esp32/notask-esp32.ino @@ -0,0 +1,148 @@ +#include + +#include + +#define WIFI_SSID "yourSSID" +#define WIFI_PASSWORD "yourpass" + +#define MQTT_HOST IPAddress(192, 168, 1, 10) +#define MQTT_PORT 1883 + +espMqttClient mqttClient(espMqttClientTypes::UseInternalTask::NO); +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; + +void connectToWiFi() { + Serial.println("Connecting to Wi-Fi..."); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); +} + +void connectToMqtt() { + Serial.println("Connecting to MQTT..."); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } +} + +void WiFiEvent(WiFiEvent_t event) { + Serial.printf("[WiFi-event] event: %d\n", event); + switch(event) { + case SYSTEM_EVENT_STA_GOT_IP: + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + connectToMqtt(); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + Serial.println("WiFi lost connection"); + break; + default: + break; + } +} + +void onMqttConnect(bool sessionPresent) { + Serial.println("Connected to MQTT."); + Serial.print("Session present: "); + Serial.println(sessionPresent); + uint16_t packetIdSub = mqttClient.subscribe("foo/bar", 2); + Serial.print("Subscribing at QoS 2, packetId: "); + Serial.println(packetIdSub); + mqttClient.publish("foo/bar", 0, true, "test 1"); + Serial.println("Publishing at QoS 0"); + uint16_t packetIdPub1 = mqttClient.publish("foo/bar", 1, true, "test 2"); + Serial.print("Publishing at QoS 1, packetId: "); + Serial.println(packetIdPub1); + uint16_t packetIdPub2 = mqttClient.publish("foo/bar", 2, true, "test 3"); + Serial.print("Publishing at QoS 2, packetId: "); + Serial.println(packetIdPub2); +} + +void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { + Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); + + if (WiFi.isConnected()) { + reconnectMqtt = true; + lastReconnect = millis(); + } +} + +void onMqttSubscribe(uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* codes, size_t len) { + Serial.println("Subscribe acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); + for (size_t i = 0; i < len; ++i) { + Serial.print(" qos: "); + Serial.println(static_cast(codes[i])); + } +} + +void onMqttUnsubscribe(uint16_t packetId) { + Serial.println("Unsubscribe acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); +} + +void onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { + (void) payload; + Serial.println("Publish received."); + Serial.print(" topic: "); + Serial.println(topic); + Serial.print(" qos: "); + Serial.println(properties.qos); + Serial.print(" dup: "); + Serial.println(properties.dup); + Serial.print(" retain: "); + Serial.println(properties.retain); + Serial.print(" len: "); + Serial.println(len); + Serial.print(" index: "); + Serial.println(index); + Serial.print(" total: "); + Serial.println(total); +} + +void onMqttPublish(uint16_t packetId) { + Serial.println("Publish acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); +} + +void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println(); + + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); + WiFi.onEvent(WiFiEvent); + + mqttClient.onConnect(onMqttConnect); + mqttClient.onDisconnect(onMqttDisconnect); + mqttClient.onSubscribe(onMqttSubscribe); + mqttClient.onUnsubscribe(onMqttUnsubscribe); + mqttClient.onMessage(onMqttMessage); + mqttClient.onPublish(onMqttPublish); + mqttClient.setServer(MQTT_HOST, MQTT_PORT); + + connectToWiFi(); +} + +void loop() { + static uint32_t currentMillis = millis(); + + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } + + // We used to option not to use the internal task + // so we need to call the loop-method ourselves. + // During connecting it may block. + // Creating a separate task yourself is obviously + // also a possibility. + mqttClient.loop(); +} diff --git a/lib/espMqttClient/examples/simple-esp32-idf/CMakeLists.txt b/lib/espMqttClient/examples/simple-esp32-idf/CMakeLists.txt new file mode 100644 index 00000000..e1f4c038 --- /dev/null +++ b/lib/espMqttClient/examples/simple-esp32-idf/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +SET(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(simple-esp32-idf) \ No newline at end of file diff --git a/lib/espMqttClient/examples/simple-esp32-idf/README.md b/lib/espMqttClient/examples/simple-esp32-idf/README.md new file mode 100644 index 00000000..8fd90c7a --- /dev/null +++ b/lib/espMqttClient/examples/simple-esp32-idf/README.md @@ -0,0 +1,3 @@ +This example is for use with [Arduino as a component](https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/esp-idf_component.html) in the ESP-IDF framework. + +Be sure to follow [this section](https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/esp-idf_component.html#adding-local-library) about adding libraries to your project. diff --git a/lib/espMqttClient/examples/simple-esp32-idf/main/CMakeLists.txt b/lib/espMqttClient/examples/simple-esp32-idf/main/CMakeLists.txt new file mode 100644 index 00000000..475d0f78 --- /dev/null +++ b/lib/espMqttClient/examples/simple-esp32-idf/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register( + SRCS "main.cpp" + INCLUDE_DIRS "") \ No newline at end of file diff --git a/lib/espMqttClient/examples/simple-esp32-idf/main/main.cpp b/lib/espMqttClient/examples/simple-esp32-idf/main/main.cpp new file mode 100644 index 00000000..88334904 --- /dev/null +++ b/lib/espMqttClient/examples/simple-esp32-idf/main/main.cpp @@ -0,0 +1,142 @@ +#include +#include + +#include + +#define WIFI_SSID "yourSSID" +#define WIFI_PASSWORD "yourpass" + +#define MQTT_HOST IPAddress(192, 168, 1, 10) +#define MQTT_PORT 1883 + +espMqttClient mqttClient; +bool reconnectMqtt = false; +uint32_t lastReconnect = 0; + +void connectToWiFi() { + Serial.println("Connecting to Wi-Fi..."); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); +} + +void connectToMqtt() { + Serial.println("Connecting to MQTT..."); + if (!mqttClient.connect()) { + reconnectMqtt = true; + lastReconnect = millis(); + Serial.println("Connecting failed."); + } else { + reconnectMqtt = false; + } +} + +void WiFiEvent(WiFiEvent_t event) { + Serial.printf("[WiFi-event] event: %d\n", event); + switch(event) { + case SYSTEM_EVENT_STA_GOT_IP: + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + connectToMqtt(); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + Serial.println("WiFi lost connection"); + break; + default: + break; + } +} + +void onMqttConnect(bool sessionPresent) { + Serial.println("Connected to MQTT."); + Serial.print("Session present: "); + Serial.println(sessionPresent); + uint16_t packetIdSub = mqttClient.subscribe("foo/bar", 2); + Serial.print("Subscribing at QoS 2, packetId: "); + Serial.println(packetIdSub); + mqttClient.publish("foo/bar", 0, true, "test 1"); + Serial.println("Publishing at QoS 0"); + uint16_t packetIdPub1 = mqttClient.publish("foo/bar", 1, true, "test 2"); + Serial.print("Publishing at QoS 1, packetId: "); + Serial.println(packetIdPub1); + uint16_t packetIdPub2 = mqttClient.publish("foo/bar", 2, true, "test 3"); + Serial.print("Publishing at QoS 2, packetId: "); + Serial.println(packetIdPub2); +} + +void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { + Serial.printf("Disconnected from MQTT: %u.\n", static_cast(reason)); + + if (WiFi.isConnected()) { + reconnectMqtt = true; + lastReconnect = millis(); + } +} + +void onMqttSubscribe(uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* codes, size_t len) { + Serial.println("Subscribe acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); + for (size_t i = 0; i < len; ++i) { + Serial.print(" qos: "); + Serial.println(static_cast(codes[i])); + } +} + +void onMqttUnsubscribe(uint16_t packetId) { + Serial.println("Unsubscribe acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); +} + +void onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { + (void) payload; + Serial.println("Publish received."); + Serial.print(" topic: "); + Serial.println(topic); + Serial.print(" qos: "); + Serial.println(properties.qos); + Serial.print(" dup: "); + Serial.println(properties.dup); + Serial.print(" retain: "); + Serial.println(properties.retain); + Serial.print(" len: "); + Serial.println(len); + Serial.print(" index: "); + Serial.println(index); + Serial.print(" total: "); + Serial.println(total); +} + +void onMqttPublish(uint16_t packetId) { + Serial.println("Publish acknowledged."); + Serial.print(" packetId: "); + Serial.println(packetId); +} + +void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println(); + + WiFi.setAutoConnect(false); + WiFi.setAutoReconnect(true); + WiFi.onEvent(WiFiEvent); + + mqttClient.onConnect(onMqttConnect); + mqttClient.onDisconnect(onMqttDisconnect); + mqttClient.onSubscribe(onMqttSubscribe); + mqttClient.onUnsubscribe(onMqttUnsubscribe); + mqttClient.onMessage(onMqttMessage); + mqttClient.onPublish(onMqttPublish); + mqttClient.setServer(MQTT_HOST, MQTT_PORT); + + connectToWiFi(); +} + +void loop() { + static uint32_t currentMillis = millis(); + + if (reconnectMqtt && currentMillis - lastReconnect > 5000) { + connectToMqtt(); + } +} diff --git a/lib/espMqttClient/examples/simple-esp32-idf/sdkconfig.defaults b/lib/espMqttClient/examples/simple-esp32-idf/sdkconfig.defaults new file mode 100644 index 00000000..4661ad26 --- /dev/null +++ b/lib/espMqttClient/examples/simple-esp32-idf/sdkconfig.defaults @@ -0,0 +1,39 @@ +# +# Bootloader config +# +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y +CONFIG_BOOTLOADER_LOG_LEVEL=0 + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# +# Partition Table +# +CONFIG_PARTITION_TABLE_CUSTOM=n + +# +# Arduino Configuration +# +CONFIG_ARDUINO_VARIANT="esp32" +CONFIG_ENABLE_ARDUINO_DEPENDS=y +CONFIG_AUTOSTART_ARDUINO=y + +# +# FreeRTOS +# +# 1000 require for Arduino +CONFIG_FREERTOS_HZ=1000 + +#ASYNC_TCP +CONFIG_ASYNC_TCP_RUN_NO_AFFINITY=y + +#MBEDTLS +CONFIG_MBEDTLS_PSK_MODES=y \ No newline at end of file diff --git a/lib/espMqttClient/keywords.txt b/lib/espMqttClient/keywords.txt index 136da0af..3807482b 100644 --- a/lib/espMqttClient/keywords.txt +++ b/lib/espMqttClient/keywords.txt @@ -44,6 +44,7 @@ publish KEYWORD2 clearQueue KEYWORD2 loop KEYWORD2 getClientId KEYWORD2 +queueSize KEYWORD2 # Structures (KEYWORD3) espMqttClientTypes KEYWORD3 diff --git a/lib/espMqttClient/library.json b/lib/espMqttClient/library.json index b883dda5..ad44295b 100644 --- a/lib/espMqttClient/library.json +++ b/lib/espMqttClient/library.json @@ -14,21 +14,21 @@ "type": "git", "url": "https://github.com/bertmelis/espMqttClient.git" }, - "version": "1.4.2", + "version": "1.6.0", "frameworks": "arduino", "platforms": ["espressif8266", "espressif32"], "headers": ["espMqttClient.h", "espMqttClientAsync.h"], "dependencies": [ { - "owner": "me-no-dev", - "name": "ESPAsyncTCP", - "version": ">=1.2.2", + "owner": "esphome", + "name": "ESPAsyncTCP-esphome", + "version": ">=2.0.0", "platforms": "espressif8266" }, { - "owner": "me-no-dev", - "name": "AsyncTCP", - "version": ">=1.1.1", + "owner": "esphome", + "name": "AsyncTCP-esphome", + "version": ">=2.1.1", "platforms": "espressif32" } ], diff --git a/lib/espMqttClient/library.properties b/lib/espMqttClient/library.properties index f80a2ebb..55d488a0 100644 --- a/lib/espMqttClient/library.properties +++ b/lib/espMqttClient/library.properties @@ -1,5 +1,5 @@ name=espMqttClient -version=1.4.2 +version=1.6.0 author=Bert Melis maintainer=Bert Melis sentence=an MQTT client for the Arduino framework for ESP8266 / ESP32 diff --git a/lib/espMqttClient/platformio.ini b/lib/espMqttClient/platformio.ini index 43e3953c..77f8f5c9 100644 --- a/lib/espMqttClient/platformio.ini +++ b/lib/espMqttClient/platformio.ini @@ -19,6 +19,7 @@ build_flags = -Wextra -std=c++11 -pthread + -ggdb3 [env:native] platform = native @@ -29,5 +30,13 @@ build_flags = --coverage -D EMC_RX_BUFFER_SIZE=100 -D EMC_TX_BUFFER_SIZE=10 + -D EMC_MULTIPLE_CALLBACKS=1 ;extra_scripts = test-coverage.py build_type = debug +test_testing_command = + valgrind + --leak-check=full + --show-leak-kinds=all + --track-origins=yes + --error-exitcode=1 + ${platformio.build_dir}/${this.__env__}/program diff --git a/lib/espMqttClient/scripts/CI/build_examples_pio.sh b/lib/espMqttClient/scripts/CI/build_examples_pio.sh deleted file mode 100644 index 4ef860c3..00000000 --- a/lib/espMqttClient/scripts/CI/build_examples_pio.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# already done by workflow -#pip install -U platformio -#platformio update -#pio pkg install --global --library me-no-dev/AsyncTCP -#pio pkg install --global --library EspAsyncTCP - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[0;33m' -NC='\033[0m' - -lines=$(find ./examples/ -maxdepth 1 -mindepth 1 -type d) -retval=0 -retvalpart=0 -while read line; do - if [[ "$line" != *esp8266 && "$line" != *esp32 && "$line" != *linux ]]; then - echo -e "========================== BUILDING $line ==========================" - echo -e "${YELLOW}SKIPPING${NC}" - continue - fi - echo -e "========================== BUILDING $line ==========================" - if [[ -e "$line/platformio.ini" ]]; then - output=$(platformio ci --lib="." --project-conf="$line/platformio.ini" $line 2>&1) - retvalpart=$? - else - if [[ "$line" == *esp8266 ]]; then - output=$(platformio ci --lib="." --project-conf="scripts/CI/platformio_esp8266.ini" $line 2>&1) - retvalpart=$? - else - output=$(platformio ci --lib="." --project-conf="scripts/CI/platformio_esp32.ini" $line 2>&1) - retvalpart=$? - fi - : - fi - if [ $retvalpart -ne 0 ]; then - echo "$output" - echo -e "Building $line ${RED}FAILED${NC}" - retval=1 - else - echo -e "${GREEN}SUCCESS${NC}" - fi -done <<< "$lines" - -# will be deleted together with container -#pio pkg uninstall --global --library me-no-dev/AsyncTCP -#pio pkg uninstall --global --library EspAsyncTCP - -exit "$retval" diff --git a/lib/espMqttClient/scripts/CI/platformio_esp32.ini b/lib/espMqttClient/scripts/CI/platformio_esp32.ini deleted file mode 100644 index 326891de..00000000 --- a/lib/espMqttClient/scripts/CI/platformio_esp32.ini +++ /dev/null @@ -1,19 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter -; Upload options: custom upload port, speed and extra flags -; Library options: dependencies, extra library storages -; Advanced options: extra scripting -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:esp32] -platform = espressif32 -board = lolin32 -framework = arduino -build_flags = - ;-Werror - -Wall - -Wextra - -Werror diff --git a/lib/espMqttClient/scripts/CI/platformio_esp8266.ini b/lib/espMqttClient/scripts/CI/platformio_esp8266.ini deleted file mode 100644 index d523d278..00000000 --- a/lib/espMqttClient/scripts/CI/platformio_esp8266.ini +++ /dev/null @@ -1,19 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter -; Upload options: custom upload port, speed and extra flags -; Library options: dependencies, extra library storages -; Advanced options: extra scripting -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:esp8266] -platform = espressif8266 -board = d1_mini -framework = arduino -build_flags = - ;-Werror - -Wall - -Wextra - -Werror diff --git a/lib/espMqttClient/src/Config.h b/lib/espMqttClient/src/Config.h index aba77956..9c609117 100644 --- a/lib/espMqttClient/src/Config.h +++ b/lib/espMqttClient/src/Config.h @@ -9,7 +9,7 @@ the LICENSE file. #pragma once #ifndef EMC_TX_TIMEOUT -#define EMC_TX_TIMEOUT 5000 +#define EMC_TX_TIMEOUT 10000 #endif #ifndef EMC_RX_BUFFER_SIZE @@ -29,7 +29,7 @@ the LICENSE file. #endif #ifndef EMC_MIN_FREE_MEMORY -#define EMC_MIN_FREE_MEMORY 4096 +#define EMC_MIN_FREE_MEMORY 16384 #endif #ifndef EMC_ESP8266_MULTITHREADING @@ -53,6 +53,10 @@ the LICENSE file. #define EMC_TASK_STACK_SIZE 5120 #endif +#ifndef EMC_MULTIPLE_CALLBACKS +#define EMC_MULTIPLE_CALLBACKS 0 +#endif + #ifndef EMC_USE_WATCHDOG #define EMC_USE_WATCHDOG 0 #endif diff --git a/lib/espMqttClient/src/Helpers.h b/lib/espMqttClient/src/Helpers.h index 4a19224b..05ab136d 100644 --- a/lib/espMqttClient/src/Helpers.h +++ b/lib/espMqttClient/src/Helpers.h @@ -16,7 +16,7 @@ the LICENSE file. #define EMC_SEMAPHORE_TAKE() xSemaphoreTake(_xSemaphore, portMAX_DELAY) #define EMC_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore) #define EMC_GET_FREE_MEMORY() std::max(ESP.getMaxAllocHeap(), ESP.getMaxAllocPsram()) - #define EMC_YIELD() taskYIELD() + #define EMC_YIELD() vTaskDelay(1) #define EMC_GENERATE_CLIENTID(x) snprintf(x, EMC_CLIENTID_LENGTH, "esp32%06llx", ESP.getEfuseMac()); #elif defined(ARDUINO_ARCH_ESP8266) #include // millis(), ESP.getFreeHeap(); diff --git a/lib/espMqttClient/src/Logging.h b/lib/espMqttClient/src/Logging.h index a1d85fa8..3ba096a8 100644 --- a/lib/espMqttClient/src/Logging.h +++ b/lib/espMqttClient/src/Logging.h @@ -10,6 +10,8 @@ the LICENSE file. #if defined(ARDUINO_ARCH_ESP32) #include + #include "freertos/FreeRTOS.h" + #include "freertos/task.h" #if defined(DEBUG_ESP_MQTT_CLIENT) // Logging is en/disabled by Arduino framework macros #define emc_log_i(...) log_i(__VA_ARGS__) diff --git a/lib/espMqttClient/src/MqttClient.cpp b/lib/espMqttClient/src/MqttClient.cpp index bae592ee..fdc2cb2d 100644 --- a/lib/espMqttClient/src/MqttClient.cpp +++ b/lib/espMqttClient/src/MqttClient.cpp @@ -14,12 +14,8 @@ using espMqttClientTypes::DisconnectReason; using espMqttClientTypes::Error; MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority, uint8_t core) -#if defined(ARDUINO_ARCH_ESP32) : _useInternalTask(useInternalTask) , _transport(nullptr) -#else -: _transport(nullptr) -#endif , _onConnectCallback(nullptr) , _onDisconnectCallback(nullptr) , _onSubscribeCallback(nullptr) @@ -41,7 +37,7 @@ MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint , _willPayloadLength(0) , _willQos(0) , _willRetain(false) -, _timeout(10000) +, _timeout(EMC_TX_TIMEOUT) , _state(State::disconnected) , _generatedClientId{0} , _packetId(0) @@ -101,7 +97,7 @@ bool MqttClient::disconnected() const { } bool MqttClient::connect() { - bool result = true; + bool result = false; if (_state == State::disconnected) { EMC_SEMAPHORE_TAKE(); if (_addPacketFront(_cleanSession, @@ -114,17 +110,17 @@ bool MqttClient::connect() { _willPayloadLength, (uint16_t)(_keepAlive / 1000), // 32b to 16b doesn't overflow because it comes from 16b orignally _clientId)) { + result = true; + _setState(State::connectingTcp1); #if defined(ARDUINO_ARCH_ESP32) if (_useInternalTask == espMqttClientTypes::UseInternalTask::YES) { vTaskResume(_taskHandle); } #endif - _state = State::connectingTcp1; } else { EMC_SEMAPHORE_GIVE(); emc_log_e("Could not create CONNECT packet"); _onError(0, Error::OUT_OF_MEMORY); - result = false; } EMC_SEMAPHORE_GIVE(); } @@ -133,11 +129,11 @@ bool MqttClient::connect() { bool MqttClient::disconnect(bool force) { if (force && _state != State::disconnected && _state != State::disconnectingTcp1 && _state != State::disconnectingTcp2) { - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); return true; } if (!force && _state == State::connected) { - _state = State::disconnectingMqtt1; + _setState(State::disconnectingMqtt1); return true; } return false; @@ -151,8 +147,8 @@ uint16_t MqttClient::publish(const char* topic, uint8_t qos, bool retain, const #endif return 0; } - uint16_t packetId = (qos > 0) ? _getNextPacketId() : 1; EMC_SEMAPHORE_TAKE(); + uint16_t packetId = (qos > 0) ? _getNextPacketId() : 1; if (!_addPacket(packetId, topic, payload, length, qos, retain)) { emc_log_e("Could not create PUBLISH packet"); _onError(packetId, Error::OUT_OF_MEMORY); @@ -175,8 +171,8 @@ uint16_t MqttClient::publish(const char* topic, uint8_t qos, bool retain, espMqt #endif return 0; } - uint16_t packetId = (qos > 0) ? _getNextPacketId() : 1; EMC_SEMAPHORE_TAKE(); + uint16_t packetId = (qos > 0) ? _getNextPacketId() : 1; if (!_addPacket(packetId, topic, callback, length, qos, retain)) { emc_log_e("Could not create PUBLISH packet"); _onError(packetId, Error::OUT_OF_MEMORY); @@ -194,6 +190,14 @@ const char* MqttClient::getClientId() const { return _clientId; } +size_t MqttClient::queueSize() { + size_t ret = 0; + EMC_SEMAPHORE_TAKE(); + ret = _outbox.size(); + EMC_SEMAPHORE_GIVE(); + return ret; +} + void MqttClient::loop() { switch (_state) { case State::disconnected: @@ -205,9 +209,9 @@ void MqttClient::loop() { break; case State::connectingTcp1: if (_useIp ? _transport->connect(_ip, _port) : _transport->connect(_host, _port)) { - _state = State::connectingTcp2; + _setState(State::connectingTcp2); } else { - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); _disconnectReason = DisconnectReason::TCP_DISCONNECTED; break; } @@ -217,7 +221,7 @@ void MqttClient::loop() { if (_transport->connected()) { _parser.reset(); _lastClientActivity = _lastServerActivity = millis(); - _state = State::connectingMqtt; + _setState(State::connectingMqtt); } break; case State::connectingMqtt: @@ -227,7 +231,7 @@ void MqttClient::loop() { _checkIncoming(); _checkPing(); } else { - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); _disconnectReason = DisconnectReason::TCP_DISCONNECTED; } break; @@ -247,7 +251,7 @@ void MqttClient::loop() { _checkPing(); _checkTimeout(); } else { - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); _disconnectReason = DisconnectReason::TCP_DISCONNECTED; } break; @@ -259,7 +263,7 @@ void MqttClient::loop() { emc_log_e("Could not create DISCONNECT packet"); _onError(0, Error::OUT_OF_MEMORY); } else { - _state = State::disconnectingMqtt2; + _setState(State::disconnectingMqtt2); } } EMC_SEMAPHORE_GIVE(); @@ -270,13 +274,13 @@ void MqttClient::loop() { break; case State::disconnectingTcp1: _transport->stop(); - _state = State::disconnectingTcp2; + _setState(State::disconnectingTcp2); break; // keep break to accomodate async clients case State::disconnectingTcp2: if (_transport->disconnected()) { _clearQueue(0); _bytesSent = 0; - _state = State::disconnected; + _setState(State::disconnected); if (_onDisconnectCallback) _onDisconnectCallback(_disconnectReason); } break; @@ -308,13 +312,15 @@ void MqttClient::_loop(MqttClient* c) { } #endif +inline void MqttClient::_setState(State newState) { + emc_log_i("state %i --> %i", static_cast::type>(_state.load()), static_cast::type>(newState)); + _state = newState; +} + uint16_t MqttClient::_getNextPacketId() { - uint16_t packetId = 0; - EMC_SEMAPHORE_TAKE(); - // cppcheck-suppress knownConditionTrueFalse - packetId = (++_packetId == 0) ? ++_packetId : _packetId; - EMC_SEMAPHORE_GIVE(); - return packetId; + ++_packetId; + if (_packetId == 0) ++_packetId; + return _packetId; } void MqttClient::_checkOutbox() { @@ -329,21 +335,14 @@ int MqttClient::_sendPacket() { EMC_SEMAPHORE_TAKE(); OutgoingPacket* 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->packet.available(_bytesSent); + size_t written = 0; + if (packet) { + size_t wantToWrite = packet->packet.available(_bytesSent); if (wantToWrite == 0) { EMC_SEMAPHORE_GIVE(); return 0; } written = _transport->write(packet->packet.data(_bytesSent), wantToWrite); - if (written < 0) { - emc_log_w("Write error, check connection"); - EMC_SEMAPHORE_GIVE(); - return -1; - } packet->timeSent = millis(); _lastClientActivity = millis(); _bytesSent += written; @@ -358,7 +357,7 @@ bool MqttClient::_advanceOutbox() { OutgoingPacket* packet = _outbox.getCurrent(); if (packet && _bytesSent == packet->packet.size()) { if ((packet->packet.packetType()) == PacketType.DISCONNECT) { - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); _disconnectReason = DisconnectReason::USER_OK; } if (packet->packet.removable()) { @@ -388,7 +387,7 @@ void MqttClient::_checkIncoming() { espMqttClientInternals::MQTTPacketType packetType = _parser.getPacket().fixedHeader.packetType & 0xF0; if (_state == State::connectingMqtt && packetType != PacketType.CONNACK) { emc_log_w("Disconnecting, expected CONNACK - protocol error"); - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); return; } switch (packetType & 0xF0) { @@ -426,7 +425,7 @@ void MqttClient::_checkIncoming() { } } else if (result == espMqttClientInternals::ParserResult::protocolError) { emc_log_w("Disconnecting, protocol error"); - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); _disconnectReason = DisconnectReason::TCP_DISCONNECTED; return; } @@ -446,7 +445,7 @@ void MqttClient::_checkPing() { // disconnect when server was inactive for twice the keepalive time if (currentMillis - _lastServerActivity > 2 * _keepAlive) { emc_log_w("Disconnecting, server exceeded keepalive"); - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); _disconnectReason = DisconnectReason::TCP_DISCONNECTED; return; } @@ -484,7 +483,7 @@ void MqttClient::_checkTimeout() { void MqttClient::_onConnack() { if (_parser.getPacket().variableHeader.fixed.connackVarHeader.returnCode == 0x00) { _pingSent = false; // reset after keepalive timeout disconnect - _state = State::connected; + _setState(State::connected); _advanceOutbox(); if (_parser.getPacket().variableHeader.fixed.connackVarHeader.sessionPresent == 0) { _clearQueue(1); @@ -493,14 +492,14 @@ void MqttClient::_onConnack() { _onConnectCallback(_parser.getPacket().variableHeader.fixed.connackVarHeader.sessionPresent); } } else { - _state = State::disconnectingTcp1; + _setState(State::disconnectingTcp1); // cast is safe because the parser already checked for a valid return code _disconnectReason = static_cast(_parser.getPacket().variableHeader.fixed.connackVarHeader.returnCode); } } void MqttClient::_onPublish() { - espMqttClientInternals::IncomingPacket p = _parser.getPacket(); + const espMqttClientInternals::IncomingPacket& p = _parser.getPacket(); uint8_t qos = p.qos(); bool retain = p.retain(); bool dup = p.dup(); @@ -633,9 +632,6 @@ void MqttClient::_onPubcomp() { // if it doesn't match the ID, return if ((it.get()->packet.packetType()) == PacketType.PUBREL) { if (it.get()->packet.packetId() == idToMatch) { - if (!_addPacket(PacketType.PUBCOMP, idToMatch)) { - emc_log_e("Could not create PUBCOMP packet"); - } callback = true; _outbox.remove(it); break; diff --git a/lib/espMqttClient/src/MqttClient.h b/lib/espMqttClient/src/MqttClient.h index 8d89abab..49979427 100644 --- a/lib/espMqttClient/src/MqttClient.h +++ b/lib/espMqttClient/src/MqttClient.h @@ -65,6 +65,7 @@ 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; + size_t queueSize(); // No const because of mutex void loop(); protected: @@ -110,6 +111,7 @@ class MqttClient { disconnectingTcp2 = 8 }; std::atomic _state; + inline void _setState(State newState); private: char _generatedClientId[EMC_CLIENTID_LENGTH]; @@ -130,7 +132,7 @@ class MqttClient { uint32_t timeSent; espMqttClientInternals::Packet packet; template - OutgoingPacket(uint32_t t, espMqttClientTypes::Error error, Args&&... args) : + OutgoingPacket(uint32_t t, espMqttClientTypes::Error& error, Args&&... args) : // NOLINT(runtime/references) timeSent(t), packet(error, std::forward(args) ...) {} }; @@ -148,16 +150,24 @@ class MqttClient { bool _addPacket(Args&&... args) { espMqttClientTypes::Error error(espMqttClientTypes::Error::SUCCESS); espMqttClientInternals::Outbox::Iterator it = _outbox.emplace(0, error, std::forward(args) ...); - if (it && error == espMqttClientTypes::Error::SUCCESS) return true; - return false; + if (it && error == espMqttClientTypes::Error::SUCCESS) { + return true; + } else { + if (it) _outbox.remove(it); + return false; + } } template bool _addPacketFront(Args&&... args) { espMqttClientTypes::Error error(espMqttClientTypes::Error::SUCCESS); espMqttClientInternals::Outbox::Iterator it = _outbox.emplaceFront(0, error, std::forward(args) ...); - if (it && error == espMqttClientTypes::Error::SUCCESS) return true; - return false; + if (it && error == espMqttClientTypes::Error::SUCCESS) { + return true; + } else { + if (it) _outbox.remove(it); + return false; + } } void _checkOutbox(); diff --git a/lib/espMqttClient/src/MqttClientSetup.h b/lib/espMqttClient/src/MqttClientSetup.h index 73458d47..67f46a07 100644 --- a/lib/espMqttClient/src/MqttClientSetup.h +++ b/lib/espMqttClient/src/MqttClientSetup.h @@ -11,6 +11,11 @@ the LICENSE file. #pragma once +#if EMC_MULTIPLE_CALLBACKS +#include +#include +#endif + #include "MqttClient.h" template @@ -73,35 +78,127 @@ class MqttClientSetup : public MqttClient { return static_cast(*this); } - T& onConnect(espMqttClientTypes::OnConnectCallback callback) { + T& onConnect(espMqttClientTypes::OnConnectCallback callback, uint32_t id = 0) { + #if EMC_MULTIPLE_CALLBACKS + _onConnectCallbacks.emplace_back(callback, id); + #else + (void) id; _onConnectCallback = callback; + #endif return static_cast(*this); } - T& onDisconnect(espMqttClientTypes::OnDisconnectCallback callback) { + T& onDisconnect(espMqttClientTypes::OnDisconnectCallback callback, uint32_t id = 0) { + #if EMC_MULTIPLE_CALLBACKS + _onDisconnectCallbacks.emplace_back(callback, id); + #else + (void) id; _onDisconnectCallback = callback; + #endif return static_cast(*this); } - T& onSubscribe(espMqttClientTypes::OnSubscribeCallback callback) { + T& onSubscribe(espMqttClientTypes::OnSubscribeCallback callback, uint32_t id = 0) { + #if EMC_MULTIPLE_CALLBACKS + _onSubscribeCallbacks.emplace_back(callback, id); + #else + (void) id; _onSubscribeCallback = callback; + #endif return static_cast(*this); } - T& onUnsubscribe(espMqttClientTypes::OnUnsubscribeCallback callback) { + T& onUnsubscribe(espMqttClientTypes::OnUnsubscribeCallback callback, uint32_t id = 0) { + #if EMC_MULTIPLE_CALLBACKS + _onUnsubscribeCallbacks.emplace_back(callback, id); + #else + (void) id; _onUnsubscribeCallback = callback; + #endif return static_cast(*this); } - T& onMessage(espMqttClientTypes::OnMessageCallback callback) { + T& onMessage(espMqttClientTypes::OnMessageCallback callback, uint32_t id = 0) { + #if EMC_MULTIPLE_CALLBACKS + _onMessageCallbacks.emplace_back(callback, id); + #else + (void) id; _onMessageCallback = callback; + #endif return static_cast(*this); } - T& onPublish(espMqttClientTypes::OnPublishCallback callback) { + T& onPublish(espMqttClientTypes::OnPublishCallback callback, uint32_t id = 0) { + #if EMC_MULTIPLE_CALLBACKS + _onPublishCallbacks.emplace_back(callback, id); + #else + (void) id; _onPublishCallback = callback; + #endif + return static_cast(*this); + } + + #if EMC_MULTIPLE_CALLBACKS + T& removeOnConnect(uint32_t id) { + for (auto it = _onConnectCallbacks.begin(); it != _onConnectCallbacks.end(); ++it) { + if (it->second == id) { + _onConnectCallbacks.erase(it); + break; + } + } + return static_cast(*this); + } + + T& removeOnDisconnect(uint32_t id) { + for (auto it = _onDisconnectCallbacks.begin(); it != _onDisconnectCallbacks.end(); ++it) { + if (it->second == id) { + _onDisconnectCallbacks.erase(it); + break; + } + } + return static_cast(*this); + } + + T& removeOnSubscribe(uint32_t id) { + for (auto it = _onSubscribeCallbacks.begin(); it != _onSubscribeCallbacks.end(); ++it) { + if (it->second == id) { + _onSubscribeCallbacks.erase(it); + break; + } + } + return static_cast(*this); + } + + T& removeOnUnsubscribe(uint32_t id) { + for (auto it = _onUnsubscribeCallbacks.begin(); it != _onUnsubscribeCallbacks.end(); ++it) { + if (it->second == id) { + _onUnsubscribeCallbacks.erase(it); + break; + } + } + return static_cast(*this); + } + + T& removeOnMessage(uint32_t id) { + for (auto it = _onMessageCallbacks.begin(); it != _onMessageCallbacks.end(); ++it) { + if (it->second == id) { + _onMessageCallbacks.erase(it); + break; + } + } + return static_cast(*this); + } + + T& removeOnPublish(uint32_t id) { + for (auto it = _onPublishCallbacks.begin(); it != _onPublishCallbacks.end(); ++it) { + if (it->second == id) { + _onPublishCallbacks.erase(it); + break; + } + } return static_cast(*this); } + #endif /* T& onError(espMqttClientTypes::OnErrorCallback callback) { @@ -112,5 +209,37 @@ class MqttClientSetup : public MqttClient { protected: explicit MqttClientSetup(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority = 1, uint8_t core = 1) - : MqttClient(useInternalTask, priority, core) {} + : MqttClient(useInternalTask, priority, core) { + #if EMC_MULTIPLE_CALLBACKS + _onConnectCallback = [this](bool sessionPresent) { + for (auto callback : _onConnectCallbacks) if (callback.first) callback.first(sessionPresent); + }; + _onDisconnectCallback = [this](espMqttClientTypes::DisconnectReason reason) { + for (auto callback : _onDisconnectCallbacks) if (callback.first) callback.first(reason); + }; + _onSubscribeCallback = [this](uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* returncodes, size_t len) { + for (auto callback : _onSubscribeCallbacks) if (callback.first) callback.first(packetId, returncodes, len); + }; + _onUnsubscribeCallback = [this](int16_t packetId) { + for (auto callback : _onUnsubscribeCallbacks) if (callback.first) callback.first(packetId); + }; + _onMessageCallback = [this](const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) { + for (auto callback : _onMessageCallbacks) if (callback.first) callback.first(properties, topic, payload, len, index, total); + }; + _onPublishCallback = [this](uint16_t packetId) { + for (auto callback : _onPublishCallbacks) if (callback.first) callback.first(packetId); + }; + #else + // empty + #endif + } + + #if EMC_MULTIPLE_CALLBACKS + std::list> _onConnectCallbacks; + std::list> _onDisconnectCallbacks; + std::list> _onSubscribeCallbacks; + std::list> _onUnsubscribeCallbacks; + std::list> _onMessageCallbacks; + std::list> _onPublishCallbacks; + #endif }; diff --git a/lib/espMqttClient/src/Outbox.h b/lib/espMqttClient/src/Outbox.h index b123b389..486b6acf 100644 --- a/lib/espMqttClient/src/Outbox.h +++ b/lib/espMqttClient/src/Outbox.h @@ -163,6 +163,16 @@ class Outbox { return false; } + size_t size() const { + Node* n = _first; + size_t count = 0; + while (n) { + n = n->next; + ++count; + } + return count; + } + private: Node* _first; Node* _last; diff --git a/lib/espMqttClient/src/Packets/Packet.cpp b/lib/espMqttClient/src/Packets/Packet.cpp index df463ef7..2f84b503 100644 --- a/lib/espMqttClient/src/Packets/Packet.cpp +++ b/lib/espMqttClient/src/Packets/Packet.cpp @@ -100,7 +100,7 @@ Packet::Packet(espMqttClientTypes::Error& error, (password ? 2 + strlen(password) : 0); // allocate memory - if (!_allocate(remainingLength)) { + if (!_allocate(remainingLength, false)) { error = espMqttClientTypes::Error::OUT_OF_MEMORY; return; } @@ -300,8 +300,8 @@ Packet::Packet(espMqttClientTypes::Error& error, MQTTPacketType type) } -bool Packet::_allocate(size_t remainingLength) { - if (EMC_GET_FREE_MEMORY() < EMC_MIN_FREE_MEMORY) { +bool Packet::_allocate(size_t remainingLength, bool check) { + if (check && EMC_GET_FREE_MEMORY() < EMC_MIN_FREE_MEMORY) { emc_log_w("Packet buffer not allocated: low memory"); return false; } diff --git a/lib/espMqttClient/src/Packets/Packet.h b/lib/espMqttClient/src/Packets/Packet.h index 21d5e0a9..00019fb1 100644 --- a/lib/espMqttClient/src/Packets/Packet.h +++ b/lib/espMqttClient/src/Packets/Packet.h @@ -12,12 +12,12 @@ the LICENSE file. #include #include "Constants.h" -#include "Config.h" +#include "../Config.h" #include "../TypeDefs.h" #include "../Helpers.h" #include "../Logging.h" #include "RemainingLength.h" -#include "String.h" +#include "StringUtil.h" namespace espMqttClientInternals { @@ -97,7 +97,7 @@ class Packet { , _payloadStartIndex(0) , _payloadEndIndex(0) , _getPayload(nullptr) { - static_assert(sizeof...(Args) % 2 == 0); + static_assert(sizeof...(Args) % 2 == 0, "Subscribe should be in topic/qos pairs"); size_t numberTopics = 2 + (sizeof...(Args) / 2); SubscribeItem list[numberTopics] = {topic1, qos1, topic2, qos2, args...}; _createSubscribe(error, list, numberTopics); @@ -133,7 +133,7 @@ class Packet { private: // pass remainingLength = total size - header - remainingLengthLength! - bool _allocate(size_t remainingLength); + bool _allocate(size_t remainingLength, bool check = true); // fills header and returns index of next available byte in buffer size_t _fillPublishHeader(uint16_t packetId, diff --git a/lib/espMqttClient/src/Packets/String.cpp b/lib/espMqttClient/src/Packets/StringUtil.cpp similarity index 96% rename from lib/espMqttClient/src/Packets/String.cpp rename to lib/espMqttClient/src/Packets/StringUtil.cpp index c3fe23fd..7cd3dd8c 100644 --- a/lib/espMqttClient/src/Packets/String.cpp +++ b/lib/espMqttClient/src/Packets/StringUtil.cpp @@ -6,7 +6,7 @@ For a copy, see or the LICENSE file. */ -#include "String.h" +#include "StringUtil.h" namespace espMqttClientInternals { diff --git a/lib/espMqttClient/src/Packets/String.h b/lib/espMqttClient/src/Packets/StringUtil.h similarity index 100% rename from lib/espMqttClient/src/Packets/String.h rename to lib/espMqttClient/src/Packets/StringUtil.h diff --git a/lib/espMqttClient/src/Transport/ClientPosix.cpp b/lib/espMqttClient/src/Transport/ClientPosix.cpp index 83b555d1..1cd66e2b 100644 --- a/lib/espMqttClient/src/Transport/ClientPosix.cpp +++ b/lib/espMqttClient/src/Transport/ClientPosix.cpp @@ -40,7 +40,7 @@ bool ClientPosix::connect(IPAddress ip, uint16_t port) { _host.sin_addr.s_addr = htonl(uint32_t(ip)); _host.sin_port = ::htons(port); - int ret = ::connect(_sockfd, (struct sockaddr *)&_host, sizeof(_host)); + int ret = ::connect(_sockfd, reinterpret_cast(&_host), sizeof(_host)); if (ret < 0) { emc_log_e("Error connecting: %d - (%d) %s", ret, errno, strerror(errno)); diff --git a/lib/espMqttClient/src/Transport/ClientPosix.h b/lib/espMqttClient/src/Transport/ClientPosix.h index a2f9c9fa..af0dd4bf 100644 --- a/lib/espMqttClient/src/Transport/ClientPosix.h +++ b/lib/espMqttClient/src/Transport/ClientPosix.h @@ -43,7 +43,7 @@ class ClientPosix : public Transport { protected: int _sockfd; - struct sockaddr_in _host; + sockaddr_in _host; }; } // namespace espMqttClientInternals diff --git a/lib/espMqttClient/src/Transport/IPAddress.cpp b/lib/espMqttClient/src/Transport/ClientPosixIPAddress.cpp similarity index 94% rename from lib/espMqttClient/src/Transport/IPAddress.cpp rename to lib/espMqttClient/src/Transport/ClientPosixIPAddress.cpp index b198429d..3386dec8 100644 --- a/lib/espMqttClient/src/Transport/IPAddress.cpp +++ b/lib/espMqttClient/src/Transport/ClientPosixIPAddress.cpp @@ -8,7 +8,7 @@ the LICENSE file. #if defined(__linux__) -#include "IPAddress.h" +#include "ClientPosixIPAddress.h" IPAddress::IPAddress() : _address(0) { diff --git a/lib/espMqttClient/src/Transport/IPAddress.h b/lib/espMqttClient/src/Transport/ClientPosixIPAddress.h similarity index 100% rename from lib/espMqttClient/src/Transport/IPAddress.h rename to lib/espMqttClient/src/Transport/ClientPosixIPAddress.h diff --git a/lib/espMqttClient/src/Transport/Transport.h b/lib/espMqttClient/src/Transport/Transport.h index 6720c024..d368d018 100644 --- a/lib/espMqttClient/src/Transport/Transport.h +++ b/lib/espMqttClient/src/Transport/Transport.h @@ -10,7 +10,7 @@ the LICENSE file. #include // size_t -#include "IPAddress.h" +#include "ClientPosixIPAddress.h" namespace espMqttClientInternals { 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 7afd7e12..db70a542 100644 --- a/lib/espMqttClient/test/test_client_native/test_client_native.cpp +++ b/lib/espMqttClient/test/test_client_native/test_client_native.cpp @@ -7,6 +7,12 @@ void setUp() {} void tearDown() {} espMqttClient mqttClient; +uint32_t onConnectCbId = 1; +uint32_t onDisconnectCbId = 2; +uint32_t onSubscribeCbId = 3; +uint32_t onUnsubscribeCbId = 4; +uint32_t onMessageCbId = 5; +uint32_t onPublishCbId = 6; std::atomic_bool exitProgram(false); std::thread t; @@ -30,7 +36,7 @@ void test_connect() { .onConnect([&](bool sessionPresent) mutable { sessionPresentTest = sessionPresent; onConnectCalledTest = true; - }); + }, onConnectCbId); mqttClient.connect(); uint32_t start = millis(); while (millis() - start < 2000) { @@ -44,7 +50,7 @@ void test_connect() { TEST_ASSERT_TRUE(onConnectCalledTest); TEST_ASSERT_FALSE(sessionPresentTest); - mqttClient.onConnect(nullptr); + mqttClient.removeOnConnect(onConnectCbId); } /* @@ -83,7 +89,7 @@ void test_subscribe() { if (len == 1 && returncodes[0] == espMqttClientTypes::SubscribeReturncode::QOS0) { subscribeTest = true; } - }); + }, onSubscribeCbId); mqttClient.subscribe("test/test", 0); uint32_t start = millis(); while (millis() - start < 2000) { @@ -96,7 +102,7 @@ void test_subscribe() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_TRUE(subscribeTest); - mqttClient.onSubscribe(nullptr); + mqttClient.removeOnSubscribe(onSubscribeCbId); } /* @@ -112,7 +118,7 @@ void test_publish() { mqttClient.onPublish([&](uint16_t packetId) mutable { (void) packetId; publishSendTest++; - }); + }, onPublishCbId); std::atomic publishReceiveTest(0); mqttClient.onMessage([&](const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) mutable { (void) properties; @@ -122,7 +128,7 @@ void test_publish() { (void) index; (void) total; publishReceiveTest++; - }); + }, onMessageCbId); 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"); @@ -138,8 +144,8 @@ void test_publish() { TEST_ASSERT_EQUAL_INT(2, publishSendTest); TEST_ASSERT_EQUAL_INT(3, publishReceiveTest); - mqttClient.onPublish(nullptr); - mqttClient.onMessage(nullptr); + mqttClient.removeOnPublish(onPublishCbId); + mqttClient.removeOnMessage(onMessageCbId); } void test_publish_empty() { @@ -147,7 +153,7 @@ void test_publish_empty() { mqttClient.onPublish([&](uint16_t packetId) mutable { (void) packetId; publishSendEmptyTest++; - }); + }, onPublishCbId); std::atomic publishReceiveEmptyTest(0); mqttClient.onMessage([&](const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) mutable { (void) properties; @@ -157,7 +163,7 @@ void test_publish_empty() { (void) index; (void) total; publishReceiveEmptyTest++; - }); + }, onMessageCbId); uint16_t sendQos0Test = mqttClient.publish("test/test", 0, false, nullptr, 0); uint16_t sendQos1Test = mqttClient.publish("test/test", 1, false, nullptr, 0); uint16_t sendQos2Test = mqttClient.publish("test/test", 2, false, nullptr, 0); @@ -173,8 +179,8 @@ void test_publish_empty() { TEST_ASSERT_EQUAL_INT(2, publishSendEmptyTest); TEST_ASSERT_EQUAL_INT(3, publishReceiveEmptyTest); - mqttClient.onPublish(nullptr); - mqttClient.onMessage(nullptr); + mqttClient.removeOnPublish(onPublishCbId); + mqttClient.removeOnMessage(onMessageCbId); } /* @@ -195,13 +201,13 @@ void test_receive1() { (void) index; (void) total; publishReceive1Test++; - }); + }, onMessageCbId); mqttClient.onSubscribe([&](uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* returncodes, size_t len) mutable { (void) packetId; if (len == 1 && returncodes[0] == espMqttClientTypes::SubscribeReturncode::QOS1) { mqttClient.publish("test/test", 1, false, ""); } - }); + }, onSubscribeCbId); mqttClient.subscribe("test/test", 1); uint32_t start = millis(); while (millis() - start < 6000) { @@ -211,8 +217,8 @@ void test_receive1() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_GREATER_THAN_INT(0, publishReceive1Test); - mqttClient.onMessage(nullptr); - mqttClient.onSubscribe(nullptr); + mqttClient.removeOnMessage(onMessageCbId); + mqttClient.removeOnSubscribe(onSubscribeCbId); } /* @@ -233,13 +239,13 @@ void test_receive2() { (void) index; (void) total; publishReceive2Test++; - }); + }, onMessageCbId); mqttClient.onSubscribe([&](uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* returncodes, size_t len) mutable { (void) packetId; if (len == 1 && returncodes[0] == espMqttClientTypes::SubscribeReturncode::QOS2) { mqttClient.publish("test/test", 2, false, ""); } - }); + }, onSubscribeCbId); mqttClient.subscribe("test/test", 2); uint32_t start = millis(); while (millis() - start < 6000) { @@ -249,8 +255,8 @@ void test_receive2() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_EQUAL_INT(1, publishReceive2Test); - mqttClient.onMessage(nullptr); - mqttClient.onSubscribe(nullptr); + mqttClient.removeOnMessage(onMessageCbId); + mqttClient.removeOnSubscribe(onSubscribeCbId); } @@ -265,7 +271,7 @@ void test_unsubscribe() { mqttClient.onUnsubscribe([&](uint16_t packetId) mutable { (void) packetId; unsubscribeTest = true; - }); + }, onUnsubscribeCbId); mqttClient.unsubscribe("test/test"); uint32_t start = millis(); while (millis() - start < 2000) { @@ -278,7 +284,7 @@ void test_unsubscribe() { TEST_ASSERT_TRUE(mqttClient.connected()); TEST_ASSERT_TRUE(unsubscribeTest); - mqttClient.onUnsubscribe(nullptr); + mqttClient.removeOnUnsubscribe(onUnsubscribeCbId); } /* @@ -293,7 +299,7 @@ void test_disconnect() { mqttClient.onDisconnect([&](espMqttClientTypes::DisconnectReason reason) mutable { reasonTest = reason; onDisconnectCalled = true; - }); + }, onDisconnectCbId); mqttClient.disconnect(); uint32_t start = millis(); while (millis() - start < 2000) { @@ -307,7 +313,7 @@ void test_disconnect() { TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::DisconnectReason::USER_OK, reasonTest); TEST_ASSERT_TRUE(mqttClient.disconnected()); - mqttClient.onDisconnect(nullptr); + mqttClient.removeOnDisconnect(onDisconnectCbId); } void test_pub_before_connect() { @@ -320,11 +326,11 @@ void test_pub_before_connect() { .onConnect([&](bool sessionPresent) mutable { sessionPresentTest = sessionPresent; onConnectCalledTest = true; - }) + }, onConnectCbId) .onPublish([&](uint16_t packetId) mutable { (void) packetId; publishSendTest++; - }); + }, onPublishCbId); 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"); @@ -349,8 +355,8 @@ void test_pub_before_connect() { TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos2Test); TEST_ASSERT_EQUAL_INT(2, publishSendTest); - mqttClient.onConnect(nullptr); - mqttClient.onPublish(nullptr); + mqttClient.removeOnConnect(onConnectCbId); + mqttClient.removeOnPublish(onPublishCbId); } void final_disconnect() { @@ -358,7 +364,7 @@ void final_disconnect() { mqttClient.onDisconnect([&](espMqttClientTypes::DisconnectReason reason) mutable { (void) reason; onDisconnectCalled = true; - }); + }, onDisconnectCbId); mqttClient.disconnect(); uint32_t start = millis(); while (millis() - start < 2000) { @@ -370,7 +376,7 @@ void final_disconnect() { if (mqttClient.connected()) { mqttClient.disconnect(true); } - mqttClient.onDisconnect(nullptr); + mqttClient.removeOnDisconnect(onDisconnectCbId); } int main() { diff --git a/lib/espMqttClient/test/test_string/test_string.cpp b/lib/espMqttClient/test/test_string/test_string.cpp index a1d67e5d..f171d775 100644 --- a/lib/espMqttClient/test/test_string/test_string.cpp +++ b/lib/espMqttClient/test/test_string/test_string.cpp @@ -2,7 +2,7 @@ #include -#include +#include void setUp() {} void tearDown() {}