raspberry_web/
rpi.rs

1use crate::errors::RpWebError;
2use crate::utilities::i32_to_u8;
3use parking_lot::Mutex;
4#[cfg(target_arch = "arm")]
5use rppal::gpio::Gpio;
6use std::sync::Arc;
7
8#[cfg(not(target_arch = "arm"))]
9pub type GpioArcMutex = Arc<Mutex<i32>>;
10
11#[cfg(target_arch = "arm")]
12pub type GpioArcMutex = Arc<Mutex<Gpio>>;
13
14#[cfg(not(target_arch = "arm"))]
15pub fn create_gpio_arc_mutex() -> Result<GpioArcMutex, String> {
16    Ok(Arc::new(Mutex::new(0)))
17}
18
19#[cfg(target_arch = "arm")]
20pub fn create_gpio_arc_mutex() -> Result<GpioArcMutex, RpWebError> {
21    let gpio = Gpio::new()?;
22    Ok(Arc::new(Mutex::new(gpio)))
23}
24
25#[cfg(not(target_arch = "arm"))]
26pub fn set_gpio_level_rpi(
27    gpio_id: i32, level: &str, gpio_arc_mutex: GpioArcMutex,
28) -> Result<(), RpWebError> {
29    let _gpio_id_u8 = i32_to_u8(gpio_id)?;
30    let mut data = gpio_arc_mutex.lock();
31    match level {
32        "high" => *data += 1,
33        "low" => *data += 1,
34        _ => {
35            let errs = format!("Invalid level: '{}'", level);
36            return Err(RpWebError::new(&errs));
37        }
38    }
39    Ok(())
40}
41
42#[cfg(not(target_arch = "arm"))]
43pub fn reset_gpio_output_pin_rpi(
44    _gpio_id: i32, _gpio_arc_mutex: GpioArcMutex
45) -> Result<(), RpWebError> {
46    Ok(())
47}
48
49#[cfg(target_arch = "arm")]
50pub fn reset_gpio_output_pin_rpi(
51    gpio_id: i32, gpio_arc_mutex: GpioArcMutex
52) -> Result<(), RpWebError> {
53
54    let data = gpio_arc_mutex.lock();
55    let gpio_id_u8 = i32_to_u8(gpio_id)?;
56    let mut output_pin = (*data).get(gpio_id_u8)?.into_output();
57    output_pin.set_reset_on_drop(true);
58
59    Ok(())
60}
61
62#[cfg(not(target_arch = "arm"))]
63pub fn set_reset_on_drop_false_for_output_pin_rpi(
64    _gpio_id: i32, _gpio_arc_mutex: GpioArcMutex
65) -> Result<(), RpWebError> {
66    Ok(())
67}
68
69#[cfg(target_arch = "arm")]
70pub fn set_reset_on_drop_false_for_output_pin_rpi(
71    gpio_id: i32, gpio_arc_mutex: GpioArcMutex
72) -> Result<(), RpWebError> {
73
74    let data = gpio_arc_mutex.lock();
75    let gpio_id_u8 = i32_to_u8(gpio_id)?;
76    let mut output_pin = (*data).get(gpio_id_u8)?.into_output();
77    output_pin.set_reset_on_drop(false);
78
79    Ok(())
80}
81
82//#[allow(unused_mut)] // output_pin needs mut but generates a warning
83#[cfg(target_arch = "arm")]
84pub fn set_gpio_level_rpi(
85    gpio_id: i32, level: &str, gpio_arc_mutex: GpioArcMutex,
86) -> Result<(), RpWebError> {
87    let gpio_id_u8 = i32_to_u8(gpio_id)?;
88    let data = gpio_arc_mutex.lock();
89
90    let mut output_pin = (*data).get(gpio_id_u8)?.into_output();
91
92    match level {
93        "high" => {
94            info!("Set gpio #{} to 'high'", gpio_id_u8);
95            output_pin.set_high()
96        }
97        "low" => {
98            info!("Set gpio #{} to 'low'", gpio_id_u8);
99            output_pin.set_low()
100        }
101        _ => {
102            let errs = format!("Invalid level: '{}'", level);
103            return Err(RpWebError::new(&errs));
104        }
105    }
106
107    Ok(())
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn set_gpio_level_rpi_high_must_succeed() {
116        let gpio_arc_mutex = create_gpio_arc_mutex().expect("Could not acquire GPIO");
117        let res = set_gpio_level_rpi(1, "high", gpio_arc_mutex);
118
119        assert!(res.is_ok());
120    }
121
122    #[test]
123    fn set_gpio_level_rpi_low_must_succeed() {
124        let gpio_arc_mutex = create_gpio_arc_mutex().expect("Could not acquire GPIO");
125        let res = set_gpio_level_rpi(1, "low", gpio_arc_mutex);
126
127        assert!(res.is_ok());
128    }
129
130    #[test]
131    fn set_gpio_level_rpi_unknown_must_fail() {
132        let gpio_arc_mutex = create_gpio_arc_mutex().expect("Could not acquire GPIO");
133        let res = set_gpio_level_rpi(1, "unknown_level", gpio_arc_mutex);
134
135        assert!(res.is_err());
136    }
137}