From 9f68e67ce8a9f65745217e240b8f7032d12c9f5f Mon Sep 17 00:00:00 2001 From: rodriguezst <2828844+rodriguezst@users.noreply.github.com> Date: Sun, 19 Jun 2022 09:51:07 +0000 Subject: [PATCH] Initial HASS autodiscovery support --- Network.cpp | 30 ++++++++++++++++++++++++++++++ Network.h | 1 + NetworkOpener.cpp | 5 +++++ NetworkOpener.h | 1 + NukiOpenerWrapper.cpp | 21 +++++++++++++++++++++ NukiOpenerWrapper.h | 2 ++ NukiWrapper.cpp | 21 +++++++++++++++++++++ NukiWrapper.h | 2 ++ 8 files changed, 83 insertions(+) diff --git a/Network.cpp b/Network.cpp index 91fb69b..3b0dadf 100644 --- a/Network.cpp +++ b/Network.cpp @@ -343,6 +343,36 @@ void Network::publishPresenceDetection(char *csv) _presenceCsv = csv; } +void Network::publishHASSConfig(const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState) +{ + String configJSON = "{\"~\": \""; + configJSON.concat(baseTopic); + configJSON.concat("\", \"name\": \""); + configJSON.concat(name); + configJSON.concat("\", \"unique_id\": \""); + configJSON.concat(uidString); + configJSON.concat("\", \"cmd_t\": \"~/lock/action\", \"pl_lock\": \""); + configJSON.concat(lockAction); + configJSON.concat("\", \"pl_unlk\": \""); + configJSON.concat(unlockAction); + configJSON.concat("\", \"pl_open\": \""); + configJSON.concat(openAction); + configJSON.concat("\", \"stat_t\": \"~/lock/state\", \"stat_locked\": \""); + configJSON.concat(lockedState); + configJSON.concat("\", \"stat_unlocked\": \""); + configJSON.concat(unlockedState); + configJSON.concat("\", \"opt\": \"false\"}"); + + String path = "homeassistant/lock/"; + path.concat(uidString); + path.concat("/config"); + + Serial.println("HASS Config:"); + Serial.println(configJSON); + + _device->mqttClient()->publish(path.c_str(), configJSON.c_str(), true); +} + void Network::setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char *)) { _lockActionReceivedCallback = lockActionReceivedCallback; diff --git a/Network.h b/Network.h index ff5890f..ff3a7f8 100644 --- a/Network.h +++ b/Network.h @@ -36,6 +36,7 @@ public: void publishConfig(const NukiLock::Config& config); void publishAdvancedConfig(const NukiLock::AdvancedConfig& config); void publishPresenceDetection(char* csv); + void publishHASSConfig(const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState); void setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char* value)); void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* path, const char* value)); diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index d2bf43e..f92f10d 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -166,6 +166,11 @@ void NetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &conf // publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1); } +void NetworkOpener::publishHASSConfig(const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState) +{ + _network->publishHASSConfig(baseTopic, name, uidString, lockAction, unlockAction, openAction, lockedState, unlockedState); +} + void NetworkOpener::setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char *)) { _lockActionReceivedCallback = lockActionReceivedCallback; diff --git a/NetworkOpener.h b/NetworkOpener.h index 5371ab7..97329c7 100644 --- a/NetworkOpener.h +++ b/NetworkOpener.h @@ -26,6 +26,7 @@ public: void publishBatteryReport(const NukiOpener::BatteryReport& batteryReport); void publishConfig(const NukiOpener::Config& config); void publishAdvancedConfig(const NukiOpener::AdvancedConfig& config); + void publishHASSConfig(const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState); void setLockActionReceivedCallback(bool (*lockActionReceivedCallback)(const char* value)); void setConfigUpdateReceivedCallback(void (*configUpdateReceivedCallback)(const char* path, const char* value)); diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index bf517c2..3e01567 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -75,6 +75,7 @@ void NukiOpenerWrapper::update() if (_nukiOpener.pairNuki() == NukiOpener::PairingResult::Success) { Serial.println(F("Nuki opener paired")); _paired = true; + setupHASS(); } else { @@ -299,3 +300,23 @@ void NukiOpenerWrapper::readAdvancedConfig() _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; Serial.println(result); } + +void NukiOpenerWrapper::setupHASS() +{ + if(!_nukiConfigValid) // only ask for config once to save battery life + { + Nuki::CmdResult result = _nukiOpener.requestConfig(&_nukiConfig); + _nukiConfigValid = result == Nuki::CmdResult::Success; + } + if (_nukiConfigValid) + { + String baseTopic = _preferences->getString(preference_mqtt_opener_path); + char uidString[20]; + itoa(_nukiConfig.nukiId, uidString, 16); + _network->publishHASSConfig(baseTopic.c_str(),(char*)_nukiConfig.name,uidString,"deactivateRTO","activateRTO","electricStrikeActuation","locked","RTOactive"); + } + else + { + Serial.println(F("Unable to setup HASS. Invalid config received.")); + } +} diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index b76af46..250e6f2 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -38,6 +38,8 @@ private: void readConfig(); void readAdvancedConfig(); + + void setupHASS(); NukiOpener::LockAction lockActionToEnum(const char* str); // char array at least 14 characters diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index b1e8493..f0f8fa9 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -76,6 +76,7 @@ void NukiWrapper::update() if (_nukiLock.pairNuki() == Nuki::PairingResult::Success) { Serial.println(F("Nuki paired")); _paired = true; + setupHASS(); } else { @@ -321,3 +322,23 @@ void NukiWrapper::readAdvancedConfig() _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; Serial.println(result); } + +void NukiWrapper::setupHASS() +{ + if(!_nukiConfigValid) // only ask for config once to save battery life + { + Nuki::CmdResult result = _nukiLock.requestConfig(&_nukiConfig); + _nukiConfigValid = result == Nuki::CmdResult::Success; + } + if (_nukiConfigValid) + { + String baseTopic = _preferences->getString(preference_mqtt_lock_path); + char uidString[20]; + itoa(_nukiConfig.nukiId, uidString, 16); + _network->publishHASSConfig(baseTopic.c_str(),(char*)_nukiConfig.name,uidString,"lock","unlock","unlatch","locked","unlocked"); + } + else + { + Serial.println(F("Unable to setup HASS. Invalid config received.")); + } +} diff --git a/NukiWrapper.h b/NukiWrapper.h index 48110cd..8f8eaa6 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -36,6 +36,8 @@ private: void readConfig(); void readAdvancedConfig(); + + void setupHASS(); NukiLock::LockAction lockActionToEnum(const char* str); // char array at least 14 characters