Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HVAC Clusters

Heating, Ventilation, and Air Conditioning clusters for climate control devices.


Thermostat (0x0201)

A full-featured thermostat with heating/cooling setpoints, weekly scheduling, and automatic mode switching. Temperature values are in 0.01°C units throughout.

Attributes

AttributeIDTypeAccessDescription
LocalTemperature0x0000I16ReportCurrent sensor reading
OutdoorTemperature0x0001I16ReadOutdoor temp (optional)
Occupancy0x0002U8ReadOccupancy bitmap
AbsMinHeatSetpointLimit0x0003I16ReadAbsolute minimum heat SP (700 = 7°C)
AbsMaxHeatSetpointLimit0x0004I16ReadAbsolute maximum heat SP (3000 = 30°C)
AbsMinCoolSetpointLimit0x0005I16ReadAbsolute minimum cool SP (1600 = 16°C)
AbsMaxCoolSetpointLimit0x0006I16ReadAbsolute maximum cool SP (3200 = 32°C)
OccupiedCoolingSetpoint0x0011I16R/WActive cooling setpoint (2600 = 26°C)
OccupiedHeatingSetpoint0x0012I16R/WActive heating setpoint (2000 = 20°C)
MinHeatSetpointLimit0x0015I16R/WConfigurable heat SP minimum
MaxHeatSetpointLimit0x0016I16R/WConfigurable heat SP maximum
MinCoolSetpointLimit0x0017I16R/WConfigurable cool SP minimum
MaxCoolSetpointLimit0x0018I16R/WConfigurable cool SP maximum
ControlSequenceOfOperation0x001BEnum8R/W0x04 = Cooling and Heating
SystemMode0x001CEnum8R/WCurrent operating mode
ThermostatRunningMode0x001EEnum8ReadComputed running mode

System Modes

ValueModeDescription
0x00OffSystem disabled
0x01AutoAutomatic heat/cool switching
0x03CoolCooling only
0x04HeatHeating only
0x05Emergency HeatEmergency/auxiliary heating
0x07Fan OnlyFan without heating/cooling

Commands

IDDirectionCommand
0x00Client→ServerSetpointRaiseLower
0x01Client→ServerSetWeeklySchedule
0x02Client→ServerGetWeeklySchedule
0x03Client→ServerClearWeeklySchedule
0x00Server→ClientGetWeeklyScheduleResponse

Usage

#![allow(unused)]
fn main() {
use zigbee_zcl::clusters::thermostat::ThermostatCluster;

let mut therm = ThermostatCluster::new();

// Update temperature from sensor (22.50°C):
therm.set_local_temperature(2250);

// In the periodic callback — advance schedule and compute running mode:
// day_of_week: bitmask (bit 0 = Sunday .. bit 6 = Saturday)
// minutes_since_midnight: current time of day
therm.tick(0b0000010, 480); // Monday, 08:00

// SystemMode and setpoints can be written remotely via Write Attributes
// RunningMode is computed automatically by tick():
//   - Auto mode: heats if temp < heat SP, cools if temp > cool SP
//   - Heat mode: heats if temp < heat SP
//   - Cool mode: cools if temp > cool SP
}

Weekly Schedule

The thermostat supports a weekly schedule with up to 16 entries, each containing multiple transitions:

#![allow(unused)]
fn main() {
// A coordinator sends SetWeeklySchedule (0x01):
//   num_transitions: 3
//   days_of_week: 0b0111110 (Monday–Friday)
//   mode: 0x01 (heat only)
//   transitions:
//     06:00 → heat SP = 21.00°C
//     09:00 → heat SP = 18.00°C  (away)
//     17:00 → heat SP = 21.00°C  (home)

// tick() finds the latest passed transition and applies its setpoints
}

Fan Control (0x0202)

Simple fan speed control with mode enumeration.

Attributes

AttributeIDTypeAccessDescription
FanMode0x0000Enum8R/WCurrent fan mode
FanModeSequence0x0001Enum8R/WAvailable mode sequence

Fan Modes

ValueMode
0x00Off
0x01Low
0x02Medium
0x03High
0x04On
0x05Auto
0x06Smart

Fan Mode Sequences

ValueSequence
0x00Low/Med/High
0x01Low/High
0x02Low/Med/High/Auto
0x03Low/High/Auto
0x04On/Auto

No cluster-specific commands — fan mode is set via Write Attributes.

#![allow(unused)]
fn main() {
use zigbee_zcl::clusters::fan_control::FanControlCluster;

let mut fan = FanControlCluster::new();
assert_eq!(fan.fan_mode(), 0x05); // Auto by default
fan.set_fan_mode(0x03); // High
}

Thermostat User Interface Configuration (0x0204)

Controls how the thermostat’s local UI behaves.

Attributes

AttributeIDTypeAccessDescription
TemperatureDisplayMode0x0000Enum8R/W0=Celsius, 1=Fahrenheit
KeypadLockout0x0001Enum8R/W0=No lockout, 1–5=lockout levels
ScheduleProgrammingVisibility0x0002Enum8R/W0=enabled, 1=disabled
#![allow(unused)]
fn main() {
use zigbee_zcl::clusters::thermostat_ui::ThermostatUiCluster;

let mut ui = ThermostatUiCluster::new();
ui.set_display_mode(0x01); // Fahrenheit
ui.set_keypad_lockout(0x01); // Level 1 lockout
}

Putting It Together: Smart Thermostat

#![allow(unused)]
fn main() {
use zigbee_zcl::clusters::thermostat::ThermostatCluster;
use zigbee_zcl::clusters::fan_control::FanControlCluster;
use zigbee_zcl::clusters::thermostat_ui::ThermostatUiCluster;
use zigbee_zcl::clusters::temperature::TemperatureCluster;

let mut therm = ThermostatCluster::new();
let mut fan = FanControlCluster::new();
let mut ui = ThermostatUiCluster::new();
let mut temp_sensor = TemperatureCluster::new(-1000, 5000);

// Periodic callback (every minute):
let reading = read_temperature_sensor(); // 0.01°C units
temp_sensor.set_temperature(reading);
therm.set_local_temperature(reading);
therm.tick(get_day_of_week(), get_minutes_since_midnight());

// The thermostat running mode drives the HVAC relays
}