matc/clusters/codec/
audio_output.rs

1//! Matter TLV encoders and decoders for Audio Output Cluster
2//! Cluster ID: 0x050B
3//!
4//! This file is automatically generated from AudioOutput.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 OutputType {
16    /// HDMI
17    Hdmi = 0,
18    Bt = 1,
19    Optical = 2,
20    Headphone = 3,
21    Internal = 4,
22    Other = 5,
23}
24
25impl OutputType {
26    /// Convert from u8 value
27    pub fn from_u8(value: u8) -> Option<Self> {
28        match value {
29            0 => Some(OutputType::Hdmi),
30            1 => Some(OutputType::Bt),
31            2 => Some(OutputType::Optical),
32            3 => Some(OutputType::Headphone),
33            4 => Some(OutputType::Internal),
34            5 => Some(OutputType::Other),
35            _ => None,
36        }
37    }
38
39    /// Convert to u8 value
40    pub fn to_u8(self) -> u8 {
41        self as u8
42    }
43}
44
45impl From<OutputType> for u8 {
46    fn from(val: OutputType) -> Self {
47        val as u8
48    }
49}
50
51// Struct definitions
52
53#[derive(Debug, serde::Serialize)]
54pub struct OutputInfo {
55    pub index: Option<u8>,
56    pub output_type: Option<OutputType>,
57    pub name: Option<String>,
58}
59
60// Command encoders
61
62/// Encode SelectOutput command (0x00)
63pub fn encode_select_output(index: u8) -> anyhow::Result<Vec<u8>> {
64    let tlv = tlv::TlvItemEnc {
65        tag: 0,
66        value: tlv::TlvItemValueEnc::StructInvisible(vec![
67        (0, tlv::TlvItemValueEnc::UInt8(index)).into(),
68        ]),
69    };
70    Ok(tlv.encode()?)
71}
72
73/// Encode RenameOutput command (0x01)
74pub fn encode_rename_output(index: u8, name: String) -> anyhow::Result<Vec<u8>> {
75    let tlv = tlv::TlvItemEnc {
76        tag: 0,
77        value: tlv::TlvItemValueEnc::StructInvisible(vec![
78        (0, tlv::TlvItemValueEnc::UInt8(index)).into(),
79        (1, tlv::TlvItemValueEnc::String(name)).into(),
80        ]),
81    };
82    Ok(tlv.encode()?)
83}
84
85// Attribute decoders
86
87/// Decode OutputList attribute (0x0000)
88pub fn decode_output_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<OutputInfo>> {
89    let mut res = Vec::new();
90    if let tlv::TlvItemValue::List(v) = inp {
91        for item in v {
92            res.push(OutputInfo {
93                index: item.get_int(&[0]).map(|v| v as u8),
94                output_type: item.get_int(&[1]).and_then(|v| OutputType::from_u8(v as u8)),
95                name: item.get_string_owned(&[2]),
96            });
97        }
98    }
99    Ok(res)
100}
101
102/// Decode CurrentOutput attribute (0x0001)
103pub fn decode_current_output(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
104    if let tlv::TlvItemValue::Int(v) = inp {
105        Ok(*v as u8)
106    } else {
107        Err(anyhow::anyhow!("Expected UInt8"))
108    }
109}
110
111
112// JSON dispatcher function
113
114/// Decode attribute value and return as JSON string
115///
116/// # Parameters
117/// * `cluster_id` - The cluster identifier
118/// * `attribute_id` - The attribute identifier
119/// * `tlv_value` - The TLV value to decode
120///
121/// # Returns
122/// JSON string representation of the decoded value or error
123pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
124    // Verify this is the correct cluster
125    if cluster_id != 0x050B {
126        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x050B, got {}\"}}", cluster_id);
127    }
128
129    match attribute_id {
130        0x0000 => {
131            match decode_output_list(tlv_value) {
132                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
133                Err(e) => format!("{{\"error\": \"{}\"}}", e),
134            }
135        }
136        0x0001 => {
137            match decode_current_output(tlv_value) {
138                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
139                Err(e) => format!("{{\"error\": \"{}\"}}", e),
140            }
141        }
142        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
143    }
144}
145
146/// Get list of all attributes supported by this cluster
147///
148/// # Returns
149/// Vector of tuples containing (attribute_id, attribute_name)
150pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
151    vec![
152        (0x0000, "OutputList"),
153        (0x0001, "CurrentOutput"),
154    ]
155}
156