The scope of Nuki Hub is to have an efficient way to integrate Nuki devices in a local Home Automation platform.
The Nuki Hub software runs on a ESP32 module and acts as a bridge between Nuki devices and a Home Automation platform.
It communicates with a Nuki Lock and/or Opener through Bluetooth (BLE) and uses MQTT to integrate with other systems.
It exposes the lock state (and much more) through MQTT and allows executing commands like locking and unlocking as well as changing the Nuki Lock/Opener configuration through MQTT.
Nuki Hub does not integrate with the Nuki mobile app, it can't register itself as a bridge in the official Nuki mobile app.
Feel free to join us on Discord: https://discord.gg/9nPq85bP4p
Supported ESP32 devices:
Not supported ESP32 devices:
Supported Nuki devices:
Untested but probably supported:
Supported Ethernet devices:
As an alternative to Wi-Fi (which is available on any supported ESP32), the following ESP32 modules with built-in wired ethernet are supported:
In principle all ESP32 (and variants) devices with built-in ethernet port are supported, but might require additional setup using the "Custom LAN setup" option. See the "Connecting via Ethernet" section for more information.
If WIFI6 is absolutely required: ESP32-C6
If PoE is required: Any of the above mentioned devices with PoE or any other ESP device in combination with a SPI Ethernet module (W5500) and PoE to Ethernet and USB type B/C splitter
If you want maximum performance and intend to run any or multiple of the following:
An ESP32-S3 with 2MB of PSRAM or more (look for an ESP32-S3 with the designation N>=4 and R>=2 such as an ESP32-S3 N16R8)
In general when buying a new device when size and a couple of dollars more or less are not an issue: An ESP32-S3 with 2MB of PSRAM or more.
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 | Nuki Hub | Nuki Bridge |
---|---|---|
Bridge API | x | |
Smart Lock remote control | x | x |
Smart Home integration via Matter | x | |
Apple HomeKit integration via Matter | x | |
MQTT API | x | x (only for SL 3, 4 and 4 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 and 4 Pro Models) |
Home Automation platform integration | x | x |
Cloud support | x (optional via smarthome solution) | x |
Cloud-less operation | x | x (since fw 3.8.2) |
Official Nuki 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 WiFI and Thread connected locks | x |
If you haven't ordered your Nuki product yet, you can support me by using my referrer code when placing your order:
REF2BJHFVHZKK
This will also give you a 10% discount on your order.
This project is free to use for everyone. However if you feel like donating, you can buy me a coffee at ko-fi.com:
Flash the firmware to an ESP32. The easiest way to install is to use the web installer using a compatible browser like Chrome/Opera/Edge:
https://technyon.github.io/nuki_hub/
NOTE: Webflash is not available for the ESP32-Solo1
Alternatively download the latest release for your ESP32 model from https://github.com/technyon/nuki_hub/releases
Unpack the zip archive and read the included how-to-flash.txt for installation instructions for either "Espressif Flash Download Tools" or "esptool".
Power up the ESP32 and a new Wi-Fi access point named "NukiHub" should appear.
The password of the access point is "NukiHubESP32".
Connect a client device to this access point and in a browser navigate to "http://192.168.4.1".
Use the web interface to connect the ESP to your preferred Wi-Fi network.
After configuring Wi-Fi, the ESP should automatically connect to your network.
To configure the connection to the MQTT broker, first connect your client device to the same Wi-Fi network the ESP32 is connected to.
In a browser navigate to the IP address assigned to the ESP32 via DHCP (often found in the web interface of your internet router).
Next click on "Edit" below "MQTT Configuration" and enter the address and port (usually 1883) of your MQTT broker and a username and a password if required by your MQTT broker.
The firmware supports SSL encryption for MQTT, however most people and especially home users don't use this.
In that case leave all fields starting with "MQTT SSL" blank. Otherwise see the "MQTT Encryption" section of this README.
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.
Pairing should be automatic when the ESP32 is powered on.
When pairing is successful, the web interface should show "Paired: Yes".
MQTT nodes like lock state and battery level should now reflect the reported values from the lock.
Note: It is possible to run Nuki Hub alongside a Nuki Bridge.
This is not recommended (unless when using hybrid mode) 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.
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.
See hybrid mode for more information.
ESP32 devices have a limited amount of free RAM available.
On version 9.01 of Nuki Hub with only a Nuki Lock connected the expected free amount of RAM/Heap available is around:
This free amount of RAM can be reduced (temporarily) by certain actions (such as changing Nuki device config) or continuously when enabling the following:
The currently available RAM/Heap can be found on the info page of the Web configurator of Nuki Hub.
When the ESP32 runs out of available RAM this device can crash or otherwise unexpected behaviour can occur.
Nuki Hub does allow for the use of embedded PSRAM on the regular binaries whenever it is available.
PSRAM is usually 2, 4 or 8MB in size and thus greatly enlarges the 320kb of internal RAM that is available.
It is basically impossible to run out of RAM when PSRAM is available.
You can check on the info page of the Web configurator if PSRAM is available.
Note that there are two builds of Nuki Hub for the ESP32-S3 available.
One for devices with no or Quad SPI PSRAM and one for devices with Octal SPI PSRAM.
If your ESP32-S3 device has PSRAM but it is not detected please flash the other S3 binary.
In a browser navigate to the IP address assigned to the ESP32.
The "Import/Export Configuration" menu option allows the importing and exporting of the NukiHub settings in JSON format.
Create a (partial) backup of the current NukiHub settings by selecting any of the following:
Both of the above options will not backup pairing data, so you will have to manually pair Nuki devices when importing this export on a factory reset or new device.
To change Nuki Lock/Opener settings set the configuration/action
topic to a JSON formatted value with any of the following settings. Multiple settings can be changed at once. See Nuki Smart Lock API Basic Config, Nuki Smart Lock API Advanced Config, Nuki Opener API Basic Config and Nuki Opener API Advanced Config for more information on the available settings.
Changing settings has to enabled first in the configuration portal. Check the settings you want to be able to change under "Nuki Lock/Opener Config Control" in "Access Level Configuration" and save the configuration.
Setting | Usage | Possible values | Example |
---|---|---|---|
name | The name of the Smart Lock. | Alphanumeric string, max length 32 chars | { "name": "Frontdoor" } |
latitude | The latitude of the Smart Locks geoposition. | Float | { "latitude": "48.858093" } |
longitude | The longitude of the Smart Locks geoposition | Float | { "longitude": "2.294694" } |
autoUnlatch | Whether or not the door shall be unlatched by manually operating a door handle from the outside. | 1 = enabled, 0 = disabled | { "autoUnlatch": "1" } |
pairingEnabled | Whether or not activating the pairing mode via button should be enabled. | 1 = enabled, 0 = disabled | { "pairingEnabled": "0" } |
buttonEnabled | Whether or not the button should be enabled. | 1 = enabled, 0 = disabled | { "buttonEnabled": "1" } |
ledEnabled | Whether or not the flashing LED should be enabled to signal an unlocked door. | 1 = enabled, 0 = disabled | { "ledEnabled": "1" } |
ledBrightness | The LED brightness level | 0 = off, …, 5 = max | { "ledBrightness": "2" } |
timeZoneOffset | The timezone offset (UTC) in minutes | Integer between 0 and 60 | { "timeZoneOffset": "0" } |
dstMode | The desired daylight saving time mode. | 0 = disabled, 1 = European | { "dstMode": "0" } |
fobAction1 | The desired action, if a Nuki Fob is pressed once. | "No Action", "Unlock", "Lock", "Lock n Go", "Intelligent" | { "fobAction1": "Lock n Go" } |
fobAction2 | The desired action, if a Nuki Fob is pressed twice. | "No Action", "Unlock", "Lock", "Lock n Go", "Intelligent" | { "fobAction2": "Intelligent" } |
fobAction3 | The desired action, if a Nuki Fob is pressed three times. | "No Action", "Unlock", "Lock", "Lock n Go", "Intelligent" | { "fobAction3": "Unlock" } |
singleLock | Whether only a single lock or double lock should be performed | 0 = double lock, 1 = single lock | { "singleLock": "0" } |
advertisingMode | The desired advertising mode. | "Automatic", "Normal", "Slow", "Slowest" | { "advertisingMode": "Normal" } |
timeZone | The current timezone or "None" if timezones are not supported | "None" or one of the timezones from Nuki Timezones | { "timeZone": "Europe/Berlin" } |
unlockedPositionOffsetDegrees | Offset that alters the unlocked position in degrees. | Integer between -90 and 180 | { "unlockedPositionOffsetDegrees": "-90" } |
lockedPositionOffsetDegrees | Offset that alters the locked position in degrees. | Integer between -180 and 90 | { "lockedPositionOffsetDegrees": "80" } |
singleLockedPositionOffsetDegrees | Offset that alters the single locked position in degrees. | Integer between -180 and 180 | { "singleLockedPositionOffsetDegrees": "120" } |
unlockedToLockedTransitionOffsetDegrees | Offset that alters the position where transition from unlocked to locked happens in degrees. | Integer between -180 and 180 | { "unlockedToLockedTransitionOffsetDegrees": "180" } |
lockNgoTimeout | Timeout for lock ‘n’ go in seconds | Integer between 5 and 60 | { "lockNgoTimeout": "60" } |
singleButtonPressAction | The desired action, if the button is pressed once. | "No Action", "Intelligent", "Unlock", "Lock", "Unlatch", "Lock n Go", "Show Status" | { "singleButtonPressAction": "Lock n Go" } |
doubleButtonPressAction | The desired action, if the button is pressed twice. | "No Action", "Intelligent", "Unlock", "Lock", "Unlatch", "Lock n Go", "Show Status" | { "doubleButtonPressAction": "Show Status" } |
detachedCylinder | Wheter the inner side of the used cylinder is detached from the outer side. | 0 = not detached, 1 = detached | { "detachedCylinder": "1" } |
batteryType | The type of the batteries present in the smart lock. | "Alkali", "Accumulators", "Lithium" | { "batteryType": "Accumulators" } |
automaticBatteryTypeDetection | Whether the automatic detection of the battery type is enabled. | 1 = enabled, 0 = disabled | { "automaticBatteryTypeDetection": "Lock n Go" } |
unlatchDuration | Duration in seconds for holding the latch in unlatched position. | Integer between 1 and 30 | { "unlatchDuration": "3" } |
autoLockTimeOut | Seconds until the smart lock relocks itself after it has been unlocked. | Integer between 30 and 1800 | { "autoLockTimeOut": "60" } |
autoUnLockDisabled | Whether auto unlock should be disabled in general. | 1 = auto unlock disabled, 0 = auto unlock enabled | { "autoUnLockDisabled": "1" } |
nightModeEnabled | Whether nightmode is enabled. | 1 = enabled, 0 = disabled | { "nightModeEnabled": "1" } |
nightModeStartTime | Start time for nightmode if enabled. | Time in "HH:MM" format | { "nightModeStartTime": "22:00" } |
nightModeEndTime | End time for nightmode if enabled. | Time in "HH:MM" format | { "nightModeEndTime": "07:00" } |
nightModeAutoLockEnabled | Whether auto lock should be enabled during nightmode. | 1 = enabled, 0 = disabled | { "nightModeAutoLockEnabled": "1" } |
nightModeAutoUnlockDisabled | Whether auto unlock should be disabled during nightmode. | 1 = auto unlock disabled, 0 = auto unlock enabled | { "nightModeAutoUnlockDisabled": "1" } |
nightModeImmediateLockOnStart | Whether the door should be immediately locked on nightmode start. | 1 = enabled, 0 = disabled | { "nightModeImmediateLockOnStart": "1" } |
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" } |
rebootNuki | Reboot the Nuki device immediately | 1 = reboot nuki | { "rebootNuki": "1" } |
Setting | Usage | Possible values | Example |
---|---|---|---|
name | The name of the Opener. | Alphanumeric string, max length 32 chars | { "name": "Frontdoor" } |
latitude | The latitude of the Openers geoposition. | Float | { "latitude": "48.858093" } |
longitude | The longitude of the Openers geoposition | Float | { "longitude": "2.294694" } |
pairingEnabled | Whether or not activating the pairing mode via button should be enabled. | 1 = enabled, 0 = disabled | { "pairingEnabled": "0" } |
buttonEnabled | Whether or not the button should be enabled. | 1 = enabled, 0 = disabled | { "buttonEnabled": "1" } |
ledFlashEnabled | Whether or not the flashing LED should be enabled to signal CM or RTO. | 1 = enabled, 0 = disabled | { "ledFlashEnabled": "1" } |
timeZoneOffset | The timezone offset (UTC) in minutes | Integer between 0 and 60 | { "timeZoneOffset": "0" } |
dstMode | The desired daylight saving time mode. | 0 = disabled, 1 = European | { "dstMode": "0" } |
fobAction1 | The desired action, if a Nuki Fob is pressed once. | "No Action", "Toggle RTO", "Activate RTO", "Deactivate RTO", "Open", "Ring" | { "fobAction1": "Toggle RTO" } |
fobAction2 | The desired action, if a Nuki Fob is pressed twice. | "No Action", "Toggle RTO", "Activate RTO", "Deactivate RTO", "Open", "Ring" | { "fobAction2": "Open" } |
fobAction3 | The desired action, if a Nuki Fob is pressed three times. | "No Action", "Toggle RTO", "Activate RTO", "Deactivate RTO", "Open", "Ring" | { "fobAction3": "Ring" } |
operatingMode | The desired operating mode | "Generic door opener", "Analogue intercom", "Digital intercom", "Siedle", "TCS", "Bticino", "Siedle HTS", "STR", "Ritto", "Fermax", "Comelit", "Urmet BiBus", "Urmet 2Voice", "Golmar", "SKS", "Spare" | { "operatingMode": "TCS" } |
advertisingMode | The desired advertising mode. | "Automatic", "Normal", "Slow", "Slowest" | { "advertisingMode": "Normal" } |
timeZone | The current timezone or "None" if timezones are not supported | "None" or one of the timezones from Nuki Timezones | { "timeZone": "Europe/Berlin" } |
intercomID | Database ID of the connected intercom. | Integer | { "intercomID": "1" } |
busModeSwitch | Method to switch between data and analogue mode | 0 = none, 1 =vshort circuit | { "busModeSwitch": "0" } |
shortCircuitDuration | Duration of the short circuit for BUS mode switching in ms. | Integer | { "shortCircuitDuration": "250" } |
electricStrikeDelay | Delay in ms of electric strike activation in case of an electric strike actuation by RTO | Integer between 0 and 30000 | { "electricStrikeDelay": "2080" } |
randomElectricStrikeDelay | Random delay (3-7s) in order to simulate a person inside actuating the electric strike. | 1 = enabled, 0 = disabled | { "randomElectricStrikeDelay": "1" } |
electricStrikeDuration | Duration in ms of electric strike actuation. . | Integer between 1000 and 30000 | { "electricStrikeDuration": "5000" } |
disableRtoAfterRing | Whether to disable RTO after ring. | 1 = disable RTO after ring, 0 = Don't disable RTO after ring | { "disableRtoAfterRing": "0" } |
rtoTimeout | After this period of time in minutes, RTO gets deactivated automatically | Integer between 5 and 60 | { "rtoTimeout": "60" } |
doorbellSuppression | Whether the doorbell is suppressed when Ring, CM and/or RTO are active | "Off", "CM", "RTO", "CM & RTO", "Ring", "CM & Ring", "RTO & Ring", "CM & RTO & Ring" | { "doorbellSuppression": "CM & Ring" } |
doorbellSuppressionDuration | Duration in ms of doorbell suppression. | Integer between 500 and 10000 | { "doorbellSuppressionDuration": "2000" } |
soundRing | The Ring sound | "No Sound", "Sound 1", "Sound 2", "Sound 3" | { "soundRing": "No Sound" } |
soundOpen | The Open sound. | "No Sound", "Sound 1", "Sound 2", "Sound 3" | { "soundOpen": "Sound 1" } |
soundRto | The RTO sound. | "No Sound", "Sound 1", "Sound 2", "Sound 3" | { "soundRto": "Sound 2" } |
soundCm | The CM sound. | "No Sound", "Sound 1", "Sound 2", "Sound 3" | { "soundCm": "Sound 3" } |
soundConfirmation | Sound confirmation | 0 = no sound, 1 = sound | { "soundConfirmation": "1" } |
soundLevel | The sound level for the opener | Integer between 0 and 255 | { "soundLevel": "200" } |
singleButtonPressAction | The desired action, if the button is pressed once. | "No Action", "Toggle RTO", "Activate RTO", "Deactivate RTO", "Toggle CM", "Activate CM", "Deactivate CM", "Open" | { "singleButtonPressAction": "Open" } |
doubleButtonPressAction | The desired action, if the button is pressed twice. | "No Action", "Toggle RTO", "Activate RTO", "Deactivate RTO", "Toggle CM", "Activate CM", "Deactivate CM", "Open" | { "doubleButtonPressAction": "No Action" } |
batteryType | The type of the batteries present in the smart lock. | "Alkali", "Accumulators", "Lithium" | { "batteryType": "Accumulators" } |
automaticBatteryTypeDetection | Whether the automatic detection of the battery type is enabled. | 1 = enabled, 0 = disabled | { "automaticBatteryTypeDetection": "1" } |
rebootNuki | Reboot the Nuki device immediately | 1 = reboot nuki | { "rebootNuki": "1" } |
Example usage for changing multiple settings at once:
{ "buttonEnabled": "1", "lockngoTimeout": "60", "automaticBatteryTypeDetection": "1" }
{ "fobAction1": "Unlock", "fobAction2": "Intelligent", "nightModeImmediateLockOnStart": "1" }
The result of the last configuration change action will be published to the configuration/commandResult
MQTT topic as JSON data.
The JSON data will include a node called "general" and a node for every setting that Nuki Hub detected in the action.
Possible values for the "general" node are "noValidPinSet", "invalidJson", "invalidConfig", "success" and "noChange".
Possible values for the node per setting are "unchanged", "noValueSet", "invalidValue", "valueTooLong", "accessDenied", "success", "failed", "timeOut", "working", "notPaired", "error" and "undefined"
Example:
{"advertisingMode":"success","general":"success"}
If Home Assistant discovery is enabled (see the Home Assistant Discovery section of this README) Nuki Hub will create entities for almost all of the above settings.
After the initial installation of the Nuki Hub firmware via serial connection, further updates can be deployed via OTA update from a browser.
In the configuration portal, select "Firmware update" from the main page.
The easiest way to upgrade Nuki Hub, if Nuki Hub is connected to the internet, is to select "Update to latest version".
This will download the latest Nuki Hub and Nuki Hub updater and automatically upgrade both applications.
Nuki Hub will reboot 3 times during this process, which will take about 5 minutes.
If you have enabled "Allow updating using MQTT" you can also use the Home Assistant updater or write "1" to the nukihub/maintanance/update
topic to start the update process.
Alternatively you can select a binary file from your file system to update Nuki Hub or the Nuki Hub updator manually
You can only update Nuki Hub from the Nuki Hub updater and update the updater only from Nuki Hub
You can reboot from Nuki Hub to the updater and vice versa by selecting the reboot option from the "Firware update" page
When you are on the right application you can upload the new binary by clicking on "Browse" and select the new "nuki_hub[board].bin" or "nuki_hub_updater[board].bin" file and select "Upload file".
After about a minute the new firmware should be installed afterwhich the ESP will reboot automatically to the updated binary.
Selecting the wrong binary will lead to an unsuccessfull update
Note for users upgrading from Nuki Hub 8.35 or lower:
Updating to version 9.00 requires a change to the partition table of the ESP32.
Please follow the instructions for the First time installation once when updating to Nuki Hub 9.00 from an earlier version.
Your settings will not be affected when updating using the above instructions (do not select erase device when updating using Webflash).
The communication via MQTT can be SSL encrypted.
To enable SSL encryption, supply the necessary information in the MQTT Configuration page.
The following configurations are supported:
CA, CERT and KEY are empty -> No encryption
CA is filled but CERT and KEY are empty -> Encrypted MQTT
CA, CERT and KEY are filled -> Encrypted MQTT with client vaildation
Example certificate creation for your MQTT server:
# make a ca key
openssl genpkey -algorithm RSA -out ca.key
# make a CA cert
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/C=US/ST=YourState/L=YourCity/O=YourOrganization/OU=YourUnit/CN=YourCAName"
# make a server key
openssl genpkey -algorithm RSA -out server.key
# Make a sign request, MAKE SURE THE CN MATCHES YOUR MQTT SERVERNAME
openssl req -new -key server.key -out server.csr -subj "/C=US/ST=YourState/L=YourCity/O=YourOrganization/OU=YourUnit/CN=homeserver.local"
# sign it
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
This software supports MQTT Discovery for integrating Nuki Hub with Home Assistant.
To enable autodiscovery, enable the checkbox on the "MQTT Configuration" page.
Once enabled, the Nuki Lock and/or Opener and related entities should automatically appear in your Home Assistant MQTT devices.
The following mapping between Home Assistant services and Nuki commands is setup when enabling autodiscovery:
Smartlock | Opener (default) | Opener (alternative) | |
---|---|---|---|
lock.lock | Lock | Disable Ring To Open | Disable Continuous Mode |
lock.unlock | Unlock | Enable Ring To Open | Enable Continuous Mode |
lock.open | Unlatch | Electric Strike Actuation | Electric Strike Actuation |
NOTE: MQTT Discovery uses retained MQTT messages to store devices configurations. In order to avoid orphan configurations on your broker please disable autodiscovery first if you no longer want to use this software. Retained messages are automatically cleared when unpairing and when changing/disabling autodiscovery topic in MQTT Configuration page.
NOTE2: Home Assistant can be setup manually using the MQTT Lock integration, but this is not recommended
If a keypad is connected to the lock, keypad codes can be added, updated and removed. This has to enabled first in the configuration portal. Check "Add, modify and delete keypad codes" under "Access Level Configuration" and save the configuration.
Information about current keypad codes is published as JSON data to the "[lock/opener]/keypad/json" MQTT topic.
This needs to be enabled separately by checking "Publish keypad codes information" under "Access Level Configuration" and saving the configuration.
For security reasons, the code itself is not published, unless this is explicitly enabled in the Nuki Hub settings.
By default a maximum of 10 entries are published.
To change Nuki Lock/Opener keypad settings set the [lock/opener]/keypad/actionJson
topic to a JSON formatted value containing the following nodes.
Node | Delete | Add | Update | Check | Usage | Possible values |
---|---|---|---|---|---|---|
action | Required | Required | Required | Required | The action to execute | "delete", "add", "update", "check" |
codeId | Required | Not used | Required | Required | The code ID of the existing code to delete or update | Integer |
code | Not used | Required | Optional | Required | The code to create or update | 6-digit Integer without zero's, can't start with "12" |
enabled | Not used | Not used | Optional | Not used | Enable or disable the code, always enabled on add | 1 = enabled, 0 = disabled |
name | Not used | Required | Optional | Not used | The name of the code to create or update | String, max 20 chars |
timeLimited | Not used | Optional | Optional | Not used | If this authorization is restricted to access only at certain times, requires enabled = 1 | 1 = enabled, 0 = disabled |
allowedFrom | Not used | Optional | Optional | Not used | The start timestamp from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" |
allowedUntil | Not used | Optional | Optional | Not used | The end timestamp until access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" |
allowedWeekdays | Not used | Optional | Optional | Not used | Weekdays on which access should be allowed (requires enabled = 1 and timeLimited = 1) | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun" |
allowedFromTime | Not used | Optional | Optional | Not used | The start time per day from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" |
allowedUntilTime | Not used | Optional | Optional | Not used | The end time per day until access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" |
Examples:
{ "action": "delete", "codeId": "1234" }
{ "action": "add", "code": "589472", "name": "Test", "timeLimited": "1", "allowedFrom": "2024-04-12 10:00:00", "allowedUntil": "2034-04-12 10:00:00", "allowedWeekdays": [ "wed", "thu", "fri" ], "allowedFromTime": "08:00", "allowedUntilTime": "16:00" }
{ "action": "update", "codeId": "1234", "enabled": "1", "name": "Test", "timeLimited": "1", "allowedFrom": "2024-04-12 10:00:00", "allowedUntil": "2034-04-12 10:00:00", "allowedWeekdays": [ "mon", "tue", "sat", "sun" ], "allowedFromTime": "08:00", "allowedUntilTime": "16:00" }
The result of the last keypad change action will be published to the [lock/opener]/configuration/commandResultJson
MQTT topic.
Possible values are "noValidPinSet", "keypadControlDisabled", "keypadNotAvailable", "keypadDisabled", "invalidConfig", "invalidJson", "noActionSet", "invalidAction", "noExistingCodeIdSet", "noNameSet", "noValidCodeSet", "noCodeSet", "invalidAllowedFrom", "invalidAllowedUntil", "invalidAllowedFromTime", "invalidAllowedUntilTime", "success", "failed", "timeOut", "working", "notPaired", "error" and "undefined".
If a keypad is connected to the lock, keypad codes can be added, updated and removed. This has to enabled first in the configuration portal. Check "Add, modify and delete keypad codes" under "Access Level Configuration" and save the configuration.
Information about codes is published under "keypad/code_x", x starting from 0 up the number of configured codes. This needs to be enabled separately by checking "Publish keypad codes information" under "Access Level Configuration" and saving the configuration. By default a maximum of 10 entries are published.
For security reasons, the code itself is not published, unless this is explicitly enabled in the Nuki Hub settings. To modify keypad codes, a command structure is setup under keypad/command:
To modify keypad codes, the first four parameter nodes have to be set depending on the command:
** Note: Rules for codes are:
After setting the necessary parameters, write the action to be executed to the command node. For example, to add a code:
Timecontrol entries can be added, updated and removed. This has to enabled first in the configuration portal. Check "Add, modify and delete timecontrol entries" under "Access Level Configuration" and save the configuration.
Information about current timecontrol entries is published as JSON data to the "[lock/opener]/timecontrol/json" MQTT topic.
This needs to be enabled separately by checking "Publish timecontrol entries information" under "Access Level Configuration" and saving the configuration.
By default a maximum of 10 entries are published.
To change Nuki Lock/Opener timecontrol settings set the [lock/opener]/timecontrol/actionJson
topic to a JSON formatted value containing the following nodes.
Node | Delete | Add | Update | Usage | Possible values |
---|---|---|---|---|---|
action | Required | Required | Required | The action to execute | "delete", "add", "update" |
entryId | Required | Not used | Required | The entry ID of the existing entry to delete or update | Integer |
enabled | Not used | Not used | Optional | Enable or disable the entry, always enabled on add | 1 = enabled, 0 = disabled |
weekdays | Not used | Optional | Optional | Weekdays on which the chosen lock action should be exectued (requires enabled = 1) | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun" |
time | Not used | Required | Optional | The time on which the chosen lock action should be executed (requires enabled = 1) | "HH:MM" |
lockAction | Not used | Required | Optional | The lock action that should be executed on the chosen weekdays at the chosen time (requires enabled = 1) | For the Nuki lock: "Unlock", "Lock", "Unlatch", "LockNgo", "LockNgoUnlatch", "FullLock". For the Nuki Opener: "ActivateRTO", "DeactivateRTO", "ElectricStrikeActuation", "ActivateCM", "DeactivateCM |
Examples:
{ "action": "delete", "entryId": "1234" }
{ "action": "add", "weekdays": [ "wed", "thu", "fri" ], "time": "08:00", "lockAction": "Unlock" }
{ "action": "update", "entryId": "1234", "enabled": "1", "weekdays": [ "mon", "tue", "sat", "sun" ], "time": "08:00", "lockAction": "Lock" }
Authorization entries can be updated and removed. This has to enabled first in the configuration portal. Check "Modify and delete authorization entries" under "Access Level Configuration" and save the configuration. It is currently not (yet) possible to add authorization entries this way.
Information about current authorization entries is published as JSON data to the "[lock/opener]/authorization/json" MQTT topic.
This needs to be enabled separately by checking "Publish authorization entries information" under "Access Level Configuration" and saving the configuration.
By default a maximum of 10 entries are published.
To change Nuki Lock/Opener authorization settings set the [lock/opener]/authorization/action
topic to a JSON formatted value containing the following nodes.
Node | Delete | Add | Update | Usage | Possible values |
---|---|---|---|---|---|
action | Required | Required | Required | The action to execute | "delete", "add", "update" |
authId | Required | Not used | Required | The auth ID of the existing entry to delete or update | Integer |
enabled | Not used | Not used | Optional | Enable or disable the authorization, always enabled on add | 1 = enabled, 0 = disabled |
name | Not used | Required | Optional | The name of the authorization to create or update | String, max 20 chars |
remoteAllowed | Not used | Optional | Optional | If this authorization is allowed remote access, requires enabled = 1 | 1 = enabled, 0 = disabled |
timeLimited | Not used | Optional | Optional | If this authorization is restricted to access only at certain times, requires enabled = 1 | 1 = enabled, 0 = disabled |
allowedFrom | Not used | Optional | Optional | The start timestamp from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" |
allowedUntil | Not used | Optional | Optional | The end timestamp until access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" |
allowedWeekdays | Not used | Optional | Optional | Weekdays on which access should be allowed (requires enabled = 1 and timeLimited = 1) | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun" |
allowedFromTime | Not used | Optional | Optional | The start time per day from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" |
allowedUntilTime | Not used | Optional | Optional | The end time per day until access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" |
Examples:
{ "action": "delete", "authId": "1234" }
{ "action": "update", "authId": "1234", "enabled": "1", "name": "Test", "timeLimited": "1", "allowedFrom": "2024-04-12 10:00:00", "allowedUntil": "2034-04-12 10:00:00", "allowedWeekdays": [ "mon", "tue", "sat", "sun" ], "allowedFromTime": "08:00", "allowedUntilTime": "16:00" }
The lock can be controlled via GPIO. To trigger actions, a connection to ground has to be present for at lease 300ms (or to +3.3V for "General input (pull-down)").
To enable GPIO control, go the the "GPIO Configuration" page where each GPIO can e configured for a specific role:
If you prefer to connect to via Ethernet instead of Wi-Fi, you either use one of the supported ESP32 modules with built-in ethernet (see "Supported devices" section)
or wire a seperate SPI Ethernet module.
Currently the Wiznet W5x00 Module (W5100, W5200, W5500), DN9051 and KSZ8851SNL chips are supported.
To use a supported module, flash the firmware, connect via Wi-Fi and select the correct network hardware in the "Network Configuration" section.
To wire an external W5x00 module to the ESP, use this wiring scheme:
Now connect via Wi-Fi and change the network hardware to "Generic W5500".
If Ethernet hardware isn't detected or initialised properly after changing the network device, Wi-Fi will be used as a fallback.
Note: LAN8720 modules are only supported on the ESP32 and ESP32-Solo1, not on the ESP32-S3, ESP32-C3 or ESP-C6
Unfortunately the ESP32 has problems with some access points and reconnecting fails.
As a workaround you can navigate to "Network Configuration" and enable "Restart on disconnect".
This will reboot the ESP as soon as it gets disconnected from Wi-Fi.
Also, this reduces the config portal timeout to three minutes to prevent the ESP being stuck in config mode in case an access point is offline temporarily.
If this still doesn't fix the disconnects and the ESP becomes unreachable, the "Restart timer" option can be used as a last resort.
It will restart the ESP after a configured amount of time.
First, make sure the firmware version of the Nuki device is up-to-date, older versions have issues pairing.
Next, try erasing the ESP32 flash and then (re-)flash the firmware.
To erase the flash, use the espressif download tool and click the "Erase" button.
Afterwards flash the firmware as described in the "how-to-flash.txt" file or using Webflash.
Also, check that pairing is allowed. In the Nuki smartphone app, go to "Settings" --> "Features & Configuration" --> "Button & LED" and make sure "Bluetooh Pairing" is enabled.
Next press the button for several seconds untill the LED light remains lit.
A note about the M5Stack PoESP32 Unit. Here the initial Bluetooth reception is very poor (range less than one meter). The reason is that the module does not have an antenna on the PCB, but only an IPEX connector. By retrofitting an external SMA antenna (IPEX, or other names U.FL, IPAX, IPX, AMC, MHF, UMCC), Bluetooth/Wi-Fi works over several meters.
Make sure you are using at least version 2023.8.0 of Home Assistant.
The Home Assistant developers have made changes to MQTT auto discovery which break support for older version and Nuki Hub has adopted these changes.
This unfortunately means that older versions of Home Assistant are not supported by the Nuki Hub discovery implementation anymore.
According to Nuki this is by design and part of the specification of the Pro lock.
You can use either the built-in Wi-Fi or a Bridge (which Nuki Hub registers as).
Or use Nuki Hub in Hybrid mode using Wi-Fi or Thread, see hybrid mode
Using both at the same time is not supported.
Some functionality is restricted by the Lock (or Opener) firmware and is only accessible when the PIN is provided.
When setting up the lock (or opener), you have to set a PIN in the Nuki smartphone app.
Navigate to the Nuki Hub Credentials page, enter this PIN and click save.
Check the main page of the configurator to see if the entered PIN is valid
See the previous point, this functionality needs the correct PIN to be configured.
Make sure the "Unlatch" option is checked under "Access Level Configuration".
Unlatching can be triggered using the lock.open service.
Alternatively an "Unlatch" button is exposed through Home Assistant discovery.
This button is disabled by default, but can be enabled in the Home Assistant UI.
When using multiple Nuki devices, different paths for each device have to be configured.
Navigate to "MQTT Configuration" and change the "MQTT NukiHub Path" under "Basic MQTT Configuration" for at least one of the devices.
This often is a result of enabling "Register as app" when not using Hybrid mode (Official MQTT / Nuki Hub co-existance).
Doing so will cause Nuki Hub to constantly query the lock and as such cause excessive battery drain.
To prevent this behaviour, unpair Nuki Hub, disable "Register as app", and re-pair.
Never enable "Register as app" unless you intend to use a Nuki Bridge in addition to Nuki Hub or you are using Hybrid mode!
Docker (Preferred)
See the README in the Docker directory for instructions on building using Docker.
Platform IO, instructions for Debian-based Linux distro (e.g. Ubuntu)
apt-get update
apt-get install -y git python3 pip make
python3 -m venv .venv
source .venv/bin/activate
git clone https://github.com/technyon/nuki_hub --recursive
cd nuki_hub
# install tools platformio and esptool
make deps
# build all binary boards
make updater
make release
This is third party software for Nuki devices.
This project or any of it's authors are not associated with Nuki Home Solutions GmbH.
Please refer for official products and support to the Nuki official website:
https://nuki.io/
For further license details, check the included LICENSE file.