diff --git a/MqttTopics.h b/MqttTopics.h index 755f586..138e370 100644 --- a/MqttTopics.h +++ b/MqttTopics.h @@ -26,3 +26,7 @@ #define mqtt_topic_config_sound_level "/configuration/soundLevel" #define mqtt_topic_presence "/presence/devices" + +#define mqtt_topic_reset "/maintenance/reset" +#define mqtt_topic_uptime "/maintenance/uptime" +#define mqtt_topic_freeheap "/maintenance/freeHeap" \ No newline at end of file diff --git a/Network.cpp b/Network.cpp index 31a4e87..e669a7d 100644 --- a/Network.cpp +++ b/Network.cpp @@ -180,6 +180,14 @@ bool Network::reconnect() { _device->mqttClient()->subscribe(topic.c_str()); } + if(_firstConnect) + { + _firstConnect = false; + for(const auto& it : _initTopics) + { + _device->mqttClient()->publish(it.first.c_str(), it.second.c_str(), true); + } + } } else { @@ -201,6 +209,15 @@ void Network::subscribe(const char* prefix, const char *path) _subscribedTopics.push_back(prefixedPath); } +void Network::initTopic(const char *prefix, const char *path, const char *value) +{ + char prefixedPath[500]; + buildMqttPath(prefix, path, prefixedPath); + String pathStr = prefixedPath; + String valueStr = value; + _initTopics[pathStr] = valueStr; +} + void Network::buildMqttPath(const char* prefix, const char* path, char* outPath) { int offset = 0; @@ -296,6 +313,15 @@ void Network::publishUInt(const char* prefix, const char *topic, const unsigned _device->mqttClient()->publish(path, str, true); } +void Network::publishULong(const char* prefix, const char *topic, const unsigned long value) +{ + char str[30]; + utoa(value, str, 10); + char path[200] = {0}; + buildMqttPath(prefix, topic, path); + _device->mqttClient()->publish(path, str, true); +} + void Network::publishBool(const char* prefix, const char *topic, const bool value) { char str[2] = {0}; diff --git a/Network.h b/Network.h index 6e8c78f..7d7eca0 100644 --- a/Network.h +++ b/Network.h @@ -2,6 +2,7 @@ #include #include +#include #include "networkDevices/NetworkDevice.h" #include "MqttReceiver.h" @@ -24,9 +25,11 @@ public: void disableAutoRestarts(); // disable on OTA start void subscribe(const char* prefix, const char* path); + void initTopic(const char* prefix, const char* path, const char* value); void publishFloat(const char* prefix, const char* topic, const float value, const uint8_t precision = 2); void publishInt(const char* prefix, const char* topic, const int value); void publishUInt(const char* prefix, const char* topic, const unsigned int value); + void publishULong(const char* prefix, const char* topic, const unsigned long value); void publishBool(const char* prefix, const char* topic, const bool value); bool publishString(const char* prefix, const char* topic, const char* value); @@ -57,11 +60,13 @@ private: char _mqttUser[31] = {0}; char _mqttPass[31] = {0}; char _mqttPresencePrefix[181] = {0}; - std::vector _subscribedTopics; int _networkTimeout = 0; std::vector _mqttReceivers; char* _presenceCsv = nullptr; bool _restartOnDisconnect = false; + bool _firstConnect = true; + std::vector _subscribedTopics; + std::map _initTopics; unsigned long _lastConnectedTs = 0; }; diff --git a/NetworkLock.cpp b/NetworkLock.cpp index e5971ae..b4c0009 100644 --- a/NetworkLock.cpp +++ b/NetworkLock.cpp @@ -48,6 +48,21 @@ void NetworkLock::initialize() { _network->subscribe(_mqttPath, topic); } + + _network->subscribe(_mqttPath, mqtt_topic_reset); + _network->initTopic(_mqttPath, mqtt_topic_reset, "0"); +} + +void NetworkLock::update() +{ + unsigned long ts = millis(); + + if(_lastMaintenanceTs == 0 || (ts - _lastMaintenanceTs) > 30000) + { + _lastMaintenanceTs = ts; + publishULong(mqtt_topic_uptime, ts / 1000 / 60); + publishUInt(mqtt_topic_freeheap, esp_get_free_heap_size()); + } } void NetworkLock::onMqttDataReceived(char *&topic, byte *&payload, unsigned int &length) @@ -60,6 +75,13 @@ void NetworkLock::onMqttDataReceived(char *&topic, byte *&payload, unsigned int value[i] = payload[i]; } + if(comparePrefixedPath(topic, mqtt_topic_reset) && strcmp(value, "1") == 0) + { + Serial.println(F("Restart requested via MQTT.")); + delay(200); + ESP.restart(); + } + if(comparePrefixedPath(topic, mqtt_topic_lock_action)) { if(strcmp(value, "") == 0 || strcmp(value, "ack") == 0 || strcmp(value, "unknown_action") == 0) return; @@ -241,3 +263,9 @@ bool NetworkLock::publishString(const char *topic, const char *value) { return _network->publishString(_mqttPath, topic, value); } + +void NetworkLock::publishULong(const char *topic, const unsigned long value) +{ + return _network->publishULong(_mqttPath, topic, value); +} + diff --git a/NetworkLock.h b/NetworkLock.h index 16ddba7..1af06c0 100644 --- a/NetworkLock.h +++ b/NetworkLock.h @@ -17,6 +17,7 @@ public: virtual ~NetworkLock(); void initialize(); + void update(); void publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState); void publishAuthorizationInfo(const uint32_t authId, const char* authName); @@ -36,6 +37,7 @@ private: void publishFloat(const char* topic, const float value, const uint8_t precision = 2); void publishInt(const char* topic, const int value); void publishUInt(const char* topic, const unsigned int value); + void publishULong(const char* topic, const unsigned long value); void publishBool(const char* topic, const bool value); bool publishString(const char* topic, const char* value); bool comparePrefixedPath(const char* fullPath, const char* subPath); @@ -49,6 +51,7 @@ private: char _mqttPath[181] = {0}; bool _firstTunerStatePublish = true; + unsigned long _lastMaintenanceTs = 0; bool (*_lockActionReceivedCallback)(const char* value) = nullptr; void (*_configUpdateReceivedCallback)(const char* path, const char* value) = nullptr; diff --git a/main.cpp b/main.cpp index 326af7e..69e8d25 100644 --- a/main.cpp +++ b/main.cpp @@ -36,16 +36,12 @@ void networkTask(void *pvParameters) { // Network Device and MQTT is connected. Process all updates. case 0: - network->update(); - webCfgServer->update(); - break; case 1: - // Network Device is connected, but MQTT isn't. Call network->update() to allow MQTT reconnect and - // keep Webserver alive to allow user to reconfigure network settings + networkLock->update(); network->update(); webCfgServer->update(); break; - // Neither Network Devicce or MQTT is connected + // Neither Network Devicc or MQTT is connected. Call network to allow for a reconnect. default: network->update(); break;