Move relay drivers from common to controller
This commit is contained in:
		
							parent
							
								
									e9ea0b625d
								
							
						
					
					
						commit
						340c4e9f15
					
				
					 9 changed files with 193 additions and 33 deletions
				
			
		
							
								
								
									
										28
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue