diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.editorconfig b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.editorconfig
new file mode 100644
index 0000000..3dccc6f
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+charset = utf-8
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+[keywords.txt]
+indent_style = tab
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/build_examples_pio.yml b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/build_examples_pio.yml
new file mode 100644
index 0000000..a8ad0ae
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/build_examples_pio.yml
@@ -0,0 +1,27 @@
+name: Build with Platformio
+
+on: [push, pull_request]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v1
+ - name: Set up Python
+ uses: actions/setup-python@v1
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install platformio
+ - name: Add libraries
+ run: |
+ platformio lib -g install AsyncTCP
+ platformio lib -g install ESPAsyncTCP
+ - name: Getting ready
+ run: |
+ chmod +x ./scripts/CI/build_examples_pio.sh
+ - name: Build examples
+ run: |
+ ./scripts/CI/build_examples_pio.sh
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/cpplint.yml b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/cpplint.yml
new file mode 100644
index 0000000..3dc4670
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/cpplint.yml
@@ -0,0 +1,20 @@
+name: cpplint
+
+on: [push, pull_request]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v1
+ - name: Set up Python
+ uses: actions/setup-python@v1
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install cpplint
+ - name: Linting
+ run: |
+ cpplint --repository=. --recursive --filter=-whitespace/line_length,-legal/copyright,-runtime/printf,-build/include,-build/namespace ./src
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.gitignore b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.gitignore
new file mode 100644
index 0000000..f846942
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.gitignore
@@ -0,0 +1,2 @@
+/config.json
+.vscode/
\ No newline at end of file
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.piopm b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.piopm
new file mode 100644
index 0000000..33bd6e8
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.piopm
@@ -0,0 +1 @@
+{"type": "library", "name": "AsyncMqttClient", "version": "0.9.0", "spec": {"owner": "marvinroger", "id": 346, "name": "AsyncMqttClient", "requirements": null, "uri": null}}
\ No newline at end of file
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/LICENSE b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/LICENSE
new file mode 100644
index 0000000..a3ee217
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2021 Marvin Roger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/Makefile b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/Makefile
new file mode 100644
index 0000000..43f99dc
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/Makefile
@@ -0,0 +1,3 @@
+cpplint:
+ cpplint --repository=. --recursive --filter=-whitespace/line_length,-legal/copyright,-runtime/printf,-build/include,-build/namespace ./src
+.PHONY: cpplint
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/README.md b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/README.md
new file mode 100644
index 0000000..beae892
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/README.md
@@ -0,0 +1,19 @@
+# Async MQTT client for ESP8266 and ESP32
+
+![Build with PlatformIO](https://github.com/marvinroger/async-mqtt-client/workflows/Build%20with%20Platformio/badge.svg)
+![cpplint](https://github.com/marvinroger/async-mqtt-client/workflows/cpplint/badge.svg)
+
+An Arduino for ESP8266 and ESP32 asynchronous [MQTT](http://mqtt.org/) client implementation, built on [me-no-dev/ESPAsyncTCP (ESP8266)](https://github.com/me-no-dev/ESPAsyncTCP) | [me-no-dev/AsyncTCP (ESP32)](https://github.com/me-no-dev/AsyncTCP) .
+
+## Features
+
+* Compliant with the 3.1.1 version of the protocol
+* Fully asynchronous
+* Subscribe at QoS 0, 1 and 2
+* Publish at QoS 0, 1 and 2
+* SSL/TLS support
+* Available in the [PlatformIO registry](http://platformio.org/lib/show/346/AsyncMqttClient)
+
+## Requirements, installation and usage
+
+The project is documented in the [/docs folder](docs).
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/async-mqtt-client.cppcheck b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/async-mqtt-client.cppcheck
new file mode 100644
index 0000000..da20086
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/async-mqtt-client.cppcheck
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP32/FullyFeatured-ESP32.ino b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP32/FullyFeatured-ESP32.ino
new file mode 100644
index 0000000..c226569
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP32/FullyFeatured-ESP32.ino
@@ -0,0 +1,135 @@
+/*
+This example uses FreeRTOS softwaretimers as there is no built-in Ticker library
+*/
+
+
+#include
+extern "C" {
+ #include "freertos/FreeRTOS.h"
+ #include "freertos/timers.h"
+}
+#include
+
+#define WIFI_SSID "yourSSID"
+#define WIFI_PASSWORD "yourpass"
+
+#define MQTT_HOST IPAddress(192, 168, 1, 10)
+#define MQTT_PORT 1883
+
+AsyncMqttClient mqttClient;
+TimerHandle_t mqttReconnectTimer;
+TimerHandle_t wifiReconnectTimer;
+
+void connectToWifi() {
+ Serial.println("Connecting to Wi-Fi...");
+ WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
+}
+
+void connectToMqtt() {
+ Serial.println("Connecting to MQTT...");
+ mqttClient.connect();
+}
+
+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");
+ xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
+ xTimerStart(wifiReconnectTimer, 0);
+ break;
+ }
+}
+
+void onMqttConnect(bool sessionPresent) {
+ Serial.println("Connected to MQTT.");
+ Serial.print("Session present: ");
+ Serial.println(sessionPresent);
+ uint16_t packetIdSub = mqttClient.subscribe("test/lol", 2);
+ Serial.print("Subscribing at QoS 2, packetId: ");
+ Serial.println(packetIdSub);
+ mqttClient.publish("test/lol", 0, true, "test 1");
+ Serial.println("Publishing at QoS 0");
+ uint16_t packetIdPub1 = mqttClient.publish("test/lol", 1, true, "test 2");
+ Serial.print("Publishing at QoS 1, packetId: ");
+ Serial.println(packetIdPub1);
+ uint16_t packetIdPub2 = mqttClient.publish("test/lol", 2, true, "test 3");
+ Serial.print("Publishing at QoS 2, packetId: ");
+ Serial.println(packetIdPub2);
+}
+
+void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
+ Serial.println("Disconnected from MQTT.");
+
+ if (WiFi.isConnected()) {
+ xTimerStart(mqttReconnectTimer, 0);
+ }
+}
+
+void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
+ Serial.println("Subscribe acknowledged.");
+ Serial.print(" packetId: ");
+ Serial.println(packetId);
+ Serial.print(" qos: ");
+ Serial.println(qos);
+}
+
+void onMqttUnsubscribe(uint16_t packetId) {
+ Serial.println("Unsubscribe acknowledged.");
+ Serial.print(" packetId: ");
+ Serial.println(packetId);
+}
+
+void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
+ 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();
+
+ mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast(connectToMqtt));
+ wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast(connectToWifi));
+
+ 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() {
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP8266/FullyFeatured-ESP8266.ino b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP8266/FullyFeatured-ESP8266.ino
new file mode 100644
index 0000000..3018b6e
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP8266/FullyFeatured-ESP8266.ino
@@ -0,0 +1,122 @@
+#include
+#include
+#include
+
+#define WIFI_SSID "My_Wi-Fi"
+#define WIFI_PASSWORD "my-awesome-password"
+
+#define MQTT_HOST IPAddress(192, 168, 1, 10)
+#define MQTT_PORT 1883
+
+AsyncMqttClient mqttClient;
+Ticker mqttReconnectTimer;
+
+WiFiEventHandler wifiConnectHandler;
+WiFiEventHandler wifiDisconnectHandler;
+Ticker wifiReconnectTimer;
+
+void connectToWifi() {
+ Serial.println("Connecting to Wi-Fi...");
+ WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
+}
+
+void connectToMqtt() {
+ Serial.println("Connecting to MQTT...");
+ mqttClient.connect();
+}
+
+void onWifiConnect(const WiFiEventStationModeGotIP& event) {
+ Serial.println("Connected to Wi-Fi.");
+ connectToMqtt();
+}
+
+void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
+ Serial.println("Disconnected from Wi-Fi.");
+ mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
+ wifiReconnectTimer.once(2, connectToWifi);
+}
+
+void onMqttConnect(bool sessionPresent) {
+ Serial.println("Connected to MQTT.");
+ Serial.print("Session present: ");
+ Serial.println(sessionPresent);
+ uint16_t packetIdSub = mqttClient.subscribe("test/lol", 2);
+ Serial.print("Subscribing at QoS 2, packetId: ");
+ Serial.println(packetIdSub);
+ mqttClient.publish("test/lol", 0, true, "test 1");
+ Serial.println("Publishing at QoS 0");
+ uint16_t packetIdPub1 = mqttClient.publish("test/lol", 1, true, "test 2");
+ Serial.print("Publishing at QoS 1, packetId: ");
+ Serial.println(packetIdPub1);
+ uint16_t packetIdPub2 = mqttClient.publish("test/lol", 2, true, "test 3");
+ Serial.print("Publishing at QoS 2, packetId: ");
+ Serial.println(packetIdPub2);
+}
+
+void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
+ Serial.println("Disconnected from MQTT.");
+
+ if (WiFi.isConnected()) {
+ mqttReconnectTimer.once(2, connectToMqtt);
+ }
+}
+
+void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
+ Serial.println("Subscribe acknowledged.");
+ Serial.print(" packetId: ");
+ Serial.println(packetId);
+ Serial.print(" qos: ");
+ Serial.println(qos);
+}
+
+void onMqttUnsubscribe(uint16_t packetId) {
+ Serial.println("Unsubscribe acknowledged.");
+ Serial.print(" packetId: ");
+ Serial.println(packetId);
+}
+
+void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
+ 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();
+
+ wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
+ wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
+
+ 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() {
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/platformio.ini b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/platformio.ini
new file mode 100644
index 0000000..8fc8816
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/platformio.ini
@@ -0,0 +1,24 @@
+#
+# Example PlatformIO configuration file for SSL and non-SSL builds.
+#
+# Before you will be able to build the SSL version of this project, you will
+# need to explicitly install the espressif8266_stage platform.
+#
+# To perform this installation, refer to step 1 of:
+# http://docs.platformio.org/en/latest/platforms/espressif8266.html#using-arduino-framework-with-staging-version
+
+[platformio]
+env_default = ssl
+
+[env:ssl]
+platform = espressif8266_stage
+framework = arduino
+board = esp01_1m
+build_flags = -DASYNC_TCP_SSL_ENABLED=1
+lib_deps = AsyncMqttClient
+
+[env:nossl]
+platform = espressif8266
+framework = arduino
+board = esp01_1m
+lib_deps = AsyncMqttClient
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/src/main.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/src/main.cpp
new file mode 100644
index 0000000..cd2cb8b
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/src/main.cpp
@@ -0,0 +1,145 @@
+
+// Example project which can be built with SSL enabled or disabled.
+// The espressif8266_stage platform must be installed.
+// Refer to platformio.ini for the build configuration and platform installation.
+
+#include
+#include
+#include
+#include
+
+#define WIFI_SSID "My_Wi-Fi"
+#define WIFI_PASSWORD "my-awesome-password"
+
+#define MQTT_HOST IPAddress(192, 168, 1, 10)
+
+#if ASYNC_TCP_SSL_ENABLED
+#define MQTT_SECURE true
+#define MQTT_SERVER_FINGERPRINT {0x7e, 0x36, 0x22, 0x01, 0xf9, 0x7e, 0x99, 0x2f, 0xc5, 0xdb, 0x3d, 0xbe, 0xac, 0x48, 0x67, 0x5b, 0x5d, 0x47, 0x94, 0xd2}
+#define MQTT_PORT 8883
+#else
+#define MQTT_PORT 1883
+#endif
+
+AsyncMqttClient mqttClient;
+Ticker mqttReconnectTimer;
+
+WiFiEventHandler wifiConnectHandler;
+WiFiEventHandler wifiDisconnectHandler;
+Ticker wifiReconnectTimer;
+
+void connectToWifi() {
+ Serial.println("Connecting to Wi-Fi...");
+ WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
+}
+
+void connectToMqtt() {
+ Serial.println("Connecting to MQTT...");
+ mqttClient.connect();
+}
+
+void onWifiConnect(const WiFiEventStationModeGotIP& event) {
+ Serial.println("Connected to Wi-Fi.");
+ connectToMqtt();
+}
+
+void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
+ Serial.println("Disconnected from Wi-Fi.");
+ mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
+ wifiReconnectTimer.once(2, connectToWifi);
+}
+
+void onMqttConnect(bool sessionPresent) {
+ Serial.println("Connected to MQTT.");
+ Serial.print("Session present: ");
+ Serial.println(sessionPresent);
+ uint16_t packetIdSub = mqttClient.subscribe("test/lol", 2);
+ Serial.print("Subscribing at QoS 2, packetId: ");
+ Serial.println(packetIdSub);
+ mqttClient.publish("test/lol", 0, true, "test 1");
+ Serial.println("Publishing at QoS 0");
+ uint16_t packetIdPub1 = mqttClient.publish("test/lol", 1, true, "test 2");
+ Serial.print("Publishing at QoS 1, packetId: ");
+ Serial.println(packetIdPub1);
+ uint16_t packetIdPub2 = mqttClient.publish("test/lol", 2, true, "test 3");
+ Serial.print("Publishing at QoS 2, packetId: ");
+ Serial.println(packetIdPub2);
+}
+
+void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
+ Serial.println("Disconnected from MQTT.");
+
+ if (reason == AsyncMqttClientDisconnectReason::TLS_BAD_FINGERPRINT) {
+ Serial.println("Bad server fingerprint.");
+ }
+
+ if (WiFi.isConnected()) {
+ mqttReconnectTimer.once(2, connectToMqtt);
+ }
+}
+
+void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
+ Serial.println("Subscribe acknowledged.");
+ Serial.print(" packetId: ");
+ Serial.println(packetId);
+ Serial.print(" qos: ");
+ Serial.println(qos);
+}
+
+void onMqttUnsubscribe(uint16_t packetId) {
+ Serial.println("Unsubscribe acknowledged.");
+ Serial.print(" packetId: ");
+ Serial.println(packetId);
+}
+
+void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
+ 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();
+
+ wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
+ wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
+
+ mqttClient.onConnect(onMqttConnect);
+ mqttClient.onDisconnect(onMqttDisconnect);
+ mqttClient.onSubscribe(onMqttSubscribe);
+ mqttClient.onUnsubscribe(onMqttUnsubscribe);
+ mqttClient.onMessage(onMqttMessage);
+ mqttClient.onPublish(onMqttPublish);
+ mqttClient.setServer(MQTT_HOST, MQTT_PORT);
+#if ASYNC_TCP_SSL_ENABLED
+ mqttClient.setSecure(MQTT_SECURE);
+ if (MQTT_SECURE) {
+ mqttClient.addServerFingerprint((const uint8_t[])MQTT_SERVER_FINGERPRINT);
+ }
+#endif
+
+ connectToWifi();
+}
+
+void loop() {
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/keywords.txt b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/keywords.txt
new file mode 100644
index 0000000..7b09c05
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/keywords.txt
@@ -0,0 +1,48 @@
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+AsyncMqttClient KEYWORD1
+AsyncMqttClientDisconnectReason KEYWORD1
+AsyncMqttClientMessageProperties KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+setKeepAlive KEYWORD2
+setClientId KEYWORD2
+setCleanSession KEYWORD2
+setMaxTopicLength KEYWORD2
+setCredentials KEYWORD2
+setWill KEYWORD2
+setServer KEYWORD2
+setSecure KEYWORD2
+addServerFingerprint KEYWORD2
+
+onConnect KEYWORD2
+onDisconnect KEYWORD2
+onSubscribe KEYWORD2
+onUnsubscribe KEYWORD2
+onMessage KEYWORD2
+onPublish KEYWORD2
+
+connected KEYWORD2
+connect KEYWORD2
+disconnect KEYWORD2
+subscribe KEYWORD2
+unsubscribe KEYWORD2
+publish KEYWORD2
+clearQueue KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
+TCP_DISCONNECTED LITERAL1
+
+MQTT_UNACCEPTABLE_PROTOCOL_VERSION LITERAL1
+MQTT_IDENTIFIER_REJECTED LITERAL1
+MQTT_SERVER_UNAVAILABLE LITERAL1
+MQTT_MALFORMED_CREDENTIALS LITERAL1
+MQTT_NOT_AUTHORIZED LITERAL1
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.json b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.json
new file mode 100644
index 0000000..9074278
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.json
@@ -0,0 +1,30 @@
+{
+ "name": "AsyncMqttClient",
+ "keywords": "iot, home, automation, async, mqtt, client, esp8266",
+ "description": "An Arduino for ESP8266 / ESP32 asynchronous MQTT client implementation",
+ "authors":
+ {
+ "name": "Marvin ROGER",
+ "url": "https://www.marvinroger.fr"
+ },
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/marvinroger/async-mqtt-client.git"
+ },
+ "version": "0.9.0",
+ "frameworks": "arduino",
+ "platforms": ["espressif8266", "espressif32"],
+ "dependencies": [
+ {
+ "name": "ESPAsyncTCP",
+ "version": ">=1.2.2",
+ "platforms": "espressif8266"
+ },
+ {
+ "name": "AsyncTCP",
+ "version": ">=1.1.1",
+ "platforms": "espressif32"
+ }
+ ]
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.properties b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.properties
new file mode 100644
index 0000000..33136fe
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.properties
@@ -0,0 +1,9 @@
+name=AsyncMqttClient
+version=0.9.0
+author=Marvin ROGER
+maintainer=Marvin ROGER
+sentence=An Arduino for ESP8266 and ESP32 asynchronous MQTT client implementation
+paragraph=Like this project? Please star it on GitHub!
+category=Communication
+url=https://github.com/marvinroger/async-mqtt-client
+architectures=esp8266,esp32
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/build_examples_pio.sh b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/build_examples_pio.sh
new file mode 100644
index 0000000..8bfd7ce
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/build_examples_pio.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+#pip install -U platformio
+#platformio update
+platformio lib -g install AsyncTCP
+platformio lib -g install 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
+while read line; do
+ if [[ "$line" != *ESP8266 && "$line" != *ESP32 ]]
+ then
+ echo -e "========================== BUILDING $line =========================="
+ echo -e "${YELLOW}SKIPPING${NC}"
+ continue
+ fi
+ echo -e "========================== BUILDING $line =========================="
+ if [[ -e "$line/platformio.ini" ]]
+ then
+ # skipping
+ #output=$(platformio ci --lib="." --project-conf="$line/platformio.ini" $line 2>&1)
+ :
+ else
+ if [[ "$line" == *ESP8266 ]]
+ then
+ output=$(platformio ci --lib="." --project-conf="scripts/CI/platformio_esp8266.ini" $line 2>&1)
+ else
+ output=$(platformio ci --lib="." --project-conf="scripts/CI/platformio_esp32.ini" $line 2>&1)
+ fi
+ fi
+ if [ $? -ne 0 ]; then
+ echo "$output"
+ echo -e "Building $line ${RED}FAILED${NC}"
+ retval=1
+ else
+ echo -e "${GREEN}SUCCESS${NC}"
+ fi
+done <<< "$lines"
+
+# cleanup
+platformio lib -g uninstall AsyncTCP
+platformio lib -g uninstall ESPAsyncTCP
+
+exit "$retval"
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp32.ini b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp32.ini
new file mode 100644
index 0000000..9e6ed40
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp32.ini
@@ -0,0 +1,16 @@
+; 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 = esp32dev
+framework = arduino
+build_flags =
+ -Wall
\ No newline at end of file
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp8266.ini b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp8266.ini
new file mode 100644
index 0000000..e0b87d9
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp8266.ini
@@ -0,0 +1,16 @@
+; 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 = esp01_1m
+framework = arduino
+build_flags =
+ -Wall
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/get-fingerprint/get-fingerprint.py b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/get-fingerprint/get-fingerprint.py
new file mode 100644
index 0000000..ec78d1b
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/get-fingerprint/get-fingerprint.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+import argparse
+import ssl
+import hashlib
+
+parser = argparse.ArgumentParser(description='Compute SSL/TLS fingerprints.')
+parser.add_argument('--host', required=True)
+parser.add_argument('--port', default=8883)
+
+args = parser.parse_args()
+print(args.host)
+
+cert_pem = ssl.get_server_certificate((args.host, args.port))
+cert_der = ssl.PEM_cert_to_DER_cert(cert_pem)
+
+md5 = hashlib.md5(cert_der).hexdigest()
+sha1 = hashlib.sha1(cert_der).hexdigest()
+sha256 = hashlib.sha256(cert_der).hexdigest()
+print("MD5: " + md5)
+print("SHA1: " + sha1)
+print("SHA256: " + sha256)
+
+print("\nSHA1 as array initializer:")
+print("const uint8_t fingerprint[] = {0x" + ", 0x".join([sha1[i:i+2] for i in range(0, len(sha1), 2)]) + "};")
+
+print("\nSHA1 as function call:")
+print("mqttClient.addServerFingerprint((const uint8_t[]){0x" + ", 0x".join([sha1[i:i+2] for i in range(0, len(sha1), 2)]) + "});")
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.cpp
new file mode 100644
index 0000000..b4375cf
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.cpp
@@ -0,0 +1,755 @@
+#include "AsyncMqttClient.hpp"
+
+AsyncMqttClient::AsyncMqttClient()
+: _client()
+, _head(nullptr)
+, _tail(nullptr)
+, _sent(0)
+, _state(DISCONNECTED)
+, _disconnectReason(AsyncMqttClientDisconnectReason::TCP_DISCONNECTED)
+, _lastClientActivity(0)
+, _lastServerActivity(0)
+, _lastPingRequestTime(0)
+, _generatedClientId{0}
+, _ip()
+, _host(nullptr)
+, _useIp(false)
+#if ASYNC_TCP_SSL_ENABLED
+, _secure(false)
+#endif
+, _port(0)
+, _keepAlive(15)
+, _cleanSession(true)
+, _clientId(nullptr)
+, _username(nullptr)
+, _password(nullptr)
+, _willTopic(nullptr)
+, _willPayload(nullptr)
+, _willPayloadLength(0)
+, _willQos(0)
+, _willRetain(false)
+#if ASYNC_TCP_SSL_ENABLED
+, _secureServerFingerprints()
+#endif
+, _onConnectUserCallbacks()
+, _onDisconnectUserCallbacks()
+, _onSubscribeUserCallbacks()
+, _onUnsubscribeUserCallbacks()
+, _onMessageUserCallbacks()
+, _onPublishUserCallbacks()
+, _parsingInformation { .bufferState = AsyncMqttClientInternals::BufferState::NONE }
+, _currentParsedPacket(nullptr)
+, _remainingLengthBufferPosition(0)
+, _remainingLengthBuffer{0}
+, _pendingPubRels() {
+ _client.onConnect([](void* obj, AsyncClient* c) { (static_cast(obj))->_onConnect(); }, this);
+ _client.onDisconnect([](void* obj, AsyncClient* c) { (static_cast(obj))->_onDisconnect(); }, this);
+ // _client.onError([](void* obj, AsyncClient* c, int8_t error) { (static_cast(obj))->_onError(error); }, this);
+ // _client.onTimeout([](void* obj, AsyncClient* c, uint32_t time) { (static_cast(obj))->_onTimeout(); }, this);
+ _client.onAck([](void* obj, AsyncClient* c, size_t len, uint32_t time) { (static_cast(obj))->_onAck(len); }, this);
+ _client.onData([](void* obj, AsyncClient* c, void* data, size_t len) { (static_cast(obj))->_onData(static_cast(data), len); }, this);
+ _client.onPoll([](void* obj, AsyncClient* c) { (static_cast(obj))->_onPoll(); }, this);
+ _client.setNoDelay(true); // send small packets immediately (PINGREQ/DISCONN are only 2 bytes)
+#ifdef ESP32
+ sprintf(_generatedClientId, "esp32-%06llx", ESP.getEfuseMac());
+ _xSemaphore = xSemaphoreCreateMutex();
+#elif defined(ESP8266)
+ sprintf(_generatedClientId, "esp8266-%06x", ESP.getChipId());
+#endif
+ _clientId = _generatedClientId;
+
+ setMaxTopicLength(128);
+}
+
+AsyncMqttClient::~AsyncMqttClient() {
+ delete _currentParsedPacket;
+ delete[] _parsingInformation.topicBuffer;
+ _clear();
+ _pendingPubRels.clear();
+ _pendingPubRels.shrink_to_fit();
+ _clearQueue(false); // _clear() doesn't clear session data
+#ifdef ESP32
+ vSemaphoreDelete(_xSemaphore);
+#endif
+}
+
+AsyncMqttClient& AsyncMqttClient::setKeepAlive(uint16_t keepAlive) {
+ _keepAlive = keepAlive;
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::setClientId(const char* clientId) {
+ _clientId = clientId;
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::setCleanSession(bool cleanSession) {
+ _cleanSession = cleanSession;
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::setMaxTopicLength(uint16_t maxTopicLength) {
+ _parsingInformation.maxTopicLength = maxTopicLength;
+ delete[] _parsingInformation.topicBuffer;
+ _parsingInformation.topicBuffer = new char[maxTopicLength + 1];
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::setCredentials(const char* username, const char* password) {
+ _username = username;
+ _password = password;
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::setWill(const char* topic, uint8_t qos, bool retain, const char* payload, size_t length) {
+ _willTopic = topic;
+ _willQos = qos;
+ _willRetain = retain;
+ _willPayload = payload;
+ _willPayloadLength = length;
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::setServer(IPAddress ip, uint16_t port) {
+ _useIp = true;
+ _ip = ip;
+ _port = port;
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::setServer(const char* host, uint16_t port) {
+ _useIp = false;
+ _host = host;
+ _port = port;
+ return *this;
+}
+
+#if ASYNC_TCP_SSL_ENABLED
+AsyncMqttClient& AsyncMqttClient::setSecure(bool secure) {
+ _secure = secure;
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::addServerFingerprint(const uint8_t* fingerprint) {
+ std::array newFingerprint;
+ memcpy(newFingerprint.data(), fingerprint, SHA1_SIZE);
+ _secureServerFingerprints.push_back(newFingerprint);
+ return *this;
+}
+#endif
+
+AsyncMqttClient& AsyncMqttClient::onConnect(AsyncMqttClientInternals::OnConnectUserCallback callback) {
+ _onConnectUserCallbacks.push_back(callback);
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::onDisconnect(AsyncMqttClientInternals::OnDisconnectUserCallback callback) {
+ _onDisconnectUserCallbacks.push_back(callback);
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::onSubscribe(AsyncMqttClientInternals::OnSubscribeUserCallback callback) {
+ _onSubscribeUserCallbacks.push_back(callback);
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::onUnsubscribe(AsyncMqttClientInternals::OnUnsubscribeUserCallback callback) {
+ _onUnsubscribeUserCallbacks.push_back(callback);
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::onMessage(AsyncMqttClientInternals::OnMessageUserCallback callback) {
+ _onMessageUserCallbacks.push_back(callback);
+ return *this;
+}
+
+AsyncMqttClient& AsyncMqttClient::onPublish(AsyncMqttClientInternals::OnPublishUserCallback callback) {
+ _onPublishUserCallbacks.push_back(callback);
+ return *this;
+}
+
+void AsyncMqttClient::_freeCurrentParsedPacket() {
+ delete _currentParsedPacket;
+ _currentParsedPacket = nullptr;
+}
+
+void AsyncMqttClient::_clear() {
+ _lastPingRequestTime = 0;
+ _freeCurrentParsedPacket();
+ _clearQueue(true); // keep session data for now
+
+ _parsingInformation.bufferState = AsyncMqttClientInternals::BufferState::NONE;
+
+ _client.setRxTimeout(0);
+}
+
+/* TCP */
+void AsyncMqttClient::_onConnect() {
+ log_i("TCP conn, MQTT CONNECT");
+#if ASYNC_TCP_SSL_ENABLED
+ if (_secure && _secureServerFingerprints.size() > 0) {
+ SSL* clientSsl = _client.getSSL();
+
+ bool sslFoundFingerprint = false;
+ for (std::array fingerprint : _secureServerFingerprints) {
+ if (ssl_match_fingerprint(clientSsl, fingerprint.data()) == SSL_OK) {
+ sslFoundFingerprint = true;
+ break;
+ }
+ }
+
+ if (!sslFoundFingerprint) {
+ _disconnectReason = AsyncMqttClientDisconnectReason::TLS_BAD_FINGERPRINT;
+ _client.close(true);
+ return;
+ }
+ }
+#endif
+ AsyncMqttClientInternals::OutPacket* msg =
+ new AsyncMqttClientInternals::ConnectOutPacket(_cleanSession,
+ _username,
+ _password,
+ _willTopic,
+ _willRetain,
+ _willQos,
+ _willPayload,
+ _willPayloadLength,
+ _keepAlive,
+ _clientId);
+ _addFront(msg);
+ _handleQueue();
+}
+
+void AsyncMqttClient::_onDisconnect() {
+ log_i("TCP disconn");
+ _state = DISCONNECTED;
+
+ _clear();
+
+ for (auto callback : _onDisconnectUserCallbacks) callback(_disconnectReason);
+}
+
+/*
+void AsyncMqttClient::_onError(int8_t error) {
+ (void)error;
+ // _onDisconnect called anyway
+}
+
+void AsyncMqttClient::_onTimeout() {
+ // disconnection will be handled by ping/pong management
+}
+*/
+
+void AsyncMqttClient::_onAck(size_t len) {
+ log_i("ack %u", len);
+ _handleQueue();
+}
+
+void AsyncMqttClient::_onData(char* data, size_t len) {
+ log_i("data rcv (%u)", len);
+ size_t currentBytePosition = 0;
+ char currentByte;
+ _lastServerActivity = millis();
+ do {
+ switch (_parsingInformation.bufferState) {
+ case AsyncMqttClientInternals::BufferState::NONE:
+ currentByte = data[currentBytePosition++];
+ _parsingInformation.packetType = currentByte >> 4;
+ _parsingInformation.packetFlags = (currentByte << 4) >> 4;
+ _parsingInformation.bufferState = AsyncMqttClientInternals::BufferState::REMAINING_LENGTH;
+ switch (_parsingInformation.packetType) {
+ case AsyncMqttClientInternals::PacketType.CONNACK:
+ log_i("rcv CONNACK");
+ _currentParsedPacket = new AsyncMqttClientInternals::ConnAckPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onConnAck, this, std::placeholders::_1, std::placeholders::_2));
+ _client.setRxTimeout(0);
+ break;
+ case AsyncMqttClientInternals::PacketType.PINGRESP:
+ log_i("rcv PINGRESP");
+ _currentParsedPacket = new AsyncMqttClientInternals::PingRespPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onPingResp, this));
+ break;
+ case AsyncMqttClientInternals::PacketType.SUBACK:
+ log_i("rcv SUBACK");
+ _currentParsedPacket = new AsyncMqttClientInternals::SubAckPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onSubAck, this, std::placeholders::_1, std::placeholders::_2));
+ break;
+ case AsyncMqttClientInternals::PacketType.UNSUBACK:
+ log_i("rcv UNSUBACK");
+ _currentParsedPacket = new AsyncMqttClientInternals::UnsubAckPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onUnsubAck, this, std::placeholders::_1));
+ break;
+ case AsyncMqttClientInternals::PacketType.PUBLISH:
+ log_i("rcv PUBLISH");
+ _currentParsedPacket = new AsyncMqttClientInternals::PublishPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6, std::placeholders::_7, std::placeholders::_8, std::placeholders::_9), std::bind(&AsyncMqttClient::_onPublish, this, std::placeholders::_1, std::placeholders::_2));
+ break;
+ case AsyncMqttClientInternals::PacketType.PUBREL:
+ log_i("rcv PUBREL");
+ _currentParsedPacket = new AsyncMqttClientInternals::PubRelPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onPubRel, this, std::placeholders::_1));
+ break;
+ case AsyncMqttClientInternals::PacketType.PUBACK:
+ log_i("rcv PUBACK");
+ _currentParsedPacket = new AsyncMqttClientInternals::PubAckPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onPubAck, this, std::placeholders::_1));
+ break;
+ case AsyncMqttClientInternals::PacketType.PUBREC:
+ log_i("rcv PUBREC");
+ _currentParsedPacket = new AsyncMqttClientInternals::PubRecPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onPubRec, this, std::placeholders::_1));
+ break;
+ case AsyncMqttClientInternals::PacketType.PUBCOMP:
+ log_i("rcv PUBCOMP");
+ _currentParsedPacket = new AsyncMqttClientInternals::PubCompPacket(&_parsingInformation, std::bind(&AsyncMqttClient::_onPubComp, this, std::placeholders::_1));
+ break;
+ default:
+ log_i("rcv PROTOCOL VIOLATION");
+ disconnect(true);
+ break;
+ }
+ break;
+ case AsyncMqttClientInternals::BufferState::REMAINING_LENGTH:
+ currentByte = data[currentBytePosition++];
+ _remainingLengthBuffer[_remainingLengthBufferPosition++] = currentByte;
+ if (currentByte >> 7 == 0) {
+ _parsingInformation.remainingLength = AsyncMqttClientInternals::Helpers::decodeRemainingLength(_remainingLengthBuffer);
+ _remainingLengthBufferPosition = 0;
+ if (_parsingInformation.remainingLength > 0) {
+ _parsingInformation.bufferState = AsyncMqttClientInternals::BufferState::VARIABLE_HEADER;
+ } else {
+ // PINGRESP is a special case where it has no variable header, so the packet ends right here
+ _parsingInformation.bufferState = AsyncMqttClientInternals::BufferState::NONE;
+ _onPingResp();
+ }
+ }
+ break;
+ case AsyncMqttClientInternals::BufferState::VARIABLE_HEADER:
+ _currentParsedPacket->parseVariableHeader(data, len, ¤tBytePosition);
+ break;
+ case AsyncMqttClientInternals::BufferState::PAYLOAD:
+ _currentParsedPacket->parsePayload(data, len, ¤tBytePosition);
+ break;
+ default:
+ currentBytePosition = len;
+ }
+ } while (currentBytePosition != len);
+}
+
+void AsyncMqttClient::_onPoll() {
+ // if there is too much time the client has sent a ping request without a response, disconnect client to avoid half open connections
+ if (_lastPingRequestTime != 0 && (millis() - _lastPingRequestTime) >= (_keepAlive * 1000 * 2)) {
+ log_w("PING t/o, disconnecting");
+ disconnect(true);
+ return;
+ }
+ // send ping to ensure the server will receive at least one message inside keepalive window
+ if (_state == CONNECTED && _lastPingRequestTime == 0 && (millis() - _lastClientActivity) >= (_keepAlive * 1000 * 0.7)) {
+ _sendPing();
+ // send ping to verify if the server is still there (ensure this is not a half connection)
+ } else if (_state == CONNECTED && _lastPingRequestTime == 0 && (millis() - _lastServerActivity) >= (_keepAlive * 1000 * 0.7)) {
+ _sendPing();
+ }
+ _handleQueue();
+}
+
+/* QUEUE */
+
+void AsyncMqttClient::_insert(AsyncMqttClientInternals::OutPacket* packet) {
+ // We only use this for QoS2 PUBREL so there must be a PUBLISH packet present.
+ // The queue therefore cannot be empty and _head points to this PUBLISH packet.
+ SEMAPHORE_TAKE();
+ log_i("new insert #%u", packet->packetType());
+ packet->next = _head->next;
+ _head->next = packet;
+ if (_head == _tail) { // PUB packet is the only one in the queue
+ _tail = packet;
+ }
+ SEMAPHORE_GIVE();
+ _handleQueue();
+}
+
+void AsyncMqttClient::_addFront(AsyncMqttClientInternals::OutPacket* packet) {
+ // This is only used for the CONNECT packet, to be able to establish a connection
+ // before anything else. The queue can be empty or has packets from the continued session.
+ // In both cases, _head should always point to the CONNECT packet afterwards.
+ SEMAPHORE_TAKE();
+ log_i("new front #%u", packet->packetType());
+ if (_head == nullptr) {
+ _tail = packet;
+ } else {
+ packet->next = _head;
+ }
+ _head = packet;
+ SEMAPHORE_GIVE();
+ _handleQueue();
+}
+
+void AsyncMqttClient::_addBack(AsyncMqttClientInternals::OutPacket* packet) {
+ SEMAPHORE_TAKE();
+ log_i("new back #%u", packet->packetType());
+ if (!_tail) {
+ _head = packet;
+ } else {
+ _tail->next = packet;
+ }
+ _tail = packet;
+ _tail->next = nullptr;
+ SEMAPHORE_GIVE();
+ _handleQueue();
+}
+
+void AsyncMqttClient::_handleQueue() {
+ SEMAPHORE_TAKE();
+ // On ESP32, onDisconnect is called within the close()-call. So we need to make sure we don't lock
+ bool disconnect = false;
+
+ while (_head && _client.space() > 10) { // safe but arbitrary value, send at least 10 bytes
+ // 1. try to send
+ if (_head->size() > _sent) {
+ // On SSL the TCP library returns the total amount of bytes, not just the unencrypted payload length.
+ // So we calculate the amount to be written ourselves.
+ size_t willSend = std::min(_head->size() - _sent, _client.space());
+ size_t realSent = _client.add(reinterpret_cast(_head->data(_sent)), willSend, ASYNC_WRITE_FLAG_COPY); // flag is set by LWIP anyway, added for clarity
+ _sent += willSend;
+ (void)realSent;
+ _client.send();
+ _lastClientActivity = millis();
+ _lastPingRequestTime = 0;
+ #if ASYNC_TCP_SSL_ENABLED
+ log_i("snd #%u: (tls: %u) %u/%u", _head->packetType(), realSent, _sent, _head->size());
+ #else
+ log_i("snd #%u: %u/%u", _head->packetType(), _sent, _head->size());
+ #endif
+ if (_head->packetType() == AsyncMqttClientInternals::PacketType.DISCONNECT) {
+ disconnect = true;
+ }
+ }
+
+ // 2. stop processing when we have to wait for an MQTT acknowledgment
+ if (_head->size() == _sent) {
+ if (_head->released()) {
+ log_i("p #%d rel", _head->packetType());
+ AsyncMqttClientInternals::OutPacket* tmp = _head;
+ _head = _head->next;
+ if (!_head) _tail = nullptr;
+ delete tmp;
+ _sent = 0;
+ } else {
+ break; // sending is complete however send next only after mqtt confirmation
+ }
+ }
+ }
+
+ SEMAPHORE_GIVE();
+ if (disconnect) {
+ log_i("snd DISCONN, disconnecting");
+ _client.close();
+ }
+}
+
+void AsyncMqttClient::_clearQueue(bool keepSessionData) {
+ SEMAPHORE_TAKE();
+ AsyncMqttClientInternals::OutPacket* packet = _head;
+ _head = nullptr;
+ _tail = nullptr;
+
+ while (packet) {
+ /* MQTT spec 3.1.2.4 Clean Session:
+ * - QoS 1 and QoS 2 messages which have been sent to the Server, but have not been completely acknowledged.
+ * - QoS 2 messages which have been received from the Server, but have not been completely acknowledged.
+ * + (unsent PUB messages with QoS > 0)
+ *
+ * To be kept:
+ * - possibly first message (sent to server but not acked)
+ * - PUBREC messages (QoS 2 PUB received but not acked)
+ * - PUBCOMP messages (QoS 2 PUBREL received but not acked)
+ */
+ if (keepSessionData) {
+ if (packet->qos() > 0 && packet->size() <= _sent) { // check for qos includes check for PUB-packet type
+ reinterpret_cast(packet)->setDup();
+ AsyncMqttClientInternals::OutPacket* next = packet->next;
+ log_i("keep #%u", packet->packetType());
+ SEMAPHORE_GIVE();
+ _addBack(packet);
+ SEMAPHORE_TAKE();
+ packet = next;
+ } else if (packet->qos() > 0 ||
+ packet->packetType() == AsyncMqttClientInternals::PacketType.PUBREC ||
+ packet->packetType() == AsyncMqttClientInternals::PacketType.PUBCOMP) {
+ AsyncMqttClientInternals::OutPacket* next = packet->next;
+ log_i("keep #%u", packet->packetType());
+ SEMAPHORE_GIVE();
+ _addBack(packet);
+ SEMAPHORE_TAKE();
+ packet = next;
+ } else {
+ AsyncMqttClientInternals::OutPacket* next = packet->next;
+ delete packet;
+ packet = next;
+ }
+ /* Delete everything when not keeping session data
+ */
+ } else {
+ AsyncMqttClientInternals::OutPacket* next = packet->next;
+ delete packet;
+ packet = next;
+ }
+ }
+ _sent = 0;
+ SEMAPHORE_GIVE();
+}
+
+/* MQTT */
+void AsyncMqttClient::_onPingResp() {
+ log_i("PINGRESP");
+ _freeCurrentParsedPacket();
+ _lastPingRequestTime = 0;
+}
+
+void AsyncMqttClient::_onConnAck(bool sessionPresent, uint8_t connectReturnCode) {
+ log_i("CONNACK");
+ _freeCurrentParsedPacket();
+
+ if (!sessionPresent) {
+ _pendingPubRels.clear();
+ _pendingPubRels.shrink_to_fit();
+ _clearQueue(false); // remove session data
+ }
+
+ if (connectReturnCode == 0) {
+ _state = CONNECTED;
+ for (auto callback : _onConnectUserCallbacks) callback(sessionPresent);
+ } else {
+ // Callbacks are handled by the onDisconnect function which is called from the AsyncTcp lib
+ _disconnectReason = static_cast(connectReturnCode);
+ return;
+ }
+ _handleQueue(); // send any remaining data from continued session
+}
+
+void AsyncMqttClient::_onSubAck(uint16_t packetId, char status) {
+ log_i("SUBACK");
+ _freeCurrentParsedPacket();
+ SEMAPHORE_TAKE();
+ if (_head && _head->packetId() == packetId) {
+ _head->release();
+ log_i("SUB released");
+ }
+ SEMAPHORE_GIVE();
+
+ for (auto callback : _onSubscribeUserCallbacks) callback(packetId, status);
+
+ _handleQueue(); // subscribe confirmed, ready to send next queued item
+}
+
+void AsyncMqttClient::_onUnsubAck(uint16_t packetId) {
+ log_i("UNSUBACK");
+ _freeCurrentParsedPacket();
+ SEMAPHORE_TAKE();
+ if (_head && _head->packetId() == packetId) {
+ _head->release();
+ log_i("UNSUB released");
+ }
+ SEMAPHORE_GIVE();
+
+ for (auto callback : _onUnsubscribeUserCallbacks) callback(packetId);
+
+ _handleQueue(); // unsubscribe confirmed, ready to send next queued item
+}
+
+void AsyncMqttClient::_onMessage(char* topic, char* payload, uint8_t qos, bool dup, bool retain, size_t len, size_t index, size_t total, uint16_t packetId) {
+ bool notifyPublish = true;
+
+ if (qos == 2) {
+ for (AsyncMqttClientInternals::PendingPubRel pendingPubRel : _pendingPubRels) {
+ if (pendingPubRel.packetId == packetId) {
+ notifyPublish = false;
+ break;
+ }
+ }
+ }
+
+ if (notifyPublish) {
+ AsyncMqttClientMessageProperties properties;
+ properties.qos = qos;
+ properties.dup = dup;
+ properties.retain = retain;
+
+ for (auto callback : _onMessageUserCallbacks) callback(topic, payload, properties, len, index, total);
+ }
+}
+
+void AsyncMqttClient::_onPublish(uint16_t packetId, uint8_t qos) {
+ AsyncMqttClientInternals::PendingAck pendingAck;
+
+ if (qos == 1) {
+ pendingAck.packetType = AsyncMqttClientInternals::PacketType.PUBACK;
+ pendingAck.headerFlag = AsyncMqttClientInternals::HeaderFlag.PUBACK_RESERVED;
+ pendingAck.packetId = packetId;
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::PubAckOutPacket(pendingAck);
+ _addBack(msg);
+ } else if (qos == 2) {
+ pendingAck.packetType = AsyncMqttClientInternals::PacketType.PUBREC;
+ pendingAck.headerFlag = AsyncMqttClientInternals::HeaderFlag.PUBREC_RESERVED;
+ pendingAck.packetId = packetId;
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::PubAckOutPacket(pendingAck);
+ _addBack(msg);
+
+ bool pubRelAwaiting = false;
+ for (AsyncMqttClientInternals::PendingPubRel pendingPubRel : _pendingPubRels) {
+ if (pendingPubRel.packetId == packetId) {
+ pubRelAwaiting = true;
+ break;
+ }
+ }
+
+ if (!pubRelAwaiting) {
+ AsyncMqttClientInternals::PendingPubRel pendingPubRel;
+ pendingPubRel.packetId = packetId;
+ _pendingPubRels.push_back(pendingPubRel);
+ }
+ }
+
+ _freeCurrentParsedPacket();
+}
+
+void AsyncMqttClient::_onPubRel(uint16_t packetId) {
+ _freeCurrentParsedPacket();
+
+ AsyncMqttClientInternals::PendingAck pendingAck;
+ pendingAck.packetType = AsyncMqttClientInternals::PacketType.PUBCOMP;
+ pendingAck.headerFlag = AsyncMqttClientInternals::HeaderFlag.PUBCOMP_RESERVED;
+ pendingAck.packetId = packetId;
+ if (_head && _head->packetId() == packetId) {
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::PubAckOutPacket(pendingAck);
+ _head->release();
+ _insert(msg);
+ log_i("PUBREC released");
+ }
+
+ for (size_t i = 0; i < _pendingPubRels.size(); i++) {
+ if (_pendingPubRels[i].packetId == packetId) {
+ _pendingPubRels.erase(_pendingPubRels.begin() + i);
+ _pendingPubRels.shrink_to_fit();
+ }
+ }
+}
+
+void AsyncMqttClient::_onPubAck(uint16_t packetId) {
+ _freeCurrentParsedPacket();
+ if (_head && _head->packetId() == packetId) {
+ _head->release();
+ log_i("PUB released");
+ }
+
+ for (auto callback : _onPublishUserCallbacks) callback(packetId);
+}
+
+void AsyncMqttClient::_onPubRec(uint16_t packetId) {
+ _freeCurrentParsedPacket();
+
+ // We will only be sending 1 QoS>0 PUB message at a time (to honor message
+ // ordering). So no need to store ACKS in a separate container as it will
+ // be stored in the outgoing queue until a PUBCOMP comes in.
+ AsyncMqttClientInternals::PendingAck pendingAck;
+ pendingAck.packetType = AsyncMqttClientInternals::PacketType.PUBREL;
+ pendingAck.headerFlag = AsyncMqttClientInternals::HeaderFlag.PUBREL_RESERVED;
+ pendingAck.packetId = packetId;
+ log_i("snd PUBREL");
+
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::PubAckOutPacket(pendingAck);
+ if (_head && _head->packetId() == packetId) {
+ _head->release();
+ log_i("PUB released");
+ }
+ _insert(msg);
+}
+
+void AsyncMqttClient::_onPubComp(uint16_t packetId) {
+ _freeCurrentParsedPacket();
+
+ // _head points to the PUBREL package
+ if (_head && _head->packetId() == packetId) {
+ _head->release();
+ log_i("PUBREL released");
+ }
+
+ for (auto callback : _onPublishUserCallbacks) callback(packetId);
+}
+
+void AsyncMqttClient::_sendPing() {
+ log_i("PING");
+ _lastPingRequestTime = millis();
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::PingReqOutPacket;
+ _addBack(msg);
+}
+
+bool AsyncMqttClient::connected() const {
+ return _state == CONNECTED;
+}
+
+void AsyncMqttClient::connect() {
+ if (_state != DISCONNECTED) return;
+ log_i("CONNECTING");
+ _state = CONNECTING;
+ _disconnectReason = AsyncMqttClientDisconnectReason::TCP_DISCONNECTED; // reset any previous
+
+ _client.setRxTimeout(_keepAlive);
+
+#if ASYNC_TCP_SSL_ENABLED
+ if (_useIp) {
+ _client.connect(_ip, _port, _secure);
+ } else {
+ _client.connect(_host, _port, _secure);
+ }
+#else
+ if (_useIp) {
+ _client.connect(_ip, _port);
+ } else {
+ _client.connect(_host, _port);
+ }
+#endif
+}
+
+void AsyncMqttClient::disconnect(bool force) {
+ if (_state == DISCONNECTED) return;
+ log_i("DISCONNECT (f:%d)", force);
+ if (force) {
+ _state = DISCONNECTED;
+ _client.close(true);
+ } else if (_state != DISCONNECTING) {
+ _state = DISCONNECTING;
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::DisconnOutPacket;
+ _addBack(msg);
+ }
+}
+
+uint16_t AsyncMqttClient::subscribe(const char* topic, uint8_t qos) {
+ if (_state != CONNECTED) return 0;
+ log_i("SUBSCRIBE");
+
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::SubscribeOutPacket(topic, qos);
+ _addBack(msg);
+ return msg->packetId();
+}
+
+uint16_t AsyncMqttClient::unsubscribe(const char* topic) {
+ if (_state != CONNECTED) return 0;
+ log_i("UNSUBSCRIBE");
+
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::UnsubscribeOutPacket(topic);
+ _addBack(msg);
+ return msg->packetId();
+}
+
+uint16_t AsyncMqttClient::publish(const char* topic, uint8_t qos, bool retain, const char* payload, size_t length, bool dup, uint16_t message_id) {
+ if (_state != CONNECTED || GET_FREE_MEMORY() < MQTT_MIN_FREE_MEMORY) return 0;
+ log_i("PUBLISH");
+
+ AsyncMqttClientInternals::OutPacket* msg = new AsyncMqttClientInternals::PublishOutPacket(topic, qos, retain, payload, length);
+ _addBack(msg);
+ return msg->packetId();
+}
+
+bool AsyncMqttClient::clearQueue() {
+ if (_state != DISCONNECTED) return false;
+ _clearQueue(false);
+ return true;
+}
+
+const char* AsyncMqttClient::getClientId() const {
+ return _clientId;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.h b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.h
new file mode 100644
index 0000000..23d3055
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.h
@@ -0,0 +1,6 @@
+#ifndef SRC_ASYNCMQTTCLIENT_H_
+#define SRC_ASYNCMQTTCLIENT_H_
+
+#include "AsyncMqttClient.hpp"
+
+#endif // SRC_ASYNCMQTTCLIENT_H_
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.hpp
new file mode 100644
index 0000000..1e81103
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.hpp
@@ -0,0 +1,179 @@
+#pragma once
+
+#include
+#include
+
+#include "Arduino.h"
+
+#ifndef MQTT_MIN_FREE_MEMORY
+#define MQTT_MIN_FREE_MEMORY 4096
+#endif
+
+#ifdef ESP32
+#include
+#include
+#elif defined(ESP8266)
+#include
+#else
+#error Platform not supported
+#endif
+
+#if ASYNC_TCP_SSL_ENABLED
+#include
+#define SHA1_SIZE 20
+#endif
+
+#include "AsyncMqttClient/Flags.hpp"
+#include "AsyncMqttClient/ParsingInformation.hpp"
+#include "AsyncMqttClient/MessageProperties.hpp"
+#include "AsyncMqttClient/Helpers.hpp"
+#include "AsyncMqttClient/Callbacks.hpp"
+#include "AsyncMqttClient/DisconnectReasons.hpp"
+#include "AsyncMqttClient/Storage.hpp"
+
+#include "AsyncMqttClient/Packets/Packet.hpp"
+#include "AsyncMqttClient/Packets/ConnAckPacket.hpp"
+#include "AsyncMqttClient/Packets/PingRespPacket.hpp"
+#include "AsyncMqttClient/Packets/SubAckPacket.hpp"
+#include "AsyncMqttClient/Packets/UnsubAckPacket.hpp"
+#include "AsyncMqttClient/Packets/PublishPacket.hpp"
+#include "AsyncMqttClient/Packets/PubRelPacket.hpp"
+#include "AsyncMqttClient/Packets/PubAckPacket.hpp"
+#include "AsyncMqttClient/Packets/PubRecPacket.hpp"
+#include "AsyncMqttClient/Packets/PubCompPacket.hpp"
+
+#include "AsyncMqttClient/Packets/Out/Connect.hpp"
+#include "AsyncMqttClient/Packets/Out/PingReq.hpp"
+#include "AsyncMqttClient/Packets/Out/PubAck.hpp"
+#include "AsyncMqttClient/Packets/Out/Disconn.hpp"
+#include "AsyncMqttClient/Packets/Out/Subscribe.hpp"
+#include "AsyncMqttClient/Packets/Out/Unsubscribe.hpp"
+#include "AsyncMqttClient/Packets/Out/Publish.hpp"
+
+class AsyncMqttClient {
+ public:
+ AsyncMqttClient();
+ ~AsyncMqttClient();
+
+ AsyncMqttClient& setKeepAlive(uint16_t keepAlive);
+ AsyncMqttClient& setClientId(const char* clientId);
+ AsyncMqttClient& setCleanSession(bool cleanSession);
+ AsyncMqttClient& setMaxTopicLength(uint16_t maxTopicLength);
+ AsyncMqttClient& setCredentials(const char* username, const char* password = nullptr);
+ AsyncMqttClient& setWill(const char* topic, uint8_t qos, bool retain, const char* payload = nullptr, size_t length = 0);
+ AsyncMqttClient& setServer(IPAddress ip, uint16_t port);
+ AsyncMqttClient& setServer(const char* host, uint16_t port);
+#if ASYNC_TCP_SSL_ENABLED
+ AsyncMqttClient& setSecure(bool secure);
+ AsyncMqttClient& addServerFingerprint(const uint8_t* fingerprint);
+#endif
+
+ AsyncMqttClient& onConnect(AsyncMqttClientInternals::OnConnectUserCallback callback);
+ AsyncMqttClient& onDisconnect(AsyncMqttClientInternals::OnDisconnectUserCallback callback);
+ AsyncMqttClient& onSubscribe(AsyncMqttClientInternals::OnSubscribeUserCallback callback);
+ AsyncMqttClient& onUnsubscribe(AsyncMqttClientInternals::OnUnsubscribeUserCallback callback);
+ AsyncMqttClient& onMessage(AsyncMqttClientInternals::OnMessageUserCallback callback);
+ AsyncMqttClient& onPublish(AsyncMqttClientInternals::OnPublishUserCallback callback);
+
+ bool connected() const;
+ void connect();
+ void disconnect(bool force = false);
+ uint16_t subscribe(const char* topic, uint8_t qos);
+ uint16_t unsubscribe(const char* topic);
+ uint16_t publish(const char* topic, uint8_t qos, bool retain, const char* payload = nullptr, size_t length = 0, bool dup = false, uint16_t message_id = 0);
+ bool clearQueue(); // Not MQTT compliant!
+
+ const char* getClientId() const;
+
+ private:
+ AsyncClient _client;
+ AsyncMqttClientInternals::OutPacket* _head;
+ AsyncMqttClientInternals::OutPacket* _tail;
+ size_t _sent;
+ enum {
+ CONNECTING,
+ CONNECTED,
+ DISCONNECTING,
+ DISCONNECTED
+ } _state;
+ AsyncMqttClientDisconnectReason _disconnectReason;
+ uint32_t _lastClientActivity;
+ uint32_t _lastServerActivity;
+ uint32_t _lastPingRequestTime;
+
+ char _generatedClientId[18 + 1]; // esp8266-abc123 and esp32-abcdef123456
+ IPAddress _ip;
+ const char* _host;
+ bool _useIp;
+#if ASYNC_TCP_SSL_ENABLED
+ bool _secure;
+#endif
+ uint16_t _port;
+ uint16_t _keepAlive;
+ bool _cleanSession;
+ const char* _clientId;
+ const char* _username;
+ const char* _password;
+ const char* _willTopic;
+ const char* _willPayload;
+ uint16_t _willPayloadLength;
+ uint8_t _willQos;
+ bool _willRetain;
+
+#if ASYNC_TCP_SSL_ENABLED
+ std::vector> _secureServerFingerprints;
+#endif
+
+ std::vector _onConnectUserCallbacks;
+ std::vector _onDisconnectUserCallbacks;
+ std::vector _onSubscribeUserCallbacks;
+ std::vector _onUnsubscribeUserCallbacks;
+ std::vector _onMessageUserCallbacks;
+ std::vector _onPublishUserCallbacks;
+
+ AsyncMqttClientInternals::ParsingInformation _parsingInformation;
+ AsyncMqttClientInternals::Packet* _currentParsedPacket;
+ uint8_t _remainingLengthBufferPosition;
+ char _remainingLengthBuffer[4];
+
+ std::vector _pendingPubRels;
+
+#if defined(ESP32)
+ SemaphoreHandle_t _xSemaphore = nullptr;
+#elif defined(ESP8266)
+ bool _xSemaphore = false;
+#endif
+
+ void _clear();
+ void _freeCurrentParsedPacket();
+
+ // TCP
+ void _onConnect();
+ void _onDisconnect();
+ // void _onError(int8_t error);
+ // void _onTimeout();
+ void _onAck(size_t len);
+ void _onData(char* data, size_t len);
+ void _onPoll();
+
+ // QUEUE
+ void _insert(AsyncMqttClientInternals::OutPacket* packet); // for PUBREL
+ void _addFront(AsyncMqttClientInternals::OutPacket* packet); // for CONNECT
+ void _addBack(AsyncMqttClientInternals::OutPacket* packet); // all the rest
+ void _handleQueue();
+ void _clearQueue(bool keepSessionData);
+
+ // MQTT
+ void _onPingResp();
+ void _onConnAck(bool sessionPresent, uint8_t connectReturnCode);
+ void _onSubAck(uint16_t packetId, char status);
+ void _onUnsubAck(uint16_t packetId);
+ void _onMessage(char* topic, char* payload, uint8_t qos, bool dup, bool retain, size_t len, size_t index, size_t total, uint16_t packetId);
+ void _onPublish(uint16_t packetId, uint8_t qos);
+ void _onPubRel(uint16_t packetId);
+ void _onPubAck(uint16_t packetId);
+ void _onPubRec(uint16_t packetId);
+ void _onPubComp(uint16_t packetId);
+
+ void _sendPing();
+};
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Callbacks.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Callbacks.hpp
new file mode 100644
index 0000000..a8ab2c2
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Callbacks.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include
+
+#include "DisconnectReasons.hpp"
+#include "MessageProperties.hpp"
+#include "Errors.hpp"
+
+namespace AsyncMqttClientInternals {
+// user callbacks
+typedef std::function OnConnectUserCallback;
+typedef std::function OnDisconnectUserCallback;
+typedef std::function OnSubscribeUserCallback;
+typedef std::function OnUnsubscribeUserCallback;
+typedef std::function OnMessageUserCallback;
+typedef std::function OnPublishUserCallback;
+typedef std::function OnErrorUserCallback;
+
+// internal callbacks
+typedef std::function OnConnAckInternalCallback;
+typedef std::function OnPingRespInternalCallback;
+typedef std::function OnSubAckInternalCallback;
+typedef std::function OnUnsubAckInternalCallback;
+typedef std::function OnMessageInternalCallback;
+typedef std::function OnPublishInternalCallback;
+typedef std::function OnPubRelInternalCallback;
+typedef std::function OnPubAckInternalCallback;
+typedef std::function OnPubRecInternalCallback;
+typedef std::function OnPubCompInternalCallback;
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/DisconnectReasons.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/DisconnectReasons.hpp
new file mode 100644
index 0000000..a151140
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/DisconnectReasons.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+enum class AsyncMqttClientDisconnectReason : uint8_t {
+ TCP_DISCONNECTED = 0,
+
+ MQTT_UNACCEPTABLE_PROTOCOL_VERSION = 1,
+ MQTT_IDENTIFIER_REJECTED = 2,
+ MQTT_SERVER_UNAVAILABLE = 3,
+ MQTT_MALFORMED_CREDENTIALS = 4,
+ MQTT_NOT_AUTHORIZED = 5,
+
+ ESP8266_NOT_ENOUGH_SPACE = 6,
+
+ TLS_BAD_FINGERPRINT = 7
+};
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Errors.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Errors.hpp
new file mode 100644
index 0000000..f93e80e
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Errors.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+enum class AsyncMqttClientError : uint8_t {
+ MAX_RETRIES = 0,
+ OUT_OF_MEMORY = 1
+};
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Flags.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Flags.hpp
new file mode 100644
index 0000000..a1fb3e3
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Flags.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+namespace AsyncMqttClientInternals {
+constexpr struct {
+ const uint8_t RESERVED = 0;
+ const uint8_t CONNECT = 1;
+ const uint8_t CONNACK = 2;
+ const uint8_t PUBLISH = 3;
+ const uint8_t PUBACK = 4;
+ const uint8_t PUBREC = 5;
+ const uint8_t PUBREL = 6;
+ const uint8_t PUBCOMP = 7;
+ const uint8_t SUBSCRIBE = 8;
+ const uint8_t SUBACK = 9;
+ const uint8_t UNSUBSCRIBE = 10;
+ const uint8_t UNSUBACK = 11;
+ const uint8_t PINGREQ = 12;
+ const uint8_t PINGRESP = 13;
+ const uint8_t DISCONNECT = 14;
+ const uint8_t RESERVED2 = 1;
+} PacketType;
+
+constexpr struct {
+ const uint8_t CONNECT_RESERVED = 0x00;
+ const uint8_t CONNACK_RESERVED = 0x00;
+ const uint8_t PUBLISH_DUP = 0x08;
+ const uint8_t PUBLISH_QOS0 = 0x00;
+ const uint8_t PUBLISH_QOS1 = 0x02;
+ const uint8_t PUBLISH_QOS2 = 0x04;
+ const uint8_t PUBLISH_QOSRESERVED = 0x06;
+ const uint8_t PUBLISH_RETAIN = 0x01;
+ const uint8_t PUBACK_RESERVED = 0x00;
+ const uint8_t PUBREC_RESERVED = 0x00;
+ const uint8_t PUBREL_RESERVED = 0x02;
+ const uint8_t PUBCOMP_RESERVED = 0x00;
+ const uint8_t SUBSCRIBE_RESERVED = 0x02;
+ const uint8_t SUBACK_RESERVED = 0x00;
+ const uint8_t UNSUBSCRIBE_RESERVED = 0x02;
+ const uint8_t UNSUBACK_RESERVED = 0x00;
+ const uint8_t PINGREQ_RESERVED = 0x00;
+ const uint8_t PINGRESP_RESERVED = 0x00;
+ const uint8_t DISCONNECT_RESERVED = 0x00;
+ const uint8_t RESERVED2_RESERVED = 0x00;
+} HeaderFlag;
+
+constexpr struct {
+ const uint8_t USERNAME = 0x80;
+ const uint8_t PASSWORD = 0x40;
+ const uint8_t WILL_RETAIN = 0x20;
+ const uint8_t WILL_QOS0 = 0x00;
+ const uint8_t WILL_QOS1 = 0x08;
+ const uint8_t WILL_QOS2 = 0x10;
+ const uint8_t WILL = 0x04;
+ const uint8_t CLEAN_SESSION = 0x02;
+ const uint8_t RESERVED = 0x00;
+} ConnectFlag;
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Helpers.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Helpers.hpp
new file mode 100644
index 0000000..1b93b66
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Helpers.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+namespace AsyncMqttClientInternals {
+class Helpers {
+ public:
+ static uint32_t decodeRemainingLength(char* bytes) {
+ uint32_t multiplier = 1;
+ uint32_t value = 0;
+ uint8_t currentByte = 0;
+ uint8_t encodedByte;
+ do {
+ encodedByte = bytes[currentByte++];
+ value += (encodedByte & 127) * multiplier;
+ multiplier *= 128;
+ } while ((encodedByte & 128) != 0);
+
+ return value;
+ }
+
+ static uint8_t encodeRemainingLength(uint32_t remainingLength, char* destination) {
+ uint8_t currentByte = 0;
+ uint8_t bytesNeeded = 0;
+
+ do {
+ uint8_t encodedByte = remainingLength % 128;
+ remainingLength /= 128;
+ if (remainingLength > 0) {
+ encodedByte = encodedByte | 128;
+ }
+
+ destination[currentByte++] = encodedByte;
+ bytesNeeded++;
+ } while (remainingLength > 0);
+
+ return bytesNeeded;
+ }
+};
+
+#if defined(ARDUINO_ARCH_ESP32)
+ #define SEMAPHORE_TAKE() xSemaphoreTake(_xSemaphore, portMAX_DELAY)
+ #define SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
+ #define GET_FREE_MEMORY() ESP.getMaxAllocHeap()
+ #include
+#elif defined(ARDUINO_ARCH_ESP8266)
+ #define SEMAPHORE_TAKE(X) while (_xSemaphore) { /*ESP.wdtFeed();*/ } _xSemaphore = true
+ #define SEMAPHORE_GIVE() _xSemaphore = false
+ #define GET_FREE_MEMORY() ESP.getMaxFreeBlockSize()
+ #if defined(DEBUG_ESP_PORT) && defined(DEBUG_ASYNC_MQTT_CLIENT)
+ #define log_i(...) DEBUG_ESP_PORT.printf(__VA_ARGS__); DEBUG_ESP_PORT.print("\n")
+ #define log_e(...) DEBUG_ESP_PORT.printf(__VA_ARGS__); DEBUG_ESP_PORT.print("\n")
+ #define log_w(...) DEBUG_ESP_PORT.printf(__VA_ARGS__); DEBUG_ESP_PORT.print("\n")
+ #else
+ #define log_i(...)
+ #define log_e(...)
+ #define log_w(...)
+ #endif
+#else
+ #pragma error "No valid architecture"
+#endif
+
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/MessageProperties.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/MessageProperties.hpp
new file mode 100644
index 0000000..c04b596
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/MessageProperties.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+struct AsyncMqttClientMessageProperties {
+ uint8_t qos;
+ bool dup;
+ bool retain;
+};
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.cpp
new file mode 100644
index 0000000..f9091c2
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.cpp
@@ -0,0 +1,30 @@
+#include "ConnAckPacket.hpp"
+
+using AsyncMqttClientInternals::ConnAckPacket;
+
+ConnAckPacket::ConnAckPacket(ParsingInformation* parsingInformation, OnConnAckInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback)
+, _bytePosition(0)
+, _sessionPresent(false)
+, _connectReturnCode(0) {
+}
+
+ConnAckPacket::~ConnAckPacket() {
+}
+
+void ConnAckPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition++ == 0) {
+ _sessionPresent = (currentByte << 7) >> 7;
+ } else {
+ _connectReturnCode = currentByte;
+ _parsingInformation->bufferState = BufferState::NONE;
+ _callback(_sessionPresent, _connectReturnCode);
+ }
+}
+
+void ConnAckPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.hpp
new file mode 100644
index 0000000..8be9ab1
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class ConnAckPacket : public Packet {
+ public:
+ explicit ConnAckPacket(ParsingInformation* parsingInformation, OnConnAckInternalCallback callback);
+ ~ConnAckPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnConnAckInternalCallback _callback;
+
+ uint8_t _bytePosition;
+ bool _sessionPresent;
+ uint8_t _connectReturnCode;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.cpp
new file mode 100644
index 0000000..a9a86e4
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.cpp
@@ -0,0 +1,162 @@
+#include "Connect.hpp"
+
+using AsyncMqttClientInternals::ConnectOutPacket;
+
+ConnectOutPacket::ConnectOutPacket(bool cleanSession,
+ const char* username,
+ const char* password,
+ const char* willTopic,
+ bool willRetain,
+ uint8_t willQos,
+ const char* willPayload,
+ uint16_t willPayloadLength,
+ uint16_t keepAlive,
+ const char* clientId) {
+ char fixedHeader[5];
+ fixedHeader[0] = AsyncMqttClientInternals::PacketType.CONNECT;
+ fixedHeader[0] = fixedHeader[0] << 4;
+ fixedHeader[0] = fixedHeader[0] | AsyncMqttClientInternals::HeaderFlag.CONNECT_RESERVED;
+
+ uint16_t protocolNameLength = 4;
+ char protocolNameLengthBytes[2];
+ protocolNameLengthBytes[0] = protocolNameLength >> 8;
+ protocolNameLengthBytes[1] = protocolNameLength & 0xFF;
+
+ char protocolLevel[1];
+ protocolLevel[0] = 0x04;
+
+ char connectFlags[1];
+ connectFlags[0] = 0;
+ if (cleanSession) connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.CLEAN_SESSION;
+ if (username != nullptr) connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.USERNAME;
+ if (password != nullptr) connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.PASSWORD;
+ if (willTopic != nullptr) {
+ connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.WILL;
+ if (willRetain) connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.WILL_RETAIN;
+ switch (willQos) {
+ case 0:
+ connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.WILL_QOS0;
+ break;
+ case 1:
+ connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.WILL_QOS1;
+ break;
+ case 2:
+ connectFlags[0] |= AsyncMqttClientInternals::ConnectFlag.WILL_QOS2;
+ break;
+ }
+ }
+
+ char keepAliveBytes[2];
+ keepAliveBytes[0] = keepAlive >> 8;
+ keepAliveBytes[1] = keepAlive & 0xFF;
+
+ uint16_t clientIdLength = strlen(clientId);
+ char clientIdLengthBytes[2];
+ clientIdLengthBytes[0] = clientIdLength >> 8;
+ clientIdLengthBytes[1] = clientIdLength & 0xFF;
+
+ // Optional fields
+ uint16_t willTopicLength = 0;
+ char willTopicLengthBytes[2];
+ char willPayloadLengthBytes[2];
+ if (willTopic != nullptr) {
+ willTopicLength = strlen(willTopic);
+ willTopicLengthBytes[0] = willTopicLength >> 8;
+ willTopicLengthBytes[1] = willTopicLength & 0xFF;
+
+ if (willPayload != nullptr && willPayloadLength == 0) willPayloadLength = strlen(willPayload);
+
+ willPayloadLengthBytes[0] = willPayloadLength >> 8;
+ willPayloadLengthBytes[1] = willPayloadLength & 0xFF;
+ }
+
+ uint16_t usernameLength = 0;
+ char usernameLengthBytes[2];
+ if (username != nullptr) {
+ usernameLength = strlen(username);
+ usernameLengthBytes[0] = usernameLength >> 8;
+ usernameLengthBytes[1] = usernameLength & 0xFF;
+ }
+
+ uint16_t passwordLength = 0;
+ char passwordLengthBytes[2];
+ if (password != nullptr) {
+ passwordLength = strlen(password);
+ passwordLengthBytes[0] = passwordLength >> 8;
+ passwordLengthBytes[1] = passwordLength & 0xFF;
+ }
+
+ uint32_t remainingLength = 2 + protocolNameLength + 1 + 1 + 2 + 2 + clientIdLength; // always present
+ if (willTopic != nullptr) remainingLength += 2 + willTopicLength + 2 + willPayloadLength;
+ if (username != nullptr) remainingLength += 2 + usernameLength;
+ if (password != nullptr) remainingLength += 2 + passwordLength;
+ uint8_t remainingLengthLength = AsyncMqttClientInternals::Helpers::encodeRemainingLength(remainingLength, fixedHeader + 1);
+
+ uint32_t neededSpace = 1 + remainingLengthLength;
+ neededSpace += 2;
+ neededSpace += protocolNameLength;
+ neededSpace += 1;
+ neededSpace += 1;
+ neededSpace += 2;
+ neededSpace += 2;
+ neededSpace += clientIdLength;
+ if (willTopic != nullptr) {
+ neededSpace += 2;
+ neededSpace += willTopicLength;
+
+ neededSpace += 2;
+ if (willPayload != nullptr) neededSpace += willPayloadLength;
+ }
+ if (username != nullptr) {
+ neededSpace += 2;
+ neededSpace += usernameLength;
+ }
+ if (password != nullptr) {
+ neededSpace += 2;
+ neededSpace += passwordLength;
+ }
+
+ _data.reserve(neededSpace);
+
+ _data.insert(_data.end(), fixedHeader, fixedHeader + 1 + remainingLengthLength);
+
+ _data.push_back(protocolNameLengthBytes[0]);
+ _data.push_back(protocolNameLengthBytes[1]);
+
+ _data.push_back('M');
+ _data.push_back('Q');
+ _data.push_back('T');
+ _data.push_back('T');
+
+ _data.push_back(protocolLevel[0]);
+ _data.push_back(connectFlags[0]);
+ _data.push_back(keepAliveBytes[0]);
+ _data.push_back(keepAliveBytes[1]);
+ _data.push_back(clientIdLengthBytes[0]);
+ _data.push_back(clientIdLengthBytes[1]);
+
+ _data.insert(_data.end(), clientId, clientId + clientIdLength);
+ if (willTopic != nullptr) {
+ _data.insert(_data.end(), willTopicLengthBytes, willTopicLengthBytes + 2);
+ _data.insert(_data.end(), willTopic, willTopic + willTopicLength);
+
+ _data.insert(_data.end(), willPayloadLengthBytes, willPayloadLengthBytes + 2);
+ if (willPayload != nullptr) _data.insert(_data.end(), willPayload, willPayload + willPayloadLength);
+ }
+ if (username != nullptr) {
+ _data.insert(_data.end(), usernameLengthBytes, usernameLengthBytes + 2);
+ _data.insert(_data.end(), username, username + usernameLength);
+ }
+ if (password != nullptr) {
+ _data.insert(_data.end(), passwordLengthBytes, passwordLengthBytes + 2);
+ _data.insert(_data.end(), password, password + passwordLength);
+ }
+}
+
+const uint8_t* ConnectOutPacket::data(size_t index) const {
+ return &_data.data()[index];
+}
+
+size_t ConnectOutPacket::size() const {
+ return _data.size();
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.hpp
new file mode 100644
index 0000000..5b17632
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include
+#include // strlen
+
+#include "OutPacket.hpp"
+#include "../../Flags.hpp"
+#include "../../Helpers.hpp"
+
+namespace AsyncMqttClientInternals {
+class ConnectOutPacket : public OutPacket {
+ public:
+ ConnectOutPacket(bool cleanSession,
+ const char* username,
+ const char* password,
+ const char* willTopic,
+ bool willRetain,
+ uint8_t willQos,
+ const char* willPayload,
+ uint16_t willPayloadLength,
+ uint16_t keepAlive,
+ const char* clientId);
+ const uint8_t* data(size_t index = 0) const;
+ size_t size() const;
+
+ private:
+ std::vector _data;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.cpp
new file mode 100644
index 0000000..3e2890d
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.cpp
@@ -0,0 +1,18 @@
+#include "Disconn.hpp"
+
+using AsyncMqttClientInternals::DisconnOutPacket;
+
+DisconnOutPacket::DisconnOutPacket() {
+ _data[0] = AsyncMqttClientInternals::PacketType.DISCONNECT;
+ _data[0] = _data[0] << 4;
+ _data[0] = _data[0] | AsyncMqttClientInternals::HeaderFlag.DISCONNECT_RESERVED;
+ _data[1] = 0;
+}
+
+const uint8_t* DisconnOutPacket::data(size_t index) const {
+ return &_data[index];
+}
+
+size_t DisconnOutPacket::size() const {
+ return 2;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.hpp
new file mode 100644
index 0000000..38dc915
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "OutPacket.hpp"
+#include "../../Flags.hpp"
+#include "../../Helpers.hpp"
+
+namespace AsyncMqttClientInternals {
+class DisconnOutPacket : public OutPacket {
+ public:
+ DisconnOutPacket();
+ const uint8_t* data(size_t index = 0) const;
+ size_t size() const;
+
+ private:
+ uint8_t _data[2];
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.cpp
new file mode 100644
index 0000000..e69a87f
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.cpp
@@ -0,0 +1,44 @@
+#include "OutPacket.hpp"
+
+using AsyncMqttClientInternals::OutPacket;
+
+OutPacket::OutPacket()
+: next(nullptr)
+, timeout(0)
+, noTries(0)
+, _released(true)
+, _packetId(0) {}
+
+OutPacket::~OutPacket() {}
+
+bool OutPacket::released() const {
+ return _released;
+}
+
+uint8_t OutPacket::packetType() const {
+ return data(0)[0] >> 4;
+}
+
+uint16_t OutPacket::packetId() const {
+ return _packetId;
+}
+
+uint8_t OutPacket::qos() const {
+ if (packetType() == AsyncMqttClientInternals::PacketType.PUBLISH) {
+ return (data()[1] & 0x06) >> 1;
+ }
+ return 0;
+}
+
+void OutPacket::release() {
+ _released = true;
+}
+
+uint16_t OutPacket::_nextPacketId = 0;
+
+uint16_t OutPacket::_getNextPacketId() {
+ if (++_nextPacketId == 0) {
+ ++_nextPacketId;
+ }
+ return _nextPacketId;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.hpp
new file mode 100644
index 0000000..52c37de
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include // uint*_t
+#include // size_t
+#include // std::min
+
+#include "../../Flags.hpp"
+
+namespace AsyncMqttClientInternals {
+class OutPacket {
+ public:
+ OutPacket();
+ virtual ~OutPacket();
+ virtual const uint8_t* data(size_t index = 0) const = 0;
+ virtual size_t size() const = 0;
+ bool released() const;
+ uint8_t packetType() const;
+ uint16_t packetId() const;
+ uint8_t qos() const;
+ void release();
+
+ public:
+ OutPacket* next;
+ uint32_t timeout;
+ uint8_t noTries;
+
+ protected:
+ static uint16_t _getNextPacketId();
+ bool _released;
+ uint16_t _packetId;
+
+ private:
+ static uint16_t _nextPacketId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.cpp
new file mode 100644
index 0000000..d59cf3d
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.cpp
@@ -0,0 +1,18 @@
+#include "PingReq.hpp"
+
+using AsyncMqttClientInternals::PingReqOutPacket;
+
+PingReqOutPacket::PingReqOutPacket() {
+ _data[0] = AsyncMqttClientInternals::PacketType.PINGREQ;
+ _data[0] = _data[0] << 4;
+ _data[0] = _data[0] | AsyncMqttClientInternals::HeaderFlag.PINGREQ_RESERVED;
+ _data[1] = 0;
+}
+
+const uint8_t* PingReqOutPacket::data(size_t index) const {
+ return &_data[index];;
+}
+
+size_t PingReqOutPacket::size() const {
+ return 2;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.hpp
new file mode 100644
index 0000000..1cb19a3
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "OutPacket.hpp"
+#include "../../Flags.hpp"
+#include "../../Helpers.hpp"
+
+namespace AsyncMqttClientInternals {
+class PingReqOutPacket : public OutPacket {
+ public:
+ PingReqOutPacket();
+ const uint8_t* data(size_t index = 0) const;
+ size_t size() const;
+
+ private:
+ uint8_t _data[2];
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.cpp
new file mode 100644
index 0000000..634607b
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.cpp
@@ -0,0 +1,25 @@
+#include "PubAck.hpp"
+
+using AsyncMqttClientInternals::PubAckOutPacket;
+
+PubAckOutPacket::PubAckOutPacket(PendingAck pendingAck) {
+ _data[0] = pendingAck.packetType;
+ _data[0] = _data[0] << 4;
+ _data[0] = _data[0] | pendingAck.headerFlag;
+ _data[1] = 2;
+ _packetId = pendingAck.packetId;
+ _data[2] = pendingAck.packetId >> 8;
+ _data[3] = pendingAck.packetId & 0xFF;
+ if (packetType() == AsyncMqttClientInternals::PacketType.PUBREL ||
+ packetType() == AsyncMqttClientInternals::PacketType.PUBREC) {
+ _released = false;
+ }
+}
+
+const uint8_t* PubAckOutPacket::data(size_t index) const {
+ return &_data[index];
+}
+
+size_t PubAckOutPacket::size() const {
+ return 4;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.hpp
new file mode 100644
index 0000000..9cd830e
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "OutPacket.hpp"
+#include "../../Flags.hpp"
+#include "../../Helpers.hpp"
+#include "../../Storage.hpp"
+
+namespace AsyncMqttClientInternals {
+class PubAckOutPacket : public OutPacket {
+ public:
+ explicit PubAckOutPacket(PendingAck pendingAck);
+ const uint8_t* data(size_t index = 0) const;
+ size_t size() const;
+
+ private:
+ uint8_t _data[4];
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.cpp
new file mode 100644
index 0000000..3f4365b
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.cpp
@@ -0,0 +1,69 @@
+#include "Publish.hpp"
+
+using AsyncMqttClientInternals::PublishOutPacket;
+
+PublishOutPacket::PublishOutPacket(const char* topic, uint8_t qos, bool retain, const char* payload, size_t length) {
+ char fixedHeader[5];
+ fixedHeader[0] = AsyncMqttClientInternals::PacketType.PUBLISH;
+ fixedHeader[0] = fixedHeader[0] << 4;
+ // if (dup) fixedHeader[0] |= AsyncMqttClientInternals::HeaderFlag.PUBLISH_DUP;
+ if (retain) fixedHeader[0] |= AsyncMqttClientInternals::HeaderFlag.PUBLISH_RETAIN;
+ switch (qos) {
+ case 0:
+ fixedHeader[0] |= AsyncMqttClientInternals::HeaderFlag.PUBLISH_QOS0;
+ break;
+ case 1:
+ fixedHeader[0] |= AsyncMqttClientInternals::HeaderFlag.PUBLISH_QOS1;
+ break;
+ case 2:
+ fixedHeader[0] |= AsyncMqttClientInternals::HeaderFlag.PUBLISH_QOS2;
+ break;
+ }
+
+ uint16_t topicLength = strlen(topic);
+ char topicLengthBytes[2];
+ topicLengthBytes[0] = topicLength >> 8;
+ topicLengthBytes[1] = topicLength & 0xFF;
+
+ uint32_t payloadLength = length;
+ if (payload != nullptr && payloadLength == 0) payloadLength = strlen(payload);
+
+ uint32_t remainingLength = 2 + topicLength + payloadLength;
+ if (qos != 0) remainingLength += 2;
+ uint8_t remainingLengthLength = AsyncMqttClientInternals::Helpers::encodeRemainingLength(remainingLength, fixedHeader + 1);
+
+ size_t neededSpace = 0;
+ neededSpace += 1 + remainingLengthLength;
+ neededSpace += 2;
+ neededSpace += topicLength;
+ if (qos != 0) neededSpace += 2;
+ if (payload != nullptr) neededSpace += payloadLength;
+
+ _data.reserve(neededSpace);
+
+ _packetId = (qos !=0) ? _getNextPacketId() : 1;
+ char packetIdBytes[2];
+ packetIdBytes[0] = _packetId >> 8;
+ packetIdBytes[1] = _packetId & 0xFF;
+
+ _data.insert(_data.end(), fixedHeader, fixedHeader + 1 + remainingLengthLength);
+ _data.insert(_data.end(), topicLengthBytes, topicLengthBytes + 2);
+ _data.insert(_data.end(), topic, topic + topicLength);
+ if (qos != 0) {
+ _data.insert(_data.end(), packetIdBytes, packetIdBytes + 2);
+ _released = false;
+ }
+ if (payload != nullptr) _data.insert(_data.end(), payload, payload + payloadLength);
+}
+
+const uint8_t* PublishOutPacket::data(size_t index) const {
+ return &_data.data()[index];
+}
+
+size_t PublishOutPacket::size() const {
+ return _data.size();
+}
+
+void PublishOutPacket::setDup() {
+ _data[0] |= AsyncMqttClientInternals::HeaderFlag.PUBLISH_DUP;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.hpp
new file mode 100644
index 0000000..6b8272e
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include // strlen
+#include
+
+#include "OutPacket.hpp"
+#include "../../Flags.hpp"
+#include "../../Helpers.hpp"
+#include "../../Storage.hpp"
+
+namespace AsyncMqttClientInternals {
+class PublishOutPacket : public OutPacket {
+ public:
+ PublishOutPacket(const char* topic, uint8_t qos, bool retain, const char* payload, size_t length);
+ const uint8_t* data(size_t index = 0) const;
+ size_t size() const;
+
+ void setDup(); // you cannot unset dup
+
+ private:
+ std::vector _data;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.cpp
new file mode 100644
index 0000000..85c10db
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.cpp
@@ -0,0 +1,49 @@
+#include "Subscribe.hpp"
+
+using AsyncMqttClientInternals::SubscribeOutPacket;
+
+SubscribeOutPacket::SubscribeOutPacket(const char* topic, uint8_t qos) {
+ char fixedHeader[5];
+ fixedHeader[0] = AsyncMqttClientInternals::PacketType.SUBSCRIBE;
+ fixedHeader[0] = fixedHeader[0] << 4;
+ fixedHeader[0] = fixedHeader[0] | AsyncMqttClientInternals::HeaderFlag.SUBSCRIBE_RESERVED;
+
+ uint16_t topicLength = strlen(topic);
+ char topicLengthBytes[2];
+ topicLengthBytes[0] = topicLength >> 8;
+ topicLengthBytes[1] = topicLength & 0xFF;
+
+ char qosByte[1];
+ qosByte[0] = qos;
+
+ uint8_t remainingLengthLength = AsyncMqttClientInternals::Helpers::encodeRemainingLength(2 + 2 + topicLength + 1, fixedHeader + 1);
+
+ size_t neededSpace = 0;
+ neededSpace += 1 + remainingLengthLength;
+ neededSpace += 2;
+ neededSpace += 2;
+ neededSpace += topicLength;
+ neededSpace += 1;
+
+ _data.reserve(neededSpace);
+
+ _packetId = _getNextPacketId();
+ char packetIdBytes[2];
+ packetIdBytes[0] = _packetId >> 8;
+ packetIdBytes[1] = _packetId & 0xFF;
+
+ _data.insert(_data.end(), fixedHeader, fixedHeader + 1 + remainingLengthLength);
+ _data.insert(_data.end(), packetIdBytes, packetIdBytes + 2);
+ _data.insert(_data.end(), topicLengthBytes, topicLengthBytes + 2);
+ _data.insert(_data.end(), topic, topic + topicLength);
+ _data.push_back(qosByte[0]);
+ _released = false;
+}
+
+const uint8_t* SubscribeOutPacket::data(size_t index) const {
+ return &_data.data()[index];
+}
+
+size_t SubscribeOutPacket::size() const {
+ return _data.size();
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.hpp
new file mode 100644
index 0000000..1f85f59
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include // strlen
+#include
+
+#include "OutPacket.hpp"
+#include "../../Flags.hpp"
+#include "../../Helpers.hpp"
+#include "../../Storage.hpp"
+
+namespace AsyncMqttClientInternals {
+class SubscribeOutPacket : public OutPacket {
+ public:
+ SubscribeOutPacket(const char* topic, uint8_t qos);
+ const uint8_t* data(size_t index = 0) const;
+ size_t size() const;
+
+ private:
+ std::vector _data;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.cpp
new file mode 100644
index 0000000..4d859c9
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.cpp
@@ -0,0 +1,42 @@
+#include "Unsubscribe.hpp"
+
+using AsyncMqttClientInternals::UnsubscribeOutPacket;
+
+UnsubscribeOutPacket::UnsubscribeOutPacket(const char* topic) {
+ char fixedHeader[5];
+ fixedHeader[0] = AsyncMqttClientInternals::PacketType.UNSUBSCRIBE;
+ fixedHeader[0] = fixedHeader[0] << 4;
+ fixedHeader[0] = fixedHeader[0] | AsyncMqttClientInternals::HeaderFlag.UNSUBSCRIBE_RESERVED;
+
+ uint16_t topicLength = strlen(topic);
+ char topicLengthBytes[2];
+ topicLengthBytes[0] = topicLength >> 8;
+ topicLengthBytes[1] = topicLength & 0xFF;
+
+ uint8_t remainingLengthLength = AsyncMqttClientInternals::Helpers::encodeRemainingLength(2 + 2 + topicLength, fixedHeader + 1);
+
+ size_t neededSpace = 0;
+ neededSpace += 1 + remainingLengthLength;
+ neededSpace += 2;
+ neededSpace += 2;
+ neededSpace += topicLength;
+
+ _packetId = _getNextPacketId();
+ char packetIdBytes[2];
+ packetIdBytes[0] = _packetId >> 8;
+ packetIdBytes[1] = _packetId & 0xFF;
+
+ _data.insert(_data.end(), fixedHeader, fixedHeader + 1 + remainingLengthLength);
+ _data.insert(_data.end(), packetIdBytes, packetIdBytes + 2);
+ _data.insert(_data.end(), topicLengthBytes, topicLengthBytes + 2);
+ _data.insert(_data.end(), topic, topic + topicLength);
+ _released = false;
+}
+
+const uint8_t* UnsubscribeOutPacket::data(size_t index) const {
+ return &_data.data()[index];
+}
+
+size_t UnsubscribeOutPacket::size() const {
+ return _data.size();
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.hpp
new file mode 100644
index 0000000..621802f
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include // strlen
+#include
+
+#include "OutPacket.hpp"
+#include "../../Flags.hpp"
+#include "../../Helpers.hpp"
+#include "../../Storage.hpp"
+
+namespace AsyncMqttClientInternals {
+class UnsubscribeOutPacket : public OutPacket {
+ public:
+ explicit UnsubscribeOutPacket(const char* topic);
+ const uint8_t* data(size_t index = 0) const;
+ size_t size() const;
+
+ private:
+ std::vector _data;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Packet.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Packet.hpp
new file mode 100644
index 0000000..9552cf0
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Packet.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace AsyncMqttClientInternals {
+class Packet {
+ public:
+ virtual ~Packet() {}
+
+ virtual void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) = 0;
+ virtual void parsePayload(char* data, size_t len, size_t* currentBytePosition) = 0;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.cpp
new file mode 100644
index 0000000..2a939aa
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.cpp
@@ -0,0 +1,21 @@
+#include "PingRespPacket.hpp"
+
+using AsyncMqttClientInternals::PingRespPacket;
+
+PingRespPacket::PingRespPacket(ParsingInformation* parsingInformation, OnPingRespInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback) {
+}
+
+PingRespPacket::~PingRespPacket() {
+}
+
+void PingRespPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
+
+void PingRespPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.hpp
new file mode 100644
index 0000000..043a730
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class PingRespPacket : public Packet {
+ public:
+ explicit PingRespPacket(ParsingInformation* parsingInformation, OnPingRespInternalCallback callback);
+ ~PingRespPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnPingRespInternalCallback _callback;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.cpp
new file mode 100644
index 0000000..efa5fa4
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.cpp
@@ -0,0 +1,30 @@
+#include "PubAckPacket.hpp"
+
+using AsyncMqttClientInternals::PubAckPacket;
+
+PubAckPacket::PubAckPacket(ParsingInformation* parsingInformation, OnPubAckInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback)
+, _bytePosition(0)
+, _packetIdMsb(0)
+, _packetId(0) {
+}
+
+PubAckPacket::~PubAckPacket() {
+}
+
+void PubAckPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition++ == 0) {
+ _packetIdMsb = currentByte;
+ } else {
+ _packetId = currentByte | _packetIdMsb << 8;
+ _parsingInformation->bufferState = BufferState::NONE;
+ _callback(_packetId);
+ }
+}
+
+void PubAckPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.hpp
new file mode 100644
index 0000000..bd00142
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class PubAckPacket : public Packet {
+ public:
+ explicit PubAckPacket(ParsingInformation* parsingInformation, OnPubAckInternalCallback callback);
+ ~PubAckPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnPubAckInternalCallback _callback;
+
+ uint8_t _bytePosition;
+ char _packetIdMsb;
+ uint16_t _packetId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.cpp
new file mode 100644
index 0000000..2b3e00d
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.cpp
@@ -0,0 +1,30 @@
+#include "PubCompPacket.hpp"
+
+using AsyncMqttClientInternals::PubCompPacket;
+
+PubCompPacket::PubCompPacket(ParsingInformation* parsingInformation, OnPubCompInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback)
+, _bytePosition(0)
+, _packetIdMsb(0)
+, _packetId(0) {
+}
+
+PubCompPacket::~PubCompPacket() {
+}
+
+void PubCompPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition++ == 0) {
+ _packetIdMsb = currentByte;
+ } else {
+ _packetId = currentByte | _packetIdMsb << 8;
+ _parsingInformation->bufferState = BufferState::NONE;
+ _callback(_packetId);
+ }
+}
+
+void PubCompPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.hpp
new file mode 100644
index 0000000..17c1db4
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class PubCompPacket : public Packet {
+ public:
+ explicit PubCompPacket(ParsingInformation* parsingInformation, OnPubCompInternalCallback callback);
+ ~PubCompPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnPubCompInternalCallback _callback;
+
+ uint8_t _bytePosition;
+ char _packetIdMsb;
+ uint16_t _packetId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.cpp
new file mode 100644
index 0000000..ec535c6
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.cpp
@@ -0,0 +1,30 @@
+#include "PubRecPacket.hpp"
+
+using AsyncMqttClientInternals::PubRecPacket;
+
+PubRecPacket::PubRecPacket(ParsingInformation* parsingInformation, OnPubRecInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback)
+, _bytePosition(0)
+, _packetIdMsb(0)
+, _packetId(0) {
+}
+
+PubRecPacket::~PubRecPacket() {
+}
+
+void PubRecPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition++ == 0) {
+ _packetIdMsb = currentByte;
+ } else {
+ _packetId = currentByte | _packetIdMsb << 8;
+ _parsingInformation->bufferState = BufferState::NONE;
+ _callback(_packetId);
+ }
+}
+
+void PubRecPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.hpp
new file mode 100644
index 0000000..910130a
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class PubRecPacket : public Packet {
+ public:
+ explicit PubRecPacket(ParsingInformation* parsingInformation, OnPubRecInternalCallback callback);
+ ~PubRecPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnPubRecInternalCallback _callback;
+
+ uint8_t _bytePosition;
+ char _packetIdMsb;
+ uint16_t _packetId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.cpp
new file mode 100644
index 0000000..2d5abde
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.cpp
@@ -0,0 +1,30 @@
+#include "PubRelPacket.hpp"
+
+using AsyncMqttClientInternals::PubRelPacket;
+
+PubRelPacket::PubRelPacket(ParsingInformation* parsingInformation, OnPubRelInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback)
+, _bytePosition(0)
+, _packetIdMsb(0)
+, _packetId(0) {
+}
+
+PubRelPacket::~PubRelPacket() {
+}
+
+void PubRelPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition++ == 0) {
+ _packetIdMsb = currentByte;
+ } else {
+ _packetId = currentByte | _packetIdMsb << 8;
+ _parsingInformation->bufferState = BufferState::NONE;
+ _callback(_packetId);
+ }
+}
+
+void PubRelPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.hpp
new file mode 100644
index 0000000..edea3d5
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class PubRelPacket : public Packet {
+ public:
+ explicit PubRelPacket(ParsingInformation* parsingInformation, OnPubRelInternalCallback callback);
+ ~PubRelPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnPubRelInternalCallback _callback;
+
+ uint8_t _bytePosition;
+ char _packetIdMsb;
+ uint16_t _packetId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.cpp
new file mode 100644
index 0000000..dab30a1
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.cpp
@@ -0,0 +1,91 @@
+#include "PublishPacket.hpp"
+
+using AsyncMqttClientInternals::PublishPacket;
+
+PublishPacket::PublishPacket(ParsingInformation* parsingInformation, OnMessageInternalCallback dataCallback, OnPublishInternalCallback completeCallback)
+: _parsingInformation(parsingInformation)
+, _dataCallback(dataCallback)
+, _completeCallback(completeCallback)
+, _dup(false)
+, _qos(0)
+, _retain(0)
+, _bytePosition(0)
+, _topicLengthMsb(0)
+, _topicLength(0)
+, _ignore(false)
+, _packetIdMsb(0)
+, _packetId(0)
+, _payloadLength(0)
+, _payloadBytesRead(0) {
+ _dup = _parsingInformation->packetFlags & HeaderFlag.PUBLISH_DUP;
+ _retain = _parsingInformation->packetFlags & HeaderFlag.PUBLISH_RETAIN;
+ char qosMasked = _parsingInformation->packetFlags & 0x06;
+ switch (qosMasked) {
+ case HeaderFlag.PUBLISH_QOS0:
+ _qos = 0;
+ break;
+ case HeaderFlag.PUBLISH_QOS1:
+ _qos = 1;
+ break;
+ case HeaderFlag.PUBLISH_QOS2:
+ _qos = 2;
+ break;
+ }
+}
+
+PublishPacket::~PublishPacket() {
+}
+
+void PublishPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition == 0) {
+ _topicLengthMsb = currentByte;
+ } else if (_bytePosition == 1) {
+ _topicLength = currentByte | _topicLengthMsb << 8;
+ if (_topicLength > _parsingInformation->maxTopicLength) {
+ _ignore = true;
+ } else {
+ _parsingInformation->topicBuffer[_topicLength] = '\0';
+ }
+ } else if (_bytePosition >= 2 && _bytePosition < 2 + _topicLength) {
+ // Starting from here, _ignore might be true
+ if (!_ignore) _parsingInformation->topicBuffer[_bytePosition - 2] = currentByte;
+ if (_bytePosition == 2 + _topicLength - 1 && _qos == 0) {
+ _preparePayloadHandling(_parsingInformation->remainingLength - (_bytePosition + 1));
+ return;
+ }
+ } else if (_bytePosition == 2 + _topicLength) {
+ _packetIdMsb = currentByte;
+ } else {
+ _packetId = currentByte | _packetIdMsb << 8;
+ _preparePayloadHandling(_parsingInformation->remainingLength - (_bytePosition + 1));
+ }
+ _bytePosition++;
+}
+
+void PublishPacket::_preparePayloadHandling(uint32_t payloadLength) {
+ _payloadLength = payloadLength;
+ if (payloadLength == 0) {
+ _parsingInformation->bufferState = BufferState::NONE;
+ if (!_ignore) {
+ _dataCallback(_parsingInformation->topicBuffer, nullptr, _qos, _dup, _retain, 0, 0, 0, _packetId);
+ _completeCallback(_packetId, _qos);
+ }
+ } else {
+ _parsingInformation->bufferState = BufferState::PAYLOAD;
+ }
+}
+
+void PublishPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ size_t remainToRead = len - (*currentBytePosition);
+ if (_payloadBytesRead + remainToRead > _payloadLength) remainToRead = _payloadLength - _payloadBytesRead;
+
+ if (!_ignore) _dataCallback(_parsingInformation->topicBuffer, data + (*currentBytePosition), _qos, _dup, _retain, remainToRead, _payloadBytesRead, _payloadLength, _packetId);
+ _payloadBytesRead += remainToRead;
+ (*currentBytePosition) += remainToRead;
+
+ if (_payloadBytesRead == _payloadLength) {
+ _parsingInformation->bufferState = BufferState::NONE;
+ if (!_ignore) _completeCallback(_packetId, _qos);
+ }
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.hpp
new file mode 100644
index 0000000..9dc19f0
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../Flags.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class PublishPacket : public Packet {
+ public:
+ explicit PublishPacket(ParsingInformation* parsingInformation, OnMessageInternalCallback dataCallback, OnPublishInternalCallback completeCallback);
+ ~PublishPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnMessageInternalCallback _dataCallback;
+ OnPublishInternalCallback _completeCallback;
+
+ void _preparePayloadHandling(uint32_t payloadLength);
+
+ bool _dup;
+ uint8_t _qos;
+ bool _retain;
+
+ uint8_t _bytePosition;
+ char _topicLengthMsb;
+ uint16_t _topicLength;
+ bool _ignore;
+ char _packetIdMsb;
+ uint16_t _packetId;
+ uint32_t _payloadLength;
+ uint32_t _payloadBytesRead;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.cpp
new file mode 100644
index 0000000..ab89965
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.cpp
@@ -0,0 +1,46 @@
+#include "SubAckPacket.hpp"
+
+using AsyncMqttClientInternals::SubAckPacket;
+
+SubAckPacket::SubAckPacket(ParsingInformation* parsingInformation, OnSubAckInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback)
+, _bytePosition(0)
+, _packetIdMsb(0)
+, _packetId(0) {
+}
+
+SubAckPacket::~SubAckPacket() {
+}
+
+void SubAckPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition++ == 0) {
+ _packetIdMsb = currentByte;
+ } else {
+ _packetId = currentByte | _packetIdMsb << 8;
+ _parsingInformation->bufferState = BufferState::PAYLOAD;
+ }
+}
+
+void SubAckPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ char status = data[(*currentBytePosition)++];
+
+ /* switch (status) {
+ case 0:
+ Serial.println("Success QoS 0");
+ break;
+ case 1:
+ Serial.println("Success QoS 1");
+ break;
+ case 2:
+ Serial.println("Success QoS 2");
+ break;
+ case 0x80:
+ Serial.println("Failure");
+ break;
+ } */
+
+ _parsingInformation->bufferState = BufferState::NONE;
+ _callback(_packetId, status);
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.hpp
new file mode 100644
index 0000000..011b800
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class SubAckPacket : public Packet {
+ public:
+ explicit SubAckPacket(ParsingInformation* parsingInformation, OnSubAckInternalCallback callback);
+ ~SubAckPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnSubAckInternalCallback _callback;
+
+ uint8_t _bytePosition;
+ char _packetIdMsb;
+ uint16_t _packetId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.cpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.cpp
new file mode 100644
index 0000000..a44943d
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.cpp
@@ -0,0 +1,30 @@
+#include "UnsubAckPacket.hpp"
+
+using AsyncMqttClientInternals::UnsubAckPacket;
+
+UnsubAckPacket::UnsubAckPacket(ParsingInformation* parsingInformation, OnUnsubAckInternalCallback callback)
+: _parsingInformation(parsingInformation)
+, _callback(callback)
+, _bytePosition(0)
+, _packetIdMsb(0)
+, _packetId(0) {
+}
+
+UnsubAckPacket::~UnsubAckPacket() {
+}
+
+void UnsubAckPacket::parseVariableHeader(char* data, size_t len, size_t* currentBytePosition) {
+ char currentByte = data[(*currentBytePosition)++];
+ if (_bytePosition++ == 0) {
+ _packetIdMsb = currentByte;
+ } else {
+ _packetId = currentByte | _packetIdMsb << 8;
+ _parsingInformation->bufferState = BufferState::NONE;
+ _callback(_packetId);
+ }
+}
+
+void UnsubAckPacket::parsePayload(char* data, size_t len, size_t* currentBytePosition) {
+ (void)data;
+ (void)currentBytePosition;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.hpp
new file mode 100644
index 0000000..ab5b9c5
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Arduino.h"
+#include "Packet.hpp"
+#include "../ParsingInformation.hpp"
+#include "../Callbacks.hpp"
+
+namespace AsyncMqttClientInternals {
+class UnsubAckPacket : public Packet {
+ public:
+ explicit UnsubAckPacket(ParsingInformation* parsingInformation, OnUnsubAckInternalCallback callback);
+ ~UnsubAckPacket();
+
+ void parseVariableHeader(char* data, size_t len, size_t* currentBytePosition);
+ void parsePayload(char* data, size_t len, size_t* currentBytePosition);
+
+ private:
+ ParsingInformation* _parsingInformation;
+ OnUnsubAckInternalCallback _callback;
+
+ uint8_t _bytePosition;
+ char _packetIdMsb;
+ uint16_t _packetId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/ParsingInformation.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/ParsingInformation.hpp
new file mode 100644
index 0000000..2d46f27
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/ParsingInformation.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+namespace AsyncMqttClientInternals {
+enum class BufferState : uint8_t {
+ NONE = 0,
+ REMAINING_LENGTH = 2,
+ VARIABLE_HEADER = 3,
+ PAYLOAD = 4
+};
+
+struct ParsingInformation {
+ BufferState bufferState;
+
+ uint16_t maxTopicLength;
+ char* topicBuffer;
+
+ uint8_t packetType;
+ uint16_t packetFlags;
+ uint32_t remainingLength;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Storage.hpp b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Storage.hpp
new file mode 100644
index 0000000..725307b
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Storage.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+namespace AsyncMqttClientInternals {
+struct PendingPubRel {
+ uint16_t packetId;
+};
+
+struct PendingAck {
+ uint8_t packetType;
+ uint8_t headerFlag;
+ uint16_t packetId;
+};
+} // namespace AsyncMqttClientInternals
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/.piopm b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/.piopm
new file mode 100644
index 0000000..8ae502b
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/.piopm
@@ -0,0 +1 @@
+{"type": "library", "name": "EspMQTT", "version": "1.0.25", "spec": {"owner": "politsin", "id": 181, "name": "EspMQTT", "requirements": null, "uri": null}}
\ No newline at end of file
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/README.md b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/README.md
new file mode 100644
index 0000000..2a2bc91
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/README.md
@@ -0,0 +1,68 @@
+# ESP32 > MQTT
+ESP32 foundation library for MQTT based HomeIOT
+
+```cpp
+#include
+using std::string;
+
+#include
+QueueHandle_t mqttQueue;
+typedef struct {
+ string name;
+ string metric;
+} mqttMessage;
+
+// EspMqtt.
+#include "EspMQTT.h"
+EspMQTT mqtt;
+void mqtt_callback(std::string param, std::string value);
+
+void mqttSetup() {
+ uint16_t debugLevel = 0;
+ if (debugLevel) {
+ mqtt.debugLevel = debugLevel;
+ mqtt.setAvailabilityInterval(5);
+ }
+ // MqTT:
+ mqtt.setWiFi("wifi-name", "wifi-pass", "hostname");
+ mqtt.setMqtt("mqtt-server", "mqtt-user", "mqtt-pass");
+ mqtt.setCommonTopics("my/root/topic/dir", "ds18b20");
+ mqtt.setCallback(mqtt_callback);
+ mqtt.start(true);
+}
+
+
+// Main.cpp Setup.
+void setup() {
+ mqttSetup();
+ mqttQueue = xQueueCreate(10, sizeof(mqttMessage));
+}
+
+// Main.cpp Loop.
+float counter = 1.1;
+void loop() {
+ if (xQueueReceive(mqttQueue, &message, 100 / portTICK_PERIOD_MS) == pdFALSE) {
+ mqtt.publishMetric(message.name, message.metric);
+ // printf("mqtt [%s] push = %s\n", msg.name.c_str(), msg.metric.c_str());
+ }
+ else {
+ counter += 0.1;
+ char data[10];
+ sprintf(data, "%.2f", counter);
+ string metric = std::string(data);
+ mqttMessage msg = {"temperature", metric};
+ xQueueSend(mqttQueue, &msg, portMAX_DELAY);
+ }
+ vTaskDelay(5000 / portTICK_PERIOD_MS);
+}
+
+
+void mqtt_callback(std::string param, std::string value) {
+ uint16_t val = atoi(value.c_str());
+ printf("%s=%s\n", param.c_str(), message.c_str());
+}
+```
+
+## Ref:
+ * https://github.com/marvinroger/async-mqtt-client/blob/master/src/AsyncMqttClient.hpp
+ * https://github.com/Dullage/ESP-LED-MQTT
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/Basic/Basic.ino b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/Basic/Basic.ino
new file mode 100644
index 0000000..442ccf9
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/Basic/Basic.ino
@@ -0,0 +1,35 @@
+#include
+#include "EspMQTT.h"
+
+EspMQTT mqtt;
+void mqtt_callback(std::string param, std::string value);
+
+void setup() {
+ pinMode(LED_BUILTIN, OUTPUT);
+ digitalWrite(LED_BUILTIN, LOW);
+ Serial.begin(115200);
+ Serial.println("\nSetup");
+ // MqTT:
+ mqtt.setWiFi("MY_ssid", "MY_pass", "MY_hostname");
+ mqtt.setMqtt("MY_host", "MY_user", "MY_pass");
+ mqtt.setCommonTopics("home/light", "roomled"); // (topicRoot, device)
+ mqtt.setCallback(mqtt_callback);
+ // mqtt.ota = true; // Default: false;
+ // mqtt.test = true; // Default: false;
+ // mqtt.debug = true; // Default: false;
+ // mqtt.setAvailabilityInterval(sec) // Default: 30sec;
+ mqtt.start();
+}
+
+void loop() {
+ mqtt.loop(); // otaHandle;
+ if (WiFi.isConnected() && mqtt.online) {
+ // Do someshing.
+ }
+ yield();
+}
+
+void mqtt_callback(std::string param, std::string value) {
+ uint16_t val = atoi(value.c_str());
+ Serial.printf("%s=%s\n", param.c_str(), message.c_str());
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/ds18b20/ds18b20.cpp b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/ds18b20/ds18b20.cpp
new file mode 100644
index 0000000..8a26cca
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/ds18b20/ds18b20.cpp
@@ -0,0 +1,73 @@
+#include
+using std::string;
+
+// Queue.
+#include
+QueueHandle_t mqttQueue;
+typedef struct {
+ string name;
+ string metric;
+} mqttMessage;
+
+// Ds18b20.
+#include
+#include
+
+#define ONE_WIRE_BUS1 GPIO_NUM_18
+OneWire oneWire1(ONE_WIRE_BUS1);
+DallasTemperature ds18(&oneWire1);
+
+TaskHandle_t ds18b20;
+void ds18b20Task(void *pvParam) {
+ ds18.begin();
+ while (true) {
+ float temperature = ds18.getTempCByIndex(0);
+ if (temperature != DEVICE_DISCONNECTED_C) {
+ char data[10];
+ sprintf(data, "%.2f", temperature);
+ string metric = std::string(data);
+ mqttMessage msg = {"temperature", metric};
+ xQueueSend(mqttQueue, &msg, portMAX_DELAY);
+ // printf("Tin = %.2f C\n", temperature);
+ } // else: printf("Error: Could not read temperature data\n");
+ vTaskDelay(10356 / portTICK_PERIOD_MS);
+ }
+}
+
+// EspMqtt.
+#include "EspMQTT.h"
+EspMQTT mqtt;
+void mqtt_callback(std::string param, std::string value);
+
+void mqttSetup() {
+ uint16_t debugLevel = 0;
+ if (debugLevel) {
+ mqtt.debugLevel = debugLevel;
+ mqtt.setAvailabilityInterval(5);
+ }
+ // MqTT:
+ mqtt.setWiFi("wifi-name", "wifi-pass", "hostname");
+ mqtt.setMqtt("mqtt-server", "mqtt-user", "mqtt-pass");
+ mqtt.setCommonTopics("my/root/topic/dir", "ds18b20");
+ // mqtt.setCallback(mqtt_callback);
+ mqtt.start(true);
+}
+
+
+// Main.cpp Setup.
+void setup() {
+ mqttSetup();
+ mqttQueue = xQueueCreate(10, sizeof(mqttMessage));
+ xTaskCreate(ds18b20Task, "ds18b20", 1024, NULL, 1, &ds18b20);
+}
+
+// Main.cpp Loop.
+mqttMessage message;
+QueueHandle_t mqttQueue;
+void loop() {
+ if (xQueueReceive(mqttQueue, &message, 100 / portTICK_PERIOD_MS) == pdTRUE) {
+ mqtt.publishMetric(message.name, message.metric);
+ // printf("mqtt [%s] push = %s\n", msg.name.c_str(), msg.metric.c_str());
+ }
+ // vTaskDelay(10 / portTICK_PERIOD_MS);
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/library.json b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/library.json
new file mode 100644
index 0000000..d22fa67
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/library.json
@@ -0,0 +1,26 @@
+{
+ "name": "EspMQTT",
+ "keywords": "esp, mqtt, arduino, esp32, wifi, iot",
+ "description": "ESP8266 foundation library for MQTT based HomeIOT",
+ "authors": {
+ "name": "Anatoly Politsin",
+ "url": "https://politsin.ru"
+ },
+ "version": "1.0.25",
+ "frameworks": "arduino",
+ "platforms": ["espressif32"],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/politsin/EspMQTT.git"
+ },
+ "dependencies": [
+ {
+ "name": "AsyncMqttClient",
+ "version": ">=0.8.0"
+ },
+ {
+ "name": "ArduinoJson",
+ "version": ">=6.13.0"
+ }
+ ]
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.cpp b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.cpp
new file mode 100644
index 0000000..c9147ad
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.cpp
@@ -0,0 +1,336 @@
+#include "EspMQTT.h"
+#include "EspMQTT_App.h"
+#include
+#include
+
+using std::string;
+// MQTT.
+AsyncMqttClient mqttClient;
+// Ticker.
+TimerHandle_t mqttReconnectTimer;
+TimerHandle_t wifiReconnectTimer;
+TimerHandle_t mqttAvailabilityTimer;
+// App.
+EspApp eapp;
+
+void EspMQTT::setWiFi(string ssid, string pass, string host) {
+ strcpy(this->WiFiSsid, ssid.c_str());
+ strcpy(this->WiFiPass, pass.c_str());
+ strcpy(this->WiFiHost, host.c_str());
+};
+
+void EspMQTT::setMqtt(string server, string user, string pass) {
+ char device[23];
+ uint64_t chipid = ESP.getEfuseMac();
+ uint16_t chip = (uint16_t)(chipid >> 32);
+ snprintf(device, 23, "ESP32-%04X%08X", chip, (uint32_t)chipid);
+ strcpy(this->mqttDevice, device);
+ strcpy(this->mqttHost, server.c_str());
+ strcpy(this->mqttUser, user.c_str());
+ strcpy(this->mqttPass, pass.c_str());
+};
+
+void EspMQTT::setCommonTopics(string root, string name) {
+ // Root: /home/[sensor/switch/light]/{name}
+ string r = root + "/" + name;
+ strcpy(this->mqttRootTopic, r.c_str());
+ // Metrics.
+ string mRoot = r + string("/metric/");
+ strcpy(this->metricRoot, mRoot.c_str());
+ // Info.
+ string availability = r + string("/availability");
+ string ip = availability + string("/$ip");
+ strcpy(this->availabilityTopic, availability.c_str());
+ strcpy(this->ipTopic, ip.c_str());
+ // Commands & Data.
+ string cmd = r + string("/cmd/*");
+ string data = r + string("/data");
+ string state = r + string("/state");
+ string recovery = r + string("/recovery");
+ this->cmdTopicLength = cmd.length() - 1;
+ strcpy(this->cmdTopic, cmd.c_str());
+ strcpy(this->dataTopic, data.c_str());
+ strcpy(this->stateTopic, state.c_str());
+ strcpy(this->recoveryTopic, recovery.c_str());
+};
+
+void EspMQTT::start(bool init) {
+ this->initMqtt = init;
+ if (this->initMqtt) {
+ this->online = false;
+ gpio_pad_select_gpio(LED);
+ gpio_set_direction(LED, GPIO_MODE_OUTPUT);
+ gpio_set_level(LED, LOW);
+ if (this->debugLevel >= 2) {
+ printf("MQTT Start\n");
+ }
+ setupTimers();
+ mqttClient.onConnect(onMqttConnect);
+ mqttClient.onDisconnect(onMqttDisconnect);
+ mqttClient.onSubscribe(onMqttSubscribe);
+ mqttClient.onUnsubscribe(onMqttUnsubscribe);
+ mqttClient.onMessage(onMqttMessage);
+ mqttClient.onPublish(onMqttPublish);
+ mqttClient.setClientId(this->mqttDevice);
+ mqttClient.setServer(this->mqttHost, this->mqttPort);
+ mqttClient.setCredentials(this->mqttUser, this->mqttPass);
+ mqttClient.setWill(availabilityTopic, 0, true, "offline");
+ // WiFi.
+ WiFi.mode(WIFI_MODE_STA);
+ WiFi.onEvent(WiFiEvent);
+ connectToWifi();
+ }
+}
+
+void EspMQTT::setupTimers() {
+ mqttReconnectTimer =
+ xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0,
+ reinterpret_cast(connectToMqtt));
+ wifiReconnectTimer =
+ xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0,
+ reinterpret_cast(connectToWifi));
+
+ mqttAvailabilityTimer = xTimerCreate(
+ "availabilityTimer", pdMS_TO_TICKS(this->availabilityInterval), pdTRUE,
+ (void *)0, reinterpret_cast(availabilityTime));
+}
+
+void EspMQTT::messageLoop() {
+ if (length >= 1024) {
+ this->publishState("$error", "Message is too big");
+ return;
+ }
+ string param = string(topic).substr(this->cmdTopicLength);
+ string message = string(payload, length);
+ if ((char)payload[0] != '{') {
+ // JSON. Do Nothing.
+ }
+ if ((char)param.at(0) == '$') {
+ eapp.app(param, message);
+ return;
+ }
+ this->callbackFunction(param, message);
+ if (this->debugLevel) {
+ printf("MQTT [%s] %s=%s\n", topic, param.c_str(), message.c_str());
+ }
+}
+
+void EspMQTT::connectToWifi() {
+ if (mqtt.debugLevel >= 2) {
+ printf("Connecting to Wi-Fi...\n");
+ }
+ WiFi.begin(mqtt.WiFiSsid, mqtt.WiFiPass);
+}
+
+void EspMQTT::WiFiEvent(WiFiEvent_t event) {
+ if (event == SYSTEM_EVENT_STA_GOT_IP) {
+ mqtt.onWifiConnect(event);
+ }
+ if (event == SYSTEM_EVENT_STA_DISCONNECTED) {
+ mqtt.onWifiDisconnect(event);
+ }
+}
+
+void EspMQTT::onWifiConnect(WiFiEvent_t event) {
+ string ip = WiFi.localIP().toString().c_str();
+ strcpy(mqtt.ip, ip.c_str());
+ if (mqtt.debugLevel >= 2) {
+ printf("Connected to Wi-Fi. IP: %s\n", mqtt.ip);
+ }
+ connectToMqtt();
+}
+
+void EspMQTT::onWifiDisconnect(WiFiEvent_t event) {
+ mqtt.setOffline();
+ xTimerStop(mqttAvailabilityTimer, 0);
+ xTimerStop(mqttReconnectTimer, 0);
+ xTimerStart(wifiReconnectTimer, 0);
+ if (mqtt.debugLevel >= 1) {
+ printf("Disconnected from Wi-Fi.\n");
+ }
+}
+
+void EspMQTT::connectToMqtt() {
+ if (mqtt.debugLevel >= 2) {
+ printf("Connecting to MQTT...\n");
+ }
+ mqttClient.connect();
+}
+
+void EspMQTT::onMqttConnect(bool sessionPresent) {
+ mqtt.setOnline();
+ gpio_set_level(LED, HIGH);
+ xTimerStart(mqttAvailabilityTimer, 0);
+ if (mqtt.debugLevel >= 2) {
+ printf("Session present: %d\n", sessionPresent);
+ }
+}
+
+void EspMQTT::setOnline() {
+ this->online = true;
+ this->publishAvailability();
+ this->mqttSubscribe();
+ WiFi.setHostname(this->WiFiHost);
+ if (this->debugLevel >= 1) {
+ printf("Connected to MQTT.\n");
+ printf("Set HostName %s.\n", this->WiFiHost);
+ this->mqttTests();
+ }
+}
+
+void EspMQTT::setOffline() {
+ this->online = false;
+ gpio_set_level(LED, LOW);
+}
+
+void EspMQTT::mqttTests() {
+ if (this->test) {
+ string test = string(cmdTopic).substr(0, cmdTopicLength) + string("test");
+ const char *topic = test.c_str();
+ printf("--== Statr Tests == --\n");
+ printf("%s\n", topic);
+ uint16_t packetIdSub = mqttClient.subscribe(topic, 2);
+ printf("T0: Subscribing at QoS 2, packetId: %d\n", packetIdSub);
+ mqttClient.publish(topic, 0, true, "test 1");
+ printf("T1: Publishing at QoS 0\n");
+ uint16_t packetIdPub1 = mqttClient.publish(topic, 1, true, "test 2");
+ printf("Т2: Publishing at QoS 1, packetId: %d\n", packetIdPub1);
+ uint16_t packetIdPub2 = mqttClient.publish(topic, 2, true, "test 3");
+ printf("Т3: Publishing at QoS 2, packetId: %d\n", packetIdPub2);
+ printf("--== End Tests Inits == --\n");
+ }
+}
+
+void EspMQTT::setAvailabilityInterval(uint16_t sec, bool onSetup) {
+ this->availabilityInterval = (uint32_t)sec * 1000;
+ if (onSetup) {
+ xTimerStop(mqttAvailabilityTimer, 0);
+ xTimerChangePeriod(mqttAvailabilityTimer,
+ pdMS_TO_TICKS(this->availabilityInterval), 0);
+ }
+ if (this->online) {
+ xTimerStart(mqttAvailabilityTimer, 0);
+ }
+ if (this->debugLevel >= 2) {
+ printf("Availability Interval=%d ms\n", availabilityInterval);
+ }
+}
+
+void EspMQTT::onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
+ mqtt.setOffline();
+ if (WiFi.isConnected()) {
+ xTimerStop(mqttAvailabilityTimer, 0);
+ xTimerStart(mqttReconnectTimer, 0);
+ }
+ if (mqtt.debugLevel >= 1) {
+ printf("Disconnected from MQTT.\n");
+ }
+}
+
+void EspMQTT::onMqttSubscribe(uint16_t packetId, uint8_t qos) {
+ if (mqtt.debugLevel >= 2) {
+ printf("Subscribe: packetId=%d | QOS=%d\n", packetId, qos);
+ }
+}
+
+void EspMQTT::onMqttUnsubscribe(uint16_t packetId) {
+ if (mqtt.debugLevel >= 2) {
+ printf("Unsubscribe: packetId=%d\n", packetId);
+ }
+}
+
+void EspMQTT::onMqttMessage(char *topic, char *payload,
+ AsyncMqttClientMessageProperties prop, size_t len,
+ size_t index, size_t total) {
+ uint8_t pos = mqtt.cmdTopicLength;
+ if ((char)topic[pos] == '$') {
+ eapp.appInterrupt(topic, payload, len);
+ return;
+ }
+ mqtt.messageFlag = true;
+ mqtt.length = len;
+ mqtt.topic = topic;
+ mqtt.payload = payload;
+ if (mqtt.test) {
+ printf("Publish received.\n");
+ printf(" topic: %s\n", topic);
+ printf(" QoS=%d \t| dup=%d \t| retain=%d\n", prop.qos, prop.dup,
+ prop.retain);
+ printf(" len=%d \t| index=%d \t| total=%d\n", len, index, total);
+ }
+}
+
+void EspMQTT::onMqttPublish(uint16_t packetId) {
+ if (false) {
+ printf("Publish acknowledged.\n packetId:%i", packetId);
+ }
+}
+
+void EspMQTT::mqttSubscribe() { mqttClient.subscribe(this->cmdTopic, 2); }
+
+void EspMQTT::setCallback(
+ std::function cBack) {
+ this->callbackFunction = cBack;
+};
+
+void EspMQTT::setDebugLevel(uint8_t debugLevel) {
+ this->debugLevel = debugLevel;
+ if (this->debugLevel) {
+ printf("debugLevel > ON %d\n", debugLevel);
+ }
+}
+
+void EspMQTT::availabilityTime() { mqtt.publishAvailability(); }
+
+void EspMQTT::publishAvailability() {
+ mqttClient.publish(ipTopic, 0, true, this->ip);
+ mqttClient.publish(availabilityTopic, 0, true, "online");
+ if (this->debugLevel >= 1) {
+ printf("MQTT [Publish Availability] at %s\n", ip);
+ }
+}
+
+void EspMQTT::publishData(string data) {
+ mqttClient.publish(dataTopic, 0, true, data.c_str());
+}
+
+void EspMQTT::publishState(string key, string value) {
+ string topic = string(this->stateTopic) + "/" + key;
+ mqttClient.publish(topic.c_str(), 1, true, value.c_str());
+}
+
+void EspMQTT::publishMetric(string key, string metric) {
+ string topic = string(this->metricRoot) + key;
+ mqttClient.publish(topic.c_str(), 0, true, metric.c_str());
+}
+
+void EspMQTT::publishMetric(char *key, uint16_t metric) {
+ char message[16];
+ itoa(metric, message, 10);
+ char topic[255];
+ strcpy(topic, this->metricRoot);
+ strcat(topic, key);
+ mqttClient.publish(topic, 0, true, message);
+}
+
+void EspMQTT::publishMetric(string key, uint16_t metric) {
+ char message[16];
+ itoa(metric, message, 10);
+ string topic = string(this->metricRoot) + key;
+ mqttClient.publish(topic.c_str(), 0, true, message);
+}
+
+void EspMQTT::publishMetric(string key, float metric) {
+ if (metric > 0) {
+ this->publishMetric(key, metric, false);
+ }
+}
+
+void EspMQTT::publishMetric(string key, float metric, bool force) {
+ if (metric > 0 || force) {
+ char message[16];
+ itoa(metric, message, 10);
+ string topic = string(this->metricRoot) + key;
+ mqttClient.publish(topic.c_str(), 0, true, message);
+ }
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.h b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.h
new file mode 100644
index 0000000..0c33a13
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.h
@@ -0,0 +1,113 @@
+#ifndef Mqtt_h
+#define Mqtt_h
+#include "freertos/FreeRTOS.h"
+#include "freertos/timers.h"
+#include
+#include
+#include
+#include
+#include
+using std::string;
+
+// TODO:
+#define LED GPIO_NUM_22
+
+class EspMQTT {
+public:
+ bool test = false;
+ bool online = false;
+ int8_t debugLevel = 0;
+ // Flag (TODO).
+ bool messageFlag = false;
+ // Set.
+ char WiFiSsid[255];
+ char WiFiPass[255];
+ char WiFiHost[255];
+ // Config.
+ char mqttHost[255];
+ char mqttUser[255];
+ char mqttPass[255];
+ char mqttDevice[255];
+ const uint16_t mqttPort = 1883;
+
+ char ip[255];
+ // Topics.
+ char mqttRootTopic[255];
+ char metricRoot[255];
+ // Info.
+ char availabilityTopic[255];
+ char ipTopic[255];
+ char testTopic[255];
+ // Cmd & Data
+ char cmdTopic[255];
+ uint16_t cmdTopicLength = 0;
+ char stateTopic[255];
+ char recoveryTopic[255];
+ char dataTopic[255];
+ // Message.
+ size_t length;
+ char *topic;
+ char *payload;
+ void messageLoop();
+
+ void start(bool init = true);
+ void setupTimers();
+ void setDebugLevel(uint8_t debugLevel);
+ void setOta(bool ota);
+ // WiFi setters.
+ void setWiFi(string ssid, string pass, string host);
+ void setMqtt(string server, string user, string pass);
+ void setCommonTopics(string root, string name);
+ // Mqtt setters.
+ void setstringValue(char *name, char *value);
+ void addSubsribeTopic(string topic);
+ // Loop.
+ void setAvailabilityInterval(uint16_t se, bool onSetup = false);
+
+ // Send.
+ void publishData(string data);
+ void publishState(string key, string value);
+ void publishMetric(char *key, uint16_t metric);
+ void publishMetric(string key, uint16_t metric);
+ void publishMetric(string key, string metric);
+ void publishMetric(string key, float metric);
+ void publishMetric(string key, float metric, bool force);
+ // Callbacks.
+ // void callback(char *topic, char *payload, uint16_t length);
+ void setCallback(std::function cBack);
+ // Timers.
+
+ // Online.
+ void mqttTests();
+ void setOnline();
+ void setOffline();
+ void mqttSubscribe();
+ void publishAvailability();
+
+ // Async.
+ static void connectToWifi();
+ static void onWifiConnect(WiFiEvent_t even);
+ static void onWifiDisconnect(WiFiEvent_t even);
+ static void WiFiEvent(WiFiEvent_t event);
+ static void connectToMqtt();
+ static void availabilityTime();
+ static void onMqttConnect(bool sessionPresent);
+ static void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
+ static void onMqttSubscribe(uint16_t packetId, uint8_t qos);
+ static void onMqttUnsubscribe(uint16_t packetId);
+ static void onMqttMessage(char *topic, char *payload,
+ AsyncMqttClientMessageProperties prop, size_t len,
+ size_t index, size_t total);
+ static void onMqttPublish(uint16_t packetId);
+
+private:
+ bool initMqtt = true;
+ uint32_t availabilityInterval = 30000;
+ void setup();
+ void subsribe();
+ void callbackParceJson(string message);
+ std::function callbackFunction;
+};
+extern EspMQTT mqtt;
+
+#endif /* !Mqtt_h */
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.cpp b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.cpp
new file mode 100644
index 0000000..49a495c
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.cpp
@@ -0,0 +1,58 @@
+#include
+#include "EspMQTT_App.h"
+using std::string;
+
+bool EspApp::app(string param, string message) {
+ if (param == "$echo") {
+ mqtt.publishState(this->messageState, message);
+ return true;
+ }
+ if (param == "$update") {
+ mqtt.publishState(this->errorState, this->notReady);
+ return true;
+ }
+ if (param == "$pinRead") {
+ mqtt.publishState(this->errorState, this->notReady);
+ return true;
+ }
+ if (param == "$pinReadAnalog") {
+ mqtt.publishState(this->errorState, this->notReady);
+ return true;
+ }
+ if (param == "$pinSet") {
+ mqtt.publishState(this->errorState, this->notReady);
+ return true;
+ }
+ if (param == "$pinSetPwm") {
+ mqtt.publishState(this->errorState, this->notReady);
+ return true;
+ }
+ if (this->debug) {
+ Serial.printf("MQTT-APP %s=%s\n", param.c_str(), message.c_str());
+ }
+ return false;
+}
+
+bool EspApp::appInterrupt(char* topic, char* payload, size_t length) {
+ if (length >= 1024) {
+ return false;
+ }
+ char param[255];
+ memcpy(param, &topic[mqtt.cmdTopicLength], strlen(topic));
+ if (this->compareStr(param, (char*) "$setInterval")) {
+ int number = std::atoi(payload);
+ if (number > 0) {
+ uint16_t sec = static_cast(number);
+ mqtt.setAvailabilityInterval(sec);
+ return true;
+ }
+ return false;
+ }
+ if (this->compareStr(param, (char*) "$debugInterrupt")) {
+ string message = string(payload, length);
+ Serial.printf("MQTT-Interrupt %s=%s\n", param, message.c_str());
+ mqtt.publishState(this->messageState, message);
+ return true;
+ }
+ return false;
+}
diff --git a/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.h b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.h
new file mode 100644
index 0000000..3c6d54d
--- /dev/null
+++ b/.pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.h
@@ -0,0 +1,29 @@
+#ifndef Mqtt_App_h
+#define Mqtt_App_h
+
+#include "EspMQTT.h"
+
+#include
+using std::string;
+
+class EspApp {
+ public:
+ bool debug = false;
+ bool app(string param, string message);
+ bool appInterrupt(char* topic, char* payload, size_t length);
+ private:
+ string messageState = string("$message");
+ string errorState = string("$error");
+ string notReady = "Not ready yet";
+ bool compareStr(char a[],char b[]){
+ for (int i = 0; a[i] != '\0'; i++) {
+ if (a[i] != b[i]) {
+ return 0;
+ }
+ }
+ return 1;
+ }
+};
+extern EspApp eapp;
+
+#endif /* !Mqtt_h */
diff --git a/platformio.ini b/platformio.ini
index 6ab4fa4..539e532 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -19,3 +19,4 @@ lib_deps =
knolleary/PubSubClient@^2.8
einararnason/ArduinoQueue@^1.2.5
256dpi/MQTT@^2.5.0
+ politsin/EspMQTT@^1.0.25