michaelarnauts / aiocomfoconnect

Python AsyncIO Zehnder ComfoConnect LAN C library to interface with ComfoAir Q350/450/600 units.
Other
66 stars 14 forks source link

Implementing ComfoCool: request for help ;) #13

Closed gertst closed 10 months ago

gertst commented 1 year ago

Hi Michaël,

I can use python -m aiocomfoconnect show-sensor 53 --host 192.168.x.x to check if my ComfoCool is on or off: Off is 1 and On is -1 or 0. Don't know why it is 0, sometimes, but it looks that -1 is On, consistently, so that's good enough ;-)

I asked the question before if it is possible to include the ComfoCool integration, but I know that you don't have the ComfoCool, so you are not able to test on it. I totally understand that. However, It would be very 'cool' (no pun intended :-)) if I manage to get the ComfoCool working by myself and sent you a pull request. I just don't know on how I can send a command to the ComfoCool to turn it on or off. Can you put me in the right direction on how to do this myself? In the Zehnder app, the UI looks more or less like the Boost feature, but the other way around: To enable it, there is no timer, but to disable it there is a timer going from 1 hour to Continuously. Of course, that timer feature is not needed as this can be done in HA. But it might give you an idea on what command to use...

I'm a JS/Node/Vue programmer, but don't know Python, but I'm happy to experiment with it to have this feature enabled!

Can you provide me some more insights? I tried running the decode_pcap.py to capture the command, but for some reason I don't see any traffic on port 56747 or on the IP of my ComfoConnect ... I guess this is the first I get to do: capturing the traffic to turn it on/off?

Any help is appreciated a lot!

Gert

gertst commented 1 year ago

Btw, the pdo 69, as mentioned here is not working. It is 53 that is working on my device.

michaelarnauts commented 1 year ago

Decode_pcap.py can only be used when you have a pcap with the traffic to the Comfoconnect Lan C in it. You will need to find a way to actually capture it first.

If you could capture the traffic, that would help immensely. The local traffic isn't encrypted, and by using my decode script, I could fairly easy see what commands are being executed.

The issue is that it's difficult to intercept the traffic. I've used a few ways in the past that worked.

Capturing on your router/firewall is probably not possible, since the traffic stays on the same subnet, and isn't passing your router/firewall.

gertst commented 1 year ago

Thanks for the info!

I was able to capture the traffic to the Comfoconnect using a managed switch, like you suggested :-) Here is a log session (decoded with your script) where I did turn on and off the ComfoCool. How do I know what commands are used?

CnRpdoRequestType
16 {'tx': [1], 'rx': ['00', '01']}
18 {'tx': [1], 'rx': ['00', '01']}
226 {'tx': [2], 'rx': ['0000', 'c800']}
224 {'tx': [1], 'rx': ['00', '03']}
225 {'tx': [1], 'rx': ['00', '01']}
120 {'tx': [2], 'rx': ['0000', '2f01', '2d01', '2c01', '2a01', '2901', '2a01', '2b01', '2a01', '2c01', '2e01', '2d01', '2c01', '2b01', '2a01']}
119 {'tx': [2], 'rx': ['2c01', '2b01', '2c01', '2b01', '2a01', '2c01', '2d01', '2e01', '2d01', '2b01', '2e01', '2d01']}
227 {'tx': [1], 'rx': ['64']}
784 {'tx': [1], 'rx': ['00', '00']}
401 {'tx': [1], 'rx': ['00', '00']}
33 {'tx': [1], 'rx': ['00', '00']}
321 {'tx': [2], 'rx': ['0000', '0100']}
49 {'tx': [1], 'rx': ['00', '01']}
65 {'tx': [1], 'rx': ['02']}
81 {'tx': [3], 'rx': ['00000000', 'ffffffff']}
337 {'tx': [3], 'rx': ['00000000', '22000000']}
37 {'tx': [1], 'rx': ['00', '00']}
325 {'tx': [2], 'rx': ['0000', '0100']}
53 {'tx': [1], 'rx': ['00', '01', 'ff', '01']}
85 {'tx': [3], 'rx': ['00000000', 'ffffffff', '100e0000', '0f0e0000', '0e0e0000', '0d0e0000', '0c0e0000', '0b0e0000', 'ffffffff']}
341 {'tx': [3], 'rx': ['00000000', '02000000', '00000000', '02000000']}
338 {'tx': [3], 'rx': ['00000000', '00000000']}
82 {'tx': [3], 'rx': ['00000000', 'ffffffff']}
66 {'tx': [1], 'rx': ['00']}
67 {'tx': [1], 'rx': ['01']}
56 {'tx': [1], 'rx': ['01']}
212 {'tx': [6], 'rx': ['0000', 'de00']}
208 {'tx': [1], 'rx': ['00', '00']}
220 {'tx': [6], 'rx': ['0000', 'b200']}
221 {'tx': [6], 'rx': ['c700']}
54 {'tx': [1], 'rx': ['00', 'ff']}
86 {'tx': [3], 'rx': ['00000000', 'ffffffff']}
70 {'tx': [1], 'rx': ['00', '00']}
342 {'tx': [3], 'rx': ['00000000', '00000000']}
55 {'tx': [1], 'rx': ['00', 'ff']}
87 {'tx': [3], 'rx': ['00000000', 'ffffffff']}
71 {'tx': [1], 'rx': ['00', '00']}
343 {'tx': [3], 'rx': ['00000000', '00000000']}
209 {'tx': [6], 'rx': ['0000', 'cb00']}
176 {'tx': [1], 'rx': ['00', '00']}
192 {'tx': [2], 'rx': ['7100']}
386 {'tx': [0], 'rx': ['00', '00']}
402 {'tx': [0], 'rx': ['00', '00']}
419 {'tx': [0], 'rx': ['00', '00']}
369 {'tx': [1], 'rx': ['00']}
370 {'tx': [1], 'rx': ['00']}
371 {'tx': [1], 'rx': ['00']}
372 {'tx': [1], 'rx': ['00']}
345 {'tx': [3], 'rx': ['00000000', '00000000']}
89 {'tx': [3], 'rx': ['00000000', 'ffffffff']}
73 {'tx': [1], 'rx': ['00', '00']}
57 {'tx': [1], 'rx': ['00', 'ff']}
42 {'tx': [1], 'rx': ['00', '00']}
330 {'tx': [2], 'rx': ['0000', '0100']}
58 {'tx': [1], 'rx': ['00', 'ff']}
74 {'tx': [1], 'rx': ['00', '00']}
90 {'tx': [3], 'rx': ['00000000', 'ffffffff']}
346 {'tx': [3], 'rx': ['00000000', '00000000']}
230 {'tx': [8], 'rx': ['0000000000000000']}

CnRmiRequestType
4 {'tx': [1, '02010101150304060514'], 'rx': b'\x03SIT14792460\x00\x02 \x10\xc0\x05ComfoAirQ\x00'}
5 {'tx': [14, '02010101150304060514'], 'rx': b'\x00LSO0CGJTY08EcCe6OKV1UB\x00\x00\x08\x10\xc0\x02ComfoCool\x00'}
6 {'tx': [38, '02010101150304060514'], 'rx': b'\x00DEM0121442148\x00\x01\x14\x10\xc0\x01ComfoConnect LAN C\x00'}
7 {'tx': [1, '871501'], 'rx': b'\x0b\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00 \x1c\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00 \x1c\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00 \x1c\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\xb0\x04\x00\x00\x00\x00\x00\x00\x00'}
8 {'tx': [1, '871505'], 'rx': b'\x01\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x01'}
57 {'tx': [1, '0117011002'], 'rx': b'\x01'}
58 {'tx': [1, '0117021002'], 'rx': b'\x01'}
59 {'tx': [1, '010101100b'], 'rx': b'471502005\x00'}
60 {'tx': [1, '871509'], 'rx': b'\x02\x00\x00\x00\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'}
65 {'tx': [1, '87150a'], 'rx': b'\x01\x00\x00\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00\x00'}
73 {'tx': [1, '012401100b'], 'rx': b'\x0e'}
74 {'tx': [1, '0125001003'], 'rx': b'\x00'}
75 {'tx': [1, '83150101'], 'rx': b'\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x02'}
76 {'tx': [1, '83150105'], 'rx': b'\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x02'}
77 {'tx': [1, '83150501'], 'rx': b'\x01\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x01'}
79 {'tx': [1, '011c011002'], 'rx': b'\x15\x00'}
80 {'tx': [1, '010101100d'], 'rx': b'BE\x00'}
81 {'tx': [1, '85150501'], 'rx': b''}
82 {'tx': [1, '8415050100000000100e000000'], 'rx': b''}
83 {'tx': [1, '8415050100000000ffffffff00'], 'rx': b''}
michaelarnauts commented 1 year ago

Awesome! All commands that are executed will be in the CnRmiRequestType section at the bottom. You might want to toggle it on and off a few times so you can recognise the command.

I think it might be the 8415050100000000100e000000. And the next one with the ffff's. The last bytes are the duration. So the most important part is the 84150501.

You could try manually execute this, but I don't think I have a way to do this from the CLI. You can modify the main.py to change the cli tool, and have that execute this command.

You could probably copy past from another command that also starts with 84 and create a new method to toggle your comfocool. I'm not near a computer right now, so it's a bit difficult to check.

gertst commented 1 year ago

Success: I was able to turn the ComfoCool on and off (with timer "Continuouly") ! I 've added this function in comfoconnect.py:

 async def set_comfocool(self, mode: bool):
        """Activate comfocool mode."""
        if mode:
            await self.cmd_rmi_request(bytes([0x85, UNIT_SCHEDULE, SUBUNIT_05, 0x01]))
        else:
            await self.cmd_rmi_request(bytestring([0x84, UNIT_SCHEDULE, SUBUNIT_05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00]))

In __main__.py, I had to hack it into the existing command set-speed, like this:, due to my lack of Python, but as a proof of concept, this works:

elif args.action == "set-speed":
        # await run_set_speed(args.host, args.uuid, args.speed)
        await run_set_comfocool(args.host, args.uuid, args.speed)

And then, for the run_set_comfocool, I did this hack:

async def run_set_comfocool(host: str, uuid: str, mode: str):
    """Connect to a bridge."""
    # Discover bridge so we know the UUID
    bridges = await discover_bridges(host)
    if not bridges:
        raise Exception("No bridge found")

    # Connect to the bridge
    comfoconnect = ComfoConnect(bridges[0].host, bridges[0].uuid)
    try:
        await comfoconnect.connect(uuid)
    except ComfoConnectNotAllowed:
        print("Could not connect to bridge. Please register first.")
        sys.exit(1)

    # my poor-mans hack to convert the literal to a bool ...
    switch = bool(True)
    print("mode", mode)
    if mode == "away":
        switch = False

    await comfoconnect.set_comfocool(switch)

    await comfoconnect.disconnect()

Now I'm able to run this a the CLI:

I hope that you can help me out on how to integrate this further in order to have this feature available in Home Assistant?

Of course I'm happy to help as much as possible! Gert

michaelarnauts commented 1 year ago

Great! I have enough information with this. I'll try to add it to the library, and the Home Assistant integration when I find the time!

michaelarnauts commented 1 year ago

@gertst what are the options you can choose from? Only "on" / "off", or is there also an "auto" option, or is "on" actually "auto"?

If possible, create a capture and toggle between all the settings. I want to be sure that the I have all the possibilities of 84150501.

gerts-but commented 1 year ago

I'm not at home , so I can't capture right now. But the App interface has the option to set it to "Auto" or to "Off".

But in fact we only need "on" (Auto) or "always off" (off with duration "Continuous"). because durations can/should be handled by Home Assistant.

Those 2 commands are the ones I provided in the previous post:

I'm happy to help if you need more info.

michaelarnauts commented 1 year ago

Okay, that's clear.

https://github.com/michaelarnauts/aiocomfoconnect/pull/14

Can you try to checkout this branch, and create and run the test.py command i've added in the merge request?

If all goes well, it should display the current status for 5 seconds (you can try to modify it from the app and it should update), turn the mode on, wait 5 seconds, and turn it off. You should see this being updated in the app UI instantly.

For my Home Assistant integration, it's also required that I can read out the current status correctly.

gertst commented 1 year ago

Sure - I will test this tonight

michaelarnauts commented 10 months ago

I've merged your PR and made a 0.1.9 release for this library.

Next thing to do is to add this to the Home Assistant integration here: https://github.com/michaelarnauts/home-assistant-comfoconnect

gertst commented 6 months ago

Hi Michaël, The cooling season is only a few months away. So I hope the ComfoCool features can be added to the HA version. Do you have an idea on when you can merge this PR into the Home Assistant integration? If there is anything I can help with, please let me know.

Thanks! Gert

szibis commented 4 months ago

I have added this two PR's which should help add Full ComfoCool support. https://github.com/michaelarnauts/aiocomfoconnect/pull/28 and https://github.com/michaelarnauts/home-assistant-comfoconnect/pull/51

szibis commented 4 months ago

and hopefully this one https://github.com/michaelarnauts/home-assistant-comfoconnect/pull/52

michaelarnauts commented 4 months ago

These look good! Thanks @szibis