marco-hoyer / zcan

API proxy for Zehnder ComfoAir Q series devices with CAN bus interface
31 stars 7 forks source link

Controlling the comfoair-q using CAN #1

Open djwlindenaar opened 6 years ago

djwlindenaar commented 6 years ago

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

marco-hoyer commented 4 years ago

@decontamin4t0R Thanks for the update. As soon as I have some time I will pick this topic up again. Your docs seem to be very helpful.

decontamin4t0R commented 4 years ago

@marco-hoyer I have more findings, but most of them are in my head or in a unstructured note... If you have any question about some propertys/commands/pdos, please ask them :)

andiwand commented 4 years ago

hey! did anyone of you succeed in setting the vent level for example over can? i tried to understand your post @decontamin4t0R but couldn't figure out what you mean with the # in 1F015057#0084150801000000 and why you need two commands to set manual mode. thanks for all your effort so far! reading the values works like a charm.

decontamin4t0R commented 4 years ago

The # is a seperator between the can id and the message itself, in that example the complete message is: id = 1F015057 and message bytes = 0084150801000000. As for the second: First you sent two can messages to set the timer for manual mode. This means that certain protection features are deactivated if configured as auto-only. Then, you send two can messages to set the timer for the desired ventilation level. You can also directly send the two messages without setting to manual, however the ventilation level is likely to be overwritten very fast.

The commands each need two messages because can only allows for 8 bytes within one message, and that is not enough. For the fragmentation part, check out the .md's in michaelarnauts/comfoconnect.

vekexasia commented 3 years ago

Nice project i just stumbled upon today. I've a Q 350 and i'm interested in integrating my module to Home Assistant. If i'm not mistaken though this library cannot "send write" messages to the unit hence only being able to read the current informations.

Is it correct or did I miss something in this issue?

decontamin4t0R commented 3 years ago

This is correct; if it is possible for you you can add it using MQTT (https://github.com/decontamin4t0R/zcan zcan_mqtt_bridge.py). In our home, we implemented some basic commands using manual shell scripts and cansend, because we do not want to interfere with it too much (we can set the comfocool profile and level) You could extend the above repo to include command sending.

If you have any question regarding the protocol or the repository, feel free to ask.

vekexasia commented 3 years ago

@decontamin4t0R thanks for your info. I'll head over there. The goal was for me to use something like a PI or a esp32 to have the ability to get informations feeded into home assistant as well as some basic controls such as set ventilation level.

I suppouse esp32 is way too big for me (in terms of time) to get it done so maybe PI would work. I just need to find a way to get USB PSU from above the comfoair.

gytisgreitai commented 3 years ago

I control mine through openHAB via mqtt with some cheap chinese usb adapter.

vekexasia commented 3 years ago

@gytisgreitai which one are you using ?

gytisgreitai commented 3 years ago

I have my own hacked-copy-pasted-solution based on this and resources on internet https://github.com/gytisgreitai/zehnder-can-mqtt . Forks fine enough for me

vekexasia commented 3 years ago

Sorry, I meant which can transceiver. I am planning to use the one on this repo README + a raspberry pi

gytisgreitai commented 3 years ago

https://www.aliexpress.com/item/32966467821.html

vekexasia commented 3 years ago

Ok I've written my own implementation trying to better understand how this thing works.

So far i've been able to read basically everything that has been exposed as depicted in the mqtt screenshot below: image

I am currently using the serial interface as @marco-hoyer here and @gytisgreitai in his own repo. So far I've been unable to send anything on the comfoair. I mean, information go through but It does not update the status.

I noticed that @gytisgreitai and @decontamin4t0R approach to sending stuff differ. For example: @gytisgreitai 's approeach to "set ventilation level to 0" is sending ->

aa:e8:91:50:01:1f:00:84:15:01:01:00:00:00:55
aa:e7:91:50:01:1f:81:00:01:00:00:00:00:55

while @decontamin4t0R sends

91:50:01:9f:08:00:00:00:00:84:15:01:01:00:00:00
91:50:01:9f:07:00:00:00:81:00:01:00:00:00:00:00

to my limited knowledge it looks like there is a problem in the later encoding length.

I tried both approaches and none of them seems to work (both using your code guys and mine).

Also it seems that the 2 approaches encode "data" length differently. And 0xaa is prepended with a tail of 0x55 for the first example. I am unable to understand why that is the case. My setup not working is probably due to the fact that I am still also unsure what srcAddr, dstAddr and addr are.

decontamin4t0R commented 3 years ago

The source ID is not really relevant, make sure that you do not use the id of the ventilation, otherwise it will change its ID. The destination ID is the ID of the ventilation, It is usually 1, you can check this by ANDing the PDO-ID with 0x3F. I do not know what the addr is you mention, or where you found it.

I think the difference is the result of different encodings of CAN packets themselves, not the actual data. If you compare the lines themselves, both contain 00:84:15:01:01:00:00:00 and 81:00:01:00:00:00:00, which are the data of the two can packets. As the actually intended RMI command is 0x84, 0x15, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, which is 15 bytes (longer than 8 bytes) you need to do the following:

Hope this helps :)

vekexasia commented 3 years ago

Thanks @decontamin4t0R,

anyway i posted my node.js implementation. I believe several mappings were missing from here. The integration also supports several commands: https://github.com/vekexasia/comfoairq-mqtt

THANKS all for the help!

decontamin4t0R commented 3 years ago

If I recall correctly, the commands should be: -- | -- 8415 0601 00000000 100e0000 01 | Set ventilation mode: supply only for 1 hour 8515 0601 | Reset supply only mode 8415 0701 00000000 100e0000 01 | Set ventilation mode: exhaust only for 1 hour 8515 0701 | Reset exhaust only mode

The 84 is a Set Timer Command, while the 85 is a Delete Timer COmmand

vekexasia commented 3 years ago

I can confirm the above works perfectly.

decontamin4t0R commented 3 years ago

nice to hear :)

vekexasia commented 3 years ago

All of a sudden it does not work anymore. I can no longer receive anything. Is it some faulty hardware or maybe i somehow initialized the canbus node and that has been working till today (I had a power surge so the comfoair (and rpi) was shut off).

vekexasia commented 3 years ago

Oyut of curiosity does anyone know the baudrate of the bus?

marco-hoyer commented 3 years ago

Oyut of curiosity does anyone know the baudrate of the bus?

The CAN baud rate should be 50k

marco-hoyer commented 3 years ago

All of a sudden it does not work anymore. I can no longer receive anything. Is it some faulty hardware or maybe i somehow initialized the canbus node and that has been working till today (I had a power surge so the comfoair (and rpi) was shut off).

May it be that you have an ID conflict and your ComfoAir device has chosen a different ID after restart?

vekexasia commented 3 years ago

hey @marco-hoyer thanks for the reply.

My code should use 0x11 as source ID.

https://github.com/vekexasia/comfoairq-mqtt/blob/a7f8cf6db23697cbf8da69e1dce7335277584d32/src/index.ts#L78-L84

But the problem is that I don't receive anything on the bus. (Well to be honest, sending does not work as well).

vekexasia commented 3 years ago

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?

vekexasia commented 3 years ago

Ok note to self. Check for commented stuff. Apparently i had commented out from my code the S2\r and 0\r code. So the usbtin never initialized itself.... :facepalm:

vekexasia commented 3 years ago

For those of you interested i also did an implementation with esp32 and a 3d enclosure here: https://github.com/vekexasia/comfoair-esp32

image

vespadj commented 3 years ago

Hi to all! I'm replicating https://github.com/vekexasia/comfoairq-mqtt I connect the USB-CAN of @marco-hoyer , @gytisgreitai and @vekexasia (first prototype) like https://www.aliexpress.com/item/32966467821.html Under Linux, I open the Port /dev/ttyUSB0, so comfoairq-mqtt at startup log me "Serial Port open!" but nothing happen to ComfoAir when I send message.

First of all, I want to know: How should be blink the LED on board of Comfoair? On mine:

And How should be blink the LEDs on USB-CAN?

vespadj commented 3 years ago

I solved checking cable wiring. LED lights fixed.

J101:
red 12 V dc
black GND
yellow CAN_H
white CAN_L
samezrp commented 2 years ago

Hi vekexasia, Would you mind helping me? I checked all cabling, all looks OK, I get following messages and there is no communication: image I nave AERISNext recuperator, but it should be the same as Zhender. How can I check what is on CAN bus? This CAN Forced Reset came in when I un-commented following line in code: CAN0.setDebuggingMode(true);

edit: Is there anyone who in fact managed to run this esp32 stuff? After a while I run djwlindenaar's zcan and managed to give boost command and some others, I did not managed to communicate with esp at all :/

michaelarnauts commented 1 year ago

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

00454041 = 277
00458041 = 278

I'm documenting more PDO's here: https://github.com/michaelarnauts/aiocomfoconnect/blob/master/docs/PROTOCOL-PDO.md

xavan83 commented 6 months ago

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

vekexasia commented 6 months ago

hey @xavan83 i'd suggest you to take a look at https://github.com/vekexasia/comfoair-esp32

xavan83 commented 6 months ago

I am not confident about building this adapter by my self. I prefer an "all-in-one solution"

xavan83 commented 6 months ago

Can you explain how to plug a 3pins adapter to a 4pins zehnder connector? Where to find the 4th "power" pin?

vespadj commented 5 months ago

@xavan83 ,

I solved checking cable wiring. LED lights fixed.

J101:
red 12 V dc
black GND
yellow CAN_H
white CAN_L

so:

black GND yellow CAN_H white CAN_L

p5y commented 2 months ago

Hi all,

Great job on figuring out how to communicate with the ComfoAir! It's awesome to be able to read statistics from the unit with the projects that built on the information in this thread.

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?

p5y commented 2 months ago

So I've tried to get familiar with the protocol since my last message. Tried to figure out what messages I captured on the bus. Went through the available documentation and some code.

I've isolated all communication from Option Box (address 2) to ComfoAir Q (address 1). The ventilation unit sends a lot of general status info to the option box that I think it doesn't care about, so I'm ignoring for now. Let's hope it doesn't bite me later.

This is what I think is relevant:

0.000000 Start of measurement 0.000000 1 10080001x Rx d 4 80 61 6A 6E 0.083722 1 10080002x Rx d 4 CF 9A 0F 53 2.084196 1 10040002x Rx d 0 2.085940 1 804042x Rx d 2 89 59 2.087738 1 808042x Rx d 2 0C 00 2.089529 1 80c042x Rx d 2 00 00 2.091351 1 810042x Rx d 2 00 00 2.093110 1 824042x Rx d 2 00 9D 2.094911 1 828042x Rx d 2 00 9D 2.096665 1 82c042x Rx d 2 00 9D 2.098301 1 814042x Rx d 1 00 2.099918 1 818042x Rx d 1 00 2.101539 1 81c042x Rx d 1 00 2.103159 1 820042x Rx d 1 00 2.105356 1 10000002x Rx d 4 04 01 00 00 2.107416 1 10040001x Rx d 4 E7 2B 2C 2D 2.110568 1 804042x Rx d 2 89 59 2.115225 1 808042x Rx d 2 0C 00 2.117022 1 80c042x Rx d 2 00 00 2.120263 1 810042x Rx d 2 00 00 2.124861 1 824042x Rx d 2 00 9D 2.126650 1 828042x Rx d 2 00 9D 2.162488 1 82c042x Rx d 2 00 9D 2.164122 1 814042x Rx d 1 00 2.165738 1 818042x Rx d 1 00 2.167364 1 81c042x Rx d 1 00 2.168978 1 820042x Rx d 1 00 2.171116 1 10000001x Rx d 4 01 01 01 64 2.174157 1 44042x Rx d 1 00 2.373307 1 604042x Rx d 2 00 00 2.379685 1 644042x Rx d 1 00 2.387860 1 688042x Rx d 1 C4 2.426414 1 804042x Rx d 2 89 59

There's some sort of handshake going on in the 100?000?x messages. When the handshake is (partially?)completed, the option box sends the current status.

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:

804042 src = 2 dest = 1 mapping = 513 808042 src = 2 dest = 1 mapping = 514 80c042 src = 2 dest = 1 mapping = 515 810042 src = 2 dest = 1 mapping = 516 824042 src = 2 dest = 1 mapping = 521 828042 src = 2 dest = 1 mapping = 522 82c042 src = 2 dest = 1 mapping = 523 814042 src = 2 dest = 1 mapping = 517 818042 src = 2 dest = 1 mapping = 518 81c042 src = 2 dest = 1 mapping = 519 820042 src = 2 dest = 1 mapping = 520 44042 src = 2 dest = 1 mapping = 17 604042 src = 2 dest = 1 mapping = 385 644042 src = 2 dest = 1 mapping = 401 688042 src = 2 dest = 1 mapping = 418

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?

samumar82 commented 1 month ago

Hello, I'm following this post as I have a CONFOAIR 180 as looks like the pinouts are exactely the same. Would love to try this project on an ESP32 C3. Actually the machine is connected via cables to the COMFOSENSE display from which I can regulate the fan, program timings etc. There are 4 pins, I believe 12V, GND, RX and TX. Do you think it is safe to wire like described here in parallel with the COMFOSENSE interface and try this code? Anyone already tried on this unit?

p5y commented 1 month ago

You probably have a unit with serial interface. Give this a try: https://github.com/adorobis/hacomfoairmqtt