As promised, here comes the tutorial on forwarding serial or USB ports to openHAB. This tutorial is the result of my efforts to use Vlad Kolotov’s Bluetooth binding (kudos to @vkolotov ) for my MiFlora plant sensors.
Problem description
Services such as Zwave or Bluetooth are limited in their transmission range for technical reasons. To improve the range, the corresponding adapters can be connected with extension cables. However, if the cable length is limited or the installation of cables is not possible, this does not lead to the desired success.
In order to solve this problem, there are two solutions, depending on the task, which are briefly presented below. For serial ports the combination of ser2net and socat and for USB ports usbip is a possible solution.
Before we start, here are some definitions. The server on which openHAB runs is always referred to as the client and the server to which the respective adapter is connected is referred to as the server.
I use a first generation Raspberry Pi with DietPi as OS for the server (which comes with the adapter). And openhab runs on a Raspberry Pi 3 with SSD and a manually installed openHabian and Raspbian Stretch (Kudos to @ThomDietrich)
Solution 1: USBIP for non-serial USB ports
In contrast to the ser2net / socat combination, this solution can be used for any USB port. Disadvantage: I got it to run on the server (the one with the adapter), but not on the openHAB site (the client) yet.
The guide is based on the blog entry “Linux, RPi and USB over IP” by Piotr Król and is a little shortened here.
Erste Schritt ist das Aufsetzen des Servers, an dem der USB Adapter angeschlossen ist. Hierzu muss zunächst usbip installiert werden. We omit the check whether the kernel is prepared for it, since this is usually the case in current kernels
sudo apt install usbip
Then the usbip daemon is started and the matching USB adapter is identified and shared.
sudo modprobe usbip-core
sudo modprobe usbip-host
sudo usbipd -D
Now we can display the USB adapters.
user@server:~ $ usbip list -l
- busid 1-1.1 (0424:ec00)
Standard Microsystems Corp. : SMSC9512/9514 Fast Ethernet Adapter (0424:ec00)
- busid 1-1.3 (0a12:0001)
Cambridge Silicon Radio, Ltd : Bluetooth Dongle (HCI mode) (0a12:0001)
The one we are looking for has the bus id 1-1.-3 and is a bluetooth adapter. With a bind it is bound and shared on the network.
sudo usbip --debug bind -b 1-1.3
And now we come to the client side, the openhab server. Here too, usbip must be installed. After that we can check if our enabled adapter is visible. IP address should be replaced with the IP address of your server.
sudo usbip list -r <IP address>
the result of the list command should be something like this.
Exportable USB devices
======================
- 10.42.42.205
1-1.3: Cambridge Silicon Radio, Ltd : Bluetooth Dongle (HCI mode) (0a12:0001)
: /sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.3
: Wireless / Radio Frequency / Bluetooth (e0/01/01)
The Bluetooth adapter is now shared on the network and can be integrated with the following commands. Attention: On a Raspberry I did not succeed in integrating the adapter.
sudo modprobe vhci-hcd
sudo usbip attach -r <IP address> -b 1-1.3
For the removal of the connection refer to the above mentioned blog article “Linux, RPi and USB over IP updated”
Solution 2: ser2net and socat for serial USB ports
If you now have a USB adapter that looks like a serial interface, e.g. the Bluetooth adapter from BlueGiga or a Z-Wave adapter like the one from Aeotech, the solution can be the combination of ser2net and socat.
ser2net is installed on the server and shares the serial port on the network and socat is installed on the client and provides the interface there.
The guide is essentially a compilation of various posts and your own research. Therefore kudos to @snoekieboe, @snackboards, 2devnull
As with the usbip solution, we start with the server. My server is a Raspberry 1 with DietPi () and a BlueGiga Bluetooth adapter.
First we check if the adapter works. For this there is a Python script from BlueGiga which queries the adapter.
apt install python-serial
wget https://raw.github.com/jrowberg/bglib/master/Python/Examples/bled112_scanner.py
chmod +x ./bled112_scanner.py
./bled112_scanner.py
If the output somehow looks like this, then the adapter already works.
user@server:~ $ ./bled112_scanner.py -p /dev/ttyACM0
================================================================
BLED112 Scanner for Python v2013-04-07
================================================================
Serial port: /dev/ttyACM0
Baud rate: 115200
Scan interval: 200 (250.00 ms)
Scan window: 200 (250.00 ms)
Scan type: Passive
UUID filters: None
MAC filter(s): None
RSSI filter: None
Display fields: - Time
- RSSI
- Packet type
- Sender MAC
- Address type
- Bond status
- Payload data
Friendly mode: Disabled
----------------------------------------------------------------
Starting scan for BLE advertisements...
1529261718.724 -90 2 11880C3159C7 1 255 1EFF0600010920029D1D359B9D58E977F053975C0B48A5A2756C7CD8B470DB
1529261718.837 -87 2 11880C3159C7 1 255 1EFF0600010920029D1D359B9D58E977F053975C0B48A5A2756C7CD8B470DB
1529261719.129 -90 2 11880C3159C7 1 255 1EFF0600010920029D1D359B9D58E977F053975C0B48A5A2756C7CD8B470DB
1529261719.185 -87 0 DCD93522D048 1 255 0201060302AFFE06094E30305558
1529261719.244 -87 2 11880C3159C7 1 255 1EFF0600010920029D1D359B9D58E977F053975C0B48A5A2756C7CD8B470DB
1529261719.290 -62 0 FB45E00C3C13 1 255 0201060302AFFE06094E30343130
1529261719.554 -87 2 11880C3159C7 1 255 1EFF0600010920029D1D359B9D58E977F053975C0B48A5A2756C7CD8B470DB
1529261719.622 -85 0 C47C8D65B8A1 0 255 020106030295FE141695FE71209800BEA1B8658D7CC40D0910026208
No output or an error message? By default, /dev/ttyACM0 is used as the port. If this is not the correct one, it can be specified on the command line.
./bled112_scanner.py -p /dev/ttyACM0
The desired serial port is then made available on the network using the ser2net tool. To do this, ser2net must first be installed.
sudo apt install ser2net
Then edit the configuration file.
sudo nano /etc/ser2net.conf
and then add the linet as follows.
3001:raw:600:/dev/ttyACM0:115200 8DATABITS NONE 1STOPBIT
All other lines are commented out. This line is then used to make our serial port available on the network on port 3001. If you like you can also try a higher speed than 115200 baud. After saving, restart the service.
service ser2net restart
With netstat you can see if ser2net on port 3001 listens for a connection.
netstat -antp
And now we come to the client side, the openhab server. The client is not set up quite as quickly as the server. First, the socat package must be installed.
sudo apt install socat
Now the configuration follows, so that we can easily integrate several shared ports. The serial port should be accessible under /dev/ttyNET0. First we create the service file
sudo nano /etc/systemd/system/socat@.service
The content should look like this.
[Unit]
Description=Multipurpose relay (SOcket CAT)
After=network.target
StartLimitIntervalSec=0
StartLimitBurst=3000
[Service]
Restart=always
RestartSec=3
EnvironmentFile=/etc/default/socat-%i.conf
Type=simple
PIDFile=/var/run/socat-%i.pid
ExecStart=/usr/bin/socat -L/var/run/socat-%i.pid $SOCAT_DEFAULTS $SOCAT_CONNECTION
ExecStop=/bin/kill -SIGKILL $MAINPID
[Install]
WantedBy=multi-user.target
After saving the configuration is reloaded
systemctl daemon-reload
Now comes the configuration file for the serial device /dev/ttyNET0
sudo nano /etc/default/socat-ttyNET0.conf
The content should look like this.
SOCAT_DEFAULTS=-d -d -s -lf /var/log/socat.log
SOCAT_CONNECTION=pty,link=/dev/ttyNET0,raw,user=openhab,group=dialout,mode=777 tcp:<ip-address>:<port>
You should replace IP address and port with the IP of the server and the corresponding port and enable and start it after saving for system startup.
systemctl enable socat@ttyNET0
systemctl start socat@ttyNET0
The same can now be repeated with wide configurations until all remote interfaces are connected. With the script of BlueGiga you can check on the client whether data arrive on the new interface now.
Now the new serial interface is available on the openHAB server, but two steps are still missing to use it in openHAB. In the first step, the serial port must be built into the openhab service options so that Java can access it.
sudo nano /etc/default/openhab2
Adjust the EXTRA_JAVA_OPTS accordingly
EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0:/dev/ttyS0:/dev/ttyS2:/dev/ttyACM0:/dev/ttyAMA0:/dev/ttyNET0"
Then you have to log into the Karaf console (see also the openHAB Documentation) and install the serial transport. Simply enter the following.
feature:install openhab-transport-serial
logout
And finally, the openHAb should be restarted. Now there are some tricks with udev rules left, but I haven’t implemented them yet.
Questions, feedback, additions, corrections etc. are always welcome and I hope the tutorial will help.
Thomas