Move relay drivers from common to controller
This commit is contained in:
parent
e9ea0b625d
commit
340c4e9f15
9 changed files with 181 additions and 17 deletions
BIN
Cargo.lock
generated
BIN
Cargo.lock
generated
Binary file not shown.
|
@ -3,7 +3,6 @@ use std::time::{Duration, Instant};
|
|||
|
||||
use actix::{Actor, Context, Handler, Message};
|
||||
use emgauwa_common::constants;
|
||||
use emgauwa_common::drivers::RelayDriver;
|
||||
use emgauwa_common::errors::EmgauwaError;
|
||||
use emgauwa_common::models::Controller;
|
||||
use emgauwa_common::types::RelayStates;
|
||||
|
@ -11,6 +10,7 @@ use futures::executor::block_on;
|
|||
use sqlx::{Pool, Sqlite};
|
||||
use tokio::sync::Notify;
|
||||
|
||||
use crate::drivers::RelayDriver;
|
||||
use crate::settings::Settings;
|
||||
|
||||
#[derive(Message)]
|
||||
|
|
31
src/drivers/gpio.rs
Normal file
31
src/drivers/gpio.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use rppal::gpio::{Gpio, OutputPin};
|
||||
|
||||
use crate::drivers::RelayDriver;
|
||||
use crate::errors::EmgauwaControllerError;
|
||||
|
||||
pub struct GpioDriver {
|
||||
pub gpio: OutputPin,
|
||||
pub inverted: bool,
|
||||
}
|
||||
|
||||
impl GpioDriver {
|
||||
pub fn new(pin: u8, inverted: bool) -> Result<Self, EmgauwaControllerError> {
|
||||
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
|
||||
}
|
||||
}
|
|
@ -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 {
|
22
src/drivers/null.rs
Normal file
22
src/drivers/null.rs
Normal file
|
@ -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
|
||||
}
|
||||
}
|
48
src/drivers/piface.rs
Normal file
48
src/drivers/piface.rs
Normal file
|
@ -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<PiFaceDigital>) -> Result<Self, EmgauwaControllerError> {
|
||||
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<PiFaceDigital, EmgauwaControllerError> {
|
||||
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
|
||||
}
|
||||
}
|
50
src/errors.rs
Normal file
50
src/errors.rs
Normal file
|
@ -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<gpio::Error> for EmgauwaControllerError {
|
||||
fn from(value: gpio::Error) -> Self {
|
||||
Self::Hardware(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PiFaceDigitalError> 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<EmgauwaControllerError> for EmgauwaError {
|
||||
fn from(value: EmgauwaControllerError) -> Self {
|
||||
EmgauwaError::from(&value)
|
||||
}
|
||||
}
|
11
src/main.rs
11
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<Sqlite>,
|
||||
|
@ -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)?
|
||||
|
|
|
@ -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<PiFaceDigital>,
|
||||
) -> Result<Box<dyn drivers::RelayDriver>, EmgauwaError> {
|
||||
let driver: Box<dyn drivers::RelayDriver> = 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()?);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue