Import/Export config over MQTT
This commit is contained in:
56
README.md
56
README.md
@@ -78,7 +78,7 @@ Devices ranked best-to-worst:
|
||||
- ESP32 without PSRAM
|
||||
- ...... <br>
|
||||
(Devices below will not support more Nuki Hub functions)
|
||||
- ......
|
||||
- ......
|
||||
- ESP32-C6
|
||||
- ESP32-solo1
|
||||
- ESP32-C3
|
||||
@@ -292,7 +292,9 @@ In a browser navigate to the IP address assigned to the ESP32.
|
||||
### Access Level Configuration
|
||||
|
||||
#### Nuki General Access Control
|
||||
- Publish Nuki configuration information: Enable to publish information about the configuration of the connected Nuki device(s) through MQTT.
|
||||
- Publish Nuki Hub configuration information: Publish Nuki Hub settings over MQTT, see "[Import and Export Nuki Hub settings over MQTT](#import-and-export-nuki-hub-settings-over-mqtt)"
|
||||
- Modify Nuki Hub configuration over MQTT: Allow changing Nuki Hub settings using MQTT, see "[Import and Export Nuki Hub settings over MQTT](#import-and-export-nuki-hub-settings-over-mqtt)"
|
||||
- Publish Nuki configuration information: Enable to publish information about the configuration of the connected Nuki device(s) through MQTT.
|
||||
|
||||
Note: All of the following requires the Nuki security code / PIN to be set, see "[Nuki Lock PIN / Nuki Opener PIN](#nuki-lock-pin--nuki-opener-pin)"
|
||||
|
||||
@@ -463,6 +465,9 @@ Note that the following options can break Nuki Hub and cause bootloops that will
|
||||
- [lock/opener/]configuration/commandResult: Result of the last configuration change action as JSON data. See the "[Changing Nuki Lock/Opener Configuration](#changing-nuki-lockopener-configuration)" section of this README for possible values
|
||||
- [lock/opener/]configuration/basicJson: The current basic configuration of the Nuki Lock/Opener as JSON data. See [Nuki Smart Lock API](https://developer.nuki.io/page/nuki-smart-lock-api-2/2/#heading--set-config) and [Nuki Opener API](https://developer.nuki.io/page/nuki-opener-api-1/7/#heading--set-config) for available settings. Please note: Longitude and Latitude of the Lock/Opener are not published to MQTT by design. These values can still be changed though.
|
||||
- [lock/opener/]configuration/advancedJson: The current advanced configuration of the Nuki Lock/Opener as JSON data. See [Nuki Smart Lock API](https://developer.nuki.io/page/nuki-smart-lock-api-2/2/#heading--advanced-config) and [Nuki Opener API](https://developer.nuki.io/page/nuki-opener-api-1/7/#heading--advanced-config) for available settings.
|
||||
- configuration/action: Allows importing and exporting configuration settings of Nuki Hub using a JSON formatted value. After receiving the action, the value is set to "--", see "[Import and Export Nuki Hub settings over MQTT](#import-and-export-nuki-hub-settings-over-mqtt)"
|
||||
- configuration/commandResult: Result of the last Nuki Hub configuration import action as JSON data, see "[Import and Export Nuki Hub settings over MQTT](#import-and-export-nuki-hub-settings-over-mqtt)"
|
||||
- configuration/json: Topic where you can export Nuki Hub configuration as JSON data to, see "[Import and Export Nuki Hub settings over MQTT](#import-and-export-nuki-hub-settings-over-mqtt)"
|
||||
|
||||
### Query
|
||||
|
||||
@@ -512,8 +517,51 @@ Note that the following options can break Nuki Hub and cause bootloops that will
|
||||
- maintenance/wifiRssi: The Wi-Fi signal strength of the Wi-Fi Access Point as measured by the ESP32 and expressed by the RSSI Value in dBm.
|
||||
- maintenance/log: If "Enable MQTT logging" is enabled in the web interface, this topic will be filled with debug log information.
|
||||
- maintenance/freeHeap: Only available when debug mode is enabled. Set to the current size of free heap memory in bytes.
|
||||
- maintenance/restartReasonNukiHub: Set to the last reason Nuki Hub was restarted. See [RestartReason.h](/RestartReason.h) for possible values
|
||||
- maintenance/restartReasonNukiEsp: Set to the last reason the ESP was restarted. See [RestartReason.h](/RestartReason.h) for possible values
|
||||
- maintenance/restartReasonNukiHub: Set to the last reason Nuki Hub was restarted. See [RestartReason.h](/src/RestartReason.h) for possible values
|
||||
- maintenance/restartReasonNukiEsp: Set to the last reason the ESP was restarted. See [RestartReason.h](/src/RestartReason.h) for possible values
|
||||
|
||||
## Import and Export Nuki Hub settings over MQTT
|
||||
|
||||
Consider this when deciding if you want to enable the following functionality:
|
||||
|
||||
- Any application/actor that has read access to `nukihub/configuration/action` and `nukihub/configuration/json` can view your changes and exports.
|
||||
- If you have not enabled the setting to require MFA when changing settings any application/actor that has write access to `nukihub/configuration/action` can change Nuki Hub settings (including pairing data and credentials)
|
||||
|
||||
### Export Nuki Hub settings over MQTT
|
||||
|
||||
To allow Nuki Hub to export configuration over MQTT first enable "Publish Nuki Hub configuration information" in "Access Level Configuration" and save the configuration.
|
||||
You can export Nuki Hub settings in JSON format by sending the following JSON values to the `nukihub/configuration/action` topic:
|
||||
- Export Nuki Hub settings without redacted settings and without pairing settings: `{"exportNH": 0}`
|
||||
|
||||
NOTE: The following settings can only be exported if you have setup a secure MQTT connection (MQTT over SSL)
|
||||
|
||||
- Export Nuki Hub settings with redacted settings and without pairing settings: `{"exportNH": 0, "redacted": 1}`
|
||||
- Export Nuki Hub settings without redacted settings and with pairing settings: `{"exportNH": 0, "pairing": 1}`
|
||||
- Export Nuki Hub settings with redacted settings and pairing settings: `{"exportNH": 0, "redacted": 1, "pairing": 1}`
|
||||
- Export Nuki Hub MQTTS certificates and key: `{"exportMQTTS": 0}`
|
||||
- Export Nuki Hub HTTPS certificate and key: `{"exportHTTPS": 0}`
|
||||
|
||||
The exported values will be available in the `nukihub/configuration/json` topic in JSON format.
|
||||
A general explanation of the exported values can be found in the [PreferencesKeys.h](/src/PreferencesKeys.h) file
|
||||
|
||||
If you set the value of `exportNH`/`exportMQTTS`/`exportHTTPS` to an integer value > 0 the `nukihub/configuration/json` will be cleared after the given amount of seconds (e.g. `{"exportMQTTS": 30}` will clear the JSON topic after 30 seconds)
|
||||
|
||||
If you have enabled `Require Duo Push authentication for all sensitive Nuki Hub operations (changing/exporting settings)` you will first need to approve the Duo Push before the settings will be exported.
|
||||
|
||||
### Import/Change Nuki Hub settings over MQTT
|
||||
|
||||
To allow Nuki Hub to import/change configuration over MQTT first enable "Modify Nuki Hub configuration over MQTT" in "Access Level Configuration" and save the configuration.
|
||||
You can import Nuki Hub settings in JSON format by sending the desired JSON values to be changed to the `nukihub/configuration/action` topic.
|
||||
The expected values and format is the same as the JSON files/values that can be exported over MQTT or through the Web Configurator.
|
||||
|
||||
The result of the import will be available in the `nukihub/configuration/commandResult` topic in JSON format.
|
||||
After the import is complete the ESP32 will reboot.
|
||||
|
||||
If you have enabled `Require Duo Push authentication for all sensitive Nuki Hub operations (changing/exporting settings)` you will first need to approve the Duo Push before the settings will be changed/imported.
|
||||
|
||||
Note: When importing settings using MQTT there are less/no checks on the values entered. These checks are only available when changing settings through the WebConfigurator.
|
||||
Consider testing your configuration values by changing them in the Web Configurator before trying to use MQTT to change configuration.
|
||||
A general explanation of the values that can be imported can be found in the [PreferencesKeys.h](/src/PreferencesKeys.h) file
|
||||
|
||||
## Changing Nuki Lock/Opener Configuration
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
14
src/Gpio.cpp
14
src/Gpio.cpp
@@ -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
1005
src/ImportExport.cpp
Normal file
File diff suppressed because it is too large
Load Diff
45
src/ImportExport.h
Normal file
45
src/ImportExport.h
Normal 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;
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 =
|
||||
{
|
||||
|
||||
1101
src/WebCfgServer.cpp
1101
src/WebCfgServer.cpp
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
};
|
||||
|
||||
77
src/main.cpp
77
src/main.cpp
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,12 @@ list(APPEND app_sources ../../src/PreferencesKeys.h)
|
||||
list(APPEND app_sources ../../src/RestartReason.h)
|
||||
list(APPEND app_sources ../../src/WebCfgServer.h)
|
||||
list(APPEND app_sources ../../src/WebCfgServerConstants.h)
|
||||
list(APPEND app_sources ../../src/ImportExport.h)
|
||||
|
||||
list(APPEND app_sources ../../src/Logger.cpp)
|
||||
list(APPEND app_sources ../../src/NukiNetwork.cpp)
|
||||
list(APPEND app_sources ../../src/WebCfgServer.cpp)
|
||||
list(APPEND app_sources ../../src/ImportExport.cpp)
|
||||
|
||||
list(APPEND app_sources ../../src/enums/NetworkDeviceType.h)
|
||||
list(APPEND app_sources ../../src/networkDevices/EthernetDevice.h)
|
||||
|
||||
Reference in New Issue
Block a user