Skip to main content

matter_clusters/gen/
thermostat.rs

1//! Thermostat cluster (0x0201).
2//! @generated by `cargo xtask codegen` — do not edit.
3
4#![allow(
5    clippy::all,
6    clippy::pedantic,
7    dead_code,
8    unreachable_pub,
9    unused_imports
10)]
11
12use crate::datatypes::SemanticTagStruct;
13use crate::error::ClusterError;
14use crate::types::Nullable;
15use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
16
17/// Cluster ID.
18pub const CLUSTER_ID: u32 = 0x0201;
19/// Cluster revision.
20pub const CLUSTER_REVISION: u16 = 10;
21
22/// Command IDs (requests and responses).
23pub mod command_id {
24    /// `SetpointRaiseLower` (request).
25    pub const SETPOINT_RAISE_LOWER: u32 = 0x00;
26    /// `SetActiveScheduleRequest` (request).
27    pub const SET_ACTIVE_SCHEDULE_REQUEST: u32 = 0x05;
28    /// `SetActivePresetRequest` (request).
29    pub const SET_ACTIVE_PRESET_REQUEST: u32 = 0x06;
30    /// `AtomicResponse` (response).
31    pub const ATOMIC_RESPONSE: u32 = 0xFD;
32    /// `AtomicRequest` (request).
33    pub const ATOMIC_REQUEST: u32 = 0xFE;
34}
35
36/// Attribute IDs (cluster-specific).
37pub mod attribute_id {
38    /// `LocalTemperature`.
39    pub const LOCAL_TEMPERATURE: u32 = 0x0000;
40    /// `OutdoorTemperature`.
41    pub const OUTDOOR_TEMPERATURE: u32 = 0x0001;
42    /// `Occupancy`.
43    pub const OCCUPANCY: u32 = 0x0002;
44    /// `AbsMinHeatSetpointLimit`.
45    pub const ABS_MIN_HEAT_SETPOINT_LIMIT: u32 = 0x0003;
46    /// `AbsMaxHeatSetpointLimit`.
47    pub const ABS_MAX_HEAT_SETPOINT_LIMIT: u32 = 0x0004;
48    /// `AbsMinCoolSetpointLimit`.
49    pub const ABS_MIN_COOL_SETPOINT_LIMIT: u32 = 0x0005;
50    /// `AbsMaxCoolSetpointLimit`.
51    pub const ABS_MAX_COOL_SETPOINT_LIMIT: u32 = 0x0006;
52    /// `LocalTemperatureCalibration`.
53    pub const LOCAL_TEMPERATURE_CALIBRATION: u32 = 0x0010;
54    /// `OccupiedCoolingSetpoint`.
55    pub const OCCUPIED_COOLING_SETPOINT: u32 = 0x0011;
56    /// `OccupiedHeatingSetpoint`.
57    pub const OCCUPIED_HEATING_SETPOINT: u32 = 0x0012;
58    /// `UnoccupiedCoolingSetpoint`.
59    pub const UNOCCUPIED_COOLING_SETPOINT: u32 = 0x0013;
60    /// `UnoccupiedHeatingSetpoint`.
61    pub const UNOCCUPIED_HEATING_SETPOINT: u32 = 0x0014;
62    /// `MinHeatSetpointLimit`.
63    pub const MIN_HEAT_SETPOINT_LIMIT: u32 = 0x0015;
64    /// `MaxHeatSetpointLimit`.
65    pub const MAX_HEAT_SETPOINT_LIMIT: u32 = 0x0016;
66    /// `MinCoolSetpointLimit`.
67    pub const MIN_COOL_SETPOINT_LIMIT: u32 = 0x0017;
68    /// `MaxCoolSetpointLimit`.
69    pub const MAX_COOL_SETPOINT_LIMIT: u32 = 0x0018;
70    /// `MinSetpointDeadBand`.
71    pub const MIN_SETPOINT_DEAD_BAND: u32 = 0x0019;
72    /// `RemoteSensing`.
73    pub const REMOTE_SENSING: u32 = 0x001A;
74    /// `ControlSequenceOfOperation`.
75    pub const CONTROL_SEQUENCE_OF_OPERATION: u32 = 0x001B;
76    /// `SystemMode`.
77    pub const SYSTEM_MODE: u32 = 0x001C;
78    /// `ThermostatRunningMode`.
79    pub const THERMOSTAT_RUNNING_MODE: u32 = 0x001E;
80    /// `TemperatureSetpointHold`.
81    pub const TEMPERATURE_SETPOINT_HOLD: u32 = 0x0023;
82    /// `TemperatureSetpointHoldDuration`.
83    pub const TEMPERATURE_SETPOINT_HOLD_DURATION: u32 = 0x0024;
84    /// `ThermostatRunningState`.
85    pub const THERMOSTAT_RUNNING_STATE: u32 = 0x0029;
86    /// `SetpointChangeSource`.
87    pub const SETPOINT_CHANGE_SOURCE: u32 = 0x0030;
88    /// `SetpointChangeAmount`.
89    pub const SETPOINT_CHANGE_AMOUNT: u32 = 0x0031;
90    /// `SetpointChangeSourceTimestamp`.
91    pub const SETPOINT_CHANGE_SOURCE_TIMESTAMP: u32 = 0x0032;
92    /// `EmergencyHeatDelta`.
93    pub const EMERGENCY_HEAT_DELTA: u32 = 0x003A;
94    /// `AcType`.
95    pub const AC_TYPE: u32 = 0x0040;
96    /// `AcCapacity`.
97    pub const AC_CAPACITY: u32 = 0x0041;
98    /// `AcRefrigerantType`.
99    pub const AC_REFRIGERANT_TYPE: u32 = 0x0042;
100    /// `AcCompressorType`.
101    pub const AC_COMPRESSOR_TYPE: u32 = 0x0043;
102    /// `AcErrorCode`.
103    pub const AC_ERROR_CODE: u32 = 0x0044;
104    /// `AcLouverPosition`.
105    pub const AC_LOUVER_POSITION: u32 = 0x0045;
106    /// `AcCoilTemperature`.
107    pub const AC_COIL_TEMPERATURE: u32 = 0x0046;
108    /// `AcCapacityFormat`.
109    pub const AC_CAPACITY_FORMAT: u32 = 0x0047;
110    /// `PresetTypes`.
111    pub const PRESET_TYPES: u32 = 0x0048;
112    /// `ScheduleTypes`.
113    pub const SCHEDULE_TYPES: u32 = 0x0049;
114    /// `NumberOfPresets`.
115    pub const NUMBER_OF_PRESETS: u32 = 0x004A;
116    /// `NumberOfSchedules`.
117    pub const NUMBER_OF_SCHEDULES: u32 = 0x004B;
118    /// `NumberOfScheduleTransitions`.
119    pub const NUMBER_OF_SCHEDULE_TRANSITIONS: u32 = 0x004C;
120    /// `NumberOfScheduleTransitionPerDay`.
121    pub const NUMBER_OF_SCHEDULE_TRANSITION_PER_DAY: u32 = 0x004D;
122    /// `ActivePresetHandle`.
123    pub const ACTIVE_PRESET_HANDLE: u32 = 0x004E;
124    /// `ActiveScheduleHandle`.
125    pub const ACTIVE_SCHEDULE_HANDLE: u32 = 0x004F;
126    /// `Presets`.
127    pub const PRESETS: u32 = 0x0050;
128    /// `Schedules`.
129    pub const SCHEDULES: u32 = 0x0051;
130    /// `SetpointHoldExpiryTimestamp`.
131    pub const SETPOINT_HOLD_EXPIRY_TIMESTAMP: u32 = 0x0052;
132}
133
134bitflags::bitflags! {
135    /// `Thermostat` feature bits (FeatureMap).
136    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
137    pub struct Feature: u32 {
138        /// Heating (HEAT).
139        const HEAT = 1 << 0;
140        /// Cooling (COOL).
141        const COOL = 1 << 1;
142        /// Occupancy (OCC).
143        const OCC = 1 << 2;
144        /// Setback (SB).
145        const SB = 1 << 4;
146        /// AutoMode (AUTO).
147        const AUTO = 1 << 5;
148        /// LocalTemperatureNotExposed (LTNE).
149        const LTNE = 1 << 6;
150        /// MatterScheduleConfiguration (MSCH).
151        const MSCH = 1 << 7;
152        /// Presets (PRES).
153        const PRES = 1 << 8;
154    }
155}
156
157/// `ACCapacityFormatEnum` (enum8).
158#[derive(Copy, Clone, Debug, PartialEq, Eq)]
159pub enum ACCapacityFormatEnum {
160    /// BtUh = 0.
161    BtUh,
162    /// A value not known to this codegen revision.
163    Unknown(u8),
164}
165
166impl ACCapacityFormatEnum {
167    /// Decode from its raw discriminant (unknown → `Unknown`).
168    #[must_use]
169    pub fn from_raw(v: u8) -> Self {
170        match v {
171            0 => Self::BtUh,
172            other => Self::Unknown(other),
173        }
174    }
175    /// The raw discriminant.
176    #[must_use]
177    pub fn to_raw(self) -> u8 {
178        match self {
179            Self::BtUh => 0,
180            Self::Unknown(v) => v,
181        }
182    }
183}
184
185/// `ACCompressorTypeEnum` (enum8).
186#[derive(Copy, Clone, Debug, PartialEq, Eq)]
187pub enum ACCompressorTypeEnum {
188    /// Unknown = 0.
189    Unknown,
190    /// T1 = 1.
191    T1,
192    /// T2 = 2.
193    T2,
194    /// T3 = 3.
195    T3,
196    /// A value not known to this codegen revision.
197    Unrecognized(u8),
198}
199
200impl ACCompressorTypeEnum {
201    /// Decode from its raw discriminant (unknown → `Unrecognized`).
202    #[must_use]
203    pub fn from_raw(v: u8) -> Self {
204        match v {
205            0 => Self::Unknown,
206            1 => Self::T1,
207            2 => Self::T2,
208            3 => Self::T3,
209            other => Self::Unrecognized(other),
210        }
211    }
212    /// The raw discriminant.
213    #[must_use]
214    pub fn to_raw(self) -> u8 {
215        match self {
216            Self::Unknown => 0,
217            Self::T1 => 1,
218            Self::T2 => 2,
219            Self::T3 => 3,
220            Self::Unrecognized(v) => v,
221        }
222    }
223}
224
225bitflags::bitflags! {
226    /// `ACErrorCodeBitmap` (map32).
227    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
228    pub struct ACErrorCodeBitmap: u32 {
229        /// CompressorFail.
230        const COMPRESSOR_FAIL = 1 << 0;
231        /// RoomSensorFail.
232        const ROOM_SENSOR_FAIL = 1 << 1;
233        /// OutdoorSensorFail.
234        const OUTDOOR_SENSOR_FAIL = 1 << 2;
235        /// CoilSensorFail.
236        const COIL_SENSOR_FAIL = 1 << 3;
237        /// FanFail.
238        const FAN_FAIL = 1 << 4;
239    }
240}
241
242/// `ACLouverPositionEnum` (enum8).
243#[derive(Copy, Clone, Debug, PartialEq, Eq)]
244pub enum ACLouverPositionEnum {
245    /// Closed = 1.
246    Closed,
247    /// Open = 2.
248    Open,
249    /// Quarter = 3.
250    Quarter,
251    /// Half = 4.
252    Half,
253    /// ThreeQuarters = 5.
254    ThreeQuarters,
255    /// A value not known to this codegen revision.
256    Unknown(u8),
257}
258
259impl ACLouverPositionEnum {
260    /// Decode from its raw discriminant (unknown → `Unknown`).
261    #[must_use]
262    pub fn from_raw(v: u8) -> Self {
263        match v {
264            1 => Self::Closed,
265            2 => Self::Open,
266            3 => Self::Quarter,
267            4 => Self::Half,
268            5 => Self::ThreeQuarters,
269            other => Self::Unknown(other),
270        }
271    }
272    /// The raw discriminant.
273    #[must_use]
274    pub fn to_raw(self) -> u8 {
275        match self {
276            Self::Closed => 1,
277            Self::Open => 2,
278            Self::Quarter => 3,
279            Self::Half => 4,
280            Self::ThreeQuarters => 5,
281            Self::Unknown(v) => v,
282        }
283    }
284}
285
286/// `ACRefrigerantTypeEnum` (enum8).
287#[derive(Copy, Clone, Debug, PartialEq, Eq)]
288pub enum ACRefrigerantTypeEnum {
289    /// Unknown = 0.
290    Unknown,
291    /// R22 = 1.
292    R22,
293    /// R410A = 2.
294    R410A,
295    /// R407C = 3.
296    R407C,
297    /// A value not known to this codegen revision.
298    Unrecognized(u8),
299}
300
301impl ACRefrigerantTypeEnum {
302    /// Decode from its raw discriminant (unknown → `Unrecognized`).
303    #[must_use]
304    pub fn from_raw(v: u8) -> Self {
305        match v {
306            0 => Self::Unknown,
307            1 => Self::R22,
308            2 => Self::R410A,
309            3 => Self::R407C,
310            other => Self::Unrecognized(other),
311        }
312    }
313    /// The raw discriminant.
314    #[must_use]
315    pub fn to_raw(self) -> u8 {
316        match self {
317            Self::Unknown => 0,
318            Self::R22 => 1,
319            Self::R410A => 2,
320            Self::R407C => 3,
321            Self::Unrecognized(v) => v,
322        }
323    }
324}
325
326/// `ACTypeEnum` (enum8).
327#[derive(Copy, Clone, Debug, PartialEq, Eq)]
328pub enum ACTypeEnum {
329    /// Unknown = 0.
330    Unknown,
331    /// CoolingFixed = 1.
332    CoolingFixed,
333    /// HeatPumpFixed = 2.
334    HeatPumpFixed,
335    /// CoolingInverter = 3.
336    CoolingInverter,
337    /// HeatPumpInverter = 4.
338    HeatPumpInverter,
339    /// A value not known to this codegen revision.
340    Unrecognized(u8),
341}
342
343impl ACTypeEnum {
344    /// Decode from its raw discriminant (unknown → `Unrecognized`).
345    #[must_use]
346    pub fn from_raw(v: u8) -> Self {
347        match v {
348            0 => Self::Unknown,
349            1 => Self::CoolingFixed,
350            2 => Self::HeatPumpFixed,
351            3 => Self::CoolingInverter,
352            4 => Self::HeatPumpInverter,
353            other => Self::Unrecognized(other),
354        }
355    }
356    /// The raw discriminant.
357    #[must_use]
358    pub fn to_raw(self) -> u8 {
359        match self {
360            Self::Unknown => 0,
361            Self::CoolingFixed => 1,
362            Self::HeatPumpFixed => 2,
363            Self::CoolingInverter => 3,
364            Self::HeatPumpInverter => 4,
365            Self::Unrecognized(v) => v,
366        }
367    }
368}
369
370/// `ControlSequenceOfOperationEnum` (enum8).
371#[derive(Copy, Clone, Debug, PartialEq, Eq)]
372pub enum ControlSequenceOfOperationEnum {
373    /// CoolingOnly = 0.
374    CoolingOnly,
375    /// CoolingWithReheat = 1.
376    CoolingWithReheat,
377    /// HeatingOnly = 2.
378    HeatingOnly,
379    /// HeatingWithReheat = 3.
380    HeatingWithReheat,
381    /// CoolingAndHeating = 4.
382    CoolingAndHeating,
383    /// CoolingAndHeatingWithReheat = 5.
384    CoolingAndHeatingWithReheat,
385    /// A value not known to this codegen revision.
386    Unknown(u8),
387}
388
389impl ControlSequenceOfOperationEnum {
390    /// Decode from its raw discriminant (unknown → `Unknown`).
391    #[must_use]
392    pub fn from_raw(v: u8) -> Self {
393        match v {
394            0 => Self::CoolingOnly,
395            1 => Self::CoolingWithReheat,
396            2 => Self::HeatingOnly,
397            3 => Self::HeatingWithReheat,
398            4 => Self::CoolingAndHeating,
399            5 => Self::CoolingAndHeatingWithReheat,
400            other => Self::Unknown(other),
401        }
402    }
403    /// The raw discriminant.
404    #[must_use]
405    pub fn to_raw(self) -> u8 {
406        match self {
407            Self::CoolingOnly => 0,
408            Self::CoolingWithReheat => 1,
409            Self::HeatingOnly => 2,
410            Self::HeatingWithReheat => 3,
411            Self::CoolingAndHeating => 4,
412            Self::CoolingAndHeatingWithReheat => 5,
413            Self::Unknown(v) => v,
414        }
415    }
416}
417
418bitflags::bitflags! {
419    /// `OccupancyBitmap` (map8).
420    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
421    pub struct OccupancyBitmap: u8 {
422        /// Occupied.
423        const OCCUPIED = 1 << 0;
424    }
425}
426
427/// `PresetScenarioEnum` (enum8).
428#[derive(Copy, Clone, Debug, PartialEq, Eq)]
429pub enum PresetScenarioEnum {
430    /// Occupied = 1.
431    Occupied,
432    /// Unoccupied = 2.
433    Unoccupied,
434    /// Sleep = 3.
435    Sleep,
436    /// Wake = 4.
437    Wake,
438    /// Vacation = 5.
439    Vacation,
440    /// GoingToSleep = 6.
441    GoingToSleep,
442    /// UserDefined = 254.
443    UserDefined,
444    /// A value not known to this codegen revision.
445    Unknown(u8),
446}
447
448impl PresetScenarioEnum {
449    /// Decode from its raw discriminant (unknown → `Unknown`).
450    #[must_use]
451    pub fn from_raw(v: u8) -> Self {
452        match v {
453            1 => Self::Occupied,
454            2 => Self::Unoccupied,
455            3 => Self::Sleep,
456            4 => Self::Wake,
457            5 => Self::Vacation,
458            6 => Self::GoingToSleep,
459            254 => Self::UserDefined,
460            other => Self::Unknown(other),
461        }
462    }
463    /// The raw discriminant.
464    #[must_use]
465    pub fn to_raw(self) -> u8 {
466        match self {
467            Self::Occupied => 1,
468            Self::Unoccupied => 2,
469            Self::Sleep => 3,
470            Self::Wake => 4,
471            Self::Vacation => 5,
472            Self::GoingToSleep => 6,
473            Self::UserDefined => 254,
474            Self::Unknown(v) => v,
475        }
476    }
477}
478
479/// `PresetStruct` struct.
480#[derive(Clone, Debug, PartialEq)]
481#[non_exhaustive]
482pub struct PresetStruct {
483    /// Field PresetHandle (tag 0).
484    pub preset_handle: Nullable<Vec<u8>>,
485    /// Field PresetScenario (tag 1).
486    pub preset_scenario: PresetScenarioEnum,
487    /// Field Name (tag 2).
488    pub name: Option<Nullable<String>>,
489    /// Field CoolingSetpoint (tag 3).
490    pub cooling_setpoint: Option<i16>,
491    /// Field HeatingSetpoint (tag 4).
492    pub heating_setpoint: Option<i16>,
493    /// Field BuiltIn (tag 5).
494    pub built_in: Nullable<bool>,
495}
496
497bitflags::bitflags! {
498    /// `PresetTypeFeaturesBitmap` (map16).
499    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
500    pub struct PresetTypeFeaturesBitmap: u16 {
501        /// Automatic.
502        const AUTOMATIC = 1 << 0;
503        /// SupportsNames.
504        const SUPPORTS_NAMES = 1 << 1;
505    }
506}
507
508/// `PresetTypeStruct` struct.
509#[derive(Clone, Debug, PartialEq)]
510#[non_exhaustive]
511pub struct PresetTypeStruct {
512    /// Field PresetScenario (tag 0).
513    pub preset_scenario: PresetScenarioEnum,
514    /// Field NumberOfPresets (tag 1).
515    pub number_of_presets: u8,
516    /// Field PresetTypeFeatures (tag 2).
517    pub preset_type_features: PresetTypeFeaturesBitmap,
518}
519
520bitflags::bitflags! {
521    /// `RelayStateBitmap` (map16).
522    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
523    pub struct RelayStateBitmap: u16 {
524        /// Heat.
525        const HEAT = 1 << 0;
526        /// Cool.
527        const COOL = 1 << 1;
528        /// Fan.
529        const FAN = 1 << 2;
530        /// HeatStage2.
531        const HEAT_STAGE2 = 1 << 3;
532        /// CoolStage2.
533        const COOL_STAGE2 = 1 << 4;
534        /// FanStage2.
535        const FAN_STAGE2 = 1 << 5;
536        /// FanStage3.
537        const FAN_STAGE3 = 1 << 6;
538    }
539}
540
541bitflags::bitflags! {
542    /// `RemoteSensingBitmap` (map8).
543    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
544    pub struct RemoteSensingBitmap: u8 {
545        /// LocalTemperature.
546        const LOCAL_TEMPERATURE = 1 << 0;
547        /// OutdoorTemperature.
548        const OUTDOOR_TEMPERATURE = 1 << 1;
549        /// Occupancy.
550        const OCCUPANCY = 1 << 2;
551    }
552}
553
554bitflags::bitflags! {
555    /// `ScheduleDayOfWeekBitmap` (map8).
556    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
557    pub struct ScheduleDayOfWeekBitmap: u8 {
558        /// Sunday.
559        const SUNDAY = 1 << 0;
560        /// Monday.
561        const MONDAY = 1 << 1;
562        /// Tuesday.
563        const TUESDAY = 1 << 2;
564        /// Wednesday.
565        const WEDNESDAY = 1 << 3;
566        /// Thursday.
567        const THURSDAY = 1 << 4;
568        /// Friday.
569        const FRIDAY = 1 << 5;
570        /// Saturday.
571        const SATURDAY = 1 << 6;
572        /// Away.
573        const AWAY = 1 << 7;
574    }
575}
576
577bitflags::bitflags! {
578    /// `ScheduleModeBitmap` (map8).
579    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
580    pub struct ScheduleModeBitmap: u8 {
581        /// HeatSetpointPresent.
582        const HEAT_SETPOINT_PRESENT = 1 << 0;
583        /// CoolSetpointPresent.
584        const COOL_SETPOINT_PRESENT = 1 << 1;
585    }
586}
587
588/// `ScheduleStruct` struct.
589#[derive(Clone, Debug, PartialEq)]
590#[non_exhaustive]
591pub struct ScheduleStruct {
592    /// Field ScheduleHandle (tag 0).
593    pub schedule_handle: Nullable<Vec<u8>>,
594    /// Field SystemMode (tag 1).
595    pub system_mode: SystemModeEnum,
596    /// Field Name (tag 2).
597    pub name: Option<String>,
598    /// Field PresetHandle (tag 3).
599    pub preset_handle: Option<Vec<u8>>,
600    /// Field Transitions (tag 4).
601    pub transitions: Vec<ScheduleTransitionStruct>,
602    /// Field BuiltIn (tag 5).
603    pub built_in: Nullable<bool>,
604}
605
606/// `ScheduleTransitionStruct` struct.
607#[derive(Clone, Debug, PartialEq)]
608#[non_exhaustive]
609pub struct ScheduleTransitionStruct {
610    /// Field DayOfWeek (tag 0).
611    pub day_of_week: ScheduleDayOfWeekBitmap,
612    /// Field TransitionTime (tag 1).
613    pub transition_time: u16,
614    /// Field PresetHandle (tag 2).
615    pub preset_handle: Option<Vec<u8>>,
616    /// Field SystemMode (tag 3).
617    pub system_mode: Option<SystemModeEnum>,
618    /// Field CoolingSetpoint (tag 4).
619    pub cooling_setpoint: Option<i16>,
620    /// Field HeatingSetpoint (tag 5).
621    pub heating_setpoint: Option<i16>,
622}
623
624bitflags::bitflags! {
625    /// `ScheduleTypeFeaturesBitmap` (map16).
626    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
627    pub struct ScheduleTypeFeaturesBitmap: u16 {
628        /// SupportsPresets.
629        const SUPPORTS_PRESETS = 1 << 0;
630        /// SupportsSetpoints.
631        const SUPPORTS_SETPOINTS = 1 << 1;
632        /// SupportsNames.
633        const SUPPORTS_NAMES = 1 << 2;
634        /// SupportsOff.
635        const SUPPORTS_OFF = 1 << 3;
636    }
637}
638
639/// `ScheduleTypeStruct` struct.
640#[derive(Clone, Debug, PartialEq)]
641#[non_exhaustive]
642pub struct ScheduleTypeStruct {
643    /// Field SystemMode (tag 0).
644    pub system_mode: SystemModeEnum,
645    /// Field NumberOfSchedules (tag 1).
646    pub number_of_schedules: u8,
647    /// Field ScheduleTypeFeatures (tag 2).
648    pub schedule_type_features: ScheduleTypeFeaturesBitmap,
649}
650
651/// `SetpointChangeSourceEnum` (enum8).
652#[derive(Copy, Clone, Debug, PartialEq, Eq)]
653pub enum SetpointChangeSourceEnum {
654    /// Manual = 0.
655    Manual,
656    /// Schedule = 1.
657    Schedule,
658    /// External = 2.
659    External,
660    /// A value not known to this codegen revision.
661    Unknown(u8),
662}
663
664impl SetpointChangeSourceEnum {
665    /// Decode from its raw discriminant (unknown → `Unknown`).
666    #[must_use]
667    pub fn from_raw(v: u8) -> Self {
668        match v {
669            0 => Self::Manual,
670            1 => Self::Schedule,
671            2 => Self::External,
672            other => Self::Unknown(other),
673        }
674    }
675    /// The raw discriminant.
676    #[must_use]
677    pub fn to_raw(self) -> u8 {
678        match self {
679            Self::Manual => 0,
680            Self::Schedule => 1,
681            Self::External => 2,
682            Self::Unknown(v) => v,
683        }
684    }
685}
686
687/// `SetpointRaiseLowerModeEnum` (enum8).
688#[derive(Copy, Clone, Debug, PartialEq, Eq)]
689pub enum SetpointRaiseLowerModeEnum {
690    /// Heat = 0.
691    Heat,
692    /// Cool = 1.
693    Cool,
694    /// Both = 2.
695    Both,
696    /// A value not known to this codegen revision.
697    Unknown(u8),
698}
699
700impl SetpointRaiseLowerModeEnum {
701    /// Decode from its raw discriminant (unknown → `Unknown`).
702    #[must_use]
703    pub fn from_raw(v: u8) -> Self {
704        match v {
705            0 => Self::Heat,
706            1 => Self::Cool,
707            2 => Self::Both,
708            other => Self::Unknown(other),
709        }
710    }
711    /// The raw discriminant.
712    #[must_use]
713    pub fn to_raw(self) -> u8 {
714        match self {
715            Self::Heat => 0,
716            Self::Cool => 1,
717            Self::Both => 2,
718            Self::Unknown(v) => v,
719        }
720    }
721}
722
723/// `StartOfWeekEnum` (enum8).
724#[derive(Copy, Clone, Debug, PartialEq, Eq)]
725pub enum StartOfWeekEnum {
726    /// Sunday = 0.
727    Sunday,
728    /// Monday = 1.
729    Monday,
730    /// Tuesday = 2.
731    Tuesday,
732    /// Wednesday = 3.
733    Wednesday,
734    /// Thursday = 4.
735    Thursday,
736    /// Friday = 5.
737    Friday,
738    /// Saturday = 6.
739    Saturday,
740    /// A value not known to this codegen revision.
741    Unknown(u8),
742}
743
744impl StartOfWeekEnum {
745    /// Decode from its raw discriminant (unknown → `Unknown`).
746    #[must_use]
747    pub fn from_raw(v: u8) -> Self {
748        match v {
749            0 => Self::Sunday,
750            1 => Self::Monday,
751            2 => Self::Tuesday,
752            3 => Self::Wednesday,
753            4 => Self::Thursday,
754            5 => Self::Friday,
755            6 => Self::Saturday,
756            other => Self::Unknown(other),
757        }
758    }
759    /// The raw discriminant.
760    #[must_use]
761    pub fn to_raw(self) -> u8 {
762        match self {
763            Self::Sunday => 0,
764            Self::Monday => 1,
765            Self::Tuesday => 2,
766            Self::Wednesday => 3,
767            Self::Thursday => 4,
768            Self::Friday => 5,
769            Self::Saturday => 6,
770            Self::Unknown(v) => v,
771        }
772    }
773}
774
775/// `SystemModeEnum` (enum8).
776#[derive(Copy, Clone, Debug, PartialEq, Eq)]
777pub enum SystemModeEnum {
778    /// Off = 0.
779    Off,
780    /// Auto = 1.
781    Auto,
782    /// Cool = 3.
783    Cool,
784    /// Heat = 4.
785    Heat,
786    /// EmergencyHeat = 5.
787    EmergencyHeat,
788    /// Precooling = 6.
789    Precooling,
790    /// FanOnly = 7.
791    FanOnly,
792    /// Dry = 8.
793    Dry,
794    /// Sleep = 9.
795    Sleep,
796    /// A value not known to this codegen revision.
797    Unknown(u8),
798}
799
800impl SystemModeEnum {
801    /// Decode from its raw discriminant (unknown → `Unknown`).
802    #[must_use]
803    pub fn from_raw(v: u8) -> Self {
804        match v {
805            0 => Self::Off,
806            1 => Self::Auto,
807            3 => Self::Cool,
808            4 => Self::Heat,
809            5 => Self::EmergencyHeat,
810            6 => Self::Precooling,
811            7 => Self::FanOnly,
812            8 => Self::Dry,
813            9 => Self::Sleep,
814            other => Self::Unknown(other),
815        }
816    }
817    /// The raw discriminant.
818    #[must_use]
819    pub fn to_raw(self) -> u8 {
820        match self {
821            Self::Off => 0,
822            Self::Auto => 1,
823            Self::Cool => 3,
824            Self::Heat => 4,
825            Self::EmergencyHeat => 5,
826            Self::Precooling => 6,
827            Self::FanOnly => 7,
828            Self::Dry => 8,
829            Self::Sleep => 9,
830            Self::Unknown(v) => v,
831        }
832    }
833}
834
835/// `TemperatureSetpointHoldEnum` (enum8).
836#[derive(Copy, Clone, Debug, PartialEq, Eq)]
837pub enum TemperatureSetpointHoldEnum {
838    /// SetpointHoldOff = 0.
839    SetpointHoldOff,
840    /// SetpointHoldOn = 1.
841    SetpointHoldOn,
842    /// A value not known to this codegen revision.
843    Unknown(u8),
844}
845
846impl TemperatureSetpointHoldEnum {
847    /// Decode from its raw discriminant (unknown → `Unknown`).
848    #[must_use]
849    pub fn from_raw(v: u8) -> Self {
850        match v {
851            0 => Self::SetpointHoldOff,
852            1 => Self::SetpointHoldOn,
853            other => Self::Unknown(other),
854        }
855    }
856    /// The raw discriminant.
857    #[must_use]
858    pub fn to_raw(self) -> u8 {
859        match self {
860            Self::SetpointHoldOff => 0,
861            Self::SetpointHoldOn => 1,
862            Self::Unknown(v) => v,
863        }
864    }
865}
866
867/// `ThermostatAttributeStatusEntryStruct` struct.
868#[derive(Clone, Debug, PartialEq)]
869#[non_exhaustive]
870pub struct ThermostatAttributeStatusEntryStruct {
871    /// Field AttributeId (tag 0).
872    pub attribute_id: u32,
873    /// Field StatusCode (tag 1).
874    pub status_code: u8,
875}
876
877/// `ThermostatRunningModeEnum` (enum8).
878#[derive(Copy, Clone, Debug, PartialEq, Eq)]
879pub enum ThermostatRunningModeEnum {
880    /// Off = 0.
881    Off,
882    /// Cool = 3.
883    Cool,
884    /// Heat = 4.
885    Heat,
886    /// A value not known to this codegen revision.
887    Unknown(u8),
888}
889
890impl ThermostatRunningModeEnum {
891    /// Decode from its raw discriminant (unknown → `Unknown`).
892    #[must_use]
893    pub fn from_raw(v: u8) -> Self {
894        match v {
895            0 => Self::Off,
896            3 => Self::Cool,
897            4 => Self::Heat,
898            other => Self::Unknown(other),
899        }
900    }
901    /// The raw discriminant.
902    #[must_use]
903    pub fn to_raw(self) -> u8 {
904        match self {
905            Self::Off => 0,
906            Self::Cool => 3,
907            Self::Heat => 4,
908            Self::Unknown(v) => v,
909        }
910    }
911}
912
913/// `WeeklyScheduleTransitionStruct` struct.
914#[derive(Clone, Debug, PartialEq)]
915#[non_exhaustive]
916pub struct WeeklyScheduleTransitionStruct {
917    /// Field TransitionTime (tag 0).
918    pub transition_time: u16,
919    /// Field HeatSetpoint (tag 1).
920    pub heat_setpoint: Nullable<i16>,
921    /// Field CoolSetpoint (tag 2).
922    pub cool_setpoint: Nullable<i16>,
923}
924
925impl PresetStruct {
926    /// Decode the fields of an already-opened anonymous structure
927    /// (reader positioned after the struct start; consumes to its end).
928    ///
929    /// # Errors
930    /// Returns [`ClusterError`] on a malformed structure or missing required field.
931    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
932        let mut f_preset_handle: Option<Nullable<Vec<u8>>> = None;
933        let mut f_preset_scenario: Option<PresetScenarioEnum> = None;
934        let mut f_name: Option<Nullable<String>> = None;
935        let mut f_cooling_setpoint: Option<i16> = None;
936        let mut f_heating_setpoint: Option<i16> = None;
937        let mut f_built_in: Option<Nullable<bool>> = None;
938        loop {
939            match r.next()? {
940                Some(Element::ContainerEnd) => break,
941                Some(Element::Scalar {
942                    tag: Tag::Context(0),
943                    value: Value::Null,
944                }) => f_preset_handle = Some(Nullable::Null),
945                Some(Element::Scalar {
946                    tag: Tag::Context(0),
947                    value: Value::Bytes(v),
948                }) => f_preset_handle = Some(Nullable::Value(v)),
949                Some(Element::Scalar {
950                    tag: Tag::Context(1),
951                    value: Value::Uint(v),
952                }) => {
953                    f_preset_scenario = Some(PresetScenarioEnum::from_raw(
954                        u8::try_from(v)
955                            .map_err(|_| ClusterError::InvalidLength("PresetScenario"))?,
956                    ))
957                }
958                Some(Element::Scalar {
959                    tag: Tag::Context(2),
960                    value: Value::Null,
961                }) => f_name = Some(Nullable::Null),
962                Some(Element::Scalar {
963                    tag: Tag::Context(2),
964                    value: Value::Utf8(v),
965                }) => f_name = Some(Nullable::Value(v)),
966                Some(Element::Scalar {
967                    tag: Tag::Context(3),
968                    value: Value::Int(v),
969                }) => {
970                    f_cooling_setpoint = Some(
971                        i16::try_from(v)
972                            .map_err(|_| ClusterError::InvalidLength("CoolingSetpoint"))?,
973                    )
974                }
975                Some(Element::Scalar {
976                    tag: Tag::Context(4),
977                    value: Value::Int(v),
978                }) => {
979                    f_heating_setpoint = Some(
980                        i16::try_from(v)
981                            .map_err(|_| ClusterError::InvalidLength("HeatingSetpoint"))?,
982                    )
983                }
984                Some(Element::Scalar {
985                    tag: Tag::Context(5),
986                    value: Value::Null,
987                }) => f_built_in = Some(Nullable::Null),
988                Some(Element::Scalar {
989                    tag: Tag::Context(5),
990                    value: Value::Bool(v),
991                }) => f_built_in = Some(Nullable::Value(v)),
992                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
993                Some(Element::ContainerStart { .. }) => r.skip_container()?,
994                Some(_) => {} // unknown/future scalar — skip
995            }
996        }
997        Ok(Self {
998            preset_handle: f_preset_handle.ok_or(ClusterError::MissingField("PresetHandle"))?,
999            preset_scenario: f_preset_scenario
1000                .ok_or(ClusterError::MissingField("PresetScenario"))?,
1001            name: f_name,
1002            cooling_setpoint: f_cooling_setpoint,
1003            heating_setpoint: f_heating_setpoint,
1004            built_in: f_built_in.ok_or(ClusterError::MissingField("BuiltIn"))?,
1005        })
1006    }
1007    /// Decode from a standalone anonymous TLV structure.
1008    ///
1009    /// # Errors
1010    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1011    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1012        let mut r = TlvReader::new(tlv);
1013        match r.next()? {
1014            Some(Element::ContainerStart {
1015                kind: ContainerKind::Structure,
1016                ..
1017            }) => {}
1018            _ => {
1019                return Err(ClusterError::UnexpectedType {
1020                    context: "PresetStruct",
1021                })
1022            }
1023        }
1024        Self::decode_from(&mut r)
1025    }
1026    /// Write this struct's fields into an already-open container.
1027    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1028    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
1029        match &self.preset_handle {
1030            Nullable::Null => w.put_null(Tag::Context(0)).expect("infallible: vec writer"),
1031            Nullable::Value(preset_handle) => {
1032                w.put_bytes(Tag::Context(0), &*preset_handle)
1033                    .expect("infallible: vec writer");
1034            }
1035        }
1036        w.put_uint(Tag::Context(1), u64::from(self.preset_scenario.to_raw()))
1037            .expect("infallible: vec writer");
1038        if let Some(name) = &self.name {
1039            match name {
1040                Nullable::Null => w.put_null(Tag::Context(2)).expect("infallible: vec writer"),
1041                Nullable::Value(name) => {
1042                    w.put_utf8(Tag::Context(2), &*name)
1043                        .expect("infallible: vec writer");
1044                }
1045            }
1046        }
1047        if let Some(cooling_setpoint) = &self.cooling_setpoint {
1048            w.put_int(Tag::Context(3), i64::from(*cooling_setpoint))
1049                .expect("infallible: vec writer");
1050        }
1051        if let Some(heating_setpoint) = &self.heating_setpoint {
1052            w.put_int(Tag::Context(4), i64::from(*heating_setpoint))
1053                .expect("infallible: vec writer");
1054        }
1055        match &self.built_in {
1056            Nullable::Null => w.put_null(Tag::Context(5)).expect("infallible: vec writer"),
1057            Nullable::Value(built_in) => {
1058                w.put_bool(Tag::Context(5), *built_in)
1059                    .expect("infallible: vec writer");
1060            }
1061        }
1062    }
1063    /// Encode as a standalone anonymous TLV structure.
1064    #[must_use]
1065    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1066    pub fn encode(&self) -> Vec<u8> {
1067        let mut buf = Vec::new();
1068        let mut w = TlvWriter::new(&mut buf);
1069        w.start_structure(Tag::Anonymous)
1070            .expect("infallible: vec writer");
1071        self.write_fields(&mut w);
1072        w.end_container().expect("infallible: vec writer");
1073        buf
1074    }
1075}
1076
1077impl PresetTypeStruct {
1078    /// Decode the fields of an already-opened anonymous structure
1079    /// (reader positioned after the struct start; consumes to its end).
1080    ///
1081    /// # Errors
1082    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1083    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1084        let mut f_preset_scenario: Option<PresetScenarioEnum> = None;
1085        let mut f_number_of_presets: Option<u8> = None;
1086        let mut f_preset_type_features: Option<PresetTypeFeaturesBitmap> = None;
1087        loop {
1088            match r.next()? {
1089                Some(Element::ContainerEnd) => break,
1090                Some(Element::Scalar {
1091                    tag: Tag::Context(0),
1092                    value: Value::Uint(v),
1093                }) => {
1094                    f_preset_scenario = Some(PresetScenarioEnum::from_raw(
1095                        u8::try_from(v)
1096                            .map_err(|_| ClusterError::InvalidLength("PresetScenario"))?,
1097                    ))
1098                }
1099                Some(Element::Scalar {
1100                    tag: Tag::Context(1),
1101                    value: Value::Uint(v),
1102                }) => {
1103                    f_number_of_presets = Some(
1104                        u8::try_from(v)
1105                            .map_err(|_| ClusterError::InvalidLength("NumberOfPresets"))?,
1106                    )
1107                }
1108                Some(Element::Scalar {
1109                    tag: Tag::Context(2),
1110                    value: Value::Uint(v),
1111                }) => {
1112                    f_preset_type_features = Some(PresetTypeFeaturesBitmap::from_bits_retain(
1113                        u16::try_from(v)
1114                            .map_err(|_| ClusterError::InvalidLength("PresetTypeFeatures"))?,
1115                    ))
1116                }
1117                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1118                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1119                Some(_) => {} // unknown/future scalar — skip
1120            }
1121        }
1122        Ok(Self {
1123            preset_scenario: f_preset_scenario
1124                .ok_or(ClusterError::MissingField("PresetScenario"))?,
1125            number_of_presets: f_number_of_presets
1126                .ok_or(ClusterError::MissingField("NumberOfPresets"))?,
1127            preset_type_features: f_preset_type_features
1128                .ok_or(ClusterError::MissingField("PresetTypeFeatures"))?,
1129        })
1130    }
1131    /// Decode from a standalone anonymous TLV structure.
1132    ///
1133    /// # Errors
1134    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1135    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1136        let mut r = TlvReader::new(tlv);
1137        match r.next()? {
1138            Some(Element::ContainerStart {
1139                kind: ContainerKind::Structure,
1140                ..
1141            }) => {}
1142            _ => {
1143                return Err(ClusterError::UnexpectedType {
1144                    context: "PresetTypeStruct",
1145                })
1146            }
1147        }
1148        Self::decode_from(&mut r)
1149    }
1150    /// Write this struct's fields into an already-open container.
1151    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1152    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
1153        w.put_uint(Tag::Context(0), u64::from(self.preset_scenario.to_raw()))
1154            .expect("infallible: vec writer");
1155        w.put_uint(Tag::Context(1), u64::from(self.number_of_presets))
1156            .expect("infallible: vec writer");
1157        w.put_uint(Tag::Context(2), u64::from(self.preset_type_features.bits()))
1158            .expect("infallible: vec writer");
1159    }
1160    /// Encode as a standalone anonymous TLV structure.
1161    #[must_use]
1162    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1163    pub fn encode(&self) -> Vec<u8> {
1164        let mut buf = Vec::new();
1165        let mut w = TlvWriter::new(&mut buf);
1166        w.start_structure(Tag::Anonymous)
1167            .expect("infallible: vec writer");
1168        self.write_fields(&mut w);
1169        w.end_container().expect("infallible: vec writer");
1170        buf
1171    }
1172}
1173
1174impl ScheduleStruct {
1175    /// Decode the fields of an already-opened anonymous structure
1176    /// (reader positioned after the struct start; consumes to its end).
1177    ///
1178    /// # Errors
1179    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1180    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1181        let mut f_schedule_handle: Option<Nullable<Vec<u8>>> = None;
1182        let mut f_system_mode: Option<SystemModeEnum> = None;
1183        let mut f_name: Option<String> = None;
1184        let mut f_preset_handle: Option<Vec<u8>> = None;
1185        let mut f_transitions: Option<Vec<ScheduleTransitionStruct>> = None;
1186        let mut f_built_in: Option<Nullable<bool>> = None;
1187        loop {
1188            match r.next()? {
1189                Some(Element::ContainerEnd) => break,
1190                Some(Element::Scalar {
1191                    tag: Tag::Context(0),
1192                    value: Value::Null,
1193                }) => f_schedule_handle = Some(Nullable::Null),
1194                Some(Element::Scalar {
1195                    tag: Tag::Context(0),
1196                    value: Value::Bytes(v),
1197                }) => f_schedule_handle = Some(Nullable::Value(v)),
1198                Some(Element::Scalar {
1199                    tag: Tag::Context(1),
1200                    value: Value::Uint(v),
1201                }) => {
1202                    f_system_mode = Some(SystemModeEnum::from_raw(
1203                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SystemMode"))?,
1204                    ))
1205                }
1206                Some(Element::Scalar {
1207                    tag: Tag::Context(2),
1208                    value: Value::Utf8(v),
1209                }) => f_name = Some(v),
1210                Some(Element::Scalar {
1211                    tag: Tag::Context(3),
1212                    value: Value::Bytes(v),
1213                }) => f_preset_handle = Some(v),
1214                Some(Element::ContainerStart {
1215                    tag: Tag::Context(4),
1216                    kind: ContainerKind::Array,
1217                }) => {
1218                    let mut out = Vec::new();
1219                    loop {
1220                        match r.next()? {
1221                            Some(Element::ContainerEnd) => break,
1222                            Some(Element::ContainerStart {
1223                                kind: ContainerKind::Structure,
1224                                ..
1225                            }) => {
1226                                out.push(ScheduleTransitionStruct::decode_from(r)?);
1227                            }
1228                            None => {
1229                                return Err(ClusterError::Tlv(
1230                                    matter_codec::Error::UnclosedContainer,
1231                                ))
1232                            }
1233                            Some(Element::ContainerStart { .. }) => r.skip_container()?,
1234                            Some(_) => {} // skip unknown scalar
1235                        }
1236                    }
1237                    f_transitions = Some(out);
1238                }
1239                Some(Element::Scalar {
1240                    tag: Tag::Context(5),
1241                    value: Value::Null,
1242                }) => f_built_in = Some(Nullable::Null),
1243                Some(Element::Scalar {
1244                    tag: Tag::Context(5),
1245                    value: Value::Bool(v),
1246                }) => f_built_in = Some(Nullable::Value(v)),
1247                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1248                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1249                Some(_) => {} // unknown/future scalar — skip
1250            }
1251        }
1252        Ok(Self {
1253            schedule_handle: f_schedule_handle
1254                .ok_or(ClusterError::MissingField("ScheduleHandle"))?,
1255            system_mode: f_system_mode.ok_or(ClusterError::MissingField("SystemMode"))?,
1256            name: f_name,
1257            preset_handle: f_preset_handle,
1258            transitions: f_transitions.ok_or(ClusterError::MissingField("Transitions"))?,
1259            built_in: f_built_in.ok_or(ClusterError::MissingField("BuiltIn"))?,
1260        })
1261    }
1262    /// Decode from a standalone anonymous TLV structure.
1263    ///
1264    /// # Errors
1265    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1266    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1267        let mut r = TlvReader::new(tlv);
1268        match r.next()? {
1269            Some(Element::ContainerStart {
1270                kind: ContainerKind::Structure,
1271                ..
1272            }) => {}
1273            _ => {
1274                return Err(ClusterError::UnexpectedType {
1275                    context: "ScheduleStruct",
1276                })
1277            }
1278        }
1279        Self::decode_from(&mut r)
1280    }
1281}
1282
1283impl ScheduleTransitionStruct {
1284    /// Decode the fields of an already-opened anonymous structure
1285    /// (reader positioned after the struct start; consumes to its end).
1286    ///
1287    /// # Errors
1288    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1289    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1290        let mut f_day_of_week: Option<ScheduleDayOfWeekBitmap> = None;
1291        let mut f_transition_time: Option<u16> = None;
1292        let mut f_preset_handle: Option<Vec<u8>> = None;
1293        let mut f_system_mode: Option<SystemModeEnum> = None;
1294        let mut f_cooling_setpoint: Option<i16> = None;
1295        let mut f_heating_setpoint: Option<i16> = None;
1296        loop {
1297            match r.next()? {
1298                Some(Element::ContainerEnd) => break,
1299                Some(Element::Scalar {
1300                    tag: Tag::Context(0),
1301                    value: Value::Uint(v),
1302                }) => {
1303                    f_day_of_week = Some(ScheduleDayOfWeekBitmap::from_bits_retain(
1304                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("DayOfWeek"))?,
1305                    ))
1306                }
1307                Some(Element::Scalar {
1308                    tag: Tag::Context(1),
1309                    value: Value::Uint(v),
1310                }) => {
1311                    f_transition_time = Some(
1312                        u16::try_from(v)
1313                            .map_err(|_| ClusterError::InvalidLength("TransitionTime"))?,
1314                    )
1315                }
1316                Some(Element::Scalar {
1317                    tag: Tag::Context(2),
1318                    value: Value::Bytes(v),
1319                }) => f_preset_handle = Some(v),
1320                Some(Element::Scalar {
1321                    tag: Tag::Context(3),
1322                    value: Value::Uint(v),
1323                }) => {
1324                    f_system_mode = Some(SystemModeEnum::from_raw(
1325                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SystemMode"))?,
1326                    ))
1327                }
1328                Some(Element::Scalar {
1329                    tag: Tag::Context(4),
1330                    value: Value::Int(v),
1331                }) => {
1332                    f_cooling_setpoint = Some(
1333                        i16::try_from(v)
1334                            .map_err(|_| ClusterError::InvalidLength("CoolingSetpoint"))?,
1335                    )
1336                }
1337                Some(Element::Scalar {
1338                    tag: Tag::Context(5),
1339                    value: Value::Int(v),
1340                }) => {
1341                    f_heating_setpoint = Some(
1342                        i16::try_from(v)
1343                            .map_err(|_| ClusterError::InvalidLength("HeatingSetpoint"))?,
1344                    )
1345                }
1346                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1347                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1348                Some(_) => {} // unknown/future scalar — skip
1349            }
1350        }
1351        Ok(Self {
1352            day_of_week: f_day_of_week.ok_or(ClusterError::MissingField("DayOfWeek"))?,
1353            transition_time: f_transition_time
1354                .ok_or(ClusterError::MissingField("TransitionTime"))?,
1355            preset_handle: f_preset_handle,
1356            system_mode: f_system_mode,
1357            cooling_setpoint: f_cooling_setpoint,
1358            heating_setpoint: f_heating_setpoint,
1359        })
1360    }
1361    /// Decode from a standalone anonymous TLV structure.
1362    ///
1363    /// # Errors
1364    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1365    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1366        let mut r = TlvReader::new(tlv);
1367        match r.next()? {
1368            Some(Element::ContainerStart {
1369                kind: ContainerKind::Structure,
1370                ..
1371            }) => {}
1372            _ => {
1373                return Err(ClusterError::UnexpectedType {
1374                    context: "ScheduleTransitionStruct",
1375                })
1376            }
1377        }
1378        Self::decode_from(&mut r)
1379    }
1380    /// Write this struct's fields into an already-open container.
1381    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1382    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
1383        w.put_uint(Tag::Context(0), u64::from(self.day_of_week.bits()))
1384            .expect("infallible: vec writer");
1385        w.put_uint(Tag::Context(1), u64::from(self.transition_time))
1386            .expect("infallible: vec writer");
1387        if let Some(preset_handle) = &self.preset_handle {
1388            w.put_bytes(Tag::Context(2), &*preset_handle)
1389                .expect("infallible: vec writer");
1390        }
1391        if let Some(system_mode) = &self.system_mode {
1392            w.put_uint(Tag::Context(3), u64::from((*system_mode).to_raw()))
1393                .expect("infallible: vec writer");
1394        }
1395        if let Some(cooling_setpoint) = &self.cooling_setpoint {
1396            w.put_int(Tag::Context(4), i64::from(*cooling_setpoint))
1397                .expect("infallible: vec writer");
1398        }
1399        if let Some(heating_setpoint) = &self.heating_setpoint {
1400            w.put_int(Tag::Context(5), i64::from(*heating_setpoint))
1401                .expect("infallible: vec writer");
1402        }
1403    }
1404    /// Encode as a standalone anonymous TLV structure.
1405    #[must_use]
1406    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1407    pub fn encode(&self) -> Vec<u8> {
1408        let mut buf = Vec::new();
1409        let mut w = TlvWriter::new(&mut buf);
1410        w.start_structure(Tag::Anonymous)
1411            .expect("infallible: vec writer");
1412        self.write_fields(&mut w);
1413        w.end_container().expect("infallible: vec writer");
1414        buf
1415    }
1416}
1417
1418impl ScheduleTypeStruct {
1419    /// Decode the fields of an already-opened anonymous structure
1420    /// (reader positioned after the struct start; consumes to its end).
1421    ///
1422    /// # Errors
1423    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1424    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1425        let mut f_system_mode: Option<SystemModeEnum> = None;
1426        let mut f_number_of_schedules: Option<u8> = None;
1427        let mut f_schedule_type_features: Option<ScheduleTypeFeaturesBitmap> = None;
1428        loop {
1429            match r.next()? {
1430                Some(Element::ContainerEnd) => break,
1431                Some(Element::Scalar {
1432                    tag: Tag::Context(0),
1433                    value: Value::Uint(v),
1434                }) => {
1435                    f_system_mode = Some(SystemModeEnum::from_raw(
1436                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SystemMode"))?,
1437                    ))
1438                }
1439                Some(Element::Scalar {
1440                    tag: Tag::Context(1),
1441                    value: Value::Uint(v),
1442                }) => {
1443                    f_number_of_schedules = Some(
1444                        u8::try_from(v)
1445                            .map_err(|_| ClusterError::InvalidLength("NumberOfSchedules"))?,
1446                    )
1447                }
1448                Some(Element::Scalar {
1449                    tag: Tag::Context(2),
1450                    value: Value::Uint(v),
1451                }) => {
1452                    f_schedule_type_features = Some(ScheduleTypeFeaturesBitmap::from_bits_retain(
1453                        u16::try_from(v)
1454                            .map_err(|_| ClusterError::InvalidLength("ScheduleTypeFeatures"))?,
1455                    ))
1456                }
1457                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1458                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1459                Some(_) => {} // unknown/future scalar — skip
1460            }
1461        }
1462        Ok(Self {
1463            system_mode: f_system_mode.ok_or(ClusterError::MissingField("SystemMode"))?,
1464            number_of_schedules: f_number_of_schedules
1465                .ok_or(ClusterError::MissingField("NumberOfSchedules"))?,
1466            schedule_type_features: f_schedule_type_features
1467                .ok_or(ClusterError::MissingField("ScheduleTypeFeatures"))?,
1468        })
1469    }
1470    /// Decode from a standalone anonymous TLV structure.
1471    ///
1472    /// # Errors
1473    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1474    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1475        let mut r = TlvReader::new(tlv);
1476        match r.next()? {
1477            Some(Element::ContainerStart {
1478                kind: ContainerKind::Structure,
1479                ..
1480            }) => {}
1481            _ => {
1482                return Err(ClusterError::UnexpectedType {
1483                    context: "ScheduleTypeStruct",
1484                })
1485            }
1486        }
1487        Self::decode_from(&mut r)
1488    }
1489    /// Write this struct's fields into an already-open container.
1490    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1491    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
1492        w.put_uint(Tag::Context(0), u64::from(self.system_mode.to_raw()))
1493            .expect("infallible: vec writer");
1494        w.put_uint(Tag::Context(1), u64::from(self.number_of_schedules))
1495            .expect("infallible: vec writer");
1496        w.put_uint(
1497            Tag::Context(2),
1498            u64::from(self.schedule_type_features.bits()),
1499        )
1500        .expect("infallible: vec writer");
1501    }
1502    /// Encode as a standalone anonymous TLV structure.
1503    #[must_use]
1504    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1505    pub fn encode(&self) -> Vec<u8> {
1506        let mut buf = Vec::new();
1507        let mut w = TlvWriter::new(&mut buf);
1508        w.start_structure(Tag::Anonymous)
1509            .expect("infallible: vec writer");
1510        self.write_fields(&mut w);
1511        w.end_container().expect("infallible: vec writer");
1512        buf
1513    }
1514}
1515
1516impl ThermostatAttributeStatusEntryStruct {
1517    /// Decode the fields of an already-opened anonymous structure
1518    /// (reader positioned after the struct start; consumes to its end).
1519    ///
1520    /// # Errors
1521    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1522    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1523        let mut f_attribute_id: Option<u32> = None;
1524        let mut f_status_code: Option<u8> = None;
1525        loop {
1526            match r.next()? {
1527                Some(Element::ContainerEnd) => break,
1528                Some(Element::Scalar {
1529                    tag: Tag::Context(0),
1530                    value: Value::Uint(v),
1531                }) => {
1532                    f_attribute_id = Some(
1533                        u32::try_from(v).map_err(|_| ClusterError::InvalidLength("AttributeId"))?,
1534                    )
1535                }
1536                Some(Element::Scalar {
1537                    tag: Tag::Context(1),
1538                    value: Value::Uint(v),
1539                }) => {
1540                    f_status_code = Some(
1541                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StatusCode"))?,
1542                    )
1543                }
1544                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1545                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1546                Some(_) => {} // unknown/future scalar — skip
1547            }
1548        }
1549        Ok(Self {
1550            attribute_id: f_attribute_id.ok_or(ClusterError::MissingField("AttributeId"))?,
1551            status_code: f_status_code.ok_or(ClusterError::MissingField("StatusCode"))?,
1552        })
1553    }
1554    /// Decode from a standalone anonymous TLV structure.
1555    ///
1556    /// # Errors
1557    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1558    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1559        let mut r = TlvReader::new(tlv);
1560        match r.next()? {
1561            Some(Element::ContainerStart {
1562                kind: ContainerKind::Structure,
1563                ..
1564            }) => {}
1565            _ => {
1566                return Err(ClusterError::UnexpectedType {
1567                    context: "ThermostatAttributeStatusEntryStruct",
1568                })
1569            }
1570        }
1571        Self::decode_from(&mut r)
1572    }
1573    /// Write this struct's fields into an already-open container.
1574    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1575    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
1576        w.put_uint(Tag::Context(0), u64::from(self.attribute_id))
1577            .expect("infallible: vec writer");
1578        w.put_uint(Tag::Context(1), u64::from(self.status_code))
1579            .expect("infallible: vec writer");
1580    }
1581    /// Encode as a standalone anonymous TLV structure.
1582    #[must_use]
1583    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1584    pub fn encode(&self) -> Vec<u8> {
1585        let mut buf = Vec::new();
1586        let mut w = TlvWriter::new(&mut buf);
1587        w.start_structure(Tag::Anonymous)
1588            .expect("infallible: vec writer");
1589        self.write_fields(&mut w);
1590        w.end_container().expect("infallible: vec writer");
1591        buf
1592    }
1593}
1594
1595impl WeeklyScheduleTransitionStruct {
1596    /// Decode the fields of an already-opened anonymous structure
1597    /// (reader positioned after the struct start; consumes to its end).
1598    ///
1599    /// # Errors
1600    /// Returns [`ClusterError`] on a malformed structure or missing required field.
1601    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1602        let mut f_transition_time: Option<u16> = None;
1603        let mut f_heat_setpoint: Option<Nullable<i16>> = None;
1604        let mut f_cool_setpoint: Option<Nullable<i16>> = None;
1605        loop {
1606            match r.next()? {
1607                Some(Element::ContainerEnd) => break,
1608                Some(Element::Scalar {
1609                    tag: Tag::Context(0),
1610                    value: Value::Uint(v),
1611                }) => {
1612                    f_transition_time = Some(
1613                        u16::try_from(v)
1614                            .map_err(|_| ClusterError::InvalidLength("TransitionTime"))?,
1615                    )
1616                }
1617                Some(Element::Scalar {
1618                    tag: Tag::Context(1),
1619                    value: Value::Null,
1620                }) => f_heat_setpoint = Some(Nullable::Null),
1621                Some(Element::Scalar {
1622                    tag: Tag::Context(1),
1623                    value: Value::Int(v),
1624                }) => {
1625                    f_heat_setpoint = Some(Nullable::Value(
1626                        i16::try_from(v)
1627                            .map_err(|_| ClusterError::InvalidLength("HeatSetpoint"))?,
1628                    ))
1629                }
1630                Some(Element::Scalar {
1631                    tag: Tag::Context(2),
1632                    value: Value::Null,
1633                }) => f_cool_setpoint = Some(Nullable::Null),
1634                Some(Element::Scalar {
1635                    tag: Tag::Context(2),
1636                    value: Value::Int(v),
1637                }) => {
1638                    f_cool_setpoint = Some(Nullable::Value(
1639                        i16::try_from(v)
1640                            .map_err(|_| ClusterError::InvalidLength("CoolSetpoint"))?,
1641                    ))
1642                }
1643                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1644                Some(Element::ContainerStart { .. }) => r.skip_container()?,
1645                Some(_) => {} // unknown/future scalar — skip
1646            }
1647        }
1648        Ok(Self {
1649            transition_time: f_transition_time
1650                .ok_or(ClusterError::MissingField("TransitionTime"))?,
1651            heat_setpoint: f_heat_setpoint.ok_or(ClusterError::MissingField("HeatSetpoint"))?,
1652            cool_setpoint: f_cool_setpoint.ok_or(ClusterError::MissingField("CoolSetpoint"))?,
1653        })
1654    }
1655    /// Decode from a standalone anonymous TLV structure.
1656    ///
1657    /// # Errors
1658    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
1659    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1660        let mut r = TlvReader::new(tlv);
1661        match r.next()? {
1662            Some(Element::ContainerStart {
1663                kind: ContainerKind::Structure,
1664                ..
1665            }) => {}
1666            _ => {
1667                return Err(ClusterError::UnexpectedType {
1668                    context: "WeeklyScheduleTransitionStruct",
1669                })
1670            }
1671        }
1672        Self::decode_from(&mut r)
1673    }
1674    /// Write this struct's fields into an already-open container.
1675    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1676    pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
1677        w.put_uint(Tag::Context(0), u64::from(self.transition_time))
1678            .expect("infallible: vec writer");
1679        match &self.heat_setpoint {
1680            Nullable::Null => w.put_null(Tag::Context(1)).expect("infallible: vec writer"),
1681            Nullable::Value(heat_setpoint) => {
1682                w.put_int(Tag::Context(1), i64::from(*heat_setpoint))
1683                    .expect("infallible: vec writer");
1684            }
1685        }
1686        match &self.cool_setpoint {
1687            Nullable::Null => w.put_null(Tag::Context(2)).expect("infallible: vec writer"),
1688            Nullable::Value(cool_setpoint) => {
1689                w.put_int(Tag::Context(2), i64::from(*cool_setpoint))
1690                    .expect("infallible: vec writer");
1691            }
1692        }
1693    }
1694    /// Encode as a standalone anonymous TLV structure.
1695    #[must_use]
1696    #[allow(clippy::expect_used)] // Vec-backed TlvWriter is infallible.
1697    pub fn encode(&self) -> Vec<u8> {
1698        let mut buf = Vec::new();
1699        let mut w = TlvWriter::new(&mut buf);
1700        w.start_structure(Tag::Anonymous)
1701            .expect("infallible: vec writer");
1702        self.write_fields(&mut w);
1703        w.end_container().expect("infallible: vec writer");
1704        buf
1705    }
1706}
1707
1708/// Decode the `LocalTemperature` attribute value.
1709///
1710/// # Errors
1711/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1712pub fn decode_local_temperature(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
1713    let mut r = TlvReader::new(tlv);
1714    match r.next()? {
1715        Some(Element::Scalar {
1716            value: Value::Null, ..
1717        }) => Ok(Nullable::Null),
1718        Some(Element::Scalar {
1719            value: Value::Int(v),
1720            ..
1721        }) => {
1722            Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
1723                ClusterError::InvalidLength("LocalTemperature")
1724            })?))
1725        }
1726        _ => Err(ClusterError::UnexpectedType {
1727            context: "LocalTemperature",
1728        }),
1729    }
1730}
1731
1732/// Decode the `OutdoorTemperature` attribute value.
1733///
1734/// # Errors
1735/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1736pub fn decode_outdoor_temperature(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
1737    let mut r = TlvReader::new(tlv);
1738    match r.next()? {
1739        Some(Element::Scalar {
1740            value: Value::Null, ..
1741        }) => Ok(Nullable::Null),
1742        Some(Element::Scalar {
1743            value: Value::Int(v),
1744            ..
1745        }) => Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
1746            ClusterError::InvalidLength("OutdoorTemperature")
1747        })?)),
1748        _ => Err(ClusterError::UnexpectedType {
1749            context: "OutdoorTemperature",
1750        }),
1751    }
1752}
1753
1754/// Decode the `Occupancy` attribute value.
1755///
1756/// # Errors
1757/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1758pub fn decode_occupancy(tlv: &[u8]) -> Result<OccupancyBitmap, ClusterError> {
1759    let mut r = TlvReader::new(tlv);
1760    match r.next()? {
1761        Some(Element::Scalar {
1762            value: Value::Uint(v),
1763            ..
1764        }) => Ok(OccupancyBitmap::from_bits_retain(
1765            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Occupancy"))?,
1766        )),
1767        _ => Err(ClusterError::UnexpectedType {
1768            context: "Occupancy",
1769        }),
1770    }
1771}
1772
1773/// Decode the `AbsMinHeatSetpointLimit` attribute value.
1774///
1775/// # Errors
1776/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1777pub fn decode_abs_min_heat_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
1778    let mut r = TlvReader::new(tlv);
1779    match r.next()? {
1780        Some(Element::Scalar {
1781            value: Value::Int(v),
1782            ..
1783        }) => {
1784            Ok(i16::try_from(v)
1785                .map_err(|_| ClusterError::InvalidLength("AbsMinHeatSetpointLimit"))?)
1786        }
1787        _ => Err(ClusterError::UnexpectedType {
1788            context: "AbsMinHeatSetpointLimit",
1789        }),
1790    }
1791}
1792
1793/// Decode the `AbsMaxHeatSetpointLimit` attribute value.
1794///
1795/// # Errors
1796/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1797pub fn decode_abs_max_heat_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
1798    let mut r = TlvReader::new(tlv);
1799    match r.next()? {
1800        Some(Element::Scalar {
1801            value: Value::Int(v),
1802            ..
1803        }) => {
1804            Ok(i16::try_from(v)
1805                .map_err(|_| ClusterError::InvalidLength("AbsMaxHeatSetpointLimit"))?)
1806        }
1807        _ => Err(ClusterError::UnexpectedType {
1808            context: "AbsMaxHeatSetpointLimit",
1809        }),
1810    }
1811}
1812
1813/// Decode the `AbsMinCoolSetpointLimit` attribute value.
1814///
1815/// # Errors
1816/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1817pub fn decode_abs_min_cool_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
1818    let mut r = TlvReader::new(tlv);
1819    match r.next()? {
1820        Some(Element::Scalar {
1821            value: Value::Int(v),
1822            ..
1823        }) => {
1824            Ok(i16::try_from(v)
1825                .map_err(|_| ClusterError::InvalidLength("AbsMinCoolSetpointLimit"))?)
1826        }
1827        _ => Err(ClusterError::UnexpectedType {
1828            context: "AbsMinCoolSetpointLimit",
1829        }),
1830    }
1831}
1832
1833/// Decode the `AbsMaxCoolSetpointLimit` attribute value.
1834///
1835/// # Errors
1836/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1837pub fn decode_abs_max_cool_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
1838    let mut r = TlvReader::new(tlv);
1839    match r.next()? {
1840        Some(Element::Scalar {
1841            value: Value::Int(v),
1842            ..
1843        }) => {
1844            Ok(i16::try_from(v)
1845                .map_err(|_| ClusterError::InvalidLength("AbsMaxCoolSetpointLimit"))?)
1846        }
1847        _ => Err(ClusterError::UnexpectedType {
1848            context: "AbsMaxCoolSetpointLimit",
1849        }),
1850    }
1851}
1852
1853/// Decode the `LocalTemperatureCalibration` attribute value.
1854///
1855/// # Errors
1856/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1857pub fn decode_local_temperature_calibration(tlv: &[u8]) -> Result<i8, ClusterError> {
1858    let mut r = TlvReader::new(tlv);
1859    match r.next()? {
1860        Some(Element::Scalar {
1861            value: Value::Int(v),
1862            ..
1863        }) => Ok(i8::try_from(v)
1864            .map_err(|_| ClusterError::InvalidLength("LocalTemperatureCalibration"))?),
1865        _ => Err(ClusterError::UnexpectedType {
1866            context: "LocalTemperatureCalibration",
1867        }),
1868    }
1869}
1870
1871/// Encode the `LocalTemperatureCalibration` attribute value as a standalone TLV element.
1872#[must_use]
1873#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1874pub fn encode_local_temperature_calibration(value: i8) -> Vec<u8> {
1875    let mut buf = Vec::new();
1876    let mut w = TlvWriter::new(&mut buf);
1877    w.put_int(Tag::Anonymous, i64::from(value))
1878        .expect("infallible: vec writer");
1879    buf
1880}
1881
1882/// Decode the `OccupiedCoolingSetpoint` attribute value.
1883///
1884/// # Errors
1885/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1886pub fn decode_occupied_cooling_setpoint(tlv: &[u8]) -> Result<i16, ClusterError> {
1887    let mut r = TlvReader::new(tlv);
1888    match r.next()? {
1889        Some(Element::Scalar {
1890            value: Value::Int(v),
1891            ..
1892        }) => {
1893            Ok(i16::try_from(v)
1894                .map_err(|_| ClusterError::InvalidLength("OccupiedCoolingSetpoint"))?)
1895        }
1896        _ => Err(ClusterError::UnexpectedType {
1897            context: "OccupiedCoolingSetpoint",
1898        }),
1899    }
1900}
1901
1902/// Encode the `OccupiedCoolingSetpoint` attribute value as a standalone TLV element.
1903#[must_use]
1904#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1905pub fn encode_occupied_cooling_setpoint(value: i16) -> Vec<u8> {
1906    let mut buf = Vec::new();
1907    let mut w = TlvWriter::new(&mut buf);
1908    w.put_int(Tag::Anonymous, i64::from(value))
1909        .expect("infallible: vec writer");
1910    buf
1911}
1912
1913/// Decode the `OccupiedHeatingSetpoint` attribute value.
1914///
1915/// # Errors
1916/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1917pub fn decode_occupied_heating_setpoint(tlv: &[u8]) -> Result<i16, ClusterError> {
1918    let mut r = TlvReader::new(tlv);
1919    match r.next()? {
1920        Some(Element::Scalar {
1921            value: Value::Int(v),
1922            ..
1923        }) => {
1924            Ok(i16::try_from(v)
1925                .map_err(|_| ClusterError::InvalidLength("OccupiedHeatingSetpoint"))?)
1926        }
1927        _ => Err(ClusterError::UnexpectedType {
1928            context: "OccupiedHeatingSetpoint",
1929        }),
1930    }
1931}
1932
1933/// Encode the `OccupiedHeatingSetpoint` attribute value as a standalone TLV element.
1934#[must_use]
1935#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1936pub fn encode_occupied_heating_setpoint(value: i16) -> Vec<u8> {
1937    let mut buf = Vec::new();
1938    let mut w = TlvWriter::new(&mut buf);
1939    w.put_int(Tag::Anonymous, i64::from(value))
1940        .expect("infallible: vec writer");
1941    buf
1942}
1943
1944/// Decode the `UnoccupiedCoolingSetpoint` attribute value.
1945///
1946/// # Errors
1947/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1948pub fn decode_unoccupied_cooling_setpoint(tlv: &[u8]) -> Result<i16, ClusterError> {
1949    let mut r = TlvReader::new(tlv);
1950    match r.next()? {
1951        Some(Element::Scalar {
1952            value: Value::Int(v),
1953            ..
1954        }) => Ok(i16::try_from(v)
1955            .map_err(|_| ClusterError::InvalidLength("UnoccupiedCoolingSetpoint"))?),
1956        _ => Err(ClusterError::UnexpectedType {
1957            context: "UnoccupiedCoolingSetpoint",
1958        }),
1959    }
1960}
1961
1962/// Encode the `UnoccupiedCoolingSetpoint` attribute value as a standalone TLV element.
1963#[must_use]
1964#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1965pub fn encode_unoccupied_cooling_setpoint(value: i16) -> Vec<u8> {
1966    let mut buf = Vec::new();
1967    let mut w = TlvWriter::new(&mut buf);
1968    w.put_int(Tag::Anonymous, i64::from(value))
1969        .expect("infallible: vec writer");
1970    buf
1971}
1972
1973/// Decode the `UnoccupiedHeatingSetpoint` attribute value.
1974///
1975/// # Errors
1976/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
1977pub fn decode_unoccupied_heating_setpoint(tlv: &[u8]) -> Result<i16, ClusterError> {
1978    let mut r = TlvReader::new(tlv);
1979    match r.next()? {
1980        Some(Element::Scalar {
1981            value: Value::Int(v),
1982            ..
1983        }) => Ok(i16::try_from(v)
1984            .map_err(|_| ClusterError::InvalidLength("UnoccupiedHeatingSetpoint"))?),
1985        _ => Err(ClusterError::UnexpectedType {
1986            context: "UnoccupiedHeatingSetpoint",
1987        }),
1988    }
1989}
1990
1991/// Encode the `UnoccupiedHeatingSetpoint` attribute value as a standalone TLV element.
1992#[must_use]
1993#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
1994pub fn encode_unoccupied_heating_setpoint(value: i16) -> Vec<u8> {
1995    let mut buf = Vec::new();
1996    let mut w = TlvWriter::new(&mut buf);
1997    w.put_int(Tag::Anonymous, i64::from(value))
1998        .expect("infallible: vec writer");
1999    buf
2000}
2001
2002/// Decode the `MinHeatSetpointLimit` attribute value.
2003///
2004/// # Errors
2005/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2006pub fn decode_min_heat_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
2007    let mut r = TlvReader::new(tlv);
2008    match r.next()? {
2009        Some(Element::Scalar {
2010            value: Value::Int(v),
2011            ..
2012        }) => Ok(i16::try_from(v).map_err(|_| ClusterError::InvalidLength("MinHeatSetpointLimit"))?),
2013        _ => Err(ClusterError::UnexpectedType {
2014            context: "MinHeatSetpointLimit",
2015        }),
2016    }
2017}
2018
2019/// Encode the `MinHeatSetpointLimit` attribute value as a standalone TLV element.
2020#[must_use]
2021#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2022pub fn encode_min_heat_setpoint_limit(value: i16) -> Vec<u8> {
2023    let mut buf = Vec::new();
2024    let mut w = TlvWriter::new(&mut buf);
2025    w.put_int(Tag::Anonymous, i64::from(value))
2026        .expect("infallible: vec writer");
2027    buf
2028}
2029
2030/// Decode the `MaxHeatSetpointLimit` attribute value.
2031///
2032/// # Errors
2033/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2034pub fn decode_max_heat_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
2035    let mut r = TlvReader::new(tlv);
2036    match r.next()? {
2037        Some(Element::Scalar {
2038            value: Value::Int(v),
2039            ..
2040        }) => Ok(i16::try_from(v).map_err(|_| ClusterError::InvalidLength("MaxHeatSetpointLimit"))?),
2041        _ => Err(ClusterError::UnexpectedType {
2042            context: "MaxHeatSetpointLimit",
2043        }),
2044    }
2045}
2046
2047/// Encode the `MaxHeatSetpointLimit` attribute value as a standalone TLV element.
2048#[must_use]
2049#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2050pub fn encode_max_heat_setpoint_limit(value: i16) -> Vec<u8> {
2051    let mut buf = Vec::new();
2052    let mut w = TlvWriter::new(&mut buf);
2053    w.put_int(Tag::Anonymous, i64::from(value))
2054        .expect("infallible: vec writer");
2055    buf
2056}
2057
2058/// Decode the `MinCoolSetpointLimit` attribute value.
2059///
2060/// # Errors
2061/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2062pub fn decode_min_cool_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
2063    let mut r = TlvReader::new(tlv);
2064    match r.next()? {
2065        Some(Element::Scalar {
2066            value: Value::Int(v),
2067            ..
2068        }) => Ok(i16::try_from(v).map_err(|_| ClusterError::InvalidLength("MinCoolSetpointLimit"))?),
2069        _ => Err(ClusterError::UnexpectedType {
2070            context: "MinCoolSetpointLimit",
2071        }),
2072    }
2073}
2074
2075/// Encode the `MinCoolSetpointLimit` attribute value as a standalone TLV element.
2076#[must_use]
2077#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2078pub fn encode_min_cool_setpoint_limit(value: i16) -> Vec<u8> {
2079    let mut buf = Vec::new();
2080    let mut w = TlvWriter::new(&mut buf);
2081    w.put_int(Tag::Anonymous, i64::from(value))
2082        .expect("infallible: vec writer");
2083    buf
2084}
2085
2086/// Decode the `MaxCoolSetpointLimit` attribute value.
2087///
2088/// # Errors
2089/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2090pub fn decode_max_cool_setpoint_limit(tlv: &[u8]) -> Result<i16, ClusterError> {
2091    let mut r = TlvReader::new(tlv);
2092    match r.next()? {
2093        Some(Element::Scalar {
2094            value: Value::Int(v),
2095            ..
2096        }) => Ok(i16::try_from(v).map_err(|_| ClusterError::InvalidLength("MaxCoolSetpointLimit"))?),
2097        _ => Err(ClusterError::UnexpectedType {
2098            context: "MaxCoolSetpointLimit",
2099        }),
2100    }
2101}
2102
2103/// Encode the `MaxCoolSetpointLimit` attribute value as a standalone TLV element.
2104#[must_use]
2105#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2106pub fn encode_max_cool_setpoint_limit(value: i16) -> Vec<u8> {
2107    let mut buf = Vec::new();
2108    let mut w = TlvWriter::new(&mut buf);
2109    w.put_int(Tag::Anonymous, i64::from(value))
2110        .expect("infallible: vec writer");
2111    buf
2112}
2113
2114/// Decode the `MinSetpointDeadBand` attribute value.
2115///
2116/// # Errors
2117/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2118pub fn decode_min_setpoint_dead_band(tlv: &[u8]) -> Result<i8, ClusterError> {
2119    let mut r = TlvReader::new(tlv);
2120    match r.next()? {
2121        Some(Element::Scalar {
2122            value: Value::Int(v),
2123            ..
2124        }) => Ok(i8::try_from(v).map_err(|_| ClusterError::InvalidLength("MinSetpointDeadBand"))?),
2125        _ => Err(ClusterError::UnexpectedType {
2126            context: "MinSetpointDeadBand",
2127        }),
2128    }
2129}
2130
2131/// Encode the `MinSetpointDeadBand` attribute value as a standalone TLV element.
2132#[must_use]
2133#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2134pub fn encode_min_setpoint_dead_band(value: i8) -> Vec<u8> {
2135    let mut buf = Vec::new();
2136    let mut w = TlvWriter::new(&mut buf);
2137    w.put_int(Tag::Anonymous, i64::from(value))
2138        .expect("infallible: vec writer");
2139    buf
2140}
2141
2142/// Decode the `RemoteSensing` attribute value.
2143///
2144/// # Errors
2145/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2146pub fn decode_remote_sensing(tlv: &[u8]) -> Result<RemoteSensingBitmap, ClusterError> {
2147    let mut r = TlvReader::new(tlv);
2148    match r.next()? {
2149        Some(Element::Scalar {
2150            value: Value::Uint(v),
2151            ..
2152        }) => Ok(RemoteSensingBitmap::from_bits_retain(
2153            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("RemoteSensing"))?,
2154        )),
2155        _ => Err(ClusterError::UnexpectedType {
2156            context: "RemoteSensing",
2157        }),
2158    }
2159}
2160
2161/// Encode the `RemoteSensing` attribute value as a standalone TLV element.
2162#[must_use]
2163#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2164pub fn encode_remote_sensing(value: RemoteSensingBitmap) -> Vec<u8> {
2165    let mut buf = Vec::new();
2166    let mut w = TlvWriter::new(&mut buf);
2167    w.put_uint(Tag::Anonymous, u64::from(value.bits()))
2168        .expect("infallible: vec writer");
2169    buf
2170}
2171
2172/// Decode the `ControlSequenceOfOperation` attribute value.
2173///
2174/// # Errors
2175/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2176pub fn decode_control_sequence_of_operation(
2177    tlv: &[u8],
2178) -> Result<ControlSequenceOfOperationEnum, ClusterError> {
2179    let mut r = TlvReader::new(tlv);
2180    match r.next()? {
2181        Some(Element::Scalar {
2182            value: Value::Uint(v),
2183            ..
2184        }) => Ok(ControlSequenceOfOperationEnum::from_raw(
2185            u8::try_from(v)
2186                .map_err(|_| ClusterError::InvalidLength("ControlSequenceOfOperation"))?,
2187        )),
2188        _ => Err(ClusterError::UnexpectedType {
2189            context: "ControlSequenceOfOperation",
2190        }),
2191    }
2192}
2193
2194/// Encode the `ControlSequenceOfOperation` attribute value as a standalone TLV element.
2195#[must_use]
2196#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2197pub fn encode_control_sequence_of_operation(value: ControlSequenceOfOperationEnum) -> Vec<u8> {
2198    let mut buf = Vec::new();
2199    let mut w = TlvWriter::new(&mut buf);
2200    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2201        .expect("infallible: vec writer");
2202    buf
2203}
2204
2205/// Decode the `SystemMode` attribute value.
2206///
2207/// # Errors
2208/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2209pub fn decode_system_mode(tlv: &[u8]) -> Result<SystemModeEnum, ClusterError> {
2210    let mut r = TlvReader::new(tlv);
2211    match r.next()? {
2212        Some(Element::Scalar {
2213            value: Value::Uint(v),
2214            ..
2215        }) => Ok(SystemModeEnum::from_raw(
2216            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SystemMode"))?,
2217        )),
2218        _ => Err(ClusterError::UnexpectedType {
2219            context: "SystemMode",
2220        }),
2221    }
2222}
2223
2224/// Encode the `SystemMode` attribute value as a standalone TLV element.
2225#[must_use]
2226#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2227pub fn encode_system_mode(value: SystemModeEnum) -> Vec<u8> {
2228    let mut buf = Vec::new();
2229    let mut w = TlvWriter::new(&mut buf);
2230    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2231        .expect("infallible: vec writer");
2232    buf
2233}
2234
2235/// Decode the `ThermostatRunningMode` attribute value.
2236///
2237/// # Errors
2238/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2239pub fn decode_thermostat_running_mode(
2240    tlv: &[u8],
2241) -> Result<ThermostatRunningModeEnum, ClusterError> {
2242    let mut r = TlvReader::new(tlv);
2243    match r.next()? {
2244        Some(Element::Scalar {
2245            value: Value::Uint(v),
2246            ..
2247        }) => Ok(ThermostatRunningModeEnum::from_raw(
2248            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("ThermostatRunningMode"))?,
2249        )),
2250        _ => Err(ClusterError::UnexpectedType {
2251            context: "ThermostatRunningMode",
2252        }),
2253    }
2254}
2255
2256/// Decode the `TemperatureSetpointHold` attribute value.
2257///
2258/// # Errors
2259/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2260pub fn decode_temperature_setpoint_hold(
2261    tlv: &[u8],
2262) -> Result<TemperatureSetpointHoldEnum, ClusterError> {
2263    let mut r = TlvReader::new(tlv);
2264    match r.next()? {
2265        Some(Element::Scalar {
2266            value: Value::Uint(v),
2267            ..
2268        }) => Ok(TemperatureSetpointHoldEnum::from_raw(
2269            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("TemperatureSetpointHold"))?,
2270        )),
2271        _ => Err(ClusterError::UnexpectedType {
2272            context: "TemperatureSetpointHold",
2273        }),
2274    }
2275}
2276
2277/// Encode the `TemperatureSetpointHold` attribute value as a standalone TLV element.
2278#[must_use]
2279#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2280pub fn encode_temperature_setpoint_hold(value: TemperatureSetpointHoldEnum) -> Vec<u8> {
2281    let mut buf = Vec::new();
2282    let mut w = TlvWriter::new(&mut buf);
2283    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2284        .expect("infallible: vec writer");
2285    buf
2286}
2287
2288/// Decode the `TemperatureSetpointHoldDuration` attribute value.
2289///
2290/// # Errors
2291/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2292pub fn decode_temperature_setpoint_hold_duration(
2293    tlv: &[u8],
2294) -> Result<Nullable<u16>, ClusterError> {
2295    let mut r = TlvReader::new(tlv);
2296    match r.next()? {
2297        Some(Element::Scalar {
2298            value: Value::Null, ..
2299        }) => Ok(Nullable::Null),
2300        Some(Element::Scalar {
2301            value: Value::Uint(v),
2302            ..
2303        }) => Ok(Nullable::Value(u16::try_from(v).map_err(|_| {
2304            ClusterError::InvalidLength("TemperatureSetpointHoldDuration")
2305        })?)),
2306        _ => Err(ClusterError::UnexpectedType {
2307            context: "TemperatureSetpointHoldDuration",
2308        }),
2309    }
2310}
2311
2312/// Encode the `TemperatureSetpointHoldDuration` attribute value as a standalone TLV element.
2313#[must_use]
2314#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2315pub fn encode_temperature_setpoint_hold_duration(value: Nullable<u16>) -> Vec<u8> {
2316    let mut buf = Vec::new();
2317    let mut w = TlvWriter::new(&mut buf);
2318    match value {
2319        Nullable::Null => w.put_null(Tag::Anonymous).expect("infallible: vec writer"),
2320        Nullable::Value(value) => {
2321            w.put_uint(Tag::Anonymous, u64::from(value))
2322                .expect("infallible: vec writer");
2323        }
2324    }
2325    buf
2326}
2327
2328/// Decode the `ThermostatRunningState` attribute value.
2329///
2330/// # Errors
2331/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2332pub fn decode_thermostat_running_state(tlv: &[u8]) -> Result<RelayStateBitmap, ClusterError> {
2333    let mut r = TlvReader::new(tlv);
2334    match r.next()? {
2335        Some(Element::Scalar {
2336            value: Value::Uint(v),
2337            ..
2338        }) => Ok(RelayStateBitmap::from_bits_retain(
2339            u16::try_from(v).map_err(|_| ClusterError::InvalidLength("ThermostatRunningState"))?,
2340        )),
2341        _ => Err(ClusterError::UnexpectedType {
2342            context: "ThermostatRunningState",
2343        }),
2344    }
2345}
2346
2347/// Decode the `SetpointChangeSource` attribute value.
2348///
2349/// # Errors
2350/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2351pub fn decode_setpoint_change_source(tlv: &[u8]) -> Result<SetpointChangeSourceEnum, ClusterError> {
2352    let mut r = TlvReader::new(tlv);
2353    match r.next()? {
2354        Some(Element::Scalar {
2355            value: Value::Uint(v),
2356            ..
2357        }) => Ok(SetpointChangeSourceEnum::from_raw(
2358            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SetpointChangeSource"))?,
2359        )),
2360        _ => Err(ClusterError::UnexpectedType {
2361            context: "SetpointChangeSource",
2362        }),
2363    }
2364}
2365
2366/// Decode the `SetpointChangeAmount` attribute value.
2367///
2368/// # Errors
2369/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2370pub fn decode_setpoint_change_amount(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
2371    let mut r = TlvReader::new(tlv);
2372    match r.next()? {
2373        Some(Element::Scalar {
2374            value: Value::Null, ..
2375        }) => Ok(Nullable::Null),
2376        Some(Element::Scalar {
2377            value: Value::Int(v),
2378            ..
2379        }) => Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
2380            ClusterError::InvalidLength("SetpointChangeAmount")
2381        })?)),
2382        _ => Err(ClusterError::UnexpectedType {
2383            context: "SetpointChangeAmount",
2384        }),
2385    }
2386}
2387
2388/// Decode the `SetpointChangeSourceTimestamp` attribute value.
2389///
2390/// # Errors
2391/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2392pub fn decode_setpoint_change_source_timestamp(tlv: &[u8]) -> Result<u32, ClusterError> {
2393    let mut r = TlvReader::new(tlv);
2394    match r.next()? {
2395        Some(Element::Scalar {
2396            value: Value::Uint(v),
2397            ..
2398        }) => Ok(u32::try_from(v)
2399            .map_err(|_| ClusterError::InvalidLength("SetpointChangeSourceTimestamp"))?),
2400        _ => Err(ClusterError::UnexpectedType {
2401            context: "SetpointChangeSourceTimestamp",
2402        }),
2403    }
2404}
2405
2406/// Decode the `EmergencyHeatDelta` attribute value.
2407///
2408/// # Errors
2409/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2410pub fn decode_emergency_heat_delta(tlv: &[u8]) -> Result<u8, ClusterError> {
2411    let mut r = TlvReader::new(tlv);
2412    match r.next()? {
2413        Some(Element::Scalar {
2414            value: Value::Uint(v),
2415            ..
2416        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("EmergencyHeatDelta"))?),
2417        _ => Err(ClusterError::UnexpectedType {
2418            context: "EmergencyHeatDelta",
2419        }),
2420    }
2421}
2422
2423/// Encode the `EmergencyHeatDelta` attribute value as a standalone TLV element.
2424#[must_use]
2425#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2426pub fn encode_emergency_heat_delta(value: u8) -> Vec<u8> {
2427    let mut buf = Vec::new();
2428    let mut w = TlvWriter::new(&mut buf);
2429    w.put_uint(Tag::Anonymous, u64::from(value))
2430        .expect("infallible: vec writer");
2431    buf
2432}
2433
2434/// Decode the `AcType` attribute value.
2435///
2436/// # Errors
2437/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2438pub fn decode_ac_type(tlv: &[u8]) -> Result<ACTypeEnum, ClusterError> {
2439    let mut r = TlvReader::new(tlv);
2440    match r.next()? {
2441        Some(Element::Scalar {
2442            value: Value::Uint(v),
2443            ..
2444        }) => Ok(ACTypeEnum::from_raw(
2445            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("AcType"))?,
2446        )),
2447        _ => Err(ClusterError::UnexpectedType { context: "AcType" }),
2448    }
2449}
2450
2451/// Encode the `AcType` attribute value as a standalone TLV element.
2452#[must_use]
2453#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2454pub fn encode_ac_type(value: ACTypeEnum) -> Vec<u8> {
2455    let mut buf = Vec::new();
2456    let mut w = TlvWriter::new(&mut buf);
2457    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2458        .expect("infallible: vec writer");
2459    buf
2460}
2461
2462/// Decode the `AcCapacity` attribute value.
2463///
2464/// # Errors
2465/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2466pub fn decode_ac_capacity(tlv: &[u8]) -> Result<u16, ClusterError> {
2467    let mut r = TlvReader::new(tlv);
2468    match r.next()? {
2469        Some(Element::Scalar {
2470            value: Value::Uint(v),
2471            ..
2472        }) => Ok(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("AcCapacity"))?),
2473        _ => Err(ClusterError::UnexpectedType {
2474            context: "AcCapacity",
2475        }),
2476    }
2477}
2478
2479/// Encode the `AcCapacity` attribute value as a standalone TLV element.
2480#[must_use]
2481#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2482pub fn encode_ac_capacity(value: u16) -> Vec<u8> {
2483    let mut buf = Vec::new();
2484    let mut w = TlvWriter::new(&mut buf);
2485    w.put_uint(Tag::Anonymous, u64::from(value))
2486        .expect("infallible: vec writer");
2487    buf
2488}
2489
2490/// Decode the `AcRefrigerantType` attribute value.
2491///
2492/// # Errors
2493/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2494pub fn decode_ac_refrigerant_type(tlv: &[u8]) -> Result<ACRefrigerantTypeEnum, ClusterError> {
2495    let mut r = TlvReader::new(tlv);
2496    match r.next()? {
2497        Some(Element::Scalar {
2498            value: Value::Uint(v),
2499            ..
2500        }) => Ok(ACRefrigerantTypeEnum::from_raw(
2501            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("AcRefrigerantType"))?,
2502        )),
2503        _ => Err(ClusterError::UnexpectedType {
2504            context: "AcRefrigerantType",
2505        }),
2506    }
2507}
2508
2509/// Encode the `AcRefrigerantType` attribute value as a standalone TLV element.
2510#[must_use]
2511#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2512pub fn encode_ac_refrigerant_type(value: ACRefrigerantTypeEnum) -> Vec<u8> {
2513    let mut buf = Vec::new();
2514    let mut w = TlvWriter::new(&mut buf);
2515    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2516        .expect("infallible: vec writer");
2517    buf
2518}
2519
2520/// Decode the `AcCompressorType` attribute value.
2521///
2522/// # Errors
2523/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2524pub fn decode_ac_compressor_type(tlv: &[u8]) -> Result<ACCompressorTypeEnum, ClusterError> {
2525    let mut r = TlvReader::new(tlv);
2526    match r.next()? {
2527        Some(Element::Scalar {
2528            value: Value::Uint(v),
2529            ..
2530        }) => Ok(ACCompressorTypeEnum::from_raw(
2531            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("AcCompressorType"))?,
2532        )),
2533        _ => Err(ClusterError::UnexpectedType {
2534            context: "AcCompressorType",
2535        }),
2536    }
2537}
2538
2539/// Encode the `AcCompressorType` attribute value as a standalone TLV element.
2540#[must_use]
2541#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2542pub fn encode_ac_compressor_type(value: ACCompressorTypeEnum) -> Vec<u8> {
2543    let mut buf = Vec::new();
2544    let mut w = TlvWriter::new(&mut buf);
2545    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2546        .expect("infallible: vec writer");
2547    buf
2548}
2549
2550/// Decode the `AcErrorCode` attribute value.
2551///
2552/// # Errors
2553/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2554pub fn decode_ac_error_code(tlv: &[u8]) -> Result<ACErrorCodeBitmap, ClusterError> {
2555    let mut r = TlvReader::new(tlv);
2556    match r.next()? {
2557        Some(Element::Scalar {
2558            value: Value::Uint(v),
2559            ..
2560        }) => Ok(ACErrorCodeBitmap::from_bits_retain(
2561            u32::try_from(v).map_err(|_| ClusterError::InvalidLength("AcErrorCode"))?,
2562        )),
2563        _ => Err(ClusterError::UnexpectedType {
2564            context: "AcErrorCode",
2565        }),
2566    }
2567}
2568
2569/// Encode the `AcErrorCode` attribute value as a standalone TLV element.
2570#[must_use]
2571#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2572pub fn encode_ac_error_code(value: ACErrorCodeBitmap) -> Vec<u8> {
2573    let mut buf = Vec::new();
2574    let mut w = TlvWriter::new(&mut buf);
2575    w.put_uint(Tag::Anonymous, u64::from(value.bits()))
2576        .expect("infallible: vec writer");
2577    buf
2578}
2579
2580/// Decode the `AcLouverPosition` attribute value.
2581///
2582/// # Errors
2583/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2584pub fn decode_ac_louver_position(tlv: &[u8]) -> Result<ACLouverPositionEnum, ClusterError> {
2585    let mut r = TlvReader::new(tlv);
2586    match r.next()? {
2587        Some(Element::Scalar {
2588            value: Value::Uint(v),
2589            ..
2590        }) => Ok(ACLouverPositionEnum::from_raw(
2591            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("AcLouverPosition"))?,
2592        )),
2593        _ => Err(ClusterError::UnexpectedType {
2594            context: "AcLouverPosition",
2595        }),
2596    }
2597}
2598
2599/// Encode the `AcLouverPosition` attribute value as a standalone TLV element.
2600#[must_use]
2601#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2602pub fn encode_ac_louver_position(value: ACLouverPositionEnum) -> Vec<u8> {
2603    let mut buf = Vec::new();
2604    let mut w = TlvWriter::new(&mut buf);
2605    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2606        .expect("infallible: vec writer");
2607    buf
2608}
2609
2610/// Decode the `AcCoilTemperature` attribute value.
2611///
2612/// # Errors
2613/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2614pub fn decode_ac_coil_temperature(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
2615    let mut r = TlvReader::new(tlv);
2616    match r.next()? {
2617        Some(Element::Scalar {
2618            value: Value::Null, ..
2619        }) => Ok(Nullable::Null),
2620        Some(Element::Scalar {
2621            value: Value::Int(v),
2622            ..
2623        }) => {
2624            Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
2625                ClusterError::InvalidLength("AcCoilTemperature")
2626            })?))
2627        }
2628        _ => Err(ClusterError::UnexpectedType {
2629            context: "AcCoilTemperature",
2630        }),
2631    }
2632}
2633
2634/// Decode the `AcCapacityFormat` attribute value.
2635///
2636/// # Errors
2637/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2638pub fn decode_ac_capacity_format(tlv: &[u8]) -> Result<ACCapacityFormatEnum, ClusterError> {
2639    let mut r = TlvReader::new(tlv);
2640    match r.next()? {
2641        Some(Element::Scalar {
2642            value: Value::Uint(v),
2643            ..
2644        }) => Ok(ACCapacityFormatEnum::from_raw(
2645            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("AcCapacityFormat"))?,
2646        )),
2647        _ => Err(ClusterError::UnexpectedType {
2648            context: "AcCapacityFormat",
2649        }),
2650    }
2651}
2652
2653/// Encode the `AcCapacityFormat` attribute value as a standalone TLV element.
2654#[must_use]
2655#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2656pub fn encode_ac_capacity_format(value: ACCapacityFormatEnum) -> Vec<u8> {
2657    let mut buf = Vec::new();
2658    let mut w = TlvWriter::new(&mut buf);
2659    w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
2660        .expect("infallible: vec writer");
2661    buf
2662}
2663
2664/// Decode the `PresetTypes` attribute value.
2665///
2666/// # Errors
2667/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2668pub fn decode_preset_types(tlv: &[u8]) -> Result<Vec<PresetTypeStruct>, ClusterError> {
2669    let mut r = TlvReader::new(tlv);
2670    match r.next()? {
2671        Some(Element::ContainerStart {
2672            kind: ContainerKind::Array,
2673            ..
2674        }) => {}
2675        _ => {
2676            return Err(ClusterError::UnexpectedType {
2677                context: "PresetTypes",
2678            })
2679        }
2680    }
2681    let r = &mut r;
2682    let mut out = Vec::new();
2683    loop {
2684        match r.next()? {
2685            Some(Element::ContainerEnd) => break,
2686            Some(Element::ContainerStart {
2687                kind: ContainerKind::Structure,
2688                ..
2689            }) => {
2690                out.push(PresetTypeStruct::decode_from(r)?);
2691            }
2692            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2693            Some(Element::ContainerStart { .. }) => r.skip_container()?,
2694            Some(_) => {} // skip unknown scalar
2695        }
2696    }
2697    Ok(out)
2698}
2699
2700/// Decode the `ScheduleTypes` attribute value.
2701///
2702/// # Errors
2703/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2704pub fn decode_schedule_types(tlv: &[u8]) -> Result<Vec<ScheduleTypeStruct>, ClusterError> {
2705    let mut r = TlvReader::new(tlv);
2706    match r.next()? {
2707        Some(Element::ContainerStart {
2708            kind: ContainerKind::Array,
2709            ..
2710        }) => {}
2711        _ => {
2712            return Err(ClusterError::UnexpectedType {
2713                context: "ScheduleTypes",
2714            })
2715        }
2716    }
2717    let r = &mut r;
2718    let mut out = Vec::new();
2719    loop {
2720        match r.next()? {
2721            Some(Element::ContainerEnd) => break,
2722            Some(Element::ContainerStart {
2723                kind: ContainerKind::Structure,
2724                ..
2725            }) => {
2726                out.push(ScheduleTypeStruct::decode_from(r)?);
2727            }
2728            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2729            Some(Element::ContainerStart { .. }) => r.skip_container()?,
2730            Some(_) => {} // skip unknown scalar
2731        }
2732    }
2733    Ok(out)
2734}
2735
2736/// Decode the `NumberOfPresets` attribute value.
2737///
2738/// # Errors
2739/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2740pub fn decode_number_of_presets(tlv: &[u8]) -> Result<u8, ClusterError> {
2741    let mut r = TlvReader::new(tlv);
2742    match r.next()? {
2743        Some(Element::Scalar {
2744            value: Value::Uint(v),
2745            ..
2746        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("NumberOfPresets"))?),
2747        _ => Err(ClusterError::UnexpectedType {
2748            context: "NumberOfPresets",
2749        }),
2750    }
2751}
2752
2753/// Decode the `NumberOfSchedules` attribute value.
2754///
2755/// # Errors
2756/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2757pub fn decode_number_of_schedules(tlv: &[u8]) -> Result<u8, ClusterError> {
2758    let mut r = TlvReader::new(tlv);
2759    match r.next()? {
2760        Some(Element::Scalar {
2761            value: Value::Uint(v),
2762            ..
2763        }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("NumberOfSchedules"))?),
2764        _ => Err(ClusterError::UnexpectedType {
2765            context: "NumberOfSchedules",
2766        }),
2767    }
2768}
2769
2770/// Decode the `NumberOfScheduleTransitions` attribute value.
2771///
2772/// # Errors
2773/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2774pub fn decode_number_of_schedule_transitions(tlv: &[u8]) -> Result<u8, ClusterError> {
2775    let mut r = TlvReader::new(tlv);
2776    match r.next()? {
2777        Some(Element::Scalar {
2778            value: Value::Uint(v),
2779            ..
2780        }) => Ok(u8::try_from(v)
2781            .map_err(|_| ClusterError::InvalidLength("NumberOfScheduleTransitions"))?),
2782        _ => Err(ClusterError::UnexpectedType {
2783            context: "NumberOfScheduleTransitions",
2784        }),
2785    }
2786}
2787
2788/// Decode the `NumberOfScheduleTransitionPerDay` attribute value.
2789///
2790/// # Errors
2791/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2792pub fn decode_number_of_schedule_transition_per_day(
2793    tlv: &[u8],
2794) -> Result<Nullable<u8>, ClusterError> {
2795    let mut r = TlvReader::new(tlv);
2796    match r.next()? {
2797        Some(Element::Scalar {
2798            value: Value::Null, ..
2799        }) => Ok(Nullable::Null),
2800        Some(Element::Scalar {
2801            value: Value::Uint(v),
2802            ..
2803        }) => Ok(Nullable::Value(u8::try_from(v).map_err(|_| {
2804            ClusterError::InvalidLength("NumberOfScheduleTransitionPerDay")
2805        })?)),
2806        _ => Err(ClusterError::UnexpectedType {
2807            context: "NumberOfScheduleTransitionPerDay",
2808        }),
2809    }
2810}
2811
2812/// Decode the `ActivePresetHandle` attribute value.
2813///
2814/// # Errors
2815/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2816pub fn decode_active_preset_handle(tlv: &[u8]) -> Result<Nullable<Vec<u8>>, ClusterError> {
2817    let mut r = TlvReader::new(tlv);
2818    match r.next()? {
2819        Some(Element::Scalar {
2820            value: Value::Null, ..
2821        }) => Ok(Nullable::Null),
2822        Some(Element::Scalar {
2823            value: Value::Bytes(v),
2824            ..
2825        }) => Ok(Nullable::Value(v)),
2826        _ => Err(ClusterError::UnexpectedType {
2827            context: "ActivePresetHandle",
2828        }),
2829    }
2830}
2831
2832/// Decode the `ActiveScheduleHandle` attribute value.
2833///
2834/// # Errors
2835/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2836pub fn decode_active_schedule_handle(tlv: &[u8]) -> Result<Nullable<Vec<u8>>, ClusterError> {
2837    let mut r = TlvReader::new(tlv);
2838    match r.next()? {
2839        Some(Element::Scalar {
2840            value: Value::Null, ..
2841        }) => Ok(Nullable::Null),
2842        Some(Element::Scalar {
2843            value: Value::Bytes(v),
2844            ..
2845        }) => Ok(Nullable::Value(v)),
2846        _ => Err(ClusterError::UnexpectedType {
2847            context: "ActiveScheduleHandle",
2848        }),
2849    }
2850}
2851
2852/// Decode the `Presets` attribute value.
2853///
2854/// # Errors
2855/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2856pub fn decode_presets(tlv: &[u8]) -> Result<Vec<PresetStruct>, ClusterError> {
2857    let mut r = TlvReader::new(tlv);
2858    match r.next()? {
2859        Some(Element::ContainerStart {
2860            kind: ContainerKind::Array,
2861            ..
2862        }) => {}
2863        _ => return Err(ClusterError::UnexpectedType { context: "Presets" }),
2864    }
2865    let r = &mut r;
2866    let mut out = Vec::new();
2867    loop {
2868        match r.next()? {
2869            Some(Element::ContainerEnd) => break,
2870            Some(Element::ContainerStart {
2871                kind: ContainerKind::Structure,
2872                ..
2873            }) => {
2874                out.push(PresetStruct::decode_from(r)?);
2875            }
2876            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2877            Some(Element::ContainerStart { .. }) => r.skip_container()?,
2878            Some(_) => {} // skip unknown scalar
2879        }
2880    }
2881    Ok(out)
2882}
2883
2884/// Decode the `Schedules` attribute value.
2885///
2886/// # Errors
2887/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2888pub fn decode_schedules(tlv: &[u8]) -> Result<Vec<ScheduleStruct>, ClusterError> {
2889    let mut r = TlvReader::new(tlv);
2890    match r.next()? {
2891        Some(Element::ContainerStart {
2892            kind: ContainerKind::Array,
2893            ..
2894        }) => {}
2895        _ => {
2896            return Err(ClusterError::UnexpectedType {
2897                context: "Schedules",
2898            })
2899        }
2900    }
2901    let r = &mut r;
2902    let mut out = Vec::new();
2903    loop {
2904        match r.next()? {
2905            Some(Element::ContainerEnd) => break,
2906            Some(Element::ContainerStart {
2907                kind: ContainerKind::Structure,
2908                ..
2909            }) => {
2910                out.push(ScheduleStruct::decode_from(r)?);
2911            }
2912            None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
2913            Some(Element::ContainerStart { .. }) => r.skip_container()?,
2914            Some(_) => {} // skip unknown scalar
2915        }
2916    }
2917    Ok(out)
2918}
2919
2920/// Decode the `SetpointHoldExpiryTimestamp` attribute value.
2921///
2922/// # Errors
2923/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
2924pub fn decode_setpoint_hold_expiry_timestamp(tlv: &[u8]) -> Result<Nullable<u32>, ClusterError> {
2925    let mut r = TlvReader::new(tlv);
2926    match r.next()? {
2927        Some(Element::Scalar {
2928            value: Value::Null, ..
2929        }) => Ok(Nullable::Null),
2930        Some(Element::Scalar {
2931            value: Value::Uint(v),
2932            ..
2933        }) => Ok(Nullable::Value(u32::try_from(v).map_err(|_| {
2934            ClusterError::InvalidLength("SetpointHoldExpiryTimestamp")
2935        })?)),
2936        _ => Err(ClusterError::UnexpectedType {
2937            context: "SetpointHoldExpiryTimestamp",
2938        }),
2939    }
2940}
2941
2942/// Encode the `SetpointRaiseLower` command request payload.
2943#[must_use]
2944#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2945pub fn encode_setpoint_raise_lower(mode: SetpointRaiseLowerModeEnum, amount: i8) -> Vec<u8> {
2946    let mut buf = Vec::new();
2947    let mut w = TlvWriter::new(&mut buf);
2948    w.start_structure(Tag::Anonymous)
2949        .expect("infallible: vec writer");
2950    w.put_uint(Tag::Context(0), u64::from(mode.to_raw()))
2951        .expect("infallible: vec writer");
2952    w.put_int(Tag::Context(1), i64::from(amount))
2953        .expect("infallible: vec writer");
2954    w.end_container().expect("infallible: vec writer");
2955    buf
2956}
2957
2958/// Encode the `SetActiveScheduleRequest` command request payload.
2959#[must_use]
2960#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2961pub fn encode_set_active_schedule_request(schedule_handle: &Vec<u8>) -> Vec<u8> {
2962    let mut buf = Vec::new();
2963    let mut w = TlvWriter::new(&mut buf);
2964    w.start_structure(Tag::Anonymous)
2965        .expect("infallible: vec writer");
2966    w.put_bytes(Tag::Context(0), &schedule_handle)
2967        .expect("infallible: vec writer");
2968    w.end_container().expect("infallible: vec writer");
2969    buf
2970}
2971
2972/// Encode the `SetActivePresetRequest` command request payload.
2973#[must_use]
2974#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
2975pub fn encode_set_active_preset_request(preset_handle: Nullable<Vec<u8>>) -> Vec<u8> {
2976    let mut buf = Vec::new();
2977    let mut w = TlvWriter::new(&mut buf);
2978    w.start_structure(Tag::Anonymous)
2979        .expect("infallible: vec writer");
2980    match preset_handle {
2981        Nullable::Null => w.put_null(Tag::Context(0)).expect("infallible: vec writer"),
2982        Nullable::Value(preset_handle) => {
2983            w.put_bytes(Tag::Context(0), &preset_handle)
2984                .expect("infallible: vec writer");
2985        }
2986    }
2987    w.end_container().expect("infallible: vec writer");
2988    buf
2989}
2990
2991/// Decoded `AtomicResponse` payload.
2992#[derive(Clone, Debug, PartialEq)]
2993#[non_exhaustive]
2994pub struct AtomicResponse {
2995    /// Field StatusCode (tag 0).
2996    pub status_code: u8,
2997    /// Field AttributeStatus (tag 1).
2998    pub attribute_status: Vec<ThermostatAttributeStatusEntryStruct>,
2999    /// Field Timeout (tag 2).
3000    pub timeout: Option<u16>,
3001}
3002
3003impl AtomicResponse {
3004    /// Decode the fields of an already-opened anonymous structure
3005    /// (reader positioned after the struct start; consumes to its end).
3006    ///
3007    /// # Errors
3008    /// Returns [`ClusterError`] on a malformed structure or missing required field.
3009    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
3010        let mut f_status_code: Option<u8> = None;
3011        let mut f_attribute_status: Option<Vec<ThermostatAttributeStatusEntryStruct>> = None;
3012        let mut f_timeout: Option<u16> = None;
3013        loop {
3014            match r.next()? {
3015                Some(Element::ContainerEnd) => break,
3016                Some(Element::Scalar {
3017                    tag: Tag::Context(0),
3018                    value: Value::Uint(v),
3019                }) => {
3020                    f_status_code = Some(
3021                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StatusCode"))?,
3022                    )
3023                }
3024                Some(Element::ContainerStart {
3025                    tag: Tag::Context(1),
3026                    kind: ContainerKind::Array,
3027                }) => {
3028                    let mut out = Vec::new();
3029                    loop {
3030                        match r.next()? {
3031                            Some(Element::ContainerEnd) => break,
3032                            Some(Element::ContainerStart {
3033                                kind: ContainerKind::Structure,
3034                                ..
3035                            }) => {
3036                                out.push(ThermostatAttributeStatusEntryStruct::decode_from(r)?);
3037                            }
3038                            None => {
3039                                return Err(ClusterError::Tlv(
3040                                    matter_codec::Error::UnclosedContainer,
3041                                ))
3042                            }
3043                            Some(Element::ContainerStart { .. }) => r.skip_container()?,
3044                            Some(_) => {} // skip unknown scalar
3045                        }
3046                    }
3047                    f_attribute_status = Some(out);
3048                }
3049                Some(Element::Scalar {
3050                    tag: Tag::Context(2),
3051                    value: Value::Uint(v),
3052                }) => {
3053                    f_timeout =
3054                        Some(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Timeout"))?)
3055                }
3056                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
3057                Some(Element::ContainerStart { .. }) => r.skip_container()?,
3058                Some(_) => {} // unknown/future scalar — skip
3059            }
3060        }
3061        Ok(Self {
3062            status_code: f_status_code.ok_or(ClusterError::MissingField("StatusCode"))?,
3063            attribute_status: f_attribute_status
3064                .ok_or(ClusterError::MissingField("AttributeStatus"))?,
3065            timeout: f_timeout,
3066        })
3067    }
3068    /// Decode from a standalone anonymous TLV structure.
3069    ///
3070    /// # Errors
3071    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
3072    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
3073        let mut r = TlvReader::new(tlv);
3074        match r.next()? {
3075            Some(Element::ContainerStart {
3076                kind: ContainerKind::Structure,
3077                ..
3078            }) => {}
3079            _ => {
3080                return Err(ClusterError::UnexpectedType {
3081                    context: "AtomicResponse",
3082                })
3083            }
3084        }
3085        Self::decode_from(&mut r)
3086    }
3087}
3088
3089/// Encode the `AtomicRequest` command request payload.
3090#[must_use]
3091#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
3092pub fn encode_atomic_request(
3093    request_type: u8,
3094    attribute_requests: &Vec<u32>,
3095    timeout: Option<u16>,
3096) -> Vec<u8> {
3097    let mut buf = Vec::new();
3098    let mut w = TlvWriter::new(&mut buf);
3099    w.start_structure(Tag::Anonymous)
3100        .expect("infallible: vec writer");
3101    w.put_uint(Tag::Context(0), u64::from(request_type))
3102        .expect("infallible: vec writer");
3103    w.start_array(Tag::Context(1))
3104        .expect("infallible: vec writer");
3105    for el in attribute_requests.iter().copied() {
3106        w.put_uint(Tag::Anonymous, u64::from(el))
3107            .expect("infallible: vec writer");
3108    }
3109    w.end_container().expect("infallible: vec writer");
3110    if let Some(timeout) = timeout {
3111        w.put_uint(Tag::Context(2), u64::from(timeout))
3112            .expect("infallible: vec writer");
3113    }
3114    w.end_container().expect("infallible: vec writer");
3115    buf
3116}