rhyst / linak-controller

A Python script to control Linak standing desks.
MIT License
353 stars 51 forks source link

Provide an example docker image #42

Closed maxime1992 closed 2 years ago

maxime1992 commented 2 years ago

Hello :wave:

First of all... thank you for the project. I've spent so much time today trying different libs to connect to my desk and none of these worked or were reliable except yours.

I'm trying to dockerize your project, I've noticed that you made a comment at some point mentioning that you built a docker to test from a fresh install: https://github.com/rhyst/idasen-controller/issues/1#issuecomment-637781513

Here's what I've got so far:

FROM ubuntu

RUN apt update -y && apt upgrade -y

RUN apt install python3 python3-pip -y

ENV TZ=Europe/Paris

RUN ln -snf /usr/share/zoneinfo/$CONTAINER_TIMEZONE /etc/localtime && echo $CONTAINER_TIMEZONE > /etc/timezone

RUN apt install bluez -y

RUN pip3 install idasen-controller

COPY config.yaml .
COPY run.sh .

and run.sh has the following content:

#!/bin/bash

service dbus start
bluetoothd &

/bin/bash

I wonder if instead of killing bluetoothd on the host and running run.sh there is a way to get the exact config of bluethoothctl from the host as that's where I've got my bluetooth devices... That'd be much cleaner.

Also... It currently doesn't work and I get

root@ubuntu:/# bash run.sh
root@ubuntu:/# idasen-controller --config config.yaml
Traceback (most recent call last):
  File "/usr/local/bin/idasen-controller", line 5, in <module>
    from idasen_controller.main import init
  File "/usr/local/lib/python3.8/dist-packages/idasen_controller/main.py", line 139, in <module>
    config.update(config_file)
TypeError: 'NoneType' object is not iterable

Here's how I've launched the container:

docker build -t bluetooth-project .
docker run -it --rm --privileged --cap-add=SYS_ADMIN --cap-add=NET_ADMIN --net=host bluetooth-project

And from my host:

$ bluetoothctl 
Agent registered
[CHG] Controller XX:XX:XX:XX:XX:XX Pairable: yes
[bluetooth]# devices
Device XX:XX:XX:XX:XX:XX Desk 7734

and from the container

root@ubuntu:/# bluetoothctl 
Waiting to connect to bluetoothd...dbus[10]: arguments to dbus_connection_get_object_path_data() were incorrect, assertion "connection != NULL" failed in file ../../../dbus/dbus-connection.c line 5905.
This is normally a bug in some application using the D-Bus library.

  D-Bus not built with -rdynamic so unable to print a backtrace
Aborted (core dumped)

So clearly something's wrong here...

Any idea? :)

Thanks!

maxime1992 commented 2 years ago

Heyyy :tada: I decided to give it another shot after a good night of sleep and finding this thread on Reddit. It now works on Docker :tada: :smiley:!

Dockerfile:

FROM ubuntu

RUN apt update -y && apt upgrade -y

RUN apt install python3 python3-pip -y

ENV TZ=Europe/Paris

RUN ln -snf /usr/share/zoneinfo/$CONTAINER_TIMEZONE /etc/localtime && echo $CONTAINER_TIMEZONE > /etc/timezone

RUN apt install bluez -y

RUN apt install build-essential libglib2.0-dev libical-dev libreadline-dev libudev-dev libdbus-1-dev libdbus-glib-1-dev bluetooth libbluetooth-dev usbutils -y

RUN pip3 install idasen-controller

COPY config.yaml .

Command to build it: (don't forget to have your config.yaml in the same folder and ready to connect to your desk)

docker build -t bluetooth-project .

Command to launch the container:

docker run -it --rm --privileged --cap-add=SYS_ADMIN --cap-add=NET_ADMIN --net=host -v /dev/bus/usb:/dev/bus/usb -v /var/run/dbus:/var/run/dbus bluetooth-project

I'm sure some of this can be relaxed by removing some flags, but I'm not a pro with all these permissions. I guess one way to find out would be to remove some and see if it still works but I'm not going to play with that right now. If someone finds out the minimal flags required to run all this please let us know :pray: But at least this is working now :D!

Oh also, I forgot. Inside the container you'll have to specify the config. So your commands should at least start with this:

idasen-controller --config ./config.yaml

I'm not 100% sure on this but also I think this is working fine because I've managed to pair (and trust) my desk using bluetoothctl. In order to do that, either from the host or the container (as it's all forwarded and shared anyway):

bluetoothctl
[bluetooth]# devices
Device XX:XX:XX:XX:XX:XX Desk 7734 <--- I can see my desk as a device here
[bluetooth]# paired-devices 
Device XX:XX:XX:XX:XX:XX Desk 7734 <-- I've also paired it
[bluetooth]# trust E9:E8:3A:03:45:46 <-- and added it as a trusted device

If your device isn't showing up here, unfortunately I don't fully remember what I've done but on top of my memory:

bluetoothctl
power on
pairable on
discoverable on
agent on
scan on

At this stage, on your desk controller, press the bluetooth button for 2/3 seconds until it starts blinking blue.

Once it's detected do

pair XX:XX:XX:XX:XX:XX
connect XX:XX:XX:XX:XX:XX

Hopefully at this stage you should be connected and you know the connection is working all fine.

Once/if connected, don't forget to run disconnect otherwise the script won't be able to connect itself!

voruti commented 2 years ago

Hi, I was also playing with the idea of Dockerizing this, but then was distracted by other things. https://github.com/rhyst/idasen-controller/compare/master...voruti:docker is what I did so far.

I think the main differences are that I use the Python image and work with the local development state.

maxime1992 commented 2 years ago

I've published my project wrapping this lib to expose some MQTT endpoints and was able to successfully integrate with Home Assistant. In case anyone is interested, have a look here (everything explained in the README): https://github.com/maxime1992/linak-2-mqtt

Still leaving this issue open for now as I still think it may be a nice idea to have a docker file in this project :+1:

rhyst commented 2 years ago

Ah thanks for this, it's a good idea! If you make a PR I will accept otherwise I will get around to adding it myself at some point.

rhyst commented 2 years ago

I have put an example docker file in the RECIPES file. Because of a weird WSL setup I can't test a docker file properly so I didn't want to include it as a dockerfile in the main repo.