From 582abae914b49110f854cb260c408fec335e703b Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 29 May 2022 22:38:10 +0200 Subject: [PATCH 01/28] rename namespaces --- CMakeLists.txt | 7 ++++++- Network.cpp | 14 +++++++------- Network.h | 9 +++++---- NukiWrapper.cpp | 46 +++++++++++++++++++++++----------------------- NukiWrapper.h | 20 ++++++++++---------- WebCfgServer.cpp | 2 +- 6 files changed, 52 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd4e1c1..c63ab3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,9 +41,14 @@ file(GLOB SRCFILES lib/WiFiManager/WiFiManager.cpp lib/Crc16/Crc16.h lib/nuki_ble/src/NukiBle.cpp + lib/nuki_ble/src/NukiOpener.cpp lib/nuki_ble/src/NukiConstants.h + lib/nuki_ble/src/NukiOpenerConstants.h + lib/nuki_ble/src/NukiLockConstants.h lib/nuki_ble/src/NukiDataTypes.h lib/nuki_ble/src/NukiUtils.cpp + lib/nuki_ble/src/NukiLockUtils.cpp + lib/nuki_ble/src/NukiOpenerUtils.cpp lib/BleScanner/src/BleInterfaces.h lib/BleScanner/src/BleScanner.cpp lib/pubsubclient/src/PubSubClient.cpp @@ -61,7 +66,7 @@ add_executable(${PROJECT_NAME} main.cpp ${SRCFILES} ${SRCFILESREC} -) + ) target_compile_definitions(${PROJECT_NAME} PRIVATE diff --git a/Network.cpp b/Network.cpp index 9a28484..6bef9ef 100644 --- a/Network.cpp +++ b/Network.cpp @@ -253,11 +253,11 @@ void Network::onMqttDataReceived(char *&topic, byte *&payload, unsigned int &len } } -void Network::publishKeyTurnerState(const Nuki::KeyTurnerState& keyTurnerState, const Nuki::KeyTurnerState& lastKeyTurnerState) +void Network::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState) { char str[50]; - if((_firstTunerStatePublish || keyTurnerState.lockState != lastKeyTurnerState.lockState) && keyTurnerState.lockState != Nuki::LockState::Undefined) + if((_firstTunerStatePublish || keyTurnerState.lockState != lastKeyTurnerState.lockState) && keyTurnerState.lockState != NukiLock::LockState::Undefined) { memset(&str, 0, sizeof(str)); lockstateToString(keyTurnerState.lockState, str); @@ -274,14 +274,14 @@ void Network::publishKeyTurnerState(const Nuki::KeyTurnerState& keyTurnerState, if(_firstTunerStatePublish || keyTurnerState.lastLockActionCompletionStatus != lastKeyTurnerState.lastLockActionCompletionStatus) { memset(&str, 0, sizeof(str)); - completionStatusToString(keyTurnerState.lastLockActionCompletionStatus, str); + NukiLock::completionStatusToString(keyTurnerState.lastLockActionCompletionStatus, str); publishString(mqtt_topic_lock_completionStatus, str); } if(_firstTunerStatePublish || keyTurnerState.doorSensorState != lastKeyTurnerState.doorSensorState) { memset(&str, 0, sizeof(str)); - doorSensorStateToString(keyTurnerState.doorSensorState, str); + NukiLock::doorSensorStateToString(keyTurnerState.doorSensorState, str); publishString(mqtt_topic_door_sensor_state, str); } @@ -309,7 +309,7 @@ void Network::publishCommandResult(const char *resultStr) publishString(mqtt_topic_lock_action_command_result, resultStr); } -void Network::publishBatteryReport(const Nuki::BatteryReport& batteryReport) +void Network::publishBatteryReport(const NukiLock::BatteryReport& batteryReport) { publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0); publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain); // milliwatt seconds @@ -317,14 +317,14 @@ void Network::publishBatteryReport(const Nuki::BatteryReport& batteryReport) publishInt(mqtt_topic_battery_lock_distance, batteryReport.lockDistance); // degrees } -void Network::publishConfig(const Nuki::Config &config) +void Network::publishConfig(const NukiLock::Config &config) { publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1); publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1); publishInt(mqtt_topic_config_led_brightness, config.ledBrightness); } -void Network::publishAdvancedConfig(const Nuki::AdvancedConfig &config) +void Network::publishAdvancedConfig(const NukiLock::AdvancedConfig &config) { publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0); publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1); diff --git a/Network.h b/Network.h index 5d9e49d..bbc0284 100644 --- a/Network.h +++ b/Network.h @@ -8,6 +8,7 @@ #include #include "NukiConstants.h" #include "SpiffsCookie.h" +#include "NukiLockConstants.h" enum class NetworkDeviceType { @@ -28,12 +29,12 @@ public: bool isMqttConnected(); - void publishKeyTurnerState(const Nuki::KeyTurnerState& keyTurnerState, const Nuki::KeyTurnerState& lastKeyTurnerState); + void publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState); void publishAuthorizationInfo(const uint32_t authId, const char* authName); void publishCommandResult(const char* resultStr); - void publishBatteryReport(const Nuki::BatteryReport& batteryReport); - void publishConfig(const Nuki::Config& config); - void publishAdvancedConfig(const Nuki::AdvancedConfig& config); + void publishBatteryReport(const NukiLock::BatteryReport& batteryReport); + void publishConfig(const NukiLock::Config& config); + void publishAdvancedConfig(const NukiLock::AdvancedConfig& config); void publishPresenceDetection(char* csv); void setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char* value)); diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 502fea4..7f4dc14 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -2,7 +2,7 @@ #include #include "PreferencesKeys.h" #include "MqttTopics.h" -#include +#include NukiWrapper* nukiInst; @@ -14,11 +14,11 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* ne { nukiInst = this; - memset(&_lastKeyTurnerState, sizeof(Nuki::KeyTurnerState), 0); - memset(&_lastBatteryReport, sizeof(Nuki::BatteryReport), 0); - memset(&_batteryReport, sizeof(Nuki::BatteryReport), 0); - memset(&_keyTurnerState, sizeof(Nuki::KeyTurnerState), 0); - _keyTurnerState.lockState = Nuki::LockState::Undefined; + memset(&_lastKeyTurnerState, sizeof(NukiLock::KeyTurnerState), 0); + memset(&_lastBatteryReport, sizeof(NukiLock::BatteryReport), 0); + memset(&_batteryReport, sizeof(NukiLock::BatteryReport), 0); + memset(&_keyTurnerState, sizeof(NukiLock::KeyTurnerState), 0); + _keyTurnerState.lockState = NukiLock::LockState::Undefined; network->setLockActionReceivedCallback(nukiInst->onLockActionReceivedCallback); network->setConfigUpdateReceivedCallback(nukiInst->onConfigUpdateReceivedCallback); @@ -111,19 +111,19 @@ void NukiWrapper::update() updateConfig(); } - if(_nextLockAction != (Nuki::LockAction)0xff) + if(_nextLockAction != (NukiLock::LockAction)0xff) { Nuki::CmdResult cmdResult = _nukiBle.lockAction(_nextLockAction, 0, 0); char resultStr[15] = {0}; - Nuki::cmdResultToString(cmdResult, resultStr); + NukiLock::cmdResultToString(cmdResult, resultStr); _network->publishCommandResult(resultStr); Serial.print(F("Lock action result: ")); Serial.println(resultStr); - _nextLockAction = (Nuki::LockAction)0xff; + _nextLockAction = (NukiLock::LockAction)0xff; if(_intervalLockstate > 10) { _nextLockStateUpdateTs = ts + 10 * 1000; @@ -136,7 +136,7 @@ void NukiWrapper::update() _clearAuthData = false; } - memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(Nuki::KeyTurnerState)); + memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiLock::KeyTurnerState)); } void NukiWrapper::setPin(const uint16_t pin) @@ -221,23 +221,23 @@ void NukiWrapper::updateAuthData() } } -Nuki::LockAction NukiWrapper::lockActionToEnum(const char *str) +NukiLock::LockAction NukiWrapper::lockActionToEnum(const char *str) { - if(strcmp(str, "unlock") == 0) return Nuki::LockAction::Unlock; - else if(strcmp(str, "lock") == 0) return Nuki::LockAction::Lock; - else if(strcmp(str, "unlatch") == 0) return Nuki::LockAction::Unlatch; - else if(strcmp(str, "lockNgo") == 0) return Nuki::LockAction::LockNgo; - else if(strcmp(str, "lockNgoUnlatch") == 0) return Nuki::LockAction::LockNgoUnlatch; - else if(strcmp(str, "fullLock") == 0) return Nuki::LockAction::FullLock; - else if(strcmp(str, "fobAction2") == 0) return Nuki::LockAction::FobAction2; - else if(strcmp(str, "fobAction1") == 0) return Nuki::LockAction::FobAction1; - else if(strcmp(str, "fobAction3") == 0) return Nuki::LockAction::FobAction3; - return (Nuki::LockAction)0xff; + if(strcmp(str, "unlock") == 0) return NukiLock::LockAction::Unlock; + else if(strcmp(str, "lock") == 0) return NukiLock::LockAction::Lock; + else if(strcmp(str, "unlatch") == 0) return NukiLock::LockAction::Unlatch; + else if(strcmp(str, "lockNgo") == 0) return NukiLock::LockAction::LockNgo; + else if(strcmp(str, "lockNgoUnlatch") == 0) return NukiLock::LockAction::LockNgoUnlatch; + else if(strcmp(str, "fullLock") == 0) return NukiLock::LockAction::FullLock; + else if(strcmp(str, "fobAction2") == 0) return NukiLock::LockAction::FobAction2; + else if(strcmp(str, "fobAction1") == 0) return NukiLock::LockAction::FobAction1; + else if(strcmp(str, "fobAction3") == 0) return NukiLock::LockAction::FobAction3; + return (NukiLock::LockAction)0xff; } bool NukiWrapper::onLockActionReceivedCallback(const char *value) { - Nuki::LockAction action = nukiInst->lockActionToEnum(value); + NukiLock::LockAction action = nukiInst->lockActionToEnum(value); nukiInst->_nextLockAction = action; return (int)action != 0xff; } @@ -294,7 +294,7 @@ void NukiWrapper::onConfigUpdateReceived(const char *topic, const char *value) } } -const Nuki::KeyTurnerState &NukiWrapper::keyTurnerState() +const NukiLock::KeyTurnerState &NukiWrapper::keyTurnerState() { return _keyTurnerState; } diff --git a/NukiWrapper.h b/NukiWrapper.h index a62376b..122cee6 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -19,7 +19,7 @@ public: void unpair(); - const Nuki::KeyTurnerState& keyTurnerState(); + const NukiLock::KeyTurnerState& keyTurnerState(); const bool isPaired(); BleScanner::Scanner* bleScanner(); @@ -39,10 +39,10 @@ private: void readConfig(); void readAdvancedConfig(); - Nuki::LockAction lockActionToEnum(const char* str); // char array at least 14 characters + NukiLock::LockAction lockActionToEnum(const char* str); // char array at least 14 characters std::string _deviceName; - Nuki::NukiBle _nukiBle; + NukiLock::NukiBle _nukiBle; BleScanner::Scanner* _bleScanner; Network* _network; Preferences* _preferences; @@ -52,16 +52,16 @@ private: bool _publishAuthData = false; bool _clearAuthData = false; - Nuki::KeyTurnerState _lastKeyTurnerState; - Nuki::KeyTurnerState _keyTurnerState; + NukiLock::KeyTurnerState _lastKeyTurnerState; + NukiLock::KeyTurnerState _keyTurnerState; uint32_t _lastAuthId = 0xffff; - Nuki::BatteryReport _batteryReport; - Nuki::BatteryReport _lastBatteryReport; + NukiLock::BatteryReport _batteryReport; + NukiLock::BatteryReport _lastBatteryReport; - Nuki::Config _nukiConfig = {0}; - Nuki::AdvancedConfig _nukiAdvancedConfig = {0}; + NukiLock::Config _nukiConfig = {0}; + NukiLock::AdvancedConfig _nukiAdvancedConfig = {0}; bool _nukiConfigValid = false; bool _nukiAdvancedConfigValid = false; @@ -71,5 +71,5 @@ private: unsigned long _nextBatteryReportTs = 0; unsigned long _nextConfigUpdateTs = 0; unsigned long _nextPairTs = 0; - Nuki::LockAction _nextLockAction = (Nuki::LockAction)0xff; + NukiLock::LockAction _nextLockAction = (NukiLock::LockAction)0xff; }; diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index 1d65999..6cf4d31 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -258,7 +258,7 @@ void WebCfgServer::buildHtml(String& response) version.concat(nuki_hub_version); char lockstateArr[20]; - Nuki::lockstateToString(_nuki->keyTurnerState().lockState, lockstateArr); + NukiLock::lockstateToString(_nuki->keyTurnerState().lockState, lockstateArr); String lockState = " "; lockState.concat(lockstateArr); From 62bf4191b2af478907b4a25f7ad1056315e25eb8 Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 29 May 2022 22:40:07 +0200 Subject: [PATCH 02/28] update ble lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index 53a4fc1..1c5a72c 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit 53a4fc1b321bbc21d779477acc85adf3eafce56e +Subproject commit 1c5a72c7431b21e36e8d52a8d2e0858354a70541 From 875dc340127096d8c0cce222a94ccbb55933f5dd Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 29 May 2022 23:23:27 +0200 Subject: [PATCH 03/28] add opener code --- CMakeLists.txt | 1 + Network.cpp | 19 ++- Network.h | 1 + NukiOpenerWrapper.cpp | 333 ++++++++++++++++++++++++++++++++++++++++++ NukiOpenerWrapper.h | 75 ++++++++++ PreferencesKeys.h | 3 +- WebCfgServer.cpp | 10 +- main.cpp | 3 + 8 files changed, 440 insertions(+), 5 deletions(-) create mode 100644 NukiOpenerWrapper.cpp create mode 100644 NukiOpenerWrapper.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c63ab3a..26b3c07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ file(GLOB SRCFILES networkDevices/WifiDevice.cpp networkDevices/W5500Device.cpp NukiWrapper.cpp + NukiOpenerWrapper.cpp MqttTopics.h WebCfgServer.cpp PresenceDetection.cpp diff --git a/Network.cpp b/Network.cpp index 6bef9ef..4b061b5 100644 --- a/Network.cpp +++ b/Network.cpp @@ -74,7 +74,7 @@ void Network::initialize() _preferences->putInt(preference_mqtt_broker_port, port); } - String mqttPath = _preferences->getString(preference_mqtt_path); + String mqttPath = _preferences->getString(preference_mqtt_lock_path); if(mqttPath.length() > 0) { size_t len = mqttPath.length(); @@ -86,7 +86,22 @@ void Network::initialize() else { strcpy(_mqttPath, "nuki"); - _preferences->putString(preference_mqtt_path, _mqttPath); + _preferences->putString(preference_mqtt_lock_path, _mqttPath); + } + + String mqttOpenerPath = _preferences->getString(preference_mqtt_opener_path); + if(mqttOpenerPath.length() > 0) + { + size_t len = mqttOpenerPath.length(); + for(int i=0; i < len; i++) + { + _mqttOpenerPath[i] = mqttOpenerPath.charAt(i); + } + } + else + { + strcpy(_mqttOpenerPath, "nukiopener"); + _preferences->putString(preference_mqtt_opener_path, _mqttOpenerPath); } String mqttUser = _preferences->getString(preference_mqtt_user); diff --git a/Network.h b/Network.h index bbc0284..6a88088 100644 --- a/Network.h +++ b/Network.h @@ -67,6 +67,7 @@ private: unsigned long _nextReconnect = 0; char _mqttBrokerAddr[101] = {0}; char _mqttPath[181] = {0}; + char _mqttOpenerPath[181] = {0}; char _mqttUser[31] = {0}; char _mqttPass[31] = {0}; int _networkTimeout = 0; diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp new file mode 100644 index 0000000..9b28a05 --- /dev/null +++ b/NukiOpenerWrapper.cpp @@ -0,0 +1,333 @@ +#include "NukiOpenerWrapper.h" +#include +#include "PreferencesKeys.h" +#include "MqttTopics.h" +#include + +NukiOpenerWrapper* nukiOpenerInst; + +NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences) + : _deviceName(deviceName), + _nukiBle(deviceName, id), + _network(network), + _preferences(preferences) +{ + nukiOpenerInst = this; + + memset(&_lastKeyTurnerState, sizeof(NukiLock::KeyTurnerState), 0); + memset(&_lastBatteryReport, sizeof(NukiLock::BatteryReport), 0); + memset(&_batteryReport, sizeof(NukiLock::BatteryReport), 0); + memset(&_keyTurnerState, sizeof(NukiLock::KeyTurnerState), 0); + _keyTurnerState.lockState = NukiOpener::LockState::Undefined; + + network->setLockActionReceivedCallback(nukiOpenerInst->onLockActionReceivedCallback); + network->setConfigUpdateReceivedCallback(nukiOpenerInst->onConfigUpdateReceivedCallback); +} + + +NukiOpenerWrapper::~NukiOpenerWrapper() +{ + delete _bleScanner; + _bleScanner = nullptr; +} + + +void NukiOpenerWrapper::initialize() +{ + _bleScanner = new BleScanner::Scanner(); + _bleScanner->initialize(_deviceName); + _bleScanner->setScanDuration(10); + _nukiBle.initialize(); + _nukiBle.registerBleScanner(_bleScanner); + + _intervalLockstate = _preferences->getInt(preference_query_interval_lockstate); + _intervalBattery = _preferences->getInt(preference_query_interval_battery); + _publishAuthData = _preferences->getBool(preference_publish_authdata); + + if(_intervalLockstate == 0) + { + _intervalLockstate = 60 * 5; + _preferences->putInt(preference_query_interval_lockstate, _intervalLockstate); + } + if(_intervalBattery == 0) + { + _intervalBattery = 60 * 30; + _preferences->putInt(preference_query_interval_battery, _intervalBattery); + } + + _nukiBle.setEventHandler(this); + + Serial.print(F("Lock state interval: ")); + Serial.print(_intervalLockstate); + Serial.print(F(" | Battery interval: ")); + Serial.print(_intervalBattery); + Serial.print(F(" | Publish auth data: ")); + Serial.println(_publishAuthData ? "yes" : "no"); + + if(!_publishAuthData) + { + _clearAuthData = true; + } +} + +void NukiOpenerWrapper::update() +{ + if (!_paired) { + Serial.println(F("Nuki start pairing")); + + _bleScanner->update(); + vTaskDelay( 5000 / portTICK_PERIOD_MS); + if (_nukiBle.pairNuki() == NukiOpener::PairingResult::Success) { + Serial.println(F("Nuki paired")); + _paired = true; + } + else + { + vTaskDelay( 200 / portTICK_PERIOD_MS); + return; + } + } + + vTaskDelay( 20 / portTICK_PERIOD_MS); + _bleScanner->update(); + _nukiBle.updateConnectionState(); + + unsigned long ts = millis(); + + if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs) + { + _statusUpdated = false; + _nextLockStateUpdateTs = ts + _intervalLockstate * 1000; + updateKeyTurnerState(); + } + if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs) + { + _nextBatteryReportTs = ts + _intervalBattery * 1000; + updateBatteryState(); + } + if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs) + { + _nextConfigUpdateTs = ts + _intervalConfig * 1000; + updateConfig(); + } + + if(_nextLockAction != (NukiOpener::LockAction)0xff) + { + NukiOpener::CmdResult cmdResult = _nukiBle.lockAction(_nextLockAction, 0, 0); + + char resultStr[15] = {0}; + NukiOpener::cmdResultToString(cmdResult, resultStr); + + _network->publishCommandResult(resultStr); + + Serial.print(F("Lock action result: ")); + Serial.println(resultStr); + + _nextLockAction = (NukiOpener::LockAction)0xff; + if(_intervalLockstate > 10) + { + _nextLockStateUpdateTs = ts + 10 * 1000; + } + } + + if(_clearAuthData) + { + _network->publishAuthorizationInfo(0, ""); + _clearAuthData = false; + } + + memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiLock::KeyTurnerState)); +} + +void NukiOpenerWrapper::setPin(const uint16_t pin) +{ + _nukiBle.saveSecurityPincode(pin); +} + +void NukiOpenerWrapper::unpair() +{ + _nukiBle.unPairNuki(); + _paired = false; +} + +void NukiOpenerWrapper::updateKeyTurnerState() +{ + _nukiBle.requestKeyTurnerState(&_keyTurnerState); +// _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); + + if(_keyTurnerState.lockState != _lastKeyTurnerState.lockState) + { + char lockStateStr[20]; + lockstateToString(_keyTurnerState.lockState, lockStateStr); + Serial.print(F("Nuki lock state: ")); + Serial.println(lockStateStr); + } + + if(_publishAuthData) + { + updateAuthData(); + } +} + +void NukiOpenerWrapper::updateBatteryState() +{ + _nukiBle.requestBatteryReport(&_batteryReport); +// _network->publishBatteryReport(_batteryReport); +} + +void NukiOpenerWrapper::updateConfig() +{ + readConfig(); + readAdvancedConfig(); +// _network->publishConfig(_nukiConfig); +// _network->publishAdvancedConfig(_nukiAdvancedConfig); +} + +void NukiOpenerWrapper::updateAuthData() +{ + Nuki::CmdResult result = _nukiBle.retrieveLogEntries(0, 0, 0, true); + if(result != Nuki::CmdResult::Success) + { + _network->publishAuthorizationInfo(0, ""); + return; + } + vTaskDelay( 100 / portTICK_PERIOD_MS); + + result = _nukiBle.retrieveLogEntries(_nukiBle.getLogEntryCount() - 2, 1, 0, false); + if(result != Nuki::CmdResult::Success) + { + _network->publishAuthorizationInfo(0, ""); + return; + } + vTaskDelay( 200 / portTICK_PERIOD_MS); + + std::list log; + _nukiBle.getLogEntries(&log); + + if(log.size() > 0) + { + const NukiOpener::LogEntry& entry = log.front(); +// log_d("Log: %d-%d-%d %d:%d:%d %s", entry.timeStampYear, entry.timeStampMonth, entry.timeStampDay, +// entry.timeStampHour, entry.timeStampMinute, entry.timeStampSecond, entry.name); + if(entry.authId != _lastAuthId) + { + _network->publishAuthorizationInfo(entry.authId, (char *) entry.name); + _lastAuthId = entry.authId; + } + } + else + { + _network->publishAuthorizationInfo(0, ""); + } +} + +NukiOpener::LockAction NukiOpenerWrapper::lockActionToEnum(const char *str) +{ + if(strcmp(str, "activateRTO") == 0) return NukiOpener::LockAction::ActivateRTO; + else if(strcmp(str, "deactivateRTO") == 0) return NukiOpener::LockAction::DeactivateRTO; + else if(strcmp(str, "electricStrikeActuation") == 0) return NukiOpener::LockAction::ElectricStrikeActuation; + else if(strcmp(str, "activateCM") == 0) return NukiOpener::LockAction::ActivateCM; + else if(strcmp(str, "deactivateCM") == 0) return NukiOpener::LockAction::DeactivateCM; + else if(strcmp(str, "fobAction2") == 0) return NukiOpener::LockAction::FobAction2; + else if(strcmp(str, "fobAction1") == 0) return NukiOpener::LockAction::FobAction1; + else if(strcmp(str, "fobAction3") == 0) return NukiOpener::LockAction::FobAction3; + return (NukiOpener::LockAction)0xff; +} + +bool NukiOpenerWrapper::onLockActionReceivedCallback(const char *value) +{ + NukiOpener::LockAction action = nukiOpenerInst->lockActionToEnum(value); + nukiOpenerInst->_nextLockAction = action; + return (int)action != 0xff; +} + +void NukiOpenerWrapper::onConfigUpdateReceivedCallback(const char *topic, const char *value) +{ + nukiOpenerInst->onConfigUpdateReceived(topic, value); +} + + +void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *value) +{ + if(strcmp(topic, mqtt_topic_config_button_enabled) == 0) + { + bool newValue = atoi(value) > 0; + if(!_nukiConfigValid || _nukiConfig.buttonEnabled == newValue) return; + _nukiBle.enableButton(newValue); + _nextConfigUpdateTs = millis() + 300; + } + if(strcmp(topic, mqtt_topic_config_led_enabled) == 0) + { + bool newValue = atoi(value) > 0; + if(!_nukiConfigValid || _nukiConfig.ledEnabled == newValue) return; + _nukiBle.enableLedFlash(newValue); + _nextConfigUpdateTs = millis() + 300; + } + else if(strcmp(topic, mqtt_topic_config_led_brightness) == 0) + { + int newValue = atoi(value); + if(!_nukiConfigValid || _nukiConfig.ledBrightness == newValue) return; + _nukiBle.setLedBrightness(newValue); + _nextConfigUpdateTs = millis() + 300; + } + else if(strcmp(topic, mqtt_topic_config_auto_unlock) == 0) + { + bool newValue = !(atoi(value) > 0); + if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoUnLockDisabled == newValue) return; + _nukiBle.disableAutoUnlock(newValue); + _nextConfigUpdateTs = millis() + 300; + } + else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) + { + bool newValue = atoi(value) > 0; + if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; + _nukiBle.enableAutoLock(newValue); + _nextConfigUpdateTs = millis() + 300; + } + else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) + { + bool newValue = atoi(value) > 0; + if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; + _nukiBle.enableAutoLock(newValue); + _nextConfigUpdateTs = millis() + 300; + } +} + +const NukiOpener::KeyTurnerState &NukiOpenerWrapper::keyTurnerState() +{ + return _keyTurnerState; +} + +const bool NukiOpenerWrapper::isPaired() +{ + return _paired; +} + +BleScanner::Scanner *NukiOpenerWrapper::bleScanner() +{ + return _bleScanner; +} + +void NukiOpenerWrapper::notify(Nuki::EventType eventType) +{ + if(eventType == Nuki::EventType::KeyTurnerStatusUpdated) + { + _statusUpdated = true; + } +} + +void NukiOpenerWrapper::readConfig() +{ + Serial.print(F("Reading config. Result: ")); + Nuki::CmdResult result = _nukiBle.requestConfig(&_nukiConfig); + _nukiConfigValid = result == Nuki::CmdResult::Success; + Serial.println(result); +} + +void NukiOpenerWrapper::readAdvancedConfig() +{ + Serial.print(F("Reading advanced config. Result: ")); + Nuki::CmdResult result = _nukiBle.requestAdvancedConfig(&_nukiAdvancedConfig); + _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; + Serial.println(result); +} diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h new file mode 100644 index 0000000..de33917 --- /dev/null +++ b/NukiOpenerWrapper.h @@ -0,0 +1,75 @@ +#pragma once + +#include "NukiOpener.h" +#include "Network.h" +#include "NukiOpenerConstants.h" +#include "NukiDataTypes.h" +#include "BleScanner.h" + +class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler +{ +public: + NukiOpenerWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences); + virtual ~NukiOpenerWrapper(); + + void initialize(); + void update(); + + void setPin(const uint16_t pin); + + void unpair(); + + const NukiOpener::KeyTurnerState& keyTurnerState(); + const bool isPaired(); + + BleScanner::Scanner* bleScanner(); + + void notify(NukiOpener::EventType eventType) override; + +private: + static bool onLockActionReceivedCallback(const char* value); + static void onConfigUpdateReceivedCallback(const char* topic, const char* value); + void onConfigUpdateReceived(const char* topic, const char* value); + + void updateKeyTurnerState(); + void updateBatteryState(); + void updateConfig(); + void updateAuthData(); + + void readConfig(); + void readAdvancedConfig(); + + NukiOpener::LockAction lockActionToEnum(const char* str); // char array at least 14 characters + + std::string _deviceName; + NukiOpener::NukiOpener _nukiBle; + BleScanner::Scanner* _bleScanner; + Network* _network; + Preferences* _preferences; + int _intervalLockstate = 0; // seconds + int _intervalBattery = 0; // seconds + int _intervalConfig = 60 * 60; // seconds + bool _publishAuthData = false; + bool _clearAuthData = false; + + NukiOpener::KeyTurnerState _lastKeyTurnerState; + NukiOpener::KeyTurnerState _keyTurnerState; + + uint32_t _lastAuthId = 0xffff; + + NukiOpener::BatteryReport _batteryReport; + NukiOpener::BatteryReport _lastBatteryReport; + + NukiOpener::Config _nukiConfig = {0}; + NukiOpener::AdvancedConfig _nukiAdvancedConfig = {0}; + bool _nukiConfigValid = false; + bool _nukiAdvancedConfigValid = false; + + bool _paired = false; + bool _statusUpdated = false; + unsigned long _nextLockStateUpdateTs = 0; + unsigned long _nextBatteryReportTs = 0; + unsigned long _nextConfigUpdateTs = 0; + unsigned long _nextPairTs = 0; + NukiOpener::LockAction _nextLockAction = (NukiOpener::LockAction)0xff; +}; diff --git a/PreferencesKeys.h b/PreferencesKeys.h index 6938637..f7253fe 100644 --- a/PreferencesKeys.h +++ b/PreferencesKeys.h @@ -5,7 +5,8 @@ #define preference_mqtt_broker_port "mqttport" #define preference_mqtt_user "mqttuser" #define preference_mqtt_password "mqttpass" -#define preference_mqtt_path "mqttpath" +#define preference_mqtt_lock_path "mqttpath" +#define preference_mqtt_opener_path "mqttoppath" #define preference_hostname "hostname" #define preference_network_timeout "nettmout" #define preference_query_interval_lockstate "lockStInterval" diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index 6cf4d31..a6e7283 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -147,7 +147,12 @@ bool WebCfgServer::processArgs(String& message) } else if(key == "MQTTPATH") { - _preferences->putString(preference_mqtt_path, value); + _preferences->putString(preference_mqtt_lock_path, value); + configChanged = true; + } + else if(key == "MQTTOPPATH") + { + _preferences->putString(preference_mqtt_opener_path, value); configChanged = true; } else if(key == "HOSTNAME") @@ -277,7 +282,8 @@ void WebCfgServer::buildHtml(String& response) printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); - printInputField(response, "MQTTPATH", "MQTT Path", _preferences->getString(preference_mqtt_path).c_str(), 180); + printInputField(response, "MQTTPATH", "MQTT Lock Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180); + printInputField(response, "MQTTOPPATH", "MQTT Opener Path", _preferences->getString(preference_mqtt_opener_path).c_str(), 180); printInputField(response, "HOSTNAME", "Host name", _preferences->getString(preference_hostname).c_str(), 100); printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5); printInputField(response, "LSTINT", "Query interval lock state (seconds)", _preferences->getInt(preference_query_interval_lockstate), 10); diff --git a/main.cpp b/main.cpp index 2a728b3..fa0da7a 100644 --- a/main.cpp +++ b/main.cpp @@ -8,10 +8,12 @@ #include "PresenceDetection.h" #include "hardware/W5500EthServer.h" #include "hardware/WifiEthServer.h" +#include "NukiOpenerWrapper.h" Network* network = nullptr; WebCfgServer* webCfgServer = nullptr; NukiWrapper* nuki = nullptr; +NukiOpenerWrapper* nukiOpener = nullptr; PresenceDetection* presenceDetection = nullptr; Preferences* preferences = nullptr; EthServer* ethServer = nullptr; @@ -120,6 +122,7 @@ void setup() initEthServer(networkDevice); nuki = new NukiWrapper("NukiHub", deviceId, network, preferences); +// nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, network, preferences); webCfgServer = new WebCfgServer(nuki, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); webCfgServer->initialize(); nuki->initialize(); From 836b84b549c9f3ed24b7afbd039e3374d292f474 Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 30 May 2022 21:24:35 +0200 Subject: [PATCH 04/28] opener fixes --- CMakeLists.txt | 2 +- Network.cpp | 17 +------- Network.h | 1 - NukiOpenerWrapper.cpp | 97 ++++++++++++++++++++----------------------- NukiOpenerWrapper.h | 4 +- NukiWrapper.cpp | 2 +- main.cpp | 8 +++- 7 files changed, 57 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 26b3c07..369c26d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(nuki_hub CXX) # ARDUHAL_LOG_LEVEL_NONE, define ARDUHAL_LOG_LEVEL_ERROR, define ARDUHAL_LOG_LEVEL_WARN, define ARDUHAL_LOG_LEVEL_INFO, # define ARDUHAL_LOG_LEVEL_DEBUG, define ARDUHAL_LOG_LEVEL_VERBOSE -set(LOG_LEVEL ARDUHAL_LOG_LEVEL_NONE) +set(LOG_LEVEL ARDUHAL_LOG_LEVEL_DEBUG) include_directories(${PROJECT_NAME} PRIVATE diff --git a/Network.cpp b/Network.cpp index 4b061b5..92dab7e 100644 --- a/Network.cpp +++ b/Network.cpp @@ -89,21 +89,6 @@ void Network::initialize() _preferences->putString(preference_mqtt_lock_path, _mqttPath); } - String mqttOpenerPath = _preferences->getString(preference_mqtt_opener_path); - if(mqttOpenerPath.length() > 0) - { - size_t len = mqttOpenerPath.length(); - for(int i=0; i < len; i++) - { - _mqttOpenerPath[i] = mqttOpenerPath.charAt(i); - } - } - else - { - strcpy(_mqttOpenerPath, "nukiopener"); - _preferences->putString(preference_mqtt_opener_path, _mqttOpenerPath); - } - String mqttUser = _preferences->getString(preference_mqtt_user); if(mqttUser.length() > 0) { @@ -448,4 +433,4 @@ bool Network::comparePrefixedPath(const char *fullPath, const char *subPath) char prefixedPath[500]; buildMqttPath(subPath, prefixedPath); return strcmp(fullPath, prefixedPath) == 0; -} +} \ No newline at end of file diff --git a/Network.h b/Network.h index 6a88088..bbc0284 100644 --- a/Network.h +++ b/Network.h @@ -67,7 +67,6 @@ private: unsigned long _nextReconnect = 0; char _mqttBrokerAddr[101] = {0}; char _mqttPath[181] = {0}; - char _mqttOpenerPath[181] = {0}; char _mqttUser[31] = {0}; char _mqttPass[31] = {0}; int _networkTimeout = 0; diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index 9b28a05..e3f1228 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -6,9 +6,10 @@ NukiOpenerWrapper* nukiOpenerInst; -NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences) +NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, Network* network, Preferences* preferences) : _deviceName(deviceName), - _nukiBle(deviceName, id), + _nukiOpener(deviceName, id), + _bleScanner(scanner), _network(network), _preferences(preferences) { @@ -27,18 +28,14 @@ NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, NukiOpenerWrapper::~NukiOpenerWrapper() { - delete _bleScanner; _bleScanner = nullptr; } void NukiOpenerWrapper::initialize() { - _bleScanner = new BleScanner::Scanner(); - _bleScanner->initialize(_deviceName); - _bleScanner->setScanDuration(10); - _nukiBle.initialize(); - _nukiBle.registerBleScanner(_bleScanner); + _nukiOpener.initialize(); + _nukiOpener.registerBleScanner(_bleScanner); _intervalLockstate = _preferences->getInt(preference_query_interval_lockstate); _intervalBattery = _preferences->getInt(preference_query_interval_battery); @@ -55,7 +52,7 @@ void NukiOpenerWrapper::initialize() _preferences->putInt(preference_query_interval_battery, _intervalBattery); } - _nukiBle.setEventHandler(this); + _nukiOpener.setEventHandler(this); Serial.print(F("Lock state interval: ")); Serial.print(_intervalLockstate); @@ -73,12 +70,12 @@ void NukiOpenerWrapper::initialize() void NukiOpenerWrapper::update() { if (!_paired) { - Serial.println(F("Nuki start pairing")); + Serial.println(F("Nuki opener start pairing")); _bleScanner->update(); vTaskDelay( 5000 / portTICK_PERIOD_MS); - if (_nukiBle.pairNuki() == NukiOpener::PairingResult::Success) { - Serial.println(F("Nuki paired")); + if (_nukiOpener.pairNuki() == NukiOpener::PairingResult::Success) { + Serial.println(F("Nuki opener paired")); _paired = true; } else @@ -88,32 +85,30 @@ void NukiOpenerWrapper::update() } } - vTaskDelay( 20 / portTICK_PERIOD_MS); - _bleScanner->update(); - _nukiBle.updateConnectionState(); + _nukiOpener.updateConnectionState(); unsigned long ts = millis(); - if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs) - { - _statusUpdated = false; - _nextLockStateUpdateTs = ts + _intervalLockstate * 1000; - updateKeyTurnerState(); - } - if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs) - { - _nextBatteryReportTs = ts + _intervalBattery * 1000; - updateBatteryState(); - } - if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs) - { - _nextConfigUpdateTs = ts + _intervalConfig * 1000; - updateConfig(); - } +// if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs) +// { +// _statusUpdated = false; +// _nextLockStateUpdateTs = ts + _intervalLockstate * 1000; +// updateKeyTurnerState(); +// } +// if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs) +// { +// _nextBatteryReportTs = ts + _intervalBattery * 1000; +// updateBatteryState(); +// } +// if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs) +// { +// _nextConfigUpdateTs = ts + _intervalConfig * 1000; +// updateConfig(); +// } if(_nextLockAction != (NukiOpener::LockAction)0xff) { - NukiOpener::CmdResult cmdResult = _nukiBle.lockAction(_nextLockAction, 0, 0); + NukiOpener::CmdResult cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0); char resultStr[15] = {0}; NukiOpener::cmdResultToString(cmdResult, resultStr); @@ -136,30 +131,30 @@ void NukiOpenerWrapper::update() _clearAuthData = false; } - memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiLock::KeyTurnerState)); + memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiOpener::KeyTurnerState)); } void NukiOpenerWrapper::setPin(const uint16_t pin) { - _nukiBle.saveSecurityPincode(pin); + _nukiOpener.saveSecurityPincode(pin); } void NukiOpenerWrapper::unpair() { - _nukiBle.unPairNuki(); + _nukiOpener.unPairNuki(); _paired = false; } void NukiOpenerWrapper::updateKeyTurnerState() { - _nukiBle.requestKeyTurnerState(&_keyTurnerState); + _nukiOpener.requestKeyTurnerState(&_keyTurnerState); // _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); if(_keyTurnerState.lockState != _lastKeyTurnerState.lockState) { char lockStateStr[20]; lockstateToString(_keyTurnerState.lockState, lockStateStr); - Serial.print(F("Nuki lock state: ")); + Serial.print(F("Nuki opener state: ")); Serial.println(lockStateStr); } @@ -171,7 +166,7 @@ void NukiOpenerWrapper::updateKeyTurnerState() void NukiOpenerWrapper::updateBatteryState() { - _nukiBle.requestBatteryReport(&_batteryReport); + _nukiOpener.requestBatteryReport(&_batteryReport); // _network->publishBatteryReport(_batteryReport); } @@ -185,7 +180,7 @@ void NukiOpenerWrapper::updateConfig() void NukiOpenerWrapper::updateAuthData() { - Nuki::CmdResult result = _nukiBle.retrieveLogEntries(0, 0, 0, true); + Nuki::CmdResult result = _nukiOpener.retrieveLogEntries(0, 0, 0, true); if(result != Nuki::CmdResult::Success) { _network->publishAuthorizationInfo(0, ""); @@ -193,7 +188,7 @@ void NukiOpenerWrapper::updateAuthData() } vTaskDelay( 100 / portTICK_PERIOD_MS); - result = _nukiBle.retrieveLogEntries(_nukiBle.getLogEntryCount() - 2, 1, 0, false); + result = _nukiOpener.retrieveLogEntries(_nukiOpener.getLogEntryCount() - 2, 1, 0, false); if(result != Nuki::CmdResult::Success) { _network->publishAuthorizationInfo(0, ""); @@ -202,7 +197,7 @@ void NukiOpenerWrapper::updateAuthData() vTaskDelay( 200 / portTICK_PERIOD_MS); std::list log; - _nukiBle.getLogEntries(&log); + _nukiOpener.getLogEntries(&log); if(log.size() > 0) { @@ -253,42 +248,42 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *va { bool newValue = atoi(value) > 0; if(!_nukiConfigValid || _nukiConfig.buttonEnabled == newValue) return; - _nukiBle.enableButton(newValue); + _nukiOpener.enableButton(newValue); _nextConfigUpdateTs = millis() + 300; } if(strcmp(topic, mqtt_topic_config_led_enabled) == 0) { bool newValue = atoi(value) > 0; if(!_nukiConfigValid || _nukiConfig.ledEnabled == newValue) return; - _nukiBle.enableLedFlash(newValue); + _nukiOpener.enableLedFlash(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_led_brightness) == 0) { int newValue = atoi(value); if(!_nukiConfigValid || _nukiConfig.ledBrightness == newValue) return; - _nukiBle.setLedBrightness(newValue); + _nukiOpener.setLedBrightness(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_auto_unlock) == 0) { bool newValue = !(atoi(value) > 0); if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoUnLockDisabled == newValue) return; - _nukiBle.disableAutoUnlock(newValue); + _nukiOpener.disableAutoUnlock(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) { bool newValue = atoi(value) > 0; if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; - _nukiBle.enableAutoLock(newValue); + _nukiOpener.enableAutoLock(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) { bool newValue = atoi(value) > 0; if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; - _nukiBle.enableAutoLock(newValue); + _nukiOpener.enableAutoLock(newValue); _nextConfigUpdateTs = millis() + 300; } } @@ -318,16 +313,16 @@ void NukiOpenerWrapper::notify(Nuki::EventType eventType) void NukiOpenerWrapper::readConfig() { - Serial.print(F("Reading config. Result: ")); - Nuki::CmdResult result = _nukiBle.requestConfig(&_nukiConfig); + Serial.print(F("Reading opener config. Result: ")); + Nuki::CmdResult result = _nukiOpener.requestConfig(&_nukiConfig); _nukiConfigValid = result == Nuki::CmdResult::Success; Serial.println(result); } void NukiOpenerWrapper::readAdvancedConfig() { - Serial.print(F("Reading advanced config. Result: ")); - Nuki::CmdResult result = _nukiBle.requestAdvancedConfig(&_nukiAdvancedConfig); + Serial.print(F("Reading opener advanced config. Result: ")); + Nuki::CmdResult result = _nukiOpener.requestAdvancedConfig(&_nukiAdvancedConfig); _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; Serial.println(result); } diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index de33917..5358bb2 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -9,7 +9,7 @@ class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler { public: - NukiOpenerWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences); + NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, Network* network, Preferences* preferences); virtual ~NukiOpenerWrapper(); void initialize(); @@ -42,7 +42,7 @@ private: NukiOpener::LockAction lockActionToEnum(const char* str); // char array at least 14 characters std::string _deviceName; - NukiOpener::NukiOpener _nukiBle; + NukiOpener::NukiOpener _nukiOpener; BleScanner::Scanner* _bleScanner; Network* _network; Preferences* _preferences; diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 7f4dc14..4c811e9 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -304,7 +304,7 @@ const bool NukiWrapper::isPaired() return _paired; } -BleScanner::Scanner *NukiWrapper::bleScanner() +BleScanner::Scanner* NukiWrapper::bleScanner() { return _bleScanner; } diff --git a/main.cpp b/main.cpp index fa0da7a..1c01d20 100644 --- a/main.cpp +++ b/main.cpp @@ -33,6 +33,7 @@ void nukiTask(void *pvParameters) while(true) { nuki->update(); + nukiOpener->update(); } } @@ -122,10 +123,13 @@ void setup() initEthServer(networkDevice); nuki = new NukiWrapper("NukiHub", deviceId, network, preferences); -// nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, network, preferences); + nuki->initialize(); + + nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), network, preferences); + nukiOpener->initialize(); + webCfgServer = new WebCfgServer(nuki, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); webCfgServer->initialize(); - nuki->initialize(); presenceDetection = new PresenceDetection(preferences, nuki->bleScanner(), network); presenceDetection->initialize(); From 2473f68947b673465be6f1fe96609a1667a8518d Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 30 May 2022 21:30:27 +0200 Subject: [PATCH 05/28] update nuki lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index 1c5a72c..bef10bf 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit 1c5a72c7431b21e36e8d52a8d2e0858354a70541 +Subproject commit bef10bf8c5b7441d47815a5bf094e2e661d9d6a3 From e68c3453dbcfb21d3b0e68822b06012d7e0d7d19 Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 30 May 2022 22:52:09 +0200 Subject: [PATCH 06/28] rewrite network code for opener --- CMakeLists.txt | 1 + Network.cpp | 17 ++- Network.h | 4 + NetworkOpener.cpp | 264 ++++++++++++++++++++++++++++++++++++++++++ NetworkOpener.h | 60 ++++++++++ NukiOpenerWrapper.cpp | 4 +- NukiOpenerWrapper.h | 6 +- main.cpp | 6 +- 8 files changed, 355 insertions(+), 7 deletions(-) create mode 100644 NetworkOpener.cpp create mode 100644 NetworkOpener.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 369c26d..d2f9357 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ include_directories(${PROJECT_NAME} file(GLOB SRCFILES Pins.h Network.cpp + NetworkOpener.cpp networkDevices/NetworkDevice.h networkDevices/WifiDevice.cpp networkDevices/W5500Device.cpp diff --git a/Network.cpp b/Network.cpp index 92dab7e..80541de 100644 --- a/Network.cpp +++ b/Network.cpp @@ -251,6 +251,11 @@ void Network::onMqttDataReceived(char *&topic, byte *&payload, unsigned int &len } } } + + if(_mqttTopicReceivedForwardCallback != nullptr) + { + _mqttTopicReceivedForwardCallback(topic, payload, length); + } } void Network::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerState, const NukiLock::KeyTurnerState& lastKeyTurnerState) @@ -345,6 +350,11 @@ void Network::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallbac _configUpdateReceivedCallback = configUpdateReceivedCallback; } +void Network::setMqttDataReceivedForwardCallback(void (*callback)(char *, uint8_t *, unsigned int)) +{ + _mqttTopicReceivedForwardCallback = callback; +} + void Network::publishFloat(const char* topic, const float value, const uint8_t precision) { char str[30]; @@ -433,4 +443,9 @@ bool Network::comparePrefixedPath(const char *fullPath, const char *subPath) char prefixedPath[500]; buildMqttPath(subPath, prefixedPath); return strcmp(fullPath, prefixedPath) == 0; -} \ No newline at end of file +} + +NetworkDevice *Network::device() +{ + return _device; +} diff --git a/Network.h b/Network.h index bbc0284..3fea58b 100644 --- a/Network.h +++ b/Network.h @@ -39,9 +39,12 @@ public: void setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char* value)); void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* path, const char* value)); + void setMqttDataReceivedForwardCallback(void (*callback)(char*, uint8_t*, unsigned int)); void restartAndConfigureWifi(); + NetworkDevice* device(); + private: static void onMqttDataReceivedCallback(char* topic, byte* payload, unsigned int length); void onMqttDataReceived(char*& topic, byte*& payload, unsigned int& length); @@ -81,4 +84,5 @@ private: bool (*_lockActionReceivedCallback)(const char* value) = nullptr; void (*_configUpdateReceivedCallback)(const char* path, const char* value) = nullptr; + void (*_mqttTopicReceivedForwardCallback)(char*, uint8_t*, unsigned int) = nullptr; }; diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp new file mode 100644 index 0000000..e7d100d --- /dev/null +++ b/NetworkOpener.cpp @@ -0,0 +1,264 @@ +#include "NetworkOpener.h" +#include // https://github.com/tzapu/WiFiManager +#include "Arduino.h" +#include "MqttTopics.h" +#include "PreferencesKeys.h" +#include "Pins.h" + +NetworkOpener* nwInstOpener; + +NetworkOpener::NetworkOpener(Network* network, Preferences* preferences) + : _preferences(preferences), + _network(network) +{ + nwInstOpener = this; + + _configTopics.reserve(5); +// _configTopics.push_back(mqtt_topic_config_button_enabled); +// _configTopics.push_back(mqtt_topic_config_led_enabled); +// _configTopics.push_back(mqtt_topic_config_led_brightness); +// _configTopics.push_back(mqtt_topic_config_auto_unlock); +// _configTopics.push_back(mqtt_topic_config_auto_lock); +} + +void NetworkOpener::initialize() +{ + String mqttPath = _preferences->getString(preference_mqtt_opener_path); + if(mqttPath.length() > 0) + { + size_t len = mqttPath.length(); + for(int i=0; i < len; i++) + { + _mqttPath[i] = mqttPath.charAt(i); + } + } + else + { + strcpy(_mqttPath, "nukiopener"); + _preferences->putString(preference_mqtt_opener_path, _mqttPath); + } + + _network->setMqttDataReceivedForwardCallback(nwInstOpener->onMqttDataReceivedCallback); +} + +void NetworkOpener::update() +{ + bool connected = _network->device()->mqttClient()->connected(); + + if(!_isConnected && connected) + { + subscribe(mqtt_topic_lock_action); + } + + _isConnected = connected; + +// long ts = millis(); + +} + +void NetworkOpener::onMqttDataReceivedCallback(char *topic, byte *payload, unsigned int length) +{ + nwInstOpener->onMqttDataReceived(topic, payload, length); +} + +void NetworkOpener::onMqttDataReceived(char *&topic, byte *&payload, unsigned int &length) +{ + char value[50] = {0}; + size_t l = min(length, sizeof(value)-1); + + for(int i=0; i> 1; + bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0; + bool charging = (keyTurnerState.criticalBatteryState & 0b00000010) > 0; + publishInt(mqtt_topic_battery_level, level); // percent + publishBool(mqtt_topic_battery_critical, critical); + publishBool(mqtt_topic_battery_charging, charging); + } + + _firstTunerStatePublish = false; +} + +void NetworkOpener::publishAuthorizationInfo(const uint32_t authId, const char *authName) +{ + publishUInt(mqtt_topic_lock_auth_id, authId); + publishString(mqtt_topic_lock_auth_name, authName); +} + +void NetworkOpener::publishCommandResult(const char *resultStr) +{ + publishString(mqtt_topic_lock_action_command_result, resultStr); +} + +void NetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batteryReport) +{ + publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0); + publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain); // milliwatt seconds + publishFloat(mqtt_topic_battery_max_turn_current, (float)batteryReport.maxTurnCurrent / 1000.0); + publishInt(mqtt_topic_battery_lock_distance, batteryReport.lockDistance); // degrees +} + +void NetworkOpener::publishConfig(const NukiOpener::Config &config) +{ + publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1); + publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1); + publishInt(mqtt_topic_config_led_brightness, config.ledBrightness); +} + +void NetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &config) +{ + publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0); + publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1); +} + +void NetworkOpener::setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char *)) +{ + _lockActionReceivedCallback = lockActionReceivedCallback; +} + +void NetworkOpener::setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char *, const char *)) +{ + _configUpdateReceivedCallback = configUpdateReceivedCallback; +} + +void NetworkOpener::publishFloat(const char* topic, const float value, const uint8_t precision) +{ + char str[30]; + dtostrf(value, 0, precision, str); + char path[200] = {0}; + buildMqttPath(topic, path); + _network->device()->mqttClient()->publish(path, str); +} + +void NetworkOpener::publishInt(const char *topic, const int value) +{ + char str[30]; + itoa(value, str, 10); + char path[200] = {0}; + buildMqttPath(topic, path); + _network->device()->mqttClient()->publish(path, str); +} + +void NetworkOpener::publishUInt(const char *topic, const unsigned int value) +{ + char str[30]; + utoa(value, str, 10); + char path[200] = {0}; + buildMqttPath(topic, path); + _network->device()->mqttClient()->publish(path, str); +} + +void NetworkOpener::publishBool(const char *topic, const bool value) +{ + char str[2] = {0}; + str[0] = value ? '1' : '0'; + char path[200] = {0}; + buildMqttPath(topic, path); + _network->device()->mqttClient()->publish(path, str); +} + +void NetworkOpener::publishString(const char *topic, const char *value) +{ + char path[200] = {0}; + buildMqttPath(topic, path); + _network->device()->mqttClient()->publish(path, value); +} + +void NetworkOpener::buildMqttPath(const char* path, char* outPath) +{ + int offset = 0; + for(const char& c : _mqttPath) + { + if(c == 0x00) + { + break; + } + outPath[offset] = c; + ++offset; + } + int i=0; + while(outPath[i] != 0x00) + { + outPath[offset] = path[i]; + ++i; + ++offset; + } + outPath[i+1] = 0x00; +} + +void NetworkOpener::subscribe(const char *path) +{ + char prefixedPath[500]; + buildMqttPath(path, prefixedPath); + _network->device()->mqttClient()->subscribe(prefixedPath); +} + +bool NetworkOpener::comparePrefixedPath(const char *fullPath, const char *subPath) +{ + char prefixedPath[500]; + buildMqttPath(subPath, prefixedPath); + return strcmp(fullPath, prefixedPath) == 0; +} \ No newline at end of file diff --git a/NetworkOpener.h b/NetworkOpener.h new file mode 100644 index 0000000..2bcb1b1 --- /dev/null +++ b/NetworkOpener.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include "networkDevices/NetworkDevice.h" +#include "networkDevices/WifiDevice.h" +#include "networkDevices/W5500Device.h" +#include +#include +#include "NukiConstants.h" +#include "SpiffsCookie.h" +#include "NukiOpenerConstants.h" +#include "Network.h" + +class NetworkOpener +{ +public: + explicit NetworkOpener(Network* network, Preferences* preferences); + virtual ~NetworkOpener() = default; + + void initialize(); + void update(); + + void publishKeyTurnerState(const NukiOpener::KeyTurnerState& keyTurnerState, const NukiOpener::KeyTurnerState& lastKeyTurnerState); + void publishAuthorizationInfo(const uint32_t authId, const char* authName); + void publishCommandResult(const char* resultStr); + void publishBatteryReport(const NukiOpener::BatteryReport& batteryReport); + void publishConfig(const NukiOpener::Config& config); + void publishAdvancedConfig(const NukiOpener::AdvancedConfig& config); + + void setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char* value)); + void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* path, const char* value)); + +private: + static void onMqttDataReceivedCallback(char* topic, byte* payload, unsigned int length); + void onMqttDataReceived(char*& topic, byte*& payload, unsigned int& length); + bool comparePrefixedPath(const char* fullPath, const char* subPath); + + void publishFloat(const char* topic, const float value, const uint8_t precision = 2); + void publishInt(const char* topic, const int value); + void publishUInt(const char* topic, const unsigned int value); + void publishBool(const char* topic, const bool value); + void publishString(const char* topic, const char* value); + + void buildMqttPath(const char* path, char* outPath); + void subscribe(const char* path); + + Preferences* _preferences; + + Network* _network = nullptr; + + char _mqttPath[181] = {0}; + bool _isConnected = false; + + std::vector _configTopics; + + bool _firstTunerStatePublish = true; + + bool (*_lockActionReceivedCallback)(const char* value) = nullptr; + void (*_configUpdateReceivedCallback)(const char* path, const char* value) = nullptr; +}; diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index e3f1228..3f76e48 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -6,7 +6,7 @@ NukiOpenerWrapper* nukiOpenerInst; -NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, Network* network, Preferences* preferences) +NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences) : _deviceName(deviceName), _nukiOpener(deviceName, id), _bleScanner(scanner), @@ -115,7 +115,7 @@ void NukiOpenerWrapper::update() _network->publishCommandResult(resultStr); - Serial.print(F("Lock action result: ")); + Serial.print(F("Opener lock action result: ")); Serial.println(resultStr); _nextLockAction = (NukiOpener::LockAction)0xff; diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index 5358bb2..40d148e 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -1,7 +1,7 @@ #pragma once #include "NukiOpener.h" -#include "Network.h" +#include "NetworkOpener.h" #include "NukiOpenerConstants.h" #include "NukiDataTypes.h" #include "BleScanner.h" @@ -9,7 +9,7 @@ class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler { public: - NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, Network* network, Preferences* preferences); + NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences); virtual ~NukiOpenerWrapper(); void initialize(); @@ -44,7 +44,7 @@ private: std::string _deviceName; NukiOpener::NukiOpener _nukiOpener; BleScanner::Scanner* _bleScanner; - Network* _network; + NetworkOpener* _network; Preferences* _preferences; int _intervalLockstate = 0; // seconds int _intervalBattery = 0; // seconds diff --git a/main.cpp b/main.cpp index 1c01d20..9bde357 100644 --- a/main.cpp +++ b/main.cpp @@ -11,6 +11,7 @@ #include "NukiOpenerWrapper.h" Network* network = nullptr; +NetworkOpener* networkOpener = nullptr; WebCfgServer* webCfgServer = nullptr; NukiWrapper* nuki = nullptr; NukiOpenerWrapper* nukiOpener = nullptr; @@ -23,6 +24,7 @@ void networkTask(void *pvParameters) while(true) { network->update(); + networkOpener->update(); webCfgServer->update(); vTaskDelay(200 / portTICK_PERIOD_MS); } @@ -112,6 +114,8 @@ void setup() preferences->begin("nukihub", false); network = new Network(networkDevice, preferences); network->initialize(); + networkOpener = new NetworkOpener(network, preferences); + networkOpener->initialize(); uint32_t deviceId = preferences->getUInt(preference_deviceId); if(deviceId == 0) @@ -125,7 +129,7 @@ void setup() nuki = new NukiWrapper("NukiHub", deviceId, network, preferences); nuki->initialize(); - nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), network, preferences); + nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), networkOpener, preferences); nukiOpener->initialize(); webCfgServer = new WebCfgServer(nuki, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); From 1fb1f9b6a673191c8de83167521f28963c5e9af8 Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 30 May 2022 23:39:24 +0200 Subject: [PATCH 07/28] opener config struct changes --- Network.cpp | 4 --- NetworkOpener.cpp | 9 ++---- NukiOpenerWrapper.cpp | 70 +++++++++++++------------------------------ 3 files changed, 24 insertions(+), 59 deletions(-) diff --git a/Network.cpp b/Network.cpp index 80541de..1446cc9 100644 --- a/Network.cpp +++ b/Network.cpp @@ -292,12 +292,8 @@ void Network::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurnerSta if(_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) { - uint8_t level = (keyTurnerState.criticalBatteryState & 0b11111100) >> 1; bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0; - bool charging = (keyTurnerState.criticalBatteryState & 0b00000010) > 0; - publishInt(mqtt_topic_battery_level, level); // percent publishBool(mqtt_topic_battery_critical, critical); - publishBool(mqtt_topic_battery_charging, charging); } _firstTunerStatePublish = false; diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index e7d100d..fd8093a 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -157,21 +157,18 @@ void NetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batter { publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0); publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain); // milliwatt seconds - publishFloat(mqtt_topic_battery_max_turn_current, (float)batteryReport.maxTurnCurrent / 1000.0); - publishInt(mqtt_topic_battery_lock_distance, batteryReport.lockDistance); // degrees } void NetworkOpener::publishConfig(const NukiOpener::Config &config) { publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1); - publishBool(mqtt_topic_config_led_enabled, config.ledEnabled == 1); - publishInt(mqtt_topic_config_led_brightness, config.ledBrightness); + publishBool(mqtt_topic_config_led_enabled, config.ledFlashEnabled == 1); } void NetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &config) { - publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0); - publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1); +// publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0); +// publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1); } void NetworkOpener::setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char *)) diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index 3f76e48..bf6450c 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -89,22 +89,22 @@ void NukiOpenerWrapper::update() unsigned long ts = millis(); -// if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs) -// { -// _statusUpdated = false; -// _nextLockStateUpdateTs = ts + _intervalLockstate * 1000; -// updateKeyTurnerState(); -// } -// if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs) -// { -// _nextBatteryReportTs = ts + _intervalBattery * 1000; -// updateBatteryState(); -// } -// if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs) -// { -// _nextConfigUpdateTs = ts + _intervalConfig * 1000; -// updateConfig(); -// } + if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs) + { + _statusUpdated = false; + _nextLockStateUpdateTs = ts + _intervalLockstate * 1000; + updateKeyTurnerState(); + } + if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs) + { + _nextBatteryReportTs = ts + _intervalBattery * 1000; + updateBatteryState(); + } + if(_nextConfigUpdateTs == 0 || ts > _nextConfigUpdateTs) + { + _nextConfigUpdateTs = ts + _intervalConfig * 1000; + updateConfig(); + } if(_nextLockAction != (NukiOpener::LockAction)0xff) { @@ -148,7 +148,7 @@ void NukiOpenerWrapper::unpair() void NukiOpenerWrapper::updateKeyTurnerState() { _nukiOpener.requestKeyTurnerState(&_keyTurnerState); -// _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); + _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); if(_keyTurnerState.lockState != _lastKeyTurnerState.lockState) { @@ -167,15 +167,15 @@ void NukiOpenerWrapper::updateKeyTurnerState() void NukiOpenerWrapper::updateBatteryState() { _nukiOpener.requestBatteryReport(&_batteryReport); -// _network->publishBatteryReport(_batteryReport); + _network->publishBatteryReport(_batteryReport); } void NukiOpenerWrapper::updateConfig() { readConfig(); readAdvancedConfig(); -// _network->publishConfig(_nukiConfig); -// _network->publishAdvancedConfig(_nukiAdvancedConfig); + _network->publishConfig(_nukiConfig); + _network->publishAdvancedConfig(_nukiAdvancedConfig); } void NukiOpenerWrapper::updateAuthData() @@ -254,38 +254,10 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *va if(strcmp(topic, mqtt_topic_config_led_enabled) == 0) { bool newValue = atoi(value) > 0; - if(!_nukiConfigValid || _nukiConfig.ledEnabled == newValue) return; + if(!_nukiConfigValid || _nukiConfig.ledFlashEnabled == newValue) return; _nukiOpener.enableLedFlash(newValue); _nextConfigUpdateTs = millis() + 300; } - else if(strcmp(topic, mqtt_topic_config_led_brightness) == 0) - { - int newValue = atoi(value); - if(!_nukiConfigValid || _nukiConfig.ledBrightness == newValue) return; - _nukiOpener.setLedBrightness(newValue); - _nextConfigUpdateTs = millis() + 300; - } - else if(strcmp(topic, mqtt_topic_config_auto_unlock) == 0) - { - bool newValue = !(atoi(value) > 0); - if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoUnLockDisabled == newValue) return; - _nukiOpener.disableAutoUnlock(newValue); - _nextConfigUpdateTs = millis() + 300; - } - else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) - { - bool newValue = atoi(value) > 0; - if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; - _nukiOpener.enableAutoLock(newValue); - _nextConfigUpdateTs = millis() + 300; - } - else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) - { - bool newValue = atoi(value) > 0; - if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; - _nukiOpener.enableAutoLock(newValue); - _nextConfigUpdateTs = millis() + 300; - } } const NukiOpener::KeyTurnerState &NukiOpenerWrapper::keyTurnerState() From cc0dc230ec8dd1d88352f6bb3efd5a976bf9903a Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 30 May 2022 23:41:17 +0200 Subject: [PATCH 08/28] update nuki lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index bef10bf..b312f93 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit bef10bf8c5b7441d47815a5bf094e2e661d9d6a3 +Subproject commit b312f936eb45b862b3236ef48992bb57f6343263 From 0061c9af633dbc2857da2e2a217690984b9f38ba Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 18:44:55 +0200 Subject: [PATCH 09/28] use shared timeout --- CMakeLists.txt | 1 + NukiOpenerWrapper.cpp | 13 +++++++------ NukiOpenerWrapper.h | 3 ++- NukiWrapper.cpp | 7 ++++--- NukiWrapper.h | 3 ++- main.cpp | 8 ++++++-- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2f9357..ed3a719 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ file(GLOB SRCFILES lib/ESP32_BLE_Arduino-1.0.1/src/*.h lib/WiFiManager/WiFiManager.cpp lib/Crc16/Crc16.h + lib/nuki_ble/src/NukiTimeout.cpp lib/nuki_ble/src/NukiBle.cpp lib/nuki_ble/src/NukiOpener.cpp lib/nuki_ble/src/NukiConstants.h diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index bf6450c..0ff1a5d 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -6,12 +6,13 @@ NukiOpenerWrapper* nukiOpenerInst; -NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences) - : _deviceName(deviceName), - _nukiOpener(deviceName, id), - _bleScanner(scanner), - _network(network), - _preferences(preferences) +NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout) +: _deviceName(deviceName), + _nukiOpener(deviceName, id, nukiTimeout), + _bleScanner(scanner), + _network(network), + _preferences(preferences), + _nukiTimeout(nukiTimeout) { nukiOpenerInst = this; diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index 40d148e..c2626d1 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -9,7 +9,7 @@ class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler { public: - NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences); + NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout); virtual ~NukiOpenerWrapper(); void initialize(); @@ -46,6 +46,7 @@ private: BleScanner::Scanner* _bleScanner; NetworkOpener* _network; Preferences* _preferences; + Nuki::NukiTimeout* _nukiTimeout; int _intervalLockstate = 0; // seconds int _intervalBattery = 0; // seconds int _intervalConfig = 60 * 60; // seconds diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 4c811e9..7fc5038 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -6,11 +6,12 @@ NukiWrapper* nukiInst; -NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences) +NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout) : _deviceName(deviceName), - _nukiBle(deviceName, id), + _nukiBle(deviceName, id, nukiTimeout), _network(network), - _preferences(preferences) + _preferences(preferences), + _nukiTimeout(nukiTimeout) { nukiInst = this; diff --git a/NukiWrapper.h b/NukiWrapper.h index 122cee6..630352d 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -9,7 +9,7 @@ class NukiWrapper : public Nuki::SmartlockEventHandler { public: - NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences); + NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout); virtual ~NukiWrapper(); void initialize(); @@ -46,6 +46,7 @@ private: BleScanner::Scanner* _bleScanner; Network* _network; Preferences* _preferences; + Nuki::NukiTimeout* _nukiTimeout; int _intervalLockstate = 0; // seconds int _intervalBattery = 0; // seconds int _intervalConfig = 60 * 60; // seconds diff --git a/main.cpp b/main.cpp index 9bde357..eaa6301 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,7 @@ Network* network = nullptr; NetworkOpener* networkOpener = nullptr; WebCfgServer* webCfgServer = nullptr; +Nuki::NukiTimeout* nukiTimeout = nullptr; NukiWrapper* nuki = nullptr; NukiOpenerWrapper* nukiOpener = nullptr; PresenceDetection* presenceDetection = nullptr; @@ -36,6 +37,7 @@ void nukiTask(void *pvParameters) { nuki->update(); nukiOpener->update(); + nukiTimeout->update(); } } @@ -126,10 +128,12 @@ void setup() initEthServer(networkDevice); - nuki = new NukiWrapper("NukiHub", deviceId, network, preferences); + nukiTimeout = new Nuki::NukiTimeout(); + + nuki = new NukiWrapper("NukiHub", deviceId, network, preferences, nukiTimeout); nuki->initialize(); - nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), networkOpener, preferences); + nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), networkOpener, preferences, nukiTimeout); nukiOpener->initialize(); webCfgServer = new WebCfgServer(nuki, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); From cc21427d73fc4b9022ccac5fa0e2cfcaff2ae101 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 18:45:29 +0200 Subject: [PATCH 10/28] update ble lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index b312f93..e848f24 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit b312f936eb45b862b3236ef48992bb57f6343263 +Subproject commit e848f24c55de0dd5f427867425aa94e08b76eea2 From 5c43f098ceba15013b0b52989b6479fafdf0bf65 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 19:08:42 +0200 Subject: [PATCH 11/28] disable shared timeout --- NukiOpenerWrapper.cpp | 7 +++---- NukiOpenerWrapper.h | 3 +-- NukiWrapper.cpp | 7 +++---- NukiWrapper.h | 3 +-- main.cpp | 8 ++------ 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index 0ff1a5d..d1fb526 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -6,13 +6,12 @@ NukiOpenerWrapper* nukiOpenerInst; -NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout) +NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences) : _deviceName(deviceName), - _nukiOpener(deviceName, id, nukiTimeout), + _nukiOpener(deviceName, id), _bleScanner(scanner), _network(network), - _preferences(preferences), - _nukiTimeout(nukiTimeout) + _preferences(preferences) { nukiOpenerInst = this; diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index c2626d1..40d148e 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -9,7 +9,7 @@ class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler { public: - NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout); + NukiOpenerWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkOpener* network, Preferences* preferences); virtual ~NukiOpenerWrapper(); void initialize(); @@ -46,7 +46,6 @@ private: BleScanner::Scanner* _bleScanner; NetworkOpener* _network; Preferences* _preferences; - Nuki::NukiTimeout* _nukiTimeout; int _intervalLockstate = 0; // seconds int _intervalBattery = 0; // seconds int _intervalConfig = 60 * 60; // seconds diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 7fc5038..4c811e9 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -6,12 +6,11 @@ NukiWrapper* nukiInst; -NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout) +NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences) : _deviceName(deviceName), - _nukiBle(deviceName, id, nukiTimeout), + _nukiBle(deviceName, id), _network(network), - _preferences(preferences), - _nukiTimeout(nukiTimeout) + _preferences(preferences) { nukiInst = this; diff --git a/NukiWrapper.h b/NukiWrapper.h index 630352d..122cee6 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -9,7 +9,7 @@ class NukiWrapper : public Nuki::SmartlockEventHandler { public: - NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences, Nuki::NukiTimeout* nukiTimeout); + NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences); virtual ~NukiWrapper(); void initialize(); @@ -46,7 +46,6 @@ private: BleScanner::Scanner* _bleScanner; Network* _network; Preferences* _preferences; - Nuki::NukiTimeout* _nukiTimeout; int _intervalLockstate = 0; // seconds int _intervalBattery = 0; // seconds int _intervalConfig = 60 * 60; // seconds diff --git a/main.cpp b/main.cpp index eaa6301..9bde357 100644 --- a/main.cpp +++ b/main.cpp @@ -13,7 +13,6 @@ Network* network = nullptr; NetworkOpener* networkOpener = nullptr; WebCfgServer* webCfgServer = nullptr; -Nuki::NukiTimeout* nukiTimeout = nullptr; NukiWrapper* nuki = nullptr; NukiOpenerWrapper* nukiOpener = nullptr; PresenceDetection* presenceDetection = nullptr; @@ -37,7 +36,6 @@ void nukiTask(void *pvParameters) { nuki->update(); nukiOpener->update(); - nukiTimeout->update(); } } @@ -128,12 +126,10 @@ void setup() initEthServer(networkDevice); - nukiTimeout = new Nuki::NukiTimeout(); - - nuki = new NukiWrapper("NukiHub", deviceId, network, preferences, nukiTimeout); + nuki = new NukiWrapper("NukiHub", deviceId, network, preferences); nuki->initialize(); - nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), networkOpener, preferences, nukiTimeout); + nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), networkOpener, preferences); nukiOpener->initialize(); webCfgServer = new WebCfgServer(nuki, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); From 76c0bc54274f94f6359d74a6cbb0eb45b846b6d8 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 19:10:15 +0200 Subject: [PATCH 12/28] update nuki lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index e848f24..3018c24 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit e848f24c55de0dd5f427867425aa94e08b76eea2 +Subproject commit 3018c24806096e827e4342edbaac5cf086a77186 From 1ce8eb6603348d3fd0e24eb228c5bc645c5798df Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 19:47:27 +0200 Subject: [PATCH 13/28] allow to enabld or disable lock/opener --- CMakeLists.txt | 2 +- NukiWrapper.cpp | 15 +++-------- NukiWrapper.h | 4 +-- PreferencesKeys.h | 3 +++ WebCfgServer.cpp | 63 ++++++++++++++++++++++++++++++++++++++--------- main.cpp | 56 ++++++++++++++++++++++++++++++++++------- 6 files changed, 107 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed3a719..6c774a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(nuki_hub CXX) # ARDUHAL_LOG_LEVEL_NONE, define ARDUHAL_LOG_LEVEL_ERROR, define ARDUHAL_LOG_LEVEL_WARN, define ARDUHAL_LOG_LEVEL_INFO, # define ARDUHAL_LOG_LEVEL_DEBUG, define ARDUHAL_LOG_LEVEL_VERBOSE -set(LOG_LEVEL ARDUHAL_LOG_LEVEL_DEBUG) +set(LOG_LEVEL ARDUHAL_LOG_LEVEL_NONE) include_directories(${PROJECT_NAME} PRIVATE diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 4c811e9..bd79123 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -6,8 +6,9 @@ NukiWrapper* nukiInst; -NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences) +NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, Network* network, Preferences* preferences) : _deviceName(deviceName), + _bleScanner(scanner), _nukiBle(deviceName, id), _network(network), _preferences(preferences) @@ -27,16 +28,13 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, Network* ne NukiWrapper::~NukiWrapper() { - delete _bleScanner; _bleScanner = nullptr; } void NukiWrapper::initialize() { - _bleScanner = new BleScanner::Scanner(); - _bleScanner->initialize(_deviceName); - _bleScanner->setScanDuration(10); + _nukiBle.initialize(); _nukiBle.registerBleScanner(_bleScanner); @@ -88,8 +86,6 @@ void NukiWrapper::update() } } - vTaskDelay( 20 / portTICK_PERIOD_MS); - _bleScanner->update(); _nukiBle.updateConnectionState(); unsigned long ts = millis(); @@ -304,11 +300,6 @@ const bool NukiWrapper::isPaired() return _paired; } -BleScanner::Scanner* NukiWrapper::bleScanner() -{ - return _bleScanner; -} - void NukiWrapper::notify(Nuki::EventType eventType) { if(eventType == Nuki::EventType::KeyTurnerStatusUpdated) diff --git a/NukiWrapper.h b/NukiWrapper.h index 122cee6..f6cc4c4 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -9,7 +9,7 @@ class NukiWrapper : public Nuki::SmartlockEventHandler { public: - NukiWrapper(const std::string& deviceName, uint32_t id, Network* network, Preferences* preferences); + NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, Network* network, Preferences* preferences); virtual ~NukiWrapper(); void initialize(); @@ -22,8 +22,6 @@ public: const NukiLock::KeyTurnerState& keyTurnerState(); const bool isPaired(); - BleScanner::Scanner* bleScanner(); - void notify(Nuki::EventType eventType) override; private: diff --git a/PreferencesKeys.h b/PreferencesKeys.h index f7253fe..8e48fc1 100644 --- a/PreferencesKeys.h +++ b/PreferencesKeys.h @@ -1,11 +1,14 @@ #pragma once +#define preference_started_befores "run" #define preference_deviceId "deviceId" #define preference_mqtt_broker "mqttbroker" #define preference_mqtt_broker_port "mqttport" #define preference_mqtt_user "mqttuser" #define preference_mqtt_password "mqttpass" +#define preference_lock_enabled "lockena" #define preference_mqtt_lock_path "mqttpath" +#define preference_opener_enabled "openerena" #define preference_mqtt_opener_path "mqttoppath" #define preference_hostname "hostname" #define preference_network_timeout "nettmout" diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index a6e7283..6711c56 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -108,6 +108,8 @@ bool WebCfgServer::processArgs(String& message) bool clearCredentials = false; bool publishAuthData = false; + bool lockEnabled = false; + bool openerEnabled = false; int count = _server.args(); for(int index = 0; index < count; index++) @@ -184,6 +186,14 @@ bool WebCfgServer::processArgs(String& message) { publishAuthData = true; } + else if(key == "LOCKENA") + { + lockEnabled = true; + } + else if(key == "OPENA") + { + openerEnabled = true; + } else if(key == "CREDUSER") { if(value == "#") @@ -201,7 +211,7 @@ bool WebCfgServer::processArgs(String& message) _preferences->putString(preference_cred_password, value); configChanged = true; } - else if(key == "NUKIPIN") + else if(key == "NUKIPIN" && _nuki != nullptr) { if(value == "#") { @@ -222,6 +232,18 @@ bool WebCfgServer::processArgs(String& message) configChanged = true; } + if(_preferences->getBool(preference_lock_enabled) != lockEnabled) + { + _preferences->putBool(preference_lock_enabled, lockEnabled); + configChanged = true; + } + + if(_preferences->getBool(preference_opener_enabled) != openerEnabled) + { + _preferences->putBool(preference_opener_enabled, openerEnabled); + configChanged = true; + } + if(clearMqttCredentials) { _preferences->putString(preference_mqtt_user, ""); @@ -262,15 +284,23 @@ void WebCfgServer::buildHtml(String& response) String version = " "; version.concat(nuki_hub_version); - char lockstateArr[20]; - NukiLock::lockstateToString(_nuki->keyTurnerState().lockState, lockstateArr); - String lockState = " "; - lockState.concat(lockstateArr); - response.concat(""); - printParameter(response, "Paired", _nuki->isPaired() ? " Yes" : " No"); + + bool lockEnabled = _preferences->getBool(preference_lock_enabled); + + String lockState = " "; + if(lockEnabled) + { + char lockstateArr[20]; + NukiLock::lockstateToString(_nuki->keyTurnerState().lockState, lockstateArr); + lockState.concat(lockstateArr); + printParameter(response, "Paired", _nuki->isPaired() ? " Yes" : " No"); + } printParameter(response, "MQTT Connected", _network->isMqttConnected() ? " Yes" : " No"); - printParameter(response, "Lock state", lockState.c_str()); + if(lockEnabled) + { + printParameter(response, "Lock state", lockState.c_str()); + } printParameter(response, "Firmware", version.c_str()); response.concat("


"); @@ -282,8 +312,16 @@ void WebCfgServer::buildHtml(String& response) printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); - printInputField(response, "MQTTPATH", "MQTT Lock Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180); - printInputField(response, "MQTTOPPATH", "MQTT Opener Path", _preferences->getString(preference_mqtt_opener_path).c_str(), 180); + printCheckBox(response, "LOCKENA", "NUKI Lock enabled", _preferences->getBool(preference_lock_enabled)); + if(_preferences->getBool(preference_lock_enabled)) + { + printInputField(response, "MQTTPATH", "MQTT Lock Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180); + } + printCheckBox(response, "OPENA", "NUKI Opener enabled", _preferences->getBool(preference_opener_enabled)); + if(_preferences->getBool(preference_opener_enabled)) + { + printInputField(response, "MQTTOPPATH", "MQTT Opener Path", _preferences->getString(preference_mqtt_opener_path).c_str(), 180); + } printInputField(response, "HOSTNAME", "Host name", _preferences->getString(preference_hostname).c_str(), 100); printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5); printInputField(response, "LSTINT", "Query interval lock state (seconds)", _preferences->getInt(preference_query_interval_lockstate), 10); @@ -413,7 +451,10 @@ void WebCfgServer::processUnpair() buildConfirmHtml(response, "Unpairing NUKI and restarting.", 3); _server.send(200, "text/html", response); - _nuki->unpair(); + if(_nuki != nullptr) + { + _nuki->unpair(); + } waitAndProcess(false, 1000); ESP.restart(); } diff --git a/main.cpp b/main.cpp index 9bde357..b4566bb 100644 --- a/main.cpp +++ b/main.cpp @@ -13,12 +13,16 @@ Network* network = nullptr; NetworkOpener* networkOpener = nullptr; WebCfgServer* webCfgServer = nullptr; +BleScanner::Scanner* bleScanner = nullptr; NukiWrapper* nuki = nullptr; NukiOpenerWrapper* nukiOpener = nullptr; PresenceDetection* presenceDetection = nullptr; Preferences* preferences = nullptr; EthServer* ethServer = nullptr; +bool lockEnabled = false; +bool openerEnabled = false; + void networkTask(void *pvParameters) { while(true) @@ -34,8 +38,16 @@ void nukiTask(void *pvParameters) { while(true) { - nuki->update(); - nukiOpener->update(); + bleScanner->update(); + vTaskDelay( 20 / portTICK_PERIOD_MS); + if(lockEnabled) + { + nuki->update(); + } + if(openerEnabled) + { + nukiOpener->update(); + } } } @@ -101,17 +113,29 @@ void initEthServer(const NetworkDeviceType device) } } +void initNuki() +{ + +} + void setup() { pinMode(NETWORK_SELECT, INPUT_PULLUP); Serial.begin(115200); + preferences = new Preferences(); + preferences->begin("nukihub", false); + + if(!preferences->getBool(preference_started_befores)) + { + preferences->putBool(preference_started_befores, true); + preferences->putBool(preference_lock_enabled, true); + } + // const NetworkDeviceType networkDevice = NetworkDeviceType::WiFi; const NetworkDeviceType networkDevice = digitalRead(NETWORK_SELECT) == HIGH ? NetworkDeviceType::WiFi : NetworkDeviceType::W5500; - preferences = new Preferences(); - preferences->begin("nukihub", false); network = new Network(networkDevice, preferences); network->initialize(); networkOpener = new NetworkOpener(network, preferences); @@ -126,16 +150,30 @@ void setup() initEthServer(networkDevice); - nuki = new NukiWrapper("NukiHub", deviceId, network, preferences); - nuki->initialize(); + bleScanner = new BleScanner::Scanner(); + bleScanner->initialize("NukiHub"); + bleScanner->setScanDuration(10); - nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, nuki->bleScanner(), networkOpener, preferences); - nukiOpener->initialize(); + lockEnabled = preferences->getBool(preference_lock_enabled); + Serial.println(lockEnabled ? F("NUKI Lock enabled") : F("NUKI Lock disabled")); + if(lockEnabled) + { + nuki = new NukiWrapper("NukiHub", deviceId, bleScanner, network, preferences); + nuki->initialize(); + } + + openerEnabled = preferences->getBool(preference_opener_enabled); + Serial.println(openerEnabled ? F("NUKI Opener enabled") : F("NUKI Opener disabled")); + if(openerEnabled) + { + nukiOpener = new NukiOpenerWrapper("NukiHub", deviceId, bleScanner, networkOpener, preferences); + nukiOpener->initialize(); + } webCfgServer = new WebCfgServer(nuki, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); webCfgServer->initialize(); - presenceDetection = new PresenceDetection(preferences, nuki->bleScanner(), network); + presenceDetection = new PresenceDetection(preferences, bleScanner, network); presenceDetection->initialize(); setupTasks(); From d58f4b6b1d9a4b4c40008d0bcbeb5550ba40cc15 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 20:42:33 +0200 Subject: [PATCH 14/28] fix config portal --- NukiOpenerWrapper.cpp | 2 - NukiWrapper.cpp | 2 - WebCfgServer.cpp | 92 ++++++++++++++++++++++--------------------- WebCfgServer.h | 1 + main.cpp | 8 ++++ 5 files changed, 57 insertions(+), 48 deletions(-) diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index d1fb526..d61618c 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -72,8 +72,6 @@ void NukiOpenerWrapper::update() if (!_paired) { Serial.println(F("Nuki opener start pairing")); - _bleScanner->update(); - vTaskDelay( 5000 / portTICK_PERIOD_MS); if (_nukiOpener.pairNuki() == NukiOpener::PairingResult::Success) { Serial.println(F("Nuki opener paired")); _paired = true; diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index bd79123..dc05f29 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -73,8 +73,6 @@ void NukiWrapper::update() if (!_paired) { Serial.println(F("Nuki start pairing")); - _bleScanner->update(); - vTaskDelay( 5000 / portTICK_PERIOD_MS); if (_nukiBle.pairNuki() == Nuki::PairingResult::Success) { Serial.println(F("Nuki paired")); _paired = true; diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index 6711c56..f7bfd98 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -26,7 +26,6 @@ WebCfgServer::WebCfgServer(NukiWrapper* nuki, Network* network, EthServer* ethSe } } - void WebCfgServer::initialize() { _server.on("/", [&]() { @@ -45,6 +44,14 @@ void WebCfgServer::initialize() buildCredHtml(response); _server.send(200, "text/html", response); }); + _server.on("/mqttconfig", [&]() { + if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { + return _server.requestAuthentication(); + } + String response = ""; + buildMqttConfigHtml(response); + _server.send(200, "text/html", response); + }); _server.on("/wifi", [&]() { if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { return _server.requestAuthentication(); @@ -107,10 +114,6 @@ bool WebCfgServer::processArgs(String& message) bool clearMqttCredentials = false; bool clearCredentials = false; - bool publishAuthData = false; - bool lockEnabled = false; - bool openerEnabled = false; - int count = _server.args(); for(int index = 0; index < count; index++) { @@ -184,15 +187,18 @@ bool WebCfgServer::processArgs(String& message) } else if(key == "PUBAUTH") { - publishAuthData = true; + _preferences->putBool(preference_publish_authdata, (value == "1")); + configChanged = true; } else if(key == "LOCKENA") { - lockEnabled = true; + _preferences->putBool(preference_lock_enabled, (value == "1")); + configChanged = true; } else if(key == "OPENA") { - openerEnabled = true; + _preferences->putBool(preference_opener_enabled, (value == "1")); + configChanged = true; } else if(key == "CREDUSER") { @@ -226,24 +232,6 @@ bool WebCfgServer::processArgs(String& message) } } - if(_preferences->getBool(preference_publish_authdata) != publishAuthData) - { - _preferences->putBool(preference_publish_authdata, publishAuthData); - configChanged = true; - } - - if(_preferences->getBool(preference_lock_enabled) != lockEnabled) - { - _preferences->putBool(preference_lock_enabled, lockEnabled); - configChanged = true; - } - - if(_preferences->getBool(preference_opener_enabled) != openerEnabled) - { - _preferences->putBool(preference_opener_enabled, openerEnabled); - configChanged = true; - } - if(clearMqttCredentials) { _preferences->putString(preference_mqtt_user, ""); @@ -304,14 +292,15 @@ void WebCfgServer::buildHtml(String& response) printParameter(response, "Firmware", version.c_str()); response.concat("

"); + response.concat("

MQTT Configuration

"); + response.concat("
"); + response.concat(""); + response.concat("
"); + response.concat("
"); - response.concat("

Configuration

"); + response.concat("

Configuration

"); response.concat(""); - printInputField(response, "MQTTSERVER", "MQTT Broker", _preferences->getString(preference_mqtt_broker).c_str(), 100); - printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); - printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); - printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); printCheckBox(response, "LOCKENA", "NUKI Lock enabled", _preferences->getBool(preference_lock_enabled)); if(_preferences->getBool(preference_lock_enabled)) { @@ -332,9 +321,9 @@ void WebCfgServer::buildHtml(String& response) response.concat("
"); - response.concat("

"); + response.concat(""); - response.concat("

Credentials

"); + response.concat("

Credentials

"); response.concat(""); response.concat(""); response.concat(""); @@ -386,6 +375,21 @@ void WebCfgServer::buildCredHtml(String &response) response.concat("\n"); } +void WebCfgServer::buildMqttConfigHtml(String &response) +{ + response.concat(""); + response.concat("

MQTT COnfiguration

"); + response.concat("
"); + printInputField(response, "MQTTSERVER", "MQTT Broker", _preferences->getString(preference_mqtt_broker).c_str(), 100); + printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); + printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); + printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); + response.concat("
"); + response.concat("
"); + response.concat(""); + +} + void WebCfgServer::buildConfirmHtml(String &response, const String &message, uint32_t redirectDelay) { String delay(redirectDelay); @@ -510,20 +514,20 @@ void WebCfgServer::printInputField(String& response, void WebCfgServer::printCheckBox(String &response, const char *token, const char *description, const bool value) { - response.concat(""); - response.concat(""); + response.concat(""); response.concat(description); - response.concat(""); - response.concat(""); - response.concat(" "); + + response.concat(""); + + response.concat(""); - response.concat(""); - response.concat(""); + response.concat("/>"); } void WebCfgServer::printParameter(String& response, const char *description, const char *value) diff --git a/WebCfgServer.h b/WebCfgServer.h index 7b6af4f..f144e64 100644 --- a/WebCfgServer.h +++ b/WebCfgServer.h @@ -31,6 +31,7 @@ private: bool processArgs(String& message); void buildHtml(String& response); void buildCredHtml(String& response); + void buildMqttConfigHtml(String& response); void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5); void buildConfigureWifiHtml(String& response); void processUnpair(); diff --git a/main.cpp b/main.cpp index b4566bb..9eb25ad 100644 --- a/main.cpp +++ b/main.cpp @@ -40,6 +40,14 @@ void nukiTask(void *pvParameters) { bleScanner->update(); vTaskDelay( 20 / portTICK_PERIOD_MS); + + bool needsPairing = (lockEnabled && !nuki->isPaired()) || (openerEnabled && !nukiOpener->isPaired()); + + if (needsPairing) + { + vTaskDelay( 5000 / portTICK_PERIOD_MS); + } + if(lockEnabled) { nuki->update(); From d6bd7dddf45323e9cf32d19f929ca9b72f743d24 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 20:49:44 +0200 Subject: [PATCH 15/28] shop opener info in config portal --- WebCfgServer.cpp | 29 +++++++++++++++++------------ WebCfgServer.h | 4 +++- main.cpp | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index f7bfd98..0f95291 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -3,9 +3,10 @@ #include "Version.h" #include "hardware/WifiEthServer.h" -WebCfgServer::WebCfgServer(NukiWrapper* nuki, Network* network, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal) +WebCfgServer::WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, Network* network, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal) : _server(ethServer), _nuki(nuki), + _nukiOpener(nukiOpener), _network(network), _preferences(preferences), _allowRestartToPortal(allowRestartToPortal) @@ -274,25 +275,29 @@ void WebCfgServer::buildHtml(String& response) response.concat(""); - bool lockEnabled = _preferences->getBool(preference_lock_enabled); - - String lockState = " "; - if(lockEnabled) + printParameter(response, "MQTT Connected", _network->isMqttConnected() ? " Yes" : " No"); + if(_nuki != nullptr) { + String lockState = " "; char lockstateArr[20]; NukiLock::lockstateToString(_nuki->keyTurnerState().lockState, lockstateArr); lockState.concat(lockstateArr); - printParameter(response, "Paired", _nuki->isPaired() ? " Yes" : " No"); + printParameter(response, "NUKI Lock Paired", _nuki->isPaired() ? " Yes" : " No"); + printParameter(response, "NUKI Lock state", lockState.c_str()); } - printParameter(response, "MQTT Connected", _network->isMqttConnected() ? " Yes" : " No"); - if(lockEnabled) + if(_nukiOpener != nullptr) { - printParameter(response, "Lock state", lockState.c_str()); + String lockState = " "; + char lockstateArr[20]; + NukiOpener::lockstateToString(_nukiOpener->keyTurnerState().lockState, lockstateArr); + lockState.concat(lockstateArr); + printParameter(response, "NUKI Lock Paired", _nukiOpener->isPaired() ? " Yes" : " No"); + printParameter(response, "NUKI Lock state", lockState.c_str()); } printParameter(response, "Firmware", version.c_str()); response.concat("


"); - response.concat("

MQTT Configuration

"); + response.concat("

MQTT and Network Configuration

"); response.concat("
"); response.concat(""); response.concat("
"); @@ -311,8 +316,6 @@ void WebCfgServer::buildHtml(String& response) { printInputField(response, "MQTTOPPATH", "MQTT Opener Path", _preferences->getString(preference_mqtt_opener_path).c_str(), 180); } - printInputField(response, "HOSTNAME", "Host name", _preferences->getString(preference_hostname).c_str(), 100); - printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5); printInputField(response, "LSTINT", "Query interval lock state (seconds)", _preferences->getInt(preference_query_interval_lockstate), 10); printInputField(response, "BATINT", "Query interval battery (seconds)", _preferences->getInt(preference_query_interval_battery), 10); printCheckBox(response, "PUBAUTH", "Publish auth data (May reduce battery life)", _preferences->getBool(preference_publish_authdata)); @@ -380,10 +383,12 @@ void WebCfgServer::buildMqttConfigHtml(String &response) response.concat("
"); response.concat("

MQTT COnfiguration

"); response.concat(""); + printInputField(response, "HOSTNAME", "Host name", _preferences->getString(preference_hostname).c_str(), 100); printInputField(response, "MQTTSERVER", "MQTT Broker", _preferences->getString(preference_mqtt_broker).c_str(), 100); printInputField(response, "MQTTPORT", "MQTT Broker port", _preferences->getInt(preference_mqtt_broker_port), 5); printInputField(response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30); printInputField(response, "MQTTPASS", "MQTT Password", "*", 30, true); + printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5); response.concat("
"); response.concat("
"); response.concat("
"); diff --git a/WebCfgServer.h b/WebCfgServer.h index f144e64..9591bbb 100644 --- a/WebCfgServer.h +++ b/WebCfgServer.h @@ -4,6 +4,7 @@ #include #include "NukiWrapper.h" #include "Network.h" +#include "NukiOpenerWrapper.h" enum class TokenType { @@ -20,7 +21,7 @@ enum class TokenType class WebCfgServer { public: - WebCfgServer(NukiWrapper* nuki, Network* network, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal); + WebCfgServer(NukiWrapper* nuki, NukiOpenerWrapper* nukiOpener, Network* network, EthServer* ethServer, Preferences* preferences, bool allowRestartToPortal); ~WebCfgServer() = default; void initialize(); @@ -48,6 +49,7 @@ private: WebServer _server; NukiWrapper* _nuki; + NukiOpenerWrapper* _nukiOpener; Network* _network; Preferences* _preferences; diff --git a/main.cpp b/main.cpp index 9eb25ad..9c09801 100644 --- a/main.cpp +++ b/main.cpp @@ -178,7 +178,7 @@ void setup() nukiOpener->initialize(); } - webCfgServer = new WebCfgServer(nuki, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); + webCfgServer = new WebCfgServer(nuki, nukiOpener, network, ethServer, preferences, networkDevice == NetworkDeviceType::WiFi); webCfgServer->initialize(); presenceDetection = new PresenceDetection(preferences, bleScanner, network); From fec38ada9c1ccd80b2f7c7bd53fbc40a611be783 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 21:02:34 +0200 Subject: [PATCH 16/28] add option to unpair opener --- WebCfgServer.cpp | 64 +++++++++++++++++++++++++++++++----------------- WebCfgServer.h | 2 +- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index 0f95291..e4e3cd3 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -61,12 +61,19 @@ void WebCfgServer::initialize() buildConfigureWifiHtml(response); _server.send(200, "text/html", response); }); - _server.on("/unpair", [&]() { + _server.on("/unpairlock", [&]() { if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { return _server.requestAuthentication(); } - processUnpair(); + processUnpair(false); + }); + _server.on("/unpairopener", [&]() { + if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { + return _server.requestAuthentication(); + } + + processUnpair(true); }); _server.on("/wifimanager", [&]() { if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { @@ -282,7 +289,7 @@ void WebCfgServer::buildHtml(String& response) char lockstateArr[20]; NukiLock::lockstateToString(_nuki->keyTurnerState().lockState, lockstateArr); lockState.concat(lockstateArr); - printParameter(response, "NUKI Lock Paired", _nuki->isPaired() ? " Yes" : " No"); + printParameter(response, "NUKI Lock paired", _nuki->isPaired() ? " Yes" : " No"); printParameter(response, "NUKI Lock state", lockState.c_str()); } if(_nukiOpener != nullptr) @@ -291,8 +298,8 @@ void WebCfgServer::buildHtml(String& response) char lockstateArr[20]; NukiOpener::lockstateToString(_nukiOpener->keyTurnerState().lockState, lockstateArr); lockState.concat(lockstateArr); - printParameter(response, "NUKI Lock Paired", _nukiOpener->isPaired() ? " Yes" : " No"); - printParameter(response, "NUKI Lock state", lockState.c_str()); + printParameter(response, "NUKI Opener paired", _nukiOpener->isPaired() ? " Yes" : " No"); + printParameter(response, "NUKI Opener state", lockState.c_str()); } printParameter(response, "Firmware", version.c_str()); response.concat("

"); @@ -366,13 +373,28 @@ void WebCfgServer::buildCredHtml(String &response) response.concat(""); _confirmCode = generateConfirmCode(); - response.concat("

Unpair NUKI

"); - response.concat("
"); - String message = "Type "; - message.concat(_confirmCode); - message.concat(" to confirm unpair"); - printInputField(response, "CONFIRMTOKEN", message.c_str(), "", 10); - response.concat("

"); + if(_nuki != nullptr) + { + response.concat("

Unpair NUKI Lock

"); + response.concat(""); + String message = "Type "; + message.concat(_confirmCode); + message.concat(" to confirm unpair"); + printInputField(response, "CONFIRMTOKEN", message.c_str(), "", 10); + response.concat("

"); + } + + if(_nukiOpener != nullptr) + { + response.concat("

Unpair NUKI Opener

"); + response.concat("
"); + String message = "Type "; + message.concat(_confirmCode); + message.concat(" to confirm unpair"); + printInputField(response, "CONFIRMTOKEN", message.c_str(), "", 10); + response.concat("

"); + } + response.concat("\n"); response.concat("\n"); @@ -428,15 +450,7 @@ void WebCfgServer::buildConfigureWifiHtml(String &response) response.concat("\n"); } -//printInputField(response, "CONFIRMTOKEN", "Type confirm", "", 10); - - -//int count = _server.args(); -//for(int index = 0; index < count; index++) -//{ -//String key = _server.argName(index); -//String value = _server.arg(index); -void WebCfgServer::processUnpair() +void WebCfgServer::processUnpair(bool opener) { String response = ""; if(_server.args() == 0) @@ -458,12 +472,16 @@ void WebCfgServer::processUnpair() } } - buildConfirmHtml(response, "Unpairing NUKI and restarting.", 3); + buildConfirmHtml(response, opener ? "Unpairing NUKI Opener and restarting." : "Unpairing NUKI Lock and restarting.", 3); _server.send(200, "text/html", response); - if(_nuki != nullptr) + if(!opener && _nuki != nullptr) { _nuki->unpair(); } + if(opener && _nukiOpener != nullptr) + { + _nukiOpener->unpair(); + } waitAndProcess(false, 1000); ESP.restart(); } diff --git a/WebCfgServer.h b/WebCfgServer.h index 9591bbb..f8152bf 100644 --- a/WebCfgServer.h +++ b/WebCfgServer.h @@ -35,7 +35,7 @@ private: void buildMqttConfigHtml(String& response); void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5); void buildConfigureWifiHtml(String& response); - void processUnpair(); + void processUnpair(bool opener); void buildHtmlHeader(String& response); void printInputField(String& response, const char* token, const char* description, const char* value, const size_t maxLength, const bool isPassword = false); From eb4c48405c94fb410635ea433a2879211ad62d5e Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 21:14:50 +0200 Subject: [PATCH 17/28] allow to set opener PIN --- CMakeLists.txt | 2 +- WebCfgServer.cpp | 45 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c774a2..ed3a719 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(nuki_hub CXX) # ARDUHAL_LOG_LEVEL_NONE, define ARDUHAL_LOG_LEVEL_ERROR, define ARDUHAL_LOG_LEVEL_WARN, define ARDUHAL_LOG_LEVEL_INFO, # define ARDUHAL_LOG_LEVEL_DEBUG, define ARDUHAL_LOG_LEVEL_VERBOSE -set(LOG_LEVEL ARDUHAL_LOG_LEVEL_NONE) +set(LOG_LEVEL ARDUHAL_LOG_LEVEL_DEBUG) include_directories(${PROJECT_NAME} PRIVATE diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index e4e3cd3..ac258e9 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -229,15 +229,28 @@ bool WebCfgServer::processArgs(String& message) { if(value == "#") { - message = "PIN cleared"; + message = "NUKI Lock PIN cleared"; _nuki->setPin(0xffff); } else { - message = "PIN saved"; + message = "NUKI Lock PIN saved"; _nuki->setPin(value.toInt()); } } + else if(key == "NUKIOPPIN" && _nukiOpener != nullptr) + { + if(value == "#") + { + message = "NUKI Opener PIN cleared"; + _nukiOpener->setPin(0xffff); + } + else + { + message = "NUKI Opener PIN saved"; + _nukiOpener->setPin(value.toInt()); + } + } } if(clearMqttCredentials) @@ -364,13 +377,27 @@ void WebCfgServer::buildCredHtml(String &response) response.concat("
"); response.concat(""); - response.concat("

"); - response.concat("

NUKI Pin Code

"); - response.concat(""); - printInputField(response, "NUKIPIN", "PIN Code (# to clear)", "*", 20, true); - response.concat("
"); - response.concat("
"); - response.concat("
"); + if(_nuki != nullptr) + { + response.concat("

"); + response.concat("

NUKI Lock PIN

"); + response.concat(""); + printInputField(response, "NUKIPIN", "PIN Code (# to clear)", "*", 20, true); + response.concat("
"); + response.concat("
"); + response.concat("
"); + } + + if(_nukiOpener != nullptr) + { + response.concat("

"); + response.concat("

NUKI Opener PIN

"); + response.concat(""); + printInputField(response, "NUKIOPPIN", "PIN Code (# to clear)", "*", 20, true); + response.concat("
"); + response.concat("
"); + response.concat("
"); + } _confirmCode = generateConfirmCode(); if(_nuki != nullptr) From a507c59f47aed8c08ebcd347f2f715534681c529 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 22:26:30 +0200 Subject: [PATCH 18/28] remove NukiTimeout :) --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed3a719..d2f9357 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,6 @@ file(GLOB SRCFILES lib/ESP32_BLE_Arduino-1.0.1/src/*.h lib/WiFiManager/WiFiManager.cpp lib/Crc16/Crc16.h - lib/nuki_ble/src/NukiTimeout.cpp lib/nuki_ble/src/NukiBle.cpp lib/nuki_ble/src/NukiOpener.cpp lib/nuki_ble/src/NukiConstants.h From d5812c6015ceddc1dbfec82ab68765684fa5fe3f Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 1 Jun 2022 22:27:52 +0200 Subject: [PATCH 19/28] update nuki lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index 3018c24..bb36925 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit 3018c24806096e827e4342edbaac5cf086a77186 +Subproject commit bb36925d9a0b5fdb436b3ad2430a81d3d37a1272 From 9fd152050397b259616d1458e1debba8d189b8b3 Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 5 Jun 2022 21:46:21 +0200 Subject: [PATCH 20/28] cmakelist changes for nuki lib --- CMakeLists.txt | 2 ++ NukiWrapper.cpp | 44 ++++++++++++++++++++++---------------------- NukiWrapper.h | 4 ++-- lib/nuki_ble | 2 +- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2f9357..2b57b64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,8 @@ file(GLOB SRCFILES lib/WiFiManager/WiFiManager.cpp lib/Crc16/Crc16.h lib/nuki_ble/src/NukiBle.cpp + lib/nuki_ble/src/NukiBle.hpp + lib/nuki_ble/src/NukiLock.cpp lib/nuki_ble/src/NukiOpener.cpp lib/nuki_ble/src/NukiConstants.h lib/nuki_ble/src/NukiOpenerConstants.h diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index dc05f29..b1e8493 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -9,7 +9,7 @@ NukiWrapper* nukiInst; NukiWrapper::NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, Network* network, Preferences* preferences) : _deviceName(deviceName), _bleScanner(scanner), - _nukiBle(deviceName, id), + _nukiLock(deviceName, id), _network(network), _preferences(preferences) { @@ -35,8 +35,8 @@ NukiWrapper::~NukiWrapper() void NukiWrapper::initialize() { - _nukiBle.initialize(); - _nukiBle.registerBleScanner(_bleScanner); + _nukiLock.initialize(); + _nukiLock.registerBleScanner(_bleScanner); _intervalLockstate = _preferences->getInt(preference_query_interval_lockstate); _intervalBattery = _preferences->getInt(preference_query_interval_battery); @@ -53,7 +53,7 @@ void NukiWrapper::initialize() _preferences->putInt(preference_query_interval_battery, _intervalBattery); } - _nukiBle.setEventHandler(this); + _nukiLock.setEventHandler(this); Serial.print(F("Lock state interval: ")); Serial.print(_intervalLockstate); @@ -73,7 +73,7 @@ void NukiWrapper::update() if (!_paired) { Serial.println(F("Nuki start pairing")); - if (_nukiBle.pairNuki() == Nuki::PairingResult::Success) { + if (_nukiLock.pairNuki() == Nuki::PairingResult::Success) { Serial.println(F("Nuki paired")); _paired = true; } @@ -84,7 +84,7 @@ void NukiWrapper::update() } } - _nukiBle.updateConnectionState(); + _nukiLock.updateConnectionState(); unsigned long ts = millis(); @@ -107,7 +107,7 @@ void NukiWrapper::update() if(_nextLockAction != (NukiLock::LockAction)0xff) { - Nuki::CmdResult cmdResult = _nukiBle.lockAction(_nextLockAction, 0, 0); + Nuki::CmdResult cmdResult = _nukiLock.lockAction(_nextLockAction, 0, 0); char resultStr[15] = {0}; NukiLock::cmdResultToString(cmdResult, resultStr); @@ -135,18 +135,18 @@ void NukiWrapper::update() void NukiWrapper::setPin(const uint16_t pin) { - _nukiBle.saveSecurityPincode(pin); + _nukiLock.saveSecurityPincode(pin); } void NukiWrapper::unpair() { - _nukiBle.unPairNuki(); + _nukiLock.unPairNuki(); _paired = false; } void NukiWrapper::updateKeyTurnerState() { - _nukiBle.requestKeyTurnerState(&_keyTurnerState); + _nukiLock.requestKeyTurnerState(&_keyTurnerState); _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); if(_keyTurnerState.lockState != _lastKeyTurnerState.lockState) @@ -165,7 +165,7 @@ void NukiWrapper::updateKeyTurnerState() void NukiWrapper::updateBatteryState() { - _nukiBle.requestBatteryReport(&_batteryReport); + _nukiLock.requestBatteryReport(&_batteryReport); _network->publishBatteryReport(_batteryReport); } @@ -179,7 +179,7 @@ void NukiWrapper::updateConfig() void NukiWrapper::updateAuthData() { - Nuki::CmdResult result = _nukiBle.retrieveLogEntries(0, 0, 0, true); + Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, 0, 0, true); if(result != Nuki::CmdResult::Success) { _network->publishAuthorizationInfo(0, ""); @@ -187,7 +187,7 @@ void NukiWrapper::updateAuthData() } vTaskDelay( 100 / portTICK_PERIOD_MS); - result = _nukiBle.retrieveLogEntries(_nukiBle.getLogEntryCount() - 2, 1, 0, false); + result = _nukiLock.retrieveLogEntries(_nukiLock.getLogEntryCount() - 2, 1, 0, false); if(result != Nuki::CmdResult::Success) { _network->publishAuthorizationInfo(0, ""); @@ -196,7 +196,7 @@ void NukiWrapper::updateAuthData() vTaskDelay( 200 / portTICK_PERIOD_MS); std::list log; - _nukiBle.getLogEntries(&log); + _nukiLock.getLogEntries(&log); if(log.size() > 0) { @@ -248,42 +248,42 @@ void NukiWrapper::onConfigUpdateReceived(const char *topic, const char *value) { bool newValue = atoi(value) > 0; if(!_nukiConfigValid || _nukiConfig.buttonEnabled == newValue) return; - _nukiBle.enableButton(newValue); + _nukiLock.enableButton(newValue); _nextConfigUpdateTs = millis() + 300; } if(strcmp(topic, mqtt_topic_config_led_enabled) == 0) { bool newValue = atoi(value) > 0; if(!_nukiConfigValid || _nukiConfig.ledEnabled == newValue) return; - _nukiBle.enableLedFlash(newValue); + _nukiLock.enableLedFlash(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_led_brightness) == 0) { int newValue = atoi(value); if(!_nukiConfigValid || _nukiConfig.ledBrightness == newValue) return; - _nukiBle.setLedBrightness(newValue); + _nukiLock.setLedBrightness(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_auto_unlock) == 0) { bool newValue = !(atoi(value) > 0); if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoUnLockDisabled == newValue) return; - _nukiBle.disableAutoUnlock(newValue); + _nukiLock.disableAutoUnlock(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) { bool newValue = atoi(value) > 0; if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; - _nukiBle.enableAutoLock(newValue); + _nukiLock.enableAutoLock(newValue); _nextConfigUpdateTs = millis() + 300; } else if(strcmp(topic, mqtt_topic_config_auto_lock) == 0) { bool newValue = atoi(value) > 0; if(!_nukiAdvancedConfigValid || _nukiAdvancedConfig.autoLockEnabled == newValue) return; - _nukiBle.enableAutoLock(newValue); + _nukiLock.enableAutoLock(newValue); _nextConfigUpdateTs = millis() + 300; } } @@ -309,7 +309,7 @@ void NukiWrapper::notify(Nuki::EventType eventType) void NukiWrapper::readConfig() { Serial.print(F("Reading config. Result: ")); - Nuki::CmdResult result = _nukiBle.requestConfig(&_nukiConfig); + Nuki::CmdResult result = _nukiLock.requestConfig(&_nukiConfig); _nukiConfigValid = result == Nuki::CmdResult::Success; Serial.println(result); } @@ -317,7 +317,7 @@ void NukiWrapper::readConfig() void NukiWrapper::readAdvancedConfig() { Serial.print(F("Reading advanced config. Result: ")); - Nuki::CmdResult result = _nukiBle.requestAdvancedConfig(&_nukiAdvancedConfig); + Nuki::CmdResult result = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig); _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; Serial.println(result); } diff --git a/NukiWrapper.h b/NukiWrapper.h index f6cc4c4..48110cd 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -1,10 +1,10 @@ #pragma once -#include "NukiBle.h" #include "Network.h" #include "NukiConstants.h" #include "NukiDataTypes.h" #include "BleScanner.h" +#include "NukiLock.h" class NukiWrapper : public Nuki::SmartlockEventHandler { @@ -40,7 +40,7 @@ private: NukiLock::LockAction lockActionToEnum(const char* str); // char array at least 14 characters std::string _deviceName; - NukiLock::NukiBle _nukiBle; + NukiLock::NukiLock _nukiLock; BleScanner::Scanner* _bleScanner; Network* _network; Preferences* _preferences; diff --git a/lib/nuki_ble b/lib/nuki_ble index bb36925..1c87e4d 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit bb36925d9a0b5fdb436b3ad2430a81d3d37a1272 +Subproject commit 1c87e4d2fc0e3444791388747f98e29cc36783d8 From 72d296a0289e7ec16a275e55fb03b908ee3dd8f0 Mon Sep 17 00:00:00 2001 From: technyon Date: Sun, 5 Jun 2022 21:47:03 +0200 Subject: [PATCH 21/28] update ble lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index 1c87e4d..39bd00f 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit 1c87e4d2fc0e3444791388747f98e29cc36783d8 +Subproject commit 39bd00f086520771a6d8b8317e10cd499bd01ce7 From 80b1df1c1397ef7e7a247ec0c1ac2726a5452dcc Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 6 Jun 2022 15:48:37 +0200 Subject: [PATCH 22/28] update ble lib --- NukiOpenerWrapper.cpp | 2 +- lib/nuki_ble | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index d61618c..675c71a 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -145,7 +145,7 @@ void NukiOpenerWrapper::unpair() void NukiOpenerWrapper::updateKeyTurnerState() { - _nukiOpener.requestKeyTurnerState(&_keyTurnerState); + _nukiOpener.requestOpenerState(&_keyTurnerState); _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); if(_keyTurnerState.lockState != _lastKeyTurnerState.lockState) diff --git a/lib/nuki_ble b/lib/nuki_ble index 39bd00f..cab8d77 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit 39bd00f086520771a6d8b8317e10cd499bd01ce7 +Subproject commit cab8d778c911e5f5a93e3c889eb970a3a6060cdd From 0dd1612f39541cab68025a4084e37286790b80d2 Mon Sep 17 00:00:00 2001 From: technyon Date: Mon, 6 Jun 2022 15:55:26 +0200 Subject: [PATCH 23/28] update ble lib --- NetworkOpener.cpp | 2 +- NetworkOpener.h | 2 +- NukiOpenerWrapper.cpp | 4 ++-- NukiOpenerWrapper.h | 6 +++--- lib/nuki_ble | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index fd8093a..b804c4e 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -97,7 +97,7 @@ void NetworkOpener::onMqttDataReceived(char *&topic, byte *&payload, unsigned in } } -void NetworkOpener::publishKeyTurnerState(const NukiOpener::KeyTurnerState& keyTurnerState, const NukiOpener::KeyTurnerState& lastKeyTurnerState) +void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurnerState, const NukiOpener::OpenerState& lastKeyTurnerState) { char str[50]; diff --git a/NetworkOpener.h b/NetworkOpener.h index 2bcb1b1..5371ab7 100644 --- a/NetworkOpener.h +++ b/NetworkOpener.h @@ -20,7 +20,7 @@ public: void initialize(); void update(); - void publishKeyTurnerState(const NukiOpener::KeyTurnerState& keyTurnerState, const NukiOpener::KeyTurnerState& lastKeyTurnerState); + void publishKeyTurnerState(const NukiOpener::OpenerState& keyTurnerState, const NukiOpener::OpenerState& lastKeyTurnerState); void publishAuthorizationInfo(const uint32_t authId, const char* authName); void publishCommandResult(const char* resultStr); void publishBatteryReport(const NukiOpener::BatteryReport& batteryReport); diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index 675c71a..dda340e 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -129,7 +129,7 @@ void NukiOpenerWrapper::update() _clearAuthData = false; } - memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiOpener::KeyTurnerState)); + memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiOpener::OpenerState)); } void NukiOpenerWrapper::setPin(const uint16_t pin) @@ -258,7 +258,7 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *va } } -const NukiOpener::KeyTurnerState &NukiOpenerWrapper::keyTurnerState() +const NukiOpener::OpenerState &NukiOpenerWrapper::keyTurnerState() { return _keyTurnerState; } diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index 40d148e..b76af46 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -19,7 +19,7 @@ public: void unpair(); - const NukiOpener::KeyTurnerState& keyTurnerState(); + const NukiOpener::OpenerState& keyTurnerState(); const bool isPaired(); BleScanner::Scanner* bleScanner(); @@ -52,8 +52,8 @@ private: bool _publishAuthData = false; bool _clearAuthData = false; - NukiOpener::KeyTurnerState _lastKeyTurnerState; - NukiOpener::KeyTurnerState _keyTurnerState; + NukiOpener::OpenerState _lastKeyTurnerState; + NukiOpener::OpenerState _keyTurnerState; uint32_t _lastAuthId = 0xffff; diff --git a/lib/nuki_ble b/lib/nuki_ble index cab8d77..8247236 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit cab8d778c911e5f5a93e3c889eb970a3a6060cdd +Subproject commit 82472362d8a0ea2cbabc968406433d8d1fbccbb7 From 5a5f5d8658878b842a079d643121aed757025d32 Mon Sep 17 00:00:00 2001 From: technyon Date: Wed, 8 Jun 2022 22:50:57 +0200 Subject: [PATCH 24/28] presence detection fixes --- Network.cpp | 8 +++++++- Network.h | 1 + PresenceDetection.cpp | 25 +++++++++++++++---------- Version.h | 2 +- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Network.cpp b/Network.cpp index 1446cc9..31af0ee 100644 --- a/Network.cpp +++ b/Network.cpp @@ -205,7 +205,7 @@ void Network::update() if(_presenceCsv != nullptr && strlen(_presenceCsv) > 0) { - publishString(mqtt_topic_presence, _presenceCsv); + publishString_P(mqtt_topic_presence, _presenceCsv); _presenceCsv = nullptr; } @@ -394,6 +394,12 @@ void Network::publishString(const char *topic, const char *value) _device->mqttClient()->publish(path, value); } +void Network::publishString_P(const char *topic, const char *value) +{ + char path[200] = {0}; + buildMqttPath(topic, path); + _device->mqttClient()->publish_P(path, value, true); +} bool Network::isMqttConnected() { diff --git a/Network.h b/Network.h index 3fea58b..05c4d8c 100644 --- a/Network.h +++ b/Network.h @@ -55,6 +55,7 @@ private: void publishUInt(const char* topic, const unsigned int value); void publishBool(const char* topic, const bool value); void publishString(const char* topic, const char* value); + void publishString_P(const char* topic, const char* value); void buildMqttPath(const char* path, char* outPath); void subscribe(const char* path); diff --git a/PresenceDetection.cpp b/PresenceDetection.cpp index c384433..681bcc0 100644 --- a/PresenceDetection.cpp +++ b/PresenceDetection.cpp @@ -37,7 +37,7 @@ void PresenceDetection::initialize() void PresenceDetection::update() { - vTaskDelay( 5000 / portTICK_PERIOD_MS); + delay(3000); if(_timeout < 0) return; if(_devices.size() == 0) @@ -65,6 +65,8 @@ void PresenceDetection::update() _csv[_csvIndex-1] = 0x00; +// Serial.print("Devices found: "); +// Serial.println(_devices.size()); _network->publishPresenceDetection(_csv); } @@ -108,12 +110,13 @@ void PresenceDetection::buildCsv(const PdDevice &device) _csvIndex++; } - void PresenceDetection::onResult(NimBLEAdvertisedDevice *device) { std::string addressStr = device->getAddress().toString(); char addrArrComp[13] = {0}; +// Serial.println(addressStr.c_str()); + addrArrComp[0] = addressStr.at(0); addrArrComp[1] = addressStr.at(1); addrArrComp[2] = addressStr.at(3); @@ -132,6 +135,7 @@ void PresenceDetection::onResult(NimBLEAdvertisedDevice *device) auto it = _devices.find(addr); if(it == _devices.end()) { + PdDevice pdDevice; int i=0; @@ -142,12 +146,19 @@ void PresenceDetection::onResult(NimBLEAdvertisedDevice *device) ++i; } + if(device->haveRSSI()) + { + pdDevice.hasRssi = true; + pdDevice.rssi = device->getRSSI(); + } + + std::string nameStr = "-"; if(device->haveName()) { std::string nameStr = device->getName(); - int i=0; - size_t len = nameStr.length(); + i=0; + len = nameStr.length(); while(i < len && i < sizeof(pdDevice.name)-1) { pdDevice.name[i] = nameStr.at(i); @@ -158,12 +169,6 @@ void PresenceDetection::onResult(NimBLEAdvertisedDevice *device) _devices[addr] = pdDevice; } - - if(device->haveRSSI()) - { - pdDevice.hasRssi = true; - pdDevice.rssi = device->getRSSI(); - } } else { diff --git a/Version.h b/Version.h index 0d6b3c3..ec6d5f2 100644 --- a/Version.h +++ b/Version.h @@ -1,3 +1,3 @@ #pragma once -#define nuki_hub_version "2.6" \ No newline at end of file +#define nuki_hub_version "3.0" \ No newline at end of file From 6ff33fc8687aa68d78af4834591807cd6eb51f2a Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 9 Jun 2022 20:49:10 +0200 Subject: [PATCH 25/28] fix requesting opener state --- NukiOpenerWrapper.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index dda340e..bf517c2 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -153,7 +153,10 @@ void NukiOpenerWrapper::updateKeyTurnerState() char lockStateStr[20]; lockstateToString(_keyTurnerState.lockState, lockStateStr); Serial.print(F("Nuki opener state: ")); - Serial.println(lockStateStr); + Serial.println((int)_keyTurnerState.lockState); +// Serial.println((int)_keyTurnerState.nukiState); +// Serial.println((int)_keyTurnerState.currentTimeYear); +// Serial.println((int)_keyTurnerState.ringToOpenTimer); } if(_publishAuthData) From 0d9ea96a4a85c89d26bc7d19a2e8de822cdb2ca1 Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 9 Jun 2022 20:51:03 +0200 Subject: [PATCH 26/28] update ble lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index 8247236..aefab2e 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit 82472362d8a0ea2cbabc968406433d8d1fbccbb7 +Subproject commit aefab2eb3d8e8e30b8ff783b5c6356b46846df68 From a575bd6ef7216ec7e6660ed0f5cff4e99b5cf264 Mon Sep 17 00:00:00 2001 From: technyon Date: Thu, 9 Jun 2022 20:55:12 +0200 Subject: [PATCH 27/28] update ble lib --- lib/nuki_ble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nuki_ble b/lib/nuki_ble index aefab2e..b1e1baa 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit aefab2eb3d8e8e30b8ff783b5c6356b46846df68 +Subproject commit b1e1baa0a97a8070b2ed5682c8116b0e0999046d From be1be90e1cac6aaee0e10443974866a6d14578b1 Mon Sep 17 00:00:00 2001 From: technyon Date: Sat, 11 Jun 2022 14:58:01 +0200 Subject: [PATCH 28/28] update readme, remove unused battery nodes --- NetworkOpener.cpp | 5 ----- README.md | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index b804c4e..d2bf43e 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -131,12 +131,8 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn if(_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) { - uint8_t level = (keyTurnerState.criticalBatteryState & 0b11111100) >> 1; bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0; - bool charging = (keyTurnerState.criticalBatteryState & 0b00000010) > 0; - publishInt(mqtt_topic_battery_level, level); // percent publishBool(mqtt_topic_battery_critical, critical); - publishBool(mqtt_topic_battery_charging, charging); } _firstTunerStatePublish = false; @@ -156,7 +152,6 @@ void NetworkOpener::publishCommandResult(const char *resultStr) void NetworkOpener::publishBatteryReport(const NukiOpener::BatteryReport& batteryReport) { publishFloat(mqtt_topic_battery_voltage, (float)batteryReport.batteryVoltage / 1000.0); - publishInt(mqtt_topic_battery_drain, batteryReport.batteryDrain); // milliwatt seconds } void NetworkOpener::publishConfig(const NukiOpener::Config &config) diff --git a/README.md b/README.md index 861f7a8..ffed63f 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Just enable pairing mode on the NUKI lock (press button for a few seconds) and p ## MQTT Interface +### Lock + - lock/action: Allows to execute lock actions. After receiving the action, the value is set to "ack". Possible actions: unlock, lock, unlatch, lockNgo, lockNgoUnlatch, fullLock, fobAction1, fobAction2, fobAction3 - lock/state: Reports the current lock state as a string. Possible values are: uncalibrated, locked, unlocked, unlatched, unlockedLnga, unlatching, bootRun, motorBlocked - lock/trigger: The trigger of the last action: autoLock, automatic, button, manual, system @@ -35,7 +37,6 @@ Just enable pairing mode on the NUKI lock (press button for a few seconds) and p - lock/commandResult: Result of the last action as reported by NUKI library: success, failed, timeOut, working, notPaired, error, undefined - lock/doorSensorState: State of the door sensor: unavailable, deactivated, doorClosed, doorOpened, doorStateUnknown, calibrating -- battery/voltage: Reports the current battery voltage in Volts. - battery/level: Battery level in percent - battery/critical: 1 if battery level is critical, otherwise 0 - battery/charging: 1 if charging, otherwise 0 @@ -43,6 +44,21 @@ Just enable pairing mode on the NUKI lock (press button for a few seconds) and p - battery/drain: The drain of the last lock action in Milliwattseconds (mWs) - battery/maxTurnCurrent: The highest current of the turn motor during the last lock action (A) +### Opener + +- lock/action: Allows to execute lock actions. After receiving the action, the value is set to "ack". Possible actions: activateRTO, deactivateRTO, electricStrikeActuation, activateCM, deactivateCM, fobAction1, fobAction2, fobAction3 +- lock/state: Reports the current lock state as a string. Possible values are: locked, RTOactive, open, opening, uncalibrated +- lock/trigger: The trigger of the last action: autoLock, automatic, button, manual, system +- lock/completionStatus: Status of the last action as reported by NUKI lock (needs bluetooth connection): success, motorBlocked, canceled, tooRecent, busy, lowMotorVoltage, clutchFailure, motorPowerFailure, incompleteFailure, invalidCode, otherError, unknown +- lock/authorizationId: If enabled in the web interface, this node returns the authorization id of the last lock action +- lock/authorizationName: If enabled in the web interface, this node returns the authorization name of the last lock action +- lock/commandResult: Result of the last action as reported by NUKI library: success, failed, timeOut, working, notPaired, error, undefined +- lock/doorSensorState: State of the door sensor: unavailable, deactivated, doorClosed, doorOpened, doorStateUnknown, calibrating + +- battery/voltage: Reports the current battery voltage in Volts. +- battery/critical: 1 if battery level is critical, otherwise 0 + +### Misc - presence/devices: List of detected bluetooth devices as CSV. Can be used for presence detection ## Connecting via LAN (Optional)