BLE fixes (#436)
* BLE fixes * Lock/Opener action fixes * Prevent Keypad/TC request when no valid PIN is set * Set BLE Power and C6 improvements * Update nuki_ble * BLE High performance on state change * Update nuki_ble
This commit is contained in:
@@ -22,8 +22,8 @@ Feel free to join us on Discord: https://discord.gg/9nPq85bP4p
|
|||||||
<b>Supported ESP32 devices:</b>
|
<b>Supported ESP32 devices:</b>
|
||||||
- Nuki Hub is compiled against all ESP32 models with Wi-Fi and Bluetooh Low Energy (BLE) which are supported by ESP-IDF 5.1.4 and Arduino Core 3.0.1.
|
- Nuki Hub is compiled against all ESP32 models with Wi-Fi and Bluetooh Low Energy (BLE) which are supported by ESP-IDF 5.1.4 and Arduino Core 3.0.1.
|
||||||
- Tested stable builds are provided for the ESP32, ESP32-S3 and ESP32-C3.
|
- Tested stable builds are provided for the ESP32, ESP32-S3 and ESP32-C3.
|
||||||
- Support for the ESP32-C6 is ***HIGHLY*** experimental. Expect frequent crashes, especially when running Nuki Hub paired as an app (when not using in Hybrid mode). Pairing is also not supported yet and needs to be done manually on the /advanced page of the web configurator.
|
- Support for the ESP32-C6 is experimental. There could be more frequent crashes than on other ESP32 devices and connections with the Nuki device could be slower than on other ESP32 devices.
|
||||||
- The ESP32-Solo1 is not supported by ESP-IDF 5.1 and as such can't be build using Arduino Core 3 and ESP-IDF 5.1. Untested build against Arduino Core 2.0.14 and ESP-IDF 4.4 are provided.
|
- The ESP32-Solo1 is not supported by ESP-IDF 5.1 and as such can't be build using Arduino Core 3 and ESP-IDF 5.1. Untested builds against Arduino Core 2.0.14 and ESP-IDF 4.4 are provided.
|
||||||
|
|
||||||
<b>Not supported ESP32 devices:</b>
|
<b>Not supported ESP32 devices:</b>
|
||||||
- The ESP32-S2 has no BLE and as such can't run Nuki Hub.
|
- The ESP32-S2 has no BLE and as such can't run Nuki Hub.
|
||||||
@@ -165,7 +165,7 @@ In a browser navigate to the IP address assigned to the ESP32.
|
|||||||
- Lock: Nuki Bridge is running alongside Nuki Hub: Enable to allow Nuki Hub to co-exist with a Nuki Bridge by registering Nuki Hub as an (smartphone) app instead of a bridge. Changing this setting will require re-pairing. Enabling this setting is strongly discouraged as described in the "[Pairing with a Nuki Lock or Opener](#pairing-with-a-nuki-lock-or-opener)" section of this README, ***unless when used in [Hybrid mode](/HYBRID.md) (Official MQTT / Nuki Hub co-existance)***
|
- Lock: Nuki Bridge is running alongside Nuki Hub: Enable to allow Nuki Hub to co-exist with a Nuki Bridge by registering Nuki Hub as an (smartphone) app instead of a bridge. Changing this setting will require re-pairing. Enabling this setting is strongly discouraged as described in the "[Pairing with a Nuki Lock or Opener](#pairing-with-a-nuki-lock-or-opener)" section of this README, ***unless when used in [Hybrid mode](/HYBRID.md) (Official MQTT / Nuki Hub co-existance)***
|
||||||
- Opener: Nuki Bridge is running alongside Nuki Hub: Enable to allow Nuki Hub to co-exist with a Nuki Bridge by registering Nuki Hub as an (smartphone) app instead of a bridge. Changing this setting will require re-pairing. Enabling this setting is strongly discouraged as described in the "[Pairing with a Nuki Lock or Opener](#pairing-with-a-nuki-lock-or-opener)" section of this README
|
- Opener: Nuki Bridge is running alongside Nuki Hub: Enable to allow Nuki Hub to co-exist with a Nuki Bridge by registering Nuki Hub as an (smartphone) app instead of a bridge. Changing this setting will require re-pairing. Enabling this setting is strongly discouraged as described in the "[Pairing with a Nuki Lock or Opener](#pairing-with-a-nuki-lock-or-opener)" section of this README
|
||||||
- Restart if bluetooth beacons not received: Set to a positive integer to restart the Nuki Hub after the set amount of seconds has passed without receiving a bluetooth beacon from the Nuki device, set to -1 to disable, default 60. Because the bluetooth stack of the ESP32 can silently fail it is not recommended to disable this setting.
|
- Restart if bluetooth beacons not received: Set to a positive integer to restart the Nuki Hub after the set amount of seconds has passed without receiving a bluetooth beacon from the Nuki device, set to -1 to disable, default 60. Because the bluetooth stack of the ESP32 can silently fail it is not recommended to disable this setting.
|
||||||
|
- BLE transmit power in dB: Set to a integer between -12 and 9 to set the Bluetooth transmit power, default 9.
|
||||||
### Access Level Configuration
|
### Access Level Configuration
|
||||||
|
|
||||||
#### Nuki General Access Control
|
#### Nuki General Access Control
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ void Scanner::initialize(const std::string& deviceName, const bool wantDuplicate
|
|||||||
}
|
}
|
||||||
BLEDevice::init(deviceName);
|
BLEDevice::init(deviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
bleScan = BLEDevice::getScan();
|
bleScan = BLEDevice::getScan();
|
||||||
|
|
||||||
#ifndef BLESCANNER_USE_LATEST_NIMBLE
|
#ifndef BLESCANNER_USE_LATEST_NIMBLE
|
||||||
@@ -98,4 +99,9 @@ void Scanner::onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scanner::whitelist(BLEAddress bleAddress) {
|
||||||
|
BLEDevice::whiteListAdd(bleAddress);
|
||||||
|
bleScan->setFilterPolicy(BLE_HCI_SCAN_FILT_USE_WL);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace BleScanner
|
} // namespace BleScanner
|
||||||
@@ -85,6 +85,14 @@ class Scanner : public Publisher, BLEAdvertisedDeviceCallbacks {
|
|||||||
*/
|
*/
|
||||||
void onResult(NimBLEAdvertisedDevice* advertisedDevice) override;
|
void onResult(NimBLEAdvertisedDevice* advertisedDevice) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whitelist a specific BLE Address
|
||||||
|
*
|
||||||
|
* @param whiteListBleAddress
|
||||||
|
*/
|
||||||
|
void whitelist(BLEAddress bleAddress);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t scanDuration = 0; //default indefinite scanning time
|
uint32_t scanDuration = 0; //default indefinite scanning time
|
||||||
BLEScan* bleScan = nullptr;
|
BLEScan* bleScan = nullptr;
|
||||||
|
|||||||
@@ -295,8 +295,6 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttributes)
|
|||||||
if(isConnected()) {
|
if(isConnected()) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Connect timeout - no response");
|
NIMBLE_LOGE(LOG_TAG, "Connect timeout - no response");
|
||||||
disconnect();
|
disconnect();
|
||||||
NIMBLE_LOGE(LOG_TAG, "Connect timeout - cancelling");
|
|
||||||
ble_gap_conn_cancel();
|
|
||||||
} else {
|
} else {
|
||||||
// workaround; if the controller doesn't cancel the connection
|
// workaround; if the controller doesn't cancel the connection
|
||||||
// at the timeout, cancel it here.
|
// at the timeout, cancel it here.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ default_envs = esp32dev
|
|||||||
boards_dir = boards
|
boards_dir = boards
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.11/platform-espressif32.zip
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.07.11/platform-espressif32.zip
|
||||||
platform_packages =
|
platform_packages =
|
||||||
framework = arduino, espidf
|
framework = arduino, espidf
|
||||||
build_type = release
|
build_type = release
|
||||||
@@ -64,6 +64,7 @@ extra_scripts =
|
|||||||
post:pio_package.py
|
post:pio_package.py
|
||||||
build_flags =
|
build_flags =
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
-DNUKI_ALT_CONNECT
|
||||||
-DBLESCANNER_USE_LATEST_NIMBLE
|
-DBLESCANNER_USE_LATEST_NIMBLE
|
||||||
-DNUKI_USE_LATEST_NIMBLE
|
-DNUKI_USE_LATEST_NIMBLE
|
||||||
-DNUKI_NO_WDT_RESET
|
-DNUKI_NO_WDT_RESET
|
||||||
@@ -98,6 +99,7 @@ build_flags =
|
|||||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
|
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
|
||||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||||
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
||||||
|
-DNUKI_ALT_CONNECT
|
||||||
-DNUKI_64BIT_TIME
|
-DNUKI_64BIT_TIME
|
||||||
lib_deps =
|
lib_deps =
|
||||||
BleScanner=symlink://lib/BleScanner
|
BleScanner=symlink://lib/BleScanner
|
||||||
@@ -115,6 +117,7 @@ build_flags =
|
|||||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||||
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
||||||
|
-DNUKI_ALT_CONNECT
|
||||||
-DBLESCANNER_USE_LATEST_NIMBLE
|
-DBLESCANNER_USE_LATEST_NIMBLE
|
||||||
-DNUKI_USE_LATEST_NIMBLE
|
-DNUKI_USE_LATEST_NIMBLE
|
||||||
-DNUKI_NO_WDT_RESET
|
-DNUKI_NO_WDT_RESET
|
||||||
@@ -136,6 +139,7 @@ build_flags =
|
|||||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||||
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
||||||
|
-DNUKI_ALT_CONNECT
|
||||||
-DBLESCANNER_USE_LATEST_NIMBLE
|
-DBLESCANNER_USE_LATEST_NIMBLE
|
||||||
-DNUKI_USE_LATEST_NIMBLE
|
-DNUKI_USE_LATEST_NIMBLE
|
||||||
-DNUKI_NO_WDT_RESET
|
-DNUKI_NO_WDT_RESET
|
||||||
@@ -157,6 +161,7 @@ build_flags =
|
|||||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||||
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
||||||
|
-DNUKI_ALT_CONNECT
|
||||||
-DBLESCANNER_USE_LATEST_NIMBLE
|
-DBLESCANNER_USE_LATEST_NIMBLE
|
||||||
-DNUKI_USE_LATEST_NIMBLE
|
-DNUKI_USE_LATEST_NIMBLE
|
||||||
-DNUKI_NO_WDT_RESET
|
-DNUKI_NO_WDT_RESET
|
||||||
@@ -178,6 +183,7 @@ build_flags =
|
|||||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||||
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
-DCONFIG_BT_NIMBLE_LOG_LEVEL=0
|
||||||
|
-DNUKI_ALT_CONNECT
|
||||||
-DBLESCANNER_USE_LATEST_NIMBLE
|
-DBLESCANNER_USE_LATEST_NIMBLE
|
||||||
-DNUKI_USE_LATEST_NIMBLE
|
-DNUKI_USE_LATEST_NIMBLE
|
||||||
-DNUKI_NO_WDT_RESET
|
-DNUKI_NO_WDT_RESET
|
||||||
@@ -199,6 +205,7 @@ build_flags =
|
|||||||
-DFRAMEWORK_ARDUINO_SOLO1
|
-DFRAMEWORK_ARDUINO_SOLO1
|
||||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||||
|
-DNUKI_ALT_CONNECT
|
||||||
-DNUKI_64BIT_TIME
|
-DNUKI_64BIT_TIME
|
||||||
-DDEBUG_NUKIHUB
|
-DDEBUG_NUKIHUB
|
||||||
-DDEBUG_SENSE_NUKI
|
-DDEBUG_SENSE_NUKI
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ CONFIG_BT_BLUEDROID_ENABLED=n
|
|||||||
CONFIG_BT_NIMBLE_ENABLED=y
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
CONFIG_BT_NIMBLE_LOG_LEVEL_NONE=y
|
CONFIG_BT_NIMBLE_LOG_LEVEL_NONE=y
|
||||||
CONFIG_BT_NIMBLE_LOG_LEVEL=0
|
CONFIG_BT_NIMBLE_LOG_LEVEL=0
|
||||||
|
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=8
|
||||||
|
CONFIG_BT_NIMBLE_MAX_BONDS=8
|
||||||
|
CONFIG_BT_NIMBLE_NVS_PERSIST=y
|
||||||
|
CONFIG_BT_NIMBLE_GATT_MAX_PROCS=8
|
||||||
CONFIG_NIMBLE_PINNED_TO_CORE_0=y
|
CONFIG_NIMBLE_PINNED_TO_CORE_0=y
|
||||||
CONFIG_NIMBLE_PINNED_TO_CORE=0
|
CONFIG_NIMBLE_PINNED_TO_CORE=0
|
||||||
CONFIG_NIMBLE_TASK_STACK_SIZE=8192
|
CONFIG_NIMBLE_TASK_STACK_SIZE=8192
|
||||||
@@ -37,6 +41,7 @@ CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255
|
|||||||
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
|
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
|
||||||
CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30
|
CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30
|
||||||
CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8
|
CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8
|
||||||
|
CONFIG_BTDM_CTRL_MODEM_SLEEP=n
|
||||||
CONFIG_NIMBLE_HS_FLOW_CTRL=y
|
CONFIG_NIMBLE_HS_FLOW_CTRL=y
|
||||||
CONFIG_NIMBLE_HS_FLOW_CTRL_ITVL=1000
|
CONFIG_NIMBLE_HS_FLOW_CTRL_ITVL=1000
|
||||||
CONFIG_NIMBLE_HS_FLOW_CTRL_THRESH=2
|
CONFIG_NIMBLE_HS_FLOW_CTRL_THRESH=2
|
||||||
@@ -44,8 +49,9 @@ CONFIG_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT=y
|
|||||||
CONFIG_NIMBLE_RPA_TIMEOUT=900
|
CONFIG_NIMBLE_RPA_TIMEOUT=900
|
||||||
CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS=y
|
CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS=y
|
||||||
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
|
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
|
||||||
CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3
|
CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=8
|
||||||
CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3
|
CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=8
|
||||||
|
CONFIG_BT_ACL_CONNECTIONS=8
|
||||||
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0
|
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0
|
||||||
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0
|
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0
|
||||||
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
|
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
|
||||||
@@ -65,3 +71,4 @@ CONFIG_IEEE802154_ENABLED=n
|
|||||||
CONFIG_ARDUINO_SELECTIVE_COMPILATION=y
|
CONFIG_ARDUINO_SELECTIVE_COMPILATION=y
|
||||||
CONFIG_ARDUINO_SELECTIVE_HTTPClient=n
|
CONFIG_ARDUINO_SELECTIVE_HTTPClient=n
|
||||||
CONFIG_ARDUINO_SELECTIVE_WebServer=n
|
CONFIG_ARDUINO_SELECTIVE_WebServer=n
|
||||||
|
CONFIG_HEAP_TASK_TRACKING=n
|
||||||
@@ -113,7 +113,7 @@ void NukiNetworkLock::initialize()
|
|||||||
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
|
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_preferences->getBool(preference_conf_info_enabled, false))
|
if(!_preferences->getBool(preference_conf_info_enabled, true))
|
||||||
{
|
{
|
||||||
_network->removeTopic(_mqttPath, mqtt_topic_config_basic_json);
|
_network->removeTopic(_mqttPath, mqtt_topic_config_basic_json);
|
||||||
_network->removeTopic(_mqttPath, mqtt_topic_config_advanced_json);
|
_network->removeTopic(_mqttPath, mqtt_topic_config_advanced_json);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ void NukiNetworkOpener::initialize()
|
|||||||
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
|
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_preferences->getBool(preference_conf_info_enabled, false))
|
if(!_preferences->getBool(preference_conf_info_enabled, true))
|
||||||
{
|
{
|
||||||
_network->removeTopic(_mqttPath, mqtt_topic_config_basic_json);
|
_network->removeTopic(_mqttPath, mqtt_topic_config_basic_json);
|
||||||
_network->removeTopic(_mqttPath, mqtt_topic_config_advanced_json);
|
_network->removeTopic(_mqttPath, mqtt_topic_config_advanced_json);
|
||||||
@@ -156,7 +156,7 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con
|
|||||||
strcmp(value, "denied") == 0 ||
|
strcmp(value, "denied") == 0 ||
|
||||||
strcmp(value, "error") == 0) return;
|
strcmp(value, "error") == 0) return;
|
||||||
|
|
||||||
Log->print(F("Lock action received: "));
|
Log->print(F("Opener action received: "));
|
||||||
Log->println(value);
|
Log->println(value);
|
||||||
LockActionResult lockActionResult = LockActionResult::Failed;
|
LockActionResult lockActionResult = LockActionResult::Failed;
|
||||||
if(_lockActionReceivedCallback != NULL)
|
if(_lockActionReceivedCallback != NULL)
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, NukiDeviceId
|
|||||||
|
|
||||||
nukiOpenerInst = this;
|
nukiOpenerInst = this;
|
||||||
|
|
||||||
memset(&_lastKeyTurnerState, sizeof(NukiLock::KeyTurnerState), 0);
|
memset(&_lastKeyTurnerState, sizeof(NukiOpener::OpenerState), 0);
|
||||||
memset(&_lastBatteryReport, sizeof(NukiLock::BatteryReport), 0);
|
memset(&_lastBatteryReport, sizeof(NukiOpener::BatteryReport), 0);
|
||||||
memset(&_batteryReport, sizeof(NukiLock::BatteryReport), 0);
|
memset(&_batteryReport, sizeof(NukiOpener::BatteryReport), 0);
|
||||||
memset(&_keyTurnerState, sizeof(NukiLock::KeyTurnerState), 0);
|
memset(&_keyTurnerState, sizeof(NukiOpener::OpenerState), 0);
|
||||||
_keyTurnerState.lockState = NukiOpener::LockState::Undefined;
|
_keyTurnerState.lockState = NukiOpener::LockState::Undefined;
|
||||||
|
|
||||||
network->setLockActionReceivedCallback(nukiOpenerInst->onLockActionReceivedCallback);
|
network->setLockActionReceivedCallback(nukiOpenerInst->onLockActionReceivedCallback);
|
||||||
@@ -48,6 +48,19 @@ NukiOpenerWrapper::~NukiOpenerWrapper()
|
|||||||
void NukiOpenerWrapper::initialize()
|
void NukiOpenerWrapper::initialize()
|
||||||
{
|
{
|
||||||
_nukiOpener.initialize();
|
_nukiOpener.initialize();
|
||||||
|
|
||||||
|
esp_power_level_t powerLevel;
|
||||||
|
|
||||||
|
if(_preferences->getInt(preference_ble_tx_power, 9) >= 9) powerLevel = ESP_PWR_LVL_P9;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 6) powerLevel = ESP_PWR_LVL_P6;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 3) powerLevel = ESP_PWR_LVL_P6;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 0) powerLevel = ESP_PWR_LVL_P3;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -3) powerLevel = ESP_PWR_LVL_N3;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -6) powerLevel = ESP_PWR_LVL_N6;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -9) powerLevel = ESP_PWR_LVL_N9;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -12) powerLevel = ESP_PWR_LVL_N12;
|
||||||
|
|
||||||
|
_nukiOpener.setPower(powerLevel);
|
||||||
_nukiOpener.registerBleScanner(_bleScanner);
|
_nukiOpener.registerBleScanner(_bleScanner);
|
||||||
|
|
||||||
_intervalLockstate = _preferences->getInt(preference_query_interval_lockstate);
|
_intervalLockstate = _preferences->getInt(preference_query_interval_lockstate);
|
||||||
@@ -103,9 +116,10 @@ void NukiOpenerWrapper::initialize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_nukiOpener.setEventHandler(this);
|
_nukiOpener.setEventHandler(this);
|
||||||
|
_nukiOpener.setConnectTimeout(3);
|
||||||
_nukiOpener.setDisconnectTimeout(5000);
|
_nukiOpener.setDisconnectTimeout(5000);
|
||||||
|
|
||||||
Log->print(F("Lock state interval: "));
|
Log->print(F("Opener state interval: "));
|
||||||
Log->print(_intervalLockstate);
|
Log->print(_intervalLockstate);
|
||||||
Log->print(F(" | Battery interval: "));
|
Log->print(F(" | Battery interval: "));
|
||||||
Log->print(_intervalBattery);
|
Log->print(_intervalBattery);
|
||||||
@@ -219,33 +233,23 @@ void NukiOpenerWrapper::update()
|
|||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_nextLockAction != (NukiOpener::LockAction)0xff && ts > _nextRetryTs)
|
if(_nextLockAction != (NukiOpener::LockAction)0xff)
|
||||||
{
|
{
|
||||||
Nuki::CmdResult cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0);
|
_retryCount = 0;
|
||||||
delay(250);
|
Nuki::CmdResult cmdResult;
|
||||||
|
|
||||||
|
while(_retryCount < _nrOfRetries + 1 && cmdResult != Nuki::CmdResult::Success)
|
||||||
|
{
|
||||||
|
cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0);
|
||||||
char resultStr[15] = {0};
|
char resultStr[15] = {0};
|
||||||
NukiOpener::cmdResultToString(cmdResult, resultStr);
|
NukiOpener::cmdResultToString(cmdResult, resultStr);
|
||||||
|
|
||||||
_network->publishCommandResult(resultStr);
|
_network->publishCommandResult(resultStr);
|
||||||
|
|
||||||
Log->print(F("Lock action result: "));
|
Log->print(F("Opener action result: "));
|
||||||
Log->println(resultStr);
|
Log->println(resultStr);
|
||||||
|
|
||||||
if(cmdResult == Nuki::CmdResult::Success)
|
if(cmdResult != Nuki::CmdResult::Success)
|
||||||
{
|
|
||||||
_retryCount = 0;
|
|
||||||
_nextLockAction = (NukiOpener::LockAction) 0xff;
|
|
||||||
_network->publishRetry("--");
|
|
||||||
|
|
||||||
if(_intervalLockstate > 10)
|
|
||||||
{
|
|
||||||
_nextLockStateUpdateTs = ts + 10 * 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(_retryCount < _nrOfRetries)
|
|
||||||
{
|
{
|
||||||
Log->print(F("Opener: Last command failed, retrying after "));
|
Log->print(F("Opener: Last command failed, retrying after "));
|
||||||
Log->print(_retryDelay);
|
Log->print(_retryDelay);
|
||||||
@@ -256,21 +260,28 @@ void NukiOpenerWrapper::update()
|
|||||||
|
|
||||||
_network->publishRetry(std::to_string(_retryCount + 1));
|
_network->publishRetry(std::to_string(_retryCount + 1));
|
||||||
|
|
||||||
_nextRetryTs = (esp_timer_get_time() / 1000) + _retryDelay;
|
delay(_retryDelay);
|
||||||
|
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
|
postponeBleWatchdog();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmdResult == Nuki::CmdResult::Success)
|
||||||
|
{
|
||||||
|
_nextLockAction = (NukiOpener::LockAction) 0xff;
|
||||||
|
_network->publishRetry("--");
|
||||||
|
_retryCount = 0;
|
||||||
|
if(_intervalLockstate > 10) _nextLockStateUpdateTs = ts + 10 * 1000;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log->println(F("Opener: Maximum number of retries exceeded, aborting."));
|
Log->println(F("Opener: Maximum number of retries exceeded, aborting."));
|
||||||
_network->publishRetry("failed");
|
_network->publishRetry("failed");
|
||||||
_retryCount = 0;
|
_retryCount = 0;
|
||||||
_nextRetryTs = 0;
|
|
||||||
_nextLockAction = (NukiOpener::LockAction) 0xff;
|
_nextLockAction = (NukiOpener::LockAction) 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postponeBleWatchdog();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_clearAuthData)
|
if(_clearAuthData)
|
||||||
{
|
{
|
||||||
@@ -349,7 +360,7 @@ void NukiOpenerWrapper::updateKeyTurnerState()
|
|||||||
{
|
{
|
||||||
Log->print(F("Querying opener state: "));
|
Log->print(F("Querying opener state: "));
|
||||||
result =_nukiOpener.requestOpenerState(&_keyTurnerState);
|
result =_nukiOpener.requestOpenerState(&_keyTurnerState);
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -459,7 +470,7 @@ void NukiOpenerWrapper::updateConfig()
|
|||||||
_hasKeypad = _nukiConfig.hasKeypad > 0 || _nukiConfig.hasKeypadV2 > 0;
|
_hasKeypad = _nukiConfig.hasKeypad > 0 || _nukiConfig.hasKeypadV2 > 0;
|
||||||
_firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]);
|
_firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]);
|
||||||
_hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]);
|
_hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]);
|
||||||
if(_preferences->getBool(preference_conf_info_enabled, false)) _network->publishConfig(_nukiConfig);
|
if(_preferences->getBool(preference_conf_info_enabled, true)) _network->publishConfig(_nukiConfig);
|
||||||
_retryConfigCount = 0;
|
_retryConfigCount = 0;
|
||||||
|
|
||||||
if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl(false);
|
if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl(false);
|
||||||
@@ -473,7 +484,7 @@ void NukiOpenerWrapper::updateConfig()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
result = _nukiOpener.verifySecurityPin();
|
result = _nukiOpener.verifySecurityPin();
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -513,7 +524,7 @@ void NukiOpenerWrapper::updateConfig()
|
|||||||
}
|
}
|
||||||
if(_nukiAdvancedConfigValid && _preferences->getUInt(preference_nuki_id_opener, 0) == _nukiConfig.nukiId)
|
if(_nukiAdvancedConfigValid && _preferences->getUInt(preference_nuki_id_opener, 0) == _nukiConfig.nukiId)
|
||||||
{
|
{
|
||||||
if(_preferences->getBool(preference_conf_info_enabled, false)) _network->publishAdvancedConfig(_nukiAdvancedConfig);
|
if(_preferences->getBool(preference_conf_info_enabled, true)) _network->publishAdvancedConfig(_nukiAdvancedConfig);
|
||||||
_retryConfigCount = 0;
|
_retryConfigCount = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -538,7 +549,6 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
|
|||||||
|
|
||||||
if(!retrieved)
|
if(!retrieved)
|
||||||
{
|
{
|
||||||
delay(250);
|
|
||||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||||
_retryCount = 0;
|
_retryCount = 0;
|
||||||
|
|
||||||
@@ -546,7 +556,7 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
|
|||||||
{
|
{
|
||||||
Log->print(F("Retrieve log entries: "));
|
Log->print(F("Retrieve log entries: "));
|
||||||
result = _nukiOpener.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
|
result = _nukiOpener.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -604,6 +614,12 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved)
|
|||||||
{
|
{
|
||||||
if(!_preferences->getBool(preference_keypad_info_enabled)) return;
|
if(!_preferences->getBool(preference_keypad_info_enabled)) return;
|
||||||
|
|
||||||
|
if(!isPinValid())
|
||||||
|
{
|
||||||
|
Log->println(F("No valid Nuki Opener PIN set"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!retrieved)
|
if(!retrieved)
|
||||||
{
|
{
|
||||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||||
@@ -613,7 +629,7 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved)
|
|||||||
{
|
{
|
||||||
Log->print(F("Querying opener keypad: "));
|
Log->print(F("Querying opener keypad: "));
|
||||||
result = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
result = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -631,7 +647,7 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved)
|
|||||||
std::list<NukiOpener::KeypadEntry> entries;
|
std::list<NukiOpener::KeypadEntry> entries;
|
||||||
_nukiOpener.getKeypadEntries(&entries);
|
_nukiOpener.getKeypadEntries(&entries);
|
||||||
|
|
||||||
Log->print(F("Lock keypad codes: "));
|
Log->print(F("Opener keypad codes: "));
|
||||||
Log->println(entries.size());
|
Log->println(entries.size());
|
||||||
|
|
||||||
entries.sort([](const NukiOpener::KeypadEntry& a, const NukiOpener::KeypadEntry& b) { return a.codeId < b.codeId; });
|
entries.sort([](const NukiOpener::KeypadEntry& a, const NukiOpener::KeypadEntry& b) { return a.codeId < b.codeId; });
|
||||||
@@ -665,6 +681,12 @@ void NukiOpenerWrapper::updateTimeControl(bool retrieved)
|
|||||||
{
|
{
|
||||||
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
||||||
|
|
||||||
|
if(!isPinValid())
|
||||||
|
{
|
||||||
|
Log->println(F("No valid Nuki Opener PIN set"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!retrieved)
|
if(!retrieved)
|
||||||
{
|
{
|
||||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||||
@@ -674,7 +696,7 @@ void NukiOpenerWrapper::updateTimeControl(bool retrieved)
|
|||||||
{
|
{
|
||||||
Log->print(F("Querying opener time control: "));
|
Log->print(F("Querying opener time control: "));
|
||||||
result = _nukiOpener.retrieveTimeControlEntries();
|
result = _nukiOpener.retrieveTimeControlEntries();
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -1509,7 +1531,6 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
|||||||
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
||||||
entry.code = codeInt;
|
entry.code = codeInt;
|
||||||
result = _nukiOpener.addKeypadEntry(entry);
|
result = _nukiOpener.addKeypadEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print("Add keypad code: ");
|
Log->print("Add keypad code: ");
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
@@ -1523,7 +1544,6 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = _nukiOpener.deleteKeypadEntry(id);
|
result = _nukiOpener.deleteKeypadEntry(id);
|
||||||
delay(250);
|
|
||||||
Log->print("Delete keypad code: ");
|
Log->print("Delete keypad code: ");
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
@@ -1559,7 +1579,6 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
|||||||
entry.code = codeInt;
|
entry.code = codeInt;
|
||||||
entry.enabled = enabled == 0 ? 0 : 1;
|
entry.enabled = enabled == 0 ? 0 : 1;
|
||||||
result = _nukiOpener.updateKeypadEntry(entry);
|
result = _nukiOpener.updateKeypadEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print("Update keypad code: ");
|
Log->print("Update keypad code: ");
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
@@ -1677,7 +1696,6 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
if(idExists)
|
if(idExists)
|
||||||
{
|
{
|
||||||
result = _nukiOpener.deleteKeypadEntry(codeId);
|
result = _nukiOpener.deleteKeypadEntry(codeId);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Delete keypad code: "));
|
Log->print(F("Delete keypad code: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -1864,7 +1882,6 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = _nukiOpener.addKeypadEntry(entry);
|
result = _nukiOpener.addKeypadEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Add keypad code: "));
|
Log->print(F("Add keypad code: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -1883,11 +1900,11 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Nuki::CmdResult resultKp = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
Nuki::CmdResult resultKp = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||||
delay(250);
|
|
||||||
bool foundExisting = false;
|
bool foundExisting = false;
|
||||||
|
|
||||||
if(resultKp == Nuki::CmdResult::Success)
|
if(resultKp == Nuki::CmdResult::Success)
|
||||||
{
|
{
|
||||||
|
delay(250);
|
||||||
std::list<NukiOpener::KeypadEntry> entries;
|
std::list<NukiOpener::KeypadEntry> entries;
|
||||||
_nukiOpener.getKeypadEntries(&entries);
|
_nukiOpener.getKeypadEntries(&entries);
|
||||||
|
|
||||||
@@ -2012,7 +2029,6 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = _nukiOpener.updateKeypadEntry(entry);
|
result = _nukiOpener.updateKeypadEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Update keypad code: "));
|
Log->print(F("Update keypad code: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2119,7 +2135,6 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
if(idExists)
|
if(idExists)
|
||||||
{
|
{
|
||||||
result = _nukiOpener.removeTimeControlEntry(entryId);
|
result = _nukiOpener.removeTimeControlEntry(entryId);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Delete time control: "));
|
Log->print(F("Delete time control: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2178,7 +2193,6 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
|
|
||||||
entry.lockAction = timeControlLockAction;
|
entry.lockAction = timeControlLockAction;
|
||||||
result = _nukiOpener.addTimeControlEntry(entry);
|
result = _nukiOpener.addTimeControlEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Add time control: "));
|
Log->print(F("Add time control: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2191,11 +2205,11 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Nuki::CmdResult resultTc = _nukiOpener.retrieveTimeControlEntries();
|
Nuki::CmdResult resultTc = _nukiOpener.retrieveTimeControlEntries();
|
||||||
delay(250);
|
|
||||||
bool foundExisting = false;
|
bool foundExisting = false;
|
||||||
|
|
||||||
if(resultTc == Nuki::CmdResult::Success)
|
if(resultTc == Nuki::CmdResult::Success)
|
||||||
{
|
{
|
||||||
|
delay(250);
|
||||||
std::list<NukiOpener::TimeControlEntry> timeControlEntries;
|
std::list<NukiOpener::TimeControlEntry> timeControlEntries;
|
||||||
_nukiOpener.getTimeControlEntries(&timeControlEntries);
|
_nukiOpener.getTimeControlEntries(&timeControlEntries);
|
||||||
|
|
||||||
@@ -2241,7 +2255,6 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
|
|
||||||
entry.lockAction = timeControlLockAction;
|
entry.lockAction = timeControlLockAction;
|
||||||
result = _nukiOpener.updateTimeControlEntry(entry);
|
result = _nukiOpener.updateTimeControlEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Update time control: "));
|
Log->print(F("Update time control: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2318,7 +2331,6 @@ void NukiOpenerWrapper::readConfig()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
Nuki::CmdResult result = _nukiOpener.requestConfig(&_nukiConfig);
|
Nuki::CmdResult result = _nukiOpener.requestConfig(&_nukiConfig);
|
||||||
delay(250);
|
|
||||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||||
|
|
||||||
if(!_nukiConfigValid) {
|
if(!_nukiConfigValid) {
|
||||||
@@ -2329,6 +2341,7 @@ void NukiOpenerWrapper::readConfig()
|
|||||||
|
|
||||||
char resultStr[20];
|
char resultStr[20];
|
||||||
NukiOpener::cmdResultToString(result, resultStr);
|
NukiOpener::cmdResultToString(result, resultStr);
|
||||||
|
Log->print(F("Opener config result: "));
|
||||||
Log->println(resultStr);
|
Log->println(resultStr);
|
||||||
postponeBleWatchdog();
|
postponeBleWatchdog();
|
||||||
}
|
}
|
||||||
@@ -2341,7 +2354,6 @@ void NukiOpenerWrapper::readAdvancedConfig()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
result = _nukiOpener.requestAdvancedConfig(&_nukiAdvancedConfig);
|
result = _nukiOpener.requestAdvancedConfig(&_nukiAdvancedConfig);
|
||||||
delay(250);
|
|
||||||
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
||||||
|
|
||||||
if(!_nukiAdvancedConfigValid) {
|
if(!_nukiAdvancedConfigValid) {
|
||||||
@@ -2352,6 +2364,7 @@ void NukiOpenerWrapper::readAdvancedConfig()
|
|||||||
|
|
||||||
char resultStr[20];
|
char resultStr[20];
|
||||||
NukiOpener::cmdResultToString(result, resultStr);
|
NukiOpener::cmdResultToString(result, resultStr);
|
||||||
|
Log->print(F("Opener advanced config result: "));
|
||||||
Log->println(resultStr);
|
Log->println(resultStr);
|
||||||
postponeBleWatchdog();
|
postponeBleWatchdog();
|
||||||
}
|
}
|
||||||
@@ -2383,7 +2396,6 @@ void NukiOpenerWrapper::disableHASS()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
result = _nukiOpener.requestConfig(&_nukiConfig);
|
result = _nukiOpener.requestConfig(&_nukiConfig);
|
||||||
delay(250);
|
|
||||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||||
|
|
||||||
if(!_nukiConfigValid) {
|
if(!_nukiConfigValid) {
|
||||||
|
|||||||
@@ -51,8 +51,20 @@ NukiWrapper::~NukiWrapper()
|
|||||||
|
|
||||||
void NukiWrapper::initialize(const bool& firstStart)
|
void NukiWrapper::initialize(const bool& firstStart)
|
||||||
{
|
{
|
||||||
|
|
||||||
_nukiLock.initialize();
|
_nukiLock.initialize();
|
||||||
|
|
||||||
|
esp_power_level_t powerLevel;
|
||||||
|
|
||||||
|
if(_preferences->getInt(preference_ble_tx_power, 9) >= 9) powerLevel = ESP_PWR_LVL_P9;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 6) powerLevel = ESP_PWR_LVL_P6;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 3) powerLevel = ESP_PWR_LVL_P6;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= 0) powerLevel = ESP_PWR_LVL_P3;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -3) powerLevel = ESP_PWR_LVL_N3;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -6) powerLevel = ESP_PWR_LVL_N6;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -9) powerLevel = ESP_PWR_LVL_N9;
|
||||||
|
else if(_preferences->getInt(preference_ble_tx_power, 9) >= -12) powerLevel = ESP_PWR_LVL_N12;
|
||||||
|
|
||||||
|
_nukiLock.setPower(powerLevel);
|
||||||
_nukiLock.registerBleScanner(_bleScanner);
|
_nukiLock.registerBleScanner(_bleScanner);
|
||||||
|
|
||||||
_intervalLockstate = _preferences->getInt(preference_query_interval_lockstate);
|
_intervalLockstate = _preferences->getInt(preference_query_interval_lockstate);
|
||||||
@@ -173,6 +185,7 @@ void NukiWrapper::initialize(const bool& firstStart)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_nukiLock.setEventHandler(this);
|
_nukiLock.setEventHandler(this);
|
||||||
|
_nukiLock.setConnectTimeout(3);
|
||||||
_nukiLock.setDisconnectTimeout(5000);
|
_nukiLock.setDisconnectTimeout(5000);
|
||||||
|
|
||||||
Log->print(F("Lock state interval: "));
|
Log->print(F("Lock state interval: "));
|
||||||
@@ -232,19 +245,72 @@ void NukiWrapper::update()
|
|||||||
|
|
||||||
_nukiLock.updateConnectionState();
|
_nukiLock.updateConnectionState();
|
||||||
|
|
||||||
if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
|
||||||
{
|
|
||||||
Log->println("Updating Lock state based on timer or query");
|
|
||||||
_statusUpdated = false;
|
|
||||||
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
|
||||||
updateKeyTurnerState();
|
|
||||||
_network->publishStatusUpdated(_statusUpdated);
|
|
||||||
}
|
|
||||||
if(networkInst->_offCommandExecutedTs>0 && ts >= networkInst->_offCommandExecutedTs)
|
if(networkInst->_offCommandExecutedTs>0 && ts >= networkInst->_offCommandExecutedTs)
|
||||||
{
|
{
|
||||||
nukiInst->_nextLockAction = networkInst->_offCommand;
|
nukiInst->_nextLockAction = networkInst->_offCommand;
|
||||||
networkInst->_offCommandExecutedTs = 0;
|
networkInst->_offCommandExecutedTs = 0;
|
||||||
}
|
}
|
||||||
|
if(_nextLockAction != (NukiLock::LockAction)0xff)
|
||||||
|
{
|
||||||
|
_retryCount = 0;
|
||||||
|
Nuki::CmdResult cmdResult;
|
||||||
|
|
||||||
|
while(_retryCount < _nrOfRetries + 1 && cmdResult != Nuki::CmdResult::Success)
|
||||||
|
{
|
||||||
|
cmdResult = _nukiLock.lockAction(_nextLockAction, 0, 0);
|
||||||
|
char resultStr[15] = {0};
|
||||||
|
NukiLock::cmdResultToString(cmdResult, resultStr);
|
||||||
|
|
||||||
|
_network->publishCommandResult(resultStr);
|
||||||
|
|
||||||
|
Log->print(F("Lock action result: "));
|
||||||
|
Log->println(resultStr);
|
||||||
|
|
||||||
|
if(cmdResult != Nuki::CmdResult::Success)
|
||||||
|
{
|
||||||
|
Log->print(F("Lock: Last command failed, retrying after "));
|
||||||
|
Log->print(_retryDelay);
|
||||||
|
Log->print(F(" milliseconds. Retry "));
|
||||||
|
Log->print(_retryCount + 1);
|
||||||
|
Log->print(" of ");
|
||||||
|
Log->println(_nrOfRetries);
|
||||||
|
|
||||||
|
_network->publishRetry(std::to_string(_retryCount + 1));
|
||||||
|
|
||||||
|
delay(_retryDelay);
|
||||||
|
|
||||||
|
++_retryCount;
|
||||||
|
}
|
||||||
|
postponeBleWatchdog();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmdResult == Nuki::CmdResult::Success)
|
||||||
|
{
|
||||||
|
_nextLockAction = (NukiLock::LockAction) 0xff;
|
||||||
|
_network->publishRetry("--");
|
||||||
|
_retryCount = 0;
|
||||||
|
if(!_network->_offConnected) _statusUpdated = true; Log->println(F("Lock: updating status after action"));
|
||||||
|
_statusUpdatedTs = ts;
|
||||||
|
if(_intervalLockstate > 10) _nextLockStateUpdateTs = ts + 10 * 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log->println(F("Lock: Maximum number of retries exceeded, aborting."));
|
||||||
|
_network->publishRetry("failed");
|
||||||
|
_retryCount = 0;
|
||||||
|
_nextLockAction = (NukiLock::LockAction) 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_statusUpdated || _nextLockStateUpdateTs == 0 || ts >= _nextLockStateUpdateTs || (queryCommands & QUERY_COMMAND_LOCKSTATE) > 0)
|
||||||
|
{
|
||||||
|
Log->println("Updating Lock state based on status, timer or query");
|
||||||
|
_statusUpdated = false;
|
||||||
|
_nextLockStateUpdateTs = ts + _intervalLockstate * 1000;
|
||||||
|
updateKeyTurnerState();
|
||||||
|
_network->publishStatusUpdated(_statusUpdated);
|
||||||
|
}
|
||||||
|
if(!_statusUpdated)
|
||||||
|
{
|
||||||
if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs || (queryCommands & QUERY_COMMAND_BATTERY) > 0)
|
if(_nextBatteryReportTs == 0 || ts > _nextBatteryReportTs || (queryCommands & QUERY_COMMAND_BATTERY) > 0)
|
||||||
{
|
{
|
||||||
Log->println("Updating Lock battery state based on timer or query");
|
Log->println("Updating Lock battery state based on timer or query");
|
||||||
@@ -291,66 +357,13 @@ void NukiWrapper::update()
|
|||||||
_lastRssi = rssi;
|
_lastRssi = rssi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_hasKeypad && _keypadEnabled && (_nextKeypadUpdateTs == 0 || ts > _nextKeypadUpdateTs || (queryCommands & QUERY_COMMAND_KEYPAD) > 0))
|
if(_hasKeypad && _keypadEnabled && (_nextKeypadUpdateTs == 0 || ts > _nextKeypadUpdateTs || (queryCommands & QUERY_COMMAND_KEYPAD) > 0))
|
||||||
{
|
{
|
||||||
Log->println("Updating Lock keypad based on timer or query");
|
Log->println("Updating Lock keypad based on timer or query");
|
||||||
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
|
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
|
||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_nextLockAction != (NukiLock::LockAction)0xff && ts > _nextRetryTs)
|
|
||||||
{
|
|
||||||
Nuki::CmdResult cmdResult = _nukiLock.lockAction(_nextLockAction, 0, 0);
|
|
||||||
|
|
||||||
char resultStr[15] = {0};
|
|
||||||
NukiLock::cmdResultToString(cmdResult, resultStr);
|
|
||||||
|
|
||||||
_network->publishCommandResult(resultStr);
|
|
||||||
|
|
||||||
Log->print(F("Lock action result: "));
|
|
||||||
Log->println(resultStr);
|
|
||||||
|
|
||||||
if(cmdResult == Nuki::CmdResult::Success)
|
|
||||||
{
|
|
||||||
_retryCount = 0;
|
|
||||||
_nextLockAction = (NukiLock::LockAction) 0xff;
|
|
||||||
_network->publishRetry("--");
|
|
||||||
|
|
||||||
if(_intervalLockstate > 10)
|
|
||||||
{
|
|
||||||
_nextLockStateUpdateTs = ts + 10 * 1000;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(_retryCount < _nrOfRetries)
|
|
||||||
{
|
|
||||||
Log->print(F("Lock: Last command failed, retrying after "));
|
|
||||||
Log->print(_retryDelay);
|
|
||||||
Log->print(F(" milliseconds. Retry "));
|
|
||||||
Log->print(_retryCount + 1);
|
|
||||||
Log->print(" of ");
|
|
||||||
Log->println(_nrOfRetries);
|
|
||||||
|
|
||||||
_network->publishRetry(std::to_string(_retryCount + 1));
|
|
||||||
|
|
||||||
_nextRetryTs = (esp_timer_get_time() / 1000) + _retryDelay;
|
|
||||||
|
|
||||||
++_retryCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log->println(F("Lock: Maximum number of retries exceeded, aborting."));
|
|
||||||
_network->publishRetry("failed");
|
|
||||||
_retryCount = 0;
|
|
||||||
_nextRetryTs = 0;
|
|
||||||
_nextLockAction = (NukiLock::LockAction) 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
postponeBleWatchdog();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_clearAuthData)
|
if(_clearAuthData)
|
||||||
{
|
{
|
||||||
Log->println("Clearing Lock auth data");
|
Log->println("Clearing Lock auth data");
|
||||||
@@ -426,7 +439,6 @@ void NukiWrapper::updateKeyTurnerState()
|
|||||||
Log->print(_retryCount + 1);
|
Log->print(_retryCount + 1);
|
||||||
Log->print("): ");
|
Log->print("): ");
|
||||||
result =_nukiLock.requestKeyTurnerState(&_keyTurnerState);
|
result =_nukiLock.requestKeyTurnerState(&_keyTurnerState);
|
||||||
delay(250);
|
|
||||||
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
@@ -456,18 +468,35 @@ void NukiWrapper::updateKeyTurnerState()
|
|||||||
|
|
||||||
_retryLockstateCount = 0;
|
_retryLockstateCount = 0;
|
||||||
|
|
||||||
if(_publishAuthData)
|
const NukiLock::LockState& lockState = _keyTurnerState.lockState;
|
||||||
|
|
||||||
|
if(lockState != _lastKeyTurnerState.lockState) _statusUpdatedTs = esp_timer_get_time() / 1000;
|
||||||
|
|
||||||
|
if(lockState == NukiLock::LockState::Locked ||
|
||||||
|
lockState == NukiLock::LockState::Unlocked ||
|
||||||
|
lockState == NukiLock::LockState::Calibration ||
|
||||||
|
lockState == NukiLock::LockState::BootRun ||
|
||||||
|
lockState == NukiLock::LockState::MotorBlocked)
|
||||||
|
{
|
||||||
|
if(_publishAuthData && (lockState == NukiLock::LockState::Locked || lockState == NukiLock::LockState::Unlocked))
|
||||||
{
|
{
|
||||||
Log->println(F("Publishing auth data"));
|
Log->println(F("Publishing auth data"));
|
||||||
updateAuthData(false);
|
updateAuthData(false);
|
||||||
Log->println(F("Done publishing auth data"));
|
Log->println(F("Done publishing auth data"));
|
||||||
}
|
}
|
||||||
|
|
||||||
_network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState);
|
|
||||||
updateGpioOutputs();
|
updateGpioOutputs();
|
||||||
|
}
|
||||||
|
else if(!_network->_offConnected && (esp_timer_get_time() / 1000) < _statusUpdatedTs + 10000)
|
||||||
|
{
|
||||||
|
_statusUpdated = true;
|
||||||
|
Log->println(F("Lock: Keep updating status on intermediate lock state"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState);
|
||||||
|
|
||||||
char lockStateStr[20];
|
char lockStateStr[20];
|
||||||
lockstateToString(_keyTurnerState.lockState, lockStateStr);
|
lockstateToString(lockState, lockStateStr);
|
||||||
Log->println(lockStateStr);
|
Log->println(lockStateStr);
|
||||||
|
|
||||||
postponeBleWatchdog();
|
postponeBleWatchdog();
|
||||||
@@ -487,7 +516,7 @@ void NukiWrapper::updateBatteryState()
|
|||||||
Log->print(_retryCount + 1);
|
Log->print(_retryCount + 1);
|
||||||
Log->print("): ");
|
Log->print("): ");
|
||||||
result = _nukiLock.requestBatteryReport(&_batteryReport);
|
result = _nukiLock.requestBatteryReport(&_batteryReport);
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -544,7 +573,7 @@ void NukiWrapper::updateConfig()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
result = _nukiLock.verifySecurityPin();
|
result = _nukiLock.verifySecurityPin();
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -615,7 +644,6 @@ void NukiWrapper::updateAuthData(bool retrieved)
|
|||||||
|
|
||||||
if(!retrieved)
|
if(!retrieved)
|
||||||
{
|
{
|
||||||
delay(250);
|
|
||||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||||
_retryCount = 0;
|
_retryCount = 0;
|
||||||
|
|
||||||
@@ -623,7 +651,7 @@ void NukiWrapper::updateAuthData(bool retrieved)
|
|||||||
{
|
{
|
||||||
Log->print(F("Retrieve log entries: "));
|
Log->print(F("Retrieve log entries: "));
|
||||||
result = _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
|
result = _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -680,6 +708,12 @@ void NukiWrapper::updateKeypad(bool retrieved)
|
|||||||
{
|
{
|
||||||
if(!_preferences->getBool(preference_keypad_info_enabled)) return;
|
if(!_preferences->getBool(preference_keypad_info_enabled)) return;
|
||||||
|
|
||||||
|
if(!isPinValid())
|
||||||
|
{
|
||||||
|
Log->println(F("No valid Nuki Lock PIN set"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!retrieved)
|
if(!retrieved)
|
||||||
{
|
{
|
||||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||||
@@ -689,7 +723,7 @@ void NukiWrapper::updateKeypad(bool retrieved)
|
|||||||
{
|
{
|
||||||
Log->print(F("Querying lock keypad: "));
|
Log->print(F("Querying lock keypad: "));
|
||||||
result = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
result = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -741,6 +775,12 @@ void NukiWrapper::updateTimeControl(bool retrieved)
|
|||||||
{
|
{
|
||||||
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
||||||
|
|
||||||
|
if(!isPinValid())
|
||||||
|
{
|
||||||
|
Log->println(F("No valid Nuki Lock PIN set"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!retrieved)
|
if(!retrieved)
|
||||||
{
|
{
|
||||||
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
Nuki::CmdResult result = (Nuki::CmdResult)-1;
|
||||||
@@ -750,7 +790,7 @@ void NukiWrapper::updateTimeControl(bool retrieved)
|
|||||||
{
|
{
|
||||||
Log->print(F("Querying lock time control: "));
|
Log->print(F("Querying lock time control: "));
|
||||||
result = _nukiLock.retrieveTimeControlEntries();
|
result = _nukiLock.retrieveTimeControlEntries();
|
||||||
delay(250);
|
|
||||||
if(result != Nuki::CmdResult::Success) {
|
if(result != Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -986,6 +1026,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
|||||||
{
|
{
|
||||||
_network->_offState = atoi(value);
|
_network->_offState = atoi(value);
|
||||||
_statusUpdated = true;
|
_statusUpdated = true;
|
||||||
|
Log->println(F("Lock: Updating status on Hybrid state change"));
|
||||||
_network->publishStatusUpdated(_statusUpdated);
|
_network->publishStatusUpdated(_statusUpdated);
|
||||||
NukiLock::lockstateToString((NukiLock::LockState)_network->_offState, str);
|
NukiLock::lockstateToString((NukiLock::LockState)_network->_offState, str);
|
||||||
_network->publishString(mqtt_topic_lock_state, str, true);
|
_network->publishString(mqtt_topic_lock_state, str, true);
|
||||||
@@ -1002,6 +1043,7 @@ void NukiWrapper::onOfficialUpdateReceived(const char *topic, const char *value)
|
|||||||
{
|
{
|
||||||
_network->_offDoorsensorState = atoi(value);
|
_network->_offDoorsensorState = atoi(value);
|
||||||
_statusUpdated = true;
|
_statusUpdated = true;
|
||||||
|
Log->println(F("Lock: Updating status on Hybrid door sensor state change"));
|
||||||
_network->publishStatusUpdated(_statusUpdated);
|
_network->publishStatusUpdated(_statusUpdated);
|
||||||
NukiLock::doorSensorStateToString((NukiLock::DoorSensorState)_network->_offDoorsensorState, str);
|
NukiLock::doorSensorStateToString((NukiLock::DoorSensorState)_network->_offDoorsensorState, str);
|
||||||
|
|
||||||
@@ -1350,7 +1392,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
|||||||
else jsonResult[basicKeys[i]] = "invalidValue";
|
else jsonResult[basicKeys[i]] = "invalidValue";
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(250);
|
|
||||||
if(!cmdResult == Nuki::CmdResult::Success) {
|
if(!cmdResult == Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -1635,7 +1676,6 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
|||||||
else jsonResult[advancedKeys[j]] = "invalidValue";
|
else jsonResult[advancedKeys[j]] = "invalidValue";
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(250);
|
|
||||||
if(!cmdResult == Nuki::CmdResult::Success) {
|
if(!cmdResult == Nuki::CmdResult::Success) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
}
|
}
|
||||||
@@ -1794,8 +1834,8 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
|||||||
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
||||||
entry.code = codeInt;
|
entry.code = codeInt;
|
||||||
result = _nukiLock.addKeypadEntry(entry);
|
result = _nukiLock.addKeypadEntry(entry);
|
||||||
delay(250);
|
Log->print("Add keypad code: ");
|
||||||
Log->print("Add keypad code: "); Log->println((int)result);
|
Log->println((int)result);
|
||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
}
|
}
|
||||||
else if(strcmp(command, "delete") == 0)
|
else if(strcmp(command, "delete") == 0)
|
||||||
@@ -1807,8 +1847,8 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = _nukiLock.deleteKeypadEntry(id);
|
result = _nukiLock.deleteKeypadEntry(id);
|
||||||
delay(250);
|
Log->print("Delete keypad code: ");
|
||||||
Log->print("Delete keypad code: "); Log->println((int)result);
|
Log->println((int)result);
|
||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
}
|
}
|
||||||
else if(strcmp(command, "update") == 0)
|
else if(strcmp(command, "update") == 0)
|
||||||
@@ -1842,8 +1882,8 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
|||||||
entry.code = codeInt;
|
entry.code = codeInt;
|
||||||
entry.enabled = enabled == 0 ? 0 : 1;
|
entry.enabled = enabled == 0 ? 0 : 1;
|
||||||
result = _nukiLock.updateKeypadEntry(entry);
|
result = _nukiLock.updateKeypadEntry(entry);
|
||||||
delay(250);
|
Log->print("Update keypad code: ");
|
||||||
Log->print("Update keypad code: "); Log->println((int)result);
|
Log->println((int)result);
|
||||||
updateKeypad(false);
|
updateKeypad(false);
|
||||||
}
|
}
|
||||||
else if(strcmp(command, "--") == 0)
|
else if(strcmp(command, "--") == 0)
|
||||||
@@ -1959,7 +1999,6 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
if(idExists)
|
if(idExists)
|
||||||
{
|
{
|
||||||
result = _nukiLock.deleteKeypadEntry(codeId);
|
result = _nukiLock.deleteKeypadEntry(codeId);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Delete keypad code: "));
|
Log->print(F("Delete keypad code: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2146,7 +2185,6 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = _nukiLock.addKeypadEntry(entry);
|
result = _nukiLock.addKeypadEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Add keypad code: "));
|
Log->print(F("Add keypad code: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2165,11 +2203,11 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Nuki::CmdResult resultKp = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
Nuki::CmdResult resultKp = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
|
||||||
delay(250);
|
|
||||||
bool foundExisting = false;
|
bool foundExisting = false;
|
||||||
|
|
||||||
if(resultKp == Nuki::CmdResult::Success)
|
if(resultKp == Nuki::CmdResult::Success)
|
||||||
{
|
{
|
||||||
|
delay(250);
|
||||||
std::list<NukiLock::KeypadEntry> entries;
|
std::list<NukiLock::KeypadEntry> entries;
|
||||||
_nukiLock.getKeypadEntries(&entries);
|
_nukiLock.getKeypadEntries(&entries);
|
||||||
|
|
||||||
@@ -2294,7 +2332,6 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = _nukiLock.updateKeypadEntry(entry);
|
result = _nukiLock.updateKeypadEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Update keypad code: "));
|
Log->print(F("Update keypad code: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2401,7 +2438,6 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
if(idExists)
|
if(idExists)
|
||||||
{
|
{
|
||||||
result = _nukiLock.removeTimeControlEntry(entryId);
|
result = _nukiLock.removeTimeControlEntry(entryId);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Delete time control: "));
|
Log->print(F("Delete time control: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2461,7 +2497,6 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
entry.lockAction = timeControlLockAction;
|
entry.lockAction = timeControlLockAction;
|
||||||
|
|
||||||
result = _nukiLock.addTimeControlEntry(entry);
|
result = _nukiLock.addTimeControlEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Add time control: "));
|
Log->print(F("Add time control: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2474,11 +2509,11 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Nuki::CmdResult resultTc = _nukiLock.retrieveTimeControlEntries();
|
Nuki::CmdResult resultTc = _nukiLock.retrieveTimeControlEntries();
|
||||||
delay(250);
|
|
||||||
bool foundExisting = false;
|
bool foundExisting = false;
|
||||||
|
|
||||||
if(resultTc == Nuki::CmdResult::Success)
|
if(resultTc == Nuki::CmdResult::Success)
|
||||||
{
|
{
|
||||||
|
delay(250);
|
||||||
std::list<NukiLock::TimeControlEntry> timeControlEntries;
|
std::list<NukiLock::TimeControlEntry> timeControlEntries;
|
||||||
_nukiLock.getTimeControlEntries(&timeControlEntries);
|
_nukiLock.getTimeControlEntries(&timeControlEntries);
|
||||||
|
|
||||||
@@ -2525,7 +2560,6 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
entry.lockAction = timeControlLockAction;
|
entry.lockAction = timeControlLockAction;
|
||||||
|
|
||||||
result = _nukiLock.updateTimeControlEntry(entry);
|
result = _nukiLock.updateTimeControlEntry(entry);
|
||||||
delay(250);
|
|
||||||
Log->print(F("Update time control: "));
|
Log->print(F("Update time control: "));
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
@@ -2590,6 +2624,7 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
|||||||
{
|
{
|
||||||
Log->println("KeyTurnerStatusUpdated");
|
Log->println("KeyTurnerStatusUpdated");
|
||||||
_statusUpdated = true;
|
_statusUpdated = true;
|
||||||
|
_statusUpdatedTs = esp_timer_get_time() / 1000;
|
||||||
_network->publishStatusUpdated(_statusUpdated);
|
_network->publishStatusUpdated(_statusUpdated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2604,11 +2639,8 @@ void NukiWrapper::readConfig()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
result = _nukiLock.requestConfig(&_nukiConfig);
|
result = _nukiLock.requestConfig(&_nukiConfig);
|
||||||
delay(250);
|
|
||||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||||
|
|
||||||
Log->print(F("Config valid: "));
|
|
||||||
Log->println(_nukiConfigValid);
|
|
||||||
if(!_nukiConfigValid) {
|
if(!_nukiConfigValid) {
|
||||||
++_retryCount;
|
++_retryCount;
|
||||||
Log->println("Retrying in 1s");
|
Log->println("Retrying in 1s");
|
||||||
@@ -2618,6 +2650,7 @@ void NukiWrapper::readConfig()
|
|||||||
|
|
||||||
char resultStr[20];
|
char resultStr[20];
|
||||||
NukiLock::cmdResultToString(result, resultStr);
|
NukiLock::cmdResultToString(result, resultStr);
|
||||||
|
Log->print(F("Lock config result: "));
|
||||||
Log->println(resultStr);
|
Log->println(resultStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2629,7 +2662,6 @@ void NukiWrapper::readAdvancedConfig()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
result = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig);
|
result = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig);
|
||||||
delay(250);
|
|
||||||
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
||||||
|
|
||||||
if(!_nukiAdvancedConfigValid) {
|
if(!_nukiAdvancedConfigValid) {
|
||||||
@@ -2640,6 +2672,7 @@ void NukiWrapper::readAdvancedConfig()
|
|||||||
|
|
||||||
char resultStr[20];
|
char resultStr[20];
|
||||||
NukiLock::cmdResultToString(result, resultStr);
|
NukiLock::cmdResultToString(result, resultStr);
|
||||||
|
Log->print(F("Lock advanced config result: "));
|
||||||
Log->println(resultStr);
|
Log->println(resultStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2675,7 +2708,6 @@ void NukiWrapper::disableHASS()
|
|||||||
while(_retryCount < _nrOfRetries + 1)
|
while(_retryCount < _nrOfRetries + 1)
|
||||||
{
|
{
|
||||||
result = _nukiLock.requestConfig(&_nukiConfig);
|
result = _nukiLock.requestConfig(&_nukiConfig);
|
||||||
delay(250);
|
|
||||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||||
|
|
||||||
if(!_nukiConfigValid) {
|
if(!_nukiConfigValid) {
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ private:
|
|||||||
int _retryConfigCount = 0;
|
int _retryConfigCount = 0;
|
||||||
int _retryLockstateCount = 0;
|
int _retryLockstateCount = 0;
|
||||||
int _rssiPublishInterval = 0;
|
int _rssiPublishInterval = 0;
|
||||||
|
int64_t _statusUpdatedTs = 0;
|
||||||
int64_t _nextRetryTs = 0;
|
int64_t _nextRetryTs = 0;
|
||||||
int64_t _nextLockStateUpdateTs = 0;
|
int64_t _nextLockStateUpdateTs = 0;
|
||||||
int64_t _nextHybridLockStateUpdateTs = 0;
|
int64_t _nextHybridLockStateUpdateTs = 0;
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
#define preference_ota_updater_url (char*)"otaUpdUrl"
|
#define preference_ota_updater_url (char*)"otaUpdUrl"
|
||||||
#define preference_update_from_mqtt (char*)"updMqtt"
|
#define preference_update_from_mqtt (char*)"updMqtt"
|
||||||
#define preference_show_secrets (char*)"showSecr"
|
#define preference_show_secrets (char*)"showSecr"
|
||||||
|
#define preference_ble_tx_power (char*)"bleTxPwr"
|
||||||
#define preference_recon_netw_on_mqtt_discon (char*)"recNtwMqttDis"
|
#define preference_recon_netw_on_mqtt_discon (char*)"recNtwMqttDis"
|
||||||
|
|
||||||
inline bool initPreferences(Preferences* preferences)
|
inline bool initPreferences(Preferences* preferences)
|
||||||
@@ -250,7 +251,7 @@ private:
|
|||||||
preference_official_hybrid, preference_query_interval_hybrid_lockstate, preference_official_hybrid_actions, preference_official_hybrid_retry, preference_has_mac_saved,
|
preference_official_hybrid, preference_query_interval_hybrid_lockstate, preference_official_hybrid_actions, preference_official_hybrid_retry, preference_has_mac_saved,
|
||||||
preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2, preference_latest_version, preference_task_size_network, preference_task_size_nuki,
|
preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2, preference_latest_version, preference_task_size_network, preference_task_size_nuki,
|
||||||
preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries, preference_update_from_mqtt, preference_show_secrets,
|
preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries, preference_update_from_mqtt, preference_show_secrets,
|
||||||
preference_recon_netw_on_mqtt_discon
|
preference_ble_tx_power, preference_recon_netw_on_mqtt_discon
|
||||||
};
|
};
|
||||||
std::vector<char*> _redact =
|
std::vector<char*> _redact =
|
||||||
{
|
{
|
||||||
@@ -280,7 +281,8 @@ private:
|
|||||||
preference_rssi_publish_interval, preference_network_timeout, preference_restart_ble_beacon_lost, preference_query_interval_lockstate,
|
preference_rssi_publish_interval, preference_network_timeout, preference_restart_ble_beacon_lost, preference_query_interval_lockstate,
|
||||||
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_command_nr_of_retries,
|
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_command_nr_of_retries,
|
||||||
preference_command_retry_delay, preference_presence_detection_timeout, preference_query_interval_hybrid_lockstate, preference_latest_version,
|
preference_command_retry_delay, preference_presence_detection_timeout, preference_query_interval_hybrid_lockstate, preference_latest_version,
|
||||||
preference_task_size_network, preference_task_size_nuki, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries
|
preference_task_size_network, preference_task_size_nuki, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries,
|
||||||
|
preference_ble_tx_power
|
||||||
};
|
};
|
||||||
std::vector<char*> _charPrefs =
|
std::vector<char*> _charPrefs =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -766,7 +766,7 @@ void WebCfgServer::sendSettings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pairing && _preferences->getBool(preference_show_secrets))
|
if(pairing)
|
||||||
{
|
{
|
||||||
if(_nuki != nullptr)
|
if(_nuki != nullptr)
|
||||||
{
|
{
|
||||||
@@ -1119,6 +1119,14 @@ bool WebCfgServer::processArgs(String& message)
|
|||||||
_preferences->putInt(preference_command_retry_delay, value.toInt());
|
_preferences->putInt(preference_command_retry_delay, value.toInt());
|
||||||
configChanged = true;
|
configChanged = true;
|
||||||
}
|
}
|
||||||
|
else if(key == "TXPWR")
|
||||||
|
{
|
||||||
|
if(value.toInt() >= -12 && value.toInt() <= 9)
|
||||||
|
{
|
||||||
|
_preferences->putInt(preference_ble_tx_power, value.toInt());
|
||||||
|
configChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
#if PRESENCE_DETECTION_ENABLED
|
#if PRESENCE_DETECTION_ENABLED
|
||||||
else if(key == "PRDTMO")
|
else if(key == "PRDTMO")
|
||||||
{
|
{
|
||||||
@@ -2530,6 +2538,8 @@ void WebCfgServer::buildNukiConfigHtml(String &response)
|
|||||||
printInputField(response, "PRDTMO", "Presence detection timeout (seconds; -1 to disable)", _preferences->getInt(preference_presence_detection_timeout), 10, "");
|
printInputField(response, "PRDTMO", "Presence detection timeout (seconds; -1 to disable)", _preferences->getInt(preference_presence_detection_timeout), 10, "");
|
||||||
#endif
|
#endif
|
||||||
printInputField(response, "RSBC", "Restart if bluetooth beacons not received (seconds; -1 to disable)", _preferences->getInt(preference_restart_ble_beacon_lost), 10, "");
|
printInputField(response, "RSBC", "Restart if bluetooth beacons not received (seconds; -1 to disable)", _preferences->getInt(preference_restart_ble_beacon_lost), 10, "");
|
||||||
|
printInputField(response, "TXPWR", "BLE transmit power in dB (minimum -12, maximum 9)", _preferences->getInt(preference_ble_tx_power, 9), 10, "");
|
||||||
|
|
||||||
response.concat("</table>");
|
response.concat("</table>");
|
||||||
response.concat("<br><input type=\"submit\" name=\"submit\" value=\"Save\">");
|
response.concat("<br><input type=\"submit\" name=\"submit\" value=\"Save\">");
|
||||||
response.concat("</form>");
|
response.concat("</form>");
|
||||||
|
|||||||
26
src/main.cpp
26
src/main.cpp
@@ -74,15 +74,20 @@ TaskHandle_t networkTaskHandle = nullptr;
|
|||||||
void networkTask(void *pvParameters)
|
void networkTask(void *pvParameters)
|
||||||
{
|
{
|
||||||
int64_t networkLoopTs = 0;
|
int64_t networkLoopTs = 0;
|
||||||
|
bool secrets = preferences->getBool(preference_show_secrets);
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
int64_t ts = (esp_timer_get_time() / 1000);
|
int64_t ts = (esp_timer_get_time() / 1000);
|
||||||
if(ts > 120000 && ts < 125000 && bootloopCounter > 0)
|
if(ts > 120000 && ts < 125000)
|
||||||
|
{
|
||||||
|
if(secrets) preferences->putBool(preference_show_secrets, false);
|
||||||
|
if(bootloopCounter > 0)
|
||||||
{
|
{
|
||||||
bootloopCounter = (int8_t)0;
|
bootloopCounter = (int8_t)0;
|
||||||
Log->println(F("Bootloop counter reset"));
|
Log->println(F("Bootloop counter reset"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool connected = network->update();
|
bool connected = network->update();
|
||||||
|
|
||||||
@@ -116,6 +121,7 @@ void networkTask(void *pvParameters)
|
|||||||
void nukiTask(void *pvParameters)
|
void nukiTask(void *pvParameters)
|
||||||
{
|
{
|
||||||
int64_t nukiLoopTs = 0;
|
int64_t nukiLoopTs = 0;
|
||||||
|
bool whiteListed = false;
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
@@ -128,6 +134,20 @@ void nukiTask(void *pvParameters)
|
|||||||
{
|
{
|
||||||
delay(5000);
|
delay(5000);
|
||||||
}
|
}
|
||||||
|
#ifndef PRESENCE_DETECTION_ENABLED
|
||||||
|
else if (!whiteListed)
|
||||||
|
{
|
||||||
|
whiteListed = true;
|
||||||
|
if(lockEnabled)
|
||||||
|
{
|
||||||
|
bleScanner->whitelist(nuki->getBleAddress());
|
||||||
|
}
|
||||||
|
if(openerEnabled)
|
||||||
|
{
|
||||||
|
bleScanner->whitelist(nukiOpener->getBleAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(lockEnabled)
|
if(lockEnabled)
|
||||||
{
|
{
|
||||||
@@ -313,7 +333,7 @@ void setupTasks(bool ota)
|
|||||||
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, 1);
|
xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), NULL, 3, &networkTaskHandle, 1);
|
||||||
esp_task_wdt_add(networkTaskHandle);
|
esp_task_wdt_add(networkTaskHandle);
|
||||||
#ifndef NUKI_HUB_UPDATER
|
#ifndef NUKI_HUB_UPDATER
|
||||||
xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), NULL, 2, &nukiTaskHandle, 1);
|
xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), NULL, 2, &nukiTaskHandle, 0);
|
||||||
esp_task_wdt_add(nukiTaskHandle);
|
esp_task_wdt_add(nukiTaskHandle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -393,7 +413,7 @@ void setup()
|
|||||||
// Scan interval and window according to Nuki recommendations:
|
// Scan interval and window according to Nuki recommendations:
|
||||||
// https://developer.nuki.io/t/bluetooth-specification-questions/1109/27
|
// https://developer.nuki.io/t/bluetooth-specification-questions/1109/27
|
||||||
bleScanner->initialize("NukiHub", true, 40, 40);
|
bleScanner->initialize("NukiHub", true, 40, 40);
|
||||||
bleScanner->setScanDuration(10);
|
bleScanner->setScanDuration(0);
|
||||||
|
|
||||||
#if PRESENCE_DETECTION_ENABLED
|
#if PRESENCE_DETECTION_ENABLED
|
||||||
if(preferences->getInt(preference_presence_detection_timeout) >= 0)
|
if(preferences->getInt(preference_presence_detection_timeout) >= 0)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ default_envs = updater_esp32dev
|
|||||||
boards_dir = ../boards
|
boards_dir = ../boards
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.11/platform-espressif32.zip
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.07.11/platform-espressif32.zip
|
||||||
platform_packages =
|
platform_packages =
|
||||||
framework = arduino, espidf
|
framework = arduino, espidf
|
||||||
build_type = release
|
build_type = release
|
||||||
|
|||||||
Reference in New Issue
Block a user