Fork of the excellent esp8266-react - https://github.com/rjwats/esp8266-react
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.5 KiB

  1. #include <MqttSettingsService.h>
  2. /**
  3. * Retains a copy of the cstr provided in the pointer provided using dynamic allocation.
  4. *
  5. * Frees the pointer before allocation and leaves it as nullptr if cstr == nullptr.
  6. */
  7. static char* retainCstr(const char* cstr, char** ptr) {
  8. // free up previously retained value if exists
  9. free(*ptr);
  10. *ptr = nullptr;
  11. // dynamically allocate and copy cstr (if non null)
  12. if (cstr != nullptr) {
  13. *ptr = (char*)malloc(strlen(cstr) + 1);
  14. strcpy(*ptr, cstr);
  15. }
  16. // return reference to pointer for convenience
  17. return *ptr;
  18. }
  19. MqttSettingsService::MqttSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
  20. _httpEndpoint(MqttSettings::serialize,
  21. MqttSettings::deserialize,
  22. this,
  23. server,
  24. MQTT_SETTINGS_SERVICE_PATH,
  25. securityManager),
  26. _fsPersistence(MqttSettings::serialize, MqttSettings::deserialize, this, fs, MQTT_SETTINGS_FILE),
  27. _retainedHost(nullptr),
  28. _retainedClientId(nullptr),
  29. _retainedUsername(nullptr),
  30. _retainedPassword(nullptr),
  31. _reconfigureMqtt(false),
  32. _disconnectedAt(0),
  33. _disconnectReason(AsyncMqttClientDisconnectReason::TCP_DISCONNECTED),
  34. _mqttClient() {
  35. #ifdef ESP32
  36. WiFi.onEvent(
  37. std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2),
  38. WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
  39. WiFi.onEvent(std::bind(&MqttSettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2),
  40. WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
  41. #elif defined(ESP8266)
  42. _onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(
  43. std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
  44. _onStationModeGotIPHandler =
  45. WiFi.onStationModeGotIP(std::bind(&MqttSettingsService::onStationModeGotIP, this, std::placeholders::_1));
  46. #endif
  47. _mqttClient.onConnect(std::bind(&MqttSettingsService::onMqttConnect, this, std::placeholders::_1));
  48. _mqttClient.onDisconnect(std::bind(&MqttSettingsService::onMqttDisconnect, this, std::placeholders::_1));
  49. addUpdateHandler([&](const String& originId) { onConfigUpdated(); }, false);
  50. }
  51. MqttSettingsService::~MqttSettingsService() {
  52. }
  53. void MqttSettingsService::begin() {
  54. _fsPersistence.readFromFS();
  55. }
  56. void MqttSettingsService::loop() {
  57. if (_reconfigureMqtt || (_disconnectedAt && (unsigned long)(millis() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) {
  58. // reconfigure MQTT client
  59. configureMqtt();
  60. // clear the reconnection flags
  61. _reconfigureMqtt = false;
  62. _disconnectedAt = 0;
  63. }
  64. }
  65. bool MqttSettingsService::isEnabled() {
  66. return _state.enabled;
  67. }
  68. bool MqttSettingsService::isConnected() {
  69. return _mqttClient.connected();
  70. }
  71. const char* MqttSettingsService::getClientId() {
  72. return _mqttClient.getClientId();
  73. }
  74. AsyncMqttClientDisconnectReason MqttSettingsService::getDisconnectReason() {
  75. return _disconnectReason;
  76. }
  77. AsyncMqttClient* MqttSettingsService::getMqttClient() {
  78. return &_mqttClient;
  79. }
  80. void MqttSettingsService::onMqttConnect(bool sessionPresent) {
  81. Serial.print(F("Connected to MQTT, "));
  82. if (sessionPresent) {
  83. Serial.println(F("with persistent session"));
  84. } else {
  85. Serial.println(F("without persistent session"));
  86. }
  87. }
  88. void MqttSettingsService::onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  89. Serial.print(F("Disconnected from MQTT reason: "));
  90. Serial.println((uint8_t)reason);
  91. _disconnectReason = reason;
  92. _disconnectedAt = millis();
  93. }
  94. void MqttSettingsService::onConfigUpdated() {
  95. _reconfigureMqtt = true;
  96. _disconnectedAt = 0;
  97. }
  98. #ifdef ESP32
  99. void MqttSettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
  100. if (_state.enabled) {
  101. Serial.println(F("WiFi connection dropped, starting MQTT client."));
  102. onConfigUpdated();
  103. }
  104. }
  105. void MqttSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
  106. if (_state.enabled) {
  107. Serial.println(F("WiFi connection dropped, stopping MQTT client."));
  108. onConfigUpdated();
  109. }
  110. }
  111. #elif defined(ESP8266)
  112. void MqttSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
  113. if (_state.enabled) {
  114. Serial.println(F("WiFi connection dropped, starting MQTT client."));
  115. onConfigUpdated();
  116. }
  117. }
  118. void MqttSettingsService::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
  119. if (_state.enabled) {
  120. Serial.println(F("WiFi connection dropped, stopping MQTT client."));
  121. onConfigUpdated();
  122. }
  123. }
  124. #endif
  125. void MqttSettingsService::configureMqtt() {
  126. // disconnect if currently connected
  127. _mqttClient.disconnect();
  128. // only connect if WiFi is connected and MQTT is enabled
  129. if (_state.enabled && WiFi.isConnected()) {
  130. Serial.println(F("Connecting to MQTT..."));
  131. _mqttClient.setServer(retainCstr(_state.host.c_str(), &_retainedHost), _state.port);
  132. if (_state.username.length() > 0) {
  133. _mqttClient.setCredentials(
  134. retainCstr(_state.username.c_str(), &_retainedUsername),
  135. retainCstr(_state.password.length() > 0 ? _state.password.c_str() : nullptr, &_retainedPassword));
  136. } else {
  137. _mqttClient.setCredentials(retainCstr(nullptr, &_retainedUsername), retainCstr(nullptr, &_retainedPassword));
  138. }
  139. _mqttClient.setClientId(retainCstr(_state.clientId.c_str(), &_retainedClientId));
  140. _mqttClient.setKeepAlive(_state.keepAlive);
  141. _mqttClient.setCleanSession(_state.cleanSession);
  142. _mqttClient.setMaxTopicLength(_state.maxTopicLength);
  143. _mqttClient.connect();
  144. }
  145. }