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#[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}