ev3robot/ev3/sensors/
ultrasonic_sensor.rs1use std::str::FromStr;
2
3use crate::device::{ReadOnlyAttributeFile, ReadWriteAttributeFile};
4
5#[derive(Debug, Device, FindableDevice)]
6#[findable_device(class = "lego-sensor", driver = "lego-ev3-us")]
7pub struct UltrasonicSensor {
8 mode: ReadWriteAttributeFile,
9 #[device(attr_name = "value0")]
10 value: ReadOnlyAttributeFile,
11}
12
13impl UltrasonicSensor {
14 pub fn measure_cm(&mut self) -> anyhow::Result<CmMeter> {
15 self.mode.set_value("US-DIST-CM")?;
16 Ok(CmMeter { ultrasonic_sensor: self })
17 }
18
19 pub fn measure_inches(&mut self) -> anyhow::Result<InchMeter> {
20 self.mode.set_value("US-DIST-IN")?;
21 Ok(InchMeter { ultrasonic_sensor: self })
22 }
23
24 pub fn listen(&mut self) -> anyhow::Result<UltrasoundListener> {
25 self.mode.set_value("US-LISTEN")?;
26 Ok(UltrasoundListener { ultrasonic_sensor: self })
27 }
28
29 fn value<T: FromStr>(&mut self) -> anyhow::Result<T>
30 where
31 T::Err: Into<Box<dyn std::error::Error + Send + Sync>>,
32 {
33 self.value.value().map_err(Into::into)
34 }
35}
36
37macro_rules! ultrasonic_sensor_mode {
38 ($name:ident) => {
39 #[derive(Debug)]
40 pub struct $name<'a> {
41 ultrasonic_sensor: &'a mut UltrasonicSensor,
42 }
43 };
44}
45
46ultrasonic_sensor_mode!(CmMeter);
47ultrasonic_sensor_mode!(InchMeter);
48ultrasonic_sensor_mode!(UltrasoundListener);
49
50impl CmMeter<'_> {
51 pub fn cm(&mut self) -> anyhow::Result<f32> {
52 self.ultrasonic_sensor.value().map(div_by_10)
53 }
54}
55
56impl InchMeter<'_> {
57 pub fn inches(&mut self) -> anyhow::Result<f32> {
58 self.ultrasonic_sensor.value().map(div_by_10)
59 }
60}
61
62fn div_by_10(n: u32) -> f32 {
63 n as f32 / 10_f32
64}
65
66impl UltrasoundListener<'_> {
67 pub fn is_ultrasound_present(&mut self) -> anyhow::Result<bool> {
68 self.ultrasonic_sensor.value().map(|present: char| present == '1')
69 }
70}