I wanted to have some smart lights in the apartment and looked around for a good solution. Home Assistant looked perfect - open source and easy to install and run. To make things easier, I bought a Home Assistant Green and a Zigbee antenna. I like the way that I can write my own scripts and create my own dashboards.
The apartment came with a smart heating and ventilation system that also could be controlled via the Domat Visual app. However, I found the app to have a poor UI and I also wanted better control over the devices. In particular the air-conditioning was not working correctly through the apartment system and I wanted to fix that as well.
The application loads a zip file containing xml files with configuration. Looking at those files, I could see that the communication protocol was called SSCP and also the username/password and other details. I wrote a program to parse the xml files and retrieve all the variables (uids) that could be read or written and output them in a readable format (yaml). That gave me results like:
- uid: 10044
length: 4
offset: 0
type: 13
name: hw.Pokoj06_ovladac_Pokoj_Temp_act
description: Teplota aktuální
page: Pracovna
format: '%4.1f °C'
perm: ro
Hunting around, I found that the SSCP protocol specification was available online. I installed the app on an old tablet, started socat as a logging relay, and ran the app with a modified xml configuration pointing to the relay.
Success! With the logging from socat, the uids from the xml files, and the SSCP specification, I watch the app do a login then fetch a number of uids. If I navigated to a different page, I could see a different set of uids being fetched. Likewise, I could change a uid in the app and watch that sequence. All the sequences matched the specification. With this information, I wrote a simple command line program to login, read or write uids and finally logout. A component of this converted length 4, type 13 uids from hex to IEEE754 format floats. I could then run, for example:
python3 main.py 10044 10045
24.3 °C : Pracovna : Teplota aktuální : 10044
37.4 %rh : Pracovna : Vlhkost aktuální : 10045
or:
python3 main.py 10055 10053 10052 10054 10056
3681.7 kWh : Odečty energií - aktuální stav : Elektroměr : 10055
75.9 m3 : Odečty energií - aktuální stav : Voda - studená : 10053
38.0 m3 : Odečty energií - aktuální stav : Voda - teplá : 10052
15.1 GJ : Odečty energií - aktuální stav : Kalorimetr Topení : 10054
641.0 kW : Odečty energií - aktuální stav : Kalorimetr Chlazení : 10056
Looking in a bit more detail, I noticed that the variables ranged from 9900 to 10300 but with lots of gaps. They were also grouped by either room or function (e.g. energy or air circulation). I also saw that the protocol requested the variables by uid and length, and that there were error messages in the specification for unknown uid and incorrect length. It turns out that you can request a smaller length for a uid, but requesting a larger one gives the incorrect size error. Starting at 50 below the lowest uid and ending at 50 above the highest uid, I requested all the missing variables at length 1, 2, 4, then 8. From the errors returned, I could create an additional list of uids and their lengths.
I now had a big list of unknown variables. For initial tests I changed settings on all the room controllers and in the app. Each time that I changed a setting, I fetched all the uids and checked for changes. I could work out what a lot of the uids represent from this, but some were still unknown. The system usually had one uid with a setter and another (or more than one) that showed the setting. As the system comprises a server plus room devices, that made sense. It also made it easier for the next step, which was to try writing new values to the unknown uids to see what changed. Over several weeks and with a bit of luck, I found additional settings like air conditioning on/off and speed, heating valves on/off, and air circulation speeds (normal and fast).
Because the goal was to control the home systems using Home Assistant, I also started writing an integration. With a lot of experimenting and looking for similar examples, I was able to add platforms to represent the devices in the apartment. It's also easy to run Home Assistant in a container or on a test system, so I used this to test my changes before running them on my real instance.
The final piece was communicating to the server for the aparment system. The app connected to it using OpenVPN on the mobile device. There were some existing addons for OpenVPN, but they didn't handle the configuration that I wanted (separate username/password file for easy conversion from the OpenVPN configuration). Writing an addon was a lot simpler than writing the integration. I could now remove the socat proxy and run everything on the Home Assistant server.
We can now control the apartment using Home Assistant with improvements over the app:
Because Home Assistant is controlled through a graphical interface, these screenshots show the progress of the integration.
-^- More notes -^-