Refractor HA discovery
This commit is contained in:
@@ -204,6 +204,7 @@ In a browser navigate to the IP address assigned to the ESP32.
|
|||||||
- MQTT Password : If using authentication on the MQTT broker set to the password belonging to a username with read/write rights on the MQTT broker, set to # to clear
|
- MQTT Password : If using authentication on the MQTT broker set to the password belonging to a username with read/write rights on the MQTT broker, set to # to clear
|
||||||
- MQTT NukiHub Path: Set to the preferred MQTT root topic for NukiHub, defaults to "nukihub". Make sure this topic is unique when using multiple ESP32 NukiHub devices
|
- MQTT NukiHub Path: Set to the preferred MQTT root topic for NukiHub, defaults to "nukihub". Make sure this topic is unique when using multiple ESP32 NukiHub devices
|
||||||
- Enable Home Assistant auto discovery: Enable Home Assistant MQTT auto discovery. Will automatically create entities in Home Assistant for NukiHub and connected Nuki Lock and/or Opener when enabled.
|
- Enable Home Assistant auto discovery: Enable Home Assistant MQTT auto discovery. Will automatically create entities in Home Assistant for NukiHub and connected Nuki Lock and/or Opener when enabled.
|
||||||
|
- Use Home Assistant device based discovery: Use Home Assistant Device discovery instead of single component discovery. Recommended, but requires Home Assistant 2024.11 or newer.
|
||||||
|
|
||||||
#### Advanced MQTT Configuration
|
#### Advanced MQTT Configuration
|
||||||
|
|
||||||
|
|||||||
3054
src/HomeAssistantDiscovery.cpp
Normal file
3054
src/HomeAssistantDiscovery.cpp
Normal file
File diff suppressed because it is too large
Load Diff
43
src/HomeAssistantDiscovery.h
Normal file
43
src/HomeAssistantDiscovery.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
void setupHASS(int type=0);
|
||||||
|
void disableHASS();
|
||||||
|
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const bool& publishAuthData, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction);
|
||||||
|
void removeHASSConfig(char* uidString);
|
||||||
|
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction);
|
||||||
|
void publishHASSConfigAdditionalLockEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
||||||
|
void publishHASSConfigDoorSensor(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
||||||
|
void publishHASSConfigAdditionalOpenerEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
||||||
|
void publishHASSConfigAccessLog(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
||||||
|
void publishHASSConfigKeypad(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
||||||
|
void publishHASSWifiRssiConfig(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
||||||
|
void removeHASSConfig(char* uidString);
|
||||||
|
void removeHASSConfigTopic(char* deviceType, char* name, char* uidString);
|
||||||
|
void publishHassTopic(const String& mqttDeviceType,
|
||||||
|
const String& mqttDeviceName,
|
||||||
|
const String& uidString,
|
||||||
|
const String& uidStringPostfix,
|
||||||
|
const String& displayName,
|
||||||
|
const String& name,
|
||||||
|
const String& baseTopic,
|
||||||
|
const String& stateTopic,
|
||||||
|
const String& deviceType,
|
||||||
|
const String& deviceClass,
|
||||||
|
const String& stateClass = "",
|
||||||
|
const String& entityCat = "",
|
||||||
|
const String& commandTopic = "",
|
||||||
|
std::vector<std::pair<char*, char*>> additionalEntries = {}
|
||||||
|
);
|
||||||
|
void removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
||||||
|
String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
||||||
|
JsonDocument createHassJson(const String& uidString,
|
||||||
|
const String& uidStringPostfix,
|
||||||
|
const String& displayName,
|
||||||
|
const String& name,
|
||||||
|
const String& baseTopic,
|
||||||
|
const String& stateTopic,
|
||||||
|
const String& deviceType,
|
||||||
|
const String& deviceClass,
|
||||||
|
const String& stateClass = "",
|
||||||
|
const String& entityCat = "",
|
||||||
|
const String& commandTopic = "",
|
||||||
|
std::vector<std::pair<char*, char*>> additionalEntries = {}
|
||||||
|
);
|
||||||
2926
src/NukiNetwork.cpp
2926
src/NukiNetwork.cpp
File diff suppressed because it is too large
Load Diff
@@ -56,32 +56,6 @@ public:
|
|||||||
void publishLongLong(const char* prefix, const char* topic, int64_t value, bool retain);
|
void publishLongLong(const char* prefix, const char* topic, int64_t value, bool retain);
|
||||||
void publishBool(const char* prefix, const char* topic, const bool value, bool retain);
|
void publishBool(const char* prefix, const char* topic, const bool value, bool retain);
|
||||||
void publishString(const char* prefix, const char* topic, const char* value, bool retain);
|
void publishString(const char* prefix, const char* topic, const char* value, bool retain);
|
||||||
|
|
||||||
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction);
|
|
||||||
void publishHASSConfigAdditionalLockEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
|
||||||
void publishHASSConfigDoorSensor(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
|
||||||
void publishHASSConfigAdditionalOpenerEntities(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
|
||||||
void publishHASSConfigAccessLog(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
|
||||||
void publishHASSConfigKeypad(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
|
||||||
void publishHASSWifiRssiConfig(char* deviceType, const char* baseTopic, char* name, char* uidString);
|
|
||||||
void removeHASSConfig(char* uidString);
|
|
||||||
void removeHASSConfigTopic(char* deviceType, char* name, char* uidString);
|
|
||||||
void publishHassTopic(const String& mqttDeviceType,
|
|
||||||
const String& mqttDeviceName,
|
|
||||||
const String& uidString,
|
|
||||||
const String& uidStringPostfix,
|
|
||||||
const String& displayName,
|
|
||||||
const String& name,
|
|
||||||
const String& baseTopic,
|
|
||||||
const String& stateTopic,
|
|
||||||
const String& deviceType,
|
|
||||||
const String& deviceClass,
|
|
||||||
const String& stateClass = "",
|
|
||||||
const String& entityCat = "",
|
|
||||||
const String& commandTopic = "",
|
|
||||||
std::vector<std::pair<char*, char*>> additionalEntries = {}
|
|
||||||
);
|
|
||||||
void removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
|
||||||
void removeTopic(const String& mqttPath, const String& mqttTopic);
|
void removeTopic(const String& mqttPath, const String& mqttTopic);
|
||||||
void batteryTypeToString(const Nuki::BatteryType battype, char* str);
|
void batteryTypeToString(const Nuki::BatteryType battype, char* str);
|
||||||
void advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str);
|
void advertisingModeToString(const Nuki::AdvertisingMode advmode, char* str);
|
||||||
@@ -123,9 +97,12 @@ private:
|
|||||||
void onMqttDisconnect(const espMqttClientTypes::DisconnectReason& reason);
|
void onMqttDisconnect(const espMqttClientTypes::DisconnectReason& reason);
|
||||||
void parseGpioTopics(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
void parseGpioTopics(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
||||||
void gpioActionCallback(const GpioAction& action, const int& pin);
|
void gpioActionCallback(const GpioAction& action, const int& pin);
|
||||||
|
void buildMqttPath(char* outPath, std::initializer_list<const char*> paths);
|
||||||
String createHassTopicPath(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
void setupHASS(int type);
|
||||||
JsonDocument createHassJson(const String& uidString,
|
void disableHASS();
|
||||||
|
void publishHassTopic(const String& mqttDeviceType,
|
||||||
|
const String& mqttDeviceName,
|
||||||
|
const String& uidString,
|
||||||
const String& uidStringPostfix,
|
const String& uidStringPostfix,
|
||||||
const String& displayName,
|
const String& displayName,
|
||||||
const String& name,
|
const String& name,
|
||||||
@@ -133,12 +110,12 @@ private:
|
|||||||
const String& stateTopic,
|
const String& stateTopic,
|
||||||
const String& deviceType,
|
const String& deviceType,
|
||||||
const String& deviceClass,
|
const String& deviceClass,
|
||||||
const String& stateClass = "",
|
const String& stateClass,
|
||||||
const String& entityCat = "",
|
const String& entityCat,
|
||||||
const String& commandTopic = "",
|
const String& commandTopic,
|
||||||
std::vector<std::pair<char*, char*>> additionalEntries = {}
|
std::vector<std::pair<char*, char*>> additionalEntries
|
||||||
);
|
);
|
||||||
void buildMqttPath(char* outPath, std::initializer_list<const char*> paths);
|
void removeHassTopic(const String& mqttDeviceType, const String& mqttDeviceName, const String& uidString);
|
||||||
|
|
||||||
const char* _lastWillPayload = "offline";
|
const char* _lastWillPayload = "offline";
|
||||||
char _mqttConnectionStateTopic[211] = {0};
|
char _mqttConnectionStateTopic[211] = {0};
|
||||||
|
|||||||
@@ -1663,53 +1663,6 @@ bool NukiNetworkLock::comparePrefixedPath(const char *fullPath, const char *subP
|
|||||||
return strcmp(fullPath, prefixedPath) == 0;
|
return strcmp(fullPath, prefixedPath) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiNetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, char *name, char *uidString, const char *softwareVersion, const char *hardwareVersion, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char *lockAction,
|
|
||||||
char *unlockAction, char *openAction)
|
|
||||||
{
|
|
||||||
String availabilityTopic = _preferences->getString(preference_mqtt_lock_path);
|
|
||||||
availabilityTopic.concat("/maintenance/mqttConnectionState");
|
|
||||||
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, softwareVersion, hardwareVersion, availabilityTopic.c_str(), hasKeypad, lockAction, unlockAction, openAction);
|
|
||||||
_network->publishHASSConfigAdditionalLockEntities(deviceType, baseTopic, name, uidString);
|
|
||||||
|
|
||||||
if(hasDoorSensor)
|
|
||||||
{
|
|
||||||
_network->publishHASSConfigDoorSensor(deviceType, baseTopic, name, uidString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_network->removeHASSConfigTopic((char*)"binary_sensor", (char*)"door_sensor", uidString);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
|
||||||
_network->publishHASSWifiRssiConfig(deviceType, baseTopic, name, uidString);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(publishAuthData)
|
|
||||||
{
|
|
||||||
_network->publishHASSConfigAccessLog(deviceType, baseTopic, name, uidString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_network->removeHASSConfigTopic((char*)"sensor", (char*)"last_action_authorization", uidString);
|
|
||||||
_network->removeHASSConfigTopic((char*)"sensor", (char*)"rolling_log", uidString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hasKeypad)
|
|
||||||
{
|
|
||||||
_network->publishHASSConfigKeypad(deviceType, baseTopic, name, uidString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_network->removeHASSConfigTopic((char*)"sensor", (char*)"keypad_status", uidString);
|
|
||||||
_network->removeHASSConfigTopic((char*)"binary_sensor", (char*)"keypad_battery_low", uidString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NukiNetworkLock::removeHASSConfig(char *uidString)
|
|
||||||
{
|
|
||||||
_network->removeHASSConfig(uidString);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NukiNetworkLock::publishOffAction(const int value)
|
void NukiNetworkLock::publishOffAction(const int value)
|
||||||
{
|
{
|
||||||
_network->publishInt(_nukiOfficial->getMqttPath(), mqtt_topic_official_lock_action, value, false);
|
_network->publishInt(_nukiOfficial->getMqttPath(), mqtt_topic_official_lock_action, value, false);
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ public:
|
|||||||
void publishRssi(const int& rssi);
|
void publishRssi(const int& rssi);
|
||||||
void publishRetry(const std::string& message);
|
void publishRetry(const std::string& message);
|
||||||
void publishBleAddress(const std::string& address);
|
void publishBleAddress(const std::string& address);
|
||||||
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction);
|
|
||||||
void removeHASSConfig(char* uidString);
|
|
||||||
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
||||||
void publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount);
|
void publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount);
|
||||||
void publishAuth(const std::list<NukiLock::AuthorizationEntry>& authEntries, uint maxAuthEntryCount);
|
void publishAuth(const std::list<NukiLock::AuthorizationEntry>& authEntries, uint maxAuthEntryCount);
|
||||||
|
|||||||
@@ -859,38 +859,6 @@ void NukiNetworkOpener::publishBleAddress(const std::string &address)
|
|||||||
publishString(mqtt_topic_lock_address, address, true);
|
publishString(mqtt_topic_lock_address, address, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiNetworkOpener::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const bool& publishAuthData, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction)
|
|
||||||
{
|
|
||||||
String availabilityTopic = _preferences->getString(preference_mqtt_lock_path);
|
|
||||||
availabilityTopic.concat("/maintenance/mqttConnectionState");
|
|
||||||
|
|
||||||
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, softwareVersion, hardwareVersion, availabilityTopic.c_str(), hasKeypad, lockAction, unlockAction, openAction);
|
|
||||||
_network->publishHASSConfigAdditionalOpenerEntities(deviceType, baseTopic, name, uidString);
|
|
||||||
if(publishAuthData)
|
|
||||||
{
|
|
||||||
_network->publishHASSConfigAccessLog(deviceType, baseTopic, name, uidString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_network->removeHASSConfigTopic((char*)"sensor", (char*)"last_action_authorization", uidString);
|
|
||||||
_network->removeHASSConfigTopic((char*)"sensor", (char*)"rolling_log", uidString);
|
|
||||||
}
|
|
||||||
if(hasKeypad)
|
|
||||||
{
|
|
||||||
_network->publishHASSConfigKeypad(deviceType, baseTopic, name, uidString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_network->removeHASSConfigTopic((char*)"sensor", (char*)"keypad_status", uidString);
|
|
||||||
_network->removeHASSConfigTopic((char*)"binary_sensor", (char*)"keypad_battery_low", uidString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NukiNetworkOpener::removeHASSConfig(char* uidString)
|
|
||||||
{
|
|
||||||
_network->removeHASSConfig(uidString);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
|
void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount)
|
||||||
{
|
{
|
||||||
bool publishCode = _preferences->getBool(preference_keypad_publish_code, false);
|
bool publishCode = _preferences->getBool(preference_keypad_publish_code, false);
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ public:
|
|||||||
void publishRssi(const int& rssi);
|
void publishRssi(const int& rssi);
|
||||||
void publishRetry(const std::string& message);
|
void publishRetry(const std::string& message);
|
||||||
void publishBleAddress(const std::string& address);
|
void publishBleAddress(const std::string& address);
|
||||||
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const bool& publishAuthData, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction);
|
|
||||||
void removeHASSConfig(char* uidString);
|
|
||||||
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
||||||
void publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount);
|
void publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries, uint maxTimeControlEntryCount);
|
||||||
void publishAuth(const std::list<NukiLock::AuthorizationEntry>& authEntries, uint maxAuthEntryCount);
|
void publishAuth(const std::list<NukiLock::AuthorizationEntry>& authEntries, uint maxAuthEntryCount);
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void NukiOfficial::onOfficialUpdateReceived(const char *topic, const char *value
|
|||||||
bool publishBatteryJson = false;
|
bool publishBatteryJson = false;
|
||||||
memset(&str, 0, sizeof(str));
|
memset(&str, 0, sizeof(str));
|
||||||
|
|
||||||
Log->println("Official Nuki change recieved");
|
Log->println("Official Nuki change received");
|
||||||
Log->print(F("Topic: "));
|
Log->print(F("Topic: "));
|
||||||
Log->println(topic);
|
Log->println(topic);
|
||||||
Log->print(F("Value: "));
|
Log->print(F("Value: "));
|
||||||
|
|||||||
@@ -313,7 +313,8 @@ void NukiOpenerWrapper::update()
|
|||||||
}
|
}
|
||||||
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
|
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
|
||||||
{
|
{
|
||||||
setupHASS();
|
_network->setupHASS(2);
|
||||||
|
_hassSetupCompleted = true;
|
||||||
}
|
}
|
||||||
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
||||||
{
|
{
|
||||||
@@ -610,13 +611,13 @@ void NukiOpenerWrapper::updateConfig()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log->println(F("Invalid/Unexpected opener config recieved, ID does not matched saved ID"));
|
Log->println(F("Invalid/Unexpected opener config received, ID does not matched saved ID"));
|
||||||
expectedConfig = false;
|
expectedConfig = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log->println(F("Invalid/Unexpected opener config recieved, Config is not valid"));
|
Log->println(F("Invalid/Unexpected opener config received, Config is not valid"));
|
||||||
expectedConfig = false;
|
expectedConfig = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,7 +634,7 @@ void NukiOpenerWrapper::updateConfig()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log->println(F("Invalid/Unexpected opener advanced config recieved, Advanced config is not valid"));
|
Log->println(F("Invalid/Unexpected opener advanced config received, Advanced config is not valid"));
|
||||||
expectedConfig = false;
|
expectedConfig = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -646,7 +647,7 @@ void NukiOpenerWrapper::updateConfig()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
++_retryConfigCount;
|
++_retryConfigCount;
|
||||||
Log->println(F("Invalid/Unexpected opener config and/or advanced config recieved, retrying in 10 seconds"));
|
Log->println(F("Invalid/Unexpected opener config and/or advanced config received, retrying in 10 seconds"));
|
||||||
int64_t ts = espMillis();
|
int64_t ts = espMillis();
|
||||||
_nextConfigUpdateTs = ts + 10000;
|
_nextConfigUpdateTs = ts + 10000;
|
||||||
}
|
}
|
||||||
@@ -3957,43 +3958,6 @@ void NukiOpenerWrapper::readAdvancedConfig()
|
|||||||
postponeBleWatchdog();
|
postponeBleWatchdog();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiOpenerWrapper::setupHASS()
|
|
||||||
{
|
|
||||||
if(!_nukiConfigValid)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(_preferences->getUInt(preference_nuki_id_opener, 0) != _nukiConfig.nukiId)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
|
||||||
baseTopic.concat("/opener");
|
|
||||||
char uidString[20];
|
|
||||||
itoa(_nukiConfig.nukiId, uidString, 16);
|
|
||||||
|
|
||||||
if(_preferences->getBool(preference_opener_continuous_mode, false))
|
|
||||||
{
|
|
||||||
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, _firmwareVersion.c_str(), _hardwareVersion.c_str(), _publishAuthData, _hasKeypad, (char*)"deactivateCM", (char*)"activateCM", (char*)"electricStrikeActuation");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, _firmwareVersion.c_str(), _hardwareVersion.c_str(), _publishAuthData, _hasKeypad, (char*)"deactivateRTO", (char*)"activateRTO", (char*)"electricStrikeActuation");
|
|
||||||
}
|
|
||||||
|
|
||||||
_hassSetupCompleted = true;
|
|
||||||
|
|
||||||
Log->println("HASS setup for opener completed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void NukiOpenerWrapper::disableHASS()
|
|
||||||
{
|
|
||||||
char uidString[20];
|
|
||||||
itoa(_preferences->getUInt(preference_nuki_id_opener, 0), uidString, 16);
|
|
||||||
_network->removeHASSConfig(uidString);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NukiOpenerWrapper::printCommandResult(Nuki::CmdResult result)
|
void NukiOpenerWrapper::printCommandResult(Nuki::CmdResult result)
|
||||||
{
|
{
|
||||||
char resultStr[15];
|
char resultStr[15];
|
||||||
|
|||||||
@@ -31,9 +31,6 @@ public:
|
|||||||
uint16_t getPin();
|
uint16_t getPin();
|
||||||
|
|
||||||
void unpair();
|
void unpair();
|
||||||
|
|
||||||
void disableHASS();
|
|
||||||
|
|
||||||
void disableWatchdog();
|
void disableWatchdog();
|
||||||
|
|
||||||
const NukiOpener::OpenerState& keyTurnerState();
|
const NukiOpener::OpenerState& keyTurnerState();
|
||||||
@@ -77,8 +74,6 @@ private:
|
|||||||
void readConfig();
|
void readConfig();
|
||||||
void readAdvancedConfig();
|
void readAdvancedConfig();
|
||||||
|
|
||||||
void setupHASS();
|
|
||||||
|
|
||||||
void printCommandResult(Nuki::CmdResult result);
|
void printCommandResult(Nuki::CmdResult result);
|
||||||
|
|
||||||
NukiOpener::LockAction lockActionToEnum(const char* str); // char array at least 14 characters
|
NukiOpener::LockAction lockActionToEnum(const char* str); // char array at least 14 characters
|
||||||
|
|||||||
@@ -405,7 +405,8 @@ void NukiWrapper::update()
|
|||||||
}
|
}
|
||||||
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
|
if(_hassEnabled && _nukiConfigValid && _nukiAdvancedConfigValid && !_hassSetupCompleted)
|
||||||
{
|
{
|
||||||
setupHASS();
|
_network->setupHASS(1);
|
||||||
|
_hassSetupCompleted = true;
|
||||||
}
|
}
|
||||||
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
if(_rssiPublishInterval > 0 && (_nextRssiTs == 0 || ts > _nextRssiTs))
|
||||||
{
|
{
|
||||||
@@ -693,13 +694,13 @@ void NukiWrapper::updateConfig()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log->println(F("Invalid/Unexpected lock config recieved, ID does not matched saved ID"));
|
Log->println(F("Invalid/Unexpected lock config received, ID does not matched saved ID"));
|
||||||
expectedConfig = false;
|
expectedConfig = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log->println(F("Invalid/Unexpected lock config recieved, Config is not valid"));
|
Log->println(F("Invalid/Unexpected lock config received, Config is not valid"));
|
||||||
expectedConfig = false;
|
expectedConfig = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,7 +717,7 @@ void NukiWrapper::updateConfig()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log->println(F("Invalid/Unexpected lock advanced config recieved, Advanced config is not valid"));
|
Log->println(F("Invalid/Unexpected lock advanced config received, Advanced config is not valid"));
|
||||||
expectedConfig = false;
|
expectedConfig = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,7 +730,7 @@ void NukiWrapper::updateConfig()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
++_retryConfigCount;
|
++_retryConfigCount;
|
||||||
Log->println(F("Invalid/Unexpected lock config and/or advanced config recieved, retrying in 10 seconds"));
|
Log->println(F("Invalid/Unexpected lock config and/or advanced config received, retrying in 10 seconds"));
|
||||||
int64_t ts = espMillis();
|
int64_t ts = espMillis();
|
||||||
_nextConfigUpdateTs = ts + 10000;
|
_nextConfigUpdateTs = ts + 10000;
|
||||||
}
|
}
|
||||||
@@ -4074,28 +4075,6 @@ void NukiWrapper::readAdvancedConfig()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiWrapper::setupHASS()
|
|
||||||
{
|
|
||||||
if(!_nukiConfigValid)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(_preferences->getUInt(preference_nuki_id_lock, 0) != _nukiConfig.nukiId)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String baseTopic = _preferences->getString(preference_mqtt_lock_path);
|
|
||||||
baseTopic.concat("/lock");
|
|
||||||
char uidString[20];
|
|
||||||
itoa(_nukiConfig.nukiId, uidString, 16);
|
|
||||||
|
|
||||||
_network->publishHASSConfig((char*)"SmartLock", baseTopic.c_str(),(char*)_nukiConfig.name, uidString, _firmwareVersion.c_str(), _hardwareVersion.c_str(), hasDoorSensor(), _hasKeypad, _publishAuthData, (char*)"lock", (char*)"unlock", (char*)"unlatch");
|
|
||||||
_hassSetupCompleted = true;
|
|
||||||
|
|
||||||
Log->println("HASS setup for lock completed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NukiWrapper::hasDoorSensor() const
|
bool NukiWrapper::hasDoorSensor() const
|
||||||
{
|
{
|
||||||
return _keyTurnerState.doorSensorState == Nuki::DoorSensorState::DoorClosed ||
|
return _keyTurnerState.doorSensorState == Nuki::DoorSensorState::DoorClosed ||
|
||||||
@@ -4103,13 +4082,6 @@ bool NukiWrapper::hasDoorSensor() const
|
|||||||
_keyTurnerState.doorSensorState == Nuki::DoorSensorState::Calibrating;
|
_keyTurnerState.doorSensorState == Nuki::DoorSensorState::Calibrating;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiWrapper::disableHASS()
|
|
||||||
{
|
|
||||||
char uidString[20];
|
|
||||||
itoa(_preferences->getUInt(preference_nuki_id_lock, 0), uidString, 16);
|
|
||||||
_network->removeHASSConfig(uidString);
|
|
||||||
}
|
|
||||||
|
|
||||||
const BLEAddress NukiWrapper::getBleAddress() const
|
const BLEAddress NukiWrapper::getBleAddress() const
|
||||||
{
|
{
|
||||||
return _nukiLock.getBleAddress();
|
return _nukiLock.getBleAddress();
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ public:
|
|||||||
uint16_t getPin();
|
uint16_t getPin();
|
||||||
void unpair();
|
void unpair();
|
||||||
|
|
||||||
void disableHASS();
|
|
||||||
|
|
||||||
void disableWatchdog();
|
void disableWatchdog();
|
||||||
|
|
||||||
const NukiLock::KeyTurnerState& keyTurnerState();
|
const NukiLock::KeyTurnerState& keyTurnerState();
|
||||||
@@ -81,8 +79,6 @@ private:
|
|||||||
void readConfig();
|
void readConfig();
|
||||||
void readAdvancedConfig();
|
void readAdvancedConfig();
|
||||||
|
|
||||||
void setupHASS();
|
|
||||||
|
|
||||||
void printCommandResult(Nuki::CmdResult result);
|
void printCommandResult(Nuki::CmdResult result);
|
||||||
|
|
||||||
NukiLock::LockAction lockActionToEnum(const char* str); // char array at least 14 characters
|
NukiLock::LockAction lockActionToEnum(const char* str); // char array at least 14 characters
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#define preference_gpio_configuration (char*)"gpiocfg"
|
#define preference_gpio_configuration (char*)"gpiocfg"
|
||||||
#define preference_mqtt_hass_enabled (char*)"hassena"
|
#define preference_mqtt_hass_enabled (char*)"hassena"
|
||||||
#define preference_mqtt_hass_discovery (char*)"hassdiscovery"
|
#define preference_mqtt_hass_discovery (char*)"hassdiscovery"
|
||||||
|
#define preference_hass_device_discovery (char*)"hassdevdisc"
|
||||||
#define preference_webserver_enabled (char*)"websrvena"
|
#define preference_webserver_enabled (char*)"websrvena"
|
||||||
#define preference_update_from_mqtt (char*)"updMqtt"
|
#define preference_update_from_mqtt (char*)"updMqtt"
|
||||||
#define preference_disable_non_json (char*)"disnonjson"
|
#define preference_disable_non_json (char*)"disnonjson"
|
||||||
@@ -294,7 +295,7 @@ private:
|
|||||||
preference_network_custom_rst, preference_network_custom_cs, preference_network_custom_sck, preference_network_custom_miso, preference_network_custom_mosi,
|
preference_network_custom_rst, preference_network_custom_cs, preference_network_custom_sck, preference_network_custom_miso, preference_network_custom_mosi,
|
||||||
preference_network_custom_pwr, preference_network_custom_mdio, preference_ntw_reconfigure, preference_lock_max_auth_entry_count, preference_opener_max_auth_entry_count,
|
preference_network_custom_pwr, preference_network_custom_mdio, preference_ntw_reconfigure, preference_lock_max_auth_entry_count, preference_opener_max_auth_entry_count,
|
||||||
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_auth_max_entries, preference_wifi_ssid, preference_wifi_pass,
|
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_auth_max_entries, preference_wifi_ssid, preference_wifi_pass,
|
||||||
preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_mqtt_hass_enabled
|
preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_mqtt_hass_enabled, preference_hass_device_discovery
|
||||||
};
|
};
|
||||||
std::vector<char*> _redact =
|
std::vector<char*> _redact =
|
||||||
{
|
{
|
||||||
@@ -309,7 +310,7 @@ private:
|
|||||||
preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_register_opener_as_app, preference_ip_dhcp_enabled,
|
preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_register_opener_as_app, preference_ip_dhcp_enabled,
|
||||||
preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled, preference_mqtt_hass_enabled,
|
preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled, preference_mqtt_hass_enabled,
|
||||||
preference_official_hybrid_actions, preference_official_hybrid_retry, preference_conf_info_enabled, preference_disable_non_json, preference_update_from_mqtt,
|
preference_official_hybrid_actions, preference_official_hybrid_retry, preference_conf_info_enabled, preference_disable_non_json, preference_update_from_mqtt,
|
||||||
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_webserial_enabled,
|
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_webserial_enabled, preference_hass_device_discovery,
|
||||||
preference_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected
|
preference_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected
|
||||||
};
|
};
|
||||||
std::vector<char*> _bytePrefs =
|
std::vector<char*> _bytePrefs =
|
||||||
|
|||||||
@@ -1740,39 +1740,35 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
|
|||||||
//configChanged = true;
|
//configChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(key == "HADEVDISC")
|
||||||
|
{
|
||||||
|
if(_preferences->getBool(preference_hass_device_discovery, false) != (value == "1"))
|
||||||
|
{
|
||||||
|
_network->disableHASS();
|
||||||
|
_preferences->putBool(preference_hass_device_discovery, (value == "1"));
|
||||||
|
Log->print(F("Setting changed: "));
|
||||||
|
Log->println(key);
|
||||||
|
configChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(key == "ENHADISC")
|
else if(key == "ENHADISC")
|
||||||
{
|
{
|
||||||
if(_preferences->getBool(preference_mqtt_hass_enabled, false) != (value == "1"))
|
if(_preferences->getBool(preference_mqtt_hass_enabled, false) != (value == "1"))
|
||||||
{
|
{
|
||||||
if(!_preferences->getBool(preference_mqtt_hass_enabled, false))
|
_network->disableHASS();
|
||||||
{
|
|
||||||
if (_nuki != nullptr)
|
|
||||||
{
|
|
||||||
_nuki->disableHASS();
|
|
||||||
}
|
|
||||||
if (_nukiOpener != nullptr)
|
|
||||||
{
|
|
||||||
_nukiOpener->disableHASS();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_preferences->putBool(preference_mqtt_hass_enabled, (value == "1"));
|
_preferences->putBool(preference_mqtt_hass_enabled, (value == "1"));
|
||||||
Log->print(F("Setting changed: "));
|
Log->print(F("Setting changed: "));
|
||||||
Log->println(key);
|
Log->println(key);
|
||||||
configChanged = true;
|
configChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HADEVDISC
|
||||||
else if(key == "HASSDISCOVERY")
|
else if(key == "HASSDISCOVERY")
|
||||||
{
|
{
|
||||||
if(_preferences->getString(preference_mqtt_hass_discovery, "") != value)
|
if(_preferences->getString(preference_mqtt_hass_discovery, "") != value)
|
||||||
{
|
{
|
||||||
if (_nuki != nullptr)
|
_network->disableHASS();
|
||||||
{
|
|
||||||
_nuki->disableHASS();
|
|
||||||
}
|
|
||||||
if (_nukiOpener != nullptr)
|
|
||||||
{
|
|
||||||
_nukiOpener->disableHASS();
|
|
||||||
}
|
|
||||||
_preferences->putString(preference_mqtt_hass_discovery, value);
|
_preferences->putString(preference_mqtt_hass_discovery, value);
|
||||||
Log->print(F("Setting changed: "));
|
Log->print(F("Setting changed: "));
|
||||||
Log->println(key);
|
Log->println(key);
|
||||||
@@ -3543,6 +3539,7 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
|
|||||||
printInputField(&response, "MQTTPASS", "MQTT Password", "*", 30, "", true, true);
|
printInputField(&response, "MQTTPASS", "MQTT Password", "*", 30, "", true, true);
|
||||||
printInputField(&response, "MQTTPATH", "MQTT NukiHub Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180, "");
|
printInputField(&response, "MQTTPATH", "MQTT NukiHub Path", _preferences->getString(preference_mqtt_lock_path).c_str(), 180, "");
|
||||||
printCheckBox(&response, "ENHADISC", "Enable Home Assistant auto discovery", _preferences->getBool(preference_mqtt_hass_enabled), "chkHass");
|
printCheckBox(&response, "ENHADISC", "Enable Home Assistant auto discovery", _preferences->getBool(preference_mqtt_hass_enabled), "chkHass");
|
||||||
|
printCheckBox(&response, "HADEVDISC", "Use Home Assistant device based discovery", _preferences->getBool(preference_hass_device_discovery), "");
|
||||||
response.print("</table><br>");
|
response.print("</table><br>");
|
||||||
|
|
||||||
response.print("<h3>Advanced MQTT Configuration</h3>");
|
response.print("<h3>Advanced MQTT Configuration</h3>");
|
||||||
@@ -4209,7 +4206,7 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request)
|
|||||||
response.print(_preferences->getInt(preference_command_nr_of_retries, 3));
|
response.print(_preferences->getInt(preference_command_nr_of_retries, 3));
|
||||||
response.print("\nBluetooth command retry delay (ms): ");
|
response.print("\nBluetooth command retry delay (ms): ");
|
||||||
response.print(_preferences->getInt(preference_command_retry_delay, 100));
|
response.print(_preferences->getInt(preference_command_retry_delay, 100));
|
||||||
response.print("\nSeconds until reboot when no BLE beacons recieved: ");
|
response.print("\nSeconds until reboot when no BLE beacons received: ");
|
||||||
response.print(_preferences->getInt(preference_restart_ble_beacon_lost, 60));
|
response.print(_preferences->getInt(preference_restart_ble_beacon_lost, 60));
|
||||||
response.print("\n\n------------ QUERY / PUBLISH SETTINGS ------------");
|
response.print("\n\n------------ QUERY / PUBLISH SETTINGS ------------");
|
||||||
response.print("\nLock/Opener state query interval (s): ");
|
response.print("\nLock/Opener state query interval (s): ");
|
||||||
@@ -4643,14 +4640,14 @@ esp_err_t WebCfgServer::processUnpair(PsychicRequest *request, bool opener)
|
|||||||
|
|
||||||
if(!opener && _nuki != nullptr)
|
if(!opener && _nuki != nullptr)
|
||||||
{
|
{
|
||||||
_nuki->disableHASS();
|
|
||||||
_nuki->unpair();
|
_nuki->unpair();
|
||||||
}
|
}
|
||||||
if(opener && _nukiOpener != nullptr)
|
if(opener && _nukiOpener != nullptr)
|
||||||
{
|
{
|
||||||
_nukiOpener->disableHASS();
|
|
||||||
_nukiOpener->unpair();
|
_nukiOpener->unpair();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_network->disableHASS();
|
||||||
waitAndProcess(false, 1000);
|
waitAndProcess(false, 1000);
|
||||||
restartEsp(RestartReason::DeviceUnpaired);
|
restartEsp(RestartReason::DeviceUnpaired);
|
||||||
return res;
|
return res;
|
||||||
@@ -4769,15 +4766,14 @@ esp_err_t WebCfgServer::processFactoryReset(PsychicRequest *request)
|
|||||||
|
|
||||||
if(_nuki != nullptr)
|
if(_nuki != nullptr)
|
||||||
{
|
{
|
||||||
_nuki->disableHASS();
|
|
||||||
_nuki->unpair();
|
_nuki->unpair();
|
||||||
}
|
}
|
||||||
if(_nukiOpener != nullptr)
|
if(_nukiOpener != nullptr)
|
||||||
{
|
{
|
||||||
_nukiOpener->disableHASS();
|
|
||||||
_nukiOpener->unpair();
|
_nukiOpener->unpair();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_network->disableHASS();
|
||||||
_preferences->clear();
|
_preferences->clear();
|
||||||
|
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
|||||||
Reference in New Issue
Block a user