matc/clusters/codec/
bridged_device_basic_information_cluster.rs

1//! Matter TLV encoders and decoders for Bridged Device Basic Information Cluster
2//! Cluster ID: 0x0039
3//!
4//! This file is automatically generated from BridgedDeviceBasicInformationCluster.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 Color {
18    /// Approximately RGB #000000.
19    Black = 0,
20    /// Approximately RGB #000080.
21    Navy = 1,
22    /// Approximately RGB #008000.
23    Green = 2,
24    /// Approximately RGB #008080.
25    Teal = 3,
26    /// Approximately RGB #800000.
27    Maroon = 4,
28    /// Approximately RGB #800080.
29    Purple = 5,
30    /// Approximately RGB #808000.
31    Olive = 6,
32    /// Approximately RGB #808080.
33    Gray = 7,
34    /// Approximately RGB #0000FF.
35    Blue = 8,
36    /// Approximately RGB #00FF00.
37    Lime = 9,
38    /// Approximately RGB #00FFFF.
39    Aqua = 10,
40    /// Approximately RGB #FF0000.
41    Red = 11,
42    /// Approximately RGB #FF00FF.
43    Fuchsia = 12,
44    /// Approximately RGB #FFFF00.
45    Yellow = 13,
46    /// Approximately RGB #FFFFFF.
47    White = 14,
48    /// Typical hardware "Nickel" color.
49    Nickel = 15,
50    /// Typical hardware "Chrome" color.
51    Chrome = 16,
52    /// Typical hardware "Brass" color.
53    Brass = 17,
54    /// Typical hardware "Copper" color.
55    Copper = 18,
56    /// Typical hardware "Silver" color.
57    Silver = 19,
58    /// Typical hardware "Gold" color.
59    Gold = 20,
60}
61
62impl Color {
63    /// Convert from u8 value
64    pub fn from_u8(value: u8) -> Option<Self> {
65        match value {
66            0 => Some(Color::Black),
67            1 => Some(Color::Navy),
68            2 => Some(Color::Green),
69            3 => Some(Color::Teal),
70            4 => Some(Color::Maroon),
71            5 => Some(Color::Purple),
72            6 => Some(Color::Olive),
73            7 => Some(Color::Gray),
74            8 => Some(Color::Blue),
75            9 => Some(Color::Lime),
76            10 => Some(Color::Aqua),
77            11 => Some(Color::Red),
78            12 => Some(Color::Fuchsia),
79            13 => Some(Color::Yellow),
80            14 => Some(Color::White),
81            15 => Some(Color::Nickel),
82            16 => Some(Color::Chrome),
83            17 => Some(Color::Brass),
84            18 => Some(Color::Copper),
85            19 => Some(Color::Silver),
86            20 => Some(Color::Gold),
87            _ => None,
88        }
89    }
90
91    /// Convert to u8 value
92    pub fn to_u8(self) -> u8 {
93        self as u8
94    }
95}
96
97impl From<Color> for u8 {
98    fn from(val: Color) -> Self {
99        val as u8
100    }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
104#[repr(u8)]
105pub enum ProductFinish {
106    /// Product has some other finish not listed below.
107    Other = 0,
108    /// Product has a matte finish.
109    Matte = 1,
110    /// Product has a satin finish.
111    Satin = 2,
112    /// Product has a polished or shiny finish.
113    Polished = 3,
114    /// Product has a rugged finish.
115    Rugged = 4,
116    /// Product has a fabric finish.
117    Fabric = 5,
118}
119
120impl ProductFinish {
121    /// Convert from u8 value
122    pub fn from_u8(value: u8) -> Option<Self> {
123        match value {
124            0 => Some(ProductFinish::Other),
125            1 => Some(ProductFinish::Matte),
126            2 => Some(ProductFinish::Satin),
127            3 => Some(ProductFinish::Polished),
128            4 => Some(ProductFinish::Rugged),
129            5 => Some(ProductFinish::Fabric),
130            _ => None,
131        }
132    }
133
134    /// Convert to u8 value
135    pub fn to_u8(self) -> u8 {
136        self as u8
137    }
138}
139
140impl From<ProductFinish> for u8 {
141    fn from(val: ProductFinish) -> Self {
142        val as u8
143    }
144}
145
146// Struct definitions
147
148#[derive(Debug, serde::Serialize)]
149pub struct CapabilityMinima {
150    pub case_sessions_per_fabric: Option<u16>,
151    pub subscriptions_per_fabric: Option<u16>,
152}
153
154#[derive(Debug, serde::Serialize)]
155pub struct ProductAppearance {
156    pub finish: Option<ProductFinish>,
157    pub primary_color: Option<Color>,
158}
159
160// Command encoders
161
162/// Encode KeepActive command (0x80)
163pub fn encode_keep_active(stay_active_duration: u32, timeout_ms: u32) -> anyhow::Result<Vec<u8>> {
164    let tlv = tlv::TlvItemEnc {
165        tag: 0,
166        value: tlv::TlvItemValueEnc::StructInvisible(vec![
167        (0, tlv::TlvItemValueEnc::UInt32(stay_active_duration)).into(),
168        (1, tlv::TlvItemValueEnc::UInt32(timeout_ms)).into(),
169        ]),
170    };
171    Ok(tlv.encode()?)
172}
173
174// Attribute decoders
175
176/// Decode DataModelRevision attribute (0x0000)
177pub fn decode_data_model_revision(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
178    if let tlv::TlvItemValue::Int(v) = inp {
179        Ok(*v as u16)
180    } else {
181        Err(anyhow::anyhow!("Expected UInt16"))
182    }
183}
184
185/// Decode VendorName attribute (0x0001)
186pub fn decode_vendor_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
187    if let tlv::TlvItemValue::String(v) = inp {
188        Ok(v.clone())
189    } else {
190        Err(anyhow::anyhow!("Expected String"))
191    }
192}
193
194/// Decode VendorID attribute (0x0002)
195pub fn decode_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
196    if let tlv::TlvItemValue::Int(v) = inp {
197        Ok(*v as u16)
198    } else {
199        Err(anyhow::anyhow!("Expected UInt16"))
200    }
201}
202
203/// Decode ProductName attribute (0x0003)
204pub fn decode_product_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
205    if let tlv::TlvItemValue::String(v) = inp {
206        Ok(v.clone())
207    } else {
208        Err(anyhow::anyhow!("Expected String"))
209    }
210}
211
212/// Decode ProductID attribute (0x0004)
213pub fn decode_product_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
214    if let tlv::TlvItemValue::Int(v) = inp {
215        Ok(*v as u16)
216    } else {
217        Err(anyhow::anyhow!("Expected UInt16"))
218    }
219}
220
221/// Decode NodeLabel attribute (0x0005)
222pub fn decode_node_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
223    if let tlv::TlvItemValue::String(v) = inp {
224        Ok(v.clone())
225    } else {
226        Err(anyhow::anyhow!("Expected String"))
227    }
228}
229
230/// Decode Location attribute (0x0006)
231pub fn decode_location(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
232    if let tlv::TlvItemValue::String(v) = inp {
233        Ok(v.clone())
234    } else {
235        Err(anyhow::anyhow!("Expected String"))
236    }
237}
238
239/// Decode HardwareVersion attribute (0x0007)
240pub fn decode_hardware_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
241    if let tlv::TlvItemValue::Int(v) = inp {
242        Ok(*v as u16)
243    } else {
244        Err(anyhow::anyhow!("Expected UInt16"))
245    }
246}
247
248/// Decode HardwareVersionString attribute (0x0008)
249pub fn decode_hardware_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
250    if let tlv::TlvItemValue::String(v) = inp {
251        Ok(v.clone())
252    } else {
253        Err(anyhow::anyhow!("Expected String"))
254    }
255}
256
257/// Decode SoftwareVersion attribute (0x0009)
258pub fn decode_software_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
259    if let tlv::TlvItemValue::Int(v) = inp {
260        Ok(*v as u32)
261    } else {
262        Err(anyhow::anyhow!("Expected UInt32"))
263    }
264}
265
266/// Decode SoftwareVersionString attribute (0x000A)
267pub fn decode_software_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
268    if let tlv::TlvItemValue::String(v) = inp {
269        Ok(v.clone())
270    } else {
271        Err(anyhow::anyhow!("Expected String"))
272    }
273}
274
275/// Decode ManufacturingDate attribute (0x000B)
276pub fn decode_manufacturing_date(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
277    if let tlv::TlvItemValue::String(v) = inp {
278        Ok(v.clone())
279    } else {
280        Err(anyhow::anyhow!("Expected String"))
281    }
282}
283
284/// Decode PartNumber attribute (0x000C)
285pub fn decode_part_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
286    if let tlv::TlvItemValue::String(v) = inp {
287        Ok(v.clone())
288    } else {
289        Err(anyhow::anyhow!("Expected String"))
290    }
291}
292
293/// Decode ProductURL attribute (0x000D)
294pub fn decode_product_url(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
295    if let tlv::TlvItemValue::String(v) = inp {
296        Ok(v.clone())
297    } else {
298        Err(anyhow::anyhow!("Expected String"))
299    }
300}
301
302/// Decode ProductLabel attribute (0x000E)
303pub fn decode_product_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
304    if let tlv::TlvItemValue::String(v) = inp {
305        Ok(v.clone())
306    } else {
307        Err(anyhow::anyhow!("Expected String"))
308    }
309}
310
311/// Decode SerialNumber attribute (0x000F)
312pub fn decode_serial_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
313    if let tlv::TlvItemValue::String(v) = inp {
314        Ok(v.clone())
315    } else {
316        Err(anyhow::anyhow!("Expected String"))
317    }
318}
319
320/// Decode LocalConfigDisabled attribute (0x0010)
321pub fn decode_local_config_disabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
322    if let tlv::TlvItemValue::Bool(v) = inp {
323        Ok(*v)
324    } else {
325        Err(anyhow::anyhow!("Expected Bool"))
326    }
327}
328
329/// Decode Reachable attribute (0x0011)
330pub fn decode_reachable(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
331    if let tlv::TlvItemValue::Bool(v) = inp {
332        Ok(*v)
333    } else {
334        Err(anyhow::anyhow!("Expected Bool"))
335    }
336}
337
338/// Decode UniqueID attribute (0x0012)
339pub fn decode_unique_id(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
340    if let tlv::TlvItemValue::String(v) = inp {
341        Ok(v.clone())
342    } else {
343        Err(anyhow::anyhow!("Expected String"))
344    }
345}
346
347/// Decode CapabilityMinima attribute (0x0013)
348pub fn decode_capability_minima(inp: &tlv::TlvItemValue) -> anyhow::Result<CapabilityMinima> {
349    if let tlv::TlvItemValue::List(_fields) = inp {
350        // Struct with fields
351        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
352        Ok(CapabilityMinima {
353                case_sessions_per_fabric: item.get_int(&[0]).map(|v| v as u16),
354                subscriptions_per_fabric: item.get_int(&[1]).map(|v| v as u16),
355        })
356    } else {
357        Err(anyhow::anyhow!("Expected struct fields"))
358    }
359}
360
361/// Decode ProductAppearance attribute (0x0014)
362pub fn decode_product_appearance(inp: &tlv::TlvItemValue) -> anyhow::Result<ProductAppearance> {
363    if let tlv::TlvItemValue::List(_fields) = inp {
364        // Struct with fields
365        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
366        Ok(ProductAppearance {
367                finish: item.get_int(&[0]).and_then(|v| ProductFinish::from_u8(v as u8)),
368                primary_color: item.get_int(&[1]).and_then(|v| Color::from_u8(v as u8)),
369        })
370    } else {
371        Err(anyhow::anyhow!("Expected struct fields"))
372    }
373}
374
375/// Decode SpecificationVersion attribute (0x0015)
376pub fn decode_specification_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
377    if let tlv::TlvItemValue::Int(v) = inp {
378        Ok(*v as u32)
379    } else {
380        Err(anyhow::anyhow!("Expected UInt32"))
381    }
382}
383
384/// Decode MaxPathsPerInvoke attribute (0x0016)
385pub fn decode_max_paths_per_invoke(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
386    if let tlv::TlvItemValue::Int(v) = inp {
387        Ok(*v as u16)
388    } else {
389        Err(anyhow::anyhow!("Expected UInt16"))
390    }
391}
392
393/// Decode ConfigurationVersion attribute (0x0018)
394pub fn decode_configuration_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
395    if let tlv::TlvItemValue::Int(v) = inp {
396        Ok(*v as u32)
397    } else {
398        Err(anyhow::anyhow!("Expected UInt32"))
399    }
400}
401
402
403// JSON dispatcher function
404
405/// Decode attribute value and return as JSON string
406///
407/// # Parameters
408/// * `cluster_id` - The cluster identifier
409/// * `attribute_id` - The attribute identifier
410/// * `tlv_value` - The TLV value to decode
411///
412/// # Returns
413/// JSON string representation of the decoded value or error
414pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
415    // Verify this is the correct cluster
416    if cluster_id != 0x0039 {
417        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0039, got {}\"}}", cluster_id);
418    }
419
420    match attribute_id {
421        0x0000 => {
422            match decode_data_model_revision(tlv_value) {
423                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
424                Err(e) => format!("{{\"error\": \"{}\"}}", e),
425            }
426        }
427        0x0001 => {
428            match decode_vendor_name(tlv_value) {
429                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
430                Err(e) => format!("{{\"error\": \"{}\"}}", e),
431            }
432        }
433        0x0002 => {
434            match decode_vendor_id(tlv_value) {
435                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
436                Err(e) => format!("{{\"error\": \"{}\"}}", e),
437            }
438        }
439        0x0003 => {
440            match decode_product_name(tlv_value) {
441                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
442                Err(e) => format!("{{\"error\": \"{}\"}}", e),
443            }
444        }
445        0x0004 => {
446            match decode_product_id(tlv_value) {
447                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
448                Err(e) => format!("{{\"error\": \"{}\"}}", e),
449            }
450        }
451        0x0005 => {
452            match decode_node_label(tlv_value) {
453                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
454                Err(e) => format!("{{\"error\": \"{}\"}}", e),
455            }
456        }
457        0x0006 => {
458            match decode_location(tlv_value) {
459                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
460                Err(e) => format!("{{\"error\": \"{}\"}}", e),
461            }
462        }
463        0x0007 => {
464            match decode_hardware_version(tlv_value) {
465                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
466                Err(e) => format!("{{\"error\": \"{}\"}}", e),
467            }
468        }
469        0x0008 => {
470            match decode_hardware_version_string(tlv_value) {
471                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
472                Err(e) => format!("{{\"error\": \"{}\"}}", e),
473            }
474        }
475        0x0009 => {
476            match decode_software_version(tlv_value) {
477                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
478                Err(e) => format!("{{\"error\": \"{}\"}}", e),
479            }
480        }
481        0x000A => {
482            match decode_software_version_string(tlv_value) {
483                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
484                Err(e) => format!("{{\"error\": \"{}\"}}", e),
485            }
486        }
487        0x000B => {
488            match decode_manufacturing_date(tlv_value) {
489                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
490                Err(e) => format!("{{\"error\": \"{}\"}}", e),
491            }
492        }
493        0x000C => {
494            match decode_part_number(tlv_value) {
495                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
496                Err(e) => format!("{{\"error\": \"{}\"}}", e),
497            }
498        }
499        0x000D => {
500            match decode_product_url(tlv_value) {
501                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
502                Err(e) => format!("{{\"error\": \"{}\"}}", e),
503            }
504        }
505        0x000E => {
506            match decode_product_label(tlv_value) {
507                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
508                Err(e) => format!("{{\"error\": \"{}\"}}", e),
509            }
510        }
511        0x000F => {
512            match decode_serial_number(tlv_value) {
513                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
514                Err(e) => format!("{{\"error\": \"{}\"}}", e),
515            }
516        }
517        0x0010 => {
518            match decode_local_config_disabled(tlv_value) {
519                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
520                Err(e) => format!("{{\"error\": \"{}\"}}", e),
521            }
522        }
523        0x0011 => {
524            match decode_reachable(tlv_value) {
525                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
526                Err(e) => format!("{{\"error\": \"{}\"}}", e),
527            }
528        }
529        0x0012 => {
530            match decode_unique_id(tlv_value) {
531                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
532                Err(e) => format!("{{\"error\": \"{}\"}}", e),
533            }
534        }
535        0x0013 => {
536            match decode_capability_minima(tlv_value) {
537                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
538                Err(e) => format!("{{\"error\": \"{}\"}}", e),
539            }
540        }
541        0x0014 => {
542            match decode_product_appearance(tlv_value) {
543                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
544                Err(e) => format!("{{\"error\": \"{}\"}}", e),
545            }
546        }
547        0x0015 => {
548            match decode_specification_version(tlv_value) {
549                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
550                Err(e) => format!("{{\"error\": \"{}\"}}", e),
551            }
552        }
553        0x0016 => {
554            match decode_max_paths_per_invoke(tlv_value) {
555                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
556                Err(e) => format!("{{\"error\": \"{}\"}}", e),
557            }
558        }
559        0x0018 => {
560            match decode_configuration_version(tlv_value) {
561                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
562                Err(e) => format!("{{\"error\": \"{}\"}}", e),
563            }
564        }
565        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
566    }
567}
568
569/// Get list of all attributes supported by this cluster
570///
571/// # Returns
572/// Vector of tuples containing (attribute_id, attribute_name)
573pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
574    vec![
575        (0x0000, "DataModelRevision"),
576        (0x0001, "VendorName"),
577        (0x0002, "VendorID"),
578        (0x0003, "ProductName"),
579        (0x0004, "ProductID"),
580        (0x0005, "NodeLabel"),
581        (0x0006, "Location"),
582        (0x0007, "HardwareVersion"),
583        (0x0008, "HardwareVersionString"),
584        (0x0009, "SoftwareVersion"),
585        (0x000A, "SoftwareVersionString"),
586        (0x000B, "ManufacturingDate"),
587        (0x000C, "PartNumber"),
588        (0x000D, "ProductURL"),
589        (0x000E, "ProductLabel"),
590        (0x000F, "SerialNumber"),
591        (0x0010, "LocalConfigDisabled"),
592        (0x0011, "Reachable"),
593        (0x0012, "UniqueID"),
594        (0x0013, "CapabilityMinima"),
595        (0x0014, "ProductAppearance"),
596        (0x0015, "SpecificationVersion"),
597        (0x0016, "MaxPathsPerInvoke"),
598        (0x0018, "ConfigurationVersion"),
599    ]
600}
601
602// Command listing
603
604pub fn get_command_list() -> Vec<(u32, &'static str)> {
605    vec![
606        (0x80, "KeepActive"),
607    ]
608}
609
610pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
611    match cmd_id {
612        0x80 => Some("KeepActive"),
613        _ => None,
614    }
615}
616
617pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
618    match cmd_id {
619        0x80 => Some(vec![
620            crate::clusters::codec::CommandField { tag: 0, name: "stay_active_duration", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: false },
621            crate::clusters::codec::CommandField { tag: 1, name: "timeout_ms", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: false },
622        ]),
623        _ => None,
624    }
625}
626
627pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
628    match cmd_id {
629        0x80 => {
630        let stay_active_duration = crate::clusters::codec::json_util::get_u32(args, "stay_active_duration")?;
631        let timeout_ms = crate::clusters::codec::json_util::get_u32(args, "timeout_ms")?;
632        encode_keep_active(stay_active_duration, timeout_ms)
633        }
634        _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
635    }
636}
637
638// Typed facade (invokes + reads)
639
640/// Invoke `KeepActive` command on cluster `Bridged Device Basic Information`.
641pub async fn keep_active(conn: &crate::controller::Connection, endpoint: u16, stay_active_duration: u32, timeout_ms: u32) -> anyhow::Result<()> {
642    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_CMD_ID_KEEPACTIVE, &encode_keep_active(stay_active_duration, timeout_ms)?).await?;
643    Ok(())
644}
645
646/// Read `DataModelRevision` attribute from cluster `Bridged Device Basic Information`.
647pub async fn read_data_model_revision(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
648    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_DATAMODELREVISION).await?;
649    decode_data_model_revision(&tlv)
650}
651
652/// Read `VendorName` attribute from cluster `Bridged Device Basic Information`.
653pub async fn read_vendor_name(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
654    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_VENDORNAME).await?;
655    decode_vendor_name(&tlv)
656}
657
658/// Read `VendorID` attribute from cluster `Bridged Device Basic Information`.
659pub async fn read_vendor_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
660    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_VENDORID).await?;
661    decode_vendor_id(&tlv)
662}
663
664/// Read `ProductName` attribute from cluster `Bridged Device Basic Information`.
665pub async fn read_product_name(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
666    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_PRODUCTNAME).await?;
667    decode_product_name(&tlv)
668}
669
670/// Read `ProductID` attribute from cluster `Bridged Device Basic Information`.
671pub async fn read_product_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
672    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_PRODUCTID).await?;
673    decode_product_id(&tlv)
674}
675
676/// Read `NodeLabel` attribute from cluster `Bridged Device Basic Information`.
677pub async fn read_node_label(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
678    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_NODELABEL).await?;
679    decode_node_label(&tlv)
680}
681
682/// Read `Location` attribute from cluster `Bridged Device Basic Information`.
683pub async fn read_location(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
684    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_LOCATION).await?;
685    decode_location(&tlv)
686}
687
688/// Read `HardwareVersion` attribute from cluster `Bridged Device Basic Information`.
689pub async fn read_hardware_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
690    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSION).await?;
691    decode_hardware_version(&tlv)
692}
693
694/// Read `HardwareVersionString` attribute from cluster `Bridged Device Basic Information`.
695pub async fn read_hardware_version_string(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
696    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSIONSTRING).await?;
697    decode_hardware_version_string(&tlv)
698}
699
700/// Read `SoftwareVersion` attribute from cluster `Bridged Device Basic Information`.
701pub async fn read_software_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
702    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSION).await?;
703    decode_software_version(&tlv)
704}
705
706/// Read `SoftwareVersionString` attribute from cluster `Bridged Device Basic Information`.
707pub async fn read_software_version_string(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
708    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSIONSTRING).await?;
709    decode_software_version_string(&tlv)
710}
711
712/// Read `ManufacturingDate` attribute from cluster `Bridged Device Basic Information`.
713pub async fn read_manufacturing_date(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
714    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_MANUFACTURINGDATE).await?;
715    decode_manufacturing_date(&tlv)
716}
717
718/// Read `PartNumber` attribute from cluster `Bridged Device Basic Information`.
719pub async fn read_part_number(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
720    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_PARTNUMBER).await?;
721    decode_part_number(&tlv)
722}
723
724/// Read `ProductURL` attribute from cluster `Bridged Device Basic Information`.
725pub async fn read_product_url(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
726    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_PRODUCTURL).await?;
727    decode_product_url(&tlv)
728}
729
730/// Read `ProductLabel` attribute from cluster `Bridged Device Basic Information`.
731pub async fn read_product_label(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
732    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_PRODUCTLABEL).await?;
733    decode_product_label(&tlv)
734}
735
736/// Read `SerialNumber` attribute from cluster `Bridged Device Basic Information`.
737pub async fn read_serial_number(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
738    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_SERIALNUMBER).await?;
739    decode_serial_number(&tlv)
740}
741
742/// Read `LocalConfigDisabled` attribute from cluster `Bridged Device Basic Information`.
743pub async fn read_local_config_disabled(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
744    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_LOCALCONFIGDISABLED).await?;
745    decode_local_config_disabled(&tlv)
746}
747
748/// Read `Reachable` attribute from cluster `Bridged Device Basic Information`.
749pub async fn read_reachable(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
750    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_REACHABLE).await?;
751    decode_reachable(&tlv)
752}
753
754/// Read `UniqueID` attribute from cluster `Bridged Device Basic Information`.
755pub async fn read_unique_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
756    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_UNIQUEID).await?;
757    decode_unique_id(&tlv)
758}
759
760/// Read `CapabilityMinima` attribute from cluster `Bridged Device Basic Information`.
761pub async fn read_capability_minima(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<CapabilityMinima> {
762    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_CAPABILITYMINIMA).await?;
763    decode_capability_minima(&tlv)
764}
765
766/// Read `ProductAppearance` attribute from cluster `Bridged Device Basic Information`.
767pub async fn read_product_appearance(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<ProductAppearance> {
768    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_PRODUCTAPPEARANCE).await?;
769    decode_product_appearance(&tlv)
770}
771
772/// Read `SpecificationVersion` attribute from cluster `Bridged Device Basic Information`.
773pub async fn read_specification_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
774    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_SPECIFICATIONVERSION).await?;
775    decode_specification_version(&tlv)
776}
777
778/// Read `MaxPathsPerInvoke` attribute from cluster `Bridged Device Basic Information`.
779pub async fn read_max_paths_per_invoke(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
780    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_MAXPATHSPERINVOKE).await?;
781    decode_max_paths_per_invoke(&tlv)
782}
783
784/// Read `ConfigurationVersion` attribute from cluster `Bridged Device Basic Information`.
785pub async fn read_configuration_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
786    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BRIDGED_DEVICE_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BRIDGED_DEVICE_BASIC_INFORMATION_ATTR_ID_CONFIGURATIONVERSION).await?;
787    decode_configuration_version(&tlv)
788}
789
790#[derive(Debug, serde::Serialize)]
791pub struct StartUpEvent {
792    pub software_version: Option<u32>,
793}
794
795#[derive(Debug, serde::Serialize)]
796pub struct LeaveEvent {
797    pub fabric_index: Option<u8>,
798}
799
800#[derive(Debug, serde::Serialize)]
801pub struct ReachableChangedEvent {
802    pub reachable_new_value: Option<bool>,
803}
804
805#[derive(Debug, serde::Serialize)]
806pub struct ActiveChangedEvent {
807    pub promised_active_duration: Option<u32>,
808}
809
810// Event decoders
811
812/// Decode StartUp event (0x00, priority: critical)
813pub fn decode_start_up_event(inp: &tlv::TlvItemValue) -> anyhow::Result<StartUpEvent> {
814    if let tlv::TlvItemValue::List(_fields) = inp {
815        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
816        Ok(StartUpEvent {
817                                software_version: item.get_int(&[0]).map(|v| v as u32),
818        })
819    } else {
820        Err(anyhow::anyhow!("Expected struct fields"))
821    }
822}
823
824/// Decode Leave event (0x02, priority: info)
825pub fn decode_leave_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LeaveEvent> {
826    if let tlv::TlvItemValue::List(_fields) = inp {
827        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
828        Ok(LeaveEvent {
829                                fabric_index: item.get_int(&[0]).map(|v| v as u8),
830        })
831    } else {
832        Err(anyhow::anyhow!("Expected struct fields"))
833    }
834}
835
836/// Decode ReachableChanged event (0x03, priority: info)
837pub fn decode_reachable_changed_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ReachableChangedEvent> {
838    if let tlv::TlvItemValue::List(_fields) = inp {
839        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
840        Ok(ReachableChangedEvent {
841                                reachable_new_value: item.get_bool(&[0]),
842        })
843    } else {
844        Err(anyhow::anyhow!("Expected struct fields"))
845    }
846}
847
848/// Decode ActiveChanged event (0x80, priority: info)
849pub fn decode_active_changed_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ActiveChangedEvent> {
850    if let tlv::TlvItemValue::List(_fields) = inp {
851        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
852        Ok(ActiveChangedEvent {
853                                promised_active_duration: item.get_int(&[0]).map(|v| v as u32),
854        })
855    } else {
856        Err(anyhow::anyhow!("Expected struct fields"))
857    }
858}
859