Merge pull request #512 from iranl/home-assistant-checkbox
Various fixes for HTTP, MQTT, PSRAM and Ring detection + Add Home assistant enable/disable checkbox
This commit is contained in:
@@ -203,10 +203,11 @@ In a browser navigate to the IP address assigned to the ESP32.
|
|||||||
- MQTT User: If using authentication on the MQTT broker set to a username with read/write rights on the MQTT broker, set to # to clear
|
- MQTT User: If using authentication on the MQTT broker set 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 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.
|
||||||
|
|
||||||
#### Advanced MQTT Configuration
|
#### Advanced MQTT Configuration
|
||||||
|
|
||||||
- Home Assistant discovery topic: Set to the Home Assistant auto discovery topic, leave empty to disable auto discovery. Usually "homeassistant" unless you manually changed this setting on the Home Assistant side.
|
- Home Assistant discovery topic: Set to the Home Assistant auto discovery topic. Usually "homeassistant" unless you manually changed this setting on the Home Assistant side.
|
||||||
- Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode (Opener only): By default the lock entity in Home Assistant will enable Ring-to-Open (RTO) when unlocking and disable RTO when locking. By enabling this setting this behaviour will change and now unlocking will enable Continuous Mode and locking will disable Continuous Mode, for more information see the "[Home Assistant Discovery](#home-assistant-discovery-optional)" section of this README.
|
- Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode (Opener only): By default the lock entity in Home Assistant will enable Ring-to-Open (RTO) when unlocking and disable RTO when locking. By enabling this setting this behaviour will change and now unlocking will enable Continuous Mode and locking will disable Continuous Mode, for more information see the "[Home Assistant Discovery](#home-assistant-discovery-optional)" section of this README.
|
||||||
- MQTT SSL CA Certificate: Optionally set to the CA SSL certificate of the MQTT broker, see the "[MQTT Encryption](#mqtt-encryption-optional)" section of this README.
|
- MQTT SSL CA Certificate: Optionally set to the CA SSL certificate of the MQTT broker, see the "[MQTT Encryption](#mqtt-encryption-optional)" section of this README.
|
||||||
- MQTT SSL Client Certificate: Optionally set to the Client SSL certificate of the MQTT broker, see the "[MQTT Encryption](#mqtt-encryption-optional)" section of this README.
|
- MQTT SSL Client Certificate: Optionally set to the Client SSL certificate of the MQTT broker, see the "[MQTT Encryption](#mqtt-encryption-optional)" section of this README.
|
||||||
|
|||||||
37
boards/nuki-esp32dev.json
Normal file
37
boards/nuki-esp32dev.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"ldscript": "esp32_out.ld"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue",
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "40000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"mcu": "esp32",
|
||||||
|
"variant": "esp32"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"bluetooth",
|
||||||
|
"ethernet",
|
||||||
|
"can"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_board": "esp-wroom-32.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32 Dev Module",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"url": "https://en.wikipedia.org/wiki/ESP32",
|
||||||
|
"vendor": "AI Thinker"
|
||||||
|
}
|
||||||
@@ -69,7 +69,7 @@ monitor_filters =
|
|||||||
time
|
time
|
||||||
|
|
||||||
[env:esp32]
|
[env:esp32]
|
||||||
board = esp32dev
|
board = nuki-esp32dev
|
||||||
board_build.cmake_extra_args =
|
board_build.cmake_extra_args =
|
||||||
-DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.release.defaults;sdkconfig.defaults.esp32"
|
-DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.release.defaults;sdkconfig.defaults.esp32"
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#define NUKI_HUB_VERSION "9.02"
|
#define NUKI_HUB_VERSION "9.02"
|
||||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||||
#define NUKI_HUB_DATE "2024-11-03"
|
#define NUKI_HUB_DATE "2024-11-04"
|
||||||
|
|
||||||
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
||||||
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"
|
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ NukiNetwork::NukiNetwork(Preferences *preferences)
|
|||||||
{
|
{
|
||||||
_mqttConnectionStateTopic[i] = connectionStateTopic.charAt(i);
|
_mqttConnectionStateTopic[i] = connectionStateTopic.charAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(_preferences->getString(preference_mqtt_hass_discovery, "") != "" && !_preferences->getBool(preference_mqtt_hass_enabled, false))
|
||||||
|
{
|
||||||
|
_preferences->putBool(preference_mqtt_hass_enabled, true);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setupDevice();
|
setupDevice();
|
||||||
@@ -455,8 +461,13 @@ bool NukiNetwork::update()
|
|||||||
|
|
||||||
if(_lastMaintenanceTs == 0 || (ts - _lastMaintenanceTs) > 30000)
|
if(_lastMaintenanceTs == 0 || (ts - _lastMaintenanceTs) > 30000)
|
||||||
{
|
{
|
||||||
publishULong(_maintenancePathPrefix, mqtt_topic_uptime, ts / 1000 / 60, true);
|
int64_t curUptime = ts / 1000 / 60;
|
||||||
publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online", true);
|
if(curUptime > _publishedUpTime)
|
||||||
|
{
|
||||||
|
publishULong(_maintenancePathPrefix, mqtt_topic_uptime, curUptime, true);
|
||||||
|
_publishedUpTime = curUptime;
|
||||||
|
}
|
||||||
|
//publishString(_maintenancePathPrefix, mqtt_topic_mqtt_connection_state, "online", true);
|
||||||
|
|
||||||
if(_lastMaintenanceTs == 0)
|
if(_lastMaintenanceTs == 0)
|
||||||
{
|
{
|
||||||
@@ -2694,6 +2705,7 @@ void NukiNetwork::publishHASSConfigAdditionalOpenerEntities(char *deviceType, co
|
|||||||
json = createHassJson(uidString, "_ring_event", "Ring", name, baseTopic, String("~") + mqtt_topic_lock_ring, deviceType, "doorbell", "", "", "", {{(char*)"val_tpl", (char*)"{ \"event_type\": \"{{ value }}\" }"}});
|
json = createHassJson(uidString, "_ring_event", "Ring", name, baseTopic, String("~") + mqtt_topic_lock_ring, deviceType, "doorbell", "", "", "", {{(char*)"val_tpl", (char*)"{ \"event_type\": \"{{ value }}\" }"}});
|
||||||
json["event_types"][0] = "ring";
|
json["event_types"][0] = "ring";
|
||||||
json["event_types"][1] = "ringlocked";
|
json["event_types"][1] = "ringlocked";
|
||||||
|
json["event_types"][2] = "standby";
|
||||||
serializeJson(json, _buffer, _bufferSize);
|
serializeJson(json, _buffer, _bufferSize);
|
||||||
String path = createHassTopicPath("event", "ring", uidString);
|
String path = createHassTopicPath("event", "ring", uidString);
|
||||||
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
|
_device->mqttPublish(path.c_str(), MQTT_QOS_LEVEL, true, _buffer);
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ private:
|
|||||||
bool _connectReplyReceived = false;
|
bool _connectReplyReceived = false;
|
||||||
bool _firstDisconnected = true;
|
bool _firstDisconnected = true;
|
||||||
|
|
||||||
|
int64_t _publishedUpTime = 0;
|
||||||
int64_t _nextReconnect = 0;
|
int64_t _nextReconnect = 0;
|
||||||
char _mqttBrokerAddr[101] = {0};
|
char _mqttBrokerAddr[101] = {0};
|
||||||
char _mqttUser[31] = {0};
|
char _mqttUser[31] = {0};
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ void NukiNetworkOpener::initialize()
|
|||||||
_network->initTopic(_mqttPath, mqtt_topic_query_lockstate, "0");
|
_network->initTopic(_mqttPath, mqtt_topic_query_lockstate, "0");
|
||||||
_network->initTopic(_mqttPath, mqtt_topic_query_battery, "0");
|
_network->initTopic(_mqttPath, mqtt_topic_query_battery, "0");
|
||||||
_network->initTopic(_mqttPath, mqtt_topic_lock_binary_ring, "standby");
|
_network->initTopic(_mqttPath, mqtt_topic_lock_binary_ring, "standby");
|
||||||
|
_network->initTopic(_mqttPath, mqtt_topic_lock_ring, "standby");
|
||||||
_network->subscribe(_mqttPath, mqtt_topic_query_config);
|
_network->subscribe(_mqttPath, mqtt_topic_query_config);
|
||||||
_network->subscribe(_mqttPath, mqtt_topic_query_lockstate);
|
_network->subscribe(_mqttPath, mqtt_topic_query_lockstate);
|
||||||
_network->subscribe(_mqttPath, mqtt_topic_query_battery);
|
_network->subscribe(_mqttPath, mqtt_topic_query_battery);
|
||||||
@@ -128,6 +129,7 @@ void NukiNetworkOpener::update()
|
|||||||
{
|
{
|
||||||
_resetRingStateTs = 0;
|
_resetRingStateTs = 0;
|
||||||
publishString(mqtt_topic_lock_binary_ring, "standby", true);
|
publishString(mqtt_topic_lock_binary_ring, "standby", true);
|
||||||
|
publishString(mqtt_topic_lock_ring, "standby", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,10 +649,25 @@ void NukiNetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::Log
|
|||||||
|
|
||||||
if(log.index > _lastRollingLog)
|
if(log.index > _lastRollingLog)
|
||||||
{
|
{
|
||||||
_lastRollingLog = log.index;
|
|
||||||
serializeJson(entry, _buffer, _bufferSize);
|
serializeJson(entry, _buffer, _bufferSize);
|
||||||
publishString(mqtt_topic_lock_log_rolling, _buffer, true);
|
publishString(mqtt_topic_lock_log_rolling, _buffer, true);
|
||||||
publishInt(mqtt_topic_lock_log_rolling_last, log.index, true);
|
publishInt(mqtt_topic_lock_log_rolling_last, log.index, true);
|
||||||
|
|
||||||
|
if(log.loggingType == NukiOpener::LoggingType::DoorbellRecognition && _lastRollingLog > 0)
|
||||||
|
{
|
||||||
|
if((log.data[0] & 3) == 0)
|
||||||
|
{
|
||||||
|
Log->println(F("Nuki opener: Ring detected (Locked)"));
|
||||||
|
publishRing(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log->println(F("Nuki opener: Ring detected (Open)"));
|
||||||
|
publishRing(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastRollingLog = log.index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,9 +272,9 @@ void NukiOpenerWrapper::update()
|
|||||||
}
|
}
|
||||||
if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||||
{
|
{
|
||||||
_statusUpdated = false;
|
|
||||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
|
||||||
updateKeyTurnerState();
|
updateKeyTurnerState();
|
||||||
|
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||||
|
_statusUpdated = false;
|
||||||
_network->publishStatusUpdated(_statusUpdated);
|
_network->publishStatusUpdated(_statusUpdated);
|
||||||
}
|
}
|
||||||
if(_network->mqttConnectionState() == 2)
|
if(_network->mqttConnectionState() == 2)
|
||||||
@@ -448,7 +448,8 @@ void NukiOpenerWrapper::updateKeyTurnerState()
|
|||||||
}
|
}
|
||||||
_retryLockstateCount = 0;
|
_retryLockstateCount = 0;
|
||||||
|
|
||||||
if(_statusUpdated &&
|
if((!isPinValid() || !_publishAuthData) &&
|
||||||
|
_statusUpdated &&
|
||||||
_keyTurnerState.lockState == NukiOpener::LockState::Locked &&
|
_keyTurnerState.lockState == NukiOpener::LockState::Locked &&
|
||||||
_lastKeyTurnerState.lockState == NukiOpener::LockState::Locked &&
|
_lastKeyTurnerState.lockState == NukiOpener::LockState::Locked &&
|
||||||
_lastKeyTurnerState.nukiState == _keyTurnerState.nukiState)
|
_lastKeyTurnerState.nukiState == _keyTurnerState.nukiState)
|
||||||
@@ -458,7 +459,8 @@ void NukiOpenerWrapper::updateKeyTurnerState()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(_keyTurnerState.lockState != _lastKeyTurnerState.lockState &&
|
if((!isPinValid() || !_publishAuthData) &&
|
||||||
|
_keyTurnerState.lockState != _lastKeyTurnerState.lockState &&
|
||||||
_keyTurnerState.lockState == NukiOpener::LockState::Open &&
|
_keyTurnerState.lockState == NukiOpener::LockState::Open &&
|
||||||
_keyTurnerState.trigger == NukiOpener::Trigger::Manual)
|
_keyTurnerState.trigger == NukiOpener::Trigger::Manual)
|
||||||
{
|
{
|
||||||
@@ -3882,14 +3884,14 @@ void NukiOpenerWrapper::notify(Nuki::EventType eventType)
|
|||||||
{
|
{
|
||||||
if(eventType == Nuki::EventType::KeyTurnerStatusReset)
|
if(eventType == Nuki::EventType::KeyTurnerStatusReset)
|
||||||
{
|
{
|
||||||
_newSignal = false;
|
_newSignal = 0;
|
||||||
Log->println("KeyTurnerStatusReset");
|
Log->println("KeyTurnerStatusReset");
|
||||||
}
|
}
|
||||||
else if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
else if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
||||||
{
|
{
|
||||||
if(!_statusUpdated && !_newSignal)
|
if(!_statusUpdated && _newSignal < 5)
|
||||||
{
|
{
|
||||||
_newSignal = true;
|
_newSignal++;
|
||||||
Log->println("KeyTurnerStatusUpdated");
|
Log->println("KeyTurnerStatusUpdated");
|
||||||
_statusUpdated = true;
|
_statusUpdated = true;
|
||||||
_statusUpdatedTs = espMillis();
|
_statusUpdatedTs = espMillis();
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ private:
|
|||||||
|
|
||||||
bool _paired = false;
|
bool _paired = false;
|
||||||
bool _statusUpdated = false;
|
bool _statusUpdated = false;
|
||||||
bool _newSignal = false;
|
int _newSignal = 0;
|
||||||
bool _hasKeypad = false;
|
bool _hasKeypad = false;
|
||||||
bool _keypadEnabled = false;
|
bool _keypadEnabled = false;
|
||||||
uint _maxKeypadCodeCount = 0;
|
uint _maxKeypadCodeCount = 0;
|
||||||
|
|||||||
@@ -362,9 +362,9 @@ void NukiWrapper::update()
|
|||||||
if(_nukiOfficial->getStatusUpdated() || _statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
if(_nukiOfficial->getStatusUpdated() || _statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||||
{
|
{
|
||||||
Log->println("Updating Lock state based on status, timer or query");
|
Log->println("Updating Lock state based on status, timer or query");
|
||||||
|
updateKeyTurnerState();
|
||||||
_statusUpdated = false;
|
_statusUpdated = false;
|
||||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||||
updateKeyTurnerState();
|
|
||||||
_network->publishStatusUpdated(_statusUpdated);
|
_network->publishStatusUpdated(_statusUpdated);
|
||||||
}
|
}
|
||||||
if(_network->mqttConnectionState() == 2)
|
if(_network->mqttConnectionState() == 2)
|
||||||
@@ -4000,14 +4000,14 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
|||||||
{
|
{
|
||||||
if(eventType == Nuki::EventType::KeyTurnerStatusReset)
|
if(eventType == Nuki::EventType::KeyTurnerStatusReset)
|
||||||
{
|
{
|
||||||
_newSignal = false;
|
_newSignal = 0;
|
||||||
Log->println("KeyTurnerStatusReset");
|
Log->println("KeyTurnerStatusReset");
|
||||||
}
|
}
|
||||||
else if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
else if(eventType == Nuki::EventType::KeyTurnerStatusUpdated)
|
||||||
{
|
{
|
||||||
if(!_statusUpdated && !_newSignal)
|
if(!_statusUpdated && _newSignal < 5)
|
||||||
{
|
{
|
||||||
_newSignal = true;
|
_newSignal++;
|
||||||
Log->println("KeyTurnerStatusUpdated");
|
Log->println("KeyTurnerStatusUpdated");
|
||||||
_statusUpdated = true;
|
_statusUpdated = true;
|
||||||
_statusUpdatedTs = espMillis();
|
_statusUpdatedTs = espMillis();
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ private:
|
|||||||
bool _pairedAsApp = false;
|
bool _pairedAsApp = false;
|
||||||
bool _paired = false;
|
bool _paired = false;
|
||||||
bool _statusUpdated = false;
|
bool _statusUpdated = false;
|
||||||
bool _newSignal = false;
|
int _newSignal = 0;
|
||||||
bool _hasKeypad = false;
|
bool _hasKeypad = false;
|
||||||
bool _keypadEnabled = false;
|
bool _keypadEnabled = false;
|
||||||
uint _maxKeypadCodeCount = 0;
|
uint _maxKeypadCodeCount = 0;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#define preference_cred_user (char*)"crdusr"
|
#define preference_cred_user (char*)"crdusr"
|
||||||
#define preference_cred_password (char*)"crdpass"
|
#define preference_cred_password (char*)"crdpass"
|
||||||
#define preference_gpio_configuration (char*)"gpiocfg"
|
#define preference_gpio_configuration (char*)"gpiocfg"
|
||||||
|
#define preference_mqtt_hass_enabled (char*)"hassena"
|
||||||
#define preference_mqtt_hass_discovery (char*)"hassdiscovery"
|
#define preference_mqtt_hass_discovery (char*)"hassdiscovery"
|
||||||
#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"
|
||||||
@@ -293,7 +294,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_keypad_check_code_enabled, preference_disable_network_not_connected, preference_mqtt_hass_enabled
|
||||||
};
|
};
|
||||||
std::vector<char*> _redact =
|
std::vector<char*> _redact =
|
||||||
{
|
{
|
||||||
@@ -306,7 +307,7 @@ private:
|
|||||||
preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry, preference_enable_bootloop_reset, preference_webserver_enabled,
|
preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry, preference_enable_bootloop_reset, preference_webserver_enabled,
|
||||||
preference_restart_on_disconnect, preference_keypad_control_enabled, preference_keypad_info_enabled, preference_keypad_publish_code, preference_show_secrets,
|
preference_restart_on_disconnect, preference_keypad_control_enabled, preference_keypad_info_enabled, preference_keypad_publish_code, preference_show_secrets,
|
||||||
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_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_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
|
||||||
|
|||||||
@@ -292,14 +292,31 @@ void WebCfgServer::initialize()
|
|||||||
{
|
{
|
||||||
return request->requestAuthentication(BASIC_AUTH, "Nuki Hub", "You must log in.");
|
return request->requestAuthentication(BASIC_AUTH, "Nuki Hub", "You must log in.");
|
||||||
}
|
}
|
||||||
if(_allowRestartToPortal)
|
String value = "";
|
||||||
|
if(request->hasParam("CONFIRMTOKEN"))
|
||||||
{
|
{
|
||||||
|
const PsychicWebParameter* p = request->getParam("CONFIRMTOKEN");
|
||||||
|
if(p->value() != "")
|
||||||
|
{
|
||||||
|
value = p->value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return buildConfirmHtml(request, "No confirm code set.", 3, true);
|
||||||
|
}
|
||||||
|
if(value != _confirmCode)
|
||||||
|
{
|
||||||
|
return request->redirect("/");
|
||||||
|
}
|
||||||
|
if(!_allowRestartToPortal)
|
||||||
|
{
|
||||||
|
return buildConfirmHtml(request, "Can't reset WiFi when network device is Ethernet", 3, true);
|
||||||
|
}
|
||||||
esp_err_t res = buildConfirmHtml(request, "Restarting. Connect to ESP access point (\"NukiHub\" with password \"NukiHubESP32\") to reconfigure Wi-Fi.", 0);
|
esp_err_t res = buildConfirmHtml(request, "Restarting. Connect to ESP access point (\"NukiHub\" with password \"NukiHubESP32\") to reconfigure Wi-Fi.", 0);
|
||||||
waitAndProcess(false, 1000);
|
waitAndProcess(false, 1000);
|
||||||
_network->reconfigureDevice();
|
_network->reconfigureDevice();
|
||||||
return res;
|
return res;
|
||||||
}
|
|
||||||
return(ESP_OK);
|
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
_psychicServer->on("/unpairlock", HTTP_POST, [&](PsychicRequest *request)
|
_psychicServer->on("/unpairlock", HTTP_POST, [&](PsychicRequest *request)
|
||||||
@@ -1723,6 +1740,27 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
|
|||||||
//configChanged = true;
|
//configChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(key == "ENHADISC")
|
||||||
|
{
|
||||||
|
if(_preferences->getBool(preference_mqtt_hass_enabled, false) != (value == "1"))
|
||||||
|
{
|
||||||
|
if(!_preferences->getBool(preference_mqtt_hass_enabled, false))
|
||||||
|
{
|
||||||
|
if (_nuki != nullptr)
|
||||||
|
{
|
||||||
|
_nuki->disableHASS();
|
||||||
|
}
|
||||||
|
if (_nukiOpener != nullptr)
|
||||||
|
{
|
||||||
|
_nukiOpener->disableHASS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_preferences->putBool(preference_mqtt_hass_enabled, (value == "1"));
|
||||||
|
Log->print(F("Setting changed: "));
|
||||||
|
Log->println(key);
|
||||||
|
configChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(key == "HASSDISCOVERY")
|
else if(key == "HASSDISCOVERY")
|
||||||
{
|
{
|
||||||
if(_preferences->getString(preference_mqtt_hass_discovery, "") != value)
|
if(_preferences->getString(preference_mqtt_hass_discovery, "") != value)
|
||||||
@@ -3342,37 +3380,37 @@ esp_err_t WebCfgServer::buildHtml(PsychicRequest *request)
|
|||||||
printParameter(&response, "Nuki Opener PIN status", openerState.c_str(), "", "openerPin");
|
printParameter(&response, "Nuki Opener PIN status", openerState.c_str(), "", "openerPin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printParameter(&response, "Firmware", NUKI_HUB_VERSION, "/info", "firmware");
|
printParameter(&response, "Firmware", NUKI_HUB_VERSION, "/info?", "firmware");
|
||||||
if(_preferences->getBool(preference_check_updates))
|
if(_preferences->getBool(preference_check_updates))
|
||||||
{
|
{
|
||||||
printParameter(&response, "Latest Firmware", _preferences->getString(preference_latest_version).c_str(), "/ota", "ota");
|
printParameter(&response, "Latest Firmware", _preferences->getString(preference_latest_version).c_str(), "/ota?", "ota");
|
||||||
}
|
}
|
||||||
response.print("</table><br>");
|
response.print("</table><br>");
|
||||||
response.print("<ul id=\"tblnav\">");
|
response.print("<ul id=\"tblnav\">");
|
||||||
buildNavigationMenuEntry(&response, "Network Configuration", "/ntwconfig");
|
buildNavigationMenuEntry(&response, "Network Configuration", "/ntwconfig?");
|
||||||
buildNavigationMenuEntry(&response, "MQTT Configuration", "/mqttconfig", _brokerConfigured ? "" : "Please configure MQTT broker");
|
buildNavigationMenuEntry(&response, "MQTT Configuration", "/mqttconfig?", _brokerConfigured ? "" : "Please configure MQTT broker");
|
||||||
buildNavigationMenuEntry(&response, "Nuki Configuration", "/nukicfg");
|
buildNavigationMenuEntry(&response, "Nuki Configuration", "/nukicfg?");
|
||||||
buildNavigationMenuEntry(&response, "Access Level Configuration", "/acclvl");
|
buildNavigationMenuEntry(&response, "Access Level Configuration", "/acclvl?");
|
||||||
buildNavigationMenuEntry(&response, "Credentials", "/cred", _pinsConfigured ? "" : "Please configure PIN");
|
buildNavigationMenuEntry(&response, "Credentials", "/cred?", _pinsConfigured ? "" : "Please configure PIN");
|
||||||
buildNavigationMenuEntry(&response, "GPIO Configuration", "/gpiocfg");
|
buildNavigationMenuEntry(&response, "GPIO Configuration", "/gpiocfg?");
|
||||||
buildNavigationMenuEntry(&response, "Firmware update", "/ota");
|
buildNavigationMenuEntry(&response, "Firmware update", "/ota?");
|
||||||
buildNavigationMenuEntry(&response, "Import/Export Configuration", "/impexpcfg");
|
buildNavigationMenuEntry(&response, "Import/Export Configuration", "/impexpcfg?");
|
||||||
if(_preferences->getInt(preference_network_hardware, 0) == 11)
|
if(_preferences->getInt(preference_network_hardware, 0) == 11)
|
||||||
{
|
{
|
||||||
buildNavigationMenuEntry(&response, "Custom Ethernet Configuration", "/custntw");
|
buildNavigationMenuEntry(&response, "Custom Ethernet Configuration", "/custntw?");
|
||||||
}
|
}
|
||||||
if (_preferences->getBool(preference_publish_debug_info, false))
|
if (_preferences->getBool(preference_publish_debug_info, false))
|
||||||
{
|
{
|
||||||
buildNavigationMenuEntry(&response, "Advanced Configuration", "/advanced");
|
buildNavigationMenuEntry(&response, "Advanced Configuration", "/advanced?");
|
||||||
}
|
}
|
||||||
if(_preferences->getBool(preference_webserial_enabled, false))
|
if(_preferences->getBool(preference_webserial_enabled, false))
|
||||||
{
|
{
|
||||||
buildNavigationMenuEntry(&response, "Open Webserial", "/webserial");
|
buildNavigationMenuEntry(&response, "Open Webserial", "/webserial?");
|
||||||
}
|
}
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||||
if(_allowRestartToPortal)
|
if(_allowRestartToPortal)
|
||||||
{
|
{
|
||||||
buildNavigationMenuEntry(&response, "Configure Wi-Fi", "/wifi");
|
buildNavigationMenuEntry(&response, "Configure Wi-Fi", "/wifi?");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
String rebooturl = "/reboot?CONFIRMTOKEN=" + _confirmCode;
|
String rebooturl = "/reboot?CONFIRMTOKEN=" + _confirmCode;
|
||||||
@@ -3504,11 +3542,12 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
|
|||||||
printInputField(&response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30, "", false, true);
|
printInputField(&response, "MQTTUSER", "MQTT User (# to clear)", _preferences->getString(preference_mqtt_user).c_str(), 30, "", false, true);
|
||||||
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");
|
||||||
response.print("</table><br>");
|
response.print("</table><br>");
|
||||||
|
|
||||||
response.print("<h3>Advanced MQTT Configuration</h3>");
|
response.print("<h3>Advanced MQTT Configuration</h3>");
|
||||||
response.print("<table>");
|
response.print("<table>");
|
||||||
printInputField(&response, "HASSDISCOVERY", "Home Assistant discovery topic (empty to disable; usually homeassistant)", _preferences->getString(preference_mqtt_hass_discovery).c_str(), 30, "");
|
printInputField(&response, "HASSDISCOVERY", "Home Assistant discovery topic (usually \"homeassistant\")", _preferences->getString(preference_mqtt_hass_discovery).c_str(), 30, "class=\"chkHass\"");
|
||||||
if(_preferences->getBool(preference_opener_enabled, false))
|
if(_preferences->getBool(preference_opener_enabled, false))
|
||||||
{
|
{
|
||||||
printCheckBox(&response, "OPENERCONT", "Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode", _preferences->getBool(preference_opener_continuous_mode), "");
|
printCheckBox(&response, "OPENERCONT", "Set Nuki Opener Lock/Unlock action in Home Assistant to Continuous mode", _preferences->getBool(preference_opener_continuous_mode), "");
|
||||||
@@ -3528,7 +3567,9 @@ esp_err_t WebCfgServer::buildMqttConfigHtml(PsychicRequest *request)
|
|||||||
response.print("* If no encryption is configured for the MQTT broker, leave empty.<br><br>");
|
response.print("* If no encryption is configured for the MQTT broker, leave empty.<br><br>");
|
||||||
response.print("<br><input type=\"submit\" name=\"submit\" value=\"Save\">");
|
response.print("<br><input type=\"submit\" name=\"submit\" value=\"Save\">");
|
||||||
response.print("</form>");
|
response.print("</form>");
|
||||||
response.print("</body></html>");
|
response.print("</body>");
|
||||||
|
response.print("<script>window.onload = function() { var hassChk; var hassTxt; for (var el of document.getElementsByClassName('chkHass')) { if (el.constructor.name === 'HTMLInputElement' && el.type === 'checkbox') { hassChk = el; el.addEventListener('change', hassChkChange); } else if (el.constructor.name==='HTMLInputElement' && el.type==='text') { hassTxt=el; el.addEventListener('keyup', hassTxtChange); } } function hassChkChange() { if(hassChk.checked == true) { if(hassTxt.value.length == 0) { hassTxt.value = 'homeassistant'; } } else { hassTxt.value = ''; } } function hassTxtChange() { if(hassTxt.value.length == 0) { hassChk.checked = false; } else { hassChk.checked = true; } } };</script>");
|
||||||
|
response.print("</html>");
|
||||||
return response.endSend();
|
return response.endSend();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3978,7 +4019,8 @@ esp_err_t WebCfgServer::buildConfigureWifiHtml(PsychicRequest *request)
|
|||||||
buildHtmlHeader(&response);
|
buildHtmlHeader(&response);
|
||||||
response.print("<h3>Wi-Fi</h3>");
|
response.print("<h3>Wi-Fi</h3>");
|
||||||
response.print("Click confirm to remove saved WiFi settings and restart ESP into Wi-Fi configuration mode. After restart, connect to ESP access point to reconfigure Wi-Fi.<br><br>");
|
response.print("Click confirm to remove saved WiFi settings and restart ESP into Wi-Fi configuration mode. After restart, connect to ESP access point to reconfigure Wi-Fi.<br><br>");
|
||||||
buildNavigationButton(&response, "Confirm", "/wifimanager");
|
String wifiMgrUrl = "/wifimanager?CONFIRMTOKEN=" + _confirmCode;
|
||||||
|
buildNavigationButton(&response, "Confirm", wifiMgrUrl.c_str());
|
||||||
response.print("</body></html>");
|
response.print("</body></html>");
|
||||||
return response.endSend();
|
return response.endSend();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ bool wifiConnected = false;
|
|||||||
|
|
||||||
TaskHandle_t nukiTaskHandle = nullptr;
|
TaskHandle_t nukiTaskHandle = nullptr;
|
||||||
|
|
||||||
int64_t restartTs = ((2^64) - (5 * 1000 * 60000)) / 1000;
|
int64_t restartTs = (pow(2,64) - (5 * 1000 * 60000)) / 1000;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include "../../src/WebCfgServer.h"
|
#include "../../src/WebCfgServer.h"
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ monitor_filters =
|
|||||||
time
|
time
|
||||||
|
|
||||||
[env:updater_esp32]
|
[env:updater_esp32]
|
||||||
board = esp32dev
|
board = nuki-esp32dev
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
pre:pio_package_pre.py
|
pre:pio_package_pre.py
|
||||||
post:pio_package_post.py
|
post:pio_package_post.py
|
||||||
|
|||||||
Reference in New Issue
Block a user