This commit is contained in:
iranl
2024-08-31 22:13:59 +02:00
parent 119ecf2983
commit 18c56de16d
13 changed files with 288 additions and 207 deletions

View File

@@ -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
)

View File

@@ -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)
{

View File

@@ -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();

View File

@@ -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"

View File

@@ -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;
};

View File

@@ -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; i<data_len; i++)
{
value[i] = data[i];
}
topic[topic_len] = '\0';
value[data_len] = '\0';
parseGpioTopics(topic, payload, len);
parseGpioTopics(topic, topic_len, (char*)value, data_len);
for(auto receiver : _mqttReceivers)
{
receiver->onMqttDataReceived(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<JsonObject>();
@@ -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<std::pair<char*, char*>> 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);
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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("<div id=\"msgdiv\" style=\"visibility:hidden\">Initiating Over-the-air update. This will take about two minutes, please be patient.<br>You will be forwarded automatically when the update is complete.</div>");
response.print("<div id=\"autoupdform\"><h4>Update Nuki Hub</h4>");
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("<br>");
#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("<span id=\"currentver\" style=\"display: none;\">currentver</span><span id=\"latestver\" style=\"display: none;\">latestver</span><span id=\"devver\" style=\"display: none;\">devver</span><span id=\"betaver\" style=\"display: none;\">betaver</span>");

View File

@@ -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;