diff --git a/clion/CMakeLists.txt b/clion/CMakeLists.txt index 2a62b19..83721a7 100644 --- a/clion/CMakeLists.txt +++ b/clion/CMakeLists.txt @@ -52,7 +52,6 @@ set(SRCFILES ../lib/BleScanner/src/BleInterfaces.h ../lib/BleScanner/src/BleScanner.cpp ../lib/MqttLogger/src/MqttLogger.cpp - ../lib/AsyncTCP/src/AsyncTCP.cpp ../src/util/NetworkUtil.cpp ../src/enums/NetworkDeviceType.h ../src/util/NetworkDeviceInstantiator.cpp @@ -62,14 +61,6 @@ file(GLOB_RECURSE SRCFILESREC lib/NimBLE-Arduino/src/*.c lib/NimBLE-Arduino/src/*.cpp lib/NimBLE-Arduino/src/*.h - lib/ESP Async WebServer/src/*.cpp - lib/ESP Async WebServer/src/*.h - lib/espMqttClient/src/*.cpp - lib/espMqttClient/src/*.h - lib/espMqttClient/src/Packets/*.cpp - lib/espMqttClient/src/Packets/*.h - lib/espMqttClient/src/Transport/*.cpp - lib/espMqttClient/src/Transport/*.h lib/ArduinoJson/src/*.h lib/ArduinoJson/src/*.hpp ) diff --git a/lib/MqttLogger/src/MqttLogger.cpp b/lib/MqttLogger/src/MqttLogger.cpp index ea59c0c..3ac5be3 100644 --- a/lib/MqttLogger/src/MqttLogger.cpp +++ b/lib/MqttLogger/src/MqttLogger.cpp @@ -76,9 +76,9 @@ void MqttLogger::sendBuffer() bool doSerial = this->mode==MqttLoggerMode::SerialOnly || this->mode==MqttLoggerMode::MqttAndSerial || this->mode==MqttLoggerMode::MqttAndSerialAndWeb || this->mode==MqttLoggerMode::SerialAndWeb; bool doWebSerial = this->mode==MqttLoggerMode::MqttAndSerialAndWeb || this->mode==MqttLoggerMode::SerialAndWeb; - if (this->mode!=MqttLoggerMode::SerialOnly && this->mode!=MqttLoggerMode::SerialAndWeb && this->client != NULL) + if (this->mode!=MqttLoggerMode::SerialOnly && this->mode!=MqttLoggerMode::SerialAndWeb) { - esp_mqtt_client_publish(this->client, topic, (const char*)this->buffer, this->bufferCnt, 0, 1); + esp_mqtt_client_publish(this->client, topic, (const char*)this->buffer, this->bufferCnt, 1, 1); } else if (this->mode == MqttLoggerMode::MqttAndSerialFallback) { diff --git a/lib/MqttLogger/src/MqttLogger.h b/lib/MqttLogger/src/MqttLogger.h index cb35fcc..56dc300 100644 --- a/lib/MqttLogger/src/MqttLogger.h +++ b/lib/MqttLogger/src/MqttLogger.h @@ -31,7 +31,8 @@ private: const char* topic; uint8_t* buffer; uint8_t* bufferEnd; - uint16_t bufferCnt = 0, bufferSize = 0; + uint16_t bufferCnt = 0; + uint16_t bufferSize = 0; esp_mqtt_client_handle_t client; MqttLoggerMode mode; void sendBuffer(); diff --git a/src/Config.h b/src/Config.h index 1a4d1cb..74e85f5 100644 --- a/src/Config.h +++ b/src/Config.h @@ -4,7 +4,7 @@ #define NUKI_HUB_VERSION "9.01" #define NUKI_HUB_BUILD "unknownbuildnr" -#define NUKI_HUB_DATE "2024-08-31" +#define NUKI_HUB_DATE "2024-09-01" #define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest" #define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json" diff --git a/src/MqttReceiver.h b/src/MqttReceiver.h index 3db350d..5529cfa 100644 --- a/src/MqttReceiver.h +++ b/src/MqttReceiver.h @@ -5,5 +5,5 @@ class MqttReceiver { public: - virtual void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) = 0; + virtual void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) = 0; }; \ No newline at end of file diff --git a/src/NukiNetwork.cpp b/src/NukiNetwork.cpp index 40eb868..e56b445 100644 --- a/src/NukiNetwork.cpp +++ b/src/NukiNetwork.cpp @@ -241,11 +241,9 @@ void NukiNetwork::initialize() Log->print(F(":")); Log->println(_mqttPort); - esp_mqtt_client_config_t mqtt_cfg = { 0 }; - - mqtt_cfg.credentials.client_id = _hostnameArr; - mqtt_cfg.session.disable_clean_session = !MQTT_CLEAN_SESSIONS; - mqtt_cfg.session.keepalive = MQTT_KEEP_ALIVE; + _mqtt_cfg.credentials.client_id = _hostnameArr; + _mqtt_cfg.session.disable_clean_session = !MQTT_CLEAN_SESSIONS; + _mqtt_cfg.session.keepalive = MQTT_KEEP_ALIVE; size_t caLength = _preferences->getString(preference_mqtt_ca, _ca, TLS_CA_MAX_SIZE); size_t crtLength = _preferences->getString(preference_mqtt_crt, _cert, TLS_CERT_MAX_SIZE); @@ -255,20 +253,38 @@ void NukiNetwork::initialize() { Log->println(F("MQTT over TLS.")); - mqtt_cfg.broker.address.uri = ((String)"mqtts://" + _preferences->getString(preference_mqtt_broker, "") + ":" + _preferences->getString(preference_mqtt_broker_port, "8883")).c_str(); - mqtt_cfg.broker.verification.certificate = _ca; + String uri = "mqtts://"; + uri.concat(_preferences->getString(preference_mqtt_broker, "")); + uri.concat(":"); + uri.concat(_preferences->getInt(preference_mqtt_broker_port, 8883)); + Log->print("URI: "); + Log->println(uri.c_str()); + //_mqtt_cfg.broker.address.uri = uri.c_str(); + _mqtt_cfg.broker.address.hostname = _mqttBrokerAddr; + _mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_SSL; + _mqtt_cfg.broker.address.port = _preferences->getInt(preference_mqtt_broker_port, 8883); + _mqtt_cfg.broker.verification.certificate = _ca; if(crtLength > 1 && keyLength > 1) // length is 1 when empty { Log->println(F("MQTT with client certificate.")); - mqtt_cfg.credentials.authentication.certificate = _cert; - mqtt_cfg.credentials.authentication.key = _key; + _mqtt_cfg.credentials.authentication.certificate = _cert; + _mqtt_cfg.credentials.authentication.key = _key; } } else { Log->println(F("MQTT without TLS.")); - mqtt_cfg.broker.address.uri = ((String)"mqtt://" + _preferences->getString(preference_mqtt_broker, "") + ":" + _preferences->getString(preference_mqtt_broker_port, "1883")).c_str(); + String uri = "mqtt://"; + uri.concat(_preferences->getString(preference_mqtt_broker, "")); + uri.concat(":"); + uri.concat(_preferences->getInt(preference_mqtt_broker_port, 1883)); + Log->print("URI: "); + Log->println(uri.c_str()); + //_mqtt_cfg.broker.address.uri = uri.c_str(); + _mqtt_cfg.broker.address.hostname = _mqttBrokerAddr; + _mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_TCP; + _mqtt_cfg.broker.address.port = _preferences->getInt(preference_mqtt_broker_port, 1883); } if(strlen(_mqttUser) == 0) @@ -278,79 +294,18 @@ void NukiNetwork::initialize() else { Log->print(F("MQTT: Connecting with user: ")); Log->println(_mqttUser); - mqtt_cfg.credentials.username = _mqttUser; - mqtt_cfg.credentials.authentication.password = _mqttPass; + _mqtt_cfg.credentials.username = _mqttUser; + _mqtt_cfg.credentials.authentication.password = _mqttPass; } - mqtt_cfg.session.last_will.topic = _mqttConnectionStateTopic; - mqtt_cfg.session.last_will.msg = _lastWillPayload; - mqtt_cfg.session.last_will.msg_len = sizeof(_lastWillPayload); - mqtt_cfg.session.last_will.qos = 1; - mqtt_cfg.session.last_will.retain = true; + _mqtt_cfg.session.last_will.topic = _mqttConnectionStateTopic; + _mqtt_cfg.session.last_will.msg = _lastWillPayload; + _mqtt_cfg.session.last_will.msg_len = sizeof(_lastWillPayload); + _mqtt_cfg.session.last_will.qos = 1; + _mqtt_cfg.session.last_will.retain = true; - esp_mqtt_client_handle_t _mqttClient = esp_mqtt_client_init(&mqtt_cfg); + _mqttClient = esp_mqtt_client_init(&_mqtt_cfg); esp_mqtt_client_register_event(_mqttClient, (esp_mqtt_event_id_t)ESP_EVENT_ANY_ID, mqtt_event_handler_cb, NULL); - - Log->println(F("Attempting MQTT connection")); - esp_mqtt_client_start(_mqttClient); - - if(_preferences->getBool(preference_mqtt_log_enabled, false) || _preferences->getBool(preference_webserial_enabled, false)) - { - MqttLoggerMode mode; - - if(_preferences->getBool(preference_mqtt_log_enabled, false) && _preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::MqttAndSerialAndWeb; - else if (_preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::SerialAndWeb; - else mode = MqttLoggerMode::MqttAndSerial; - - char* _path = new char[200]; - memset(_path, 0, sizeof(_path)); - - String pathStr = _preferences->getString(preference_mqtt_lock_path); - pathStr.concat(mqtt_topic_log); - strcpy(_path, pathStr.c_str()); - Log = new MqttLogger(_mqttClient, _path, mode); - } - - char gpioPath[250]; - bool rebGpio = rebuildGpio(); - - if(rebGpio) - { - Log->println(F("Rebuild MQTT GPIO structure")); - } - for (const auto &pinEntry: _gpio->pinConfiguration()) - { - switch (pinEntry.role) - { - case PinRole::GeneralInputPullDown: - case PinRole::GeneralInputPullUp: - if(rebGpio) - { - buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role}); - publishString(_lockPath.c_str(), gpioPath, "input", false); - buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); - publishString(_lockPath.c_str(), gpioPath, std::to_string(digitalRead(pinEntry.pin)).c_str(), false); - } - break; - case PinRole::GeneralOutput: - if(rebGpio) - { - buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role}); - publishString(_lockPath.c_str(), gpioPath, "output", false); - buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); - publishString(_lockPath.c_str(), gpioPath, "0", false); - } - buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); - subscribe(_lockPath.c_str(), gpioPath); - break; - default: - break; - } - } - _gpio->addCallback([this](const GpioAction& action, const int& pin) - { - gpioActionCallback(action, pin); - }); } _discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery, ""); @@ -420,6 +375,70 @@ bool NukiNetwork::update() } } + if(_device->isConnected() && !_mqttClientInitiated && strcmp(_mqttBrokerAddr, "") != 0) + { + Log->println(F("Attempting MQTT connection")); + esp_mqtt_client_start(_mqttClient); + + if(_preferences->getBool(preference_mqtt_log_enabled, false) || _preferences->getBool(preference_webserial_enabled, false)) + { + MqttLoggerMode mode; + + if(_preferences->getBool(preference_mqtt_log_enabled, false) && _preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::MqttAndSerialAndWeb; + else if (_preferences->getBool(preference_webserial_enabled, false)) mode = MqttLoggerMode::SerialAndWeb; + else mode = MqttLoggerMode::MqttAndSerial; + + char* _path = new char[200]; + memset(_path, 0, sizeof(_path)); + + String pathStr = _preferences->getString(preference_mqtt_lock_path); + pathStr.concat(mqtt_topic_log); + strcpy(_path, pathStr.c_str()); + Log = new MqttLogger(_mqttClient, _path, mode); + } + + char gpioPath[250]; + bool rebGpio = rebuildGpio(); + + if(rebGpio) + { + Log->println(F("Rebuild MQTT GPIO structure")); + } + for (const auto &pinEntry: _gpio->pinConfiguration()) + { + switch (pinEntry.role) + { + case PinRole::GeneralInputPullDown: + case PinRole::GeneralInputPullUp: + if(rebGpio) + { + buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role}); + publishString(_lockPath.c_str(), gpioPath, "input", false); + buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); + publishString(_lockPath.c_str(), gpioPath, std::to_string(digitalRead(pinEntry.pin)).c_str(), false); + } + break; + case PinRole::GeneralOutput: + if(rebGpio) + { + buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role}); + publishString(_lockPath.c_str(), gpioPath, "output", false); + buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); + publishString(_lockPath.c_str(), gpioPath, "0", false); + } + buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); + subscribe(_lockPath.c_str(), gpioPath); + break; + default: + break; + } + } + _gpio->addCallback([this](const GpioAction& action, const int& pin) + { + gpioActionCallback(action, pin); + }); + } + if(_logIp && device()->isConnected() && !_device->localIP().equals("0.0.0.0")) { _logIp = false; @@ -579,6 +598,7 @@ void NukiNetwork::mqtt_event_handler(void *handler_args, esp_event_base_t base, switch ((esp_mqtt_event_id_t)event_id) { case MQTT_EVENT_CONNECTED: ESP_LOGI(MQTT_TAG, "MQTT_EVENT_CONNECTED"); + _mqttClientInitiated = true; _mqttConnected = true; reconnect(); break; @@ -597,9 +617,9 @@ void NukiNetwork::mqtt_event_handler(void *handler_args, esp_event_base_t base, break; case MQTT_EVENT_DATA: ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - onMqttDataReceived((const char*)event->topic, (const uint8_t*)event->data, (size_t&)event->data_len); + //printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); + //printf("DATA=%.*s\r\n", event->data_len, event->data); + onMqttDataReceived(event->topic, event->topic_len, event->data, event->data_len); break; case MQTT_EVENT_ERROR: ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR"); @@ -698,20 +718,26 @@ void NukiNetwork::registerMqttReceiver(MqttReceiver* receiver) _mqttReceivers.push_back(receiver); } -void NukiNetwork::onMqttDataReceived(const char* topic, const uint8_t* payload, size_t& len) +void NukiNetwork::onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) { - if((_mqttConnectedTs == -1 || (millis() - _mqttConnectedTs < 2000)) && topic) return; + char value[800] = {0}; + for(int i=0; ionMqttDataReceived(topic, (byte*)payload, len); + receiver->onMqttDataReceived(topic, topic_len, (char*)value, data_len); } } -void NukiNetwork::parseGpioTopics(const char *topic, const uint8_t *payload, size_t& len) +void NukiNetwork::parseGpioTopics(char* topic, int topic_len, char* data, int data_len) { char gpioPath[250]; buildMqttPath(gpioPath, {_lockPath.c_str(), mqtt_topic_gpio_prefix, mqtt_topic_gpio_pin}); @@ -730,7 +756,7 @@ void NukiNetwork::parseGpioTopics(const char *topic, const uint8_t *payload, siz if(_gpio->getPinRole(pin) == PinRole::GeneralOutput) { - const uint8_t pinState = strcmp((const char*)payload, "1") == 0 ? HIGH : LOW; + const uint8_t pinState = strcmp(data, "1") == 0 ? HIGH : LOW; Log->print(F("GPIO ")); Log->print(pin); Log->print(F(" (Output) --> ")); @@ -771,6 +797,10 @@ bool NukiNetwork::pathEquals(const char* prefix, const char* path, const char* r void NukiNetwork::publishFloat(const char* prefix, const char* topic, const float value, bool retain, const uint8_t precision) { + if(!_mqttClientInitiated) + { + return; + } char str[30]; dtostrf(value, 0, precision, str); char path[200] = {0}; @@ -780,6 +810,10 @@ void NukiNetwork::publishFloat(const char* prefix, const char* topic, const floa void NukiNetwork::publishInt(const char* prefix, const char *topic, const int value, bool retain) { + if(!_mqttClientInitiated) + { + return; + } char str[30]; itoa(value, str, 10); char path[200] = {0}; @@ -789,6 +823,10 @@ void NukiNetwork::publishInt(const char* prefix, const char *topic, const int va void NukiNetwork::publishUInt(const char* prefix, const char *topic, const unsigned int value, bool retain) { + if(!_mqttClientInitiated) + { + return; + } char str[30]; utoa(value, str, 10); char path[200] = {0}; @@ -798,6 +836,10 @@ void NukiNetwork::publishUInt(const char* prefix, const char *topic, const unsig void NukiNetwork::publishULong(const char* prefix, const char *topic, const unsigned long value, bool retain) { + if(!_mqttClientInitiated) + { + return; + } char str[30]; utoa(value, str, 10); char path[200] = {0}; @@ -807,6 +849,10 @@ void NukiNetwork::publishULong(const char* prefix, const char *topic, const unsi void NukiNetwork::publishLongLong(const char* prefix, const char *topic, int64_t value, bool retain) { + if(!_mqttClientInitiated) + { + return; + } static char result[21] = ""; memset(&result[0], 0, sizeof(result)); char temp[21] = ""; @@ -828,6 +874,10 @@ void NukiNetwork::publishLongLong(const char* prefix, const char *topic, int64_t void NukiNetwork::publishBool(const char* prefix, const char *topic, const bool value, bool retain) { + if(!_mqttClientInitiated) + { + return; + } char str[2] = {0}; str[0] = value ? '1' : '0'; char path[200] = {0}; @@ -837,6 +887,10 @@ void NukiNetwork::publishBool(const char* prefix, const char *topic, const bool bool NukiNetwork::publishString(const char* prefix, const char *topic, const char *value, bool retain) { + if(!_mqttClientInitiated) + { + return false; + } char path[200] = {0}; buildMqttPath(path, { prefix, topic }); return esp_mqtt_client_publish(_mqttClient, path, value, 0, MQTT_QOS_LEVEL, retain) > 0; @@ -844,6 +898,10 @@ bool NukiNetwork::publishString(const char* prefix, const char *topic, const cha void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction) { + if(!_mqttClientInitiated) + { + return; + } JsonDocument json; json.clear(); JsonObject dev = json["dev"].to(); @@ -1343,6 +1401,10 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, const char *baseTopic, char *name, char *uidString) { + if(!_mqttClientInitiated) + { + return; + } uint32_t aclPrefs[17]; _preferences->getBytes(preference_acl, &aclPrefs, sizeof(aclPrefs)); @@ -2393,6 +2455,10 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons void NukiNetwork::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopic, char *name, char *uidString) { + if(!_mqttClientInitiated) + { + return; + } publishHassTopic("binary_sensor", "door_sensor", uidString, @@ -2413,6 +2479,10 @@ void NukiNetwork::publishHASSConfigDoorSensor(char *deviceType, const char *base void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, const char *baseTopic, char *name, char *uidString) { + if(!_mqttClientInitiated) + { + return; + } uint32_t aclPrefs[17]; _preferences->getBytes(preference_acl, &aclPrefs, sizeof(aclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -3401,6 +3471,10 @@ void NukiNetwork::publishHassTopic(const String& mqttDeviceType, std::vector> additionalEntries ) { + if(!_mqttClientInitiated) + { + return; + } if (_discoveryTopic != "") { JsonDocument json; @@ -3427,6 +3501,10 @@ String NukiNetwork::createHassTopicPath(const String& mqttDeviceType, const Stri void NukiNetwork::removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString) { + if(!_mqttClientInitiated) + { + return; + } if (_discoveryTopic != "") { String path = createHassTopicPath(mqttDeviceType, mqttDeviceName, uidString); @@ -3436,6 +3514,10 @@ void NukiNetwork::removeHassTopic(const String& mqttDeviceType, const String& mq void NukiNetwork::removeTopic(const String& mqttPath, const String& mqttTopic) { + if(!_mqttClientInitiated) + { + return; + } String path = mqttPath; path.concat(mqttTopic); esp_mqtt_client_publish(_mqttClient, path.c_str(), "", 0, MQTT_QOS_LEVEL, 1); @@ -3808,6 +3890,10 @@ void NukiNetwork::timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* st uint16_t NukiNetwork::subscribe(const char *topic, uint8_t qos) { + if(!_mqttClientInitiated) + { + return -1; + } return esp_mqtt_client_subscribe(_mqttClient, topic, qos); } diff --git a/src/NukiNetwork.h b/src/NukiNetwork.h index 39f0e72..fad16f3 100644 --- a/src/NukiNetwork.h +++ b/src/NukiNetwork.h @@ -117,8 +117,8 @@ private: #ifndef NUKI_HUB_UPDATER static void mqtt_event_handler_cb(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data); void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data); - void onMqttDataReceived(const char* topic, const uint8_t* payload, size_t& len); - void parseGpioTopics(const char* topic, const uint8_t* payload, size_t& len); + void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len); + void parseGpioTopics(char* topic, int topic_len, char* data, int data_len); void gpioActionCallback(const GpioAction& action, const int& pin); String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString); @@ -144,6 +144,8 @@ private: Gpio* _gpio; + esp_mqtt_client_config_t _mqtt_cfg = { 0 }; + bool _mqttClientInitiated = false; int _mqttConnectionState = 0; bool _mqttConnected = false; int _mqttConnectCounter = 0; diff --git a/src/NukiNetworkLock.cpp b/src/NukiNetworkLock.cpp index a5f77af..2c8e84f 100644 --- a/src/NukiNetworkLock.cpp +++ b/src/NukiNetworkLock.cpp @@ -184,24 +184,22 @@ void NukiNetworkLock::initialize() }); } -void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) +void NukiNetworkLock::onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) { - char* value = (char*)payload; - if(_network->mqttRecentlyConnected() && _network->pathEquals(_mqttPath, mqtt_topic_lock_action, topic)) { Log->println("MQTT recently connected, ignoring lock action."); return; } - if(comparePrefixedPath(topic, mqtt_topic_reset) && strcmp(value, "1") == 0) + if(comparePrefixedPath(topic, mqtt_topic_reset) && strcmp(data, "1") == 0) { Log->println(F("Restart requested via MQTT.")); _network->clearWifiFallback(); delay(200); restartEsp(RestartReason::RequestedViaMqtt); } - else if(comparePrefixedPath(topic, mqtt_topic_update) && strcmp(value, "1") == 0 && _preferences->getBool(preference_update_from_mqtt, false)) + else if(comparePrefixedPath(topic, mqtt_topic_update) && strcmp(data, "1") == 0 && _preferences->getBool(preference_update_from_mqtt, false)) { Log->println(F("Update requested via MQTT.")); @@ -303,17 +301,17 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const } else if(comparePrefixedPath(topic, mqtt_topic_webserver_action)) { - if(strcmp(value, "") == 0 || - strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || + strcmp(data, "--") == 0) return; - if(strcmp(value, "1") == 0) + if(strcmp(data, "1") == 0) { if(_preferences->getBool(preference_webserver_enabled, true) || forceEnableWebServer) return; Log->println(F("Webserver enabled, restarting.")); _preferences->putBool(preference_webserver_enabled, true); } - else if (strcmp(value, "0") == 0) + else if (strcmp(data, "0") == 0) { if(!_preferences->getBool(preference_webserver_enabled, true) && !forceEnableWebServer) return; Log->println(F("Webserver disabled, restarting.")); @@ -327,10 +325,10 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const } else if(comparePrefixedPath(topic, mqtt_topic_lock_log_rolling_last)) { - if(strcmp(value, "") == 0 || - strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || + strcmp(data, "--") == 0) return; - if(atoi(value) > 0 && atoi(value) > _lastRollingLog) _lastRollingLog = atoi(value); + if(atoi(data) > 0 && atoi(data) > _lastRollingLog) _lastRollingLog = atoi(data); } if(_offEnabled) @@ -341,7 +339,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const { if(_officialUpdateReceivedCallback != nullptr) { - _officialUpdateReceivedCallback(offTopic, value); + _officialUpdateReceivedCallback(offTopic, data); } } } @@ -349,19 +347,19 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const if(comparePrefixedPath(topic, mqtt_topic_lock_action)) { - if(strcmp(value, "") == 0 || - strcmp(value, "--") == 0 || - strcmp(value, "ack") == 0 || - strcmp(value, "unknown_action") == 0 || - strcmp(value, "denied") == 0 || - strcmp(value, "error") == 0) return; + if(strcmp(data, "") == 0 || + strcmp(data, "--") == 0 || + strcmp(data, "ack") == 0 || + strcmp(data, "unknown_action") == 0 || + strcmp(data, "denied") == 0 || + strcmp(data, "error") == 0) return; Log->print(F("Lock action received: ")); - Log->println(value); + Log->println(data); LockActionResult lockActionResult = LockActionResult::Failed; if(_lockActionReceivedCallback != NULL) { - lockActionResult = _lockActionReceivedCallback(value); + lockActionResult = _lockActionReceivedCallback(data); } switch(lockActionResult) @@ -387,16 +385,16 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const { if(_keypadCommandReceivedReceivedCallback != nullptr) { - if(strcmp(value, "--") == 0) return; + if(strcmp(data, "--") == 0) return; - _keypadCommandReceivedReceivedCallback(value, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled); + _keypadCommandReceivedReceivedCallback(data, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled); _keypadCommandId = 0; _keypadCommandName = "--"; _keypadCommandCode = "000000"; _keypadCommandEnabled = 1; - if(strcmp(value, "--") != 0) + if(strcmp(data, "--") != 0) { publishString(mqtt_topic_keypad_command_action, "--", true); } @@ -408,38 +406,38 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id)) { - _keypadCommandId = atoi(value); + _keypadCommandId = atoi(data); } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_name)) { - _keypadCommandName = value; + _keypadCommandName = data; } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_code)) { - _keypadCommandCode = value; + _keypadCommandCode = data; } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_enabled)) { - _keypadCommandEnabled = atoi(value); + _keypadCommandEnabled = atoi(data); } } - if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0) + if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_CONFIG; publishString(mqtt_topic_query_config, "0", true); } - else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(value, "1") == 0) + else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_LOCKSTATE; publishString(mqtt_topic_query_lockstate, "0", true); } - else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(value, "1") == 0) + else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_KEYPAD; publishString(mqtt_topic_query_keypad, "0", true); } - else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(value, "1") == 0) + else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_BATTERY; publishString(mqtt_topic_query_battery, "0", true); @@ -447,11 +445,11 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const if(comparePrefixedPath(topic, mqtt_topic_config_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_configUpdateReceivedCallback != NULL) { - _configUpdateReceivedCallback(value); + _configUpdateReceivedCallback(data); } publishString(mqtt_topic_config_action, "--", true); @@ -459,11 +457,11 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const if(comparePrefixedPath(topic, mqtt_topic_keypad_json_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_keypadJsonCommandReceivedReceivedCallback != NULL) { - _keypadJsonCommandReceivedReceivedCallback(value); + _keypadJsonCommandReceivedReceivedCallback(data); } publishString(mqtt_topic_keypad_json_action, "--", true); @@ -471,11 +469,11 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const if(comparePrefixedPath(topic, mqtt_topic_timecontrol_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_timeControlCommandReceivedReceivedCallback != NULL) { - _timeControlCommandReceivedReceivedCallback(value); + _timeControlCommandReceivedReceivedCallback(data); } publishString(mqtt_topic_timecontrol_action, "--", true); @@ -483,11 +481,11 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const if(comparePrefixedPath(topic, mqtt_topic_auth_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_authCommandReceivedReceivedCallback != NULL) { - _authCommandReceivedReceivedCallback(value); + _authCommandReceivedReceivedCallback(data); } publishString(mqtt_topic_auth_action, "--", true); diff --git a/src/NukiNetworkLock.h b/src/NukiNetworkLock.h index d069ccf..34a8cbe 100644 --- a/src/NukiNetworkLock.h +++ b/src/NukiNetworkLock.h @@ -53,7 +53,7 @@ public: void setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char* value)); void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value)); void setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char* value)); - void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override; + void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) override; void publishFloat(const char* topic, const float value, bool retain, const uint8_t precision = 2); void publishInt(const char* topic, const int value, bool retain); diff --git a/src/NukiNetworkOpener.cpp b/src/NukiNetworkOpener.cpp index da7e868..337068f 100644 --- a/src/NukiNetworkOpener.cpp +++ b/src/NukiNetworkOpener.cpp @@ -136,10 +136,8 @@ void NukiNetworkOpener::update() } } -void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) +void NukiNetworkOpener::onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) { - char* value = (char*)payload; - if(_network->mqttRecentlyConnected() && _network->pathEquals(_mqttPath, mqtt_topic_lock_action, topic)) { Log->println("MQTT recently connected, ignoring opener action."); @@ -148,27 +146,27 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con if(comparePrefixedPath(topic, mqtt_topic_lock_log_rolling_last)) { - if(strcmp(value, "") == 0 || - strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || + strcmp(data, "--") == 0) return; - if(atoi(value) > 0 && atoi(value) > _lastRollingLog) _lastRollingLog = atoi(value); + if(atoi(data) > 0 && atoi(data) > _lastRollingLog) _lastRollingLog = atoi(data); } if(comparePrefixedPath(topic, mqtt_topic_lock_action)) { - if(strcmp(value, "") == 0 || - strcmp(value, "--") == 0 || - strcmp(value, "ack") == 0 || - strcmp(value, "unknown_action") == 0 || - strcmp(value, "denied") == 0 || - strcmp(value, "error") == 0) return; + if(strcmp(data, "") == 0 || + strcmp(data, "--") == 0 || + strcmp(data, "ack") == 0 || + strcmp(data, "unknown_action") == 0 || + strcmp(data, "denied") == 0 || + strcmp(data, "error") == 0) return; Log->print(F("Opener action received: ")); - Log->println(value); + Log->println(data); LockActionResult lockActionResult = LockActionResult::Failed; if(_lockActionReceivedCallback != NULL) { - lockActionResult = _lockActionReceivedCallback(value); + lockActionResult = _lockActionReceivedCallback(data); } switch(lockActionResult) @@ -194,16 +192,16 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con { if(_keypadCommandReceivedReceivedCallback != nullptr) { - if(strcmp(value, "--") == 0) return; + if(strcmp(data, "--") == 0) return; - _keypadCommandReceivedReceivedCallback(value, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled); + _keypadCommandReceivedReceivedCallback(data, _keypadCommandId, _keypadCommandName, _keypadCommandCode, _keypadCommandEnabled); _keypadCommandId = 0; _keypadCommandName = "--"; _keypadCommandCode = "000000"; _keypadCommandEnabled = 1; - if(strcmp(value, "--") != 0) + if(strcmp(data, "--") != 0) { publishString(mqtt_topic_keypad_command_action, "--", true); } @@ -215,38 +213,38 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_id)) { - _keypadCommandId = atoi(value); + _keypadCommandId = atoi(data); } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_name)) { - _keypadCommandName = value; + _keypadCommandName = data; } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_code)) { - _keypadCommandCode = value; + _keypadCommandCode = data; } else if(comparePrefixedPath(topic, mqtt_topic_keypad_command_enabled)) { - _keypadCommandEnabled = atoi(value); + _keypadCommandEnabled = atoi(data); } } - if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(value, "1") == 0) + if(comparePrefixedPath(topic, mqtt_topic_query_config) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_CONFIG; publishString(mqtt_topic_query_config, "0", true); } - else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(value, "1") == 0) + else if(comparePrefixedPath(topic, mqtt_topic_query_lockstate) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_LOCKSTATE; publishString(mqtt_topic_query_lockstate, "0", true); } - else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(value, "1") == 0) + else if(comparePrefixedPath(topic, mqtt_topic_query_keypad) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_KEYPAD; publishString(mqtt_topic_query_keypad, "0", true); } - else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(value, "1") == 0) + else if(comparePrefixedPath(topic, mqtt_topic_query_battery) && strcmp(data, "1") == 0) { _queryCommands = _queryCommands | QUERY_COMMAND_BATTERY; publishString(mqtt_topic_query_battery, "0", true); @@ -254,11 +252,11 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con if(comparePrefixedPath(topic, mqtt_topic_config_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_configUpdateReceivedCallback != NULL) { - _configUpdateReceivedCallback(value); + _configUpdateReceivedCallback(data); } publishString(mqtt_topic_config_action, "--", true); @@ -266,11 +264,11 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con if(comparePrefixedPath(topic, mqtt_topic_keypad_json_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_keypadJsonCommandReceivedReceivedCallback != NULL) { - _keypadJsonCommandReceivedReceivedCallback(value); + _keypadJsonCommandReceivedReceivedCallback(data); } publishString(mqtt_topic_keypad_json_action, "--", true); @@ -278,11 +276,11 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con if(comparePrefixedPath(topic, mqtt_topic_timecontrol_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_timeControlCommandReceivedReceivedCallback != NULL) { - _timeControlCommandReceivedReceivedCallback(value); + _timeControlCommandReceivedReceivedCallback(data); } publishString(mqtt_topic_timecontrol_action, "--", true); @@ -290,11 +288,11 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con if(comparePrefixedPath(topic, mqtt_topic_auth_action)) { - if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; + if(strcmp(data, "") == 0 || strcmp(data, "--") == 0) return; if(_authCommandReceivedReceivedCallback != NULL) { - _authCommandReceivedReceivedCallback(value); + _authCommandReceivedReceivedCallback(data); } publishString(mqtt_topic_auth_action, "--", true); diff --git a/src/NukiNetworkOpener.h b/src/NukiNetworkOpener.h index 498cfe7..df36893 100644 --- a/src/NukiNetworkOpener.h +++ b/src/NukiNetworkOpener.h @@ -47,7 +47,7 @@ public: void setKeypadJsonCommandReceivedCallback(void (*keypadJsonCommandReceivedReceivedCallback)(const char* value)); void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value)); void setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char* value)); - void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override; + void onMqttDataReceived(char* topic, int topic_len, char* data, int data_len) override; bool reconnected(); uint8_t queryCommands(); diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index 090148b..203c37f 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -289,6 +289,33 @@ esp_err_t WebCfgServer::buildOtaHtml(PsychicRequest *request, bool debug) return response.endSend(); } + #ifndef NUKI_HUB_UPDATER + bool manifestSuccess = false; + JsonDocument doc; + + NetworkClientSecure *clientOTAUpdate = new NetworkClientSecure; + if (clientOTAUpdate) { + clientOTAUpdate->setCACertBundle(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start); + { + HTTPClient httpsOTAClient; + httpsOTAClient.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + httpsOTAClient.setTimeout(2500); + httpsOTAClient.useHTTP10(true); + + if (httpsOTAClient.begin(*clientOTAUpdate, GITHUB_OTA_MANIFEST_URL)) { + int httpResponseCodeOTA = httpsOTAClient.GET(); + + if (httpResponseCodeOTA == HTTP_CODE_OK || httpResponseCodeOTA == HTTP_CODE_MOVED_PERMANENTLY) + { + DeserializationError jsonError = deserializeJson(doc, httpsOTAClient.getStream()); + if (!jsonError) { manifestSuccess = true; } + } + httpsOTAClient.end(); + } + } + delete clientOTAUpdate; + } + response.print("
Initiating Over-the-air update. This will take about two minutes, please be patient.
You will be forwarded automatically when the update is complete.
"); response.print("

Update Nuki Hub

"); response.print("Click on the button to reboot and automatically update Nuki Hub and the Nuki Hub updater to the latest versions from GitHub"); @@ -317,33 +344,6 @@ esp_err_t WebCfgServer::buildOtaHtml(PsychicRequest *request, bool debug) response.print(NUKI_HUB_DATE); response.print("
"); - #ifndef NUKI_HUB_UPDATER - bool manifestSuccess = false; - JsonDocument doc; - - NetworkClientSecure *clientOTAUpdate = new NetworkClientSecure; - if (clientOTAUpdate) { - clientOTAUpdate->setCACertBundle(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start); - { - HTTPClient httpsOTAClient; - httpsOTAClient.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - httpsOTAClient.setTimeout(2500); - httpsOTAClient.useHTTP10(true); - - if (httpsOTAClient.begin(*clientOTAUpdate, GITHUB_OTA_MANIFEST_URL)) { - int httpResponseCodeOTA = httpsOTAClient.GET(); - - if (httpResponseCodeOTA == HTTP_CODE_OK || httpResponseCodeOTA == HTTP_CODE_MOVED_PERMANENTLY) - { - DeserializationError jsonError = deserializeJson(doc, httpsOTAClient.getStream()); - if (!jsonError) { manifestSuccess = true; } - } - httpsOTAClient.end(); - } - } - delete clientOTAUpdate; - } - if(!manifestSuccess) { response.print("currentverlatestverdevverbetaver"); diff --git a/src/main.cpp b/src/main.cpp index 2e82446..a6ca969 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -103,7 +103,11 @@ int _log_vprintf(const char *fmt, va_list args) { void setReroute(){ esp_log_set_vprintf(_log_vprintf); - if(preferences->getBool(preference_mqtt_log_enabled)) esp_log_level_set("*", ESP_LOG_INFO); + if(preferences->getBool(preference_mqtt_log_enabled)) + { + esp_log_level_set("*", ESP_LOG_INFO); + esp_log_level_set("mqtt", ESP_LOG_NONE); + } else { esp_log_level_set("*", ESP_LOG_DEBUG); @@ -376,6 +380,7 @@ void setupTasks(bool ota) void setup() { esp_log_level_set("*", ESP_LOG_ERROR); + esp_log_level_set("mqtt", ESP_LOG_NONE); Serial.begin(115200); Log = &Serial;