-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
relay interface and voxpower inhibiter skeleton (#9)
- Loading branch information
Showing
5 changed files
with
377 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
src/builtin_devices/panduza/voxpower_inhibiter/itf_voxpower_inhibiter.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use async_trait::async_trait; | ||
use crate::platform::PlatformError; | ||
use crate::meta::relay; | ||
use crate::interface::AmInterface; | ||
use crate::interface::builder::Builder as InterfaceBuilder; | ||
|
||
use crate::connector::serial::tty; | ||
|
||
|
||
|
||
/// Voxpower Inhibiter Channel Data | ||
/// | ||
struct VoxpowerInhibiterActions { | ||
state_open: String, | ||
} | ||
|
||
#[async_trait] | ||
impl relay::RelayActions for VoxpowerInhibiterActions { | ||
|
||
/// Initialize the interface | ||
/// | ||
async fn initializating(&mut self, interface: &AmInterface) -> Result<(), PlatformError> { | ||
// let self.channel = channel; | ||
|
||
// tty::Get(name) | ||
|
||
return Ok(()); | ||
} | ||
|
||
/// Configuration of the interface | ||
/// | ||
async fn config(&mut self, interface: &AmInterface) -> Result<(), PlatformError> { | ||
return Ok(()); | ||
} | ||
|
||
/// Read the enable value | ||
/// | ||
async fn read_state_open(&mut self, interface: &AmInterface) -> Result<bool, PlatformError> { | ||
interface.lock().await.log_info( | ||
format!("VoxpowerInhibiter - read_state_open {}", self.state_open) | ||
); | ||
if self.state_open == "H" { | ||
return Ok(true); | ||
} else { | ||
return Ok(false); | ||
} | ||
} | ||
|
||
/// Write the enable value | ||
async fn write_state_open(&mut self, interface: &AmInterface, v: bool) { | ||
if v { | ||
let command = "I\n"; //format!("I{}\n", self.channel); | ||
self.state_open = command.to_string(); | ||
interface.lock().await.log_info( | ||
format!("VoxpowerInhibiter - inhibit channel: {}", self.state_open) | ||
); | ||
} else { | ||
let command = "E\n"; //format!("E{}\n", self.channel); | ||
self.state_open = command.to_string(); | ||
interface.lock().await.log_info( | ||
format!("VoxpowerInhibiter - enable channel: {}", self.state_open) | ||
); | ||
} | ||
} | ||
} | ||
|
||
|
||
/// Interface to emulate a Bench Power Channel | ||
/// | ||
pub fn build<A: Into<String>>( | ||
name: A, | ||
) -> InterfaceBuilder { | ||
|
||
return relay::build( | ||
name, | ||
Box::new(VoxpowerInhibiterActions { | ||
state_open: "L".to_string(), | ||
}) | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use async_trait::async_trait; | ||
use tokio::time::{sleep, Duration}; | ||
|
||
use crate::platform::PlatformError; | ||
use crate::subscription; | ||
use crate::interface::{self, Runner}; | ||
use crate::interface::AmInterface; | ||
use crate::interface::AmRunner; | ||
use crate::device::{ Device, traits::DeviceActions, traits::Producer }; | ||
|
||
use crate::interface::builder::Builder as InterfaceBuilder; | ||
struct PlatformInterfaceSubscriber; | ||
|
||
|
||
mod itf_voxpower_inhibiter; | ||
|
||
|
||
struct VoxpowerInhibiter; | ||
|
||
|
||
impl DeviceActions for VoxpowerInhibiter { | ||
|
||
// fn hunt(&self) -> LinkedList<Value> { | ||
// return LinkedList::new(); | ||
// } | ||
|
||
/// Create the interfaces | ||
fn interface_builders(&self, device_settings: &serde_json::Value) | ||
-> Result<Vec<InterfaceBuilder>, PlatformError> | ||
{ | ||
let mut list = Vec::new(); | ||
for n in 2..10 { | ||
list.push( | ||
itf_voxpower_inhibiter::build(format!("channel_{}", n)) | ||
); | ||
} | ||
|
||
return Ok(list); | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
pub struct DeviceProducer; | ||
|
||
impl Producer for DeviceProducer { | ||
|
||
fn produce(&self) -> Result<Box<dyn DeviceActions>, PlatformError> { | ||
return Ok(Box::new(VoxpowerInhibiter{})); | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
pub mod bpc; | ||
pub mod relay; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
use std::sync::Arc; | ||
|
||
use async_trait::async_trait; | ||
use serde_json::Value; | ||
use tokio::sync::Mutex; | ||
|
||
use crate::attribute::{self, JsonAttribute}; | ||
use crate::interface::AmInterface; | ||
use crate::platform::PlatformError; | ||
use crate::{interface, subscription}; | ||
use crate::interface::builder::Builder as InterfaceBuilder; | ||
|
||
|
||
#[async_trait] | ||
pub trait RelayActions: Send + Sync { | ||
|
||
/// Initialize the interface | ||
/// The connector initialization must be done here | ||
/// | ||
async fn initializating(&mut self, interface: &AmInterface) -> Result<(), PlatformError>; | ||
|
||
async fn config(&mut self, interface: &AmInterface) -> Result<(), PlatformError>; | ||
|
||
async fn read_state_open(&mut self, interface: &AmInterface) -> Result<bool, PlatformError>; | ||
|
||
async fn write_state_open(&mut self, interface: &AmInterface, v: bool); | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
|
||
|
||
pub struct StateAttribute { | ||
attr: JsonAttribute, | ||
} | ||
|
||
|
||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
|
||
struct RelayInterface { | ||
|
||
actions: Box<dyn RelayActions> | ||
} | ||
type AmRelayInterface = Arc<Mutex<RelayInterface>>; | ||
|
||
impl RelayInterface { | ||
fn new(actions: Box<dyn RelayActions>) -> RelayInterface { | ||
return RelayInterface { | ||
actions: actions | ||
} | ||
} | ||
fn new_am(actions: Box<dyn RelayActions>) -> AmRelayInterface { | ||
return Arc::new(Mutex::new( RelayInterface::new(actions) )); | ||
} | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
|
||
struct RelayStates { | ||
relay_interface: Arc<Mutex<RelayInterface>> | ||
} | ||
|
||
|
||
#[async_trait] | ||
impl interface::fsm::States for RelayStates { | ||
|
||
/// Just wait for an fsm event for the connection | ||
/// | ||
async fn connecting(&self, interface: &AmInterface) | ||
{ | ||
interface::basic::wait_for_fsm_event(interface).await; | ||
} | ||
|
||
/// Initialize the interface | ||
/// | ||
async fn initializating(&self, interface: &AmInterface) | ||
{ | ||
// Custom initialization slot | ||
self.relay_interface.lock().await.actions.initializating(&interface).await.unwrap(); | ||
|
||
// Register attributes | ||
interface.lock().await.register_attribute(JsonAttribute::new_boxed("state", true)); | ||
|
||
// Init state | ||
let state_value = self.relay_interface.lock().await.actions.read_state_open(&interface).await.unwrap(); | ||
interface.lock().await.update_attribute_with_bool("state", "value", state_value); | ||
|
||
// Publish all attributes for start | ||
interface.lock().await.publish_all_attributes().await; | ||
|
||
// Notify the end of the initialization | ||
interface.lock().await.set_event_init_done(); | ||
} | ||
|
||
async fn running(&self, interface: &AmInterface) | ||
{ | ||
println!("running"); | ||
|
||
|
||
interface::basic::wait_for_fsm_event(interface).await; | ||
} | ||
|
||
async fn error(&self, interface: &AmInterface) | ||
{ | ||
println!("error"); | ||
} | ||
|
||
async fn cleaning(&self, interface: &AmInterface) | ||
{ | ||
println!("cleaning"); | ||
} | ||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
|
||
const ID_STATE: subscription::Id = 0; | ||
|
||
struct RelaySubscriber { | ||
relay_interface: Arc<Mutex<RelayInterface>> | ||
} | ||
|
||
impl RelaySubscriber { | ||
|
||
/// | ||
/// | ||
#[inline(always)] | ||
async fn process_state_open(&self, interface: &AmInterface, attribute_name: &str, field_name: &str, field_data: &Value) { | ||
let requested_value = field_data.as_bool().unwrap(); | ||
self.relay_interface.lock().await | ||
.actions.write_state_open(&interface, requested_value).await; | ||
|
||
let r_value = self.relay_interface.lock().await | ||
.actions.read_state_open(&interface).await | ||
.unwrap(); | ||
|
||
interface.lock().await | ||
.update_attribute_with_bool("state", "value", r_value); | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl interface::subscriber::Subscriber for RelaySubscriber { | ||
|
||
/// Get the list of attributes names | ||
/// | ||
async fn attributes_names(&self) -> Vec<(subscription::Id, String)> { | ||
return vec![ | ||
(ID_STATE, "state".to_string()) | ||
]; | ||
} | ||
|
||
|
||
|
||
|
||
/// Process a message | ||
/// | ||
async fn process(&self, interface: &AmInterface, msg: &subscription::Message) { | ||
// Common processing | ||
interface::basic::process(&interface, msg).await; | ||
|
||
match msg { | ||
subscription::Message::Mqtt(msg) => { | ||
match msg.id() { | ||
subscription::ID_PZA_CMDS_SET => { | ||
// interface.lock().await.publish_info().await; | ||
|
||
// only when running state | ||
|
||
println!("RelaySubscriber::process: {:?}", msg.topic()); | ||
println!("RelaySubscriber::process: {:?}", msg.payload()); | ||
|
||
let payload = msg.payload(); | ||
let oo = serde_json::from_slice::<Value>(payload).unwrap(); | ||
let o = oo.as_object().unwrap(); | ||
|
||
|
||
for (attribute_name, fields) in o.iter() { | ||
for (field_name, field_data) in fields.as_object().unwrap().iter() { | ||
if attribute_name == "state" && field_name == "value" { | ||
self.process_state_open(&interface, attribute_name, field_name, field_data).await; | ||
} | ||
} | ||
} | ||
interface.lock().await.publish_all_attributes().await; | ||
|
||
|
||
}, | ||
_ => { | ||
// not managed by the common level | ||
} | ||
} | ||
} | ||
_ => { | ||
// not managed by the common level | ||
} | ||
} | ||
} | ||
|
||
|
||
} | ||
|
||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
// ---------------------------------------------------------------------------- | ||
|
||
/// Build the meta interface for a Voxpower Channel | ||
/// | ||
pub fn build<A: Into<String>>( | ||
name: A, | ||
actions: Box<dyn RelayActions> | ||
) -> InterfaceBuilder { | ||
|
||
let c = RelayInterface::new_am(actions); | ||
|
||
return InterfaceBuilder::new( | ||
name, | ||
"relay", | ||
"0.0", | ||
Box::new(RelayStates{relay_interface: c.clone()}), | ||
Box::new(RelaySubscriber{relay_interface: c.clone()}) | ||
); | ||
} | ||
|