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

View file

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

View file

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