Move relay drivers from common to controller

This commit is contained in:
Tobias Reisinger 2024-05-05 23:46:38 +02:00
parent e9ea0b625d
commit 340c4e9f15
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
9 changed files with 193 additions and 33 deletions

28
Cargo.lock generated
View file

@ -330,9 +330,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
@ -714,9 +714,6 @@ dependencies = [
"libc", "libc",
"libsqlite3-sys", "libsqlite3-sys",
"log", "log",
"rppal 0.17.1",
"rppal-mcp23s17",
"rppal-pfd",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
@ -1353,9 +1350,9 @@ dependencies = [
[[package]] [[package]]
name = "num-iter" name = "num-iter"
version = "0.1.44" version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
@ -1364,9 +1361,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm", "libm",
@ -2329,16 +2326,15 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.10" version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
"tracing",
] ]
[[package]] [[package]]
@ -2760,18 +2756,18 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.32" version = "0.7.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.7.32" version = "0.7.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -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
View 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
}
}

View file

@ -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
View 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
View 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
View 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)
}
}

View file

@ -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)?

View file

@ -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()?);
} }