Here goes nothing :
Nuki door lock integration
Scrips assume you have multiple devices (front door, side door) with multiple bridges (since bridges work through bluetooth, 1 bridge won't cover both locks) although its fairly easy to adapt the script such that you can use 1 bridge.
Scripts are tested on rasbian ONLY. They probably work on other linux distros as well. In order to function correctly, you need to install jq (sudo apt-get install jq) to parse json messages from the lock.
The concept is as follows: the bridge will transmit any lock status update for a lock to an ip/port through a json message as per the nuki published API (callback hook).
The below uses 2 scripts: 1 to listen to messages on that port (doorlock_change.sh) and 1 to handle accordingly (update domoticz: handle_doorlock_event.sh)). The first process gets started through cron
Both scripts sit in /usr/local/bin.
Following steps need to be performed:
- Install bridges and locks. Check through the mobile app. Make sure you give the bridges a static IP or figure out how to replace the static IP below with a device name.
2 Install jq if need be
3 Create a switch device for each lock. I don't use lock devices since these do not support timers. I have timers on the devices in domoticz to lock at night.
4 Put the bridges in developer mode (can be done from the nuki app). This allows you to tell the bridge where to send status updates. Write down the data from the bridge/lock (API token)
for each bridge issue the following command via curl:
curl -s "http://BRIDGE IP:8080/callback/add?url=http%3A%2F%2F[IP_OF_YOUR_DOMO_SYSTEM]%3A[PORT_TO_LISTEN_ON_SUGGEST_15003]%2Fnuki&token=[API_TOKEN]"
from now on, any change of lock state is sent as a json message to the domoticz system on port 15003
- Now we need to listen on that port. Put the following script in /usr/local/bin/doorlock_change.sh:
Code: Select all
#!/bin/bash
# doorlock_change.sh
# listens on a port for nuki lock change messages
while :
do
res=`nc -d -l 15003`
ret=$?
if [ -z "$res" ]; then
logger Doorlock change received NULL response $ret and $res
else
logger Doorlock change Received message $res
echo ${res} | /usr/local/bin/handle_doorlock_event.sh &
fi
done
- Now install the following in /usr/local/bin/handle_doorlock_event.sh but replace the API tokens with your API tokens and the corresponding IDX (123 and 456) with your device idx of your locks in domoticz
Code: Select all
#!/bin/bash
#logger handle_doorlock_change called with $line
while read in
do
line=`echo ${in} | sed -n 's/^.*{/{/p'`
nukiId=0
logger "handle_doorlock_event: received ${line}"
stateName=`echo $line | jq -r '.stateName'`
nukiId=`echo $line | jq -r '.nukiId'`
logger "handle_doorlock_event: got ${stateName} for ${nukiId}"
case "${nukiId}" in
"[API_TOKEN_1]")
idx=[123]
;;
"[API_TOKEN_2]")
idx=[456]
;;
esac
case "${stateName}" in
"unlocked")
logger "handle_doorlock_event: setting mode to ON for ${nukiId}"
mode="1"
curl -s "http://127.0.0.1:8080/json.htm?type=command¶m=udevice&idx=${idx}&nvalue=${mode}&svalue="
;;
"undefined")
logger "handle_doorlock_event: got state undefined for ${nukiId}"
/usr/local/bin/mailIP "handle_doorlock_event: got state undefined for ${nukiId}"
;;
"locked")
logger "handle_doorlock_event: setting mode to OFF for ${nukiId}"
mode="0"
curl -s "http://127.0.0.1:8080/json.htm?type=command¶m=udevice&idx=${idx}&nvalue=${mode}&svalue="
;;
"unlocking")
logger "handle_doorlock_event: got unlocking for ${nukiId} so ignore"
;;
"locking")
logger "handle_doorlock_event: got locking for ${nukiId} so ignore"
;;
"motor blocked")
logger "handle_doorlock_event: ERROR: Motor blocked for ${nukiId}"
;;
*)
logger "handle_doorlock_event: ERROR: INVALID EVENT ${stateName} for ${nukiId}"
;;
esac
done
- now install a 3rd script in your domoticz/script folder. This script is called when you change the device in domoticz in order to switch the lock open or closed:
Code: Select all
#!/bin/bash
#
# lockscript.sh
# script that switches the door lock
# called from Domoticz
#
#
opt=$1
lock=$2
res=0
if [ $lock = [NUKI ID of the lock] ]
then
idx=[domoticz idx of the lock]
token=[API TOKEN]
ip=[BRIDGE ip OF THE NUKI BRIDGE]
else
idx=[OTHER IDX OF OTHER LOCK]
token=[other api token in case of another bridge]
ip=[IP of the other bridge]
fi
logger "lockscript: Domoticz wants to $opt $lock"
case ${opt} in
Unlock)
# test if the lock is closed. If so, open.
state=`curl -s "http://${ip}:8080/lockState?nukiId=${lock}&token=${token}"|jq -r '.stateName'`
logger "lockscript: lock status is $state"
if [ ${state} = "" ]
then
sleep 2
state=`curl -s "http://${ip}:8080/lockState?nukiId=${lock}&token=${token}"|jq -r '.stateName'`
logger "lockscript: lock status is $state"
fi
if [ ${state} = "uncalibrated" ]
then
sleep 10
state=`curl -s "http://${ip}:8080/lockState?nukiId=${lock}&token=${token}"|jq -r '.stateName'`
logger "lockscript: lock status is $state"
fi
if [ ${state} = "locked" ]
then
logger "let's unlock ${lock}"
res=`curl -s "http://${ip}:8080/lockAction?nukiId=${lock}&action=1&token=${token}"|jq -r '.success'`
if [ ${res} != "true" ]
then
logger "Unlock lock ${lock} FAILED with ${res}, lock in FALSE state"
res=-1
else
logger "Successfully unlocked lock ${lock}"
res=0
fi
else
logger "lockscript: Lock ${lock} unlocked already"
fi
logger "lockscript: exiting ${res}"
exit $res
;;
Lock)
# test if the lock is open. If so, close.
state=`curl -s "http://${ip}:8080/lockState?nukiId=${lock}&token=${token}"|jq -r '.stateName'`
logger "lockscript: lock status is $state"
if [ ${state} = "" ]
then
sleep 2
state=`curl -s "http://${ip}:8080/lockState?nukiId=${lock}&token=${token}"|jq -r '.stateName'`
logger "lockscript: lock status is $state"
fi
if [ ${state} = "uncalibrated" ]
then
sleep 10
state=`curl -s "http://${ip}:8080/lockState?nukiId=${lock}&token=${token}"|jq -r '.stateName'`
logger "lockscript: lock status is $state"
fi
if [ ${state} = "unlocked" ]
then
logger "let's lock ${lock}"
res=`curl -s "http://${ip}:8080/lockAction?nukiId=${lock}&action=2&token=${token}"|jq -r '.success'`
if [ ${res} != "true" ]
then
logger "Lock lock ${lock} FAILED with ${res}, lock in FALSE state"
res=-1
else
logger "Successfully locked lock ${lock}"
res=0
fi
else
logger "lockscript: Lock ${lock} locked already"
fi
logger "lockscript: exiting ${res}"
exit $res
;;
esac
exit 0
- [now add the lock and unlock commands under the lock devices in domoticz:
Off action: script://lockscript.sh Lock [lock id]
Make sure you fill in the correct id's of your locks and then test. These scripts should work with/without the callback hook installed.
That should be it. Please note that these scripts really need tidying up and are a bit of a quick/dirty hack but they work for me.
If anyone has the time to tidy up and put these in a wiki then even better.
Let me know if you have issues or whether there are any mistakes in the above from my copy/paste.
the bridge http api can be found here: https://nuki.io/en/api/