1#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13pub fn encode_get_setup_pin(temp_account_identifier: String) -> anyhow::Result<Vec<u8>> {
17 let tlv = tlv::TlvItemEnc {
18 tag: 0,
19 value: tlv::TlvItemValueEnc::StructInvisible(vec![
20 (0, tlv::TlvItemValueEnc::String(temp_account_identifier)).into(),
21 ]),
22 };
23 Ok(tlv.encode()?)
24}
25
26pub fn encode_login(temp_account_identifier: String, setup_pin: String, node: u64) -> anyhow::Result<Vec<u8>> {
28 let tlv = tlv::TlvItemEnc {
29 tag: 0,
30 value: tlv::TlvItemValueEnc::StructInvisible(vec![
31 (0, tlv::TlvItemValueEnc::String(temp_account_identifier)).into(),
32 (1, tlv::TlvItemValueEnc::String(setup_pin)).into(),
33 (2, tlv::TlvItemValueEnc::UInt64(node)).into(),
34 ]),
35 };
36 Ok(tlv.encode()?)
37}
38
39pub fn encode_logout(node: u64) -> anyhow::Result<Vec<u8>> {
41 let tlv = tlv::TlvItemEnc {
42 tag: 0,
43 value: tlv::TlvItemValueEnc::StructInvisible(vec![
44 (0, tlv::TlvItemValueEnc::UInt64(node)).into(),
45 ]),
46 };
47 Ok(tlv.encode()?)
48}
49
50pub fn get_command_list() -> Vec<(u32, &'static str)> {
53 vec![
54 (0x00, "GetSetupPIN"),
55 (0x02, "Login"),
56 (0x03, "Logout"),
57 ]
58}
59
60pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
61 match cmd_id {
62 0x00 => Some("GetSetupPIN"),
63 0x02 => Some("Login"),
64 0x03 => Some("Logout"),
65 _ => None,
66 }
67}
68
69pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
70 match cmd_id {
71 0x00 => Some(vec![
72 crate::clusters::codec::CommandField { tag: 0, name: "temp_account_identifier", kind: crate::clusters::codec::FieldKind::String, optional: false, nullable: false },
73 ]),
74 0x02 => Some(vec![
75 crate::clusters::codec::CommandField { tag: 0, name: "temp_account_identifier", kind: crate::clusters::codec::FieldKind::String, optional: false, nullable: false },
76 crate::clusters::codec::CommandField { tag: 1, name: "setup_pin", kind: crate::clusters::codec::FieldKind::String, optional: false, nullable: false },
77 crate::clusters::codec::CommandField { tag: 2, name: "node", kind: crate::clusters::codec::FieldKind::U64, optional: true, nullable: false },
78 ]),
79 0x03 => Some(vec![
80 crate::clusters::codec::CommandField { tag: 0, name: "node", kind: crate::clusters::codec::FieldKind::U64, optional: true, nullable: false },
81 ]),
82 _ => None,
83 }
84}
85
86pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
87 match cmd_id {
88 0x00 => {
89 let temp_account_identifier = crate::clusters::codec::json_util::get_string(args, "temp_account_identifier")?;
90 encode_get_setup_pin(temp_account_identifier)
91 }
92 0x02 => {
93 let temp_account_identifier = crate::clusters::codec::json_util::get_string(args, "temp_account_identifier")?;
94 let setup_pin = crate::clusters::codec::json_util::get_string(args, "setup_pin")?;
95 let node = crate::clusters::codec::json_util::get_u64(args, "node")?;
96 encode_login(temp_account_identifier, setup_pin, node)
97 }
98 0x03 => {
99 let node = crate::clusters::codec::json_util::get_u64(args, "node")?;
100 encode_logout(node)
101 }
102 _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
103 }
104}
105
106#[derive(Debug, serde::Serialize)]
107pub struct GetSetupPINResponse {
108 pub setup_pin: Option<String>,
109}
110
111pub fn decode_get_setup_pin_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetSetupPINResponse> {
115 if let tlv::TlvItemValue::List(_fields) = inp {
116 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
117 Ok(GetSetupPINResponse {
118 setup_pin: item.get_string_owned(&[0]),
119 })
120 } else {
121 Err(anyhow::anyhow!("Expected struct fields"))
122 }
123}
124
125pub async fn get_setup_pin(conn: &crate::controller::Connection, endpoint: u16, temp_account_identifier: String) -> anyhow::Result<GetSetupPINResponse> {
129 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ACCOUNT_LOGIN, crate::clusters::defs::CLUSTER_ACCOUNT_LOGIN_CMD_ID_GETSETUPPIN, &encode_get_setup_pin(temp_account_identifier)?).await?;
130 decode_get_setup_pin_response(&tlv)
131}
132
133pub async fn login(conn: &crate::controller::Connection, endpoint: u16, temp_account_identifier: String, setup_pin: String, node: u64) -> anyhow::Result<()> {
135 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_ACCOUNT_LOGIN, crate::clusters::defs::CLUSTER_ACCOUNT_LOGIN_CMD_ID_LOGIN, &encode_login(temp_account_identifier, setup_pin, node)?).await?;
136 Ok(())
137}
138
139pub async fn logout(conn: &crate::controller::Connection, endpoint: u16, node: u64) -> anyhow::Result<()> {
141 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_ACCOUNT_LOGIN, crate::clusters::defs::CLUSTER_ACCOUNT_LOGIN_CMD_ID_LOGOUT, &encode_logout(node)?).await?;
142 Ok(())
143}
144
145#[derive(Debug, serde::Serialize)]
146pub struct LoggedOutEvent {
147 pub node: Option<u64>,
148}
149
150pub fn decode_logged_out_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LoggedOutEvent> {
154 if let tlv::TlvItemValue::List(_fields) = inp {
155 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
156 Ok(LoggedOutEvent {
157 node: item.get_int(&[0]),
158 })
159 } else {
160 Err(anyhow::anyhow!("Expected struct fields"))
161 }
162}
163