From 4acadac2b9df8661dc32aae68183e9e67ac27f71 Mon Sep 17 00:00:00 2001 From: iranl Date: Mon, 4 Mar 2024 19:17:27 +0100 Subject: [PATCH 1/4] Better ring detection --- NukiOpenerWrapper.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index 0398fbb..afe9fcf 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -350,6 +350,15 @@ void NukiOpenerWrapper::updateKeyTurnerState() } else { + if(_statusUpdated && + _keyTurnerState.lockState != _lastKeyTurnerState.lockState && + _keyTurnerState.lockState == NukiOpener::LockState::Open && + _keyTurnerState.trigger == NukiOpener::Trigger::Manual) + { + Log->println(F("Nuki opener: Ring detected")); + _network->publishRing(); + } + _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); updateGpioOutputs(); From a35a0b89ba0ca9a93db57e270e38aab0278c7259 Mon Sep 17 00:00:00 2001 From: iranl Date: Tue, 5 Mar 2024 20:45:53 +0100 Subject: [PATCH 2/4] Fix Ring Event + add ring locked or open --- Network.cpp | 3 ++- NetworkOpener.cpp | 15 +++++++++++---- NetworkOpener.h | 2 +- NukiOpenerWrapper.cpp | 11 +++++------ 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Network.cpp b/Network.cpp index 9d841df..dd261d3 100644 --- a/Network.cpp +++ b/Network.cpp @@ -1229,8 +1229,9 @@ void Network::publishHASSConfigRingDetect(char *deviceType, const char *baseTopi {"pl_off", "locked"}}); DynamicJsonDocument json(_bufferSize); - json = createHassJson(uidString, "_ring_event", "Ring", name, baseTopic, String("~") + mqtt_topic_lock_ring, deviceType, "doorbell", "", "", "", {{"value_template", "{ \"event_type\": \"{{ value }}\" }, \"duration\": 2"}}); + json = createHassJson(uidString, "_ring_event", "Ring", name, baseTopic, String("~") + mqtt_topic_lock_ring, deviceType, "doorbell", "", "", "", {{"value_template", "{ \"event_type\": \"{{ value }}\" }"}}); json["event_types"][0] = "ring"; + json["event_types"][1] = "ringlocked"; serializeJson(json, _buffer, _bufferSize); String path = createHassTopicPath("event", "ring", uidString); _device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer); diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index f80a21f..42c7703 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -274,11 +274,18 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn _firstTunerStatePublish = false; } -void NetworkOpener::publishRing() +void NetworkOpener::publishRing(const bool locked) { - publishString(mqtt_topic_lock_state, "ring"); - publishString(mqtt_topic_lock_ring, "ring"); - _resetLockStateTs = millis() + 2000; + if (locked) + { + publishString(mqtt_topic_lock_state, "ring"); + publishString(mqtt_topic_lock_ring, "ringlocked"); + _resetLockStateTs = millis() + 2000; + } + else + { + publishString(mqtt_topic_lock_ring, "ring"); + } } void NetworkOpener::publishState(NukiOpener::OpenerState lockState) diff --git a/NetworkOpener.h b/NetworkOpener.h index 212bd09..ac85004 100644 --- a/NetworkOpener.h +++ b/NetworkOpener.h @@ -19,7 +19,7 @@ public: void update(); void publishKeyTurnerState(const NukiOpener::OpenerState& keyTurnerState, const NukiOpener::OpenerState& lastKeyTurnerState); - void publishRing(); + void publishRing(const bool locked); void publishState(NukiOpener::OpenerState lockState); void publishAuthorizationInfo(const std::list& logEntries); void clearAuthorizationInfo(); diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index afe9fcf..a19f79c 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -345,18 +345,17 @@ void NukiOpenerWrapper::updateKeyTurnerState() _lastKeyTurnerState.lockState == NukiOpener::LockState::Locked && _lastKeyTurnerState.nukiState == _keyTurnerState.nukiState) { - Log->println(F("Nuki opener: Ring detected")); - _network->publishRing(); + Log->println(F("Nuki opener: Ring detected (Locked)")); + _network->publishRing(true); } else { - if(_statusUpdated && - _keyTurnerState.lockState != _lastKeyTurnerState.lockState && + if(_keyTurnerState.lockState != _lastKeyTurnerState.lockState && _keyTurnerState.lockState == NukiOpener::LockState::Open && _keyTurnerState.trigger == NukiOpener::Trigger::Manual) { - Log->println(F("Nuki opener: Ring detected")); - _network->publishRing(); + Log->println(F("Nuki opener: Ring detected (Open)")); + _network->publishRing(false); } _network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState); From 4ba0501244b919893acbc8131b88d9bb01b85122 Mon Sep 17 00:00:00 2001 From: iranl Date: Tue, 5 Mar 2024 21:00:29 +0100 Subject: [PATCH 3/4] Seperate ring from lockstate --- MqttTopics.h | 1 + Network.cpp | 4 ++-- NetworkOpener.cpp | 15 +++++++-------- NetworkOpener.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/MqttTopics.h b/MqttTopics.h index 7e4a327..3ed9c47 100644 --- a/MqttTopics.h +++ b/MqttTopics.h @@ -20,6 +20,7 @@ #define mqtt_topic_lock_binary_state "/lock/binaryState" #define mqtt_topic_lock_continuous_mode "/lock/continuousMode" #define mqtt_topic_lock_ring "/lock/ring" +#define mqtt_topic_lock_binary_ring "/lock/binaryRing" #define mqtt_topic_lock_trigger "/lock/trigger" #define mqtt_topic_lock_last_lock_action "/lock/lastLockAction" #define mqtt_topic_lock_log "/lock/log" diff --git a/Network.cpp b/Network.cpp index dd261d3..49a657b 100644 --- a/Network.cpp +++ b/Network.cpp @@ -1219,14 +1219,14 @@ void Network::publishHASSConfigRingDetect(char *deviceType, const char *baseTopi "Ring detect", name, baseTopic, - String("~") + mqtt_topic_lock_state, + String("~") + mqtt_topic_lock_binary_ring, deviceType, "sound", "", "", "", {{"pl_on", "ring"}, - {"pl_off", "locked"}}); + {"pl_off", "standby"}}); DynamicJsonDocument json(_bufferSize); json = createHassJson(uidString, "_ring_event", "Ring", name, baseTopic, String("~") + mqtt_topic_lock_ring, deviceType, "doorbell", "", "", "", {{"value_template", "{ \"event_type\": \"{{ value }}\" }"}}); diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index 42c7703..04817be 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -49,6 +49,7 @@ void NetworkOpener::initialize() _network->initTopic(_mqttPath, mqtt_topic_query_config, "0"); _network->initTopic(_mqttPath, mqtt_topic_query_lockstate, "0"); _network->initTopic(_mqttPath, mqtt_topic_query_battery, "0"); + _network->initTopic(_mqttPath, mqtt_topic_lock_binary_ring, "standby"); _network->subscribe(_mqttPath, mqtt_topic_query_config); _network->subscribe(_mqttPath, mqtt_topic_query_lockstate); _network->subscribe(_mqttPath, mqtt_topic_query_battery); @@ -77,13 +78,10 @@ void NetworkOpener::initialize() void NetworkOpener::update() { - if(_resetLockStateTs != 0 && millis() >= _resetLockStateTs) + if(_resetRingStateTs != 0 && millis() >= _resetRingStateTs) { - char str[50]; - memset(str, 0, sizeof(str)); - _resetLockStateTs = 0; - lockstateToString(_currentLockState, str); - publishString(mqtt_topic_lock_state, str); + _resetRingStateTs = 0; + publishString(mqtt_topic_lock_binary_ring, "standby"); } } @@ -278,14 +276,15 @@ void NetworkOpener::publishRing(const bool locked) { if (locked) { - publishString(mqtt_topic_lock_state, "ring"); publishString(mqtt_topic_lock_ring, "ringlocked"); - _resetLockStateTs = millis() + 2000; } else { publishString(mqtt_topic_lock_ring, "ring"); } + + publishString(mqtt_topic_lock_binary_ring, "ring"); + _resetRingStateTs = millis() + 2000; } void NetworkOpener::publishState(NukiOpener::OpenerState lockState) diff --git a/NetworkOpener.h b/NetworkOpener.h index ac85004..ec84dc7 100644 --- a/NetworkOpener.h +++ b/NetworkOpener.h @@ -80,7 +80,7 @@ private: String _keypadCommandCode = ""; uint _keypadCommandId = 0; int _keypadCommandEnabled = 1; - unsigned long _resetLockStateTs = 0; + unsigned long _resetRingStateTs = 0; uint8_t _queryCommands = 0; uint32_t authId = 0; char authName[33]; From f9c2752235e6cd627e22a6f36d0c223f2a918b01 Mon Sep 17 00:00:00 2001 From: iranl Date: Sun, 10 Mar 2024 20:41:12 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d04b469..17c86be 100644 --- a/README.md +++ b/README.md @@ -196,12 +196,13 @@ In a browser navigate to the IP address assigned to the ESP32. ### 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, ring, open, opening, uncalibrated. +- lock/state: Reports the current lock state as a string. Possible values are: locked, RTOactive, open, opening, uncalibrated. - lock/hastate: Reports the current lock state as a string, specifically for use by Home Assistant. Possible values are: locking, locked, unlocking, unlocked, jammed. - lock/json: Reports the lock state, last action trigger, last lock action, lock completion status, door sensor state, auth ID and auth name as JSON data. - lock/binaryState: Reports the current lock state as a string, mostly for use by Home Assistant. Possible values are: locked, unlocked. -- lock/continuousMode: Reports the current state of Continuous mode (0 = disabled; 1 = enabled). -- lock/ring: The string "ring" is published to this topic when a doorbell ring is detected, for use by the related Home Assistant event. +- lock/continuousMode: Enable or disable continuous mode on the opener (0 = disabled; 1 = enabled). +- lock/ring: The string "ring" is published to this topic when a doorbell ring is detected while RTO or continuous mode is active or "ringlocked" when both are inactive. +- lock/binaryRing: The string "ring" is published to this topic when a doorbell ring is detected, the state will revert to "standby" after 2 seconds. - lock/trigger: The trigger of the last action: autoLock, automatic, button, manual, system. - lock/lastLockAction: Reports the last lock action as a string. Possible values are: ActivateRTO, DeactivateRTO, ElectricStrikeActuation, ActivateCM, DeactivateCM, FobAction1, FobAction2, FobAction3, Unknown. - lock/log: If "Publish auth data" is enabled in the web interface, this topic will be filled with the log of authorization data. @@ -214,8 +215,8 @@ In a browser navigate to the IP address assigned to the ESP32. - lock/address: The BLE address of the Nuki Lock. - lock/retry: Reports the current number of retries for the current command. 0 when command is succesfull, "failed" if the number of retries is greater than the maximum configured number of retries.

-- configuration/buttonEnabled: enable or disable the button on the lock (0 = disabled; 1 = enabled). -- configuration/ledEnabled: enable or disable the LED on the lock (0 = disabled; 1 = enabled). +- configuration/buttonEnabled: enable or disable the button on the opener (0 = disabled; 1 = enabled). +- configuration/ledEnabled: enable or disable the LED on the opener (0 = disabled; 1 = enabled). - configuration/soundLevel: configures the volume of sounds the opener plays back (0 = min; 255 = max). ### Query @@ -302,7 +303,8 @@ NOTE2: Home Assistant can be setup manually using the [MQTT Lock integration](ht If a keypad is connected to the lock, keypad codes can be added, updated and removed. This has to enabled first in the configuration portal. Check "Enable keypad control via MQTT" and save the configuration. -After enabling keypad control, information about codes is published under "keypad/code_x", x starting from 0 up the number of configured codes. +After enabling keypad control, information about codes is published under "keypad/code_x", x starting from 0 up the number of configured codes. +The same data is also published as JSON data to keypad/json.
For security reasons, the code itself is not published. To modify keypad codes, a command structure is setup under keypad/command: