matc/clusters/codec/
content_app_observer.rs1#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[repr(u8)]
17pub enum Status {
18 Success = 0,
20 Unexpecteddata = 1,
22}
23
24impl Status {
25 pub fn from_u8(value: u8) -> Option<Self> {
27 match value {
28 0 => Some(Status::Success),
29 1 => Some(Status::Unexpecteddata),
30 _ => None,
31 }
32 }
33
34 pub fn to_u8(self) -> u8 {
36 self as u8
37 }
38}
39
40impl From<Status> for u8 {
41 fn from(val: Status) -> Self {
42 val as u8
43 }
44}
45
46pub fn encode_content_app_message(data: String, encoding_hint: String) -> anyhow::Result<Vec<u8>> {
50 let tlv = tlv::TlvItemEnc {
51 tag: 0,
52 value: tlv::TlvItemValueEnc::StructInvisible(vec![
53 (0, tlv::TlvItemValueEnc::String(data)).into(),
54 (1, tlv::TlvItemValueEnc::String(encoding_hint)).into(),
55 ]),
56 };
57 Ok(tlv.encode()?)
58}
59
60pub fn get_command_list() -> Vec<(u32, &'static str)> {
63 vec![
64 (0x00, "ContentAppMessage"),
65 ]
66}
67
68pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
69 match cmd_id {
70 0x00 => Some("ContentAppMessage"),
71 _ => None,
72 }
73}
74
75pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
76 match cmd_id {
77 0x00 => Some(vec![
78 crate::clusters::codec::CommandField { tag: 0, name: "data", kind: crate::clusters::codec::FieldKind::String, optional: false, nullable: false },
79 crate::clusters::codec::CommandField { tag: 1, name: "encoding_hint", kind: crate::clusters::codec::FieldKind::String, optional: true, nullable: false },
80 ]),
81 _ => None,
82 }
83}
84
85pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
86 match cmd_id {
87 0x00 => {
88 let data = crate::clusters::codec::json_util::get_string(args, "data")?;
89 let encoding_hint = crate::clusters::codec::json_util::get_string(args, "encoding_hint")?;
90 encode_content_app_message(data, encoding_hint)
91 }
92 _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
93 }
94}
95
96#[derive(Debug, serde::Serialize)]
97pub struct ContentAppMessageResponse {
98 pub status: Option<Status>,
99 pub data: Option<String>,
100 pub encoding_hint: Option<String>,
101}
102
103pub fn decode_content_app_message_response(inp: &tlv::TlvItemValue) -> anyhow::Result<ContentAppMessageResponse> {
107 if let tlv::TlvItemValue::List(_fields) = inp {
108 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
109 Ok(ContentAppMessageResponse {
110 status: item.get_int(&[0]).and_then(|v| Status::from_u8(v as u8)),
111 data: item.get_string_owned(&[1]),
112 encoding_hint: item.get_string_owned(&[2]),
113 })
114 } else {
115 Err(anyhow::anyhow!("Expected struct fields"))
116 }
117}
118
119pub async fn content_app_message(conn: &crate::controller::Connection, endpoint: u16, data: String, encoding_hint: String) -> anyhow::Result<ContentAppMessageResponse> {
123 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_CONTENT_APP_OBSERVER, crate::clusters::defs::CLUSTER_CONTENT_APP_OBSERVER_CMD_ID_CONTENTAPPMESSAGE, &encode_content_app_message(data, encoding_hint)?).await?;
124 decode_content_app_message_response(&tlv)
125}
126