-
Notifications
You must be signed in to change notification settings - Fork 9
3220: OpenTherm Message
OpenTherm protocol-compliant messages are regularly exchanged between the controller and the OpenTherm Bridge (R8810A1018).
060 RQ --- 01:187666 10:138822 --:------ 3220 005 0000120000
058 RP --- 10:138822 01:187666 --:------ 3220 005 00401201EE
060 RQ --- 01:187666 10:138822 --:------ 3220 005 0080130000
058 RP --- 10:138822 01:187666 --:------ 3220 005 00C0192300
Such payloads comply with the OpenTherm protocol, and are not discussed in detail here, see instead: https://www.domoticaforum.eu/uploaded/Ard%20M/Opentherm%20Protocol%20v2-2.pdf
All OpenTherm payloads are 5 bytes long; the first byte is ignored as the OpenTherm protocol specifies a 4 byte message.
segment | size | contents |
---|---|---|
unused | [0:2] | Always 0x00 |
msg_type | [2:4] | Message type, includes parity check |
data_id | [4:6] | Message identifier |
data_value | [6:10] | One 16-bit, or two 8-bit values |
The msg_type
will indicate the direction of the message (master-to-slave, or slave-to-master) and whether it is a read/write request, or a response to such. It includes a 1-bit parity check of the remaining message.
The most significant bit is the parity bit, and the next 3 bits are used for the message type. The 4 least significant bits should be 0 (this is the specification for OT v2.2, but is unknown for later versions of the protocol).
Note: in this context, the evohome controller is the master, and the OpenTherm bridge is the slave (and bridge also functions as a master to the boiler, but evohome is blind to this).
The data_id
(and msg_type
) will indicate how to process the data_value
. Note the value field could be one 16-bit data structure, or two 8-bit data structures called HB
(high byte) and LB
(low byte).
The data could be signed or unsigned integers, floats, or bit masks: refer to the protocol reference for more detail. For many messages, such as Read-Data
requests, the data_value
segment is not used, and will be 0000
.
From v2.2 of the OT specification, the following data IDs must be supported: 0, 1, 3, 14, 17 & 25; these messages include status, setpoint, temperature and modulation level data (note that this is the case, even if the corresponding data is not normally available for that system).
In addition, the following has been seen with the evohome OpenTherm bridge: 5, 15, 18-19, 26, 28, 56-57, 115-123, 127 (there is good evidence that other data IDs are supported). The following has also been seen, but are not included in the v2.2 specification: 113, 114 (these may be boiler-specific, or part of a later specification).
In Python:
def parser_3220(payload, msg) -> Optional[dict]: # opentherm_msg
assert len(payload) / 2 == 5
assert payload[:2] == "00"
# these are OpenTherm-specific assertions, first check parity bit
assert int(payload[2:4], 16) // 0x80 == parity(int(payload[2:], 16) & 0x7FFFFFFF)
ot_msg_type = int(payload[2:4], 16) & 0x70
assert ot_msg_type in OPENTHERM_MSG_TYPES # is it a known msg type
assert int(payload[2:4], 16) & 0x0F == 0 # valid for v2.2 of the protocol
ot_msg_id = int(payload[4:6], 16)
assert str(ot_msg_id) in OPENTHERM_MESSAGES
return {
"msg_type": ot_msg_type,
"data_id": ot_msg_id,
"data_value": ot_msg_value(payload[6:], ot_msg_id),
"description": OPENTHERM_MESSAGES[ot_msg_id],
}
Note that the detail of ot_msg_value()
is not included here.
OPENTHERM_MSG_TYPES = {
0: "Read-Data", # 0b.000....
16: "Write-Data", # 0b.001....
32: "Invalid-Data", # 0b.010....
48: "-reserved-", # 0b.011....
64: "Read-Ack", # 0b.100....
80: "Write-Ack", # 0b.101....
96: "Data-Invalid", # 0b.110....
112: "Unknown-DataId", # 0b.111....
}
def parity(x: int) -> int:
shiftamount = 1
while x >> shiftamount:
x ^= x >> shiftamount
shiftamount <<= 1
return x & 1
0001
RF Check0004
Zone name0008
Relay demand0009
Relay failsafe000A
Zone config000C
Zone actuators0016
RF signal test0100
Localisation0404
Zone schedule0418
System fault1030
Mix zone config1060
Battery state10A0
DHW setpoint10E0
Device info1100
Boiler relay info1260
DHW temperature12B0
Window sensor1F09
System Sync1F41
DHW mode1FC9
RF bind1FD4
Opentherm ticker22C9
UFH setpoint22D9
Boiler setpoint2309
Zone setpoint2349
Setpoint override2E04
Controller mode30C9
Zone temperature313F
System datetime3150
Heat demand3220
Opentherm message3B00
Actuator sync3EF0
Actuator info3EF1
Actuator unknown
0002
External sensor0005
Zone management0006
Schedule sync000E
Unknown01D0
Unknown01E9
Unknown042F
Unknown1280
Outdoor humidity1290
Outdoor temp12A0
Indoor humidity2249
Now/next setpoint22D0
UFH unknown22F1
Ventilation unit command22F3
Ventilation unit temp. high2389
Unknown2D49
Unknown3120
Unknown31D9
HVAC Unknown31DA
HVAC Unknown31E0
HVAC Unknown