Add drivers for gpio and piface
This commit is contained in:
		
							parent
							
								
									61a3c6093b
								
							
						
					
					
						commit
						4ed1cd3182
					
				
					 14 changed files with 259 additions and 17 deletions
				
			
		
							
								
								
									
										48
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										48
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -709,6 +709,9 @@ dependencies = [
 | 
				
			||||||
 "futures",
 | 
					 "futures",
 | 
				
			||||||
 "futures-channel",
 | 
					 "futures-channel",
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 | 
					 "rppal 0.17.1",
 | 
				
			||||||
 | 
					 "rppal-mcp23s17",
 | 
				
			||||||
 | 
					 "rppal-pfd",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_derive",
 | 
					 "serde_derive",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
| 
						 | 
					@ -755,6 +758,9 @@ 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",
 | 
				
			||||||
| 
						 | 
					@ -1738,6 +1744,48 @@ dependencies = [
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rppal"
 | 
				
			||||||
 | 
					version = "0.14.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "612e1a22e21f08a246657c6433fe52b773ae43d07c9ef88ccfc433cc8683caba"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "libc",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rppal"
 | 
				
			||||||
 | 
					version = "0.17.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "1dc171bbe325b04172e18d917c58c2cf1fb5adfd9ffabb1d6b3d62ba4c1c1331"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "libc",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rppal-mcp23s17"
 | 
				
			||||||
 | 
					version = "0.0.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "66119979a7ae3d743517c63b26e039080bd8d3b9c782bad5103c06877293b1cf"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "bitflags 1.3.2",
 | 
				
			||||||
 | 
					 "log",
 | 
				
			||||||
 | 
					 "rppal 0.14.1",
 | 
				
			||||||
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rppal-pfd"
 | 
				
			||||||
 | 
					version = "0.0.5"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "1804948e00d57085912f87c724be9aa4fdb6c00aa54ef8cf1eae40dd76053088"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "log",
 | 
				
			||||||
 | 
					 "rppal 0.14.1",
 | 
				
			||||||
 | 
					 "rppal-mcp23s17",
 | 
				
			||||||
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rsa"
 | 
					name = "rsa"
 | 
				
			||||||
version = "0.9.3"
 | 
					version = "0.9.3"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										5
									
								
								Cross.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Cross.toml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					[build]
 | 
				
			||||||
 | 
					pre-build = [
 | 
				
			||||||
 | 
					    "curl -Lo /usr/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64",
 | 
				
			||||||
 | 
					    "chmod +x /usr/bin/yq"
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
| 
						 | 
					@ -8,8 +8,8 @@ server {
 | 
				
			||||||
database = "sqlite://emgauwa-controller.sqlite"
 | 
					database = "sqlite://emgauwa-controller.sqlite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions {
 | 
					permissions {
 | 
				
			||||||
  user = read("env:USER")
 | 
					  user = "" // read("env:USER")
 | 
				
			||||||
  group = read("env:USER")
 | 
					  group = "" // read("env:USER")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logging {
 | 
					logging {
 | 
				
			||||||
| 
						 | 
					@ -20,37 +20,32 @@ logging {
 | 
				
			||||||
relays {
 | 
					relays {
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
    driver = "gpio"
 | 
					    driver = "gpio"
 | 
				
			||||||
    pin = 5
 | 
					    pin = 24
 | 
				
			||||||
    inverted = true
 | 
					    inverted = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
    driver = "gpio"
 | 
					    driver = "gpio"
 | 
				
			||||||
    pin = 4
 | 
					    pin = 23
 | 
				
			||||||
    inverted = true
 | 
					    inverted = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
    driver = "gpio"
 | 
					    driver = "gpio"
 | 
				
			||||||
    pin = 3
 | 
					    pin = 22
 | 
				
			||||||
    inverted = true
 | 
					    inverted = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
    driver = "gpio"
 | 
					    driver = "gpio"
 | 
				
			||||||
    pin = 2
 | 
					    pin = 27
 | 
				
			||||||
    inverted = true
 | 
					    inverted = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
    driver = "gpio"
 | 
					    driver = "gpio"
 | 
				
			||||||
    pin = 1
 | 
					    pin = 18
 | 
				
			||||||
    inverted = true
 | 
					    inverted = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
    driver = "gpio"
 | 
					    driver = "gpio"
 | 
				
			||||||
    pin = 0
 | 
					    pin = 17
 | 
				
			||||||
    inverted = true
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  new {
 | 
					 | 
				
			||||||
    driver = "gpio"
 | 
					 | 
				
			||||||
    pin = 16
 | 
					 | 
				
			||||||
    inverted = true
 | 
					    inverted = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
| 
						 | 
					@ -58,6 +53,11 @@ relays {
 | 
				
			||||||
    pin = 15
 | 
					    pin = 15
 | 
				
			||||||
    inverted = true
 | 
					    inverted = true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  new {
 | 
				
			||||||
 | 
					    driver = "gpio"
 | 
				
			||||||
 | 
					    pin = 14
 | 
				
			||||||
 | 
					    inverted = true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  new {
 | 
					  new {
 | 
				
			||||||
    driver = "piface"
 | 
					    driver = "piface"
 | 
				
			||||||
    pin = 1
 | 
					    pin = 1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,8 +8,8 @@ server {
 | 
				
			||||||
database = "sqlite://emgauwa-core.sqlite"
 | 
					database = "sqlite://emgauwa-core.sqlite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions {
 | 
					permissions {
 | 
				
			||||||
  user = read("env:USER")
 | 
					  user = "" // read("env:USER")
 | 
				
			||||||
  group = read("env:USER")
 | 
					  group = "" // read("env:USER")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logging {
 | 
					logging {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,3 +26,7 @@ sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio", "macros", "chro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
futures = "0.3"
 | 
					futures = "0.3"
 | 
				
			||||||
futures-channel = "0.3"
 | 
					futures-channel = "0.3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rppal = "0.17"
 | 
				
			||||||
 | 
					rppal-pfd = "0.0.5"
 | 
				
			||||||
 | 
					rppal-mcp23s17 = "0.0.3"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ use std::time::{Duration, Instant};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use actix::{Actor, Context, Handler, Message};
 | 
					use actix::{Actor, Context, Handler, Message};
 | 
				
			||||||
use emgauwa_lib::constants;
 | 
					use emgauwa_lib::constants;
 | 
				
			||||||
 | 
					use emgauwa_lib::drivers::RelayDriver;
 | 
				
			||||||
use emgauwa_lib::errors::EmgauwaError;
 | 
					use emgauwa_lib::errors::EmgauwaError;
 | 
				
			||||||
use emgauwa_lib::models::Controller;
 | 
					use emgauwa_lib::models::Controller;
 | 
				
			||||||
use emgauwa_lib::types::RelayStates;
 | 
					use emgauwa_lib::types::RelayStates;
 | 
				
			||||||
| 
						 | 
					@ -45,16 +46,23 @@ pub struct AppState {
 | 
				
			||||||
	pub pool: Pool<Sqlite>,
 | 
						pub pool: Pool<Sqlite>,
 | 
				
			||||||
	pub this: Controller,
 | 
						pub this: Controller,
 | 
				
			||||||
	pub settings: Settings,
 | 
						pub settings: Settings,
 | 
				
			||||||
 | 
						pub drivers: Vec<Box<dyn RelayDriver>>,
 | 
				
			||||||
	pub controller_notifier: Arc<Notify>,
 | 
						pub controller_notifier: Arc<Notify>,
 | 
				
			||||||
	pub relay_notifier: Arc<Notify>,
 | 
						pub relay_notifier: Arc<Notify>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl AppState {
 | 
					impl AppState {
 | 
				
			||||||
	pub fn new(pool: Pool<Sqlite>, this: Controller, settings: Settings) -> AppState {
 | 
						pub fn new(
 | 
				
			||||||
 | 
							pool: Pool<Sqlite>,
 | 
				
			||||||
 | 
							this: Controller,
 | 
				
			||||||
 | 
							settings: Settings,
 | 
				
			||||||
 | 
							drivers: Vec<Box<dyn RelayDriver>>,
 | 
				
			||||||
 | 
						) -> AppState {
 | 
				
			||||||
		AppState {
 | 
							AppState {
 | 
				
			||||||
			pool,
 | 
								pool,
 | 
				
			||||||
			this,
 | 
								this,
 | 
				
			||||||
			settings,
 | 
								settings,
 | 
				
			||||||
 | 
								drivers,
 | 
				
			||||||
			controller_notifier: Arc::new(Notify::new()),
 | 
								controller_notifier: Arc::new(Notify::new()),
 | 
				
			||||||
			relay_notifier: Arc::new(Notify::new()),
 | 
								relay_notifier: Arc::new(Notify::new()),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -93,6 +101,14 @@ impl Handler<UpdateRelayStates> for AppState {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn handle(&mut self, msg: UpdateRelayStates, _ctx: &mut Self::Context) -> Self::Result {
 | 
						fn handle(&mut self, msg: UpdateRelayStates, _ctx: &mut Self::Context) -> Self::Result {
 | 
				
			||||||
		self.this.apply_relay_states(&msg.relay_states);
 | 
							self.this.apply_relay_states(&msg.relay_states);
 | 
				
			||||||
 | 
							self.drivers
 | 
				
			||||||
 | 
								.iter_mut()
 | 
				
			||||||
 | 
								.zip(msg.relay_states.iter())
 | 
				
			||||||
 | 
								.for_each(|(driver, state)| {
 | 
				
			||||||
 | 
									if let Err(e) = driver.set(state.unwrap_or(false)) {
 | 
				
			||||||
 | 
										log::error!("Error setting relay: {}", e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		self.notify_relay_change();
 | 
							self.notify_relay_change();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ use emgauwa_lib::errors::EmgauwaError;
 | 
				
			||||||
use emgauwa_lib::models::{Controller, FromDbModel};
 | 
					use emgauwa_lib::models::{Controller, FromDbModel};
 | 
				
			||||||
use emgauwa_lib::types::ControllerUid;
 | 
					use emgauwa_lib::types::ControllerUid;
 | 
				
			||||||
use emgauwa_lib::utils::{drop_privileges, init_logging};
 | 
					use emgauwa_lib::utils::{drop_privileges, init_logging};
 | 
				
			||||||
 | 
					use rppal_pfd::PiFaceDigital;
 | 
				
			||||||
use sqlx::pool::PoolConnection;
 | 
					use sqlx::pool::PoolConnection;
 | 
				
			||||||
use sqlx::Sqlite;
 | 
					use sqlx::Sqlite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +65,9 @@ async fn main() -> Result<(), std::io::Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_logging(&settings.logging.level)?;
 | 
						init_logging(&settings.logging.level)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let mut pfd: Option<PiFaceDigital> = None;
 | 
				
			||||||
 | 
						let drivers = settings.relays_make_drivers(&mut pfd)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let pool = db::init(&settings.database)
 | 
						let pool = db::init(&settings.database)
 | 
				
			||||||
		.await
 | 
							.await
 | 
				
			||||||
		.map_err(EmgauwaError::from)?;
 | 
							.map_err(EmgauwaError::from)?;
 | 
				
			||||||
| 
						 | 
					@ -109,7 +113,7 @@ async fn main() -> Result<(), std::io::Error> {
 | 
				
			||||||
		settings.server.host, settings.server.port
 | 
							settings.server.host, settings.server.port
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let app_state = app_state::AppState::new(pool.clone(), this, settings).start();
 | 
						let app_state = app_state::AppState::new(pool.clone(), this, settings, drivers).start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let _ = tokio::join!(
 | 
						let _ = tokio::join!(
 | 
				
			||||||
		tokio::spawn(run_relays_loop(app_state.clone())),
 | 
							tokio::spawn(run_relays_loop(app_state.clone())),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
 | 
					use emgauwa_lib::drivers::{GpioDriver, PifaceDriver, RelayDriver};
 | 
				
			||||||
use emgauwa_lib::errors::EmgauwaError;
 | 
					use emgauwa_lib::errors::EmgauwaError;
 | 
				
			||||||
use emgauwa_lib::settings;
 | 
					use emgauwa_lib::settings;
 | 
				
			||||||
 | 
					use rppal_pfd::PiFaceDigital;
 | 
				
			||||||
use serde_derive::Deserialize;
 | 
					use serde_derive::Deserialize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::driver::Driver;
 | 
					use crate::driver::Driver;
 | 
				
			||||||
| 
						 | 
					@ -72,4 +74,33 @@ impl Settings {
 | 
				
			||||||
	pub fn get_relay(&self, number: i64) -> Option<&Relay> {
 | 
						pub fn get_relay(&self, number: i64) -> Option<&Relay> {
 | 
				
			||||||
		self.relays.iter().find(|r| r.number == Some(number))
 | 
							self.relays.iter().find(|r| r.number == Some(number))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pub fn relays_make_drivers(
 | 
				
			||||||
 | 
							&self,
 | 
				
			||||||
 | 
							pfd: &mut Option<PiFaceDigital>,
 | 
				
			||||||
 | 
						) -> Result<Vec<Box<dyn RelayDriver>>, EmgauwaError> {
 | 
				
			||||||
 | 
							let mut drivers = Vec::new();
 | 
				
			||||||
 | 
							for relay in &self.relays {
 | 
				
			||||||
 | 
								drivers.push(relay.make_driver(pfd)?);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							Ok(drivers)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Relay {
 | 
				
			||||||
 | 
						pub fn make_driver(
 | 
				
			||||||
 | 
							&self,
 | 
				
			||||||
 | 
							pfd: &mut Option<PiFaceDigital>,
 | 
				
			||||||
 | 
						) -> Result<Box<dyn RelayDriver>, EmgauwaError> {
 | 
				
			||||||
 | 
							let driver: Box<dyn RelayDriver> = match self.driver {
 | 
				
			||||||
 | 
								Driver::Gpio => Box::new(GpioDriver::new(self.pin, self.inverted)?),
 | 
				
			||||||
 | 
								Driver::Piface => {
 | 
				
			||||||
 | 
									if pfd.is_none() {
 | 
				
			||||||
 | 
										*pfd = Some(PifaceDriver::init_piface()?);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									Box::new(PifaceDriver::new(self.pin, pfd)?)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							Ok(driver)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,3 +26,7 @@ libsqlite3-sys = { version = "*", features = ["bundled"] }
 | 
				
			||||||
uuid = "1.6"
 | 
					uuid = "1.6"
 | 
				
			||||||
futures = "0.3"
 | 
					futures = "0.3"
 | 
				
			||||||
libc = "0.2"
 | 
					libc = "0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rppal = "0.17"
 | 
				
			||||||
 | 
					rppal-pfd = "0.0.5"
 | 
				
			||||||
 | 
					rppal-mcp23s17 = "0.0.3"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										35
									
								
								emgauwa-lib/src/drivers/gpio.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								emgauwa-lib/src/drivers/gpio.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,35 @@
 | 
				
			||||||
 | 
					use rppal::gpio::{Gpio, OutputPin};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::drivers::RelayDriver;
 | 
				
			||||||
 | 
					use crate::errors::EmgauwaError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct GpioDriver {
 | 
				
			||||||
 | 
						pub gpio: OutputPin,
 | 
				
			||||||
 | 
						pub inverted: bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl GpioDriver {
 | 
				
			||||||
 | 
						pub fn new(pin: u8, inverted: bool) -> Result<Self, EmgauwaError> {
 | 
				
			||||||
 | 
							let gpio = Gpio::new()?.get(pin)?.into_output();
 | 
				
			||||||
 | 
							Ok(Self { gpio, inverted })
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl RelayDriver for GpioDriver {
 | 
				
			||||||
 | 
						fn set(&mut self, value: bool) -> Result<(), EmgauwaError> {
 | 
				
			||||||
 | 
							if self.get_high(value) {
 | 
				
			||||||
 | 
								self.gpio.set_high();
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								self.gpio.set_low();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							Ok(())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn get_pin(&self) -> u8 {
 | 
				
			||||||
 | 
							self.gpio.pin()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn get_inverted(&self) -> bool {
 | 
				
			||||||
 | 
							self.inverted
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								emgauwa-lib/src/drivers/mod.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								emgauwa-lib/src/drivers/mod.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					mod gpio;
 | 
				
			||||||
 | 
					mod piface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub use gpio::GpioDriver;
 | 
				
			||||||
 | 
					pub use piface::PifaceDriver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::errors::EmgauwaError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait RelayDriver {
 | 
				
			||||||
 | 
						fn get_high(&self, value: bool) -> bool {
 | 
				
			||||||
 | 
							value ^ self.get_inverted()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn set(&mut self, value: bool) -> Result<(), EmgauwaError>;
 | 
				
			||||||
 | 
						fn get_pin(&self) -> u8;
 | 
				
			||||||
 | 
						fn get_inverted(&self) -> bool;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										52
									
								
								emgauwa-lib/src/drivers/piface.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								emgauwa-lib/src/drivers/piface.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,52 @@
 | 
				
			||||||
 | 
					use rppal_pfd::{
 | 
				
			||||||
 | 
						ChipSelect, HardwareAddress, OutputPin, PiFaceDigital, PiFaceDigitalError, SpiBus, SpiMode,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::drivers::RelayDriver;
 | 
				
			||||||
 | 
					use crate::errors::EmgauwaError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct PifaceDriver {
 | 
				
			||||||
 | 
						pub pfd_pin: OutputPin,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl PifaceDriver {
 | 
				
			||||||
 | 
						pub fn new(pin: u8, pfd: &Option<PiFaceDigital>) -> Result<Self, EmgauwaError> {
 | 
				
			||||||
 | 
							let pfd = pfd.as_ref().ok_or(EmgauwaError::Hardware(String::from(
 | 
				
			||||||
 | 
								"PiFaceDigital not initialized",
 | 
				
			||||||
 | 
							)))?;
 | 
				
			||||||
 | 
							let pfd_pin = pfd.get_output_pin(pin)?;
 | 
				
			||||||
 | 
							Ok(Self { pfd_pin })
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pub fn init_piface() -> Result<PiFaceDigital, EmgauwaError> {
 | 
				
			||||||
 | 
							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<(), EmgauwaError> {
 | 
				
			||||||
 | 
							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_pin(&self) -> u8 {
 | 
				
			||||||
 | 
							self.pfd_pin.get_pin_number()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn get_inverted(&self) -> bool {
 | 
				
			||||||
 | 
							false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,9 @@ use actix::MailboxError;
 | 
				
			||||||
use actix_web::http::StatusCode;
 | 
					use actix_web::http::StatusCode;
 | 
				
			||||||
use actix_web::HttpResponse;
 | 
					use actix_web::HttpResponse;
 | 
				
			||||||
use config::ConfigError;
 | 
					use config::ConfigError;
 | 
				
			||||||
 | 
					use rppal::gpio;
 | 
				
			||||||
 | 
					use rppal_mcp23s17::Mcp23s17Error;
 | 
				
			||||||
 | 
					use rppal_pfd::PiFaceDigitalError;
 | 
				
			||||||
use serde::ser::SerializeStruct;
 | 
					use serde::ser::SerializeStruct;
 | 
				
			||||||
use serde::{Serialize, Serializer};
 | 
					use serde::{Serialize, Serializer};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +24,7 @@ pub enum EmgauwaError {
 | 
				
			||||||
	Other(String),
 | 
						Other(String),
 | 
				
			||||||
	Internal(String),
 | 
						Internal(String),
 | 
				
			||||||
	Connection(ControllerUid),
 | 
						Connection(ControllerUid),
 | 
				
			||||||
 | 
						Hardware(String),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl EmgauwaError {
 | 
					impl EmgauwaError {
 | 
				
			||||||
| 
						 | 
					@ -33,6 +37,7 @@ impl EmgauwaError {
 | 
				
			||||||
			EmgauwaError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
 | 
								EmgauwaError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
 | 
				
			||||||
			EmgauwaError::Connection(_) => StatusCode::GATEWAY_TIMEOUT,
 | 
								EmgauwaError::Connection(_) => StatusCode::GATEWAY_TIMEOUT,
 | 
				
			||||||
			EmgauwaError::Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
 | 
								EmgauwaError::Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
 | 
				
			||||||
 | 
								EmgauwaError::Hardware(_) => StatusCode::INTERNAL_SERVER_ERROR,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -47,6 +52,7 @@ impl From<&EmgauwaError> for String {
 | 
				
			||||||
			EmgauwaError::Internal(_) => String::from("internal error"),
 | 
								EmgauwaError::Internal(_) => String::from("internal error"),
 | 
				
			||||||
			EmgauwaError::Connection(_) => String::from("the target controller is not connected"),
 | 
								EmgauwaError::Connection(_) => String::from("the target controller is not connected"),
 | 
				
			||||||
			EmgauwaError::Other(err) => format!("other error: {}", err),
 | 
								EmgauwaError::Other(err) => format!("other error: {}", err),
 | 
				
			||||||
 | 
								EmgauwaError::Hardware(err) => format!("hardware error: {}", err),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -93,6 +99,25 @@ impl From<ConfigError> for EmgauwaError {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<gpio::Error> for EmgauwaError {
 | 
				
			||||||
 | 
						fn from(value: gpio::Error) -> Self {
 | 
				
			||||||
 | 
							Self::Hardware(value.to_string())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<PiFaceDigitalError> for EmgauwaError {
 | 
				
			||||||
 | 
						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<&EmgauwaError> for HttpResponse {
 | 
					impl From<&EmgauwaError> for HttpResponse {
 | 
				
			||||||
	fn from(err: &EmgauwaError) -> Self {
 | 
						fn from(err: &EmgauwaError) -> Self {
 | 
				
			||||||
		HttpResponse::build(err.get_code()).json(err)
 | 
							HttpResponse::build(err.get_code()).json(err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
pub mod constants;
 | 
					pub mod constants;
 | 
				
			||||||
pub mod db;
 | 
					pub mod db;
 | 
				
			||||||
 | 
					pub mod drivers;
 | 
				
			||||||
pub mod errors;
 | 
					pub mod errors;
 | 
				
			||||||
pub mod models;
 | 
					pub mod models;
 | 
				
			||||||
pub mod settings;
 | 
					pub mod settings;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue