Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing ComfoCool: request for help ;) #13

Closed
gertst opened this issue Aug 26, 2023 · 15 comments
Closed

Implementing ComfoCool: request for help ;) #13

gertst opened this issue Aug 26, 2023 · 15 comments

Comments

@gertst
Copy link

gertst commented Aug 26, 2023

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
Copy link
Author

gertst commented Aug 26, 2023

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

@michaelarnauts
Copy link
Owner

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.

  • Using my laptop as a wireless Access Point (as bridge) and connecting it with a LAN cable to my network. I could then wirelessly connect my phone trough my laptop and use dump all traffic going through.

  • I have a managed switch where I can mark a port as monitored (the one that is connected to the Comfoconnect), and all traffic that is passing that port will be dumped in another port. I can then connect my laptop on that port and capture all the traffic going to the Comfoconnect.

  • You could do the same as above by using an old ethernet hub and connecting your pc, the Comfoconnect, and a connection to the rest of your network. All traffic going to the Comfoconnect can then also been seen by your computer.

  • If your phone is rooted, there might be a way to capture directly in your phone, I'm not sure about that.

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
Copy link
Author

gertst commented Aug 27, 2023

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
Copy link
Owner

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
Copy link
Author

gertst commented Aug 27, 2023

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:

  • turn it off using AWAY: python __main__.py set-speed away --host 192.168.X.X
  • turn it on using MEDIUM : python __main__.py set-speed medium --host 192.168.X.X

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
Copy link
Owner

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
Copy link
Owner

michaelarnauts commented Sep 4, 2023

@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
Copy link
Contributor

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".

  • If "Auto" is selected, that's all there is: it will turn the ComfoCool on (if the outside temperature is above a given setpoint., but that is not important, as it is a setting in the advanced settings menu)
  • If "Off" is selected, there's an additional combobox to choose the duration it should stay off: "Continuous", "1:00", "2:00", "3:00", "12:00" and "24:00". (out of my head)

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:

  • Auto: await self.cmd_rmi_request(bytes([0x85, UNIT_SCHEDULE, SUBUNIT_05, 0x01]))
  • Off with duration "Continuous": await self.cmd_rmi_request(bytestring([0x84, UNIT_SCHEDULE, SUBUNIT_05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00]))

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

@michaelarnauts
Copy link
Owner

michaelarnauts commented Sep 4, 2023

Okay, that's clear.

#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
Copy link
Author

gertst commented Sep 4, 2023

Sure - I will test this tonight

@michaelarnauts
Copy link
Owner

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
Copy link
Author

gertst commented Mar 17, 2024

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
Copy link
Contributor

szibis commented May 4, 2024

I have added this two PR's which should help add Full ComfoCool support. #28 and michaelarnauts/home-assistant-comfoconnect#51

@szibis
Copy link
Contributor

szibis commented May 4, 2024

and hopefully this one michaelarnauts/home-assistant-comfoconnect#52

@michaelarnauts
Copy link
Owner

These look good! Thanks @szibis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants