matc/clusters/codec/
admin_commissioning_cluster.rs

1//! Matter TLV encoders and decoders for Administrator Commissioning Cluster
2//! Cluster ID: 0x003C
3//!
4//! This file is automatically generated from AdminCommissioningCluster.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Enum definitions
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14#[repr(u8)]
15pub enum CommissioningWindowStatus {
16    /// Commissioning window not open
17    Windownotopen = 0,
18    /// An Enhanced Commissioning Method window is open
19    Enhancedwindowopen = 1,
20    /// A Basic Commissioning Method window is open
21    Basicwindowopen = 2,
22}
23
24impl CommissioningWindowStatus {
25    /// Convert from u8 value
26    pub fn from_u8(value: u8) -> Option<Self> {
27        match value {
28            0 => Some(CommissioningWindowStatus::Windownotopen),
29            1 => Some(CommissioningWindowStatus::Enhancedwindowopen),
30            2 => Some(CommissioningWindowStatus::Basicwindowopen),
31            _ => None,
32        }
33    }
34
35    /// Convert to u8 value
36    pub fn to_u8(self) -> u8 {
37        self as u8
38    }
39}
40
41impl From<CommissioningWindowStatus> for u8 {
42    fn from(val: CommissioningWindowStatus) -> Self {
43        val as u8
44    }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
48#[repr(u8)]
49pub enum StatusCode {
50    /// Could not be completed because another commissioning is in progress
51    Busy = 2,
52    /// Provided PAKE parameters were incorrectly formatted or otherwise invalid
53    Pakeparametererror = 3,
54    /// No commissioning window was currently open
55    Windownotopen = 4,
56}
57
58impl StatusCode {
59    /// Convert from u8 value
60    pub fn from_u8(value: u8) -> Option<Self> {
61        match value {
62            2 => Some(StatusCode::Busy),
63            3 => Some(StatusCode::Pakeparametererror),
64            4 => Some(StatusCode::Windownotopen),
65            _ => None,
66        }
67    }
68
69    /// Convert to u8 value
70    pub fn to_u8(self) -> u8 {
71        self as u8
72    }
73}
74
75impl From<StatusCode> for u8 {
76    fn from(val: StatusCode) -> Self {
77        val as u8
78    }
79}
80
81// Command encoders
82
83/// Encode OpenCommissioningWindow command (0x00)
84pub fn encode_open_commissioning_window(commissioning_timeout: u16, pake_passcode_verifier: Vec<u8>, discriminator: u16, iterations: u32, salt: Vec<u8>) -> anyhow::Result<Vec<u8>> {
85    let tlv = tlv::TlvItemEnc {
86        tag: 0,
87        value: tlv::TlvItemValueEnc::StructInvisible(vec![
88        (0, tlv::TlvItemValueEnc::UInt16(commissioning_timeout)).into(),
89        (1, tlv::TlvItemValueEnc::OctetString(pake_passcode_verifier)).into(),
90        (2, tlv::TlvItemValueEnc::UInt16(discriminator)).into(),
91        (3, tlv::TlvItemValueEnc::UInt32(iterations)).into(),
92        (4, tlv::TlvItemValueEnc::OctetString(salt)).into(),
93        ]),
94    };
95    Ok(tlv.encode()?)
96}
97
98/// Encode OpenBasicCommissioningWindow command (0x01)
99pub fn encode_open_basic_commissioning_window(commissioning_timeout: u16) -> anyhow::Result<Vec<u8>> {
100    let tlv = tlv::TlvItemEnc {
101        tag: 0,
102        value: tlv::TlvItemValueEnc::StructInvisible(vec![
103        (0, tlv::TlvItemValueEnc::UInt16(commissioning_timeout)).into(),
104        ]),
105    };
106    Ok(tlv.encode()?)
107}
108
109// Attribute decoders
110
111/// Decode WindowStatus attribute (0x0000)
112pub fn decode_window_status(inp: &tlv::TlvItemValue) -> anyhow::Result<CommissioningWindowStatus> {
113    if let tlv::TlvItemValue::Int(v) = inp {
114        CommissioningWindowStatus::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
115    } else {
116        Err(anyhow::anyhow!("Expected Integer"))
117    }
118}
119
120/// Decode AdminFabricIndex attribute (0x0001)
121pub fn decode_admin_fabric_index(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
122    if let tlv::TlvItemValue::Int(v) = inp {
123        Ok(Some(*v as u8))
124    } else {
125        Ok(None)
126    }
127}
128
129/// Decode AdminVendorId attribute (0x0002)
130pub fn decode_admin_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
131    if let tlv::TlvItemValue::Int(v) = inp {
132        Ok(Some(*v as u16))
133    } else {
134        Ok(None)
135    }
136}
137
138
139// JSON dispatcher function
140
141/// Decode attribute value and return as JSON string
142///
143/// # Parameters
144/// * `cluster_id` - The cluster identifier
145/// * `attribute_id` - The attribute identifier
146/// * `tlv_value` - The TLV value to decode
147///
148/// # Returns
149/// JSON string representation of the decoded value or error
150pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
151    // Verify this is the correct cluster
152    if cluster_id != 0x003C {
153        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x003C, got {}\"}}", cluster_id);
154    }
155
156    match attribute_id {
157        0x0000 => {
158            match decode_window_status(tlv_value) {
159                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
160                Err(e) => format!("{{\"error\": \"{}\"}}", e),
161            }
162        }
163        0x0001 => {
164            match decode_admin_fabric_index(tlv_value) {
165                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
166                Err(e) => format!("{{\"error\": \"{}\"}}", e),
167            }
168        }
169        0x0002 => {
170            match decode_admin_vendor_id(tlv_value) {
171                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
172                Err(e) => format!("{{\"error\": \"{}\"}}", e),
173            }
174        }
175        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
176    }
177}
178
179/// Get list of all attributes supported by this cluster
180///
181/// # Returns
182/// Vector of tuples containing (attribute_id, attribute_name)
183pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
184    vec![
185        (0x0000, "WindowStatus"),
186        (0x0001, "AdminFabricIndex"),
187        (0x0002, "AdminVendorId"),
188    ]
189}
190