matc/clusters/codec/
web_rtc_requestor.rs

1//! Matter TLV encoders and decoders for WebRTC Transport Requestor Cluster
2//! Cluster ID: 0x0554
3//!
4//! This file is automatically generated from WebRTC_Requestor.xml
5
6#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13// Command encoders
14
15/// Encode Offer command (0x00)
16pub fn encode_offer(web_rtc_session_id: u8, sdp: String, ice_transport_policy: String) -> anyhow::Result<Vec<u8>> {
17    let tlv = tlv::TlvItemEnc {
18        tag: 0,
19        value: tlv::TlvItemValueEnc::StructInvisible(vec![
20        (0, tlv::TlvItemValueEnc::UInt8(web_rtc_session_id)).into(),
21        (1, tlv::TlvItemValueEnc::String(sdp)).into(),
22        (3, tlv::TlvItemValueEnc::String(ice_transport_policy)).into(),
23        ]),
24    };
25    Ok(tlv.encode()?)
26}
27
28/// Encode Answer command (0x01)
29pub fn encode_answer(web_rtc_session_id: u8, sdp: String) -> anyhow::Result<Vec<u8>> {
30    let tlv = tlv::TlvItemEnc {
31        tag: 0,
32        value: tlv::TlvItemValueEnc::StructInvisible(vec![
33        (0, tlv::TlvItemValueEnc::UInt8(web_rtc_session_id)).into(),
34        (1, tlv::TlvItemValueEnc::String(sdp)).into(),
35        ]),
36    };
37    Ok(tlv.encode()?)
38}
39
40/// Encode ICECandidates command (0x02)
41pub fn encode_ice_candidates(web_rtc_session_id: u8) -> anyhow::Result<Vec<u8>> {
42    let tlv = tlv::TlvItemEnc {
43        tag: 0,
44        value: tlv::TlvItemValueEnc::StructInvisible(vec![
45        (0, tlv::TlvItemValueEnc::UInt8(web_rtc_session_id)).into(),
46        ]),
47    };
48    Ok(tlv.encode()?)
49}
50
51/// Encode End command (0x03)
52pub fn encode_end(web_rtc_session_id: u8, reason: u8) -> anyhow::Result<Vec<u8>> {
53    let tlv = tlv::TlvItemEnc {
54        tag: 0,
55        value: tlv::TlvItemValueEnc::StructInvisible(vec![
56        (0, tlv::TlvItemValueEnc::UInt8(web_rtc_session_id)).into(),
57        (1, tlv::TlvItemValueEnc::UInt8(reason)).into(),
58        ]),
59    };
60    Ok(tlv.encode()?)
61}
62
63// Attribute decoders
64
65/// Decode CurrentSessions attribute (0x0000)
66pub fn decode_current_sessions(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
67    let mut res = Vec::new();
68    if let tlv::TlvItemValue::List(v) = inp {
69        for item in v {
70            if let tlv::TlvItemValue::Int(i) = &item.value {
71                res.push(*i as u8);
72            }
73        }
74    }
75    Ok(res)
76}
77
78
79// JSON dispatcher function
80
81/// Decode attribute value and return as JSON string
82///
83/// # Parameters
84/// * `cluster_id` - The cluster identifier
85/// * `attribute_id` - The attribute identifier
86/// * `tlv_value` - The TLV value to decode
87///
88/// # Returns
89/// JSON string representation of the decoded value or error
90pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
91    // Verify this is the correct cluster
92    if cluster_id != 0x0554 {
93        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0554, got {}\"}}", cluster_id);
94    }
95
96    match attribute_id {
97        0x0000 => {
98            match decode_current_sessions(tlv_value) {
99                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
100                Err(e) => format!("{{\"error\": \"{}\"}}", e),
101            }
102        }
103        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
104    }
105}
106
107/// Get list of all attributes supported by this cluster
108///
109/// # Returns
110/// Vector of tuples containing (attribute_id, attribute_name)
111pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
112    vec![
113        (0x0000, "CurrentSessions"),
114    ]
115}
116
117// Command listing
118
119pub fn get_command_list() -> Vec<(u32, &'static str)> {
120    vec![
121        (0x00, "Offer"),
122        (0x01, "Answer"),
123        (0x02, "ICECandidates"),
124        (0x03, "End"),
125    ]
126}
127
128pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
129    match cmd_id {
130        0x00 => Some("Offer"),
131        0x01 => Some("Answer"),
132        0x02 => Some("ICECandidates"),
133        0x03 => Some("End"),
134        _ => None,
135    }
136}
137
138pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
139    match cmd_id {
140        0x00 => Some(vec![
141            crate::clusters::codec::CommandField { tag: 0, name: "web_rtc_session_id", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: false },
142            crate::clusters::codec::CommandField { tag: 1, name: "sdp", kind: crate::clusters::codec::FieldKind::String, optional: false, nullable: false },
143            crate::clusters::codec::CommandField { tag: 3, name: "ice_transport_policy", kind: crate::clusters::codec::FieldKind::String, optional: true, nullable: false },
144        ]),
145        0x01 => Some(vec![
146            crate::clusters::codec::CommandField { tag: 0, name: "web_rtc_session_id", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: false },
147            crate::clusters::codec::CommandField { tag: 1, name: "sdp", kind: crate::clusters::codec::FieldKind::String, optional: false, nullable: false },
148        ]),
149        0x02 => Some(vec![
150            crate::clusters::codec::CommandField { tag: 0, name: "web_rtc_session_id", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: false },
151        ]),
152        0x03 => Some(vec![
153            crate::clusters::codec::CommandField { tag: 0, name: "web_rtc_session_id", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: false },
154            crate::clusters::codec::CommandField { tag: 1, name: "reason", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
155        ]),
156        _ => None,
157    }
158}
159
160pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
161    match cmd_id {
162        0x00 => {
163        let web_rtc_session_id = crate::clusters::codec::json_util::get_u8(args, "web_rtc_session_id")?;
164        let sdp = crate::clusters::codec::json_util::get_string(args, "sdp")?;
165        let ice_transport_policy = crate::clusters::codec::json_util::get_string(args, "ice_transport_policy")?;
166        encode_offer(web_rtc_session_id, sdp, ice_transport_policy)
167        }
168        0x01 => {
169        let web_rtc_session_id = crate::clusters::codec::json_util::get_u8(args, "web_rtc_session_id")?;
170        let sdp = crate::clusters::codec::json_util::get_string(args, "sdp")?;
171        encode_answer(web_rtc_session_id, sdp)
172        }
173        0x02 => {
174        let web_rtc_session_id = crate::clusters::codec::json_util::get_u8(args, "web_rtc_session_id")?;
175        encode_ice_candidates(web_rtc_session_id)
176        }
177        0x03 => {
178        let web_rtc_session_id = crate::clusters::codec::json_util::get_u8(args, "web_rtc_session_id")?;
179        let reason = crate::clusters::codec::json_util::get_u8(args, "reason")?;
180        encode_end(web_rtc_session_id, reason)
181        }
182        _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
183    }
184}
185
186// Typed facade (invokes + reads)
187
188/// Invoke `Offer` command on cluster `WebRTC Transport Requestor`.
189pub async fn offer(conn: &crate::controller::Connection, endpoint: u16, web_rtc_session_id: u8, sdp: String, ice_transport_policy: String) -> anyhow::Result<()> {
190    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_WEBRTC_TRANSPORT_REQUESTOR, crate::clusters::defs::CLUSTER_WEBRTC_TRANSPORT_REQUESTOR_CMD_ID_OFFER, &encode_offer(web_rtc_session_id, sdp, ice_transport_policy)?).await?;
191    Ok(())
192}
193
194/// Invoke `Answer` command on cluster `WebRTC Transport Requestor`.
195pub async fn answer(conn: &crate::controller::Connection, endpoint: u16, web_rtc_session_id: u8, sdp: String) -> anyhow::Result<()> {
196    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_WEBRTC_TRANSPORT_REQUESTOR, crate::clusters::defs::CLUSTER_WEBRTC_TRANSPORT_REQUESTOR_CMD_ID_ANSWER, &encode_answer(web_rtc_session_id, sdp)?).await?;
197    Ok(())
198}
199
200/// Invoke `ICECandidates` command on cluster `WebRTC Transport Requestor`.
201pub async fn ice_candidates(conn: &crate::controller::Connection, endpoint: u16, web_rtc_session_id: u8) -> anyhow::Result<()> {
202    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_WEBRTC_TRANSPORT_REQUESTOR, crate::clusters::defs::CLUSTER_WEBRTC_TRANSPORT_REQUESTOR_CMD_ID_ICECANDIDATES, &encode_ice_candidates(web_rtc_session_id)?).await?;
203    Ok(())
204}
205
206/// Invoke `End` command on cluster `WebRTC Transport Requestor`.
207pub async fn end(conn: &crate::controller::Connection, endpoint: u16, web_rtc_session_id: u8, reason: u8) -> anyhow::Result<()> {
208    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_WEBRTC_TRANSPORT_REQUESTOR, crate::clusters::defs::CLUSTER_WEBRTC_TRANSPORT_REQUESTOR_CMD_ID_END, &encode_end(web_rtc_session_id, reason)?).await?;
209    Ok(())
210}
211
212/// Read `CurrentSessions` attribute from cluster `WebRTC Transport Requestor`.
213pub async fn read_current_sessions(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<u8>> {
214    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_WEBRTC_TRANSPORT_REQUESTOR, crate::clusters::defs::CLUSTER_WEBRTC_TRANSPORT_REQUESTOR_ATTR_ID_CURRENTSESSIONS).await?;
215    decode_current_sessions(&tlv)
216}
217