From 340c4e9f152b9d57ecfe02b41a36439383cb8728 Mon Sep 17 00:00:00 2001 From: Tobias Reisinger Date: Sun, 5 May 2024 23:46:38 +0200 Subject: [PATCH] Move relay drivers from common to controller --- Cargo.lock | Bin 68987 -> 68925 bytes src/app_state.rs | 2 +- src/drivers/gpio.rs | 31 ++++++++++++++++++ src/{driver.rs => drivers/mod.rs} | 17 ++++++++++ src/drivers/null.rs | 22 +++++++++++++ src/drivers/piface.rs | 48 ++++++++++++++++++++++++++++ src/errors.rs | 50 ++++++++++++++++++++++++++++++ src/main.rs | 11 +++---- src/settings.rs | 17 +++++----- 9 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 src/drivers/gpio.rs rename src/{driver.rs => drivers/mod.rs} (56%) create mode 100644 src/drivers/null.rs create mode 100644 src/drivers/piface.rs create mode 100644 src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 254f13e18a284a20f88f8640c3425bcf620199a7..bfbaa09f273add17e9ecb00f8720756ed68389e9 100644 GIT binary patch delta 518 zcmXw#J8Km{5QVuh;3I`;l2}Ag&{CM)o!yx!H20>o@%q3<5O!vEYc0f9^cTn$fmAm3 z!Ue4?#9v@17J^M`dmGonYG8`*JLmj4-Tr*K{o(fEB8}CJ`%5rXbWo33=OHW{464U~ zLM4E;pkxv>K#Vru#$ctZyC4;X@r@5QXNMnej{aqL^Yi%Cow0baUIvT;2`iug#VG*F zO*N`XW6EAKBumzdw3u>b!B8t@a!##h?c?pi{&@CsXIy^09xGlifr58~5{p2S88o4R z#z@H;#p=*|mE6GyvlO+M!L7R#h$S+H|G>@eo8!mh0j-xZ?TVy{C>TmL$`d2Cgc5sB z)lnIkl}fb&jhh9`SyQNirMG{?y>ZQV27SFU)=w^u?XA6W{`>V!`*C(_uKRrJ-Vrc0 ztI0yEoo&iwP7z7K9k`fhL6s0a0wzaqsNEe)(WI>_jn(`8liwE>cPH-GyY*2=EjBB6 tl;YeSCpIwW)MgW8nq^~lgEZHOhMX&L;ViY)l4M4D^zhTwON*!H{sMytnce^Z delta 506 zcmWkrv1%1S5aeMBH5N9$Sfmk2Dcs)f-tHF3!&s@!(?VE5rv{ zS=$O$3L0$0NDJr*-EnmH;i^Ngxwr@?BV)tfQs@|(E0|D8 zfXGst&b>}nObE4QXoyCxhsK~>3sFyYjxmX* z-Y7sx9t|s45FsipXX!b`5*ud*8MhxV$Nuq^&5vh?kH(i5>lG7NM-q(HT1l;u&!Aew zbZRJz73l%ZODX0#I!z0}LWTkj#!p#}KfXOae?1uYFW=nkefxcDET&VTN);_ZW9*sS za^$QDrF$$r_sGTtE9Qoz!kjd-_e3(^3#p8kJIgokE-vm(u?H(}P(a Result { + let gpio = Gpio::new()?.get(pin)?.into_output(); + Ok(Self { gpio, inverted }) + } +} + +impl RelayDriver for GpioDriver { + fn set(&mut self, value: bool) -> Result<(), EmgauwaControllerError> { + if self.get_high(value) { + self.gpio.set_high(); + } else { + self.gpio.set_low(); + } + Ok(()) + } + + fn get_inverted(&self) -> bool { + self.inverted + } +} diff --git a/src/driver.rs b/src/drivers/mod.rs similarity index 56% rename from src/driver.rs rename to src/drivers/mod.rs index 9df8d31..9c0c971 100644 --- a/src/driver.rs +++ b/src/drivers/mod.rs @@ -1,4 +1,21 @@ +pub use gpio::GpioDriver; +pub use null::NullDriver; +pub use piface::PiFaceDriver; use serde::{Deserialize, Deserializer}; +use crate::errors::EmgauwaControllerError; + +mod gpio; +mod null; +mod piface; + +pub trait RelayDriver { + fn get_high(&self, value: bool) -> bool { + value ^ self.get_inverted() + } + + fn set(&mut self, value: bool) -> Result<(), EmgauwaControllerError>; + fn get_inverted(&self) -> bool; +} #[derive(Debug, Clone, Copy)] pub enum Driver { diff --git a/src/drivers/null.rs b/src/drivers/null.rs new file mode 100644 index 0000000..1e8e2c2 --- /dev/null +++ b/src/drivers/null.rs @@ -0,0 +1,22 @@ +use crate::drivers::RelayDriver; +use crate::errors::EmgauwaControllerError; + +pub struct NullDriver { + pub pin: u8, +} + +impl NullDriver { + pub fn new(pin: u8) -> Self { + Self { pin } + } +} + +impl RelayDriver for NullDriver { + fn set(&mut self, _value: bool) -> Result<(), EmgauwaControllerError> { + Ok(()) + } + + fn get_inverted(&self) -> bool { + false + } +} diff --git a/src/drivers/piface.rs b/src/drivers/piface.rs new file mode 100644 index 0000000..4a0baf0 --- /dev/null +++ b/src/drivers/piface.rs @@ -0,0 +1,48 @@ +use rppal_pfd::{ + ChipSelect, HardwareAddress, OutputPin, PiFaceDigital, PiFaceDigitalError, SpiBus, SpiMode, +}; + +use crate::drivers::RelayDriver; +use crate::errors::EmgauwaControllerError; + +pub struct PiFaceDriver { + pub pfd_pin: OutputPin, +} + +impl PiFaceDriver { + pub fn new(pin: u8, pfd: &Option) -> Result { + let pfd = pfd.as_ref().ok_or(EmgauwaControllerError::Hardware(String::from( + "PiFaceDigital not initialized", + )))?; + let pfd_pin = pfd.get_output_pin(pin)?; + Ok(Self { pfd_pin }) + } + + pub fn init_piface() -> Result { + let mut pfd = PiFaceDigital::new( + HardwareAddress::new(0)?, + SpiBus::Spi0, + ChipSelect::Cs0, + 100_000, + SpiMode::Mode0, + )?; + pfd.init()?; + + Ok(pfd) + } +} + +impl RelayDriver for PiFaceDriver { + fn set(&mut self, value: bool) -> Result<(), EmgauwaControllerError> { + if self.get_high(value) { + self.pfd_pin.set_high().map_err(PiFaceDigitalError::from)?; + } else { + self.pfd_pin.set_low().map_err(PiFaceDigitalError::from)?; + } + Ok(()) + } + + fn get_inverted(&self) -> bool { + false + } +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..3916180 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,50 @@ +use std::fmt::{Display, Formatter}; +use rppal::gpio; +use rppal_mcp23s17::Mcp23s17Error; +use rppal_pfd::PiFaceDigitalError; + +use emgauwa_common::errors::EmgauwaError; + +#[derive(Debug)] +pub enum EmgauwaControllerError { + Hardware(String), +} + +impl Display for EmgauwaControllerError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", EmgauwaError::from(self)) + } +} + +impl From for EmgauwaControllerError { + fn from(value: gpio::Error) -> Self { + Self::Hardware(value.to_string()) + } +} + +impl From for EmgauwaControllerError { + fn from(value: PiFaceDigitalError) -> Self { + match value { + PiFaceDigitalError::Mcp23s17Error { source } => match source { + Mcp23s17Error::SpiError { source } => Self::Hardware(source.to_string()), + _ => Self::Hardware(source.to_string()), + }, + PiFaceDigitalError::GpioError { source } => Self::Hardware(source.to_string()), + _ => Self::Hardware(value.to_string()), + } + } +} + +impl From<&EmgauwaControllerError> for EmgauwaError { + fn from(value: &EmgauwaControllerError) -> Self { + match value { + EmgauwaControllerError::Hardware(value) => EmgauwaError::Hardware(value.to_string()), + } + } +} + +impl From for EmgauwaError { + fn from(value: EmgauwaControllerError) -> Self { + EmgauwaError::from(&value) + } +} diff --git a/src/main.rs b/src/main.rs index 1ba2d42..b49a92b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,11 +14,12 @@ use crate::settings::Settings; use crate::ws::run_ws_loop; mod app_state; -mod driver; +mod drivers; mod relay_loop; mod settings; mod utils; mod ws; +mod errors; async fn create_this_controller( conn: &mut PoolConnection, @@ -42,9 +43,7 @@ async fn create_this_relay( let relay = DbRelay::create( conn, &settings_relay.name, - settings_relay.number.ok_or(EmgauwaError::Internal( - "Relay number is missing".to_string(), - ))?, + settings_relay.number, this_controller, ) .await?; @@ -87,9 +86,7 @@ async fn main() -> Result<(), std::io::Error> { if DbRelay::get_by_controller_and_num( &mut conn, &db_controller, - relay.number.ok_or(EmgauwaError::Internal( - "Relay number is missing".to_string(), - ))?, + relay.number, ) .await .map_err(EmgauwaError::from)? diff --git a/src/settings.rs b/src/settings.rs index fa414f2..445f531 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,15 +1,14 @@ use emgauwa_common::errors::EmgauwaError; -use emgauwa_common::{drivers, settings}; +use emgauwa_common::settings; use rppal_pfd::PiFaceDigital; use serde_derive::Deserialize; - -use crate::driver::Driver; +use crate::drivers; #[derive(Clone, Debug, Deserialize)] #[serde(default)] #[allow(unused)] pub struct Relay { - pub driver: Driver, + pub driver: drivers::Driver, pub name: String, pub number: i64, pub pin: u8, @@ -47,8 +46,8 @@ impl Default for Settings { impl Default for Relay { fn default() -> Self { Relay { - driver: Driver::Gpio, - number: None, + driver: drivers::Driver::Gpio, + number: 0, name: String::from("Relay"), pin: 0, inverted: false, @@ -84,9 +83,9 @@ impl Relay { pfd: &mut Option, ) -> Result, EmgauwaError> { let driver: Box = match self.driver { - Driver::Null => Box::new(drivers::NullDriver::new(self.pin)), - Driver::Gpio => Box::new(drivers::GpioDriver::new(self.pin, self.inverted)?), - Driver::PiFace => { + drivers::Driver::Null => Box::new(drivers::NullDriver::new(self.pin)), + drivers::Driver::Gpio => Box::new(drivers::GpioDriver::new(self.pin, self.inverted)?), + drivers::Driver::PiFace => { if pfd.is_none() { *pfd = Some(drivers::PiFaceDriver::init_piface()?); }