Import/Export config over MQTT

This commit is contained in:
iranl
2025-01-31 20:21:26 +01:00
parent 57456f42f9
commit 24bbe22e87
25 changed files with 1792 additions and 1206 deletions

View File

@@ -5,7 +5,7 @@
#define NUKI_HUB_VERSION "9.09"
#define NUKI_HUB_VERSION_INT (uint32_t)909
#define NUKI_HUB_BUILD "unknownbuildnr"
#define NUKI_HUB_DATE "2025-01-28"
#define NUKI_HUB_DATE "2025-02-04"
#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

@@ -223,7 +223,7 @@ void Gpio::loadPinConfiguration()
{
PinEntry entry;
entry.pin = serialized[i * 2];
Log->print(("Pin "));
Log->print("Pin ");
Log->println(entry.pin);
if(std::find(disabledPins.begin(), disabledPins.end(), entry.pin) == disabledPins.end())
@@ -234,14 +234,14 @@ void Gpio::loadPinConfiguration()
}
entry.role = (PinRole) serialized[(i * 2 + 1)];
Log->println("Not found in Ethernet disabled pins");
Log->print(("Role: "));
Log->print("Role: ");
Log->println(getRoleDescription(entry.role));
}
else
{
entry.role = PinRole::Ethernet;
Log->println("Found in Ethernet disabled pins");
Log->print(("Role: "));
Log->print("Role: ");
Log->println(getRoleDescription(entry.role));
}
if(entry.role != PinRole::Disabled)
@@ -359,7 +359,7 @@ const std::vector<int> Gpio::getDisabledPins() const
break;
}
Log->print(("GPIO Boot button and Ethernet disabled pins:"));
Log->print("GPIO Boot button and Ethernet disabled pins:");
for_each_n(disabledPins.begin(), disabledPins.size(),
[](int x)
{
@@ -382,7 +382,7 @@ void Gpio::savePinConfiguration(const std::vector<PinEntry> &pinConfiguration)
for(int i=0; i < len; i++)
{
const auto& entry = pinConfiguration[i];
Log->print(("Pin "));
Log->print("Pin ");
Log->println(entry.pin);
if(std::find(disabledPins.begin(), disabledPins.end(), entry.pin) != disabledPins.end())
@@ -390,7 +390,7 @@ void Gpio::savePinConfiguration(const std::vector<PinEntry> &pinConfiguration)
serialized[i * 2] = entry.pin;
serialized[i * 2 + 1] = (int8_t)PinRole::Ethernet;
Log->println("Found in Ethernet disabled pins");
Log->print(("Role: "));
Log->print("Role: ");
Log->println(getRoleDescription(PinRole::Ethernet));
}
@@ -401,7 +401,7 @@ void Gpio::savePinConfiguration(const std::vector<PinEntry> &pinConfiguration)
serialized[i * 2] = entry.pin;
serialized[i * 2 + 1] = (int8_t) entry.role;
Log->println("Not found in Ethernet disabled pins");
Log->print(("Role: "));
Log->print("Role: ");
Log->println(getRoleDescription(entry.role));
}
}

1005
src/ImportExport.cpp Normal file

File diff suppressed because it is too large Load Diff

45
src/ImportExport.h Normal file
View File

@@ -0,0 +1,45 @@
#pragma once
#include <Preferences.h>
#include "ArduinoJson.h"
#include <PsychicHttp.h>
class ImportExport
{
public:
explicit ImportExport(Preferences* preferences);
void exportHttpsJson(JsonDocument &json);
void exportMqttsJson(JsonDocument &json);
void exportNukiHubJson(JsonDocument &json, bool redacted = false, bool pairing = false, bool nuki = false, bool nukiOpener = false);
JsonDocument importJson(JsonDocument &doc);
int checkDuoAuth(PsychicRequest *request);
int checkDuoApprove();
bool startDuoAuth(char* pushType = (char*)"");
bool getDuoEnabled();
bool getBypassGPIOEnabled();
int getBypassGPIOHigh();
int getBypassGPIOLow();
void readSettings();
void setDuoCheckIP(String duoCheckIP);
void setDuoCheckId(String duoCheckId);
JsonDocument _duoSessions;
JsonDocument _sessionsOpts;
private:
void saveSessions();
Preferences* _preferences;
struct tm timeinfo;
bool _duoActiveRequest;
bool _duoEnabled = false;
bool _bypassGPIO = false;
int _bypassGPIOHigh = -1;
int _bypassGPIOLow = -1;
int64_t _duoRequestTS = 0;
String _duoTransactionId;
String _duoHost;
String _duoSkey;
String _duoIkey;
String _duoUser;
String _duoCheckId;
String _duoCheckIP;
};

View File

@@ -113,6 +113,11 @@
#define mqtt_topic_restart_reason_esp (char*)"/maintenance/restartReasonNukiEsp"
#define mqtt_topic_mqtt_connection_state (char*)"/maintenance/mqttConnectionState"
#define mqtt_topic_network_device (char*)"/maintenance/networkDevice"
#define mqtt_topic_nuki_hub_config_action (char*)"/configuration/action"
#define mqtt_topic_nuki_hub_config_action_command_result (char*)"/configuration/commandResult"
#define mqtt_topic_nuki_hub_config_json (char*)"/configuration/json"
#define mqtt_topic_hybrid_state (char*)"/hybridConnected"
#define mqtt_topic_gpio_prefix (char*)"/gpio"

View File

@@ -14,6 +14,7 @@
NukiNetwork* NukiNetwork::_inst = nullptr;
extern bool timeSynced;
extern bool wifiFallback;
extern bool disableNetwork;
extern bool forceEnableWebServer;
@@ -21,11 +22,12 @@ extern const uint8_t x509_crt_imported_bundle_bin_start[] asm("_binary_x509_crt_
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm("_binary_x509_crt_bundle_end");
#ifndef NUKI_HUB_UPDATER
NukiNetwork::NukiNetwork(Preferences *preferences, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize)
NukiNetwork::NukiNetwork(Preferences *preferences, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize, ImportExport* importExport)
: _preferences(preferences),
_gpio(gpio),
_buffer(buffer),
_bufferSize(bufferSize)
_bufferSize(bufferSize),
_importExport(importExport)
#else
NukiNetwork::NukiNetwork(Preferences *preferences)
: _preferences(preferences)
@@ -66,7 +68,7 @@ void NukiNetwork::setupDevice()
{
_ipConfiguration = new IPConfiguration(_preferences);
int hardwareDetect = _preferences->getInt(preference_network_hardware, 0);
Log->print(("Hardware detect: "));
Log->print("Hardware detect: ");
Log->println(hardwareDetect);
_firstBootAfterDeviceChange = _preferences->getBool(preference_ntw_reconfigure, false);
@@ -94,13 +96,13 @@ void NukiNetwork::setupDevice()
#ifndef CONFIG_IDF_TARGET_ESP32H2
if(!_firstBootAfterDeviceChange)
{
Log->println(("Failed to connect to network. Wi-Fi fallback is disabled, rebooting."));
Log->println("Failed to connect to network. Wi-Fi fallback is disabled, rebooting.");
wifiFallback = false;
sleep(5);
restartEsp(RestartReason::NetworkDeviceCriticalFailureNoWifiFallback);
}
Log->println(("Switching to Wi-Fi device as fallback."));
Log->println("Switching to Wi-Fi device as fallback.");
_networkDeviceType = NetworkDeviceType::WiFi;
#else
int custEth = _preferences->getInt(preference_network_custom_phy, 0);
@@ -124,7 +126,7 @@ void NukiNetwork::setupDevice()
_device = NetworkDeviceInstantiator::Create(_networkDeviceType, _hostname, _preferences, _ipConfiguration);
Log->print(("Network device: "));
Log->print("Network device: ");
Log->println(_device->deviceName());
#ifndef NUKI_HUB_UPDATER
@@ -223,7 +225,7 @@ void NukiNetwork::initialize()
strcpy(_hostnameArr, _hostname.c_str());
_device->initialize();
Log->print(("Host name: "));
Log->print("Host name: ");
Log->println(_hostname);
}
@@ -273,7 +275,7 @@ void NukiNetwork::initialize()
strcpy(_hostnameArr, _hostname.c_str());
_device->initialize();
Log->print(("Host name: "));
Log->print("Host name: ");
Log->println(_hostname);
String brokerAddr = _preferences->getString(preference_mqtt_broker);
@@ -300,9 +302,9 @@ void NukiNetwork::initialize()
}
}
Log->print(("MQTT Broker: "));
Log->print("MQTT Broker: ");
Log->print(_mqttBrokerAddr);
Log->print((":"));
Log->print(":");
Log->println(_mqttPort);
_device->mqttSetClientId(_hostnameArr);
@@ -314,7 +316,7 @@ void NukiNetwork::initialize()
if(rebGpio)
{
Log->println(("Rebuild MQTT GPIO structure"));
Log->println("Rebuild MQTT GPIO structure");
}
for (const auto &pinEntry: _gpio->pinConfiguration())
{
@@ -412,7 +414,7 @@ bool NukiNetwork::update()
if(_logIp && _device->isConnected() && !_device->localIP().equals("0.0.0.0"))
{
_logIp = false;
Log->print(("IP: "));
Log->print("IP: ");
Log->println(_device->localIP());
_firstDisconnected = true;
}
@@ -470,6 +472,12 @@ bool NukiNetwork::update()
_lastRssi = rssi;
}
}
if(_overwriteNukiHubConfigTS > 0 && espMillis() > _overwriteNukiHubConfigTS)
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_json, "--", true);
_overwriteNukiHubConfigTS = -1;
}
if(_lastMaintenanceTs == 0 || (ts - _lastMaintenanceTs) > 30000)
{
@@ -575,9 +583,9 @@ bool NukiNetwork::update()
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pin)).c_str(), mqtt_topic_gpio_state});
publishInt(_lockPath.c_str(), gpioPath, pinState, _retainGpio);
Log->print(("GPIO "));
Log->print("GPIO ");
Log->print(pin);
Log->print((" (Input) --> "));
Log->print(" (Input) --> ");
Log->println(pinState);
}
}
@@ -597,31 +605,31 @@ void NukiNetwork::onMqttDisconnect(const espMqttClientTypes::DisconnectReason &r
switch(reason)
{
case espMqttClientTypes::DisconnectReason::USER_OK:
Log->println(("USER_OK"));
Log->println("USER_OK");
break;
case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION:
Log->println(("MQTT_UNACCEPTABLE_PROTOCOL_VERSION"));
Log->println("MQTT_UNACCEPTABLE_PROTOCOL_VERSION");
break;
case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED:
Log->println(("MQTT_IDENTIFIER_REJECTED"));
Log->println("MQTT_IDENTIFIER_REJECTED");
break;
case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE:
Log->println(("MQTT_SERVER_UNAVAILABLE"));
Log->println("MQTT_SERVER_UNAVAILABLE");
break;
case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS:
Log->println(("MQTT_MALFORMED_CREDENTIALS"));
Log->println("MQTT_MALFORMED_CREDENTIALS");
break;
case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED:
Log->println(("MQTT_NOT_AUTHORIZED"));
Log->println("MQTT_NOT_AUTHORIZED");
break;
case espMqttClientTypes::DisconnectReason::TLS_BAD_FINGERPRINT:
Log->println(("TLS_BAD_FINGERPRINT"));
Log->println("TLS_BAD_FINGERPRINT");
break;
case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED:
Log->println(("TCP_DISCONNECTED"));
Log->println("TCP_DISCONNECTED");
break;
default:
Log->println(("Unknown"));
Log->println("Unknown");
break;
}
}
@@ -634,7 +642,7 @@ bool NukiNetwork::reconnect()
{
if(strcmp(_mqttBrokerAddr, "") == 0)
{
Log->println(("MQTT Broker not configured, aborting connection attempt."));
Log->println("MQTT Broker not configured, aborting connection attempt.");
_nextReconnect = espMillis() + 5000;
if(_device->isConnected())
@@ -644,17 +652,17 @@ bool NukiNetwork::reconnect()
return false;
}
Log->println(("Attempting MQTT connection"));
Log->println("Attempting MQTT connection");
_connectReplyReceived = false;
if(strlen(_mqttUser) == 0)
{
Log->println(("MQTT: Connecting without credentials"));
Log->println("MQTT: Connecting without credentials");
}
else
{
Log->print(("MQTT: Connecting with user: "));
Log->print("MQTT: Connecting with user: ");
Log->println(_mqttUser);
_device->mqttSetCredentials(_mqttUser, _mqttPass);
}
@@ -677,7 +685,7 @@ bool NukiNetwork::reconnect()
if (_device->mqttConnected())
{
Log->println(("MQTT connected"));
Log->println("MQTT connected");
_mqttConnectedTs = millis();
_mqttConnectionState = 1;
delay(100);
@@ -766,6 +774,18 @@ bool NukiNetwork::reconnect()
subscribe(_maintenancePathPrefix, mqtt_topic_update);
}
if(_preferences->getBool(preference_publish_config, false))
{
initTopic(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_json, "--");
}
if(_preferences->getBool(preference_config_from_mqtt, false) || _preferences->getBool(preference_publish_config, false))
{
initTopic(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action, "--");
subscribe(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action);
initTopic(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "--");
}
initTopic(_maintenancePathPrefix, mqtt_topic_webserver_action, "--");
subscribe(_maintenancePathPrefix, mqtt_topic_webserver_action);
initTopic(_maintenancePathPrefix, mqtt_topic_webserver_state, (_preferences->getBool(preference_webserver_enabled, true) || forceEnableWebServer ? "1" : "0"));
@@ -792,7 +812,7 @@ bool NukiNetwork::reconnect()
}
else
{
Log->print(("MQTT connect failed"));
Log->print("MQTT connect failed");
_mqttConnectionState = 0;
_nextReconnect = espMillis() + 5000;
//_device->mqttDisconnect(true);
@@ -911,14 +931,14 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
if(comparePrefixedPath(topic, mqtt_topic_reset) && strcmp(data, "1") == 0 && !mqttRecentlyConnected())
{
Log->println(("Restart requested via MQTT."));
Log->println("Restart requested via MQTT.");
clearWifiFallback();
delay(200);
restartEsp(RestartReason::RequestedViaMqtt);
}
else if(comparePrefixedPath(topic, mqtt_topic_update) && strcmp(data, "1") == 0 && _preferences->getBool(preference_update_from_mqtt, false) && !mqttRecentlyConnected())
{
Log->println(("Update requested via MQTT."));
Log->println("Update requested via MQTT.");
bool otaManifestSuccess = false;
JsonDocument doc;
@@ -959,13 +979,13 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
{
if(strcmp(NUKI_HUB_VERSION, doc["release"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["release"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["release"]["time"].as<const char*>()) == 0)
{
Log->println(("Nuki Hub is already on the latest release version, OTA update aborted."));
Log->println("Nuki Hub is already on the latest release version, OTA update aborted.");
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
Log->println(("Updating to latest release version."));
Log->println("Updating to latest release version.");
delay(200);
restartEsp(RestartReason::OTAReboot);
}
@@ -974,13 +994,13 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
{
if(strcmp(NUKI_HUB_VERSION, doc["beta"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["beta"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["beta"]["time"].as<const char*>()) == 0)
{
Log->println(("Nuki Hub is already on the latest beta version, OTA update aborted."));
Log->println("Nuki Hub is already on the latest beta version, OTA update aborted.");
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_BETA_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_BETA_RELEASE_BINARY_URL);
Log->println(("Updating to latest beta version."));
Log->println("Updating to latest beta version.");
delay(200);
restartEsp(RestartReason::OTAReboot);
}
@@ -989,13 +1009,13 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
{
if(strcmp(NUKI_HUB_VERSION, doc["master"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["master"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["master"]["time"].as<const char*>()) == 0)
{
Log->println(("Nuki Hub is already on the latest development version, OTA update aborted."));
Log->println("Nuki Hub is already on the latest development version, OTA update aborted.");
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_MASTER_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_MASTER_RELEASE_BINARY_URL);
Log->println(("Updating to latest developmemt version."));
Log->println("Updating to latest developmemt version.");
delay(200);
restartEsp(RestartReason::OTAReboot);
}
@@ -1004,13 +1024,13 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
{
if(strcmp(NUKI_HUB_VERSION, doc["release"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["release"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["release"]["time"].as<const char*>()) == 0)
{
Log->println(("Nuki Hub is already on the latest release version, OTA update aborted."));
Log->println("Nuki Hub is already on the latest release version, OTA update aborted.");
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
Log->println(("Updating to latest release version."));
Log->println("Updating to latest release version.");
delay(200);
restartEsp(RestartReason::OTAReboot);
}
@@ -1018,7 +1038,7 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
}
else
{
Log->println(("Failed to retrieve OTA manifest, OTA update aborted."));
Log->println("Failed to retrieve OTA manifest, OTA update aborted.");
}
}
else if(comparePrefixedPath(topic, mqtt_topic_webserver_action) && !mqttRecentlyConnected())
@@ -1035,7 +1055,7 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
{
return;
}
Log->println(("Webserver enabled, restarting."));
Log->println("Webserver enabled, restarting.");
_preferences->putBool(preference_webserver_enabled, true);
}
else if (strcmp(data, "0") == 0)
@@ -1044,20 +1064,184 @@ void NukiNetwork::onMqttDataReceived(const char* topic, byte* payload, const uns
{
return;
}
Log->println(("Webserver disabled, restarting."));
Log->println("Webserver disabled, restarting.");
_preferences->putBool(preference_webserver_enabled, false);
}
clearWifiFallback();
delay(200);
restartEsp(RestartReason::ReconfigureWebServer);
}
else if(comparePrefixedPath(topic, mqtt_topic_nuki_hub_config_action) && !mqttRecentlyConnected())
{
if(strcmp(data, "") == 0 || strcmp(data, "--") == 0)
{
return;
}
else
{
Log->println("JSON config update received");
JsonDocument doc;
DeserializationError error = deserializeJson(doc, data);
if (error)
{
Log->println("Invalid JSON for import/export");
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"jsonInvalid\"}", false);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action, "--", true);
}
else
{
if(_preferences->getBool(preference_cred_duo_approval, false))
{
if (!timeSynced)
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"duoTimeNotSynced\"}", false);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action, "--", true);
return;
}
else if (_importExport->startDuoAuth((char*)"Approve Nuki Hub setting change"))
{
int duoResult = 2;
while (duoResult == 2)
{
duoResult = _importExport->checkDuoApprove();
delay(2000);
esp_task_wdt_reset();
}
if (duoResult != 1)
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"duoApprovalFailed\"}", false);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action, "--", true);
return;
}
}
}
if(!doc["exportHTTPS"].isNull() && _device->isEncrypted())
{
if(_preferences->getBool(preference_publish_config, false))
{
if(_device->isEncrypted())
{
JsonDocument json;
_importExport->exportHttpsJson(json);
serializeJson(json, _buffer, _bufferSize);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_json, _buffer, false);
if (doc["exportHTTPS"].as<int>() > 0)
{
_overwriteNukiHubConfigTS = espMillis() + (doc["exportHTTPS"].as<int>() * 1000);
}
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttExportNotEncrypted\"}", false);
}
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttExportNotEnabled\"}", false);
}
}
else if(!doc["exportMQTTS"].isNull())
{
if(_preferences->getBool(preference_publish_config, false))
{
if(_device->isEncrypted())
{
JsonDocument json;
_importExport->exportMqttsJson(json);
serializeJson(json, _buffer, _bufferSize);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_json, _buffer, false);
if (doc["exportMQTTS"].as<int>() > 0)
{
_overwriteNukiHubConfigTS = espMillis() + (doc["exportMQTTS"].as<int>() * 1000);
}
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttExportNotEncrypted\"}", false);
}
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttExportNotEnabled\"}", false);
}
}
else if(!doc["exportNH"].isNull())
{
if(_preferences->getBool(preference_publish_config, false))
{
bool redacted = false;
if(!doc["redacted"].isNull())
{
if(_device->isEncrypted())
{
redacted = true;
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttExportNotEncrypted\"}", false);
}
}
bool pairing = false;
if(!doc["pairing"].isNull())
{
if(_device->isEncrypted())
{
pairing = true;
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttExportNotEncrypted\"}", false);
}
}
JsonDocument json;
_importExport->exportNukiHubJson(json, redacted, pairing, _preferences->getBool(preference_lock_enabled, true), _preferences->getBool(preference_opener_enabled, false));
serializeJson(json, _buffer, _bufferSize);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_json, _buffer, false);
if (doc["exportNH"].as<int>() > 0)
{
_overwriteNukiHubConfigTS = espMillis() + (doc["exportNH"].as<int>() * 1000);
}
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttExportNotEnabled\"}", false);
}
}
else
{
if(_preferences->getBool(preference_config_from_mqtt, false))
{
JsonDocument json;
json = _importExport->importJson(doc);
serializeJson(json, _buffer, _bufferSize);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_json, _buffer, false);
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action, "--", true);
delay(200);
restartEsp(RestartReason::ConfigurationUpdated);
}
else
{
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action_command_result, "{\"error\": \"mqttImportNotEnabled\"}", false);
}
}
publishString(_maintenancePathPrefix, mqtt_topic_nuki_hub_config_action, "--", true);
}
}
}
}
void NukiNetwork::parseGpioTopics(const espMqttClientTypes::MessageProperties &properties, const char *topic, const uint8_t *payload, size_t& len, size_t& index, size_t& total)
{
char gpioPath[250];
buildMqttPath(gpioPath, {_lockPath.c_str(), mqtt_topic_gpio_prefix, mqtt_topic_gpio_pin});
// /nuki_t/gpio/pin_17/state
size_t gpioLen = strlen(gpioPath);
if(strncmp(gpioPath, topic, gpioLen) == 0)
{
@@ -1073,9 +1257,9 @@ void NukiNetwork::parseGpioTopics(const espMqttClientTypes::MessageProperties &p
if(_gpio->getPinRole(pin) == PinRole::GeneralOutput)
{
const uint8_t pinState = strcmp((const char*)payload, "1") == 0 ? HIGH : LOW;
Log->print(("GPIO "));
Log->print("GPIO ");
Log->print(pin);
Log->print((" (Output) --> "));
Log->print(" (Output) --> ");
Log->println(pinState);
digitalWrite(pin, pinState);
}
@@ -1177,7 +1361,7 @@ void NukiNetwork::removeTopic(const String& mqttPath, const String& mqttTopic)
publish(path.c_str(), "", true);
#ifdef DEBUG_NUKIHUB
Log->print(("Removing MQTT topic: "));
Log->print("Removing MQTT topic: ");
Log->println(path.c_str());
#endif
}

View File

@@ -16,6 +16,7 @@
#include <ArduinoJson.h>
#include "NukiConstants.h"
#include "HomeAssistantDiscovery.h"
#include "ImportExport.h"
#endif
class NukiNetwork
@@ -42,7 +43,7 @@ public:
#ifdef NUKI_HUB_UPDATER
explicit NukiNetwork(Preferences* preferences);
#else
explicit NukiNetwork(Preferences* preferences, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize);
explicit NukiNetwork(Preferences* preferences, Gpio* gpio, const String& maintenancePathPrefix, char* buffer, size_t bufferSize, ImportExport* importExport);
void registerMqttReceiver(MqttReceiver* receiver);
void disableAutoRestarts(); // disable on OTA start
@@ -128,13 +129,14 @@ private:
String _lockPath;
HomeAssistantDiscovery* _hadiscovery = nullptr;
ImportExport* _importExport;
Gpio* _gpio;
int _mqttConnectionState = 0;
int _mqttConnectCounter = 0;
int _mqttPort = 1883;
long _mqttConnectedTs = -1;
long _overwriteNukiHubConfigTS = -1;
bool _connectReplyReceived = false;
bool _firstDisconnected = true;

View File

@@ -237,7 +237,7 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
return;
}
Log->print(("Lock action received: "));
Log->print("Lock action received: ");
Log->println(data);
LockActionResult lockActionResult = LockActionResult::Failed;
if(_lockActionReceivedCallback != NULL)

View File

@@ -175,7 +175,7 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con
return;
}
Log->print(("Opener action received: "));
Log->print("Opener action received: ");
Log->println(data);
LockActionResult lockActionResult = LockActionResult::Failed;
if(_lockActionReceivedCallback != NULL)
@@ -667,12 +667,12 @@ void NukiNetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::Log
{
if((log.data[0] & 3) == 0)
{
Log->println(("Nuki opener: Ring detected (Locked)"));
Log->println("Nuki opener: Ring detected (Locked)");
publishRing(true);
}
else
{
Log->println(("Nuki opener: Ring detected (Open)"));
Log->println("Nuki opener: Ring detected (Open)");
publishRing(false);
}
}

View File

@@ -86,14 +86,14 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
memset(&str, 0, sizeof(str));
Log->println("Official Nuki change received");
Log->print(("Topic: "));
Log->print("Topic: ");
Log->println(topic);
Log->print(("Value: "));
Log->print("Value: ");
Log->println(value);
if(strcmp(topic, mqtt_topic_official_connected) == 0)
{
Log->print(("Connected: "));
Log->print("Connected: ");
Log->println((strcmp(value, "true") == 0 ? 1 : 0));
offConnected = (strcmp(value, "true") == 0 ? 1 : 0);
_publisher->publishBool(mqtt_topic_hybrid_state, offConnected, true);
@@ -102,12 +102,12 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
{
offState = atoi(value);
_statusUpdated = true;
Log->println(("Lock: Updating status on Hybrid state change"));
Log->println("Lock: Updating status on Hybrid state change");
_publisher->publishBool(mqtt_topic_hybrid_state, offConnected, true);
NukiLock::lockstateToString((NukiLock::LockState)offState, str);
_publisher->publishString(mqtt_topic_lock_state, str, true);
Log->print(("Lockstate: "));
Log->print("Lockstate: ");
Log->println(str);
_offStateToPublish = (NukiLock::LockState)offState;
@@ -117,11 +117,11 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
{
offDoorsensorState = atoi(value);
_statusUpdated = true;
Log->println(("Lock: Updating status on Hybrid door sensor state change"));
Log->println("Lock: Updating status on Hybrid door sensor state change");
_publisher->publishBool(mqtt_topic_lock_status_updated, _statusUpdated, true);
NukiLock::doorSensorStateToString((NukiLock::DoorSensorState)offDoorsensorState, str);
Log->print(("Doorsensor state: "));
Log->print("Doorsensor state: ");
Log->println(str);
_publisher->publishString(mqtt_topic_lock_door_sensor_state, str, true);
@@ -130,7 +130,7 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
{
offCritical = (strcmp(value, "true") == 0 ? 1 : 0);
Log->print(("Battery critical: "));
Log->print("Battery critical: ");
Log->println(offCritical);
if(!_disableNonJSON)
@@ -143,7 +143,7 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
{
offCharging = (strcmp(value, "true") == 0 ? 1 : 0);
Log->print(("Battery charging: "));
Log->print("Battery charging: ");
Log->println(offCharging);
if(!_disableNonJSON)
@@ -156,7 +156,7 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
{
offChargeState = atoi(value);
Log->print(("Battery level: "));
Log->print("Battery level: ");
Log->println(offChargeState);
if(!_disableNonJSON)

View File

@@ -12,14 +12,16 @@
NukiOpenerWrapper* nukiOpenerInst;
Preferences* nukiOpenerPreferences = nullptr;
NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkOpener* network, Gpio* gpio, Preferences* preferences)
NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkOpener* network, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize)
: _deviceName(deviceName),
_deviceId(deviceId),
_nukiOpener(deviceName, _deviceId->get()),
_bleScanner(scanner),
_network(network),
_gpio(gpio),
_preferences(preferences)
_preferences(preferences),
_buffer(buffer),
_bufferSize(bufferSize)
{
Log->print("Device id opener: ");
Log->println(_deviceId->get());
@@ -81,7 +83,7 @@ void NukiOpenerWrapper::readSettings()
#else
if(pwrLvl >= 20)
{
powerLevel = ESP_PWR_LVL_P20;
powerLevel = ESP_PWR_LVL_P20;
}
else if(pwrLvl >= 18)
{
@@ -197,11 +199,11 @@ void NukiOpenerWrapper::readSettings()
_preferences->putInt(preference_restart_ble_beacon_lost, _restartBeaconTimeout);
}
Log->print(("Opener state interval: "));
Log->print("Opener state interval: ");
Log->print(_intervalLockstate);
Log->print((" | Battery interval: "));
Log->print(" | Battery interval: ");
Log->print(_intervalBattery);
Log->print((" | Publish auth data: "));
Log->print(" | Publish auth data: ");
Log->println(_publishAuthData ? "yes" : "no");
if(!_publishAuthData)
@@ -218,7 +220,7 @@ void NukiOpenerWrapper::update()
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
if(!_paired)
{
Log->println(("Nuki opener start pairing"));
Log->println("Nuki opener start pairing");
_network->publishBleAddress("");
Nuki::AuthorizationIdType idType = _preferences->getBool(preference_register_opener_as_app) ?
@@ -227,7 +229,7 @@ void NukiOpenerWrapper::update()
if(_nukiOpener.pairNuki(idType) == NukiOpener::PairingResult::Success)
{
Log->println(("Nuki opener paired"));
Log->println("Nuki opener paired");
_paired = true;
_network->publishBleAddress(_nukiOpener.getBleAddress().toString());
}
@@ -270,14 +272,14 @@ void NukiOpenerWrapper::update()
_network->publishCommandResult(resultStr);
Log->print(("Opener action result: "));
Log->print("Opener action result: ");
Log->println(resultStr);
if(cmdResult != Nuki::CmdResult::Success)
{
Log->print(("Opener: Last command failed, retrying after "));
Log->print("Opener: Last command failed, retrying after ");
Log->print(_retryDelay);
Log->print((" milliseconds. Retry "));
Log->print(" milliseconds. Retry ");
Log->print(retryCount + 1);
Log->print(" of ");
Log->println(_nrOfRetries);
@@ -297,7 +299,7 @@ void NukiOpenerWrapper::update()
_network->publishRetry("--");
retryCount = 0;
_statusUpdated = true;
Log->println(("Opener: updating status after action"));
Log->println("Opener: updating status after action");
_statusUpdatedTs = ts;
if(_intervalLockstate > 10)
{
@@ -306,7 +308,7 @@ void NukiOpenerWrapper::update()
}
else
{
Log->println(("Opener: Maximum number of retries exceeded, aborting."));
Log->println("Opener: Maximum number of retries exceeded, aborting.");
_network->publishRetry("failed");
retryCount = 0;
_nextLockAction = (NukiOpener::LockAction) 0xff;
@@ -432,11 +434,6 @@ void NukiOpenerWrapper::deactivateCM()
_nextLockAction = NukiOpener::LockAction::DeactivateCM;
}
bool NukiOpenerWrapper::isPinSet()
{
return _nukiOpener.getSecurityPincode() != 0;
}
bool NukiOpenerWrapper::isPinValid()
{
return _preferences->getInt(preference_opener_pin_status, 4) == 1;
@@ -475,7 +472,7 @@ bool NukiOpenerWrapper::updateKeyTurnerState()
while(result != Nuki::CmdResult::Success && retryCount < _nrOfRetries + 1)
{
Log->print(("Result (attempt "));
Log->print("Result (attempt ");
Log->print(retryCount + 1);
Log->print("): ");
result =_nukiOpener.requestOpenerState(&_keyTurnerState);
@@ -494,7 +491,7 @@ bool NukiOpenerWrapper::updateKeyTurnerState()
postponeBleWatchdog();
if(_retryLockstateCount < _nrOfRetries + 1)
{
Log->print(("Query opener state retrying in "));
Log->print("Query opener state retrying in ");
Log->print(_retryDelay);
Log->println("ms");
_nextLockStateUpdateTs = espMillis() + _retryDelay;
@@ -517,7 +514,7 @@ bool NukiOpenerWrapper::updateKeyTurnerState()
_lastKeyTurnerState.lockState == NukiOpener::LockState::Locked &&
_lastKeyTurnerState.nukiState == _keyTurnerState.nukiState)
{
Log->println(("Nuki opener: Ring detected (Locked)"));
Log->println("Nuki opener: Ring detected (Locked)");
_network->publishRing(true);
}
else
@@ -527,17 +524,17 @@ bool NukiOpenerWrapper::updateKeyTurnerState()
_keyTurnerState.lockState == NukiOpener::LockState::Open &&
_keyTurnerState.trigger == NukiOpener::Trigger::Manual)
{
Log->println(("Nuki opener: Ring detected (Open)"));
Log->println("Nuki opener: Ring detected (Open)");
_network->publishRing(false);
}
if(_publishAuthData)
{
Log->println(("Publishing auth data"));
Log->println("Publishing auth data");
updateAuthData(false);
Log->println(("Done publishing auth data"));
Log->println("Done publishing auth data");
}
if(_keyTurnerState.lockState == NukiOpener::LockState::Undefined)
{
if (_nextLockStateUpdateTs > espMillis() + 60000)
@@ -552,12 +549,12 @@ bool NukiOpenerWrapper::updateKeyTurnerState()
if((_keyTurnerState.lockState == NukiOpener::LockState::Open || _keyTurnerState.lockState == NukiOpener::LockState::Opening) && espMillis() < _statusUpdatedTs + 10000)
{
updateStatus = true;
Log->println(("Opener: Keep updating status on intermediate lock state"));
Log->println("Opener: Keep updating status on intermediate lock state");
}
if(_keyTurnerState.nukiState == NukiOpener::State::ContinuousMode)
{
Log->println(("Continuous Mode"));
Log->println("Continuous Mode");
}
char lockStateStr[20];
@@ -566,7 +563,7 @@ bool NukiOpenerWrapper::updateKeyTurnerState()
}
postponeBleWatchdog();
Log->println(("Done querying opener state"));
Log->println("Done querying opener state");
return updateStatus;
}
@@ -577,7 +574,7 @@ void NukiOpenerWrapper::updateBatteryState()
while(retryCount < _nrOfRetries + 1)
{
Log->print(("Querying opener battery state: "));
Log->print("Querying opener battery state: ");
result = _nukiOpener.requestBatteryReport(&_batteryReport);
delay(250);
if(result != Nuki::CmdResult::Success)
@@ -596,7 +593,7 @@ void NukiOpenerWrapper::updateBatteryState()
_network->publishBatteryReport(_batteryReport);
}
postponeBleWatchdog();
Log->println(("Done querying opener battery state"));
Log->println("Done querying opener battery state");
}
void NukiOpenerWrapper::updateConfig()
@@ -611,7 +608,7 @@ void NukiOpenerWrapper::updateConfig()
{
char uidString[20];
itoa(_nukiConfig.nukiId, uidString, 16);
Log->print(("Saving Opener Nuki ID to preferences ("));
Log->print("Saving Opener Nuki ID to preferences (");
Log->print(_nukiConfig.nukiId);
Log->print(" / ");
Log->print(uidString);
@@ -640,61 +637,49 @@ void NukiOpenerWrapper::updateConfig()
const int pinStatus = _preferences->getInt(preference_opener_pin_status, 4);
if(isPinSet())
Nuki::CmdResult result = (Nuki::CmdResult)-1;
int retryCount = 0;
while(retryCount < _nrOfRetries + 1)
{
Nuki::CmdResult result = (Nuki::CmdResult)-1;
int retryCount = 0;
Log->println(("Nuki opener PIN is set"));
while(retryCount < _nrOfRetries + 1)
{
result = _nukiOpener.verifySecurityPin();
if(result != Nuki::CmdResult::Success)
{
++retryCount;
}
else
{
break;
}
}
result = _nukiOpener.verifySecurityPin();
if(result != Nuki::CmdResult::Success)
{
Log->println(("Nuki opener PIN is invalid"));
if(pinStatus != 2)
{
_preferences->putInt(preference_opener_pin_status, 2);
}
++retryCount;
}
else
{
Log->println(("Nuki opener PIN is valid"));
if(pinStatus != 1)
{
_preferences->putInt(preference_opener_pin_status, 1);
}
break;
}
}
if(result != Nuki::CmdResult::Success)
{
Log->println("Nuki opener PIN is invalid or not set");
if(pinStatus != 2)
{
_preferences->putInt(preference_opener_pin_status, 2);
}
}
else
{
Log->println(("Nuki opener PIN is not set"));
if(pinStatus != 0)
Log->println("Nuki opener PIN is valid");
if(pinStatus != 1)
{
_preferences->putInt(preference_opener_pin_status, 0);
_preferences->putInt(preference_opener_pin_status, 1);
}
}
}
else
{
Log->println(("Invalid/Unexpected opener config received, ID does not matched saved ID"));
Log->println("Invalid/Unexpected opener config received, ID does not matched saved ID");
expectedConfig = false;
}
}
else
{
Log->println(("Invalid/Unexpected opener config received, Config is not valid"));
Log->println("Invalid/Unexpected opener config received, Config is not valid");
expectedConfig = false;
}
@@ -711,7 +696,7 @@ void NukiOpenerWrapper::updateConfig()
}
else
{
Log->println(("Invalid/Unexpected opener advanced config received, Advanced config is not valid"));
Log->println("Invalid/Unexpected opener advanced config received, Advanced config is not valid");
expectedConfig = false;
}
}
@@ -719,12 +704,12 @@ void NukiOpenerWrapper::updateConfig()
if(expectedConfig && _nukiConfigValid && _nukiAdvancedConfigValid)
{
_retryConfigCount = 0;
Log->println(("Done retrieving opener config and advanced config"));
Log->println("Done retrieving opener config and advanced config");
}
else
{
++_retryConfigCount;
Log->println(("Invalid/Unexpected opener config and/or advanced config received, retrying in 10 seconds"));
Log->println("Invalid/Unexpected opener config and/or advanced config received, retrying in 10 seconds");
int64_t ts = espMillis();
_nextConfigUpdateTs = ts + 10000;
}
@@ -734,7 +719,7 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
{
if(!isPinValid())
{
Log->println(("No valid PIN set"));
Log->println("No valid PIN set");
return;
}
@@ -820,7 +805,7 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved)
if(!isPinValid())
{
Log->println(("No valid Nuki Opener PIN set"));
Log->println("No valid Nuki Opener PIN set");
return;
}
@@ -900,7 +885,7 @@ void NukiOpenerWrapper::updateTimeControl(bool retrieved)
if(!isPinValid())
{
Log->println(("No valid Nuki Opener PIN set"));
Log->println("No valid Nuki Opener PIN set");
return;
}
@@ -972,7 +957,7 @@ void NukiOpenerWrapper::updateAuth(bool retrieved)
{
if(!isPinValid())
{
Log->println(("No valid Nuki Lock PIN set"));
Log->println("No valid Nuki Lock PIN set");
return;
}
@@ -1558,23 +1543,21 @@ Nuki::BatteryType NukiOpenerWrapper::batteryTypeToEnum(const char* str)
void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
{
JsonDocument jsonResult;
char _resbuf[2048];
if(!_nukiConfigValid)
{
jsonResult["general"] = "configNotReady";
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
if(!isPinValid())
{
jsonResult["general"] = "noValidPinSet";
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
@@ -1584,8 +1567,8 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
if(jsonError)
{
jsonResult["general"] = "invalidJson";
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
@@ -2437,8 +2420,8 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
_nextConfigUpdateTs = espMillis() + 300;
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
@@ -4198,7 +4181,7 @@ void NukiOpenerWrapper::updateTime()
{
if(!isPinValid())
{
Log->println(("No valid PIN set"));
Log->println("No valid PIN set");
return;
}
@@ -4209,7 +4192,7 @@ void NukiOpenerWrapper::updateTime()
if (int(tm.tm_year + 1900) < int(2025))
{
Log->println(("NTP Time not valid, not updating Nuki device"));
Log->println("NTP Time not valid, not updating Nuki device");
return;
}

View File

@@ -11,7 +11,7 @@
class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler
{
public:
NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkOpener* network, Gpio* gpio, Preferences* preferences);
NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkOpener* network, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize);
virtual ~NukiOpenerWrapper();
void initialize();
@@ -25,7 +25,6 @@ public:
void deactivateRTO();
void deactivateCM();
bool isPinSet();
bool isPinValid();
void setPin(const uint16_t pin);
uint16_t getPin();
@@ -159,4 +158,7 @@ private:
std::string _firmwareVersion = "";
std::string _hardwareVersion = "";
NukiOpener::LockAction _nextLockAction = (NukiOpener::LockAction)0xff;
char* _buffer;
const size_t _bufferSize;
};

View File

@@ -11,7 +11,7 @@
NukiWrapper* nukiInst = nullptr;
NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences)
NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize)
: _deviceName(deviceName),
_deviceId(deviceId),
_bleScanner(scanner),
@@ -19,7 +19,9 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId,
_network(network),
_nukiOfficial(nukiOfficial),
_gpio(gpio),
_preferences(preferences)
_preferences(preferences),
_buffer(buffer),
_bufferSize(bufferSize)
{
Log->print("Device id lock: ");
@@ -233,8 +235,8 @@ void NukiWrapper::update(bool reboot)
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
if(!_paired)
{
Log->println(("Nuki lock start pairing"));
_preferences->getBool(preference_register_as_app) ? Log->println(("Pairing as app")) : Log->println(("Pairing as bridge"));
Log->println("Nuki lock start pairing");
_preferences->getBool(preference_register_as_app) ? Log->println("Pairing as app") : Log->println("Pairing as bridge");
_network->publishBleAddress("");
Nuki::AuthorizationIdType idType = _preferences->getBool(preference_register_as_app) ?
@@ -243,7 +245,7 @@ void NukiWrapper::update(bool reboot)
if(_nukiLock.pairNuki(idType) == Nuki::PairingResult::Success)
{
Log->println(("Nuki paired"));
Log->println("Nuki paired");
_paired = true;
_network->publishBleAddress(_nukiLock.getBleAddress().toString());
}
@@ -295,9 +297,9 @@ void NukiWrapper::update(bool reboot)
if(cmdResult != Nuki::CmdResult::Success)
{
Log->print(("Lock: Last command failed, retrying after "));
Log->print("Lock: Last command failed, retrying after ");
Log->print(_retryDelay);
Log->print((" milliseconds. Retry "));
Log->print(" milliseconds. Retry ");
Log->print(retryCount + 1);
Log->print(" of ");
Log->println(_nrOfRetries);
@@ -320,7 +322,7 @@ void NukiWrapper::update(bool reboot)
{
_statusUpdated = true;
}
Log->println(("Lock: updating status after action"));
Log->println("Lock: updating status after action");
_statusUpdatedTs = ts;
if(_intervalLockstate > 10)
{
@@ -329,7 +331,7 @@ void NukiWrapper::update(bool reboot)
}
else
{
Log->println(("Lock: Maximum number of retries exceeded, aborting."));
Log->println("Lock: Maximum number of retries exceeded, aborting.");
_network->publishRetry("failed");
retryCount = 0;
_nextLockAction = (NukiLock::LockAction) 0xff;
@@ -450,18 +452,6 @@ void NukiWrapper::lockngounlatch()
_nextLockAction = NukiLock::LockAction::LockNgoUnlatch;
}
bool NukiWrapper::isPinSet()
{
if (_isUltra)
{
return _nukiLock.getUltraPincode() != 0;
}
else
{
return _nukiLock.getSecurityPincode() != 0;
}
}
bool NukiWrapper::isPinValid()
{
return _preferences->getInt(preference_lock_pin_status, 4) == 1;
@@ -508,11 +498,11 @@ bool NukiWrapper::updateKeyTurnerState()
Nuki::CmdResult result = (Nuki::CmdResult)-1;
int retryCount = 0;
Log->println(("Querying lock state"));
Log->println("Querying lock state");
while(result != Nuki::CmdResult::Success && retryCount < _nrOfRetries + 1)
{
Log->print(("Result (attempt "));
Log->print("Result (attempt ");
Log->print(retryCount + 1);
Log->print(("): "));
result =_nukiLock.requestKeyTurnerState(&_keyTurnerState);
@@ -531,7 +521,7 @@ bool NukiWrapper::updateKeyTurnerState()
postponeBleWatchdog();
if(_retryLockstateCount < _nrOfRetries + 1)
{
Log->print(("Query lock state retrying in "));
Log->print("Query lock state retrying in ");
Log->print(_retryDelay);
Log->println("ms");
_nextLockStateUpdateTs = espMillis() + _retryDelay;
@@ -557,9 +547,9 @@ bool NukiWrapper::updateKeyTurnerState()
{
if(_publishAuthData && (lockState == NukiLock::LockState::Locked || lockState == NukiLock::LockState::Unlocked))
{
Log->println(("Publishing auth data"));
Log->println("Publishing auth data");
updateAuthData(false);
Log->println(("Done publishing auth data"));
Log->println("Done publishing auth data");
}
updateGpioOutputs();
@@ -567,7 +557,7 @@ bool NukiWrapper::updateKeyTurnerState()
else if(!_nukiOfficial->getOffConnected() && espMillis() < _statusUpdatedTs + 10000)
{
updateStatus = true;
Log->println(("Lock: Keep updating status on intermediate lock state"));
Log->println("Lock: Keep updating status on intermediate lock state");
}
else if(lockState == NukiLock::LockState::Undefined)
{
@@ -583,7 +573,7 @@ bool NukiWrapper::updateKeyTurnerState()
Log->println(lockStateStr);
postponeBleWatchdog();
Log->println(("Done querying lock state"));
Log->println("Done querying lock state");
return updateStatus;
}
@@ -617,7 +607,7 @@ void NukiWrapper::updateBatteryState()
_network->publishBatteryReport(_batteryReport);
}
postponeBleWatchdog();
Log->println(("Done querying lock battery state"));
Log->println("Done querying lock battery state");
}
void NukiWrapper::updateConfig()
@@ -632,7 +622,7 @@ void NukiWrapper::updateConfig()
{
char uidString[20];
itoa(_nukiConfig.nukiId, uidString, 16);
Log->print(("Saving Lock Nuki ID to preferences ("));
Log->print("Saving Lock Nuki ID to preferences (");
Log->print(_nukiConfig.nukiId);
Log->print(" / ");
Log->print(uidString);
@@ -660,60 +650,48 @@ void NukiWrapper::updateConfig()
const int pinStatus = _preferences->getInt(preference_lock_pin_status, 4);
if(isPinSet())
Nuki::CmdResult result = (Nuki::CmdResult)-1;
int retryCount = 0;
while(retryCount < _nrOfRetries + 1)
{
Nuki::CmdResult result = (Nuki::CmdResult)-1;
int retryCount = 0;
Log->println(("Nuki Lock PIN is set"));
while(retryCount < _nrOfRetries + 1)
{
result = _nukiLock.verifySecurityPin();
if(result != Nuki::CmdResult::Success)
{
++retryCount;
}
else
{
break;
}
}
result = _nukiLock.verifySecurityPin();
if(result != Nuki::CmdResult::Success)
{
Log->println(("Nuki Lock PIN is invalid"));
if(pinStatus != 2)
{
_preferences->putInt(preference_lock_pin_status, 2);
}
++retryCount;
}
else
{
Log->println(("Nuki Lock PIN is valid"));
if(pinStatus != 1)
{
_preferences->putInt(preference_lock_pin_status, 1);
}
break;
}
}
if(result != Nuki::CmdResult::Success)
{
Log->println("Nuki Lock PIN is invalid or not set");
if(pinStatus != 2)
{
_preferences->putInt(preference_lock_pin_status, 2);
}
}
else
{
Log->println(("Nuki Lock PIN is not set"));
if(pinStatus != 0)
Log->println("Nuki Lock PIN is valid");
if(pinStatus != 1)
{
_preferences->putInt(preference_lock_pin_status, 0);
_preferences->putInt(preference_lock_pin_status, 1);
}
}
}
else
{
Log->println(("Invalid/Unexpected lock config received, ID does not matched saved ID"));
Log->println("Invalid/Unexpected lock config received, ID does not matched saved ID");
expectedConfig = false;
}
}
else
{
Log->println(("Invalid/Unexpected lock config received, Config is not valid"));
Log->println("Invalid/Unexpected lock config received, Config is not valid");
expectedConfig = false;
}
@@ -730,7 +708,7 @@ void NukiWrapper::updateConfig()
}
else
{
Log->println(("Invalid/Unexpected lock advanced config received, Advanced config is not valid"));
Log->println("Invalid/Unexpected lock advanced config received, Advanced config is not valid");
expectedConfig = false;
}
}
@@ -738,12 +716,12 @@ void NukiWrapper::updateConfig()
if(expectedConfig && _nukiConfigValid && _nukiAdvancedConfigValid)
{
_retryConfigCount = 0;
Log->println(("Done retrieving lock config and advanced config"));
Log->println("Done retrieving lock config and advanced config");
}
else
{
++_retryConfigCount;
Log->println(("Invalid/Unexpected lock config and/or advanced config received, retrying in 10 seconds"));
Log->println("Invalid/Unexpected lock config and/or advanced config received, retrying in 10 seconds");
int64_t ts = espMillis();
_nextConfigUpdateTs = ts + 10000;
}
@@ -753,7 +731,7 @@ void NukiWrapper::updateAuthData(bool retrieved)
{
if(!isPinValid())
{
Log->println(("No valid Nuki Lock PIN set"));
Log->println("No valid Nuki Lock PIN set");
return;
}
@@ -837,7 +815,7 @@ void NukiWrapper::updateKeypad(bool retrieved)
if(!isPinValid())
{
Log->println(("No valid Nuki Lock PIN set"));
Log->println("No valid Nuki Lock PIN set");
return;
}
@@ -916,7 +894,7 @@ void NukiWrapper::updateTimeControl(bool retrieved)
if(!isPinValid())
{
Log->println(("No valid Nuki Lock PIN set"));
Log->println("No valid Nuki Lock PIN set");
return;
}
@@ -987,7 +965,7 @@ void NukiWrapper::updateAuth(bool retrieved)
{
if(!isPinValid())
{
Log->println(("No valid Nuki Lock PIN set"));
Log->println("No valid Nuki Lock PIN set");
return;
}
@@ -1495,21 +1473,20 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
void NukiWrapper::onConfigUpdateReceived(const char *value)
{
JsonDocument jsonResult;
char _resbuf[2048];
if(!_nukiConfigValid)
{
jsonResult["general"] = "configNotReady";
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
if(!isPinValid())
{
jsonResult["general"] = "noValidPinSet";
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
@@ -1519,15 +1496,11 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
if(jsonError)
{
jsonResult["general"] = "invalidJson";
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
Log->println(value);
serializeJson(json, _resbuf, sizeof(_resbuf));
Log->println(_resbuf);
Nuki::CmdResult cmdResult;
const char *basicKeys[16] = {"name", "latitude", "longitude", "autoUnlatch", "pairingEnabled", "buttonEnabled", "ledEnabled", "ledBrightness", "timeZoneOffset", "dstMode", "fobAction1", "fobAction2", "fobAction3", "singleLock", "advertisingMode", "timeZone"};
const char *advancedKeys[25] = {"unlockedPositionOffsetDegrees", "lockedPositionOffsetDegrees", "singleLockedPositionOffsetDegrees", "unlockedToLockedTransitionOffsetDegrees", "lockNgoTimeout", "singleButtonPressAction", "doubleButtonPressAction", "detachedCylinder", "batteryType", "automaticBatteryTypeDetection", "unlatchDuration", "autoLockTimeOut", "autoUnLockDisabled", "nightModeEnabled", "nightModeStartTime", "nightModeEndTime", "nightModeAutoLockEnabled", "nightModeAutoUnlockDisabled", "nightModeImmediateLockOnStart", "autoLockEnabled", "immediateAutoLockEnabled", "autoUpdateEnabled", "rebootNuki", "motorSpeed", "enableSlowSpeedDuringNightMode"};
@@ -2500,8 +2473,8 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
_nextConfigUpdateTs = espMillis() + 300;
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
_network->publishConfigCommandResult(_resbuf);
serializeJson(jsonResult, _buffer, _bufferSize);
_network->publishConfigCommandResult(_buffer);
return;
}
@@ -4325,7 +4298,7 @@ void NukiWrapper::updateTime()
{
if(!isPinValid())
{
Log->println(("No valid PIN set"));
Log->println("No valid PIN set");
return;
}
@@ -4336,7 +4309,7 @@ void NukiWrapper::updateTime()
if (int(tm.tm_year + 1900) < int(2025))
{
Log->println(("NTP Time not valid, not updating Nuki device"));
Log->println("NTP Time not valid, not updating Nuki device");
return;
}

View File

@@ -14,7 +14,7 @@
class NukiWrapper : public Nuki::SmartlockEventHandler
{
public:
NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences);
NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, BleScanner::Scanner* scanner, NukiNetworkLock* network, NukiOfficial* nukiOfficial, Gpio* gpio, Preferences* preferences, char* buffer, size_t bufferSize);
virtual ~NukiWrapper();
void initialize();
@@ -27,7 +27,6 @@ public:
void lockngo();
void lockngounlatch();
bool isPinSet();
bool isPinValid();
void setPin(const uint16_t pin);
void setUltraPin(const uint32_t pin);
@@ -168,4 +167,7 @@ private:
std::string _firmwareVersion = "";
std::string _hardwareVersion = "";
volatile NukiLock::LockAction _nextLockAction = (NukiLock::LockAction)0xff;
char* _buffer;
const size_t _bufferSize;
};

View File

@@ -91,6 +91,8 @@
#define preference_cred_bypass_boot_btn_enabled (char*)"bypassBtBtn"
#define preference_cred_bypass_gpio_high (char*)"bypassHigh"
#define preference_cred_bypass_gpio_low (char*)"bypassLow"
#define preference_publish_config (char*)"nhPubConfig"
#define preference_config_from_mqtt (char*)"nhCntrlEnabled"
// CHANGE DOES NOT REQUIRE REBOOT TO TAKE EFFECT
#define preference_find_best_rssi (char*)"nwbestrssi"
@@ -241,6 +243,8 @@ inline void initPreferences(Preferences* preferences)
preferences->putBool(preference_cred_duo_enabled, false);
preferences->putBool(preference_cred_duo_approval, false);
preferences->putBool(preference_cred_bypass_boot_btn_enabled, false);
preferences->putBool(preference_publish_config, false);
preferences->putBool(preference_config_from_mqtt, false);
preferences->putInt(preference_mqtt_broker_port, 1883);
preferences->putInt(preference_buffer_size, CHAR_BUFFER_SIZE);
@@ -504,8 +508,8 @@ private:
preference_mqtt_broker, preference_mqtt_broker_port, preference_mqtt_user, preference_mqtt_password, preference_mqtt_log_enabled, preference_check_updates,
preference_webserver_enabled, preference_lock_enabled, preference_lock_pin_status, preference_mqtt_lock_path, preference_opener_enabled, preference_opener_pin_status,
preference_opener_continuous_mode, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count, preference_update_time, preference_time_server,
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset, preference_mqtt_ca, preference_mqtt_crt,
preference_mqtt_key, preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url, preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address,
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset,
preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url, preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address,
preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, preference_network_hardware, preference_http_auth_type, preference_lock_gemini_pin,
preference_rssi_publish_interval, preference_hostname, preference_network_timeout, preference_restart_on_disconnect, preference_hybrid_reboot_on_disconnect,
preference_restart_ble_beacon_lost, preference_query_interval_lockstate, preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry,
@@ -525,7 +529,8 @@ private:
preference_lock_force_id, preference_lock_force_doorsensor, preference_lock_force_keypad, preference_opener_force_id, preference_opener_force_keypad, preference_nukihub_id,
preference_cred_duo_host, preference_cred_duo_ikey, preference_cred_duo_skey, preference_cred_duo_user, preference_cred_duo_enabled, preference_https_fqdn, preference_bypass_proxy,
preference_cred_session_lifetime, preference_cred_session_lifetime_remember, preference_cred_session_lifetime_duo, preference_cred_session_lifetime_duo_remember,
preference_cred_duo_approval, preference_cred_bypass_boot_btn_enabled, preference_cred_bypass_gpio_high, preference_cred_bypass_gpio_low
preference_cred_duo_approval, preference_cred_bypass_boot_btn_enabled, preference_cred_bypass_gpio_high, preference_cred_bypass_gpio_low, preference_publish_config,
preference_config_from_mqtt
};
std::vector<char*> _redact =
{
@@ -544,7 +549,8 @@ private:
preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_find_best_rssi, preference_cred_bypass_boot_btn_enabled,
preference_debug_connect, preference_debug_communication, preference_debug_readable_data, preference_debug_hex_data, preference_debug_command, preference_connect_mode,
preference_lock_force_id, preference_lock_force_doorsensor, preference_lock_force_keypad, preference_opener_force_id, preference_opener_force_keypad, preference_mqtt_ssl_enabled,
preference_hybrid_reboot_on_disconnect, preference_lock_gemini_enabled, preference_enable_debug_mode, preference_cred_duo_enabled, preference_cred_duo_approval
preference_hybrid_reboot_on_disconnect, preference_lock_gemini_enabled, preference_enable_debug_mode, preference_cred_duo_enabled, preference_cred_duo_approval,
preference_publish_config, preference_config_from_mqtt
};
std::vector<char*> _bytePrefs =
{

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@
#include "NukiNetworkLock.h"
#include "NukiOpenerWrapper.h"
#include "Gpio.h"
#include "ImportExport.h"
extern TaskHandle_t nukiTaskHandle;
@@ -30,6 +31,7 @@ enum class TokenType
#else
#include "NukiNetwork.h"
#include "ImportExport.h"
#endif
extern TaskHandle_t networkTaskHandle;
@@ -38,9 +40,9 @@ class WebCfgServer
{
public:
#ifndef NUKI_HUB_UPDATER
WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, NukiNetwork* network, Gpio* gpio, Preferences* preferences, bool allowRestartToPortal, uint8_t partitionType, PsychicHttpServer* psychicServer);
WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, NukiNetwork* network, Gpio* gpio, Preferences* preferences, bool allowRestartToPortal, uint8_t partitionType, PsychicHttpServer* psychicServer, ImportExport* importExport);
#else
WebCfgServer(NukiNetwork* network, Preferences* preferences, bool allowRestartToPortal, uint8_t partitionType, PsychicHttpServer* psychicServer);
WebCfgServer(NukiNetwork* network, Preferences* preferences, bool allowRestartToPortal, uint8_t partitionType, PsychicHttpServer* psychicServer, ImportExport* importExport);
#endif
~WebCfgServer() = default;
@@ -91,7 +93,6 @@ private:
NukiWrapper* _nuki = nullptr;
NukiOpenerWrapper* _nukiOpener = nullptr;
Gpio* _gpio = nullptr;
bool _pinsConfigured = false;
bool _brokerConfigured = false;
bool _rebootRequired = false;
#endif
@@ -101,9 +102,6 @@ private:
String generateConfirmCode();
String _confirmCode = "----";
int checkDuoAuth(PsychicRequest *request);
int checkDuoApprove();
bool startDuoAuth(char* pushType = (char*)"");
void saveSessions(bool duo = false);
void loadSessions(bool duo = false);
void clearSessions();
@@ -136,6 +134,7 @@ private:
PsychicHttpServer* _psychicServer = nullptr;
NukiNetwork* _network = nullptr;
Preferences* _preferences = nullptr;
ImportExport* _importExport;
char _credUser[31] = {0};
char _credPassword[31] = {0};
@@ -145,20 +144,8 @@ private:
size_t _otaContentLen = 0;
String _hostname;
JsonDocument _httpSessions;
JsonDocument _duoSessions;
JsonDocument _sessionsOpts;
struct tm timeinfo;
bool _duoActiveRequest;
bool _duoEnabled = false;
bool _bypassGPIO = false;
int _bypassGPIOHigh = -1;
int _bypassGPIOLow = -1;
int64_t _duoRequestTS = 0;
String _duoTransactionId;
String _duoHost;
String _duoSkey;
String _duoIkey;
String _duoUser;
String _duoCheckId;
String _duoCheckIP;
};

View File

@@ -31,6 +31,7 @@
#include "RestartReason.h"
#include "EspMillis.h"
#include "NimBLEDevice.h"
#include "ImportExport.h"
/*
#ifdef DEBUG_NUKIHUB
@@ -65,6 +66,7 @@ int64_t restartTs = (pow(2,63) - (5 * 1000 * 60000)) / 1000;
#include "../../src/RestartReason.h"
#include "../../src/NukiNetwork.h"
#include "../../src/EspMillis.h"
#include "../../src/ImportExport.h"
int64_t restartTs = 10 * 60 * 1000;
@@ -78,6 +80,7 @@ NukiNetwork* network = nullptr;
WebCfgServer* webCfgServer = nullptr;
WebCfgServer* webCfgServerSSL = nullptr;
Preferences* preferences = nullptr;
ImportExport* importExport = nullptr;
RTC_NOINIT_ATTR int espRunning;
RTC_NOINIT_ATTR int restartReason;
@@ -163,9 +166,9 @@ void setReroute()
uint8_t checkPartition()
{
const esp_partition_t* running_partition = esp_ota_get_running_partition();
Log->print(("Partition size: "));
Log->print("Partition size: ");
Log->println(running_partition->size);
Log->print(("Partition subtype: "));
Log->print("Partition subtype: ");
Log->println(running_partition->subtype);
if(running_partition->size == 1966080)
@@ -203,7 +206,7 @@ void networkTask(void *pvParameters)
if(bootloopCounter > 0)
{
bootloopCounter = (int8_t)0;
Log->println(("Bootloop counter reset"));
Log->println("Bootloop counter reset");
}
}
@@ -339,12 +342,12 @@ void bootloopDetection()
esp_reset_reason() == esp_reset_reason_t::ESP_RST_WDT)
{
bootloopCounter++;
Log->print(("Bootloop counter incremented: "));
Log->print("Bootloop counter incremented: ");
Log->println(bootloopCounter);
if(bootloopCounter == 10)
{
Log->print(("Bootloop detected."));
Log->print("Bootloop detected.");
preferences->putInt(preference_buffer_size, CHAR_BUFFER_SIZE);
preferences->putInt(preference_task_size_network, NETWORK_TASK_SIZE);
@@ -440,7 +443,7 @@ void otaTask(void *pvParameter)
{
.http_config = &config,
};
Log->print(("Attempting to download update from "));
Log->print("Attempting to download update from ");
Log->println(config.url);
int retryMax = 3;
@@ -649,9 +652,9 @@ void setup()
}
#ifdef NUKI_HUB_UPDATER
Log->print(("Nuki Hub OTA version "));
Log->print("Nuki Hub OTA version ");
Log->println(NUKI_HUB_VERSION);
Log->print(("Nuki Hub OTA build "));
Log->print("Nuki Hub OTA build ");
Log->println();
if(preferences->getString(preference_updater_version, "") != NUKI_HUB_VERSION)
@@ -666,6 +669,8 @@ void setup()
{
preferences->putString(preference_updater_date, NUKI_HUB_DATE);
}
importExport = new ImportExport(preferences);
network = new NukiNetwork(preferences);
network->initialize();
@@ -735,7 +740,7 @@ void setup()
psychicSSLServer->ssl_config.httpd.max_open_sockets = 8;
psychicSSLServer->setCertificate(cert, key);
psychicSSLServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServerSSL = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer);
webCfgServerSSL = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer, importExport);
webCfgServerSSL->initialize();
psychicSSLServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
return response->redirect("/");
@@ -751,7 +756,7 @@ void setup()
#endif
psychicServer = new PsychicHttpServer;
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServer = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
webCfgServer = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer, importExport);
webCfgServer->initialize();
psychicServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
return response->redirect("/");
@@ -767,9 +772,9 @@ void setup()
bootloopDetection();
}
Log->print(("Nuki Hub version "));
Log->print("Nuki Hub version ");
Log->println(NUKI_HUB_VERSION);
Log->print(("Nuki Hub build "));
Log->print("Nuki Hub build ");
Log->println(NUKI_HUB_BUILD);
uint32_t devIdOpener = preferences->getUInt(preference_device_id_opener);
@@ -791,8 +796,10 @@ void setup()
Log->print(gpioDesc.c_str());
const String mqttLockPath = preferences->getString(preference_mqtt_lock_path);
importExport = new ImportExport(preferences);
network = new NukiNetwork(preferences, gpio, mqttLockPath, CharBuffer::get(), buffer_size);
network = new NukiNetwork(preferences, gpio, mqttLockPath, CharBuffer::get(), buffer_size, importExport);
network->initialize();
lockEnabled = preferences->getBool(preference_lock_enabled);
@@ -826,7 +833,7 @@ void setup()
networkLock->initialize();
}
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences);
nuki = new NukiWrapper("NukiHub", deviceIdLock, bleScanner, networkLock, nukiOfficial, gpio, preferences, CharBuffer::get(), buffer_size);
nuki->initialize();
}
@@ -840,7 +847,7 @@ void setup()
networkOpener->initialize();
}
nukiOpener = new NukiOpenerWrapper("NukiHub", deviceIdOpener, bleScanner, networkOpener, gpio, preferences);
nukiOpener = new NukiOpenerWrapper("NukiHub", deviceIdOpener, bleScanner, networkOpener, gpio, preferences, CharBuffer::get(), buffer_size);
nukiOpener->initialize();
}
@@ -911,7 +918,7 @@ void setup()
psychicSSLServer->ssl_config.httpd.max_open_sockets = 8;
psychicSSLServer->setCertificate(cert, key);
psychicSSLServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServerSSL = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer);
webCfgServerSSL = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer, importExport);
webCfgServerSSL->initialize();
psychicSSLServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
return response->redirect("/");
@@ -927,7 +934,7 @@ void setup()
#endif
psychicServer = new PsychicHttpServer;
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer, importExport);
webCfgServer->initialize();
psychicServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
return response->redirect("/");
@@ -949,27 +956,27 @@ void setup()
}
#endif
*/
String timeserver = preferences->getString(preference_time_server, "pool.ntp.org");
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG(timeserver.c_str());
config.start = false;
config.server_from_dhcp = true;
config.renew_servers_after_new_IP = true;
config.index_of_first_server = 1;
if (network->networkDeviceType() == NetworkDeviceType::WiFi)
{
config.ip_event_to_renew = IP_EVENT_STA_GOT_IP;
}
else
{
config.ip_event_to_renew = IP_EVENT_ETH_GOT_IP;
}
config.sync_cb = cbSyncTime;
esp_netif_sntp_init(&config);
}
#endif
String timeserver = preferences->getString(preference_time_server, "pool.ntp.org");
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG(timeserver.c_str());
config.start = false;
config.server_from_dhcp = true;
config.renew_servers_after_new_IP = true;
config.index_of_first_server = 1;
if (network->networkDeviceType() == NetworkDeviceType::WiFi)
{
config.ip_event_to_renew = IP_EVENT_STA_GOT_IP;
}
else
{
config.ip_event_to_renew = IP_EVENT_ETH_GOT_IP;
}
config.sync_cb = cbSyncTime;
esp_netif_sntp_init(&config);
if(doOta)
{
setupTasks(true);

View File

@@ -72,7 +72,7 @@ void EthernetDevice::initialize()
if(ethCriticalFailure)
{
ethCriticalFailure = false;
Log->println(("Failed to initialize ethernet hardware"));
Log->println("Failed to initialize ethernet hardware");
Log->println("Network device has a critical failure, enable fallback to Wi-Fi and reboot.");
wifiFallback = true;
delay(200);
@@ -80,11 +80,11 @@ void EthernetDevice::initialize()
return;
}
Log->println(("Init Ethernet"));
Log->println("Init Ethernet");
if(_useSpi)
{
Log->println(("Use SPI"));
Log->println("Use SPI");
ethCriticalFailure = true;
SPI.begin(_spi_sck, _spi_miso, _spi_mosi);
_hardwareInitialized = ETH.begin(_type, _phy_addr, _cs, _irq, _rst, SPI);
@@ -93,7 +93,7 @@ void EthernetDevice::initialize()
#ifdef CONFIG_IDF_TARGET_ESP32
else
{
Log->println(("Use RMII"));
Log->println("Use RMII");
// Workaround for failing RMII initialization with pioarduino 3.1.0
// Revoke all GPIO's some of them set by init PSRAM in IDF
@@ -118,7 +118,7 @@ void EthernetDevice::initialize()
if(_hardwareInitialized)
{
Log->println(("Ethernet hardware Initialized"));
Log->println("Ethernet hardware Initialized");
wifiFallback = false;
if(_useSpi && !_ipConfiguration->dhcpEnabled())
@@ -133,7 +133,7 @@ void EthernetDevice::initialize()
}
else
{
Log->println(("Failed to initialize ethernet hardware"));
Log->println("Failed to initialize ethernet hardware");
Log->println("Network device has a critical failure, enable fallback to Wi-Fi and reboot.");
wifiFallback = true;
delay(200);
@@ -150,7 +150,7 @@ void EthernetDevice::update()
{
if(_ipConfiguration->ipAddress() != ETH.localIP())
{
Log->println(("ETH Set static IP"));
Log->println("ETH Set static IP");
ETH.config(_ipConfiguration->ipAddress(), _ipConfiguration->defaultGateway(), _ipConfiguration->subnet(), _ipConfiguration->dnsServer());
_checkIpTs = espMillis() + 5000;
return;

View File

@@ -16,20 +16,20 @@ IPConfiguration::IPConfiguration(Preferences *preferences)
_gateway.fromString(_preferences->getString(preference_ip_gateway, ""));
_dnsServer.fromString(_preferences->getString(preference_ip_dns_server, ""));
Log->print(("IP configuration: "));
Log->print("IP configuration: ");
if(dhcpEnabled())
{
Log->println(("DHCP"));
Log->println("DHCP");
}
else
{
Log->print(("IP address: "));
Log->print("IP address: ");
Log->print(ipAddress());
Log->print((", Subnet: "));
Log->print(", Subnet: ");
Log->print(subnet());
Log->print((", Gateway: "));
Log->print(", Gateway: ");
Log->print(defaultGateway());
Log->print((", DNS: "));
Log->print(", DNS: ");
Log->println(dnsServer());
}
}

View File

@@ -32,7 +32,7 @@ void NetworkDevice::init()
if(ca_cert.length() > 1)
{
_useEncryption = true;
Log->println(("MQTT over TLS."));
Log->println("MQTT over TLS.");
_mqttClientSecure = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
_mqttClientSecure->setCACert(caDest);
@@ -57,7 +57,7 @@ void NetworkDevice::init()
if(cert.length() > 1 && key.length() > 1)
{
Log->println(("MQTT with client certificate."));
Log->println("MQTT with client certificate.");
_mqttClientSecure->setCertificate(certDest);
_mqttClientSecure->setPrivateKey(keyDest);
}
@@ -69,7 +69,7 @@ void NetworkDevice::init()
if (!_useEncryption)
{
Log->println(("MQTT without TLS."));
Log->println("MQTT without TLS.");
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO);
}
@@ -251,6 +251,11 @@ void NetworkDevice::mqttDisable()
_mqttEnabled = false;
}
bool NetworkDevice::isEncrypted()
{
return _useEncryption;
}
MqttClient *NetworkDevice::getMqttClient() const
{
if (_useEncryption)

View File

@@ -29,6 +29,7 @@ public:
virtual String BSSIDstr() = 0;
#ifndef NUKI_HUB_UPDATER
virtual bool isEncrypted();
virtual bool mqttConnect();
virtual bool mqttDisconnect(bool force);
virtual void mqttDisable();

View File

@@ -50,7 +50,7 @@ NetworkDeviceType NetworkUtil::GetDeviceTypeFromPreference(int hardwareDetect, i
return NetworkDeviceType::LilyGO_T_ETH_ELite;
break;
default:
Log->println(("Unknown hardware selected, falling back to Wi-Fi."));
Log->println("Unknown hardware selected, falling back to Wi-Fi.");
return NetworkDeviceType::WiFi;
break;
}