matc/clusters/codec/
icd_management.rs

1//! Matter TLV encoders and decoders for ICD Management Cluster
2//! Cluster ID: 0x0046
3//!
4//! This file is automatically generated from ICDManagement.xml
5
6#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13// Enum definitions
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[repr(u8)]
17pub enum ClientType {
18    /// The client is typically resident, always-on, fixed infrastructure in the home.
19    Permanent = 0,
20    /// The client is mobile or non-resident or not always-on and may not always be available in the home.
21    Ephemeral = 1,
22}
23
24impl ClientType {
25    /// Convert from u8 value
26    pub fn from_u8(value: u8) -> Option<Self> {
27        match value {
28            0 => Some(ClientType::Permanent),
29            1 => Some(ClientType::Ephemeral),
30            _ => None,
31        }
32    }
33
34    /// Convert to u8 value
35    pub fn to_u8(self) -> u8 {
36        self as u8
37    }
38}
39
40impl From<ClientType> for u8 {
41    fn from(val: ClientType) -> Self {
42        val as u8
43    }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
47#[repr(u8)]
48pub enum OperatingMode {
49    /// ICD is operating as a Short Idle Time ICD.
50    Sit = 0,
51    /// ICD is operating as a Long Idle Time ICD.
52    Lit = 1,
53}
54
55impl OperatingMode {
56    /// Convert from u8 value
57    pub fn from_u8(value: u8) -> Option<Self> {
58        match value {
59            0 => Some(OperatingMode::Sit),
60            1 => Some(OperatingMode::Lit),
61            _ => None,
62        }
63    }
64
65    /// Convert to u8 value
66    pub fn to_u8(self) -> u8 {
67        self as u8
68    }
69}
70
71impl From<OperatingMode> for u8 {
72    fn from(val: OperatingMode) -> Self {
73        val as u8
74    }
75}
76
77// Bitmap definitions
78
79/// UserActiveModeTrigger bitmap type
80pub type UserActiveModeTrigger = u32;
81
82/// Constants for UserActiveModeTrigger
83pub mod useractivemodetrigger {
84    /// Power Cycle to transition the device to ActiveMode
85    pub const POWER_CYCLE: u32 = 0x01;
86    /// Settings menu on the device informs how to transition the device to ActiveMode
87    pub const SETTINGS_MENU: u32 = 0x02;
88    /// Custom Instruction on how to transition the device to ActiveMode
89    pub const CUSTOM_INSTRUCTION: u32 = 0x04;
90    /// Device Manual informs how to transition the device to ActiveMode
91    pub const DEVICE_MANUAL: u32 = 0x08;
92    /// Actuate Sensor to transition the device to ActiveMode
93    pub const ACTUATE_SENSOR: u32 = 0x10;
94    /// Actuate Sensor for N seconds to transition the device to ActiveMode
95    pub const ACTUATE_SENSOR_SECONDS: u32 = 0x20;
96    /// Actuate Sensor N times to transition the device to ActiveMode
97    pub const ACTUATE_SENSOR_TIMES: u32 = 0x40;
98    /// Actuate Sensor until light blinks to transition the device to ActiveMode
99    pub const ACTUATE_SENSOR_LIGHTS_BLINK: u32 = 0x80;
100    /// Press Reset Button to transition the device to ActiveMode
101    pub const RESET_BUTTON: u32 = 0x100;
102    /// Press Reset Button until light blinks to transition the device to ActiveMode
103    pub const RESET_BUTTON_LIGHTS_BLINK: u32 = 0x200;
104    /// Press Reset Button for N seconds to transition the device to ActiveMode
105    pub const RESET_BUTTON_SECONDS: u32 = 0x400;
106    /// Press Reset Button N times to transition the device to ActiveMode
107    pub const RESET_BUTTON_TIMES: u32 = 0x800;
108    /// Press Setup Button to transition the device to ActiveMode
109    pub const SETUP_BUTTON: u32 = 0x1000;
110    /// Press Setup Button for N seconds to transition the device to ActiveMode
111    pub const SETUP_BUTTON_SECONDS: u32 = 0x2000;
112    /// Press Setup Button until light blinks to transition the device to ActiveMode
113    pub const SETUP_BUTTON_LIGHTS_BLINK: u32 = 0x4000;
114    /// Press Setup Button N times to transition the device to ActiveMode
115    pub const SETUP_BUTTON_TIMES: u32 = 0x8000;
116    /// Press the N Button to transition the device to ActiveMode
117    pub const APP_DEFINED_BUTTON: u32 = 0x10000;
118}
119
120// Struct definitions
121
122#[derive(Debug, serde::Serialize)]
123pub struct MonitoringRegistration {
124    pub check_in_node_id: Option<u64>,
125    pub monitored_subject: Option<u64>,
126    pub key: Option<u8>,
127    pub client_type: Option<ClientType>,
128}
129
130// Command encoders
131
132/// Encode RegisterClient command (0x00)
133pub fn encode_register_client(check_in_node_id: u64, monitored_subject: u64, key: Vec<u8>, verification_key: Vec<u8>, client_type: ClientType) -> anyhow::Result<Vec<u8>> {
134    let tlv = tlv::TlvItemEnc {
135        tag: 0,
136        value: tlv::TlvItemValueEnc::StructInvisible(vec![
137        (0, tlv::TlvItemValueEnc::UInt64(check_in_node_id)).into(),
138        (1, tlv::TlvItemValueEnc::UInt64(monitored_subject)).into(),
139        (2, tlv::TlvItemValueEnc::OctetString(key)).into(),
140        (3, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
141        (4, tlv::TlvItemValueEnc::UInt8(client_type.to_u8())).into(),
142        ]),
143    };
144    Ok(tlv.encode()?)
145}
146
147/// Encode UnregisterClient command (0x02)
148pub fn encode_unregister_client(check_in_node_id: u64, verification_key: Vec<u8>) -> anyhow::Result<Vec<u8>> {
149    let tlv = tlv::TlvItemEnc {
150        tag: 0,
151        value: tlv::TlvItemValueEnc::StructInvisible(vec![
152        (0, tlv::TlvItemValueEnc::UInt64(check_in_node_id)).into(),
153        (1, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
154        ]),
155    };
156    Ok(tlv.encode()?)
157}
158
159/// Encode StayActiveRequest command (0x03)
160pub fn encode_stay_active_request(stay_active_duration: u32) -> anyhow::Result<Vec<u8>> {
161    let tlv = tlv::TlvItemEnc {
162        tag: 0,
163        value: tlv::TlvItemValueEnc::StructInvisible(vec![
164        (0, tlv::TlvItemValueEnc::UInt32(stay_active_duration)).into(),
165        ]),
166    };
167    Ok(tlv.encode()?)
168}
169
170// Attribute decoders
171
172/// Decode IdleModeDuration attribute (0x0000)
173pub fn decode_idle_mode_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
174    if let tlv::TlvItemValue::Int(v) = inp {
175        Ok(*v as u32)
176    } else {
177        Err(anyhow::anyhow!("Expected UInt32"))
178    }
179}
180
181/// Decode ActiveModeDuration attribute (0x0001)
182pub fn decode_active_mode_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
183    if let tlv::TlvItemValue::Int(v) = inp {
184        Ok(*v as u32)
185    } else {
186        Err(anyhow::anyhow!("Expected UInt32"))
187    }
188}
189
190/// Decode ActiveModeThreshold attribute (0x0002)
191pub fn decode_active_mode_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
192    if let tlv::TlvItemValue::Int(v) = inp {
193        Ok(*v as u16)
194    } else {
195        Err(anyhow::anyhow!("Expected UInt16"))
196    }
197}
198
199/// Decode RegisteredClients attribute (0x0003)
200pub fn decode_registered_clients(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MonitoringRegistration>> {
201    let mut res = Vec::new();
202    if let tlv::TlvItemValue::List(v) = inp {
203        for item in v {
204            res.push(MonitoringRegistration {
205                check_in_node_id: item.get_int(&[1]),
206                monitored_subject: item.get_int(&[2]),
207                key: item.get_int(&[3]).map(|v| v as u8),
208                client_type: item.get_int(&[4]).and_then(|v| ClientType::from_u8(v as u8)),
209            });
210        }
211    }
212    Ok(res)
213}
214
215/// Decode ICDCounter attribute (0x0004)
216pub fn decode_icd_counter(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
217    if let tlv::TlvItemValue::Int(v) = inp {
218        Ok(*v as u32)
219    } else {
220        Err(anyhow::anyhow!("Expected UInt32"))
221    }
222}
223
224/// Decode ClientsSupportedPerFabric attribute (0x0005)
225pub fn decode_clients_supported_per_fabric(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
226    if let tlv::TlvItemValue::Int(v) = inp {
227        Ok(*v as u16)
228    } else {
229        Err(anyhow::anyhow!("Expected UInt16"))
230    }
231}
232
233/// Decode UserActiveModeTriggerHint attribute (0x0006)
234pub fn decode_user_active_mode_trigger_hint(inp: &tlv::TlvItemValue) -> anyhow::Result<UserActiveModeTrigger> {
235    if let tlv::TlvItemValue::Int(v) = inp {
236        Ok(*v as u32)
237    } else {
238        Err(anyhow::anyhow!("Expected Integer"))
239    }
240}
241
242/// Decode UserActiveModeTriggerInstruction attribute (0x0007)
243pub fn decode_user_active_mode_trigger_instruction(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
244    if let tlv::TlvItemValue::String(v) = inp {
245        Ok(v.clone())
246    } else {
247        Err(anyhow::anyhow!("Expected String"))
248    }
249}
250
251/// Decode OperatingMode attribute (0x0008)
252pub fn decode_operating_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<OperatingMode> {
253    if let tlv::TlvItemValue::Int(v) = inp {
254        OperatingMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
255    } else {
256        Err(anyhow::anyhow!("Expected Integer"))
257    }
258}
259
260/// Decode MaximumCheckInBackoff attribute (0x0009)
261pub fn decode_maximum_check_in_backoff(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
262    if let tlv::TlvItemValue::Int(v) = inp {
263        Ok(*v as u32)
264    } else {
265        Err(anyhow::anyhow!("Expected UInt32"))
266    }
267}
268
269
270// JSON dispatcher function
271
272/// Decode attribute value and return as JSON string
273///
274/// # Parameters
275/// * `cluster_id` - The cluster identifier
276/// * `attribute_id` - The attribute identifier
277/// * `tlv_value` - The TLV value to decode
278///
279/// # Returns
280/// JSON string representation of the decoded value or error
281pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
282    // Verify this is the correct cluster
283    if cluster_id != 0x0046 {
284        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0046, got {}\"}}", cluster_id);
285    }
286
287    match attribute_id {
288        0x0000 => {
289            match decode_idle_mode_duration(tlv_value) {
290                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
291                Err(e) => format!("{{\"error\": \"{}\"}}", e),
292            }
293        }
294        0x0001 => {
295            match decode_active_mode_duration(tlv_value) {
296                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
297                Err(e) => format!("{{\"error\": \"{}\"}}", e),
298            }
299        }
300        0x0002 => {
301            match decode_active_mode_threshold(tlv_value) {
302                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
303                Err(e) => format!("{{\"error\": \"{}\"}}", e),
304            }
305        }
306        0x0003 => {
307            match decode_registered_clients(tlv_value) {
308                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
309                Err(e) => format!("{{\"error\": \"{}\"}}", e),
310            }
311        }
312        0x0004 => {
313            match decode_icd_counter(tlv_value) {
314                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
315                Err(e) => format!("{{\"error\": \"{}\"}}", e),
316            }
317        }
318        0x0005 => {
319            match decode_clients_supported_per_fabric(tlv_value) {
320                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
321                Err(e) => format!("{{\"error\": \"{}\"}}", e),
322            }
323        }
324        0x0006 => {
325            match decode_user_active_mode_trigger_hint(tlv_value) {
326                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
327                Err(e) => format!("{{\"error\": \"{}\"}}", e),
328            }
329        }
330        0x0007 => {
331            match decode_user_active_mode_trigger_instruction(tlv_value) {
332                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
333                Err(e) => format!("{{\"error\": \"{}\"}}", e),
334            }
335        }
336        0x0008 => {
337            match decode_operating_mode(tlv_value) {
338                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
339                Err(e) => format!("{{\"error\": \"{}\"}}", e),
340            }
341        }
342        0x0009 => {
343            match decode_maximum_check_in_backoff(tlv_value) {
344                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
345                Err(e) => format!("{{\"error\": \"{}\"}}", e),
346            }
347        }
348        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
349    }
350}
351
352/// Get list of all attributes supported by this cluster
353///
354/// # Returns
355/// Vector of tuples containing (attribute_id, attribute_name)
356pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
357    vec![
358        (0x0000, "IdleModeDuration"),
359        (0x0001, "ActiveModeDuration"),
360        (0x0002, "ActiveModeThreshold"),
361        (0x0003, "RegisteredClients"),
362        (0x0004, "ICDCounter"),
363        (0x0005, "ClientsSupportedPerFabric"),
364        (0x0006, "UserActiveModeTriggerHint"),
365        (0x0007, "UserActiveModeTriggerInstruction"),
366        (0x0008, "OperatingMode"),
367        (0x0009, "MaximumCheckInBackoff"),
368    ]
369}
370
371// Command listing
372
373pub fn get_command_list() -> Vec<(u32, &'static str)> {
374    vec![
375        (0x00, "RegisterClient"),
376        (0x02, "UnregisterClient"),
377        (0x03, "StayActiveRequest"),
378    ]
379}
380
381pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
382    match cmd_id {
383        0x00 => Some("RegisterClient"),
384        0x02 => Some("UnregisterClient"),
385        0x03 => Some("StayActiveRequest"),
386        _ => None,
387    }
388}
389
390pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
391    match cmd_id {
392        0x00 => Some(vec![
393            crate::clusters::codec::CommandField { tag: 0, name: "check_in_node_id", kind: crate::clusters::codec::FieldKind::U64, optional: false, nullable: false },
394            crate::clusters::codec::CommandField { tag: 1, name: "monitored_subject", kind: crate::clusters::codec::FieldKind::U64, optional: false, nullable: false },
395            crate::clusters::codec::CommandField { tag: 2, name: "key", kind: crate::clusters::codec::FieldKind::OctetString, optional: false, nullable: false },
396            crate::clusters::codec::CommandField { tag: 3, name: "verification_key", kind: crate::clusters::codec::FieldKind::OctetString, optional: true, nullable: false },
397            crate::clusters::codec::CommandField { tag: 4, name: "client_type", kind: crate::clusters::codec::FieldKind::Enum { name: "ClientType", variants: &[(0, "Permanent"), (1, "Ephemeral")] }, optional: false, nullable: false },
398        ]),
399        0x02 => Some(vec![
400            crate::clusters::codec::CommandField { tag: 0, name: "check_in_node_id", kind: crate::clusters::codec::FieldKind::U64, optional: false, nullable: false },
401            crate::clusters::codec::CommandField { tag: 1, name: "verification_key", kind: crate::clusters::codec::FieldKind::OctetString, optional: true, nullable: false },
402        ]),
403        0x03 => Some(vec![
404            crate::clusters::codec::CommandField { tag: 0, name: "stay_active_duration", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: false },
405        ]),
406        _ => None,
407    }
408}
409
410pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
411    match cmd_id {
412        0x00 => {
413        let check_in_node_id = crate::clusters::codec::json_util::get_u64(args, "check_in_node_id")?;
414        let monitored_subject = crate::clusters::codec::json_util::get_u64(args, "monitored_subject")?;
415        let key = crate::clusters::codec::json_util::get_octstr(args, "key")?;
416        let verification_key = crate::clusters::codec::json_util::get_octstr(args, "verification_key")?;
417        let client_type = {
418            let n = crate::clusters::codec::json_util::get_u64(args, "client_type")?;
419            ClientType::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid ClientType: {}", n))?
420        };
421        encode_register_client(check_in_node_id, monitored_subject, key, verification_key, client_type)
422        }
423        0x02 => {
424        let check_in_node_id = crate::clusters::codec::json_util::get_u64(args, "check_in_node_id")?;
425        let verification_key = crate::clusters::codec::json_util::get_octstr(args, "verification_key")?;
426        encode_unregister_client(check_in_node_id, verification_key)
427        }
428        0x03 => {
429        let stay_active_duration = crate::clusters::codec::json_util::get_u32(args, "stay_active_duration")?;
430        encode_stay_active_request(stay_active_duration)
431        }
432        _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
433    }
434}
435
436#[derive(Debug, serde::Serialize)]
437pub struct RegisterClientResponse {
438    pub icd_counter: Option<u32>,
439}
440
441#[derive(Debug, serde::Serialize)]
442pub struct StayActiveResponse {
443    pub promised_active_duration: Option<u32>,
444}
445
446// Command response decoders
447
448/// Decode RegisterClientResponse command response (01)
449pub fn decode_register_client_response(inp: &tlv::TlvItemValue) -> anyhow::Result<RegisterClientResponse> {
450    if let tlv::TlvItemValue::List(_fields) = inp {
451        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
452        Ok(RegisterClientResponse {
453                icd_counter: item.get_int(&[0]).map(|v| v as u32),
454        })
455    } else {
456        Err(anyhow::anyhow!("Expected struct fields"))
457    }
458}
459
460/// Decode StayActiveResponse command response (04)
461pub fn decode_stay_active_response(inp: &tlv::TlvItemValue) -> anyhow::Result<StayActiveResponse> {
462    if let tlv::TlvItemValue::List(_fields) = inp {
463        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
464        Ok(StayActiveResponse {
465                promised_active_duration: item.get_int(&[0]).map(|v| v as u32),
466        })
467    } else {
468        Err(anyhow::anyhow!("Expected struct fields"))
469    }
470}
471
472// Typed facade (invokes + reads)
473
474/// Invoke `RegisterClient` command on cluster `ICD Management`.
475pub async fn register_client(conn: &crate::controller::Connection, endpoint: u16, check_in_node_id: u64, monitored_subject: u64, key: Vec<u8>, verification_key: Vec<u8>, client_type: ClientType) -> anyhow::Result<RegisterClientResponse> {
476    let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_CMD_ID_REGISTERCLIENT, &encode_register_client(check_in_node_id, monitored_subject, key, verification_key, client_type)?).await?;
477    decode_register_client_response(&tlv)
478}
479
480/// Invoke `UnregisterClient` command on cluster `ICD Management`.
481pub async fn unregister_client(conn: &crate::controller::Connection, endpoint: u16, check_in_node_id: u64, verification_key: Vec<u8>) -> anyhow::Result<()> {
482    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_CMD_ID_UNREGISTERCLIENT, &encode_unregister_client(check_in_node_id, verification_key)?).await?;
483    Ok(())
484}
485
486/// Invoke `StayActiveRequest` command on cluster `ICD Management`.
487pub async fn stay_active_request(conn: &crate::controller::Connection, endpoint: u16, stay_active_duration: u32) -> anyhow::Result<StayActiveResponse> {
488    let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_CMD_ID_STAYACTIVEREQUEST, &encode_stay_active_request(stay_active_duration)?).await?;
489    decode_stay_active_response(&tlv)
490}
491
492/// Read `IdleModeDuration` attribute from cluster `ICD Management`.
493pub async fn read_idle_mode_duration(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
494    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_IDLEMODEDURATION).await?;
495    decode_idle_mode_duration(&tlv)
496}
497
498/// Read `ActiveModeDuration` attribute from cluster `ICD Management`.
499pub async fn read_active_mode_duration(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
500    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_ACTIVEMODEDURATION).await?;
501    decode_active_mode_duration(&tlv)
502}
503
504/// Read `ActiveModeThreshold` attribute from cluster `ICD Management`.
505pub async fn read_active_mode_threshold(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
506    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_ACTIVEMODETHRESHOLD).await?;
507    decode_active_mode_threshold(&tlv)
508}
509
510/// Read `RegisteredClients` attribute from cluster `ICD Management`.
511pub async fn read_registered_clients(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<MonitoringRegistration>> {
512    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_REGISTEREDCLIENTS).await?;
513    decode_registered_clients(&tlv)
514}
515
516/// Read `ICDCounter` attribute from cluster `ICD Management`.
517pub async fn read_icd_counter(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
518    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_ICDCOUNTER).await?;
519    decode_icd_counter(&tlv)
520}
521
522/// Read `ClientsSupportedPerFabric` attribute from cluster `ICD Management`.
523pub async fn read_clients_supported_per_fabric(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
524    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_CLIENTSSUPPORTEDPERFABRIC).await?;
525    decode_clients_supported_per_fabric(&tlv)
526}
527
528/// Read `UserActiveModeTriggerHint` attribute from cluster `ICD Management`.
529pub async fn read_user_active_mode_trigger_hint(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<UserActiveModeTrigger> {
530    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_USERACTIVEMODETRIGGERHINT).await?;
531    decode_user_active_mode_trigger_hint(&tlv)
532}
533
534/// Read `UserActiveModeTriggerInstruction` attribute from cluster `ICD Management`.
535pub async fn read_user_active_mode_trigger_instruction(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
536    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_USERACTIVEMODETRIGGERINSTRUCTION).await?;
537    decode_user_active_mode_trigger_instruction(&tlv)
538}
539
540/// Read `OperatingMode` attribute from cluster `ICD Management`.
541pub async fn read_operating_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<OperatingMode> {
542    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_OPERATINGMODE).await?;
543    decode_operating_mode(&tlv)
544}
545
546/// Read `MaximumCheckInBackoff` attribute from cluster `ICD Management`.
547pub async fn read_maximum_check_in_backoff(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
548    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ICD_MANAGEMENT, crate::clusters::defs::CLUSTER_ICD_MANAGEMENT_ATTR_ID_MAXIMUMCHECKINBACKOFF).await?;
549    decode_maximum_check_in_backoff(&tlv)
550}
551