HVAC - ClimateTalk Protocol

Many new HVAC systems being installed today, at least in north america are using and open protocol called ClimateTalk rather then the 5 - 7 wire 24 volt system. I am looking for someone who is interested in writing a ClimateTalk binding for OpenHAB. The hardware is simple, all you needs is a RS485 to RS232 adapter to read / control multi-stage HVAC system.

The standard can be found at: http://www.climatetalkalliance.org/ClimateTalkTechnology/SpecDownload.aspx

At first I am just looking for something that can read the protocol and tell me whats going on with my 4 stage heat / 2 cool system, but in the future I would like to also be able to control the system.

Did the ClimateTalk/Comfortnet support have any progress?
Iā€™ve been playing around with this protocol over the break. I have a Python version logging the activity.
Would this be of use to anyone?

1 Like

Yes!! can you share along with and example of the output?

Here is a link to my Dropbox folder items for the Python code and Journal file.


The output example is in the bottom of the journal file.
I just spent a few days looking into this protocol. It follows the spec pretty good.

1 Like

I used a US Converters RS485/Ethernet adapter (P/N: XS1000)
I have two comfortnet systems:
Upstairs: 2stg gas furnace/2stg a/c
MainLevel: 2stg heat pump/2stg gas furnace/2stg a/c

I was playing around with generating some logging info on both systems.
I was able to obtain outside air temp, fan info, heatpump info, furnace info.
I stopped before I could get the indoor temp and the setpoint.
Youā€™d have to request that info from the thermostats. I was only doing the decode and didnā€™t do the encoding which has some message timing.
This program was my first Python app. Iā€™m an embedded programmer mostly in C.

As a quick diversion, I changed my main level system back to legacy/normal mode and installed a NEST a week ago to checkout the reporting. Iā€™m very unimpressed. It also doesnā€™t support a remote thermostat.

Iā€™m here if you need me. Iā€™m just getting started with the OpenHab stuff. Iā€™d like to get a setup running soon.

WOW! I am so impressed, canā€™t wait to test it out. I have 3 units, upstairs, main, and basement. All are like your main level with 2stg heat pump / 2stg gas furnace / 2stg a/c. Have you thought about turning this into a binding? I would like to be able to track status on all 3 of my units (including what stages they are at) and eventually control the system. My system is a bit unique because I have 21 HVAC zones in my house with 3 zone controllers controlling the 3 largest zones on each floor. The rest of the zones are all controlled with OpenHab.

Iā€™m not sure if Iā€™m smart enough to do a binding. Iā€™m not a Java guy.

Do you have time for a quick telco to discuss? Jeff, 816-407-7749

On conference calls all day :-(, I am not a programmer, but I may have access to a Java guy, I will check if he is free.

root@maggie ~ # python Listener.py 
connecting to 10.88.64.134 port 23
Traceback (most recent call last):
  File "Listener.py", line 23, in <module>
    pygame.display.set_mode((100,100))
pygame.error: Couldn't set console screen info
root@maggie ~ # 

So I did what every hacker does and commented out that line:

root@maggie ~ # python Listener.py 
connecting to 10.88.64.134 port 23
Press ESC in the black open window form to quit
Opening Socket
Sync Begin
00 00 13 43 54 33 30 30 7d 07 d4 d1 9f 9a c6 7c 10 a2 02 ff 02 00 00 00 a5 00 a0 11 00 00 00 09 10 04 1c 2b 50 02 8c f6 87 a0 09 8a a7 55 07 
sync finished
Decode Begin
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[1]  7D 07 D4 D1 9F 9A C6 7C 
2017-01-04 16:20:29  (00,00)  New MacID[1]  00 00 13 43 54 33 30 30 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
2017-01-04 16:20:29  (00,00)  New SessionID[5]  02 8C F6 87 A0 09 8A A7 
2017-01-04 16:20:29  (00,00)  New MacID[5]  00 00 09 10 04 1C 2B 50 
closing socket
2017-01-04 16:20:29  (00,00) 
Traceback (most recent call last):
  File "Listener.py", line 121, in <module>
    print ' '.join('{:02x}'.format(x) for x in command),
  File "Listener.py", line 121, in <genexpr>
    print ' '.join('{:02x}'.format(x) for x in command),
ValueError: zero length field name in format
root@maggie ~ #

So I am getting something, but it keeps crashing.

I forgot to mention, I had to install pygame on my system.

I used WinPython 2.7

I used that to allow me to exit the running python program.

Pygame is a gamer console that allows for keyboard entry.

Yep, got past that, but still see the other errors.

Iā€™m not much of a Python guy. I just got it to work on my windows machine.

There should only be one New MacID and one New SessionID entry per device. 5=thermostat for example.

Yours has a bunch, so I think memory allocation is different on your OS.

The closing of the socket could only happen when Pygame sends the ESC (0x1b) character to Python.

You may have to put a conditional statement checking for ā€˜commandā€™ to have zero length before the print statement on line 121.

I donā€™t have this running any more (for now). I converted my main level to Legacy mode and installed a NEST gen3 to see how it works.

You may become familiar with Python debugging before it works.

I only played with Python for 4 days to get this working. Nothing before this project. My mind may be a bit fuzzy on it.

Iā€™m trying to get a s/w release out for a customer. I wonā€™t forget. Iā€™ll look into it in a day or two.

Actually, I just tried it and connected to your public IP.

I got about the same results. I look into it soon.

Thanks! Let me know what you charge an hour, happy to pay you for your time.

Now need. It looks like you have at least 2 thermostats on the same network. I didnā€™t account for that case.

Grab the current version from my dropbox. See what it does.

Looks good on this end.

Itā€™s a lot different than mine. Iā€™m surprised by all the fan control requests.

Getting the same ā€œzero length field name in formatā€ errors. I only have Linux boxes, but I guess I can try a VM with Windows and see if that helps. What sort of output do you get from my system? I am getting:

root@maggie ~ # python Listener.py
connecting to 50.246.121.173 port 8023
Press ESC in the black open window form to quit
Opening Socket
Sync Begin
30 30 7d 07 d4 d1 9f 9a c6 7c 10 a2 01 ff 02 00 00 00 a5 00 a0 11 00 00 00 09 10 04 1c 2b 50 02 8c f6 87 a0 09 8a a7 71 eb 
sync finished
Decode Begin
2017-01-04 20:31:29  (00,00)  New SessionID[1]  7D 07 D4 D1 9F 9A C6 7C 
2017-01-04 20:31:29  (00,00)  New MacID[1]  00 00 13 43 54 33 30 30 
2017-01-04 20:31:29  (00,00)  New SessionID[5]  05 43 03 B2 3B 82 BC 8D 
2017-01-04 20:31:29  (00,00)  New MacID[5]  00 00 09 0F 06 16 28 11 
closing socket
2017-01-04 20:31:29  (00,00) 
Traceback (most recent call last):
  File "Listener.py", line 123, in <module>
    print ' '.join('{:02x}'.format(x) for x in command),
  File "Listener.py", line 123, in <genexpr>
    print ' '.join('{:02x}'.format(x) for x in command),
ValueError: zero length field name in format
root@maggie ~ #

Did you get my 5:46pm email. That was from your system.

Got it! Turns out that error is because of a change in Python 2.7! Upgraded Python and it now works! Tomorrow I will see if my Java friend can make a binding out of it.