1use once_cell::sync::Lazy;
2
3use crate::info::Kind;
4
5use super::{codes, AjazzProtocolParser};
6
7fn format_request(cmd: &[u8]) -> Vec<u8> {
8 let mut buf = vec![];
9 buf.extend(codes::REQUEST_HEADER);
10 buf.extend(cmd);
11 buf
12}
13
14static REQUEST_KEEP_ALIVE: Lazy<Vec<u8>> =
16 Lazy::new(|| format_request(codes::REQUEST_CMD_KEEP_ALIVE));
17
18static REQUEST_INITIALIZE: Lazy<Vec<u8>> =
20 Lazy::new(|| format_request(codes::REQUEST_CMD_DIS));
21
22static REQUEST_BRIGHTNESS: Lazy<Vec<u8>> =
24 Lazy::new(|| format_request(codes::REQUEST_CMD_LIG));
25
26static REQUEST_SLEEP: Lazy<Vec<u8>> = Lazy::new(|| format_request(codes::REQUEST_CMD_SLEEP));
28
29static REQUEST_SHUTDOWN: Lazy<Vec<u8>> =
31 Lazy::new(|| format_request(codes::REQUEST_CMD_SHUTDOWN));
32
33static REQUEST_CLEAR_BUTTON_IMAGE: Lazy<Vec<u8>> =
35 Lazy::new(|| format_request(codes::REQUEST_CMD_CLEAR_BUTTON_IMAGE));
36
37static REQUEST_FLUSH: Lazy<Vec<u8>> = Lazy::new(|| format_request(codes::REQUEST_CMD_FLUSH));
39
40static REQUEST_IMAGE_ANNOUNCE: Lazy<Vec<u8>> =
42 Lazy::new(|| format_request(codes::REQUEST_CMD_IMAGE_ANNOUNCE));
43
44static REQUEST_LOGO_IMAGE_V1: Lazy<Vec<u8>> =
46 Lazy::new(|| format_request(codes::REQUEST_CMD_LOGO_IMAGE_V1));
47
48static REQUEST_LOGO_IMAGE_V2: Lazy<Vec<u8>> =
50 Lazy::new(|| format_request(codes::REQUEST_CMD_LOGO_IMAGE_V2));
51
52pub(crate) static FEATURE_REPORT_VERSION: Lazy<Vec<u8>> = Lazy::new(|| {
53 let mut buff = vec![0x00; 20];
54 buff.insert(0, codes::FEATURE_REPORT_ID_VERSION);
55 buff
56});
57
58pub(crate) trait AjazzRequestBuilder {
59 fn brightness_packet(&self, percent: u8) -> Vec<u8>;
60 fn keep_alive_packet(&self) -> Vec<u8>;
61 fn initialize_packet(&self) -> Vec<u8>;
62 fn sleep_packet(&self) -> Vec<u8>;
63 fn shutdown_packet(&self) -> Vec<u8>;
64 fn clear_button_image_packet(&self, key: u8) -> Vec<u8>;
65 fn flush_packet(&self) -> Vec<u8>;
66
67 fn image_announce_packet(&self, index: u8, image_data: &[u8]) -> Vec<u8>;
68 fn key_image_announce_packet(&self, key: u8, image_data: &[u8]) -> Vec<u8>;
69
70 fn logo_image_packet(&self, image_data: &[u8]) -> Vec<u8>;
71}
72
73impl Kind {
74 fn packet_length(&self) -> usize {
75 if self.is_v2_api() {
76 1024
77 } else {
78 512
79 }
80 }
81
82 pub fn pad_packet(&self, buf: &mut Vec<u8>) {
84 let length = self.packet_length() + 1;
85
86 buf.extend(vec![0x00; length - buf.len()]);
87 }
88}
89
90impl AjazzRequestBuilder for Kind {
91 fn brightness_packet(&self, percent: u8) -> Vec<u8> {
92 let mut buf = REQUEST_BRIGHTNESS.clone();
93 buf.push(percent);
94
95 self.pad_packet(&mut buf);
96 buf
97 }
98
99 fn keep_alive_packet(&self) -> Vec<u8> {
100 let mut buf = REQUEST_KEEP_ALIVE.clone();
101 self.pad_packet(&mut buf);
102 buf
103 }
104
105 fn initialize_packet(&self) -> Vec<u8> {
106 let mut buf = REQUEST_INITIALIZE.clone();
107 self.pad_packet(&mut buf);
108 buf
109 }
110
111 fn sleep_packet(&self) -> Vec<u8> {
112 let mut buf = REQUEST_SLEEP.clone();
113 self.pad_packet(&mut buf);
114 buf
115 }
116
117 fn shutdown_packet(&self) -> Vec<u8> {
118 let mut buf = REQUEST_SHUTDOWN.clone();
119 self.pad_packet(&mut buf);
120 buf
121 }
122
123 fn clear_button_image_packet(&self, key: u8) -> Vec<u8> {
124 let key = self.index_from_native_v1(key).unwrap_or(key);
125 let key = if key == 0xff { 0xff } else { key + 1 };
126
127 let mut buf = REQUEST_CLEAR_BUTTON_IMAGE.clone();
128 buf.push(key);
129 self.pad_packet(&mut buf);
130 buf
131 }
132
133 fn flush_packet(&self) -> Vec<u8> {
134 let mut buf = REQUEST_FLUSH.clone();
135 self.pad_packet(&mut buf);
136 buf
137 }
138
139 fn image_announce_packet(&self, index: u8, image_data: &[u8]) -> Vec<u8> {
140 let mut buf = REQUEST_IMAGE_ANNOUNCE.clone();
141 buf.push((image_data.len() >> 8) as u8);
142 buf.push(image_data.len() as u8);
143 buf.push(index);
144 self.pad_packet(&mut buf);
145 buf
146 }
147
148 fn key_image_announce_packet(&self, key: u8, image_data: &[u8]) -> Vec<u8> {
149 let index = self.index_to_native_v1(key).unwrap_or(key);
150 self.image_announce_packet(index + 1, image_data)
151 }
152
153 fn logo_image_packet(&self, image_data: &[u8]) -> Vec<u8> {
154 let mut buf = if self.is_v2_api() {
155 let mut buf = REQUEST_LOGO_IMAGE_V2.clone();
156 buf.push((image_data.len() >> 8) as u8);
157 buf.push(image_data.len() as u8);
158 buf
159 } else {
160 REQUEST_LOGO_IMAGE_V1.clone()
161 };
162 self.pad_packet(&mut buf);
163 buf
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 fn padded_packet(kind: Kind, buf: Vec<u8>) -> Vec<u8> {
174 let length = if kind.is_v2_api() { 1025 } else { 513 };
175 let mut buf = buf;
176 buf.extend(vec![0u8; length - buf.len()]);
177 buf
178 }
179
180 #[test]
181 fn test_brightness_packet() {
182 let kind = Kind::Akp153;
183 let brightness = 50;
184 let packet = kind.brightness_packet(brightness);
185 let expected = padded_packet(
186 kind,
187 vec![
188 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x49, 0x47, 0x00, 0x00, brightness,
189 ],
190 );
191
192 assert_eq!(packet, expected);
193 }
194
195 #[test]
196 fn test_keep_alive_packet() {
197 let kind = Kind::Akp153;
198 let packet = kind.keep_alive_packet();
199 let expected = padded_packet(
200 kind,
201 vec![
202 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54,
203 ],
204 );
205 assert_eq!(packet, expected);
206 }
207
208 #[test]
209 fn test_initialize_packet() {
210 let kind = Kind::Akp153;
211 let packet = kind.initialize_packet();
212 let expected = padded_packet(
213 kind,
214 vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x44, 0x49, 0x53],
215 );
216
217 assert_eq!(packet, expected);
218 }
219
220 #[test]
221 fn test_sleep_packet() {
222 let kind = Kind::Akp153;
223 let packet = kind.sleep_packet();
224 let expected = padded_packet(
225 kind,
226 vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x48, 0x41, 0x4E],
227 );
228 assert_eq!(packet, expected);
229 }
230
231 #[test]
232 fn test_shutdown_packet() {
233 let kind = Kind::Akp153;
234 let packet = kind.shutdown_packet();
235 let expected = padded_packet(
236 kind,
237 vec![
238 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x44, 0x43,
239 ],
240 );
241 assert_eq!(packet, expected);
242 }
243
244 #[test]
245 fn test_clear_button_image_packet() {
246 let kind = Kind::Akp153;
247
248 fn assert_clear_packet(kind: Kind, key: u8, expected: Vec<u8>) {
249 let packet = kind.clear_button_image_packet(key);
250 let expected = padded_packet(kind, expected);
251 assert_eq!(packet, expected);
252 }
253
254 assert_clear_packet(
255 kind,
256 0,
257 vec![
258 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x00, 0x05,
259 ],
260 );
261 assert_clear_packet(
262 kind,
263 1,
264 vec![
265 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x00, 0x0B,
266 ],
267 );
268 assert_clear_packet(
269 kind,
270 0xff,
271 vec![
272 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x00, 0xff,
273 ],
274 );
275 }
276
277 #[test]
278 fn test_flush_packet() {
279 let kind = Kind::Akp153;
280 let packet = kind.flush_packet();
281 let expected = padded_packet(
282 kind,
283 vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x53, 0x54, 0x50],
284 );
285 assert_eq!(packet, expected);
286 }
287
288 #[test]
289 fn test_image_announce_packet() {
290 let kind = Kind::Akp03RRev2;
291 let packet = kind.image_announce_packet(0, &[0x00, 0x01]);
292 let expected = padded_packet(
293 kind,
294 vec![
295 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x42, 0x41, 0x54, 0x00, 0x00, 0x00, 0x02,
296 0x00, 0x00, 0x00,
297 ],
298 );
299 assert_eq!(packet, expected);
300 }
301
302 #[test]
303 fn test_logo_image_packet() {
304 let kind = Kind::Akp153;
305 let packet = kind.logo_image_packet(&[0x00, 0x01]);
306 let expected = padded_packet(
307 kind,
308 vec![
309 0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x4f, 0x47, 0x00, 0x12, 0xc3, 0xc0,
310 0x01,
311 ],
312 );
313 assert_eq!(packet, expected);
314 }
315
316 }