data format (THZ 303 SOL) of set-points ("Soll-Werte")

Asked by alphaomega

Hello,

I have analyzed the data transmitted (TX) and received (RX) between my Macbook and my THZ 303 SOL (v2.16) and found the following (further details also in German here: http://www.haustechnikdialog.de/Forum/Default.aspx?t=85548&p=1309225) information... Please note that all numbers are hexadecimal, i.e. 0x... These data were monitored after clicking the "Lesen" ("Read") button of the original Windows software which then displayed all "Soll-Werte" (set-points), i.e. no "Ist-Werte" (current values of the heatpump), but for a start this was quite interesting to analyze.

(TX) 02 START OF COMMUNICATION

(TX) 01 ??
(TX) 00 ??
(TX) 18 ??
(TX) 17 ??
(TX) 10 ??
(TX) 03 ??

(RX) 10 ACK
(RX) 02 START OF COMMUNICATION

(TX) 10 ACK

(RX) 01 ??
(RX) 00 ??
(RX) 41 ??
(RX) 17 ??

In words: When clicking the "Lesen" ("Read") button of the original Windows software for this heatpump (THZ 303 SOL), the communication is initiated by sending (TX) 0x02 (START OF COMMUNICATION), 0x01, 0x00, 0x18, 0x17, 0x10 and 0x03. I do not yet know what these other 6 bytes mean.
Then two bytes are received from the heatpump (RX) by the software: 0x10 (ACK) and 0x02 (START OF COMMUNICATION).
The software in turn acknowledges this by sending (TX) 0x10 (ACK) to the heatpump.
Again, four unknown bytes are received in turn. And here the fun part starts (remember: all are set-points ["Soll-Werte"])...

(RX) 00
(RX) D7 = 215 (21.5°C; P1)
(RX) 00
(RX) DC = 220 (22.0°C; P2)
(RX) 00
(RX) 64 = 100 (10.0°C; P3)
(RX) 01
(RX) C2 = 450 (45.0°C; P4)
(RX) 01
(RX) C2 = 450 (45.0°C; P5)
(RX) 00
(RX) 64 = 100 (10.0°C; P6)
(RX) 02 = 2 (P7)
(RX) 01 = 1 (P8)
(RX) 01 = 1 (P9)
(RX) 01
(RX) 5E = 350 (35.0°C; P10)
(RX) 01
(RX) C2 = 450 (45.0°C; P11)
(RX) 02 = 2 (P12)

Interestingly, this is followed by:

(RX) 10 (=16 in decimal = 16 values were sent by the heatpump - see above: 16 parameters incl. the 4 unknown bytes above)
(RX) 03 This seems to mean something like END OF TRANSMISSION, I believe.
(TX) 10 ACK
(TX) 02 START OF COMMUNICATION
(RX) 10 ACK

This design repeats again with other values (for P37 to P46 and P75), i.e. RX 0x10, 0x03 indicated that 0x10 (=16 in decimal) values (parameters) were sent from the heatpump, ended by an RX of 0x03 (END OF TRANSMISSION).

It would be very nice if others could also contribute to expand this knowledge. Thank you very much.
Best regards, alphaomega

Question information

Language:
English Edit question
Status:
Solved
For:
heatpumpMonitor Edit question
Assignee:
No assignee Edit question
Solved by:
VViki
Solved:
Last query:
Last reply:
Revision history for this message
Best VViki (viktor-volmut) said :
#1

Hello Alfaomega,

I also did some protocol analysis and from my point of view, whole protocol is following:

1. Communication starts with START COMM/ACK sequence:
Client sends START COMM : 02
Device sends ACK (indicates readyness): 10

2. Then client sends request. Each request has header (four bytes), optional data and footer:
    Request start: 01
    Read/Write: 00 for Read (get), 80 for Write (set)
    Checksum: ? 1 byte - sum of header (without checksum of course) and data (footer is not covered by checksum)
    Command: ? 1 byte - defines requested operation
    Data: ? length and meaning depends on Command, optional (for most Write operations, also for some Read)
    Footer: 10 03

3. Device Acknowledges receiving of requst with ACK: 10

Response is nearly the same (opposite roles):

4. Device starts communication, client have to acknowledge:
Device sends START COMM : 02
Client have to send ACK (indicates readyness): 10

5. Device sends response. Each response has the same structure as request - header (four bytes), optional data and footer:
    Header: 01
    Read/Write: 00 for Read (get) response, 80 for Write (set) response;
                                    when some error occured, then device stores error code here;
                                      actually, I know only meaning of error 03 = unknown command
    Checksum: ? 1 byte - the same algorithm as for request
    Command: ? 1 byte - should match Request.Command
    Data: ? only when Read, length depends on data type
    Footer: 10 03
6. Client have to ackowledge recepton of data with 10

Important note: before header and data are sent to device, it must be escaped with following rules:
 - each 2B byte must be completed by byte 18
 - each 10 byte must be repeated (duplicated)

Similarly, raw data received from device have to be de-escaped before header evaluation and data use:
 - each sequece 2B 18 must be replaced with single byte 2B
 - each sequece 10 10 must be replaced with single byte 10

Examples:

request:
when you want to send request with Command 0F, you prepare following data (four bytes header and two bytes footer):

01 00 10 0F 10 03

BUT you must to escape data and send following to device:

01 00 10 10 0F 10 03

device will respond with

01 00 10 10 0F 00 00 00 00 00

but you have to de-escape data before use:

01 00 10 0F 00 00 00 00 00
----------------------
Well, I believe, that communication protocol is common for all operations. So we have to talk about commands and appropriate data.

For data description, I use following prefixes:
 - i8 values are one-byte integers
 - i16 values are big endian two-bytes integers
 - f16.1 values are big endian fixed point numbers, real value = value/10
 - f16.2 values are big endian fixed point numbers, real value = value/100

I actually know following commands:

GetVersion (Read):

  Data type: FD
  InData: -
  OutData: f16.2_Version

GetDateTime (Read):

  Data type: FC
  InData: -
  OutData: i8_??? always 00
                   i8_DayOfWeek 0 = Mo
                   i8_Hour
                   i8_Minute
                   i8_Second
                   i8_Year Year = i8_Year + 2000
                   i8_??? always 00
                   i8_Month
                   i8_Day

SetDateTime (Write):

  DataType: FC
  InData: i8_??? always 00
                 i8_DayOfWeek 0 = Mo
                 i8_Hour
                 i8_Minute
                 i8_Second
                 i8_Year Year = i8_Year + 2000
                 i8_??? always 00
                 i8_Month
                 i8_Day
  OutData: -

GetCummulativeValues (Read):

  DataType: 09
  InData: -
  OutData: i16_CompresorRunningHours_Heating
                   i16_CompresorRunningHours_Cooling
                   i16_CompresorRunningHours_DHW
                   i16_ElectricalHeating_DHW
                   i16_??? (ElectricalHeating_Heating ??)
                   i16_???
                   i8_???

GetActualValues (Read):

  DataType: FB
  InData: -
  OutData: f16.1_SolarCollectorTemperature
                   f16.1_OutsideTemperature
                   f16.1_OutputTemperature
                   f16.1_ReturnTemperature
                   f16.1_HotGasTemperature
                   f16.1_DhwTemperature
                   f16.1_Output2CircleTemperature
                   f16.1_RoomTemperatre
                   f16.1_VaporizerTemperature
                   f16.1_CondenserTemperature
                   i8_ComponentsStatus (1 = running, 0 = stopped):
                               bit 0 - heating pump
                               bit 1 - DHW pump
                               bit 2 - ???? this bit is set to 1, when defrosting runs; probably heat pipe ventil ?
                               bit 3 - ???? this bit is periodically cycling between 0 and 1 when compressor is stopped; probably some ventil
                               bit 4 - compressor
                               bit 5 - electrical heating, 1. part, 2.6 kW
                               bit 6 - electrical heating, 2. part, 3.0 kW (1+2 = 5.6 kW) hypothesis
                               bit 7 - electrical heating, 3. part, 3.2 kW (1+2+3 = 8.8 kW) hypothesis
                   i8_??? - changed very often
                   i8_OutputVentilatorPercentualPower
                   i8_InputVentilatorPercentualPower
                   i8_MainVentilatorPercentualPower percent = i8_MainVentilatorPercentualPower/255 * 100
                   i8_????
                               bits 7, 6, 3 are nearly always set in my case
                               bit 5 is set approximately 30 seconds before defrosting starts
                               bits 0, 1, 2 are changed very often
                   i8_OutputVentilatorSpeed (revolutions per second, RPM = i8_OutputVentilatorSpeed*60)
                   i8_InputVentilatorSpeed (revolutions per second, RPM = i8_InputVentilatorSpeed*60)
                   i8_MainVentilatorSpeed (revolutions per second, RPM = i8_MainVentilatorSpeed*60)
                   i8_??? always 00
                   i16.1_OutsideTemperatureFiltered
                   i8_??? nearly always 00
                   i8_??? nearly always 00
                   i8_??? nearly always 00
                   i8_??? nearly always 00
                   i8_??? nearly always 00
                   i8_??? nearly always 00, 08 when device computes flux (see P87)
                   i8_??? nearly always 00
                   i8_??? 02 when heat is needed for heating
                   i8_??? 02 when heat is needed for DHW

------------------------
This is all, what I actually know. And with your knowledge (reading of P parameters), I am able to monitor and control nearly all aspects of device (writing of parameters works, I tried this already with Command 17).

When you will find something interesting, please contact me at e-mail (Viktor (dot) Volmut (at) bsc (dot) cz).
VViki

Revision history for this message
alphaomega (alpha-omega) said :
#2

Hi VViki,

thank you so much for your really interesting and very detailed information!
I am still struggling to use my own python test script (see below) to send the START COMM ('\x02') to my THZ, i.e. I never get some reply (the reply is 0 bytes long). But I am confident that I will manage this. And then - with your information posted above - it will be very interesting to explore more.

Do you also use python and pyserial to communicate with your heatpump? Which versions?
Which model of heatpump do you own? Which software version?
If you have some code which you could share, this forum here might be the right place. ;-)

Below is my python script to test the first initiation of the device (Tecalor THZ 303 SOL), connected to an RS232-USB-Adapter with FTDI chipset, which works perfectly with the original Stiebel Eltron software under Windows XP.
I have now tried the script with python 2.6.4 and 3.1.1 and pyserial 2.5-rc2 installed also for both python versions.
But as I wrote above, my THZ does not seem to respond after sending the hex code 02 to the device.

If you (or someone else) finds an error in my script, I would be very glad for some hints.

Again, thanks a lot for your kind and detailed feedback and my best wishes for all athletes at the Winter Olympics in Vancouver!

Best regards,
alphaomega

Test script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import serial

ser = serial.Serial (None) # set the serial device, but do not yet open it ("None")
ser.port = "\\.\COM5" # set port number (this could also just be "COM5" or 4 (because ports are numbered starting with 0)
ser.baudrate = 9600 # set baudrate to 9600
ser.bytesize=serial.EIGHTBITS # set bytesize to 8 bits
ser.parity=serial.PARITY_NONE # set parity to None
ser.stopbits=serial.STOPBITS_ONE # set stopbits to 1 bit
ser.xonxoff=0 # set software flowcontrol to 0 (=disabled)
ser.rtscts=0 # set hardware flowcontrol to 0 (=disabled)
ser.interCharTimeout=None # set inter-character timeout to None (=disabled)
ser.timeout = 0 # set timeout to 5
ser.open () # open serial port with above parameters

# initiate communication
send = ser.write ('\x02') # send hex value 02 to device

# read and print 1 byte
received = ser.read (1) # read 1 byte from device (should reply with hex value 10)
print "status:", repr (received) # print reply from device in form of hex code (therefore use of repr)
print "status:", len (received) # print length of reply from device (should be 1 byte)

# HERE I HAVE A PROBLEM: The reply from the device is 0 bytes long, i.e. no reply at all?

if received == '\x10': # device should reply with hex value 10 (but it does not, see PROBLEM described above)
 print "# ACK"

# close port
ser.close ()

Revision history for this message
alphaomega (alpha-omega) said :
#3

PS - Now it worked!
I had to change the timeout from 0 to 5. Zero was obviously wrong/ too short. ;-/
Still, I would be interested in some further python code, if someone has some in addition to the really useful scripts of heatpumpmonitor 0.4.

Best regards,
alphaomega

Revision history for this message
VViki (viktor-volmut) said :
#4

Hello Alfaomega,

"Real Programmers Don't Use Pascal" :-)... maybe, I am not a real programmer, but I dont use Python too, I am C/C++ programmer, so I wrote small C++ application to monitor and control my heat pump (I built my own house two years ago and I plan to control heating in much more sophisticated way in future... you know, servos, many temperature sensors etc ;-)).

I own Stiebel Eltron LWZ 303 SOL, firmware 2.16. Unfortunately, I don't have correct version of service application (I received version 5.10, which supports firmwares 3.07 - 4.49), so it is not so simple to do analysis of communication for me (by the way, didn't you have some older service application? If yes, can you send it to me please?),

To code share - maybe later, I started to work on analysis and monitoring utility a week ago, it is too much immature now (though it is already able to estimate actual device power drain and power output from monitored data).

As I wrote, I don't use python at all, so I am not able to help you with it. Also, I am connected directly through RS-232 port (COM1) on my old notebook (it is from year 1999, but is able to run Windows XP and has power drain only 12 W... perfect device for house control), which can be substantial difference, if there is some timing issue.

Back to your python script - though I don't know python, usually, when read operation returns different number of bytes than requested, then there was some problem; in case of serial communication, it can be timeout. Please check it in python's documentation.
Or - which will be more effective - try to ask Robert Penz, he is using python for communication with heat pump, you can also see source code of his heatpumpmonitor (which is open source)...

Best Regards,
VViki

Revision history for this message
VViki (viktor-volmut) said :
#5

Alfaomega, I wrote my answer to long for your fast progress :-)... It was really timeout issue... I am glad, you are found the problem source :-)....

Best Regards,
VViki

Revision history for this message
Steff (shb1999) said :
#6

VViki,

are you sure about the i8_* values in the GetActualValues Block? I think there should be some i16 values, especially the ventilator values? The heatpump is returning more than 50 bytes, so there should be some more or at least some bigger values ;)

I'm surprised about the service application you mentioned. My THZ 303SOL has the firmware 4.18 and the customer service told me, that there is no software available for this firmware revision. How did you get the software? Would it be possible to you to share it? I'd like to figure out some more protocol values for this revision, because not all commands mentioned above are working (e.g.0x17 doesn't work)...

Regards, Steff

Revision history for this message
VViki (viktor-volmut) said :
#7

Hello Steff,

for firmware 2.16, which I have, device returns 41 bytes. I checked each value, which I described, to values displayed directly by heatpump's regulator. For ventilators, two types of information is reported - percentual power and real revolutions per second and i8 has big reserve for both information types (255 revolutions per seconds gives you 15 300 r.p.m. - really impressive value for ventilators ;-) ).

Other firmwares can return more or less information - I think, Robert described most values for newer firmwares.

About 0x17 command - you are right, service application I have, uses totally different protocol to get parameters from heatpump (communication ends with error in my case because of old firmware), there are plenty (tens, maybe hundreds) of commands issued by application to get parameter values...

I think, I can send you service application 5.10 (I received it from service two weeks ago), please send me your e-mail to:

Viktor (dot) Volmut (at) bsc (dot) cz.

But I am not sure, if it supports firmware 4.18. There is one dialog in application, where you have to set firmware version. In it, here are listed approximately 20 different firmware versions and you have to choose from them. And I am not sure, if 4.18 is also there (actually I am not by computer with service application).

And which version do you have? Maybe you can send your (older) version to me :-) (Alfaomega still didn't send me anything :-((( )?

Best Regards,
Viktor

Revision history for this message
VViki (viktor-volmut) said :
#8

Steff,

I sent you my service application version, but it seems, that you have full mailbox:

Diagnostic-Code: smtp; 552 5.2.2 Over quota

Please get some space and let me know, I resend the file...

Best Regards,
VViki

Revision history for this message
alphaomega (alpha-omega) said :
#9

Hi Viktor,

I had sent an email to you, which you obviously did not receive. Can you please recheck?
Please make sure that your spam filter accepts emails from ... a t kabelmail dot de.

The software/ firmware you and Steff were talking about... I have firmware 2.16 in my THZ 303 SOL.
The software/ application is 4.08 I believe (I guess I had written it somewhere here in Launchpad).

Best regards,
alphaomega

Revision history for this message
alphaomega (alpha-omega) said :
#10

Thanks VViki, that solved my question.

Revision history for this message
Joao (joao-simoes) said :
#11

Dear all,

I've just saw your post which I find very interesting.
I have a THZ 303 SOL and I am trying to connect to it but I get nothing and I am not even sure that serial communication is established. I've tried with a Raspberry Pi and then with Realterm (on Windows 7).

I think the cabling is ok but, in any case, here's what I am doing:
The connector in THZ has three pins. From top to bottom I have:
- pin 1 (top of THZ connector) connected to pin 2 in DB9 connector (TX)
- pin 2 (mid of THZ connector) connected to pin 3 in DB9 connector (RX)
- pin 3 (bottom of THZ connector) connected to pin 5 in DB9 connector (GND)

Could you please help me with the basics:
1) Is the pinout correct
2) Can you provide some small tool which allows me to connect to the machine and actually get something

Thank you very much in advance.
regards
Joao