1mod cipher;
45mod crc;
46pub mod error;
47pub mod mesparse;
48pub mod tuyadevice;
49
50extern crate num;
51extern crate num_derive;
52#[macro_use]
53extern crate lazy_static;
54
55use serde::{Deserialize, Serialize};
56
57use std::convert::TryFrom;
58use std::fmt::Display;
59
60use crate::error::ErrorKind;
61use std::convert::TryInto;
62
63pub type Result<T> = std::result::Result<T, ErrorKind>;
64#[derive(Debug, Clone, PartialEq, Eq)]
67pub enum Payload {
68 Struct(PayloadStruct),
69 ControlNewStruct(ControlNewPayload),
70 String(String),
71 Raw(Vec<u8>),
72}
73
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub enum DpId {
76 Lower,
77 Higher,
78}
79
80impl DpId {
81 fn get_ids(self) -> Vec<u8> {
82 match self {
83 DpId::Lower => vec![4, 5, 6],
84 DpId::Higher => vec![18, 19, 20],
85 }
86 }
87}
88
89impl Payload {
90 pub fn new(
91 dev_id: String,
92 gw_id: Option<String>,
93 uid: Option<String>,
94 t: Option<u32>,
95 dp_id: Option<DpId>,
96 dps: Option<serde_json::Value>,
97 ) -> Payload {
98 Payload::Struct(PayloadStruct {
99 dev_id,
100 gw_id,
101 uid,
102 t: t.map(|t| t.to_string()),
103 dp_id: dp_id.map(DpId::get_ids),
104 dps,
105 })
106 }
107}
108
109impl Display for Payload {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 match self {
112 Payload::Struct(s) => write!(f, "{}", s),
113 Payload::ControlNewStruct(s) => write!(f, "{}", s),
114 Payload::String(s) => write!(f, "{}", s),
115 Payload::Raw(s) => write!(f, "{}", hex::encode(s)),
116 }
117 }
118}
119
120#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
123pub struct PayloadStruct {
124 #[serde(rename = "gwId", skip_serializing_if = "Option::is_none")]
125 pub gw_id: Option<String>,
126 #[serde(rename = "devId")]
127 pub dev_id: String,
128 #[serde(skip_serializing_if = "Option::is_none")]
129 pub uid: Option<String>,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 pub t: Option<String>,
132 #[serde(rename = "dpId", skip_serializing_if = "Option::is_none")]
133 pub dp_id: Option<Vec<u8>>,
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub dps: Option<serde_json::Value>,
136}
137
138#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
141pub struct ControlNewPayload {
142 pub protocol: u32,
143 pub t: u32,
144 pub data: ControlNewPayloadData,
145}
146
147#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
148pub struct ControlNewPayloadData {
149 dps: serde_json::Value,
150}
151pub trait Truncate {
153 fn truncate(&self) -> Self;
154
155 fn truncate_str(text: &str) -> &str {
157 if let Some((i, _)) = text.char_indices().rev().nth(5) {
158 return &text[i..];
159 }
160 text
161 }
162}
163
164impl TryFrom<Vec<u8>> for Payload {
165 type Error = ErrorKind;
166
167 fn try_from(vec: Vec<u8>) -> Result<Self> {
168 match serde_json::from_slice(&vec)? {
169 serde_json::Value::String(s) => Ok(Payload::String(s)),
170 value => Ok(Payload::Struct(serde_json::from_value(value)?)),
171 }
172 }
173}
174impl TryInto<Vec<u8>> for Payload {
175 type Error = ErrorKind;
176
177 fn try_into(self) -> Result<Vec<u8>> {
178 match self {
179 Payload::Struct(s) => Ok(serde_json::to_vec(&s)?),
180 Payload::ControlNewStruct(s) => Ok(serde_json::to_vec(&s)?),
181 Payload::String(s) => Ok(s.as_bytes().to_vec()),
182 Payload::Raw(s) => Ok(s),
183 }
184 }
185}
186
187impl Truncate for PayloadStruct {
188 fn truncate(&self) -> PayloadStruct {
189 PayloadStruct {
190 dev_id: String::from("...") + Self::truncate_str(&self.dev_id),
191 gw_id: self
192 .gw_id
193 .as_ref()
194 .map(|gwid| String::from("...") + Self::truncate_str(gwid)),
195 t: self.t.clone(),
196 dp_id: self.dp_id.clone(),
197 uid: self.uid.clone(),
198 dps: self.dps.clone(),
199 }
200 }
201}
202
203impl Display for PayloadStruct {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 let full_display = std::env::var("TUYA_FULL_DISPLAY").map_or_else(|_| false, |_| true);
206 if full_display {
207 write!(f, "{}", serde_json::to_string(self).unwrap())
208 } else {
209 write!(f, "{}", serde_json::to_string(&self.truncate()).unwrap())
210 }
211 }
212}
213
214impl Display for ControlNewPayload {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 write!(f, "{}", serde_json::to_string(self).unwrap())
217 }
218}