ajazz_sdk/protocol/
request.rs

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
14/// Request for keep alive command
15static REQUEST_KEEP_ALIVE: Lazy<Vec<u8>> =
16    Lazy::new(|| format_request(codes::REQUEST_CMD_KEEP_ALIVE));
17
18/// Request for initialize command
19static REQUEST_INITIALIZE: Lazy<Vec<u8>> =
20    Lazy::new(|| format_request(codes::REQUEST_CMD_DIS));
21
22/// Request for brightness command
23static REQUEST_BRIGHTNESS: Lazy<Vec<u8>> =
24    Lazy::new(|| format_request(codes::REQUEST_CMD_LIG));
25
26/// Request for sleep command
27static REQUEST_SLEEP: Lazy<Vec<u8>> = Lazy::new(|| format_request(codes::REQUEST_CMD_SLEEP));
28
29/// Request for shutdown command
30static REQUEST_SHUTDOWN: Lazy<Vec<u8>> =
31    Lazy::new(|| format_request(codes::REQUEST_CMD_SHUTDOWN));
32
33/// Request for clear button image command
34static REQUEST_CLEAR_BUTTON_IMAGE: Lazy<Vec<u8>> =
35    Lazy::new(|| format_request(codes::REQUEST_CMD_CLEAR_BUTTON_IMAGE));
36
37/// Request for flush command
38static REQUEST_FLUSH: Lazy<Vec<u8>> = Lazy::new(|| format_request(codes::REQUEST_CMD_FLUSH));
39
40/// Request for image announce packet
41static REQUEST_IMAGE_ANNOUNCE: Lazy<Vec<u8>> =
42    Lazy::new(|| format_request(codes::REQUEST_CMD_IMAGE_ANNOUNCE));
43
44/// Request for logo image command
45static REQUEST_LOGO_IMAGE_V1: Lazy<Vec<u8>> =
46    Lazy::new(|| format_request(codes::REQUEST_CMD_LOGO_IMAGE_V1));
47
48/// Request for logo image command
49static 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    /// Extends buffer up to required packet length
83    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    /// Pads packet up to required packet length.
172    /// Function is used to generate expected packet for testing.
173    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    // TODO: Add test for apply logo image packet
317}