experimental mqtt client supporting large packets

This commit is contained in:
proddy
2021-02-27 14:45:51 +01:00
parent 333c5c16c0
commit ce45374b54
28 changed files with 1358 additions and 1046 deletions

View File

@@ -5,6 +5,10 @@
#include "Arduino.h"
#ifndef MQTT_MIN_FREE_MEMORY
#define MQTT_MIN_FREE_MEMORY 4096
#endif
#ifdef ESP32
#include <AsyncTCP.h>
#include <freertos/semphr.h>
@@ -38,137 +42,137 @@
#include "AsyncMqttClient/Packets/PubRecPacket.hpp"
#include "AsyncMqttClient/Packets/PubCompPacket.hpp"
#if ESP32
#define SEMAPHORE_TAKE(X) \
if (xSemaphoreTake(_xSemaphore, 1000 / portTICK_PERIOD_MS) != pdTRUE) { \
return X; \
} // Waits max 1000ms
#define SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore);
#elif defined(ESP8266)
#define SEMAPHORE_TAKE(X) void()
#define SEMAPHORE_GIVE() void()
#endif
#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();
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);
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);
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, const char * _userTopic = "#");
AsyncMqttClient & onFilteredMessage(AsyncMqttClientInternals::OnMessageUserCallback callback, const char * _userTopic);
AsyncMqttClient & onPublish(AsyncMqttClientInternals::OnPublishUserCallback callback);
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 subscribe(const char * topic, uint8_t qos, AsyncMqttClientInternals::OnMessageUserCallback callback);
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 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);
const char * getClientId();
const char* getClientId() const;
private:
AsyncClient _client;
private:
AsyncClient _client;
AsyncMqttClientInternals::OutPacket* _head;
AsyncMqttClientInternals::OutPacket* _tail;
size_t _sent;
enum {
CONNECTING,
CONNECTED,
DISCONNECTING,
DISCONNECTED
} _state;
bool _tlsBadFingerprint;
uint32_t _lastClientActivity;
uint32_t _lastServerActivity;
uint32_t _lastPingRequestTime;
bool _connected;
bool _lockMutiConnections;
bool _connectPacketNotEnoughSpace;
bool _disconnectFlagged;
bool _tlsBadFingerprint;
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;
char _generatedClientId[18 + 1]; // esp8266-abc123 and esp32-abcdef123456
IPAddress _ip;
const char* _host;
bool _useIp;
#if ASYNC_TCP_SSL_ENABLED
bool _secure;
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;
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<std::array<uint8_t, SHA1_SIZE>> _secureServerFingerprints;
std::vector<std::array<uint8_t, SHA1_SIZE>> _secureServerFingerprints;
#endif
std::vector<AsyncMqttClientInternals::OnConnectUserCallback> _onConnectUserCallbacks;
std::vector<AsyncMqttClientInternals::OnDisconnectUserCallback> _onDisconnectUserCallbacks;
std::vector<AsyncMqttClientInternals::OnSubscribeUserCallback> _onSubscribeUserCallbacks;
std::vector<AsyncMqttClientInternals::OnUnsubscribeUserCallback> _onUnsubscribeUserCallbacks;
std::vector<AsyncMqttClientInternals::onFilteredMessageUserCallback> _onMessageUserCallbacks;
std::vector<AsyncMqttClientInternals::OnPublishUserCallback> _onPublishUserCallbacks;
std::vector<AsyncMqttClientInternals::OnConnectUserCallback> _onConnectUserCallbacks;
std::vector<AsyncMqttClientInternals::OnDisconnectUserCallback> _onDisconnectUserCallbacks;
std::vector<AsyncMqttClientInternals::OnSubscribeUserCallback> _onSubscribeUserCallbacks;
std::vector<AsyncMqttClientInternals::OnUnsubscribeUserCallback> _onUnsubscribeUserCallbacks;
std::vector<AsyncMqttClientInternals::OnMessageUserCallback> _onMessageUserCallbacks;
std::vector<AsyncMqttClientInternals::OnPublishUserCallback> _onPublishUserCallbacks;
AsyncMqttClientInternals::ParsingInformation _parsingInformation;
AsyncMqttClientInternals::Packet * _currentParsedPacket;
uint8_t _remainingLengthBufferPosition;
char _remainingLengthBuffer[4];
AsyncMqttClientInternals::ParsingInformation _parsingInformation;
AsyncMqttClientInternals::Packet* _currentParsedPacket;
uint8_t _remainingLengthBufferPosition;
char _remainingLengthBuffer[4];
uint16_t _nextPacketId;
std::vector<AsyncMqttClientInternals::PendingPubRel> _pendingPubRels;
std::vector<AsyncMqttClientInternals::PendingPubRel> _pendingPubRels;
std::vector<AsyncMqttClientInternals::PendingAck> _toSendAcks;
#ifdef ESP32
SemaphoreHandle_t _xSemaphore = nullptr;
#if defined(ESP32)
SemaphoreHandle_t _xSemaphore = nullptr;
#elif defined(ESP8266)
bool _xSemaphore = false;
#endif
void _clear();
void _freeCurrentParsedPacket();
void _clear();
void _freeCurrentParsedPacket();
// TCP
void _onConnect(AsyncClient * client);
void _onDisconnect(AsyncClient * client);
static void _onError(AsyncClient * client, int8_t error);
void _onTimeout(AsyncClient * client, uint32_t time);
static void _onAck(AsyncClient * client, size_t len, uint32_t time);
void _onData(AsyncClient * client, char * data, size_t len);
void _onPoll(AsyncClient * client);
// 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();
// 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);
// 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);
bool _sendPing();
void _sendAcks();
bool _sendDisconnect();
// 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);
uint16_t _getNextPacketId();
void _sendPing();
};