A Dreamer's Lair

Install domoticz on the Raspberry PI in a docker container part 2: using linux server image

In a previous post I showed how I installed domoticz in a docker container using the documentation on the WIKI.

Since I now need to start using domoticz for ‘real’ (since the razberry daughterboard on my ‘production’ PI seems to have died on me) I wanted to update the container with the latest version. Although I no longer have to do the two part install (see my previous post) I searched for an alternative which would be simpler to use and also up-to-date. That is when I came across the linux server.io site which also has a domoticz image available. I tried to install that and it all seems a lot simpler than the one from Joshuacox. Well at least for a domoticz/docker beginner like me!

Since I am using docker on a Raspberry PI3 I needed the ARM version of the domoticz image which can be found here.

As I mentioned in my previous post I already have a mount to my NAS in which I want to store my domoticz data. The mount on the PI is

/home/pi/dockerdata

After removing the old domoticz container and images and cleaning up the mapped config folder on the NAS, I then installed the new domoticz instance.

sudo docker run --name=domoticz \
                --restart unless-stopped \
                -d \
                -t \
                -p 1443:1443 \
                -p 6144:6144 \
                -p 8080:8080 \
                -v /home/pi/dockerdata/domoticz:/config \
                -e TZ=Europe/Amsterdam \
                --device=/dev/ttyUSB0 \
                lsioarmhf/domoticz

I no longer use the –privileged flag now because it’s more secure. Mapping the USB device seems to work just as fine.

After starting the container I checked the running domoticz instance on

http://<ip-from-your-pi>:8080

Unfortunately domoticz seemed not to be running. After inspecting the container logs, it turned out that an SSL key was generated for domoticz so it could be accessed using SSL. However, generating such a key on a Raspberry PI 3 takes quite a long time (in my case it took about 30-45 minutes!).

After I drank a nice cup of tea, and such…, domoticz was finally up.

So I now can start to reset all my ZWave nodes (since they can’t be removed from a dead ZWave controller) and include the in my new ZWave ‘production’ environment.

Setting up a fresh Raspberry PI 3 with Docker

I already mentioned in a previous post that I am moving away from several of my existing systems to replace them with new, and hopefully more reliable, solutions.

Not too long ago I started out experimenting with Docker containers on my Synology NAS and I must say that this has turned out quite well. Because of this I am planning to use Docker for all my new domotica where possible.

I intend to use a Raspberry PI 3 as a docker host. In the future I could even include Docker Swarm to make my domotica available 24/7 even when some hardware fails.

Setting up a PI 3 for Docker is already described in several posts on the great wide internet. Below I will describe the method I used including the links for that. No need to reinvent the wheel now is there!

Prepare SD/USB

The first step in setting up the PI is to prepare both a micro SD card and a USB thumb drive. I want to use the USB drive as my main memory device on the PI because it is less vulnerable then a micro SD card. But to be able to use a USB drive one first has to start with a micro SD card.

So from the Raspberry site itself I downloaded the lastest Raspbian Stretch Lite. The Lite version of course since I don’t want to use the GUI.

So download the image from here.

For writing the downloaded image to the SD card and USB drive Raspberry suggests Etcher which works just fine. See here.

I follow the instructions and now have both a micro SD card and a USB drive with Raspbian Stretch Lite on them.

On both the images I added an empty file called ssh so ssh is enabled by default when booting.

Boot and program USB mode

Next step is to connect the PI to the desired peripherals of choice (display, ethernet, keyboard, mouse etc).

Then insert the micro SD card and turn the power on (insert micro USB power cable).

We now want to program the USB mode on the PI. How to do this can be found here. So program the USB mode, reboot the PI and check if USB mode has been enabled.

When you have confirmed that USB mode is active, we can power off the Raspberry with the following command

sudo poweroff

Boot from USB, initial setup

Next step is to boot from the USB drive. So remove the micro SD card from the PI and attach the prepared USB drive. Again power on the PI and wait for it to have booted.

The first thing after we have logged in, is to change the password for the user pi. You can do this with the command passwd. Make sure it’s a strong password!

Next we want to make sure the PI has all the latest updates:

sudo apt-get update
sudo apt-get upgrade

Next we start the configuration tool using the command sudo raspi-config. With this configuration we need to change the folllowing stuff:

  • Hostname -> choose an appropiate one (for example DOM-PI01 for domotica PI number 1)
  • Wi-fi -> Enter your SSID and passphrase to enable Wi-fi. I want this enabled so I don’t need to have the PI connected with an UTP-cable.
  • Localisation options -> Change the timezone, keyboard layout and Wi-fi country to what’s applicable.
  • Advanced options -> Choose the smallest possible memory split of 16MB to free up as much RAM as possible. This because we don’t use a GUI anyway.

Quit the tool and let the PI reboot.

Next step is to make the IP-address for the WLAN static (make sure you reserve it on your router!) so the PI can be accessed wirelessly through a fixed IP-address.

Enter the following command to open the dhcp config

sudo nano /etc/dhcpcd.conf

Add the following lines to the config

interface wlan0
static ip_address=<your-static-ip>/24
static routers=<ip-to-your-gateway>
static domain_name_servers=<ip-to-your-dns-server>

(if you want you can do this for the LAN too. Simply use ‘interface eth0’)

Press Ctrl-X then Y to save the file and exit nano.

We now reboot one more time and again log in to the PI. Now verify with ifconfig that the WLAN0 is using the correct assigned IP-address.

Since I am now done with the initial setup, I power off my PI (sudo poweroff) and then remove the power cable.
Now I can remove the keyboard, mouse and monitor since they are no longer necessary.

When you have done this power up the PI by connecting the micro USB cable and let it boot. To access it you can use any SSH client. I use the free tool Bitvise SSH Client.

Setup watch dog and monitor tools

To monitor the PI so it for example automatically reboots when it hangs you can use watchdos and monitor tools. The DomoticZ site shows some nice options for this.

I installed the watchdog and Monit.

Add the Aeon Labs Z-Stick

Since I am planning to use the Aeon Labs Z-Stick (gen2 in my case) I insert the device into the PI. Since there are several reports of issues with such hardware after rebooting, I create a symbolic link again with useful help of Domoticz.

I opened the configuration with

sudo nano /etc/udev/rules.d/99-usb-serial.rules

and since I use a gen-2 Z-Stick I added the following line to it

SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="ttyUSB-ZStick-GEN2"

I can now access my Z-Stick hardware using the device

/dev/ttyUSB-ZStick-GEN2

regardless of the physical USB port it is attached to.

Mount a folder from my Synology NAS

To be able to more conveniently see data files which the docker containers use, I have created a shared folder on my NAS called dockerdata. To use this on the PI I have to mount an NFS volume on it.

First create the folder locally on the PI

mkdir /home/pi/dockerdata

The open fstab

sudo nano /etc/fstab

and add the following line to it

<ip-of-your-nas>:/volume1/dockerdata /home/pi/dockerdata nfs defaults 0 0

This assumes that you have a shared folder called dockerdata on your NAS.

Mount the volume

sudo mount -a

and check if the folder /home/pi/dockerdata reflects the contents of /volume1/dockerdata.

Install Docker CE

The final step in setting up our PI for docker is to install Docker itself.

You can do this simply by entering

curl -sSL https://get.docker.com | sh

Docker CE will now be installed.

And there you have it. The PI is ready to be used as a Docker Host!

eQ-3 Max Cube message protocol decrypted: Part 4, the ‘C’ word

In this part of unravelling the secrets of the eQ-3 Max Cube, I shall tell something about the Configuration Message Response, or the C Message Response. Like the H and M messages, the C message is one of the messages that the cubes sends when connecting to it for the first time. Also the message can be requested by using the c: command.

The configuration message contains, as the name would suggest, configuration data for a specific device which has been paired to the Cube. This means that, when a connection has been made to the Cube, a C message response will be received for each device that has been paired to the Cube.

Like the M message, the C message contains a comma separated list of strings in the form of


C:03f25d,7QPyXQATAQBKRVEwNTQ0OTIzAAsABEAAAAAAAAAAAPIA==

The first field contains the address of the device in HEX form. Because the eQ-3 software displays addresses in decimal notation, the address in this example would be 0x03f25d = 258653.

The second and last field contains a Base64 encoded string with the configuration data for the device (as identified by its address). The decoded bytes will look something like this for the Cube device itself


0000: ed 03 f2 5d 00 13 01 00   ........
0008: 4a 45 51 30 35 34 34 39   JEQ05449
0010: 32 33 00 0b 00 04 40 00   23......
0018: 00 00 00 00 00 00 00 ff   ........
0020: ff ff ff ff ff ff ff ff   ........
0028: ff ff ff ff ff ff ff ff   ........
0030: ff ff ff ff 0b 00 04 40   ........
0038: 00 00 00 00 00 00 00 41   .......A
0040: ff ff ff ff ff ff ff ff   ........
0048: ff ff ff ff ff ff ff ff   ........
0050: ff ff ff ff ff 68 74 74   .....htt
0058: 70 3a 2f 2f 6d 61 78 2e   p://max.
0060: 65 71 2d 33 2e 64 65 3a   eq-3.de:
0068: 38 30 2f 63 75 62 65 00   80/cube.
0070: 30 2f 6c 6f 6f 6b 75 70   0/lookup
0078: 00 00 00 00 00 00 00 00   ........
0080: 00 00 00 00 00 00 00 00   ........
0088: 00 00 00 00 00 00 00 00   ........
0090: 00 00 00 00 00 00 00 00   ........
0098: 00 00 00 00 00 00 00 00   ........
00a0: 00 00 00 00 00 00 00 00   ........
00a8: 00 00 00 00 00 00 00 00   ........
00b0: 00 00 00 00 00 00 00 00   ........
00b8: 00 00 00 00 00 00 00 00   ........
00c0: 00 00 00 00 00 00 00 00   ........
00c8: 00 00 00 00 00 00 00 00   ........
00d0: 00 00 00 00 00 00 43 45   ......CE
00d8: 54 00 00 0a 00 03 00 00   T.......
00e0: 0e 10 43 45 53 54 00 03   ..CEST..
00e8: 00 02 00 00 1c 20         ......

The first 18 bytes seem to contain the same type of information for all devices (except the Cube which seems to have one difference). The rest of the information is device specific.

So the first 18 bytes contain the following information


Position   Length   Information
===================================================
00         1        Data Length
01         3        Address of device
04         1        Device Type
05         1        Room ID
06         1        Firmware version
07         1        Test Result
08         10       Serial Number

So in the example above, the data length would be 237 bytes (0xed), the address is 0x03f25d (which is the same as the first field of the C message), the device type is 0 (meaning the Cube device itself). The Room ID and firmware version seem to be combined to the firmware version only when it concerns the cube device where Room ID is the LSB and Firmware version the MSB both of which are BCD encoded. So in this specific case the firmware version of the cube is 0113 which equals to 1.1.3. I haven’t got a clue where the field test result is for. It always seems 0. Lastly in the common block of device data, the serial number of the device is specified. In this case JEQ0544923.

The device type, as we have already seen in the M message is encoded as


///
/// Enumeration of possible Max Device Types.
/// The int value of the enumeration is important since it links
/// to the device type number in the MAX device.
///
public enum MaxDeviceType
{
    Cube = 0,
    RadiatorThermostat = 1,
    RadiatorThermostatPlus = 2,
    WallThermostat = 3,
    ShutterContact = 4,
    EcoButton = 5
}

The device specific bytes are specific (hence device specific ;)) for a certain device type. The first byte in the generic part gives us the total of bytes in the C message so we know how long the message should be and what to expect. When it comes to the C message for the Cube, I don’t have much data available yet. So there are a lot of unknowns here as you can see


Position   Length   Information
===================================================
0012       1        Is Portal Enabled
0013-0054  66       Unknown
0055-????  ??       Portal URL
????-00ed  ??       Unknown

The only thing I know now is the flag which indicates if the portal function has been enabled or not. And the Portal UR itself. In this case the URL seems to be http://max.eq-3.de:80/cube. In contrast to other fields the URL does not seem to have a field length specified as the first byte. Instead, the URL string seems to be terminated with a null byte. At the end of the message we can see some time zones specified but its unsure for me what the exact meaning is. So for now, this is the Cube C message.

For a radiator thermostat the decoded message looks something like this


0000: d2 06 c9 41 01 01 18 ff   ...A....
0008: 4b 45 51 30 33 35 32 32   KEQ03522
0010: 37 36 24 20 3d 09 07 18   76......
0018: 03 f4 0c ff 00 41 20 41   .....A.A
0020: 20 41 20 41 20 41 20 41   .A.A.A.A
0028: 20 41 20 45 20 45 20 45   .A.E.E.E
0030: 20 45 20 45 20 45 20 41   .E.E.E.A
0038: 20 41 20 41 20 41 20 41   .A.A.A.A
0040: 20 41 20 41 20 45 20 45   .A.A.E.E
0048: 20 45 20 45 20 45 20 45   .E.E.E.E
0050: 20 41 20 41 20 41 20 41   .A.A.A.A
0058: 20 41 20 41 20 41 20 45   .A.A.A.E
0060: 20 45 20 45 20 45 20 45   .E.E.E.E
0068: 20 45 20 41 20 41 20 41   .E.A.A.A
0070: 20 41 20 41 20 41 20 41   .A.A.A.A
0078: 20 45 20 45 20 45 20 45   .E.E.E.E
0080: 20 45 20 45 20 41 20 41   .E.E.A.A
0088: 20 41 20 41 20 41 20 41   .A.A.A.A
0090: 20 41 20 45 20 45 20 45   .A.E.E.E
0098: 20 45 20 45 20 45 20 41   .E.E.E.A
00a0: 20 41 20 41 20 41 20 41   .A.A.A.A
00a8: 20 41 20 41 20 45 20 45   .A.A.E.E
00b0: 20 45 20 45 20 45 20 45   .E.E.E.E
00b8: 20 41 20 41 20 41 20 41   .A.A.A.A
00c0: 20 41 20 41 20 41 20 45   .A.A.A.E
00c8: 20 45 20 45 20 45 20 45   .E.E.E.E
00d0: 20 45 20                  .E.

We can see that the data block is 210 (0xd2) bytes long. The address is 0x06c941 or decimal 444737. The device type is 1 (which means it’s a radiator thermostat) and it belongs to room 1. The firmware version is 24 (0x18) and the test result, whatever it means, is 255 (0xff). Finally the serial number is KEQ0352276.

The device specific bytes contain the following information


Pos  Len  Information
================================================================
12   1    Comfort Temperature       in degrees celsius * 2
13   1    Eco Temperature           in degrees celsius * 2
14   1    Max Set Point Temperature in degrees celsius * 2
15   1    Min Set Point Temperature in degrees celsius * 2
16   1    Temperature offset        in degrees celsius * 2 + 3,5
17   1    Window Open Temperature   in degrees celsius * 2
18   1    Window Open Duration      in minutes * 5
19   1    Boost                     3 MSB bits are duration:
                                      value is in minutes * 5
                                      but value 7 means 60 min.
                                    5 LSB bits are valve opening
                                      in % * 5
1a   1    Decalcification           3 MSB bits are day of week:
                                      Saturday = 0 etc.
                                    5 LSB bits are time in hours
1b   1    Max Valve Setting         in % * 255 / 100  (so to get
                                      valve setting use
                                      value * 100 / 255)
1c   1    Valve Offset              in % * 255 / 100
1d   182  Weekly Program            Schedule of 26 bytes for
                                    each day starting with
                                    Saturday. Each schedule
                                    consists of 13 words
                                    (2 bytes) e.g. set points.
                                    1 set point consist of
                                    7 MSB bits is temperature
                                      set point (in degrees * 2)
                                    9 LSB bits is until time
                                      (in minutes * 5)

For the above example data this translates to


               Raw     Decoded
================================================================
Comfort Temp    24     18 degrees Celsius
Eco Temp        20     16 degrees Celsius
Max Temp        3d     30,5 degrees Celsius
Min Temp        09     4,5 degrees Celsius
Temp Offset     07     0 degrees Celsius
Win Open Temp   18     12 degrees Celsius
Win Open Dur    03     15 minutes
Boost           f4     111 10100 -> 60 minutes, 100 %
Decal           0c     000 01100 -> Saturday, 12:00 hours
Max Valve       ff     100 %
Valve offset    00     0 %
Weekly program  41 20  0100000 100100000
                       -> 16 degrees, until 24:00
                etc.
          

For a wall thermostat the decoded message looks something like this


0000: ce 0a 12 bd 03 01 10 ff   ........
0008: 4b 45 51 30 37 30 34 37   KEQ07047
0010: 35 32 24 20 3d 09 41 20   52....A.
0018: 41 20 41 20 41 20 41 20   A.A.A.A.
0020: 41 20 41 20 45 20 45 20   A.A.E.E.
0028: 45 20 45 20 45 20 45 20   E.E.E.E.
0030: 41 20 41 20 41 20 41 20   A.A.A.A.
0038: 41 20 41 20 41 20 45 20   A.A.A.E.
0040: 45 20 45 20 45 20 45 20   E.E.E.E.
0048: 45 20 41 20 41 20 41 20   E.A.A.A.
0050: 41 20 41 20 41 20 41 20   A.A.A.A.
0058: 45 20 45 20 45 20 45 20   E.E.E.E.
0060: 45 20 45 20 41 20 41 20   E.E.A.A.
0068: 41 20 41 20 41 20 41 20   A.A.A.A.
0070: 41 20 45 20 45 20 45 20   A.E.E.E.
0078: 45 20 45 20 45 20 41 20   E.E.E.A.
0080: 41 20 41 20 41 20 41 20   A.A.A.A.
0088: 41 20 41 20 45 20 45 20   A.A.E.E.
0090: 45 20 45 20 45 20 45 20   E.E.E.E.
0098: 41 20 41 20 41 20 41 20   A.A.A.A.
00a0: 41 20 41 20 41 20 45 20   A.A.A.E.
00a8: 45 20 45 20 45 20 45 20   E.E.E.E.
00b0: 45 20 41 20 41 20 41 20   E.A.A.A.
00b8: 41 20 41 20 41 20 41 20   A.A.A.A.
00c0: 45 20 45 20 45 20 45 20   E.E.E.E.
00c8: 45 20 45 20 06 18 f4      E.E....
        

We can see that the data block is 206 (0xce) bytes long. The address is 0x0a12bd or decimal 660157. The device type is 3 (which means it’s a wall thermostat) and it belongs to room 1. The firmware version is 16 (0x10) and the test result, whatever it means, is 255 (0xff). Finally the serial number is KEQ0704752.

The device specific bytes contain the following information


Pos  Len  Information
================================================================

12   1    Comfort Temperature       in degrees celsius * 2
13   1    Eco Temperature           in degrees celsius * 2
14   1    Max Set Point Temperature in degrees celsius * 2
15   1    Min Set Point Temperature in degrees celsius * 2
1d   182  Weekly Program            Schedule of 26 bytes for
                                    each day starting with
                                    Saturday. Each schedule
                                    consists of 13 words
                                    (2 bytes) e.g. set points.
                                    1 set point consist of
                                    7 MSB bits is temperature
                                      set point (in degrees * 2)
                                    9 LSB bits is until time
                                      (in minutes * 5)
cc   3    Unknown

For the above example data this translates to


               Raw     Decoded
================================================================
Comfort Temp    24     18 degrees Celsius
Eco Temp        20     16 degrees Celsius
Max Temp        3d     30,5 degrees Celsius
Min Temp        09     4,5 degrees Celsius
Weekly program  41 20  0100000 100100000
                       -> 16 degrees, until 24:00
                etc.
          

Since the shutter contact and eco switch doesn’t seem to have configuration data (and I don’t yet own them so can’t verify it either), this concludes this part of the series.