Skip to main content

audiomoth_hid_rs/
lib.rs

1use hidapi::HidDevice;
2use std::io;
3use thiserror::Error;
4
5pub mod convert;
6
7#[cfg(test)]
8mod tests {
9    use crate::{
10        convert::{convert_four_bytes_from_buffer_to_id, make_response_handler},
11        new_hid_device, AudioMothDevice,
12    };
13
14    #[test]
15    fn it_works() {
16        let result = 2 + 2;
17        assert_eq!(result, 4);
18    }
19    #[test]
20    fn new_device_test() {
21        let device = new_hid_device().expect("打开设备失败");
22        let audio_moth = AudioMothDevice { device: device };
23        let buffer = [0x00, 0x03];
24        //通过调用函数返回使用
25        audio_moth.write_call(
26            &buffer,
27            make_response_handler(0x03, convert_four_bytes_from_buffer_to_id, |e, d| {
28                if e != None {
29                    println!("{:?} get device id get error", e)
30                } else {
31                    println!("{:?}", d)
32                }
33            }),
34        );
35    }
36}
37
38///
39///消息类型
40const USB_MSG_TYPE_GET_TIME: u8 = 0x01;
41const USB_MSG_TYPE_SET_TIME: u8 = 0x02;
42const USB_MSG_TYPE_GET_UID: u8 = 0x03;
43const USB_MSG_TYPE_GET_BATTERY: u8 = 0x04;
44const USB_MSG_TYPE_GET_APP_PACKET: u8 = 0x05;
45const USB_MSG_TYPE_SET_APP_PACKET: u8 = 0x06;
46const USB_MSG_TYPE_GET_FIRMWARE_VERSION: u8 = 0x07;
47const USB_MSG_TYPE_GET_FIRMWARE_DESCRIPTION: u8 = 0x08;
48const USB_MSG_TYPE_QUERY_BOOTLOADER: u8 = 0x09;
49const USB_MSG_TYPE_SWITCH_TO_BOOTLOADER: u8 = 0x0A;
50
51const VENDORID: u16 = 0x10c4;
52const PRODUCTID: u16 = 0x0002;
53
54type AudioMothResult<T> = std::result::Result<T, AudioMothError>;
55
56#[derive(Error, Debug)]
57pub  enum AudioMothError {
58    #[error("HID device not connect")]
59    HidError(#[from] hidapi::HidError),
60    #[error("OtherError")]
61    OtherError(String),
62    #[error("data store disconnected")]
63    IOError(#[from] io::Error),
64    #[error("get battery error is error")]
65    BatteryError(),
66}
67
68///new_hid_device
69/// 创建新的hid设备链接
70///
71fn new_hid_device() -> Option<HidDevice> {
72    let api =
73        hidapi::HidApi::new().unwrap_or_else(|e| panic!("Hid is init error{}", e.to_string()));
74    let hid = match api.open(VENDORID, PRODUCTID) {
75        Ok(hid) => hid,
76        Err(_) => {
77            return None;
78        }
79    };
80    Some(hid)
81}
82
83pub struct AudioMothDevice {
84    device: HidDevice,
85}
86
87#[allow(dead_code)]
88impl AudioMothDevice {
89    pub fn new() -> Option<Self> {
90        let device = new_hid_device();
91        match device {
92            Some(d) => {
93                return Some(AudioMothDevice { device: d });
94            }
95            None => None,
96        }
97    }
98
99    //写入数据
100    pub   fn write_call(&self, data: &[u8], callback: impl Fn(Option<String>, Option<&[u8]>)) {
101        self.device.write(data).unwrap();
102        let mut buf: [u8; 64] = [0; 64];
103        match self.device.read(&mut buf) {
104            Ok(ok) => callback(None, Some(&buf)),
105            Err(_) => callback(Some("No data read".to_string()), None),
106        };
107    }
108
109    pub   fn write(&self, data: &[u8]) -> AudioMothResult<usize> {
110        match self.device.write(data) {
111            Ok(size) => {
112                return Ok(size);
113            }
114            Err(e) => return Err(AudioMothError::HidError(e)),
115        }
116    }
117
118    /// msg_id=>0x01
119    pub    fn get_time(&self) -> AudioMothResult<Option<String>> {
120        let data: [u8; 2] = [0x00, USB_MSG_TYPE_GET_TIME];
121        match self.write(&data) {
122            Ok(usize) => {
123                if usize != 0 {
124                    let mut buff: [u8; 64] = [0; 64];
125                    if let Ok(size) = self.device.read(&mut buff) {
126                        if size > 0 && buff[0] == USB_MSG_TYPE_GET_TIME {
127                            return Ok(Some(
128                                crate::convert::convert_four_bytes_from_buffer_to_date(
129                                    &mut buff, 1,
130                                )
131                                .to_string(),
132                            ));
133                        }
134                    }
135                }
136            }
137            Err(_) => {
138                return Err(AudioMothError::OtherError(String::from(
139                    "Failed to get time",
140                )))
141            }
142        }
143        return Err(AudioMothError::OtherError(String::from(
144            "Failed to get time",
145        )));
146    }
147
148    /// msg_id=>0x02
149    pub     fn send_time(&self, unix_time_stamp: i64) -> AudioMothResult<usize> {
150        let mut msg_data = [0x00, USB_MSG_TYPE_SET_TIME, 0x00, 0x00, 0x00, 0x00];
151        convert::convert_date_to_four_bytes_in_buffer(&mut msg_data, 2, unix_time_stamp);
152        if let Ok(size) = self.write(&msg_data) {
153            if size == 0 {
154                return Err(AudioMothError::OtherError(String::from("send time error")));
155            }
156            let mut buf = [0u8; 64];
157            match self.device.read(&mut buf[..]) {
158                Ok(size) => {
159                    if size > 0 && buf[0] == USB_MSG_TYPE_SET_TIME {
160                        return Ok(size);
161                    } else {
162                        return Err(AudioMothError::OtherError(String::from("send time error")));
163                    }
164                }
165                Err(e) => return Err(AudioMothError::HidError(e)),
166            }
167        }
168        return Err(AudioMothError::OtherError(String::from("send time error")));
169    }
170
171    /// msg_id=>0x03
172    pub    fn get_id(&self) -> AudioMothResult<String> {
173        let data: [u8; 2] = [0x00, USB_MSG_TYPE_GET_UID];
174        match self.write(&data) {
175            Ok(usize) => {
176                if usize != 0 {
177                    let mut buff: [u8; 64] = [0; 64];
178                    if let Ok(size) = self.device.read(&mut buff) {
179                        if size > 0 && buff[0] == USB_MSG_TYPE_GET_UID {
180                            return Ok(convert::convert_four_bytes_from_buffer_to_id(&buff, 1));
181                        } else {
182                            return Err(AudioMothError::OtherError(String::from(
183                                " Incorrect message type from AudioMoth device",
184                            )));
185                        }
186                    }
187                }
188            }
189            Err(e) => {
190                return Err(e);
191            }
192        }
193        return Err(AudioMothError::OtherError(String::from("get id error")));
194    }
195    /// msg_id=>0x04
196    pub    fn get_battery(&self) -> AudioMothResult<String> {
197        let data: [u8; 2] = [0x00, USB_MSG_TYPE_GET_BATTERY];
198        match self.write(&data) {
199            Ok(usize) => {
200                if usize != 0 {
201                    let mut buff: [u8; 64] = [0; 64];
202                    if let Ok(size) = self.device.read(&mut buff) {
203                        if size > 0 && buff[0] == USB_MSG_TYPE_GET_BATTERY {
204                            return Ok(convert::convert_one_byte_from_buffer_to_battery_state(
205                                &buff, 1,
206                            ));
207                        } else {
208                            return Err(AudioMothError::OtherError(String::from(
209                                " Incorrect message type from AudioMoth device",
210                            )));
211                        }
212                    }
213                }
214            }
215            Err(e) => {
216                return Err(e);
217            }
218        }
219        return Err(AudioMothError::BatteryError());
220    }
221
222    /// msg_id=>0x05
223    pub   fn get_packet(&self) -> AudioMothResult<Option<[u8; 64]>> {
224        let msg_data = [0x00, USB_MSG_TYPE_GET_APP_PACKET];
225        let mut buff: [u8; 64] = [0; 64];
226        match self.write(&msg_data) {
227            Ok(size) => {
228                if size > 0 {
229                    match self.device.read(&mut buff) {
230                        Ok(size) => {
231                            if size > 0 && buff[0] == USB_MSG_TYPE_GET_APP_PACKET {
232                                return Ok(Some(buff));
233                            }
234                        }
235                        Err(e) => return Err(AudioMothError::HidError(e)),
236                    }
237                }
238            }
239            Err(e) => return Err(e),
240        }
241        return Err(AudioMothError::OtherError(String::from("get packet error")));
242    }
243
244    /**
245     *发送一个数据包
246     */
247    ///msg_id=>0x06
248    pub   fn send_packet(&self, msg_data: &[u8]) -> AudioMothResult<usize> {
249        let mut buffer = vec![0x00, USB_MSG_TYPE_SET_APP_PACKET];
250        msg_data.iter().for_each(|f| buffer.push(*f));
251        match self.device.write(&msg_data) {
252            Ok(uszie) => {
253                return Ok(uszie);
254            }
255            Err(e) => return Err(AudioMothError::HidError(e)),
256        }
257    }
258
259    /// msg_id=>0x07
260    pub   fn get_firmware_version(&self) -> AudioMothResult<[u8; 3]> {
261        let buffer = [0x00, USB_MSG_TYPE_GET_FIRMWARE_VERSION];
262        match self.write(&buffer) {
263            Ok(usize) => {
264                if usize != 0 {
265                    let mut buff: [u8; 64] = [0; 64];
266                    if let Ok(size) = self.device.read(&mut buff) {
267                        if size > 0 && buff[0] == USB_MSG_TYPE_GET_FIRMWARE_VERSION {
268                            return Ok(
269                                convert::convert_three_bytes_from_buffer_to_firmware_version(
270                                    &buff, 1,
271                                ),
272                            );
273                        } else {
274                            return Err(AudioMothError::OtherError(String::from(
275                                " Incorrect message type from AudioMoth device",
276                            )));
277                        }
278                    }
279                }
280            }
281            Err(e) => return Err(e),
282        }
283        return Err(AudioMothError::OtherError(String::from(
284            "get firmware version error",
285        )));
286    }
287
288    ///获取版本说明
289    ///get AudoiMoth for Device firmware description
290    /// msg_id=>0x08
291    pub    fn get_firmware_description(&self) -> AudioMothResult<String> {
292        let buffer = [0x00, USB_MSG_TYPE_GET_FIRMWARE_DESCRIPTION];
293        match self.write(&buffer) {
294            Ok(usize) => {
295                if usize != 0 {
296                    let mut buff: [u8; 64] = [0; 64];
297                    if let Ok(size) = self.device.read(&mut buff) {
298                        if size > 0 && buff[0] == USB_MSG_TYPE_GET_FIRMWARE_DESCRIPTION {
299                            return Ok(convert::convert_bytes_from_buffer_to_firmware_description(
300                                &buff, 1,
301                            ));
302                        } else {
303                            return Err(AudioMothError::OtherError(String::from(
304                                " Incorrect message type from AudioMoth device",
305                            )));
306                        }
307                    }
308                }
309            }
310            Err(e) => {
311                return Err(e);
312            }
313        }
314        return Err(AudioMothError::OtherError(String::from(
315            "get firmware description error",
316        )));
317    }
318
319    //查询设备bootloader模式
320    pub    fn query_bootloader_state(&self) -> AudioMothResult<bool> {
321        let buffer = [0x00, USB_MSG_TYPE_QUERY_BOOTLOADER];
322        let _ = self.write(&buffer).unwrap();
323        let mut buf = [0u8; 64];
324        let _ = self.device.read(&mut buf);
325        Ok(convert::convert_bytes_to_bootloader_state(&mut buf, 1))
326    }
327
328    //切换设备进入bootloader模式
329    pub    fn switch_to_bootloader(&self) -> AudioMothResult<usize> {
330        let buffer = [0x00, USB_MSG_TYPE_SWITCH_TO_BOOTLOADER];
331        match self.write(&buffer) {
332            Ok(_) => {
333                let mut buf = [0u8; 64];
334                match self.device.read(&mut buf[..]) {
335                    Ok(usize) => return Ok(usize),
336                    Err(e) => return Err(AudioMothError::HidError(e)),
337                }
338            }
339            Err(e) => return Err(e),
340        }
341    }
342}