From c4b6029f3d793733f597486b8c3ee97b3a7eba72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A6=82=E6=84=8F=20=E5=BD=AD?= <2417589739@qq.com> Date: Tue, 16 Aug 2022 17:20:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ESPMQTT=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AsyncMqttClient/.editorconfig | 12 + .../.github/workflows/build_examples_pio.yml | 27 + .../.github/workflows/cpplint.yml | 20 + .../AsyncMqttClient/.gitignore | 2 + .../AsyncMqttClient/.piopm | 1 + .../AsyncMqttClient/LICENSE | 21 + .../AsyncMqttClient/Makefile | 3 + .../AsyncMqttClient/README.md | 19 + .../async-mqtt-client.cppcheck | 6 + .../FullyFeatured-ESP32.ino | 135 ++++ .../FullyFeatured-ESP8266.ino | 122 +++ .../examples/FullyFeaturedSSL/platformio.ini | 24 + .../examples/FullyFeaturedSSL/src/main.cpp | 145 ++++ .../AsyncMqttClient/keywords.txt | 48 ++ .../AsyncMqttClient/library.json | 30 + .../AsyncMqttClient/library.properties | 9 + .../scripts/CI/build_examples_pio.sh | 49 ++ .../scripts/CI/platformio_esp32.ini | 16 + .../scripts/CI/platformio_esp8266.ini | 16 + .../get-fingerprint/get-fingerprint.py | 28 + .../AsyncMqttClient/src/AsyncMqttClient.cpp | 755 ++++++++++++++++++ .../AsyncMqttClient/src/AsyncMqttClient.h | 6 + .../AsyncMqttClient/src/AsyncMqttClient.hpp | 179 +++++ .../src/AsyncMqttClient/Callbacks.hpp | 30 + .../src/AsyncMqttClient/DisconnectReasons.hpp | 15 + .../src/AsyncMqttClient/Errors.hpp | 6 + .../src/AsyncMqttClient/Flags.hpp | 57 ++ .../src/AsyncMqttClient/Helpers.hpp | 61 ++ .../src/AsyncMqttClient/MessageProperties.hpp | 7 + .../AsyncMqttClient/Packets/ConnAckPacket.cpp | 30 + .../AsyncMqttClient/Packets/ConnAckPacket.hpp | 25 + .../AsyncMqttClient/Packets/Out/Connect.cpp | 162 ++++ .../AsyncMqttClient/Packets/Out/Connect.hpp | 29 + .../AsyncMqttClient/Packets/Out/Disconn.cpp | 18 + .../AsyncMqttClient/Packets/Out/Disconn.hpp | 17 + .../AsyncMqttClient/Packets/Out/OutPacket.cpp | 44 + .../AsyncMqttClient/Packets/Out/OutPacket.hpp | 35 + .../AsyncMqttClient/Packets/Out/PingReq.cpp | 18 + .../AsyncMqttClient/Packets/Out/PingReq.hpp | 17 + .../AsyncMqttClient/Packets/Out/PubAck.cpp | 25 + .../AsyncMqttClient/Packets/Out/PubAck.hpp | 18 + .../AsyncMqttClient/Packets/Out/Publish.cpp | 69 ++ .../AsyncMqttClient/Packets/Out/Publish.hpp | 23 + .../AsyncMqttClient/Packets/Out/Subscribe.cpp | 49 ++ .../AsyncMqttClient/Packets/Out/Subscribe.hpp | 21 + .../Packets/Out/Unsubscribe.cpp | 42 + .../Packets/Out/Unsubscribe.hpp | 21 + .../src/AsyncMqttClient/Packets/Packet.hpp | 11 + .../Packets/PingRespPacket.cpp | 21 + .../Packets/PingRespPacket.hpp | 21 + .../AsyncMqttClient/Packets/PubAckPacket.cpp | 30 + .../AsyncMqttClient/Packets/PubAckPacket.hpp | 25 + .../AsyncMqttClient/Packets/PubCompPacket.cpp | 30 + .../AsyncMqttClient/Packets/PubCompPacket.hpp | 25 + .../AsyncMqttClient/Packets/PubRecPacket.cpp | 30 + .../AsyncMqttClient/Packets/PubRecPacket.hpp | 25 + .../AsyncMqttClient/Packets/PubRelPacket.cpp | 30 + .../AsyncMqttClient/Packets/PubRelPacket.hpp | 25 + .../AsyncMqttClient/Packets/PublishPacket.cpp | 91 +++ .../AsyncMqttClient/Packets/PublishPacket.hpp | 38 + .../AsyncMqttClient/Packets/SubAckPacket.cpp | 46 ++ .../AsyncMqttClient/Packets/SubAckPacket.hpp | 25 + .../Packets/UnsubAckPacket.cpp | 30 + .../Packets/UnsubAckPacket.hpp | 25 + .../AsyncMqttClient/ParsingInformation.hpp | 21 + .../src/AsyncMqttClient/Storage.hpp | 13 + .../esp32doit-devkit-v1/EspMQTT/.piopm | 1 + .../esp32doit-devkit-v1/EspMQTT/README.md | 68 ++ .../EspMQTT/examples/Basic/Basic.ino | 35 + .../EspMQTT/examples/ds18b20/ds18b20.cpp | 73 ++ .../esp32doit-devkit-v1/EspMQTT/library.json | 26 + .../EspMQTT/src/EspMQTT.cpp | 336 ++++++++ .../esp32doit-devkit-v1/EspMQTT/src/EspMQTT.h | 113 +++ .../EspMQTT/src/EspMQTT_App.cpp | 58 ++ .../EspMQTT/src/EspMQTT_App.h | 29 + platformio.ini | 1 + 76 files changed, 3814 insertions(+) create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.editorconfig create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/build_examples_pio.yml create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.github/workflows/cpplint.yml create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.gitignore create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/.piopm create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/LICENSE create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/Makefile create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/README.md create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/async-mqtt-client.cppcheck create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP32/FullyFeatured-ESP32.ino create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeatured-ESP8266/FullyFeatured-ESP8266.ino create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/platformio.ini create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/examples/FullyFeaturedSSL/src/main.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/keywords.txt create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.json create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/library.properties create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/build_examples_pio.sh create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp32.ini create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/CI/platformio_esp8266.ini create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/scripts/get-fingerprint/get-fingerprint.py create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.h create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Callbacks.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/DisconnectReasons.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Errors.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Flags.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Helpers.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/MessageProperties.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/ConnAckPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Connect.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Disconn.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/OutPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PingReq.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/PubAck.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Publish.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Subscribe.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Out/Unsubscribe.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/Packet.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PingRespPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubAckPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubCompPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRecPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PubRelPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/PublishPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/SubAckPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Packets/UnsubAckPacket.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/ParsingInformation.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/AsyncMqttClient/src/AsyncMqttClient/Storage.hpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/.piopm create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/README.md create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/Basic/Basic.ino create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/examples/ds18b20/ds18b20.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/library.json create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT.h create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.cpp create mode 100644 .pio/libdeps/esp32doit-devkit-v1/EspMQTT/src/EspMQTT_App.h 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