This commit is contained in:
iranl
2024-08-29 23:27:56 +02:00
parent 52bd4f74c1
commit 25076e6e7e
102 changed files with 262 additions and 11599 deletions

View File

@@ -4,7 +4,7 @@
#define NUKI_HUB_VERSION "9.01"
#define NUKI_HUB_BUILD "unknownbuildnr"
#define NUKI_HUB_DATE "2024-08-28"
#define NUKI_HUB_DATE "2024-08-31"
#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

@@ -123,18 +123,6 @@ void NukiNetwork::setupDevice()
Log->print(F("Network device: "));
Log->print(_device->deviceName());
#ifndef NUKI_HUB_UPDATER
_device->mqttOnConnect([&](bool sessionPresent)
{
onMqttConnect(sessionPresent);
});
_device->mqttOnDisconnect([&](espMqttClientTypes::DisconnectReason reason)
{
onMqttDisconnect(reason);
});
#endif
}
void NukiNetwork::reconfigureDevice()
@@ -242,55 +230,128 @@ void NukiNetwork::initialize()
}
}
Log->print(F("MQTT Broker: "));
Log->print(_mqttBrokerAddr);
Log->print(F(":"));
Log->println(_mqttPort);
_device->mqttSetClientId(_hostnameArr);
_device->mqttSetCleanSession(MQTT_CLEAN_SESSIONS);
_device->mqttSetKeepAlive(MQTT_KEEP_ALIVE);
char gpioPath[250];
bool rebGpio = rebuildGpio();
if(rebGpio)
if(strcmp(_mqttBrokerAddr, "") == 0)
{
Log->println(F("Rebuild MQTT GPIO structure"));
Log->println(F("MQTT Broker not configured, aborting connection attempt."));
}
for (const auto &pinEntry: _gpio->pinConfiguration())
else
{
switch (pinEntry.role)
Log->print(F("MQTT Broker: "));
Log->print(_mqttBrokerAddr);
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;
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);
size_t keyLength = _preferences->getString(preference_mqtt_key, _key, TLS_KEY_MAX_SIZE);
if(caLength > 1)
{
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;
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;
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;
}
}
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();
}
if(strlen(_mqttUser) == 0)
{
Log->println(F("MQTT: Connecting without credentials"));
}
else
{
Log->print(F("MQTT: Connecting with user: ")); Log->println(_mqttUser);
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;
esp_mqtt_client_handle_t _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);
});
}
_gpio->addCallback([this](const GpioAction& action, const int& pin)
{
gpioActionCallback(action, pin);
});
_discoveryTopic = _preferences->getString(preference_mqtt_hass_discovery, "");
_offEnabled = _preferences->getBool(preference_official_hybrid, false);
@@ -334,11 +395,6 @@ bool NukiNetwork::update()
{
_mqttConnectCounter = 0;
if(_firstDisconnected) {
_firstDisconnected = false;
_device->mqttDisconnect(true);
}
if(!_webEnabled) forceEnableWebServer = true;
if(_restartOnDisconnect && (esp_timer_get_time() / 1000) > 60000) restartEsp(RestartReason::RestartOnDisconnectWatchdog);
@@ -369,18 +425,17 @@ bool NukiNetwork::update()
_logIp = false;
Log->print(F("IP: "));
Log->println(_device->localIP());
_firstDisconnected = true;
}
if(!_device->mqttConnected() && _device->isConnected())
while(!_mqttConnected && _device->isConnected())
{
delay(2000);
_mqttConnectCounter++;
return false;
}
if(!_mqttConnected && _device->isConnected())
{
bool success = reconnect();
if(!success)
{
delay(2000);
_mqttConnectCounter++;
return false;
}
_mqttConnectCounter = 0;
if(forceEnableWebServer && !_webEnabled)
{
@@ -392,7 +447,7 @@ bool NukiNetwork::update()
delay(2000);
}
if(!_device->mqttConnected() || !_device->isConnected())
if(!_mqttConnected || !_device->isConnected())
{
if(_networkTimeout > 0 && (ts - _lastConnectedTs > _networkTimeout * 1000) && ts > 60000)
{
@@ -508,131 +563,91 @@ bool NukiNetwork::update()
return true;
}
void NukiNetwork::onMqttConnect(const bool &sessionPresent)
void NukiNetwork::mqtt_event_handler_cb(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
_connectReplyReceived = true;
_inst->mqtt_event_handler(handler_args, base, event_id, event_data);
}
void NukiNetwork::onMqttDisconnect(const espMqttClientTypes::DisconnectReason &reason)
void NukiNetwork::mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
_connectReplyReceived = false;
static const char *MQTT_TAG = "mqtt";
Log->print("MQTT disconnected. Reason: ");
switch(reason)
{
case espMqttClientTypes::DisconnectReason::USER_OK:
Log->println(F("USER_OK"));
break;
case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION:
Log->println(F("MQTT_UNACCEPTABLE_PROTOCOL_VERSION"));
break;
case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED:
Log->println(F("MQTT_IDENTIFIER_REJECTED"));
break;
case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE:
Log->println(F("MQTT_SERVER_UNAVAILABLE"));
break;
case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS:
Log->println(F("MQTT_MALFORMED_CREDENTIALS"));
break;
case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED:
Log->println(F("MQTT_NOT_AUTHORIZED"));
break;
case espMqttClientTypes::DisconnectReason::TLS_BAD_FINGERPRINT:
Log->println(F("TLS_BAD_FINGERPRINT"));
break;
case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED:
Log->println(F("TCP_DISCONNECTED"));
break;
default:
Log->println(F("Unknown"));
break;
ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = (esp_mqtt_event_t*)event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_CONNECTED");
_mqttConnected = true;
reconnect();
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DISCONNECTED");
_mqttConnected = false;
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
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);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
ESP_LOGI(MQTT_TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(MQTT_TAG, "Other event id:%d", event->event_id);
break;
}
}
bool NukiNetwork::reconnect()
{
_mqttConnectionState = 0;
while (!_device->mqttConnected() && (esp_timer_get_time() / 1000) > _nextReconnect)
if (_mqttConnected)
{
if(strcmp(_mqttBrokerAddr, "") == 0)
Log->println(F("MQTT connected"));
_mqttConnectedTs = millis();
_mqttConnectionState = 1;
delay(100);
for(const String& topic : _subscribedTopics)
{
Log->println(F("MQTT Broker not configured, aborting connection attempt."));
_nextReconnect = (esp_timer_get_time() / 1000) + 5000;
return false;
esp_mqtt_client_subscribe(_mqttClient, topic.c_str(), MQTT_QOS_LEVEL);
}
Log->println(F("Attempting MQTT connection"));
_connectReplyReceived = false;
if(strlen(_mqttUser) == 0)
if(_firstConnect)
{
Log->println(F("MQTT: Connecting without credentials"));
}
else
{
Log->print(F("MQTT: Connecting with user: ")); Log->println(_mqttUser);
_device->mqttSetCredentials(_mqttUser, _mqttPass);
}
_device->setWill(_mqttConnectionStateTopic, 1, true, _lastWillPayload);
_device->mqttSetServer(_mqttBrokerAddr, _mqttPort);
_device->mqttConnect();
int64_t timeout = (esp_timer_get_time() / 1000) + 60000;
while(!_connectReplyReceived && (esp_timer_get_time() / 1000) < timeout)
{
delay(50);
_device->update();
if(_keepAliveCallback != nullptr)
_firstConnect = false;
publishString(_maintenancePathPrefix, mqtt_topic_network_device, _device->deviceName().c_str(), true);
for(const auto& it : _initTopics)
{
_keepAliveCallback();
esp_mqtt_client_publish(_mqttClient, it.first.c_str(), it.second.c_str(), 0, MQTT_QOS_LEVEL, 1);
}
}
if (_device->mqttConnected())
{
Log->println(F("MQTT connected"));
_mqttConnectedTs = millis();
_mqttConnectionState = 1;
delay(100);
_device->mqttOnMessage(NukiNetwork::onMqttDataReceivedCallback);
for(const String& topic : _subscribedTopics)
{
_device->mqttSubscribe(topic.c_str(), MQTT_QOS_LEVEL);
}
if(_firstConnect)
{
_firstConnect = false;
publishString(_maintenancePathPrefix, mqtt_topic_network_device, _device->deviceName().c_str(), true);
for(const auto& it : _initTopics)
{
_device->mqttPublish(it.first.c_str(), MQTT_QOS_LEVEL, true, it.second.c_str());
}
}
publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online", true);
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_ip, _device->localIP().c_str(), true);
publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online", true);
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_ip, _device->localIP().c_str(), true);
_mqttConnectionState = 2;
for(const auto& callback : _reconnectedCallbacks)
{
callback();
}
}
else
_mqttConnectionState = 2;
for(const auto& callback : _reconnectedCallbacks)
{
Log->print(F("MQTT connect failed, rc="));
_device->printError();
_mqttConnectionState = 0;
_nextReconnect = (esp_timer_get_time() / 1000) + 5000;
//_device->mqttDisconnect(true);
callback();
}
}
else
{
_mqttConnectionState = 0;
}
return _mqttConnectionState > 0;
}
@@ -683,34 +698,20 @@ void NukiNetwork::registerMqttReceiver(MqttReceiver* receiver)
_mqttReceivers.push_back(receiver);
}
void NukiNetwork::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
void NukiNetwork::onMqttDataReceived(const char* topic, const uint8_t* payload, size_t& len)
{
uint8_t value[800] = {0};
if((_mqttConnectedTs == -1 || (millis() - _mqttConnectedTs < 2000)) && topic) return;
size_t l = min(len, sizeof(value)-1);
for(int i=0; i<l; i++)
{
value[i] = payload[i];
}
_inst->onMqttDataReceived(properties, topic, value, len, index, total);
}
void NukiNetwork::onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total)
{
if(_mqttConnectedTs == -1 || (millis() - _mqttConnectedTs < 2000)) return;
parseGpioTopics(properties, topic, payload, len, index, total);
parseGpioTopics(topic, payload, len);
for(auto receiver : _mqttReceivers)
{
receiver->onMqttDataReceived(topic, (byte*)payload, index);
receiver->onMqttDataReceived(topic, (byte*)payload, len);
}
}
void NukiNetwork::parseGpioTopics(const espMqttClientTypes::MessageProperties &properties, const char *topic, const uint8_t *payload, size_t& len, size_t& index, size_t& total)
void NukiNetwork::parseGpioTopics(const char *topic, const uint8_t *payload, size_t& len)
{
char gpioPath[250];
buildMqttPath(gpioPath, {_lockPath.c_str(), mqtt_topic_gpio_prefix, mqtt_topic_gpio_pin});
@@ -756,11 +757,6 @@ int NukiNetwork::mqttConnectionState()
return _mqttConnectionState;
}
bool NukiNetwork::encryptionSupported()
{
return _device->supportsEncryption();
}
bool NukiNetwork::mqttRecentlyConnected()
{
return _mqttConnectedTs != -1 && (millis() - _mqttConnectedTs < 6000);
@@ -779,7 +775,7 @@ void NukiNetwork::publishFloat(const char* prefix, const char* topic, const floa
dtostrf(value, 0, precision, str);
char path[200] = {0};
buildMqttPath(path, { prefix, topic });
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
esp_mqtt_client_publish(_mqttClient, path, str, 0, MQTT_QOS_LEVEL, retain);
}
void NukiNetwork::publishInt(const char* prefix, const char *topic, const int value, bool retain)
@@ -788,7 +784,7 @@ void NukiNetwork::publishInt(const char* prefix, const char *topic, const int va
itoa(value, str, 10);
char path[200] = {0};
buildMqttPath(path, { prefix, topic });
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
esp_mqtt_client_publish(_mqttClient, path, str, 0, MQTT_QOS_LEVEL, retain);
}
void NukiNetwork::publishUInt(const char* prefix, const char *topic, const unsigned int value, bool retain)
@@ -797,7 +793,7 @@ void NukiNetwork::publishUInt(const char* prefix, const char *topic, const unsig
utoa(value, str, 10);
char path[200] = {0};
buildMqttPath(path, { prefix, topic });
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
esp_mqtt_client_publish(_mqttClient, path, str, 0, MQTT_QOS_LEVEL, retain);
}
void NukiNetwork::publishULong(const char* prefix, const char *topic, const unsigned long value, bool retain)
@@ -806,7 +802,7 @@ void NukiNetwork::publishULong(const char* prefix, const char *topic, const unsi
utoa(value, str, 10);
char path[200] = {0};
buildMqttPath(path, { prefix, topic });
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
esp_mqtt_client_publish(_mqttClient, path, str, 0, MQTT_QOS_LEVEL, retain);
}
void NukiNetwork::publishLongLong(const char* prefix, const char *topic, int64_t value, bool retain)
@@ -827,7 +823,7 @@ void NukiNetwork::publishLongLong(const char* prefix, const char *topic, int64_t
}
char path[200] = {0};
buildMqttPath(path, { prefix, topic });
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, result);
esp_mqtt_client_publish(_mqttClient, path, result, 0, MQTT_QOS_LEVEL, retain);
}
void NukiNetwork::publishBool(const char* prefix, const char *topic, const bool value, bool retain)
@@ -836,14 +832,14 @@ void NukiNetwork::publishBool(const char* prefix, const char *topic, const bool
str[0] = value ? '1' : '0';
char path[200] = {0};
buildMqttPath(path, { prefix, topic });
_device->mqttPublish(path, MQTT_QOS_LEVEL, retain, str);
esp_mqtt_client_publish(_mqttClient, path, str, 0, MQTT_QOS_LEVEL, retain);
}
bool NukiNetwork::publishString(const char* prefix, const char *topic, const char *value, bool retain)
{
char path[200] = {0};
buildMqttPath(path, { prefix, topic });
return _device->mqttPublish(path, MQTT_QOS_LEVEL, retain, value) > 0;
return esp_mqtt_client_publish(_mqttClient, path, value, 0, MQTT_QOS_LEVEL, retain) > 0;
}
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)
@@ -899,7 +895,7 @@ void NukiNetwork::publishHASSConfig(char* deviceType, const char* baseTopic, cha
path.concat(uidString);
path.concat("/smartlock/config");
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
// Battery critical
publishHassTopic("binary_sensor",
@@ -1755,7 +1751,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
json["options"][4] = "Intelligent";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "fob_action_1", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -1773,7 +1769,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
json["options"][4] = "Intelligent";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "fob_action_2", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -1791,7 +1787,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
json["options"][4] = "Intelligent";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "fob_action_3", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -1808,7 +1804,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
json["options"][3] = "Slowest";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "advertising_mode", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -1869,7 +1865,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "timezone", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2019,7 +2015,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
json["options"][6] = "Show Status";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "single_button_press_action", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2039,7 +2035,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
json["options"][6] = "Show Status";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "double_button_press_action", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2083,7 +2079,7 @@ void NukiNetwork::publishHASSConfigAdditionalLockEntities(char *deviceType, cons
json["options"][2] = "Lithium";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "battery_type", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2516,7 +2512,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["event_types"][1] = "ringlocked";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("event", "ring", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
if((int)basicOpenerConfigAclPrefs[5] == 1)
{
@@ -2700,7 +2696,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][5] = "Ring";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "fob_action_1", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2719,7 +2715,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][5] = "Ring";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "fob_action_2", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2738,7 +2734,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][5] = "Ring";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "fob_action_3", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2755,7 +2751,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][3] = "Slowest";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "advertising_mode", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2816,7 +2812,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "timezone", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -2845,7 +2841,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][15] = "Spare";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "operating_mode", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3055,7 +3051,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][7] = "CM & RTO & Ring";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "doorbell_suppression", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3099,7 +3095,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][3] = "Sound 3";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "sound_ring", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3116,7 +3112,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][3] = "Sound 3";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "sound_open", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3133,7 +3129,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][3] = "Sound 3";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "sound_rto", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3150,7 +3146,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][3] = "Sound 3";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "sound_cm", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3199,7 +3195,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][7] = "Open";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "single_button_press_action", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3220,7 +3216,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][7] = "Open";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "double_button_press_action", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3236,7 +3232,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
json["options"][2] = "Lithium";
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath("select", "battery_type", uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
else
{
@@ -3411,7 +3407,7 @@ void NukiNetwork::publishHassTopic(const String& mqttDeviceType,
json = createHassJson(uidString, uidStringPostfix, displayName, name, baseTopic, stateTopic, deviceType, deviceClass, stateClass, entityCat, commandTopic, additionalEntries);
serializeJson(json, _buffer, _bufferSize);
String path = createHassTopicPath(mqttDeviceType, mqttDeviceName, uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
esp_mqtt_client_publish(_mqttClient, path.c_str(), _buffer, 0, MQTT_QOS_LEVEL, 1);
}
}
@@ -3434,7 +3430,7 @@ void NukiNetwork::removeHassTopic(const String& mqttDeviceType, const String& mq
if (_discoveryTopic != "")
{
String path = createHassTopicPath(mqttDeviceType, mqttDeviceName, uidString);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, "");
esp_mqtt_client_publish(_mqttClient, path.c_str(), "", 0, MQTT_QOS_LEVEL, 1);
}
}
@@ -3442,7 +3438,7 @@ void NukiNetwork::removeTopic(const String& mqttPath, const String& mqttTopic)
{
String path = mqttPath;
path.concat(mqttTopic);
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, "");
esp_mqtt_client_publish(_mqttClient, path.c_str(), "", 0, MQTT_QOS_LEVEL, 1);
#ifdef DEBUG_NUKIHUB
Log->print(F("Removing MQTT topic: "));
@@ -3812,7 +3808,7 @@ void NukiNetwork::timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* st
uint16_t NukiNetwork::subscribe(const char *topic, uint8_t qos)
{
return _device->mqttSubscribe(topic, qos);
return esp_mqtt_client_subscribe(_mqttClient, topic, qos);
}
void NukiNetwork::addReconnectedCallback(std::function<void()> reconnectedCallback)
@@ -3822,7 +3818,7 @@ void NukiNetwork::addReconnectedCallback(std::function<void()> reconnectedCallba
void NukiNetwork::disableMqtt()
{
_device->disableMqtt();
esp_mqtt_client_disconnect(_mqttClient);
_mqttEnabled = false;
}

View File

@@ -10,6 +10,7 @@
#ifndef NUKI_HUB_UPDATER
#include "MqttReceiver.h"
#include "mqtt_client.h"
#include "MqttTopics.h"
#include "Gpio.h"
#include <ArduinoJson.h>
@@ -84,7 +85,6 @@ public:
void timeZoneIdToString(const Nuki::TimeZoneId timeZoneId, char* str);
int mqttConnectionState(); // 0 = not connected; 1 = connected; 2 = connected and mqtt processed
bool encryptionSupported();
bool mqttRecentlyConnected();
bool pathEquals(const char* prefix, const char* path, const char* referencePath);
uint16_t subscribe(const char* topic, uint8_t qos);
@@ -115,9 +115,10 @@ private:
bool _offEnabled = false;
#ifndef NUKI_HUB_UPDATER
static void onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
void onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
void parseGpioTopics(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
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 gpioActionCallback(const GpioAction& action, const int& pin);
String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
@@ -134,10 +135,6 @@ private:
const String& commandTopic = "",
std::vector<std::pair<char*, char*>> additionalEntries = {}
);
void onMqttConnect(const bool& sessionPresent);
void onMqttDisconnect(const espMqttClientTypes::DisconnectReason& reason);
void buildMqttPath(char* outPath, std::initializer_list<const char*> paths);
const char* _lastWillPayload = "offline";
@@ -146,13 +143,18 @@ private:
String _discoveryTopic;
Gpio* _gpio;
int _mqttConnectionState = 0;
bool _mqttConnected = false;
int _mqttConnectCounter = 0;
int _mqttPort = 1883;
long _mqttConnectedTs = -1;
bool _connectReplyReceived = false;
bool _firstDisconnected = true;
esp_mqtt_client_handle_t _mqttClient;
char _ca[TLS_CA_MAX_SIZE] = {0};
char _cert[TLS_CERT_MAX_SIZE] = {0};
char _key[TLS_KEY_MAX_SIZE] = {0};
int64_t _nextReconnect = 0;
char _mqttBrokerAddr[101] = {0};

View File

@@ -2786,9 +2786,9 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
printInputField(&response, "HASSDISCOVERY", "Home Assistant discovery topic (empty to disable; usually homeassistant)", _preferences->getString(preference_mqtt_hass_discovery).c_str(), 30, "");
printInputField(&response, "HASSCUURL", "Home Assistant device configuration URL (empty to use http://LOCALIP; fill when using a reverse proxy for example)", _preferences->getString(preference_mqtt_hass_cu_url).c_str(), 261, "");
if(_preferences->getBool(preference_opener_enabled, false)) printCheckBox(&response, "OPENERCONT", "Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode", _preferences->getBool(preference_opener_continuous_mode), "");
printTextarea(&response, "MQTTCA", "MQTT SSL CA Certificate (*, optional)", _preferences->getString(preference_mqtt_ca).c_str(), TLS_CA_MAX_SIZE, _network->encryptionSupported(), true);
printTextarea(&response, "MQTTCRT", "MQTT SSL Client Certificate (*, optional)", _preferences->getString(preference_mqtt_crt).c_str(), TLS_CERT_MAX_SIZE, _network->encryptionSupported(), true);
printTextarea(&response, "MQTTKEY", "MQTT SSL Client Key (*, optional)", _preferences->getString(preference_mqtt_key).c_str(), TLS_KEY_MAX_SIZE, _network->encryptionSupported(), true);
printTextarea(&response, "MQTTCA", "MQTT SSL CA Certificate (*, optional)", _preferences->getString(preference_mqtt_ca).c_str(), TLS_CA_MAX_SIZE, true, true);
printTextarea(&response, "MQTTCRT", "MQTT SSL Client Certificate (*, optional)", _preferences->getString(preference_mqtt_crt).c_str(), TLS_CERT_MAX_SIZE, true, true);
printTextarea(&response, "MQTTKEY", "MQTT SSL Client Key (*, optional)", _preferences->getString(preference_mqtt_key).c_str(), TLS_KEY_MAX_SIZE, true, true);
printDropDown(&response, "NWHW", "Network hardware", String(_preferences->getInt(preference_network_hardware)), getNetworkDetectionOptions(), "");
#ifndef CONFIG_IDF_TARGET_ESP32H2
printCheckBox(&response, "NWHWWIFIFB", "Disable fallback to Wi-Fi / Wi-Fi config portal", _preferences->getBool(preference_network_wifi_fallback_disabled), "");

View File

@@ -1,10 +1,6 @@
#include "EthernetDevice.h"
#include "../PreferencesKeys.h"
#include "../Logger.h"
#ifndef NUKI_HUB_UPDATER
#include "../MqttTopics.h"
#include "espMqttClient.h"
#endif
#include "../RestartReason.h"
EthernetDevice::EthernetDevice(const String& hostname, Preferences* preferences, const IPConfiguration* ipConfiguration, const std::string& deviceName, uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t ethtype, eth_clock_mode_t clock_mode)
@@ -50,54 +46,6 @@ EthernetDevice::EthernetDevice(const String &hostname,
init();
}
void EthernetDevice::init()
{
#ifndef NUKI_HUB_UPDATER
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);
size_t keyLength = _preferences->getString(preference_mqtt_key, _key, TLS_KEY_MAX_SIZE);
_useEncryption = caLength > 1; // length is 1 when empty
if(_useEncryption)
{
Log->println(F("MQTT over TLS."));
Log->println(_ca);
_mqttClientSecure = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
_mqttClientSecure->setCACert(_ca);
if(crtLength > 1 && keyLength > 1) // length is 1 when empty
{
Log->println(F("MQTT with client certificate."));
Log->println(_cert);
Log->println(_key);
_mqttClientSecure->setCertificate(_cert);
_mqttClientSecure->setPrivateKey(_key);
}
} else
{
Log->println(F("MQTT without TLS."));
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO);
}
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;
_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(*getMqttClient(), _path, mode);
}
#endif
}
const String EthernetDevice::deviceName() const
{
return _deviceName.c_str();
@@ -149,8 +97,6 @@ void EthernetDevice::initialize()
void EthernetDevice::update()
{
NetworkDevice::update();
if(_checkIpTs != -1)
{
if(_ipConfiguration->ipAddress() != ETH.localIP())
@@ -221,19 +167,12 @@ void EthernetDevice::onNetworkEvent(arduino_event_id_t event, arduino_event_info
}
}
void EthernetDevice::reconfigure()
{
delay(200);
restartEsp(RestartReason::ReconfigureETH);
}
bool EthernetDevice::supportsEncryption()
{
return true;
}
bool EthernetDevice::isConnected()
{
return _connected;

View File

@@ -11,9 +11,6 @@
#include <NetworkClientSecure.h>
#include <Preferences.h>
#include "NetworkDevice.h"
#ifndef NUKI_HUB_UPDATER
#include "espMqttClient.h"
#endif
class EthernetDevice : public NetworkDevice
{
@@ -50,7 +47,6 @@ public:
virtual void update();
virtual ReconnectStatus reconnect(bool force = false);
bool supportsEncryption() override;
virtual bool isConnected();
@@ -62,12 +58,10 @@ public:
private:
Preferences* _preferences;
void init();
void onDisconnected();
void onNetworkEvent(arduino_event_id_t event, arduino_event_info_t info);
bool _connected = false;
char* _path;
bool _hardwareInitialized = false;
const std::string _deviceName;
@@ -91,10 +85,4 @@ private:
eth_phy_type_t _type;
eth_clock_mode_t _clock_mode;
bool _useSpi = false;
#ifndef NUKI_HUB_UPDATER
char _ca[TLS_CA_MAX_SIZE] = {0};
char _cert[TLS_CERT_MAX_SIZE] = {0};
char _key[TLS_KEY_MAX_SIZE] = {0};
#endif
};

View File

@@ -1,179 +1,6 @@
#include <Arduino.h>
#include "NetworkDevice.h"
#include "../Logger.h"
void NetworkDevice::printError()
{
Log->print(F("Free Heap: "));
Log->println(ESP.getFreeHeap());
}
#ifndef NUKI_HUB_UPDATER
void NetworkDevice::update()
{
if (_mqttEnabled)
{
getMqttClient()->loop();
}
}
void NetworkDevice::mqttSetClientId(const char *clientId)
{
if (_useEncryption)
{
_mqttClientSecure->setClientId(clientId);
}
else
{
_mqttClient->setClientId(clientId);
}
}
void NetworkDevice::mqttSetCleanSession(bool cleanSession)
{
if (_useEncryption)
{
_mqttClientSecure->setCleanSession(cleanSession);
}
else
{
_mqttClient->setCleanSession(cleanSession);
}
}
void NetworkDevice::mqttSetKeepAlive(uint16_t keepAlive)
{
if (_useEncryption)
{
_mqttClientSecure->setKeepAlive(keepAlive);
}
else
{
_mqttClient->setKeepAlive(keepAlive);
}
}
uint16_t NetworkDevice::mqttPublish(const char *topic, uint8_t qos, bool retain, const char *payload)
{
return getMqttClient()->publish(topic, qos, retain, payload);
}
uint16_t NetworkDevice::mqttPublish(const char *topic, uint8_t qos, bool retain, const uint8_t *payload, size_t length)
{
return getMqttClient()->publish(topic, qos, retain, payload, length);
}
bool NetworkDevice::mqttConnected() const
{
return getMqttClient()->connected();
}
void NetworkDevice::mqttSetServer(const char *host, uint16_t port)
{
if (_useEncryption)
{
_mqttClientSecure->setServer(host, port);
}
else
{
_mqttClient->setServer(host, port);
}
}
bool NetworkDevice::mqttConnect()
{
return getMqttClient()->connect();
}
bool NetworkDevice::mqttDisconnect(bool force)
{
return getMqttClient()->disconnect(force);
}
void NetworkDevice::setWill(const char *topic, uint8_t qos, bool retain, const char *payload)
{
if (_useEncryption)
{
_mqttClientSecure->setWill(topic, qos, retain, payload);
}
else
{
_mqttClient->setWill(topic, qos, retain, payload);
}
}
void NetworkDevice::mqttSetCredentials(const char *username, const char *password)
{
if (_useEncryption)
{
_mqttClientSecure->setCredentials(username, password);
}
else
{
_mqttClient->setCredentials(username, password);
}
}
void NetworkDevice::mqttOnMessage(espMqttClientTypes::OnMessageCallback callback)
{
if (_useEncryption)
{
_mqttClientSecure->onMessage(callback);
}
else
{
_mqttClient->onMessage(callback);
}
}
void NetworkDevice::mqttOnConnect(espMqttClientTypes::OnConnectCallback callback)
{
if(_useEncryption)
{
_mqttClientSecure->onConnect(callback);
}
else
{
_mqttClient->onConnect(callback);
}
}
void NetworkDevice::mqttOnDisconnect(espMqttClientTypes::OnDisconnectCallback callback)
{
if (_useEncryption)
{
_mqttClientSecure->onDisconnect(callback);
}
else
{
_mqttClient->onDisconnect(callback);
}
}
uint16_t NetworkDevice::mqttSubscribe(const char *topic, uint8_t qos)
{
return getMqttClient()->subscribe(topic, qos);
}
void NetworkDevice::disableMqtt()
{
getMqttClient()->disconnect();
_mqttEnabled = false;
}
MqttClient *NetworkDevice::getMqttClient() const
{
if (_useEncryption)
{
return _mqttClientSecure;
}
else
{
return _mqttClient;
}
}
#else
void NetworkDevice::update()
{
}
#endif
}

View File

@@ -1,9 +1,4 @@
#pragma once
#ifndef NUKI_HUB_UPDATER
#include "espMqttClient.h"
#include "MqttClientSetup.h"
#endif
#include "IPConfiguration.h"
enum class ReconnectStatus
@@ -26,9 +21,6 @@ public:
virtual void initialize() = 0;
virtual ReconnectStatus reconnect(bool force = false) = 0;
virtual void reconfigure() = 0;
virtual void printError();
virtual bool supportsEncryption() = 0;
virtual void update();
virtual bool isConnected() = 0;
@@ -36,38 +28,7 @@ public:
virtual String localIP() = 0;
virtual String BSSIDstr() = 0;
#ifndef NUKI_HUB_UPDATER
virtual void mqttSetClientId(const char* clientId);
virtual void mqttSetCleanSession(bool cleanSession);
virtual void mqttSetKeepAlive(uint16_t keepAlive);
virtual uint16_t mqttPublish(const char* topic, uint8_t qos, bool retain, const char* payload);
virtual uint16_t mqttPublish(const char* topic, uint8_t qos, bool retain, const uint8_t* payload, size_t length);
virtual bool mqttConnected() const;
virtual void mqttSetServer(const char* host, uint16_t port);
virtual bool mqttConnect();
virtual bool mqttDisconnect(bool force);
virtual void setWill(const char* topic, uint8_t qos, bool retain, const char* payload);
virtual void mqttSetCredentials(const char* username, const char* password);
virtual void mqttOnMessage(espMqttClientTypes::OnMessageCallback callback);
virtual void mqttOnConnect(espMqttClientTypes::OnConnectCallback callback);
virtual void mqttOnDisconnect(espMqttClientTypes::OnDisconnectCallback callback);
virtual void disableMqtt();
virtual uint16_t mqttSubscribe(const char* topic, uint8_t qos);
#endif
protected:
#ifndef NUKI_HUB_UPDATER
espMqttClient *_mqttClient = nullptr;
espMqttClientSecure *_mqttClientSecure = nullptr;
bool _useEncryption = false;
bool _mqttEnabled = true;
MqttClient *getMqttClient() const;
#endif
protected:
const String _hostname;
const IPConfiguration* _ipConfiguration = nullptr;
};

View File

@@ -2,10 +2,6 @@
#include "WifiDevice.h"
#include "../PreferencesKeys.h"
#include "../Logger.h"
#ifndef NUKI_HUB_UPDATER
#include "../MqttTopics.h"
#include "espMqttClient.h"
#endif
#include "../RestartReason.h"
RTC_NOINIT_ATTR char WiFiDevice_reconfdetect[17];
@@ -16,51 +12,6 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* preferences, const I
_wm(preferences->getString(preference_cred_user, "").c_str(), preferences->getString(preference_cred_password, "").c_str())
{
_startAp = strcmp(WiFiDevice_reconfdetect, "reconfigure_wifi") == 0;
#ifndef NUKI_HUB_UPDATER
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);
size_t keyLength = preferences->getString(preference_mqtt_key, _key, TLS_KEY_MAX_SIZE);
_useEncryption = caLength > 1; // length is 1 when empty
if(_useEncryption)
{
Log->println(F("MQTT over TLS."));
Log->println(_ca);
_mqttClientSecure = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
_mqttClientSecure->setCACert(_ca);
if(crtLength > 1 && keyLength > 1) // length is 1 when empty
{
Log->println(F("MQTT with client certificate."));
Log->println(_cert);
Log->println(_key);
_mqttClientSecure->setCertificate(_cert);
_mqttClientSecure->setPrivateKey(_key);
}
} else
{
Log->println(F("MQTT without TLS."));
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO);
}
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;
_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(*getMqttClient(), _path, mode);
}
#endif
}
const String WifiDevice::deviceName() const
@@ -145,11 +96,6 @@ void WifiDevice::reconfigure()
restartEsp(RestartReason::ReconfigureWifi);
}
bool WifiDevice::supportsEncryption()
{
return true;
}
bool WifiDevice::isConnected()
{
return WiFi.isConnected();
@@ -212,4 +158,4 @@ String WifiDevice::BSSIDstr()
void WifiDevice::clearRtcInitVar(WiFiManager *)
{
memset(WiFiDevice_reconfdetect, 0, sizeof WiFiDevice_reconfdetect);
}
}

View File

@@ -5,9 +5,6 @@
#include <Preferences.h>
#include "NetworkDevice.h"
#include "WiFiManager.h"
#ifndef NUKI_HUB_UPDATER
#include "espMqttClient.h"
#endif
#include "IPConfiguration.h"
class WifiDevice : public NetworkDevice
@@ -20,7 +17,6 @@ public:
virtual void initialize();
virtual void reconfigure();
virtual ReconnectStatus reconnect(bool force = false);
bool supportsEncryption() override;
virtual bool isConnected();
@@ -40,12 +36,5 @@ private:
bool _startAp = false;
bool _isReconnecting = false;
char* _path;
int64_t _disconnectTs = 0;
#ifndef NUKI_HUB_UPDATER
char _ca[TLS_CA_MAX_SIZE] = {0};
char _cert[TLS_CERT_MAX_SIZE] = {0};
char _key[TLS_KEY_MAX_SIZE] = {0};
#endif
};