Skip to content

Commit

Permalink
Merge pull request #609 from iranl/api-2.3
Browse files Browse the repository at this point in the history
Add Nuki Lock Ultra support + Nuki Smart Lock API V2.3.0 compliance
  • Loading branch information
iranl authored Jan 15, 2025
2 parents c413596 + a7d539b commit cd30612
Show file tree
Hide file tree
Showing 19 changed files with 583 additions and 232 deletions.
8 changes: 4 additions & 4 deletions HYBRID.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ The purpose of this mode is to have Nuki Hub work in conjunction with the offici

### Requirements ###

- ESP32 running Nuki Hub 8.35 or higher
- For WiFi: Nuki lock 3.0 Pro or Nuki Lock 4.0 Pro
- For Thread: Nuki Lock 4.0 or Nuki Lock 4.0 Pro. Note that you do ***NOT*** need to buy the remote access addon for the Nuki Lock 4.0
- ESP32 running Nuki Hub 9.08 or higher
- For WiFi: Nuki lock 3.0 Pro, Nuki Lock 4.0 Pro or Nuki Lock Ultra
- For Thread: Nuki Lock 4.0, Nuki Lock 4.0 Pro or Nuki Lock Ultra. Note that you do ***NOT*** need to buy the remote access addon for the Nuki Lock 4.0
- For Thread: The Nuki Lock needs to have network access to the same MQTT server as the one that Nuki Hub is conected to. Depending if the MQTT server is reachable over IPv6 you might need an OpenThread Border router that supports NAT64 and has this enabled. Currently this means an Apple Device or Home Assistant with the Matter server and OpenThread Border Router
- The Nuki Opener does not have WiFI or Thread and thus doesn't benefit from the hybrid solutions added speed. You can however use and connect a Nuki Opener as usual which will function over regular BLE and can still connect Nuki Hub as a bridge to an Opener.

Expand Down Expand Up @@ -38,7 +38,7 @@ The Hybrid Official MQTT over Thread + Nuki Hub solution allows for the best com
- Optionally enable `Allow locking`. Note that if you enable this setting it is preferred to set ACL on your MQTT broker to only allow the Nuki lock and Nuki Hub MQTT user access to the topic `nuki/NUKI-ID/lockAction` to make sure that only Nuki Hub can execute commands on the lock (otherwise ACL settings through Nuki Hub can not be 100% enforced)
- Make sure that MQTT is setup correctly by checking if you get a green check mark in the Nuki app

- Install Nuki Hub 8.35 or higher on a supported ESP32 device
- Install Nuki Hub 9.08 or higher on a supported ESP32 device
- Make sure you are not paired as a bridge. Unpair your Nuki lock in Nuki Hub if Nuki Hub was paired as a bridge (this is mandatory even if you removed the bridge connection from the Nuki lock).
- Enable `Enable hybrid official MQTT and Nuki Hub setup`. The `Lock: Nuki Bridge is running alongside Nuki Hub (needs re-pairing if changed)` setting will be automatically be enabled.
- Optionally enable `Enable sending actions through official MQTT`, if not enabled lock actions will be sent over BLE as usual (slower)
Expand Down
65 changes: 58 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,13 @@ Feel free to join us on Discord: https://discord.gg/9nPq85bP4p
- Nuki Smart Lock 2.0
- Nuki Smart Lock 3.0
- Nuki Smart Lock 3.0 Pro (read FAQ below)
- Nuki Smart Lock 4.0
- Nuki Smart Lock 4.0 (read FAQ below)
- Nuki Smart Lock 4.0 Pro (read FAQ below)
- Nuki Smart Lock Ultra (read FAQ below)
- Nuki Opener
- Nuki Keypad 1.0
- Nuki Keypad 2.0

<b>Not (yet?) supported:</b>
- Nuki Smart Lock Ultra

<b>Supported Ethernet devices:</b><br>
As an alternative to Wi-Fi (which is available on any supported ESP32), the following ESP32 modules with built-in wired ethernet are supported:
- [Olimex ESP32-POE](https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware)
Expand Down Expand Up @@ -147,7 +145,7 @@ Next click on "MQTT Configuration" and enter the address and port (usually 1883)
The firmware supports SSL encryption for MQTT, however most people don't use this.<br>
See the "[MQTT Encryption](#mqtt-encryption-optional)" section of this README.

## Pairing with a Nuki Lock or Opener
## Pairing with a Nuki Lock (1.0-4.0) or Opener

Make sure "Bluetooth pairing" is enabled for the Nuki device by enabling this setting in the official Nuki App in "Settings" > "Features & Configuration" > "Button and LED".
After enabling the setting press the button on the Nuki device for a few seconds.<br>
Expand All @@ -161,9 +159,22 @@ MQTT nodes like lock state and battery level should now reflect the reported val
This is not recommended (unless when using [hybrid mode](/HYBRID.md)) and will lead to excessive battery drain and can lead to either device missing updates.
Enable "Register as app" before pairing to allow this. Otherwise the Bridge will be unregistered when pairing the Nuki Hub.</b>

## Pairing with a Nuki Lock Ultra

Make sure "Bluetooth pairing" is enabled for the Nuki device by enabling this setting in the official Nuki App in "Settings" > "Features & Configuration" > "Button and LED".

Before enabling pairing mode using the button on the Lock Ultra first setup NukiHub as follows:
- Enable both "Nuki Smartlock enabled" and "Nuki Smartlock Ultra enabled" settings on the "Basic Nuki Configuration" page and Save. Setting the "Nuki Smartlock Ultra enabled" will change multiple other NukiHub settings.
- Input your 6-digit Nuki Lock Ultra PIN on the "Credentials" page and Save
- Press the button on the Nuki device for a few seconds
- It is **strongly** recommended to setup and enable Hybrid mode over Thread/WiFi + official MQTT as NukiHub works best in Hybrid or Bridge mode and the Ultra does not support Bridge mode

Pairing should be automatic if no lock is paired.<br>
When pairing is successful, the web interface should show "Paired: Yes".<br>

## Hybrid mode

Hybrid mode allows you to use the official Nuki MQTT implemenation on a Nuki Lock 3.0 Pro, Nuki Lock 4.0 or Nuki Lock 4.0 Pro in conjunction with Nuki Hub.<br>
Hybrid mode allows you to use the official Nuki MQTT implemenation on a Nuki Lock 3.0 Pro, Nuki Lock 4.0, Nuki Lock 4.0 Pro or Nuki Lock Ultra in conjunction with NukiHub.<br>
See [hybrid mode](/HYBRID.md) for more information.

## Memory constraints
Expand Down Expand Up @@ -251,7 +262,8 @@ In a browser navigate to the IP address assigned to the ESP32.

#### Basic Nuki Configuration

- Nuki Smartlock enabled: Enable if you want Nuki Hub to connect to a Nuki Lock (1.0-4.0)
- Nuki Smartlock enabled: Enable if you want Nuki Hub to connect to a Nuki Lock (1.0-4.0 and Ultra)
- Nuki Smartlock Ultra enabled: Enable if you want Nuki Hub to connect to a Nuki Lock Ultra
- Nuki Opener enabled: Enable if you want Nuki Hub to connect to a Nuki Opener
- New Nuki Bluetooth connection mode (disable if there are connection issues): Enable to use the latest Nuki BLE connection mode (recommended). Disable if you have issues communicating with the lock/opener

Expand All @@ -267,6 +279,9 @@ In a browser navigate to the IP address assigned to the ESP32.
- 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.
- BLE transmit power in dB: Set to a integer between -12 and 9 to set the Bluetooth transmit power, default 9.
- Update Nuki Hub and Lock/Opener time using NTP: Enable to update the ESP32 time and Nuki Lock and/or Nuki Opener time every 12 hours using a NTP time server
- NTP server: Set to the NTP server you want to use, defaults to "pool.ntp.org". If DHCP is used and NTP servers are provided using DHCP these will take precedence over the specified NTP server.

### Access Level Configuration

#### Nuki General Access Control
Expand Down Expand Up @@ -299,6 +314,7 @@ In a browser navigate to the IP address assigned to the ESP32.
#### Nuki Lock PIN / Nuki Opener PIN

- PIN Code: Fill with the Nuki Security Code of the Nuki Lock and/or Nuki Opener. Required for functions that require the security code to be sent to the lock/opener such as setting lock permissions/adding keypad codes, viewing the activity log or changing the Nuki device configuration. Set to "#" to remove the security code from the Nuki Hub configuration.
- PIN Code Ultra: Fill with the 6-digit Nuki Security Code of the Nuki Lock Ultra. Required for pairing (and many other functions)

#### Unpair Nuki Lock / Unpair Nuki Opener

Expand Down Expand Up @@ -327,6 +343,39 @@ Both of the above options will not backup pairing data, so you will have to manu
To import settings copy and paste the contents of the JSON file that is created by any of the above export options and select "Import".
After importing the device will reboot.

### Advanced Configuration

The advanced configuration menu is not reachable from the main menu of the web configurator by default.<br>
You can reach the menu directly by browsing to http://NUKIHUBIP/?get=advanced or enable showing it in the main menu by browsing to http://NUKIHUBIP/?get=debugon once (http://NUKIHUBIP/?get=debugoff to disable).

Note that the following options can break NukiHub and cause bootloops that will require you to erase your ESP and reflash following the instructions for first-time flashing.

- Disable Network if not connected within 60s: Enable to allow NukiHub to function without a network connection (for example when only using NukiHub with GPIO)
- Enable Bootloop prevention: Enable to reset the following stack size and max entry settings to default if NukiHub detects a bootloop.
- Char buffer size (min 4096, max 65536): Set the character buffer size, needs to be enlarged to support large amounts of auth/keypad/timecontrol/authorization entries. Default 4096.
- Task size Network (min 12288, max 65536): Set the Network task stack size, needs to be enlarged to support large amounts of auth/keypad/timecontrol/authorization entries. Default 12288.
- Task size Nuki (min 8192, max 65536): Set the Nuki task stack size. Default 8192.
- Max auth log entries (min 1, max 100): The maximum amount of log entries that will be requested from the lock/opener, default 5.
- Max keypad entries (min 1, max 200): The maximum amount of keypad codes that will be requested from the lock/opener, default 10.
- Max timecontrol entries (min 1, max 100): The maximum amount of timecontrol entries that will be requested from the lock/opener, default 10.
- Max authorization entries (min 1, max 100): The maximum amount of authorization entries that will be requested from the lock/opener, default 10.
- Show Pairing secrets on Info page: Enable to show the pairing secrets on the info page. Will be disabled on reboot.
- Manually set lock pairing data: Enable to save the pairing data fields and manually set pairing info for the lock.
- Manually set opener pairing data: Enable to save the pairing data fields and manually set pairing info for the opener.
- Custom URL to update Nuki Hub updater: Set to a HTTPS address to update to a custom NukiHub updater binary on next boot of the NukiHub partition.
- Custom URL to update Nuki Hub: Set to a HTTPS address to update to a custom NukiHub binary on next boot of the NukiHub updater partition.
- Force Lock ID to current ID: Enable to force the current Lock ID, irrespective of the config received from the lock.
- Force Lock Keypad connected: Enable to force NukiHub to function as if a keypad was connected, irrespective of the config received from the lock.
- Force Lock Doorsensor connected: Enable to force NukiHub to function as if a doorsensor was connected, irrespective of the config received from the lock.
- Force Opener ID to current ID: Enable to force the current Opener ID, irrespective of the config received from the opener.
- Force Opener Keypad: Enable to force NukiHub to function as if a keypad was connected, irrespective of the config received from the opener.
- Enable Nuki connect debug logging: Enable to log debug information regarding Nuki BLE connection to MQTT and/or Serial.
- Enable Nuki communication debug logging: Enable to log debug information regarding Nuki BLE communication to MQTT and/or Serial.
- Enable Nuki readable data debug logging: Enable to log human readable debug information regarding Nuki BLE to MQTT and/or Serial.
- Enable Nuki hex data debug logging: Enable to log hex debug information regarding Nuki BLE to MQTT and/or Serial.
- Enable Nuki command debug logging: Enable to log debug information regarding Nuki BLE commands to MQTT and/or Serial.
- Pubish free heap over MQTT: Enable to publish free heap to MQTT.

## Exposed MQTT Topics

### Lock
Expand Down Expand Up @@ -484,6 +533,8 @@ Changing settings has to enabled first in the configuration portal. Check the se
| autoLockEnabled | Whether auto lock is enabled. | 1 = enabled, 0 = disabled |`{ "autoLockEnabled": "1" }` |
| immediateAutoLockEnabled | Whether auto lock should be performed immediately after the door has been closed. | 1 = enabled, 0 = disabled |`{ "immediateAutoLockEnabled": "1" }`|
| autoUpdateEnabled | Whether automatic firmware updates should be enabled. | 1 = enabled, 0 = disabled |`{ "autoUpdateEnabled": "1" }` |
| motorSpeed | The desired motor speed (Ultra only) | "Standard", "Insane", "Gentle" |`{ "motorSpeed": "Standard" }` |
| enableSlowSpeedDuringNightMode | Whether the slow speed should be applied during Night Mode (Ultra only) | 1 = enabled, 0 = disabled |`{ "enableSlowSpeedDuringNightMode": "1" }` |
| rebootNuki | Reboot the Nuki device immediately | 1 = reboot nuki |`{ "rebootNuki": "1" }` |

### Nuki Opener Configuration
Expand Down
2 changes: 1 addition & 1 deletion lib/nuki_ble
4 changes: 3 additions & 1 deletion sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,6 @@ CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=8
CONFIG_ESP_WIFI_RX_BA_WIN=6
CONFIG_ESP_WIFI_IRAM_OPT=n
CONFIG_ESP_WIFI_RX_IRAM_OPT=n
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_LWIP_DHCP_GET_NTP_SRV=y
CONFIG_LWIP_SNTP_UPDATE_DELAY=43200000
4 changes: 1 addition & 3 deletions src/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#define NUKI_HUB_VERSION "9.08"
#define NUKI_HUB_VERSION_INT (uint32_t)908
#define NUKI_HUB_BUILD "unknownbuildnr"
#define NUKI_HUB_DATE "2025-01-10"
#define NUKI_HUB_DATE "2025-01-15"

#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"
Expand Down Expand Up @@ -120,8 +120,6 @@

#ifndef NUKI_HUB_UPDATER
#define MQTT_QOS_LEVEL 1
#define MQTT_CLEAN_SESSIONS false
#define MQTT_KEEP_ALIVE 60
#define GPIO_DEBOUNCE_TIME 200
#define CHAR_BUFFER_SIZE 4096
#define NUKI_TASK_SIZE 8192
Expand Down
36 changes: 0 additions & 36 deletions src/Gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ Gpio::Gpio(Preferences* preferences)
{
_inst = this;
loadPinConfiguration();

if(_preferences->getBool(preference_gpio_locking_enabled, false))
{
migrateObsoleteSetting();
}

_inst->init();
}

Expand Down Expand Up @@ -541,33 +535,3 @@ void Gpio::setPinOutput(const uint8_t& pin, const uint8_t& state)
{
digitalWrite(pin, state);
}

void Gpio::migrateObsoleteSetting()
{
_pinConfiguration.clear();

PinEntry entry1;
entry1.pin = 27;
entry1.role = PinRole::InputUnlatch;

PinEntry entry2;
entry2.pin = 32;
entry2.role = PinRole::InputLock;

PinEntry entry3;
entry3.pin = 33;
entry3.role = PinRole::InputUnlock;

_pinConfiguration.push_back(entry1);
_pinConfiguration.push_back(entry2);
_pinConfiguration.push_back(entry3);

savePinConfiguration(_pinConfiguration);

_preferences->remove(preference_gpio_locking_enabled);
Log->println("Migrated gpio control setting");
delay(200);
restartEsp(RestartReason::GpioConfigurationUpdated);
}


2 changes: 0 additions & 2 deletions src/Gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ class Gpio
Gpio(Preferences* preferences);
static void init();

void migrateObsoleteSetting();

void addCallback(std::function<void(const GpioAction&, const int&)> callback);

void loadPinConfiguration();
Expand Down
Loading

0 comments on commit cd30612

Please sign in to comment.