Merge branch 'master' into update-tasks

This commit is contained in:
iranl
2024-05-26 21:27:29 +02:00
committed by GitHub
33 changed files with 1065 additions and 486 deletions

View File

@@ -3,6 +3,7 @@
#include "sdkconfig.h"
#define NUKI_HUB_VERSION "8.34"
#define NUKI_HUB_BUILD "unknownbuildnr"
#define GITHUB_LATEST_RELEASE_URL "https://github.com/technyon/nuki_hub/releases/latest"
#define GITHUB_LATEST_RELEASE_API_URL "https://api.github.com/repos/technyon/nuki_hub/releases/latest"

View File

@@ -66,6 +66,7 @@
#define mqtt_topic_info_hardware_version "/info/hardwareVersion"
#define mqtt_topic_info_firmware_version "/info/firmwareVersion"
#define mqtt_topic_info_nuki_hub_version "/info/nukiHubVersion"
#define mqtt_topic_info_nuki_hub_build "/info/nukiHubBuild"
#define mqtt_topic_info_nuki_hub_latest "/info/nukiHubLatest"
#define mqtt_topic_info_nuki_hub_ip "/info/nukiHubIp"

View File

@@ -359,6 +359,7 @@ bool Network::update()
}
if (!_versionPublished) {
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_version, NUKI_HUB_VERSION);
publishString(_maintenancePathPrefix, mqtt_topic_info_nuki_hub_build, NUKI_HUB_BUILD);
_versionPublished = true;
}
_lastMaintenanceTs = ts;
@@ -598,7 +599,8 @@ void Network::registerMqttReceiver(MqttReceiver* receiver)
void Network::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
{
uint8_t value[360] = {0};
uint8_t value[800] = {0};
size_t l = min(len, sizeof(value)-1);
for(int i=0; i<l; i++)
@@ -692,6 +694,11 @@ const String Network::networkDeviceName() const
return _device->deviceName();
}
const String Network::networkBSSID() const
{
return _device->BSSIDstr();
}
void Network::publishFloat(const char* prefix, const char* topic, const float value, const uint8_t precision)
{
char str[30];
@@ -928,6 +935,23 @@ void Network::publishHASSConfig(char* deviceType, const char* baseTopic, char* n
"",
{ { (char*)"en", (char*)"true" },
{(char*)"ic", (char*)"mdi:counter"}});
// Nuki Hub build
publishHassTopic("sensor",
"nuki_hub_build",
uidString,
"_nuki_hub_build",
"Nuki Hub build",
name,
baseTopic,
_lockPath + mqtt_topic_info_nuki_hub_build,
deviceType,
"",
"",
"diagnostic",
"",
{ { (char*)"en", (char*)"true" },
{(char*)"ic", (char*)"mdi:counter"}});
if(_preferences->getBool(preference_check_updates))
{
@@ -3141,6 +3165,7 @@ void Network::removeHASSConfig(char* uidString)
removeHassTopic((char*)"sensor", (char*)"firmware_version", uidString);
removeHassTopic((char*)"sensor", (char*)"hardware_version", uidString);
removeHassTopic((char*)"sensor", (char*)"nuki_hub_version", uidString);
removeHassTopic((char*)"sensor", (char*)"nuki_hub_build", uidString);
removeHassTopic((char*)"sensor", (char*)"nuki_hub_latest", uidString);
removeHassTopic((char*)"update", (char*)"nuki_hub_update", uidString);
removeHassTopic((char*)"sensor", (char*)"nuki_hub_ip", uidString);

View File

@@ -66,6 +66,7 @@ public:
int mqttConnectionState(); // 0 = not connected; 1 = connected; 2 = connected and mqtt processed
bool encryptionSupported();
const String networkDeviceName() const;
const String networkBSSID() const;
const NetworkDeviceType networkDeviceType();

View File

@@ -46,7 +46,6 @@ void NetworkLock::initialize()
_network->initTopic(_mqttPath, mqtt_topic_lock_action, "--");
_network->subscribe(_mqttPath, mqtt_topic_lock_action);
_network->initTopic(_mqttPath, mqtt_topic_config_action, "--");
_network->subscribe(_mqttPath, mqtt_topic_config_action);
@@ -588,7 +587,6 @@ void NetworkLock::publishConfig(const NukiLock::Config &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_basic_json, _buffer);
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);
@@ -639,7 +637,6 @@ void NetworkLock::publishAdvancedConfig(const NukiLock::AdvancedConfig &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_advanced_json, _buffer);
publishBool(mqtt_topic_config_auto_unlock, config.autoUnLockDisabled == 0);
publishBool(mqtt_topic_config_auto_lock, config.autoLockEnabled == 1);
}
@@ -922,6 +919,7 @@ void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, cha
{
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, "~/maintenance/mqttConnectionState", hasKeypad, lockAction, unlockAction, openAction);
_network->publishHASSConfigAdditionalLockEntities(deviceType, baseTopic, name, uidString);
if(hasDoorSensor)
{
_network->publishHASSConfigDoorSensor(deviceType, baseTopic, name, uidString);

View File

@@ -39,7 +39,6 @@ void NetworkOpener::initialize()
_network->initTopic(_mqttPath, mqtt_topic_lock_action, "--");
_network->subscribe(_mqttPath, mqtt_topic_lock_action);
_network->initTopic(_mqttPath, mqtt_topic_config_action, "--");
_network->subscribe(_mqttPath, mqtt_topic_config_action);
@@ -578,7 +577,6 @@ void NetworkOpener::publishConfig(const NukiOpener::Config &config)
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_basic_json, _buffer);
publishBool(mqtt_topic_config_button_enabled, config.buttonEnabled == 1);
publishBool(mqtt_topic_config_led_enabled, config.ledFlashEnabled == 1);
publishString(mqtt_topic_info_firmware_version, std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]));
@@ -630,7 +628,6 @@ void NetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig &conf
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_config_advanced_json, _buffer);
publishUInt(mqtt_topic_config_sound_level, config.soundLevel);
}
@@ -675,7 +672,7 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
basePath.concat("/code_");
basePath.concat(std::to_string(index).c_str());
publishKeypadEntry(basePath, entry);
auto jsonEntry = json.add<JsonVariant>();
jsonEntry["codeId"] = entry.codeId;

View File

@@ -71,7 +71,7 @@ private:
void doorbellSuppressionToString(const int dbsupr, char* str);
void soundToString(const int sound, char* str);
void capabilitiesToString(const int capabilities, char* str);
String concat(String a, String b);
Preferences* _preferences;
@@ -80,7 +80,6 @@ private:
char _mqttPath[181] = {0};
bool _isConnected = false;
bool _firstTunerStatePublish = true;
bool _haEnabled= false;
bool _reconnected = false;

View File

@@ -228,6 +228,7 @@ void NukiOpenerWrapper::update()
_retryCount = 0;
_nextLockAction = (NukiOpener::LockAction) 0xff;
_network->publishRetry("--");
if(_intervalLockstate > 10)
{
_nextLockStateUpdateTs = ts + 10 * 1000;
@@ -1483,6 +1484,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
_network->publishKeypadJsonCommandResult("keypadNotAvailable");
return;
}
_network->publishKeypadJsonCommandResult("configNotReady");
return;
}
@@ -1732,7 +1734,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
_network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
return;
}
NukiOpener::UpdatedKeypadEntry entry;
memset(&entry, 0, sizeof(entry));
entry.codeId = codeId;
@@ -2078,6 +2080,7 @@ void NukiOpenerWrapper::disableHASS()
Nuki::CmdResult result = _nukiOpener.requestConfig(&_nukiConfig);
_nukiConfigValid = result == Nuki::CmdResult::Success;
}
if(_nukiConfigValid)
{
char uidString[20];

View File

@@ -53,6 +53,7 @@ private:
static void onKeypadJsonCommandReceivedCallback(const char* value);
static void onTimeControlCommandReceivedCallback(const char* value);
static void gpioActionCallback(const GpioAction& action, const int& pin);
void onKeypadCommandReceived(const char* command, const uint& id, const String& name, const String& code, const int& enabled);
void onConfigUpdateReceived(const char* value);
void onKeypadJsonCommandReceived(const char* value);

View File

@@ -247,6 +247,7 @@ void NukiWrapper::update()
_retryCount = 0;
_nextLockAction = (NukiLock::LockAction) 0xff;
_network->publishRetry("--");
if(_intervalLockstate > 10)
{
_nextLockStateUpdateTs = ts + 10 * 1000;
@@ -1477,6 +1478,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
_network->publishKeypadJsonCommandResult("keypadNotAvailable");
return;
}
_network->publishKeypadJsonCommandResult("configNotReady");
return;
}
@@ -1843,7 +1845,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
const char *time = json["time"].as<const char*>();
const char *lockAct = json["lockAction"].as<const char*>();
NukiLock::LockAction timeControlLockAction;
if(lockAct)
{
timeControlLockAction = nukiInst->lockActionToEnum(lockAct);
@@ -2059,6 +2061,7 @@ void NukiWrapper::disableHASS()
Nuki::CmdResult result = _nukiLock.requestConfig(&_nukiConfig);
_nukiConfigValid = result == Nuki::CmdResult::Success;
}
if(_nukiConfigValid)
{
char uidString[20];

View File

@@ -37,6 +37,7 @@
#define preference_network_hardware (char*)"nwhw"
#define preference_network_hardware_gpio (char*)"nwhwdt" // obsolete
#define preference_network_wifi_fallback_disabled (char*)"nwwififb"
#define preference_find_best_rssi (char*)"nwbestrssi"
#define preference_rssi_publish_interval (char*)"rssipb"
#define preference_hostname (char*)"hostname"
#define preference_network_timeout (char*)"nettmout"
@@ -92,7 +93,7 @@ private:
preference_opener_continuous_mode, preference_mqtt_opener_path, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count,
preference_enable_bootloop_reset, preference_mqtt_ca, preference_mqtt_crt, preference_mqtt_key, preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url,
preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address, preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server,
preference_network_hardware, preference_network_wifi_fallback_disabled, preference_rssi_publish_interval, preference_hostname,
preference_network_hardware, preference_network_wifi_fallback_disabled, preference_rssi_publish_interval, preference_hostname, preference_find_best_rssi,
preference_network_timeout, preference_restart_on_disconnect, preference_restart_ble_beacon_lost, preference_query_interval_lockstate,
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_keypad_control_enabled,
preference_keypad_info_enabled, preference_acl, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled,
@@ -112,8 +113,8 @@ private:
std::vector<char*> _boolPrefs =
{
preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_opener_enabled, preference_opener_continuous_mode,
preference_enable_bootloop_reset, preference_webserver_enabled, preference_restart_on_disconnect, preference_keypad_control_enabled, preference_keypad_info_enabled,
preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_ip_dhcp_enabled,
preference_enable_bootloop_reset, preference_webserver_enabled, preference_find_best_rssi, preference_restart_on_disconnect, preference_keypad_control_enabled,
preference_keypad_info_enabled, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_ip_dhcp_enabled,
preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info, preference_network_wifi_fallback_disabled
};

View File

@@ -383,6 +383,11 @@ bool WebCfgServer::processArgs(String& message)
_preferences->putString(preference_mqtt_hass_cu_url, value);
configChanged = true;
}
else if(key == "BESTRSSI")
{
_preferences->putBool(preference_find_best_rssi, (value == "1"));
configChanged = true;
}
else if(key == "HOSTNAME")
{
_preferences->putString(preference_hostname, value);
@@ -1067,9 +1072,6 @@ void WebCfgServer::buildHtml(String& response)
buildHtmlHeader(response);
response.concat("<br><h3>Info</h3>\n");
String version = NUKI_HUB_VERSION;
response.concat("<table>");
printParameter(response, "Hostname", _hostname.c_str());
@@ -1135,7 +1137,7 @@ void WebCfgServer::buildHtml(String& response)
}
}
printParameter(response, "Firmware", version.c_str(), "/info");
printParameter(response, "Firmware", NUKI_HUB_VERSION, "/info");
if(_preferences->getBool(preference_check_updates)) printParameter(response, "Latest Firmware", _preferences->getString(preference_latest_version).c_str(), "/ota");
@@ -1311,6 +1313,7 @@ void WebCfgServer::buildMqttConfigHtml(String &response)
printTextarea(response, "MQTTKEY", "MQTT SSL Client Key (*, optional)", _preferences->getString(preference_mqtt_key).c_str(), TLS_KEY_MAX_SIZE, _network->encryptionSupported(), true);
printDropDown(response, "NWHW", "Network hardware", String(_preferences->getInt(preference_network_hardware)), getNetworkDetectionOptions());
printCheckBox(response, "NWHWWIFIFB", "Disable fallback to Wi-Fi / Wi-Fi config portal", _preferences->getBool(preference_network_wifi_fallback_disabled), "");
printCheckBox(response, "BESTRSSI", "Connect to AP with the best signal in an environment with multiple APs with the same SSID", _preferences->getBool(preference_find_best_rssi), "");
printInputField(response, "RSSI", "RSSI Publish interval (seconds; -1 to disable)", _preferences->getInt(preference_rssi_publish_interval), 6);
printInputField(response, "NETTIMEOUT", "Network Timeout until restart (seconds; -1 to disable)", _preferences->getInt(preference_network_timeout), 5);
printCheckBox(response, "RSTDISC", "Restart on disconnect", _preferences->getBool(preference_restart_on_disconnect), "");
@@ -1368,6 +1371,7 @@ void WebCfgServer::buildAccLvlHtml(String &response)
response.concat("<input type=\"hidden\" name=\"ACLLVLCHANGED\" value=\"1\">");
response.concat("<h3>Nuki General Access Control</h3>");
response.concat("<table><tr><th>Setting</th><th>Enabled</th></tr>");
if((_nuki != nullptr && _nuki->hasKeypad()) || (_nukiOpener != nullptr && _nukiOpener->hasKeypad()))
{
printCheckBox(response, "KPPUB", "Publish keypad codes information", _preferences->getBool(preference_keypad_info_enabled), "");
@@ -1531,11 +1535,14 @@ void WebCfgServer::buildNukiConfigHtml(String &response)
response.concat("<h3>Basic Nuki Configuration</h3>");
response.concat("<table>");
printCheckBox(response, "LOCKENA", "Nuki Smartlock enabled", _preferences->getBool(preference_lock_enabled), "");
if(_preferences->getBool(preference_lock_enabled))
{
printInputField(response, "MQTTPATH", "MQTT Nuki Smartlock 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 Nuki Opener Path", _preferences->getString(preference_mqtt_opener_path).c_str(), 180);
@@ -1624,6 +1631,9 @@ void WebCfgServer::buildInfoHtml(String &response)
response.concat("Nuki Hub version: ");
response.concat(NUKI_HUB_VERSION);
response.concat("\n");
response.concat("Nuki Hub build: ");
response.concat(NUKI_HUB_BUILD);
response.concat("\n");
response.concat(debugPreferences.preferencesToString(_preferences));
@@ -1754,7 +1764,6 @@ void WebCfgServer::buildInfoHtml(String &response)
_preferences->getBytes(preference_conf_opener_basic_acl, &basicOpenerConfigAclPrefs, sizeof(basicOpenerConfigAclPrefs));
uint32_t advancedOpenerConfigAclPrefs[22];
_preferences->getBytes(preference_conf_opener_advanced_acl, &advancedOpenerConfigAclPrefs, sizeof(advancedOpenerConfigAclPrefs));
response.concat("Opener firmware version: ");
response.concat(_nukiOpener->firmwareVersion().c_str());
response.concat("\nOpener hardware version: ");
@@ -1853,6 +1862,13 @@ void WebCfgServer::buildInfoHtml(String &response)
response.concat("Network device: ");
response.concat(_network->networkDeviceName());
response.concat("\n");
if(_network->networkDeviceName() == "Built-in Wi-Fi")
{
response.concat("BSSID of AP: ");
response.concat(_network->networkBSSID());
response.concat("\n");
}
response.concat("Uptime: ");
response.concat(millis() / 1000 / 60);
@@ -1997,8 +2013,10 @@ void WebCfgServer::printCheckBox(String &response, const char *token, const char
response.concat("<input type=checkbox name=\"");
response.concat(token);
response.concat("\" class=\"");
response.concat(htmlClass);
response.concat("\" value=\"1\"");
response.concat(value ? " checked=\"checked\"" : "");
response.concat("/></td></tr>");

View File

@@ -260,6 +260,8 @@ void setup()
Log = &Serial;
Log->print(F("Nuki Hub version ")); Log->println(NUKI_HUB_VERSION);
Log->print(F("Nuki Hub build ")); Log->println(NUKI_HUB_BUILD);
bool firstStart = initPreferences();

View File

@@ -143,3 +143,8 @@ String EthLan8720Device::localIP()
{
return ETH.localIP().toString();
}
String EthLan8720Device::BSSIDstr()
{
return "";
}

View File

@@ -35,6 +35,7 @@ public:
int8_t signalStrength() override;
String localIP() override;
String BSSIDstr() override;
private:
void onDisconnected();

View File

@@ -33,6 +33,7 @@ public:
virtual int8_t signalStrength() = 0;
virtual String localIP() = 0;
virtual String BSSIDstr() = 0;
virtual void mqttSetClientId(const char* clientId);
virtual void mqttSetCleanSession(bool cleanSession);

View File

@@ -230,3 +230,8 @@ String W5500Device::localIP()
{
return Ethernet.localIP().toString();
}
String W5500Device::BSSIDstr()
{
return "";
}

View File

@@ -33,6 +33,7 @@ public:
int8_t signalStrength() override;
String localIP() override;
String BSSIDstr() override;
private:
void resetDevice();

View File

@@ -66,7 +66,8 @@ void WifiDevice::initialize()
wm_menu.push_back("wifi");
wm_menu.push_back("exit");
_wm.setEnableConfigPortal(_startAp || !_preferences->getBool(preference_network_wifi_fallback_disabled));
// reduced tieout if ESP is set to restart on disconnect
// reduced timeout if ESP is set to restart on disconnect
_wm.setFindBestRSSI(_preferences->getBool(preference_find_best_rssi));
_wm.setConfigPortalTimeout(_restartOnDisconnect ? 60 * 3 : 60 * 30);
_wm.setShowInfoUpdate(false);
_wm.setMenu(wm_menu);
@@ -159,6 +160,11 @@ String WifiDevice::localIP()
return WiFi.localIP().toString();
}
String WifiDevice::BSSIDstr()
{
return WiFi.BSSIDstr();
}
void WifiDevice::clearRtcInitVar(WiFiManager *)
{
memset(WiFiDevice_reconfdetect, 0, sizeof WiFiDevice_reconfdetect);

View File

@@ -25,6 +25,7 @@ public:
int8_t signalStrength() override;
String localIP() override;
String BSSIDstr() override;
private:
static void clearRtcInitVar(WiFiManager*);