-
Notifications
You must be signed in to change notification settings - Fork 7
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
Controlling the comfoair-q using CAN #1
Comments
@marco-hoyer do you have any logs available? |
Hi @djwlindenaar, I started sniffing the CAN traffic going over the wire regularly and searched for some patterns and tried to find out how they encoded the values comparing what I saw to what was displayed on the device itself. Then I had a Zehnder ComfoSense C67 device for a while which helped finding some more things. I mostly bought it to reverse engineer how to send commands and thats where I failed so far. Even when I sent the exact same sequences I was not able to make the device do anything. The code is there but mostly for testing atm. I have returned the ComfoSense device and bought a ComfoConnect KNX C bridge and will try to find some time to make another try to find out how it works. I'm totally open for ideas and would be glad if you would contribute something. |
I will see if I can find some logs from the traffic I recorded. |
|
I updated the readme with some information about how to execute the code. If you have any questions don't hesitate to ask. |
Thanks for that, I had to figure it out from reading the code :) I've been able to use the mapping.py for a different software that will output a json file with all the latest sensor data. I'm using the USBtin as well, but I'm using the SocketCAN interface in linux, which allows me to use standard candump and cansend methods to inject packets. When I send the sequence for changing the ventilation level:
Nothing happens. It seems to me the 'iterator' is actually the ID of the device sending the request, which are listed nicely in the protocol.md of michaelarnauts/comfoconnect:
You have listed in mapping.py the reference to T1F055051 as well as T1F075051, which makes sense considering you had both the ComfoConnect LAN C and the ComfoConnect KNX C. Now it seems to me for the ComfoAirQ to accept commands, first a kind of handshake or identification has gone on. I've tried the following which seems to trigger something of that sort. Now when I inject the same kind of ping like this: I get back:
So it seems this triggers something in the ComfoAirQ. But I'm not sure what to send next, hence a log would be nice :). Especially if you could get one right from bootup of the ComfoAirQ, so we can be sure any identification/initialization sequence is there. I'd appreciate it! Best regards |
The idea of the iterator potentially being an id is an interesting one. I usually saw the ComfoSense sending 1,3,5 and 7 as iterator value for subsequent commands. It always repeated but I couldn't make sense of it so far. I recorded messages for setting the ventilation level. You see the value regularly alternating without any visible reference.
|
hmmm, then it may be something else after all. Anyway, something funky happened yesterday evening, where the ComfoAirQ suddenly decided to change the codings... now it sends:
Somehow the last byte of the can_id has changed (and so my code does not function anymore...) Did something like this ever happen to you? Best regards |
@marco-hoyer, did you have a chance to track down those logs? It'd be really helpful! By now the data changed again and I'm now getting 19 and 59 as last bytes of the can ID. |
@djwlindenaar did you have any progress with this? |
Yes I have :) I've been reverse engineering the firmware for the comfoair Q and that has given some insights. Although it is quite limited, since of course all symbols were stripped from the firmware. Basically I found out that this ComfoConnect Lan product is not much more than a LAN2CAN bridge with some session management. Most of the commands for the ComfoConnect translate directly to CAN messages. So the CAN messages starting with 0x1Fxxxxxx are the commands. And indeed, @marco-hoyer was right, there's a sequence number which allows to link responses to commands. The format is:
I've not yet figured out the two bits called A8000 and A10000. The first two addresses are the addresses of devices on the bus. This is by default determined for each device sold by Zehnder, but I found out the when you send a message with the same SrcAddr as the ComfoAirQ, it will pick a new random address. Probably to avoid collision? or maybe this allows multiple units on a single can bus. Then the content of the message is structured like this: CmdUnit is the submodule which Cmd is targeted to:
Then the Cmd meaning depends on this subunit. F.e. for the Schedule unit (0x15) we have:
Then the data is defined by the Cmd and CmdUnit. For example for timers, I found this list:
Now we can assemble a command to turn off the inlet fan for one hour:
which decodes as:
Or to disable the timer and return to normal operation
There's still a lot to document, which I'm not so fond of, so always loses from figuring out the next item... I have a little python code which is far from complete/finished/usable, but I could put it up if you like. Best regards |
Ok so you can actually send commands and they are accepted by the unit? That is great to hear. And yes please, if possible I would like to get the code. I still need to mount my Q350 and order can-to-usb adapter, so that will probably take a month until i can play with it... |
Hm but aren't commands the same as described here? https://github.com/michaelarnauts/comfoconnect/blob/master/PROTOCOL.md ? So if you would like to set fan speed to 3 you would send: Or am I missing something? |
Yes I can send commands and they are indeed accepted. They indeed closely resemble the commands to the comfoconnect Lan device. Some padding is required, but other than that it's the same. |
That is really great, fantastic job. Already ordered can-to-usb adapter, and waiting for the code :) |
Hey @djwlindenaar so today my can adapter arrived. I now can read the messages on CAN bus, but with other library :) maybe you have more mappings than defined in this library? I'm interested in extract air temperature |
ok, I managed to map all temperature and humidity values, afaik some mappings in What is strange is that some values arrive with different ids, e.g. I also don't see any correlation between ids and comfoconnect protocol, e.g. And that chinese CAN adapter is crap... almost zero protocol documentation, some hakish way to make it work on linux, and I get a lot of garbage in between CAN packets, at least if the reverse engineered protocol spec is correct, so probably I'll have to go with usbtin :/ |
I just forked this repository into djwlindenaar/zcan. And committed my scripts. Have a look at those. It contains some hints as to what you're referring to... Especially have a look at mapping2.py and how it's used in e.g. testcan.py. This stuff is still very hackish and geared specifically for my personal use, but we probably should invest a bit to get it to a more useful and shareable state... I use the usbtin and it's stable/great. BR |
COB-ID 001DC041 is related to pdid 119: |
Actually 119(dec)<<14 = 001DC000 |
Cool, thanks for the code. mapping2.py looks really extensive. Readonly mode with the chinese adapter works fine. Now I somehow must figure out how write to the ComfAir :) Now looking at the example code in sendmsg.py if I would like to set venilation mode to Auto I would send: Or am I missing something? Edit: yes, all good. I'm able to set this to auto by using the chinese provided windows software, so something is wrong with my linux implementation:) |
Looks about right. I believe the 0x85 command really means 'disable timer'. And that results in auto mode if all timers are disabled. I think it should be possible to manipulate the configuration through the pdo's but haven't yet figured that out... |
yeah, got that short one working. Now comes the splitting:) Can you elaborate more on the data split pattern? why are you adding changing first byte of the data array? protocol spec? And which one is the correct one to change ventilation level? in sendmsg.py I see |
The first one should work. The 03 is the level. The 00,1C,00,00 is the time (0x00001C00 s). |
The second one set the bypass... |
Wow, I noticed recently that I had an expired email address in my GitHub profile. I didn't realise what happened here and now I'm super exited about your progress. Still trying to successfully send some commands... :-). I started work on a Golang implementation of the existing code with your improvements and some more features. Will share a link once it is uploaded. I recently found out that socat is an awesome utility to forward serial connections via TCP which massively simplifies development and testing for me. |
Say I want to set the ventilation level to 1. My ComfoAir also has id 1 and I have chosen 42 as source id and 3 as sequence number. This brought me to CAN ID: Sending this data distributed amongst 3 datagrams like this:
Does this make sense to you? I don't see anything happening at the device. When I sniff messages sent from my ComfoConnect KNX C device changing ventilation level looks like this: for level 3
for level 1
|
Hi @marco-hoyer, good to have you back :) I'd have to check, but that'll be next weekend. I noticed that sometimes less padding is needed, but it also does not hurt to have a too long message. Too short hurts, though. I'm wondering whether 42 as source ID might be too high. I'd need to check about the number of bits available for ID or whether there may be a filter on the ID... Maybe you should try using the same ID as the comfoconnect..? |
I tried with ID 11 and a variation of the messages I sniffed from the ComfoConnect KNX c box which worked for 3 consecutive calls and then stopped working again. Maybe because of the sequence number not being altered. Did you understand the mechanics behind this sequence number? Can I choose any? Do I need to change it from one command to another? The messages I sent:
(where 03 at the very end is the ventilation level) |
I haven't checked, but the sequence number is certainly part of the reassembly process for multiple message split. Also it is used for preparing the actual change in the system as well as the reply to acknowledge the communication. You may be running into a race condition by not changing the sequence number..? |
May it be that you have an ID conflict and your ComfoAir device has chosen a different ID after restart? |
hey @marco-hoyer thanks for the reply. My code should use 0x11 as source ID. But the problem is that I don't receive anything on the bus. (Well to be honest, sending does not work as well). |
Also, when the code starts i don't send anything on the bus. I just set the code to listen and eventually send a message when a command arrives. Maybe it requires a "Start" command somehow? |
Ok note to self. Check for commented stuff. Apparently i had commented out from my code the |
For those of you interested i also did an implementation with esp32 and a 3d enclosure here: https://github.com/vekexasia/comfoair-esp32 |
Hi to all! I'm replicating https://github.com/vekexasia/comfoairq-mqtt First of all, I want to know: How should be blink the LED on board of Comfoair?
And How should be blink the LEDs on USB-CAN? |
I solved checking cable wiring. LED lights fixed.
|
In case it is usefull for somebody, here is a small function to convert CAN ID's to PDO ID's and visa-versa. def pdo_to_can(pdo, node_id=1):
"""Convert a PDO-ID to a CAN-ID."""
return ((pdo << 14) + 0x40 + node_id).to_bytes(4, byteorder='big').hex()
def can_to_pdo(can, node_id=1):
"""Convert a CAN-ID to a PDO-ID."""
return (int(can, 16) - 0x40 - node_id) >> 14
print("00454041 = %s" % can_to_pdo("00454041"))
print("00458041 = %s" % can_to_pdo("00458041")) returns
I'm documenting more PDO's here: https://github.com/michaelarnauts/aiocomfoconnect/blob/master/docs/PROTOCOL-PDO.md |
Hello, the links for the aliexpress adapters are invalid. Can you indicate which one you test and how to connect these 3pins adapters to the 4pins connector of the zehnder unit? Thank you |
hey @xavan83 i'd suggest you to take a look at https://github.com/vekexasia/comfoair-esp32 |
I am not confident about building this adapter by my self. |
Can you explain how to plug a 3pins adapter to a 4pins zehnder connector? Where to find the 4th "power" pin? |
@xavan83 ,
so: black GND |
Hi all, Great job on figuring out how to communicate with the ComfoAir! I was wondering, did anyone try to do the same with the Zehnder Option Box that enables use of a lot of external sensors? I figured it would be great to replicate Option Box functionality for domotics use. One could for example use existing CO2 sensor ppm value and translate this to a 1-10V value that the Option Box normally sends to the ComfoAir. This would enable CO2 controlled ventilation demand. I have sniffed the startup comms between Option Box and ComfoAir with a U-CAN, candlelight and CANgaroo as a start, but my reverse engineering skills are a bit rusty. Anyone interested in pursuing this together? |
So I've tried to get familiar with the protocol since my last message. I've isolated all communication from Option Box (address 2) to ComfoAir Q (address 1). This is what I think is relevant:
There's some sort of handshake going on in the 100?000?x messages. I've added a potentiometer to the first 1-10V input during capture, this corresponds with the 804042x messages. The capture shows a lot of messages to this address as I turn the pot over the 38sec of capture time. Quick python script identifies the following mapping:
When I have time again I want to try and emulate the option box and send sensor data myself. From the discussion above and information I could find I could not find much information on the handshake that occurs. Any more information on that that I missed maybe? |
Hello, I'm following this post as I have a CONFOAIR 180 as looks like the pinouts are exactely the same. |
You probably have a unit with serial interface. Give this a try: |
Just to add I am also trying to do this. My main goal for the moment is to emulate the Boost zero-volt contact. So far I can get it to work by connecting up the existing option box to do the handshake, and then quickly swap over the CANBus before it notices... Once that's done my code is able to keep the connection alive and emulate the contact as expected, but obviously I want to be able to do the full handshake directly! Just wondering if you ever got any further with it? |
I think that no one has publicly documented the handshake before. Maybe you could capture the handshake with candump or wireshark and upload it? We currently do not have the need for an optionbox or a LAN C, therefore I can not try it myself... |
Yes this is the problem I have! I've been using a CANBus adapter on an Arduino to do all my experiments, so I'll have a go at capturing the handshake. I will readily admit I don't fully understand the IDs etc so any pointers are greatly appreciated. |
Does the handshake message change every powerup? |
I don't think so - but the problem is I only have access to one unit for testing, so if it varies between units, systems etc it'll screw stuff up! |
There's not much to permanently screw up I think. Especially with the optionbox. |
So far I've determined that the option box sends back data regardless of the handshake, so it seems very likely that it doesn't care about it at all. That's how I discovered the correct ID etc to keep the connection alive & trigger the boost - connected the Option box directly to my arduino & powered up seperately. It happily pings away. It therefore seems possible that the handshake message is something like a version number...? In any case I'm very much hoping that means it won't ever change. |
It seems that my comfoair died. It does the startup sequence, fans are on, display is not working and then it stops and green light on top keeps blinking. Is it possible to check the error codes somehow? |
Haven't figured out a way to check error codes. I guess we need someone with a LAN-C box and a sniffer on the can bus for that. |
for me it was a faulty sensor, having the ability to read error codes would have probably saved some money in service labor cost :) But oh well, good that at leas there is some control |
Hi,
I'm very happy with the code you've put up, since I'm trying to connect my comfoair-q 450 to my home automation using CAN. I've already figured out some more can messages ( have to double-check before I will upload), but the basis you've provided is great.
How did you figure these out? Did you have something to sniff? If so could you share that data?
Especially I'm still trying to figure out how to control anything on the system. When I send the command to change the bypass setting, nothing happens.
Is there something like a handshake needed or..?
I'd love to get some help and once I get things working contribute back to the project as well.
Best regards
Daniel
The text was updated successfully, but these errors were encountered: