Merge branch 'master' into check-keypad-codes
This commit is contained in:
29
README.md
29
README.md
@@ -15,7 +15,7 @@ Feel free to join us on Discord: https://discord.gg/9nPq85bP4p
|
||||
## Supported devices
|
||||
|
||||
<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.4.
|
||||
- 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.7.
|
||||
- Tested stable builds are provided for the ESP32, ESP32-S3 and ESP32-C3.
|
||||
- Untested builds are provided for the ESP32-Solo1.
|
||||
- Support for the ESP32-C6 and ESP32-H2 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.
|
||||
@@ -64,6 +64,33 @@ See the "[Connecting via Ethernet](#connecting-via-ethernet-optional)" section f
|
||||
|
||||
The ESP32-S3 is a dual-core CPU with many GPIO's, ability to enlarge RAM using PSRAM, ability to connect Ethernet modules over SPI and optionally power the device with a PoE splitter. The only functions missing from the ESP32-S3 as compared to other ESP devices is the ability to use some Ethernet modules only supported by the original ESP32 and the ability to connect over WIFI6 (C6)
|
||||
|
||||
## Feature comparison Nuki Hub vs. Nuki Bridge
|
||||
|
||||
| Feature | Nuki Hub | Nuki Bridge |
|
||||
|---|---|---|
|
||||
| Bridge API | | x |
|
||||
| Smart Lock remote control | (optional via smarthome solution) | x |
|
||||
| Smart Home integration via Matter | | x |
|
||||
| Apple HomeKit integration via Matter | | x |
|
||||
| MQTT API | x | x (only for SL > 3, Pro models) |
|
||||
| Wired LAN support | x | |
|
||||
| Power over Ethernet (PoE) | x (if supported by LAN/ESP module) | |
|
||||
| WLAN support | x | x (only for SL > 3, Pro Models) || Home Assistant integration | x (full integration of most Nuki features) | x |
|
||||
| Home Automation platform integration | x | x |
|
||||
| Cloud support | (optional via smarthome solution) | x |
|
||||
| Cloud-less operation | x | x (since fw 3.8.2, to be tested) |
|
||||
| Smarthome app integration | | x |
|
||||
| Nuki Smartlocks all models | x | x |
|
||||
| Nuki opener | x | x |
|
||||
| Nuki Keypad (1.0 and 2.0) | x | x |
|
||||
| MQTT encryption | x | |
|
||||
| Fine-grained access control of MQTT API | x | |
|
||||
| Export of lock actions via MQTT API | x | |
|
||||
| Control via GPIO | x | |
|
||||
| Hybrid mode for Pro locks | x | |
|
||||
|
||||
|
||||
|
||||
## Support Nuki Hub development
|
||||
|
||||
If you haven't ordered your Nuki product yet, you can support me by using my referrer code when placing your order:<br>
|
||||
|
||||
@@ -13,7 +13,7 @@ default_envs = esp32
|
||||
boards_dir = boards
|
||||
|
||||
[env]
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
|
||||
platform_packages =
|
||||
framework = arduino, espidf
|
||||
board_build.embed_txtfiles =
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#define NUKI_HUB_VERSION "9.02"
|
||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||
#define NUKI_HUB_DATE "2024-10-20"
|
||||
#define NUKI_HUB_DATE "2024-10-28"
|
||||
|
||||
#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"
|
||||
@@ -110,6 +110,7 @@
|
||||
#define MQTT_QOS_LEVEL 1
|
||||
#define MQTT_CLEAN_SESSIONS false
|
||||
#define MQTT_KEEP_ALIVE 60
|
||||
#define MQTT_STACK_SIZE 12288
|
||||
#define GPIO_DEBOUNCE_TIME 200
|
||||
#define CHAR_BUFFER_SIZE 4096
|
||||
#define NUKI_TASK_SIZE 8192
|
||||
|
||||
@@ -206,6 +206,7 @@ bool NukiNetwork::update()
|
||||
#else
|
||||
void NukiNetwork::initialize()
|
||||
{
|
||||
_mqtt_cfg.task.stack_size = MQTT_STACK_SIZE;
|
||||
_hostname = _preferences->getString(preference_hostname, "");
|
||||
|
||||
if(_hostname == "")
|
||||
|
||||
@@ -2539,7 +2539,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
String allowedFromTime;
|
||||
String allowedUntilTime;
|
||||
|
||||
if(json["code"].is<unsigned int>())
|
||||
if(json["code"].is<JsonVariant>())
|
||||
{
|
||||
code = json["code"].as<unsigned int>();
|
||||
}
|
||||
@@ -2548,7 +2548,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
code = 12;
|
||||
}
|
||||
|
||||
if(json["enabled"].is<unsigned int>())
|
||||
if(json["enabled"].is<JsonVariant>())
|
||||
{
|
||||
enabled = json["enabled"].as<unsigned int>();
|
||||
}
|
||||
@@ -2557,7 +2557,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
enabled = 2;
|
||||
}
|
||||
|
||||
if(json["timeLimited"].is<unsigned int>())
|
||||
if(json["timeLimited"].is<JsonVariant>())
|
||||
{
|
||||
timeLimited = json["timeLimited"].as<unsigned int>();
|
||||
}
|
||||
@@ -2566,27 +2566,27 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
timeLimited = 2;
|
||||
}
|
||||
|
||||
if(json["name"].is<String>())
|
||||
if(json["name"].is<JsonVariant>())
|
||||
{
|
||||
name = json["name"].as<String>();
|
||||
}
|
||||
if(json["allowedFrom"].is<String>())
|
||||
if(json["allowedFrom"].is<JsonVariant>())
|
||||
{
|
||||
allowedFrom = json["allowedFrom"].as<String>();
|
||||
}
|
||||
if(json["allowedUntil"].is<String>())
|
||||
if(json["allowedUntil"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntil = json["allowedUntil"].as<String>();
|
||||
}
|
||||
if(json["allowedWeekdays"].is<String>())
|
||||
if(json["allowedWeekdays"].is<JsonVariant>())
|
||||
{
|
||||
allowedWeekdays = json["allowedWeekdays"].as<String>();
|
||||
}
|
||||
if(json["allowedFromTime"].is<String>())
|
||||
if(json["allowedFromTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedFromTime = json["allowedFromTime"].as<String>();
|
||||
}
|
||||
if(json["allowedUntilTime"].is<String>())
|
||||
if(json["allowedUntilTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntilTime = json["allowedUntilTime"].as<String>();
|
||||
}
|
||||
@@ -2726,8 +2726,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
if(allowedUntil.length() > 0)
|
||||
{
|
||||
if(allowedUntil.length() > 0 == 19)
|
||||
if(allowedUntil.length() == 19)
|
||||
{
|
||||
allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
|
||||
allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
|
||||
@@ -3061,7 +3060,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
String lockAction;
|
||||
NukiOpener::LockAction timeControlLockAction;
|
||||
|
||||
if(json["enabled"].is<unsigned int>())
|
||||
if(json["enabled"].is<JsonVariant>())
|
||||
{
|
||||
enabled = json["enabled"].as<unsigned int>();
|
||||
}
|
||||
@@ -3070,15 +3069,15 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
enabled = 2;
|
||||
}
|
||||
|
||||
if(json["weekdays"].is<String>())
|
||||
if(json["weekdays"].is<JsonVariant>())
|
||||
{
|
||||
weekdays = json["weekdays"].as<String>();
|
||||
}
|
||||
if(json["time"].is<String>())
|
||||
if(json["time"].is<JsonVariant>())
|
||||
{
|
||||
time = json["time"].as<String>();
|
||||
}
|
||||
if(json["lockAction"].is<String>())
|
||||
if(json["lockAction"].is<JsonVariant>())
|
||||
{
|
||||
lockAction = json["lockAction"].as<String>();
|
||||
}
|
||||
@@ -3351,7 +3350,7 @@ void NukiOpenerWrapper::onAuthCommandReceived(const char *value)
|
||||
String allowedFromTime;
|
||||
String allowedUntilTime;
|
||||
|
||||
if(json["remoteAllowed"].is<unsigned int>())
|
||||
if(json["remoteAllowed"].is<JsonVariant>())
|
||||
{
|
||||
remoteAllowed = json["remoteAllowed"].as<unsigned int>();
|
||||
}
|
||||
@@ -3360,7 +3359,7 @@ void NukiOpenerWrapper::onAuthCommandReceived(const char *value)
|
||||
remoteAllowed = 2;
|
||||
}
|
||||
|
||||
if(json["enabled"].is<unsigned int>())
|
||||
if(json["enabled"].is<JsonVariant>())
|
||||
{
|
||||
enabled = json["enabled"].as<unsigned int>();
|
||||
}
|
||||
@@ -3369,7 +3368,7 @@ void NukiOpenerWrapper::onAuthCommandReceived(const char *value)
|
||||
enabled = 2;
|
||||
}
|
||||
|
||||
if(json["timeLimited"].is<unsigned int>())
|
||||
if(json["timeLimited"].is<JsonVariant>())
|
||||
{
|
||||
timeLimited = json["timeLimited"].as<unsigned int>();
|
||||
}
|
||||
@@ -3378,28 +3377,28 @@ void NukiOpenerWrapper::onAuthCommandReceived(const char *value)
|
||||
timeLimited = 2;
|
||||
}
|
||||
|
||||
if(json["name"].is<String>())
|
||||
if(json["name"].is<JsonVariant>())
|
||||
{
|
||||
name = json["name"].as<String>();
|
||||
}
|
||||
//if(json["sharedKey"].is<String>()) sharedKey = json["sharedKey"].as<String>();
|
||||
if(json["allowedFrom"].is<String>())
|
||||
//if(json["sharedKey"].is<JsonVariant>()) sharedKey = json["sharedKey"].as<String>();
|
||||
if(json["allowedFrom"].is<JsonVariant>())
|
||||
{
|
||||
allowedFrom = json["allowedFrom"].as<String>();
|
||||
}
|
||||
if(json["allowedUntil"].is<String>())
|
||||
if(json["allowedUntil"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntil = json["allowedUntil"].as<String>();
|
||||
}
|
||||
if(json["allowedWeekdays"].is<String>())
|
||||
if(json["allowedWeekdays"].is<JsonVariant>())
|
||||
{
|
||||
allowedWeekdays = json["allowedWeekdays"].as<String>();
|
||||
}
|
||||
if(json["allowedFromTime"].is<String>())
|
||||
if(json["allowedFromTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedFromTime = json["allowedFromTime"].as<String>();
|
||||
}
|
||||
if(json["allowedUntilTime"].is<String>())
|
||||
if(json["allowedUntilTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntilTime = json["allowedUntilTime"].as<String>();
|
||||
}
|
||||
@@ -3492,7 +3491,7 @@ void NukiOpenerWrapper::onAuthCommandReceived(const char *value)
|
||||
|
||||
if(allowedUntil.length() > 0)
|
||||
{
|
||||
if(allowedUntil.length() > 0 == 19)
|
||||
if(allowedUntil.length() == 19)
|
||||
{
|
||||
allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
|
||||
allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
|
||||
|
||||
@@ -2650,7 +2650,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
String allowedFromTime;
|
||||
String allowedUntilTime;
|
||||
|
||||
if(json["code"].is<unsigned int>())
|
||||
if(json["code"].is<JsonVariant>())
|
||||
{
|
||||
code = json["code"].as<unsigned int>();
|
||||
}
|
||||
@@ -2659,7 +2659,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
code = 12;
|
||||
}
|
||||
|
||||
if(json["enabled"].is<unsigned int>())
|
||||
if(json["enabled"].is<JsonVariant>())
|
||||
{
|
||||
enabled = json["enabled"].as<unsigned int>();
|
||||
}
|
||||
@@ -2668,7 +2668,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
enabled = 2;
|
||||
}
|
||||
|
||||
if(json["timeLimited"].is<unsigned int>())
|
||||
if(json["timeLimited"].is<JsonVariant>())
|
||||
{
|
||||
timeLimited = json["timeLimited"].as<unsigned int>();
|
||||
}
|
||||
@@ -2677,27 +2677,27 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
timeLimited = 2;
|
||||
}
|
||||
|
||||
if(json["name"].is<String>())
|
||||
if(json["name"].is<JsonVariant>())
|
||||
{
|
||||
name = json["name"].as<String>();
|
||||
}
|
||||
if(json["allowedFrom"].is<String>())
|
||||
if(json["allowedFrom"].is<JsonVariant>())
|
||||
{
|
||||
allowedFrom = json["allowedFrom"].as<String>();
|
||||
}
|
||||
if(json["allowedUntil"].is<String>())
|
||||
if(json["allowedUntil"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntil = json["allowedUntil"].as<String>();
|
||||
}
|
||||
if(json["allowedWeekdays"].is<String>())
|
||||
if(json["allowedWeekdays"].is<JsonVariant>())
|
||||
{
|
||||
allowedWeekdays = json["allowedWeekdays"].as<String>();
|
||||
}
|
||||
if(json["allowedFromTime"].is<String>())
|
||||
if(json["allowedFromTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedFromTime = json["allowedFromTime"].as<String>();
|
||||
}
|
||||
if(json["allowedUntilTime"].is<String>())
|
||||
if(json["allowedUntilTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntilTime = json["allowedUntilTime"].as<String>();
|
||||
}
|
||||
@@ -2837,8 +2837,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
if(allowedUntil.length() > 0)
|
||||
{
|
||||
if(allowedUntil.length() > 0 == 19)
|
||||
if(allowedUntil.length() == 19)
|
||||
{
|
||||
allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
|
||||
allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
|
||||
@@ -3172,7 +3171,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
String lockAction;
|
||||
NukiLock::LockAction timeControlLockAction;
|
||||
|
||||
if(json["enabled"].is<unsigned int>())
|
||||
if(json["enabled"].is<JsonVariant>())
|
||||
{
|
||||
enabled = json["enabled"].as<unsigned int>();
|
||||
}
|
||||
@@ -3181,15 +3180,15 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
enabled = 2;
|
||||
}
|
||||
|
||||
if(json["weekdays"].is<String>())
|
||||
if(json["weekdays"].is<JsonVariant>())
|
||||
{
|
||||
weekdays = json["weekdays"].as<String>();
|
||||
}
|
||||
if(json["time"].is<String>())
|
||||
if(json["time"].is<JsonVariant>())
|
||||
{
|
||||
time = json["time"].as<String>();
|
||||
}
|
||||
if(json["lockAction"].is<String>())
|
||||
if(json["lockAction"].is<JsonVariant>())
|
||||
{
|
||||
lockAction = json["lockAction"].as<String>();
|
||||
}
|
||||
@@ -3464,7 +3463,7 @@ void NukiWrapper::onAuthCommandReceived(const char *value)
|
||||
String allowedFromTime;
|
||||
String allowedUntilTime;
|
||||
|
||||
if(json["remoteAllowed"].is<unsigned int>())
|
||||
if(json["remoteAllowed"].is<JsonVariant>())
|
||||
{
|
||||
remoteAllowed = json["remoteAllowed"].as<unsigned int>();
|
||||
}
|
||||
@@ -3473,7 +3472,7 @@ void NukiWrapper::onAuthCommandReceived(const char *value)
|
||||
remoteAllowed = 2;
|
||||
}
|
||||
|
||||
if(json["enabled"].is<unsigned int>())
|
||||
if(json["enabled"].is<JsonVariant>())
|
||||
{
|
||||
enabled = json["enabled"].as<unsigned int>();
|
||||
}
|
||||
@@ -3482,7 +3481,7 @@ void NukiWrapper::onAuthCommandReceived(const char *value)
|
||||
enabled = 2;
|
||||
}
|
||||
|
||||
if(json["timeLimited"].is<unsigned int>())
|
||||
if(json["timeLimited"].is<JsonVariant>())
|
||||
{
|
||||
timeLimited = json["timeLimited"].as<unsigned int>();
|
||||
}
|
||||
@@ -3491,28 +3490,28 @@ void NukiWrapper::onAuthCommandReceived(const char *value)
|
||||
timeLimited = 2;
|
||||
}
|
||||
|
||||
if(json["name"].is<String>())
|
||||
if(json["name"].is<JsonVariant>())
|
||||
{
|
||||
name = json["name"].as<String>();
|
||||
}
|
||||
//if(json["sharedKey"].is<String>()) sharedKey = json["sharedKey"].as<String>();
|
||||
if(json["allowedFrom"].is<String>())
|
||||
//if(json["sharedKey"].is<JsonVariant>()) sharedKey = json["sharedKey"].as<String>();
|
||||
if(json["allowedFrom"].is<JsonVariant>())
|
||||
{
|
||||
allowedFrom = json["allowedFrom"].as<String>();
|
||||
}
|
||||
if(json["allowedUntil"].is<String>())
|
||||
if(json["allowedUntil"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntil = json["allowedUntil"].as<String>();
|
||||
}
|
||||
if(json["allowedWeekdays"].is<String>())
|
||||
if(json["allowedWeekdays"].is<JsonVariant>())
|
||||
{
|
||||
allowedWeekdays = json["allowedWeekdays"].as<String>();
|
||||
}
|
||||
if(json["allowedFromTime"].is<String>())
|
||||
if(json["allowedFromTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedFromTime = json["allowedFromTime"].as<String>();
|
||||
}
|
||||
if(json["allowedUntilTime"].is<String>())
|
||||
if(json["allowedUntilTime"].is<JsonVariant>())
|
||||
{
|
||||
allowedUntilTime = json["allowedUntilTime"].as<String>();
|
||||
}
|
||||
@@ -3606,7 +3605,7 @@ void NukiWrapper::onAuthCommandReceived(const char *value)
|
||||
|
||||
if(allowedUntil.length() > 0)
|
||||
{
|
||||
if(allowedUntil.length() > 0 == 19)
|
||||
if(allowedUntil.length() == 19)
|
||||
{
|
||||
allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
|
||||
allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
|
||||
|
||||
@@ -2955,7 +2955,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
|
||||
{
|
||||
_preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs));
|
||||
Log->print(F("Setting changed: "));
|
||||
Log->println("ACLCONFBADVANCEDOPENER");
|
||||
Log->println("ACLCONFADVANCEDOPENER");
|
||||
//configChanged = true;
|
||||
break;
|
||||
}
|
||||
@@ -3078,7 +3078,7 @@ bool WebCfgServer::processImport(PsychicRequest *request, String& message)
|
||||
|
||||
for(const auto& key : bytePrefs)
|
||||
{
|
||||
if(!doc[key].isNull() && doc[key].is<String>())
|
||||
if(!doc[key].isNull() && doc[key].is<JsonVariant>())
|
||||
{
|
||||
String value = doc[key].as<String>();
|
||||
unsigned char tmpchar[32];
|
||||
|
||||
@@ -13,7 +13,7 @@ default_envs = updater_esp32
|
||||
boards_dir = ../boards
|
||||
|
||||
[env]
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
|
||||
platform_packages =
|
||||
framework = arduino, espidf
|
||||
board_build.embed_txtfiles =
|
||||
|
||||
Reference in New Issue
Block a user