use espMqttClient, qos2 fixed

This commit is contained in:
MichaelDvP
2023-06-03 16:36:53 +02:00
parent d9c2fe0fb9
commit 7865ddc51f
43 changed files with 3749 additions and 230 deletions

View File

@@ -59,7 +59,7 @@ class ESP8266React {
return &_mqttSettingsService;
}
AsyncMqttClient * getMqttClient() {
espMqttClient * getMqttClient() {
return _mqttSettingsService.getMqttClient();
}

View File

@@ -1,163 +0,0 @@
#ifndef MqttPubSub_h
#define MqttPubSub_h
#include <StatefulService.h>
#include <AsyncMqttClient.h>
using namespace std::placeholders; // for `_1` etc
#define MQTT_ORIGIN_ID "mqtt"
template <class T>
class MqttConnector {
protected:
StatefulService<T> * _statefulService;
AsyncMqttClient * _mqttClient;
size_t _bufferSize;
MqttConnector(StatefulService<T> * statefulService, AsyncMqttClient * mqttClient, size_t bufferSize)
: _statefulService(statefulService)
, _mqttClient(mqttClient)
, _bufferSize(bufferSize) {
_mqttClient->onConnect(std::bind(&MqttConnector::onConnect, this));
}
virtual void onConnect() = 0;
public:
inline AsyncMqttClient * getMqttClient() const {
return _mqttClient;
}
};
template <class T>
class MqttPub : virtual public MqttConnector<T> {
public:
MqttPub(JsonStateReader<T> stateReader,
StatefulService<T> * statefulService,
AsyncMqttClient * mqttClient,
const String & pubTopic = "",
size_t bufferSize = DEFAULT_BUFFER_SIZE)
: MqttConnector<T>(statefulService, mqttClient, bufferSize)
, _stateReader(stateReader)
, _pubTopic(pubTopic) {
MqttConnector<T>::_statefulService->addUpdateHandler([&](const String & originId) { publish(); }, false);
}
void setPubTopic(const String & pubTopic) {
_pubTopic = pubTopic;
publish();
}
protected:
virtual void onConnect() {
publish();
}
private:
JsonStateReader<T> _stateReader;
String _pubTopic;
void publish() {
if (_pubTopic.length() > 0 && MqttConnector<T>::_mqttClient->connected()) {
// serialize to json doc
DynamicJsonDocument json(MqttConnector<T>::_bufferSize);
JsonObject jsonObject = json.to<JsonObject>();
MqttConnector<T>::_statefulService->read(jsonObject, _stateReader);
// serialize to string
String payload;
serializeJson(json, payload);
// publish the payload
MqttConnector<T>::_mqttClient->publish(_pubTopic.c_str(), 0, false, payload.c_str());
}
}
};
template <class T>
class MqttSub : virtual public MqttConnector<T> {
public:
MqttSub(JsonStateUpdater<T> stateUpdater,
StatefulService<T> * statefulService,
AsyncMqttClient * mqttClient,
const String & subTopic = "",
size_t bufferSize = DEFAULT_BUFFER_SIZE)
: MqttConnector<T>(statefulService, mqttClient, bufferSize)
, _stateUpdater(stateUpdater)
, _subTopic(subTopic) {
MqttConnector<T>::_mqttClient->onMessage(std::bind(&MqttSub::onMqttMessage, this, _1, _2, _3, _4, _5, _6));
}
void setSubTopic(const String & subTopic) {
if (!_subTopic.equals(subTopic)) {
// unsubscribe from the existing topic if one was set
if (_subTopic.length() > 0) {
MqttConnector<T>::_mqttClient->unsubscribe(_subTopic.c_str());
}
// set the new topic and re-configure the subscription
_subTopic = subTopic;
subscribe();
}
}
protected:
virtual void onConnect() {
subscribe();
}
private:
JsonStateUpdater<T> _stateUpdater;
String _subTopic;
void subscribe() {
if (_subTopic.length() > 0) {
MqttConnector<T>::_mqttClient->subscribe(_subTopic.c_str(), 2);
}
}
void onMqttMessage(char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
// we only care about the topic we are watching in this class
if (strcmp(_subTopic.c_str(), topic)) {
return;
}
// deserialize from string
DynamicJsonDocument json(MqttConnector<T>::_bufferSize);
DeserializationError error = deserializeJson(json, payload, len);
if (!error && json.is<JsonObject>()) {
JsonObject jsonObject = json.as<JsonObject>();
MqttConnector<T>::_statefulService->update(jsonObject, _stateUpdater, MQTT_ORIGIN_ID);
}
}
};
template <class T>
class MqttPubSub : public MqttPub<T>, public MqttSub<T> {
public:
MqttPubSub(JsonStateReader<T> stateReader,
JsonStateUpdater<T> stateUpdater,
StatefulService<T> * statefulService,
AsyncMqttClient * mqttClient,
const String & pubTopic = "",
const String & subTopic = "",
size_t bufferSize = DEFAULT_BUFFER_SIZE)
: MqttConnector<T>(statefulService, mqttClient, bufferSize)
, MqttPub<T>(stateReader, statefulService, mqttClient, pubTopic, bufferSize)
, MqttSub<T>(stateUpdater, statefulService, mqttClient, subTopic, bufferSize) {
}
public:
void configureTopics(const String & pubTopic, const String & subTopic) {
MqttSub<T>::setSubTopic(subTopic);
MqttPub<T>::setPubTopic(pubTopic);
}
protected:
void onConnect() {
MqttSub<T>::onConnect();
MqttPub<T>::onConnect();
}
};
#endif

View File

@@ -33,8 +33,8 @@ MqttSettingsService::MqttSettingsService(AsyncWebServer * server, FS * fs, Secur
, _retainedPassword(nullptr)
, _reconfigureMqtt(false)
, _disconnectedAt(0)
, _disconnectReason(AsyncMqttClientDisconnectReason::TCP_DISCONNECTED)
, _mqttClient() {
, _disconnectReason(espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED)
, _mqttClient(espMqttClientTypes::UseInternalTask::NO) {
WiFi.onEvent(std::bind(&MqttSettingsService::WiFiEvent, this, _1, _2));
_mqttClient.onConnect(std::bind(&MqttSettingsService::onMqttConnect, this, _1));
_mqttClient.onDisconnect(std::bind(&MqttSettingsService::onMqttDisconnect, this, _1));
@@ -51,12 +51,13 @@ void MqttSettingsService::begin() {
void MqttSettingsService::loop() {
if (_reconfigureMqtt || (_disconnectedAt && (uint32_t)(uuid::get_uptime() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) {
// reconfigure MQTT client
configureMqtt();
// clear the reconnection flags
_disconnectedAt = uuid::get_uptime();
if (configureMqtt()) {
_disconnectedAt = 0;
}
_reconfigureMqtt = false;
_disconnectedAt = 0;
}
_mqttClient.loop();
}
bool MqttSettingsService::isEnabled() {
@@ -71,22 +72,27 @@ const char * MqttSettingsService::getClientId() {
return _mqttClient.getClientId();
}
AsyncMqttClientDisconnectReason MqttSettingsService::getDisconnectReason() {
espMqttClientTypes::DisconnectReason MqttSettingsService::getDisconnectReason() {
return _disconnectReason;
}
AsyncMqttClient * MqttSettingsService::getMqttClient() {
espMqttClient * MqttSettingsService::getMqttClient() {
return &_mqttClient;
}
void MqttSettingsService::onMqttConnect(bool sessionPresent) {
// _disconnectedAt = 0;
emsesp::EMSESP::mqtt_.on_connect();
// emsesp::EMSESP::logger().info("Connected to MQTT, %s", (sessionPresent) ? ("with persistent session") : ("without persistent session"));
}
void MqttSettingsService::onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
void MqttSettingsService::onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) {
// emsesp::EMSESP::logger().info("Disconnected from MQTT reason: %d", (uint8_t)reason);
_disconnectReason = reason;
_disconnectedAt = uuid::get_uptime();
if (!_disconnectedAt) {
_disconnectedAt = uuid::get_uptime();
}
emsesp::EMSESP::mqtt_.on_disconnect(reason);
}
void MqttSettingsService::onConfigUpdated() {
@@ -121,7 +127,7 @@ void MqttSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
}
}
void MqttSettingsService::configureMqtt() {
bool MqttSettingsService::configureMqtt() {
// disconnect if connected
_mqttClient.disconnect();
// only connect if WiFi is connected and MQTT is enabled
@@ -137,11 +143,11 @@ void MqttSettingsService::configureMqtt() {
_mqttClient.setClientId(retainCstr(_state.clientId.c_str(), &_retainedClientId));
_mqttClient.setKeepAlive(_state.keepAlive);
_mqttClient.setCleanSession(_state.cleanSession);
_mqttClient.setMaxTopicLength(FACTORY_MQTT_MAX_TOPIC_LENGTH); // hardcode. We don't take this from the settings anymore.
_mqttClient.connect();
return _mqttClient.connect();
// } else {
// emsesp::EMSESP::logger().info("Error configuring MQTT client");
}
return false;
}
void MqttSettings::read(MqttSettings & settings, JsonObject & root) {

View File

@@ -4,7 +4,7 @@
#include <StatefulService.h>
#include <HttpEndpoint.h>
#include <FSPersistence.h>
#include <AsyncMqttClient.h>
#include <espMqttClient.h>
#include <ESPUtils.h>
#include <uuid/common.h>
@@ -104,13 +104,13 @@ class MqttSettingsService : public StatefulService<MqttSettings> {
MqttSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
~MqttSettingsService();
void begin();
void loop();
bool isEnabled();
bool isConnected();
const char * getClientId();
AsyncMqttClientDisconnectReason getDisconnectReason();
AsyncMqttClient * getMqttClient();
void begin();
void loop();
bool isEnabled();
bool isConnected();
const char * getClientId();
espMqttClientTypes::DisconnectReason getDisconnectReason();
espMqttClient * getMqttClient();
protected:
void onConfigUpdated();
@@ -120,7 +120,7 @@ class MqttSettingsService : public StatefulService<MqttSettings> {
FSPersistence<MqttSettings> _fsPersistence;
// Pointers to hold retained copies of the mqtt client connection strings.
// This is required as AsyncMqttClient holds references to the supplied connection strings.
// This is required as espMqttClient holds references to the supplied connection strings.
char * _retainedHost;
char * _retainedClientId;
char * _retainedUsername;
@@ -131,15 +131,15 @@ class MqttSettingsService : public StatefulService<MqttSettings> {
unsigned long _disconnectedAt;
// connection status
AsyncMqttClientDisconnectReason _disconnectReason;
espMqttClientTypes::DisconnectReason _disconnectReason;
// the MQTT client instance
AsyncMqttClient _mqttClient;
espMqttClient _mqttClient;
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
void onMqttConnect(bool sessionPresent);
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
void configureMqtt();
void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason);
bool configureMqtt();
};
#endif