[HomeConnect]: Elegant solution based on a MQTT bridge. Local (no cloud)

Homeconnect is the system provided by SIEMENS and other brands to connect their appliances.
I have a connected oven and its timer alarm is not very loud. My first automation was very basic: use all available channels (TTS, lights,…) to inform me that time was elapsed. Then when the oven door was open, the alarm was dismissed.
That was before HA, and it was working fine with jeedom.

When I switched to HA, I realized that the offical homeconnect integration was not really up to date (many features non functional with my oven). There is also an alternative integration, but it does not support a basic feature as the timer. I contacted the developer who clearly told me that he was not interested in this feature.

So I started searching for other solutions. IFTTT work with homeconnect API but it’s a paying feature.
Finally I found this article:

And I discovered a very elegant solution : a local bridge relaying all messages from home connect to my MQTT broker. This is a cloudless solution ans it’s a plus as I always prefer local vs cloud.
The source code is here: github.com/osresearch/hcpy

The installation took me a couple of hours as I’m not used to install missing python dependencies etc… and I had to applied mods in the code described in the github. But at the end everything is working fine!
I was surprised to get immediate answer with solution in the issue I posted in the github. Actually all the solutions to my problems were already described in the “pull request” section of the github page. I will be happy to share my files to save you some time.

I installed a very light linux container on proxmod with python.
In HA, just 2 very basic sensors in my configuration.yaml file trigger the automations:

mqtt:
   sensor:
     - name: "Porte four"
       state_topic: "homeconnect/oven/state"
       value_template: "{{ value_json.door }}"
     - name: "Alarme four"
       state_topic: "homeconnect/oven/state"
       value_template: "{{ value_json.alarm }}"

I spent time looking for this solution and I would have been very happy to find a post like this one, that’s why I share it.
I hope you’ll enjoy it as much as I do :slight_smile:

EDIT: this is a link to a new fork of this project for Home Assistant:

4 Likes

Hi,

I’m really interested as I just bought a Siemens Dishwasher, and I was looking to have a cloudless connection to HA.
I’m interested by your files. If you could share them, it would be great !

One question though : I’m using supervised HA on a Raspberry. Is there any way to integrate these python scripts “inside” HA, or have I to go with another Raspberry ?

Thanks !

Sure, here are my files. For the install I remember there was some difficulties but I found all the solutions after a bit of googling. Also, two sections of the github were really usefull:

  • issues: here you will see some issues you will face, reported by other people often with the solution.
  • pull request: here you can find some modifications done by other people who share their code.

Here is my file hc2mqtt file. All the credits goes to the authors, it’s coming from the github that I posted herebefore:
The original file did not support mqtt with authentication, it is added here a I don’t remember if I did other changes, I give you the whole file here:

#!/usr/bin/env python3
# Contact Bosh-Siemens Home Connect devices
# and connect their messages to the mqtt server
import json
import sys
import time
import ssl
from threading import Thread

import click
import paho.mqtt.client as mqtt

from HCDevice import HCDevice
from HCSocket import HCSocket, now


@click.command()
@click.argument("config_file")
@click.option("-h", "--mqtt_host", default="192.168.20.100")
@click.option("-p", "--mqtt_prefix", default="homeconnect/")
@click.option("--mqtt_port", default=1883, type=int)
@click.option("--mqtt_username")
@click.option("--mqtt_password")
@click.option("--mqtt_ssl", is_flag=True)
@click.option("--mqtt_cafile")
@click.option("--mqtt_certfile")
@click.option("--mqtt_keyfile")
def hc2mqtt(config_file: str, mqtt_host: str, mqtt_prefix: str, mqtt_port: int, mqtt_username: str,
            mqtt_password: str, mqtt_ssl: bool, mqtt_cafile: str, mqtt_certfile: str, mqtt_keyfile: str):
    click.echo(f"Hello {config_file=} {mqtt_host=} {mqtt_prefix=} {mqtt_port=} {mqtt_username=} {mqtt_password=} "
               f"{mqtt_ssl=} {mqtt_cafile=} {mqtt_certfile=} {mqtt_keyfile=}")

    with open(config_file, "r") as f:
        devices = json.load(f)

    client = mqtt.Client()

    if mqtt_username and mqtt_password:
        client.username_pw_set(mqtt_username, mqtt_password)

    if mqtt_ssl:
        if mqtt_cafile and mqtt_certfile and mqtt_keyfile:
            client.tls_set(ca_certs=mqtt_cafile, certfile=mqtt_certfile, keyfile=mqtt_keyfile, cert_reqs=ssl.CERT_REQUIRED)
        else:
            client.tls_set(cert_reqs=ssl.CERT_NONE)

    client.connect(host=mqtt_host, port=mqtt_port, keepalive=70)

    for device in devices:
        mqtt_topic = mqtt_prefix + device["name"]
        thread = Thread(target=client_connect, args=(client, device, mqtt_topic))
        thread.start()

    client.loop_forever()

# Map their value names to easier state names
topics = {
        "OperationState": "state",
        "DoorState": "door",
        "RemainingProgramTime": "remaining",
        "PowerState": "power",
        "LowWaterPressure": "lowwaterpressure",
        "AquaStopOccured": "aquastop",
        "InternalError": "error",
        "FatalErrorOccured": "error",
        "AlarmClockElapsed": "alarm",
}



def client_connect(client, device, mqtt_topic):
        host = device["host"]

        state = {}
        for topic in topics:
                state[topics[topic]] = None

        while True:
                try:
                        ws = HCSocket(host, device["key"], device.get("iv",None))
                        dev = HCDevice(ws, device.get("features", None))

                        #ws.debug = True
                        ws.reconnect()

                        while True:
                                msg = dev.recv()
                                if msg is None:
                                        break
                                if len(msg) > 0:
                                        print(now(), msg)

                                update = False
                                for topic in topics:
                                        value = msg.get(topic, None)
                                        if value is None:
                                                continue

                                        # Convert "On" to True, "Off" to False
                                        if value == "On":
                                                value = True
                                        elif value == "Off":
                                                value = False

                                        new_topic = topics[topic]
                                        if new_topic == "remaining":
                                                state["remainingseconds"] = value
                                                value = "%d:%02d" % (value / 60 / 60, (value / 60) % 60)

                                        state[new_topic] = value
                                        update = True

                                if not update:
                                        continue

                                msg = json.dumps(state)
                                print("publish", mqtt_topic, msg)
                                client.publish(mqtt_topic + "/state", msg)

                except Exception as e:
                        print("ERROR", host, e, file=sys.stderr)

                time.sleep(5)

if __name__ == "__main__":
        hc2mqtt()

There was also a very little modification in hc-login something like ‘R’ instead of ‘r’ but it is documented in the github:

About your second question, I guess it would be possible but I have no idea how to make it clean (you don’t want your code to be overwritten when HA update). Probably in a kind of docker container.
I run HA in a VM under proxmox, so it was much easier for me to create a new container with minimalistic debian just with python to run this script.

We have forked this to make some faster progress:

Just waiting to get a few commits landed I think it should be able to retrieve all values, set all configuration options, as well as start programs etc.

Currently requires manual MQTT configuration of entities but I have produced some samples.

4 Likes

Just bought 3 connected Siemens devices. So very interesting topic and if possible I am available for testing my dishwasher, oven or my cooker.

1 Like

Very nice to see that you take this in charge :slight_smile:
I will edit my first message to show your github link.

What’s your progress ?
I see you have a homeassistant addon. Is it only the mqtt part ?

Anything local would be great for home connect as the official HA cloud integration(for me at least) loses connection entirely and frequently requiring removal and reinstallation.
Pile of poo to be honest

3 Likes

Initial setup is working great here too for my Siemens oven. I have to experiment further with what is possible but glad to get rid of the cloud (which disconnects / errors out once in a while).

I’m running it in a python environment for now, trying to decide whether a docker image is worth it. I assume this could be a direct integration as well, even skipping mqtt altogether.

I’m highly exited for this, an bought a bosh dishwasher and a neff induction cooktop with a hood especially because I saw this post!

I really want to try, it would be a good learning experience to make a ha addon from it, but the place those should go are still under heavy construction.

Soon!

Hello, thanks for this post.
I have generate the devices.json file. Also install the Home assistant Add on ( https://github.com/hcpy2-0/hcpy/wiki/HomeAssistant-Addon.
Create a Directory “share” in my HA
Copy devices.json in this one.
But when i start the Add on HomeConnectMqtt, i have this “File not found /share/devices.json
Please supply a suitable devices file using hc-login.py”.O…
Where is my mistake?
Br

You shouldn’t have to create the share directory, it exists in HAOS by default? The easiest way to access it is via the advanced SSH/ web terminal addon

If going via the HAOS native file system share is in /mnt/data/supervisor/share

Hello,

thanks, i will try it when i came back at home. But normally, i create the directory Share in “Config” directory. Then the path is normally correct but certainly i make something wrong.
Also i use file editor to add this one :frowning:

It can also go in the addon_configs/#######_hcpy directory and would map to /config/devices.json in the configuration path.

Hello,

thanks for the hint :slight_smile: .

I use File Editor from Home Assistant (i’m no familiar with commande of SSH/ web terminal addon). By default, it doesn’t display the “root” but only the /config directory → So I unchecked the option to display EVERYTHING. I then saw that the “SHARE” directory existed at the root and placed my devices.json file in it :slight_smile: This time, my file was correctly recognized :slight_smile:
However, in the logs, there was still an error.
I saw that the add-on could be updated from v0.4.0 to v0.4.1 → I did the update.
Then I saw that there was an additional field in the configuration that it didn’t have before: HCPY_DISCOVERY_FILE with “/config/discovery.yaml” in it.
I also created another user for the HCPYmqtt.
But the add on HomeConnectMQTT still doesn’t launch.
Here’s my log and I don’t know what to do :frowning:

Hello devices_file='/share/devices.json' mqtt_host='localhost' mqtt_prefix='homeconnect/' mqtt_port=1883 mqtt_username='hcpyusername' mqtt_password='hcpypassword' mqtt_ssl=False mqtt_cafile=None mqtt_certfile=None mqtt_keyfile=None mqtt_clientname='hcpy1'domain_suffix='' debug=False ha_discovery=True
Traceback (most recent call last):
  File "/app/hc2mqtt.py", line 268, in <module>
    hc2mqtt(auto_envvar_prefix="HCPY")
    ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/click/core.py", line 1161, in __call__
    return self.main(*args, **kwargs)
           ~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/click/core.py", line 1082, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.13/site-packages/click/core.py", line 1443, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
  File "/app/hc2mqtt.py", line 162, in hc2mqtt
    client.connect(host=mqtt_host, port=mqtt_port, keepalive=70)
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/paho/mqtt/client.py", line 914, in connect
    return self.reconnect()
           ~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/paho/mqtt/client.py", line 1044, in reconnect
    sock = self._create_socket_connection()
  File "/usr/local/lib/python3.13/site-packages/paho/mqtt/client.py", line 3685, in _create_socket_connection
    return socket.create_connection(addr, timeout=self._connect_timeout, source_address=source)
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/socket.py", line 864, in create_connection
    raise exceptions[0]
  File "/usr/local/lib/python3.13/socket.py", line 849, in create_connection
    sock.connect(sa)
    ~~~~~~~~~~~~^^^^
ConnectionRefusedError: [Errno 111] Connection refused

This is just an error connecting to your MQTT broker. Are you running the mosquito add-on to provide an MQTT service?

Check the host/port in the configuration

Yes i have this one.
What I’ve just done is put the ip 192.168.1.77 in the HCPY_MQTT_HOST field instead of localhost.
After that I see that it starts trying to connect but in the logs I see that it doesn’t work (I’ve deliberately ended the “id” of my devices with 123456 12345.) I think that after resolving not to connect to my mqtt, I’ll also have an edition of the devices.json file…

Hello devices_file='/share/devices.json' mqtt_host='192.168.1.77' mqtt_prefix='homeconnect/' mqtt_port=1883 mqtt_username='hcpyusername' mqtt_password='hcpypassword' mqtt_ssl=False mqtt_cafile=None mqtt_certfile=None mqtt_keyfile=None mqtt_clientname='hcpy1'domain_suffix='' debug=False ha_discovery=True
2025-03-04 10:52:50.960085 MQTT connection established: 0
2025-03-04 10:52:50.960348 oven set topic: homeconnect/oven/set
2025-03-04 10:52:50.961060 oven program topic: homeconnect/oven/activeProgram
2025-03-04 10:52:50.961313 oven program topic: homeconnect/oven/selectedProgram
2025-03-04 10:52:53.954881 oven connecting to SIEMENS-Oven-384020390136123456
2025-03-04 10:52:53.956887 oven connecting to SIEMENS-Oven-384020390239123456
2025-03-04 10:52:53.957864 dishwasher connecting to SIEMENS-Dishwasher-014020389735123456
2025-03-04 10:52:53.959471 hob connecting to SIEMENS-EZ877KZY1E-68A40EB12345
2025-03-04 10:52:53.962122 hood connecting to SIEMENS-LD88WMM66-68A40EB12345
2025-03-04 10:52:57.352135 oven ERROR [Errno -5] No address associated with hostname
2025-03-04 10:52:57.353605 oven ERROR [Errno -5] No address associated with hostname
2025-03-04 10:52:57.354354 dishwasher ERROR [Errno -5] No address associated with hostname
2025-03-04 10:52:57.355010 hob ERROR [Errno -5] No address associated with hostname
2025-03-04 10:52:57.356091 hood ERROR [Errno -5] No address associated with hostname
2025-03-04 10:53:05.992088 HADiscovery - publishing MQTT discovery for oven
2025-03-04 10:53:06.020801 oven set topic: homeconnect/oven/set
2025-03-04 10:53:06.021082 oven program topic: homeconnect/oven/activeProgram
2025-03-04 10:53:06.021232 oven program topic: homeconnect/oven/selectedProgram
2025-03-04 10:53:21.050549 HADiscovery - publishing MQTT discovery for oven
2025-03-04 10:53:21.086888 dishwasher set topic: homeconnect/dishwasher/set
2025-03-04 10:53:21.087155 dishwasher program topic: homeconnect/dishwasher/activeProgram
2025-03-04 10:53:21.087300 dishwasher program topic: homeconnect/dishwasher/selectedProgram
2025-03-04 10:53:36.119028 HADiscovery - publishing MQTT discovery for dishwasher
2025-03-04 10:53:36.132334 hob set topic: homeconnect/hob/set
2025-03-04 10:53:36.132591 hob program topic: homeconnect/hob/activeProgram
2025-03-04 10:53:36.132713 hob program topic: homeconnect/hob/selectedProgram

Log of mqtt:

2025-03-04 10:58:15: New client connected from 172.30.32.1:58504 as hcpy1 (p2, c1, k70, u'hcpyusername').
2025-03-04 10:58:44: New connection from 172.30.32.2:44206 on port 1883.
2025-03-04 10:58:44: Client <unknown> closed its connection.

Generally this is a local DNS issue, you can try to set the domain_suffix to match your router (e.g. you may be .local or .home or something). However foolproof is to modify devices.json and change the host to the IP addresses (and then provide MAC addresses to lock the IP in DHCP).

I appreciate that you take so much time for an amateur like me.
Although your explanations are undoubtedly very clear for many, they are a little less so for me.
At the moment, I haven’t yet set the IP of the Siemens devices in my router to the Mac address. However, I can find out which IP my hood has, for example. Currently 192.168.1.6

Should I adapt this in devices.json?

        "name": "hood",
        "host": "SIEMENS-LD88WMM66-68A40E123456",
        "key": "bSHxxxxxxx_xxxxxx",
        "iv": "HexxxxxxxxxxWx6A",
        "description": {
            "type": "Hood",
            "brand": "SIEMENS",
            "model": "LD88WMM66",
            "version": "9",
            "revision": "5"

to this?

        "name": "hood",
        "host": "SIEMENS-LD88WMM66-68A40E123456.192.168.1.6",
        "key": "bSHxxxxxxx_xxxxxx",
        "iv": "HexxxxxxxxxxWx6A",
        "description": {
            "type": "Hood",
            "brand": "SIEMENS",
            "model": "LD88WMM66",
            "version": "9",
            "revision": "5"

Just checking have you tried without the 123456 on the end of was that just to hide the serial number pasting on here?

It would just be

"name": "hood",
"host": "192.168.1.6",

It was just to hide the complete number
SIEMENS-LD88WMM66-68A40Exxxxxx.192.168.1.6

Ok, I’ll test it by putting only the ip as you ask :slight_smile: