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 actix::{Actor, Context, Handler, Message};
|
||||||
use emgauwa_common::constants;
|
use emgauwa_common::constants;
|
||||||
use emgauwa_common::drivers::RelayDriver;
|
|
||||||
use emgauwa_common::errors::EmgauwaError;
|
use emgauwa_common::errors::EmgauwaError;
|
||||||
use emgauwa_common::models::Controller;
|
use emgauwa_common::models::Controller;
|
||||||
use emgauwa_common::types::RelayStates;
|
use emgauwa_common::types::RelayStates;
|
||||||
|
@ -11,6 +10,7 @@ use futures::executor::block_on;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
use tokio::sync::Notify;
|
use tokio::sync::Notify;
|
||||||
|
|
||||||
|
use crate::drivers::RelayDriver;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[derive(Message)]
|
#[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 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)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Driver {
|
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;
|
use crate::ws::run_ws_loop;
|
||||||
|
|
||||||
mod app_state;
|
mod app_state;
|
||||||
mod driver;
|
mod drivers;
|
||||||
mod relay_loop;
|
mod relay_loop;
|
||||||
mod settings;
|
mod settings;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod ws;
|
mod ws;
|
||||||
|
mod errors;
|
||||||
|
|
||||||
async fn create_this_controller(
|
async fn create_this_controller(
|
||||||
conn: &mut PoolConnection<Sqlite>,
|
conn: &mut PoolConnection<Sqlite>,
|
||||||
|
@ -42,9 +43,7 @@ async fn create_this_relay(
|
||||||
let relay = DbRelay::create(
|
let relay = DbRelay::create(
|
||||||
conn,
|
conn,
|
||||||
&settings_relay.name,
|
&settings_relay.name,
|
||||||
settings_relay.number.ok_or(EmgauwaError::Internal(
|
settings_relay.number,
|
||||||
"Relay number is missing".to_string(),
|
|
||||||
))?,
|
|
||||||
this_controller,
|
this_controller,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -87,9 +86,7 @@ async fn main() -> Result<(), std::io::Error> {
|
||||||
if DbRelay::get_by_controller_and_num(
|
if DbRelay::get_by_controller_and_num(
|
||||||
&mut conn,
|
&mut conn,
|
||||||
&db_controller,
|
&db_controller,
|
||||||
relay.number.ok_or(EmgauwaError::Internal(
|
relay.number,
|
||||||
"Relay number is missing".to_string(),
|
|
||||||
))?,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(EmgauwaError::from)?
|
.map_err(EmgauwaError::from)?
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
use emgauwa_common::errors::EmgauwaError;
|
use emgauwa_common::errors::EmgauwaError;
|
||||||
use emgauwa_common::{drivers, settings};
|
use emgauwa_common::settings;
|
||||||
use rppal_pfd::PiFaceDigital;
|
use rppal_pfd::PiFaceDigital;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
|
use crate::drivers;
|
||||||
use crate::driver::Driver;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub struct Relay {
|
pub struct Relay {
|
||||||
pub driver: Driver,
|
pub driver: drivers::Driver,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub number: i64,
|
pub number: i64,
|
||||||
pub pin: u8,
|
pub pin: u8,
|
||||||
|
@ -47,8 +46,8 @@ impl Default for Settings {
|
||||||
impl Default for Relay {
|
impl Default for Relay {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Relay {
|
Relay {
|
||||||
driver: Driver::Gpio,
|
driver: drivers::Driver::Gpio,
|
||||||
number: None,
|
number: 0,
|
||||||
name: String::from("Relay"),
|
name: String::from("Relay"),
|
||||||
pin: 0,
|
pin: 0,
|
||||||
inverted: false,
|
inverted: false,
|
||||||
|
@ -84,9 +83,9 @@ impl Relay {
|
||||||
pfd: &mut Option<PiFaceDigital>,
|
pfd: &mut Option<PiFaceDigital>,
|
||||||
) -> Result<Box<dyn drivers::RelayDriver>, EmgauwaError> {
|
) -> Result<Box<dyn drivers::RelayDriver>, EmgauwaError> {
|
||||||
let driver: Box<dyn drivers::RelayDriver> = match self.driver {
|
let driver: Box<dyn drivers::RelayDriver> = match self.driver {
|
||||||
Driver::Null => Box::new(drivers::NullDriver::new(self.pin)),
|
drivers::Driver::Null => Box::new(drivers::NullDriver::new(self.pin)),
|
||||||
Driver::Gpio => Box::new(drivers::GpioDriver::new(self.pin, self.inverted)?),
|
drivers::Driver::Gpio => Box::new(drivers::GpioDriver::new(self.pin, self.inverted)?),
|
||||||
Driver::PiFace => {
|
drivers::Driver::PiFace => {
|
||||||
if pfd.is_none() {
|
if pfd.is_none() {
|
||||||
*pfd = Some(drivers::PiFaceDriver::init_piface()?);
|
*pfd = Some(drivers::PiFaceDriver::init_piface()?);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue