1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use super::{instruction_id, packet_id};
use crate::{Bus, ReadError, TransferError, WriteError};
#[derive(Debug, Clone)]
pub struct PingResponse {
pub motor_id: u8,
pub model: u16,
pub firmware: u8,
}
impl<ReadBuffer, WriteBuffer> Bus<ReadBuffer, WriteBuffer>
where
ReadBuffer: AsRef<[u8]> + AsMut<[u8]>,
WriteBuffer: AsRef<[u8]> + AsMut<[u8]>,
{
pub fn ping(&mut self, motor_id: u8) -> Result<PingResponse, TransferError> {
let response = self.transfer_single(motor_id, instruction_id::PING, 0, |_| ())?;
Ok(parse_ping_response(response.packet_id(), response.parameters()))
}
pub fn scan(&mut self) -> Result<Vec<Result<PingResponse, ReadError>>, WriteError> {
let mut result = Vec::with_capacity(253);
self.scan_cb(|x| result.push(x))?;
Ok(result)
}
pub fn scan_cb<F>(&mut self, mut on_response: F) -> Result<(), WriteError>
where
F: FnMut(Result<PingResponse, ReadError>),
{
self.write_instruction(packet_id::BROADCAST, instruction_id::PING, 0, |_| ())?;
for _ in 0..253 {
let response = self.read_status_response();
if let Err(ReadError::Io(e)) = &response {
if e.kind() == std::io::ErrorKind::TimedOut {
continue;
}
}
let response = response.and_then(|response| {
crate::InvalidParameterCount::check(response.parameters().len(), 3)?;
Ok(parse_ping_response(response.packet_id(), response.parameters()))
});
on_response(response);
}
Ok(())
}
}
fn parse_ping_response(motor_id: u8, parameters: &[u8]) -> PingResponse {
PingResponse {
motor_id,
model: crate::endian::read_u16_le(¶meters[0..]),
firmware: crate::endian::read_u8_le(¶meters[2..]),
}
}