Linux Software Bridge

Product name

Bridge

Summary

I would love to see a linux based (apt-get/snap installable) command line only software bridge so that I can use a server/rpi that I already have running as a bridge instead of buying and hosting new hardware or using a old android phone.

Features

Software bridge on Linux manageable through command line.

Reason

Easier to use that a android phone or custom hardware when you already have something running.

Examples

As a bridge

5 Likes

Do you mean something like this: https://github.com/as19git67/nukible?

Unfortunately I cannot get it to work with my bluetooth dongle, but maybe you can give it a shot?

Similar, but there is a android bridge app, so why not a linux one as well, this appears to replicate just the fob. I don’t have my nuki yet, it will be installed in my new home which I get the keys to at the end of the month.

+1, ideally open source. That would allow fixing connection problems as they are currently happening with the hardware bridge. The connection to the official cloud servers could be encapsulated in a closed source library.

1 Like

+1, I have a lot of trouble keeping Android phones running as bridge. A Linux version of the Bridge would be amazing. I’ve tried to go the Anbox route, but Android emulators don’t support Bluetooth :frowning:

+1 … docker container … would be nice on a nas or a raspberry solution

2 Likes

Im running a bridge on my 2 Raspberry Pi’s (2 locks) very succesfully for the last 6 months. I forked the nukiPyBridge GitHub repository, fixed some compilation errors, added a REST interface and upgraded to Python 3.7: https://github.com/giejay/nukiPyBridge

Now I can just call http://local-ip:3000/RearDoor/Unlock from my Home Automation System whenever I’m close (500 metres) to my home, unlock happens in aprox 15 seconds.

I also added some setup scripts to the repo, running install-bluetooth-deps.sh should be sufficient for running the complete stack including a supervised service.

I also tried to run it in docker, but I had a lot of issues getting Bluetooth/bluez to work properly so I gave up on that path for now.

3 Likes

Great project even though I am still unsure if a bridge-compatible API would help.

Which problems did you run into with docker? Given the nature of the installation - no package and replacement of stock files - I think it would be a good fit for a container.

Patrick

The installation of the packages and building bluez went fine. The problem was in binding the Bluetooth device of the host correctly to the docker container. I’m not exactly sure what the problem was, but I will update the docker image to python 3, rerun it and post the results.

1 Like

So, I’ve updated the docker image and made it work without throwing any errors regarding bluetooth. However, I can’t seem to get it connected to my lock, the code tries to pair to it initially for three times and then stops.

Can anyone try the image to see if they have more success?

Image can be found at: giejay/nuki-bridge, I build it for the raspberry pi so ARM. If another architecture is needed, let me know.

A docker-compose example would be:

 nuki:
    image: giejay/nuki-bridge
    privileged: true
    network_mode: host

The REST service runs at port 5000, an example of an initial pair call would be:

http://192.168.2.100:5000/connect/54:D2:00:00:00/RearDoor

Find the mac address in the app and I think it’s also on the lock. The name (RearDoor) can be anything.

Your repository is great, I followed the procedures a couple of times but I get stuck when pairing. I get next error. Any idea on what’s wrong? BTW, I’m on Python3. I did not try it with Python2.

Traceback (most recent call last):
File “/home/pi/Nuki/connect-example.py”, line 14, in
nuki.Nuki(sys.argv[0]).authenticateUser(myPublicKeyHex, myPrivateKeyHex, myID, myIDType, ‘54:D2:72:4D:3E:15’)
File “/home/pi/Nuki/nuki.py”, line 88, in authenticateUser
pairingHandle = self.device.get_handle(‘a92ee101-5501-11e4-916c-0800200c9a66’)
AttributeError: ‘NoneType’ object has no attribute ‘get_handle’

You are probably also seeing this line three times:

Unable to connect, retrying…

What other logging do you see? Are you sure your Nuki is in pairing mode and the pi is close enough?

Nuki lock is 10 cm from my RPI. I pushed the pairing button for 5’ and the ring light is on still, not blinking. Here you are the full log:

pi@rpi2:~/Nuki $ /usr/bin/python3.7 /home/pi/Nuki/connect-example.py
Starting BLE adapter…
Init Nuki BLE connection…
Unable to connect, retrying…, retry count: 1
Starting BLE adapter…
Init Nuki BLE connection…
Unable to connect, retrying…, retry count: 2
Starting BLE adapter…
Init Nuki BLE connection…
Unable to connect, retrying…, retry count: 3
Nuki BLE connection established
Traceback (most recent call last):
File “/home/pi/Nuki/connect-example.py”, line 14, in
nuki.Nuki(sys.argv[0]).authenticateUser(myPublicKeyHex, myPrivateKeyHex, myID, myIDType, ‘54:D2:72:4D:3E:15’)
File “/home/pi/Nuki/nuki.py”, line 88, in authenticateUser
pairingHandle = self.device.get_handle(‘a92ee101-5501-11e4-916c-0800200c9a66’)
AttributeError: ‘NoneType’ object has no attribute ‘get_handle’

I think I see the issue, you are not passing in the Mac address in nuki.Nuki(), but you are placing it where the name should be. Can you try:

nuki.Nuki(“54:D2:72:4D:3E:15”).authenticateUser(myPublicKeyHex, myPrivateKeyHex, myID, myIDType, “Door”)

That works, my fault…but now I have problems with gatttool.py, the ones I solved were related to indentation, tabs instead of spaces and VSC did not like it. But next issues are related with code. I copied gatttool.py, to /usr/local/lib/python3.7/dist-packages/pygatt/backends/gatttool/gatttool.py but your sh script copies it to 2…7 folder…even though it seems you use python 3.

Starting BLE adapter…
Init Nuki BLE connection…
Nuki BLE connection established
Nuki Pairing UUID handle created: 008b
Requesting Nuki Public Key using command: Nuki_REQ
Payload: Nuki_PUBLIC_KEY
Exception in thread Thread-1:
Traceback (most recent call last):
File “/usr/lib/python3.7/threading.py”, line 917, in _bootstrap_inner
self.run()
File “/usr/local/lib/python3.7/dist-packages/pygatt/backends/gatttool/gatttool.py”, line 109, in run
event"callback"
File “/usr/local/lib/python3.7/dist-packages/pygatt/backends/gatttool/gatttool.py”, line 403, in _handle_notification_string
values = bytearray(hex_values.replace(" ", “”).decode(“hex”))
TypeError: a bytes-like object is required, not ‘str’

Nuki Public key requested
Error while requesting public key: does not seem to be a valid Nuki command

Ah yes, did not port the gattool.py to python 3 yet. Just pushed the required changes, can you try again?

We’re still stuck in this line:
File “/usr/local/lib/python3.7/dist-packages/pygatt/backends/gatttool/gatttool.py”, line 403, in _handle_notification_string
values = bytearray.fromhex(hex_values.replace(" ", “”))
TypeError: a bytes-like object is required, not ‘str’
Nuki Public key requested
Error while requesting public key: does not seem to be a valid Nuki command

Looking at the original gattool, I dont think its still necessary to modify it. Can you try it with the original one?

It did work but I got some further issues that I solved by changing,
in: /home/pi/nuki/nuki_messages.py,
self.name = name.hex().ljust(64, ‘0’)
for:
self.name = name.encode(“utf-8”).hex().ljust(64, ‘0’)

and in /home/pi/nuki/nuki.py,
open(’/home/pi/nuki/nuki.cfg’, ‘wb’) as configfile:
for:
with open(’/home/pi/nuki/nuki.cfg’, ‘w’) as configfile:
as I got and error too.

Now my nuki.cfg file is created and my lock works fine with Python3.

For the server to run I have had to set up a new environment with only Python3: follow instructions here: https://flask.palletsprojects.com/en/1.1.x/installation/

And then change these two lines in: /home/pi/nuki/nuki3/server.py (where nuki3 is the new env dir)
from configparser import SafeConfigParser # old
from configparser import ConfigParser # new
parser = SafeConfigParser() # old
parser = ConfigParser() # new

Now everything goes smooth!

Ah great, that change in self.name was added yesterday evening by a pull request so that’s also in the repository now.

Did SafeConfigParser not work for you? I don’t have any issues with that one with python 3.7

Great that everything works now!