Skip to content

0008: Relay Heat Demand

David Bonnes edited this page Jun 21, 2020 · 6 revisions

The 0008 packet is a 'call for heat' instruction from a controller, sent to a device which can provide heat (e.g. a boiler, or an electric radiator); usually via a relay such as a BDR91.

16:44:20.110 045  I --- 01:145038 --:------ 01:145038 0008 002 F924

16:45:30.322 045  I --- 01:145038 --:------ 01:145038 0008 002 FCC8
16:45:30.338 045  I --- 01:145038 --:------ 01:145038 0008 002 FAC8

16:47:15.437 045  I --- 01:145038 --:------ 01:145038 0008 002 FC00
16:47:15.449 045  I --- 01:145038 --:------ 01:145038 0008 002 FA00

Compare this with a 3150 packet, which is a request for heat from a sensor (e.g. TRVs, thermostats).

Usually the scenario is a BDR91 connected to boiler, but less common configurations would include a zone with a BDR91 which is used to control, for example, an electric heat source or a 3rd-party UFH system (as BDR91s can only handle small loads, a contactor will be required).

Payload Structure

These packets are always 2 bytes long and contain a domain ID and % demand.

segment size contents
domain_id [0:2] 0xF9, 0xFA or 0xFC, or zone_idx
demand [2:4] % demand (0x00-0xC8)

In the majority of cases, the domain_id is one of:

  • F9: stored DHW
  • FA: central heating (circulating volume)
  • FC: the boiler (or similar)

However, the domain_id could also be a zone_idx (0x00-0x0B), representing a Zone Valve or an Electric Heat zone. The distinction between these two zone types is that the former will also call for heat, whilst the latter will not.

The demand is either a percentage (0 to 100), or a boolean (0x00 = on, 0xC8 = off). If a relay/actuator cannot handle partial demands, then any non-zero value is 'on'.

OR:

The demand is a percentage, with a precision of 0.5%. Some scenarios will have only 0% or 100%, whilst others may have any value in the range.

Here is an example of a controller sending an instruction to a Zone Valve zone, with the corresponding instruction the the boiler. In this case, the BDR91 is simply opening a valve, and the boiler is heating/pumping a circulating volume of water.

11:13:05.259 045  I --- 01:145038 --:------ 01:145038 0008 002 073E
11:13:05.263 045  I --- 01:145038 --:------ 01:145038 0008 002 FC3E
...
11:13:05.705 045  I --- 01:145038 --:------ 01:145038 0008 002 073C
11:13:05.706 045  I --- 01:145038 --:------ 01:145038 0008 002 FC3C

Sample Code

def parser_0008(payload) -> dict:
    assert len(payload) / 2 == 2
    assert int(payload[:2], 16) <= 11 or payload[:2] in ["F9", "FA", "FC"]

    return {
        "zone_idx" if int(payload[:2], 16) <= 11 else "domain_id": payload[:2],
        "relay_demand": int(payload[2:], 16) / 200,
    }
Clone this wiki locally