Even more improved init

This commit is contained in:
Gregor Reitzenstein 2020-12-14 12:39:01 +01:00
parent 5a42b34fe3
commit 1dc8dc4710
6 changed files with 104 additions and 19 deletions

View File

@ -110,7 +110,7 @@ pub fn load(log: &Logger, client: &AsyncClient, config: &Config) -> Result<(Acto
let mut map = HashMap::new(); let mut map = HashMap::new();
let actuators = config.actors.iter() let actuators = config.actors.iter()
.map(|(k,v)| (k, load_single(log, client, k, &v.name, &v.params))) .map(|(k,v)| (k, load_single(log, client, k, &v.module, &v.params)))
.filter_map(|(k, n)| match n { .filter_map(|(k, n)| match n {
None => None, None => None,
Some(a) => Some((k, a)) Some(a) => Some((k, a))
@ -127,13 +127,30 @@ pub fn load(log: &Logger, client: &AsyncClient, config: &Config) -> Result<(Acto
Ok(( map, v )) Ok(( map, v ))
} }
fn load_single(log: &Logger, client: &AsyncClient, name: &String, module_name: &String, params: &HashMap<String, String>) -> Option<Box<dyn Actuator + Sync + Send>> { fn load_single(
log: &Logger,
client: &AsyncClient,
name: &String,
module_name: &String,
params: &HashMap<String, String>
) -> Option<Box<dyn Actuator + Sync + Send>>
{
use crate::modules::*; use crate::modules::*;
match module_name.as_ref() { match module_name.as_ref() {
"Shelly" => { "Shelly" => {
Some(Box::new(Shelly::new(log, name.clone(), client.clone()))) if !params.is_empty() {
warn!(log, "\"{}\" module expects no parameters. Configured as \"{}\".",
module_name, name);
} }
_ => None, Some(Box::new(Shelly::new(log, name.clone(), client.clone())))
},
"Dummy" => {
Some(Box::new(Dummy))
}
_ => {
error!(log, "No actor found with name \"{}\", configured as \"{}\".", module_name, name);
None
},
} }
} }

View File

@ -10,6 +10,7 @@ use serde::{Serialize, Deserialize};
use crate::error::Result; use crate::error::Result;
use crate::machine::MachineDescription; use crate::machine::MachineDescription;
use crate::db::machine::MachineIdentifier; use crate::db::machine::MachineIdentifier;
use crate::db::access::*;
pub fn read(path: &Path) -> Result<Config> { pub fn read(path: &Path) -> Result<Config> {
serde_dhall::from_file(path) serde_dhall::from_file(path)
@ -38,6 +39,9 @@ pub struct Config {
pub initiators: HashMap<String, ModuleConfig>, pub initiators: HashMap<String, ModuleConfig>,
pub mqtt_url: String, pub mqtt_url: String,
pub actor_connections: Box<[(String, String)]>,
pub init_connections: Box<[(String, String)]>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -48,8 +52,7 @@ pub struct Listen {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModuleConfig { pub struct ModuleConfig {
pub name: String, pub module: String,
#[serde(skip_serializing_if = "HashMap::is_empty")]
pub params: HashMap<String, String> pub params: HashMap<String, String>
} }
@ -57,16 +60,28 @@ impl Default for Config {
fn default() -> Self { fn default() -> Self {
let mut actors: HashMap::<String, ModuleConfig> = HashMap::new(); let mut actors: HashMap::<String, ModuleConfig> = HashMap::new();
let mut initiators: HashMap::<String, ModuleConfig> = HashMap::new(); let mut initiators: HashMap::<String, ModuleConfig> = HashMap::new();
let mut machines = HashMap::new();
actors.insert("Actor".to_string(), ModuleConfig { actors.insert("Actor".to_string(), ModuleConfig {
name: "Shelly".to_string(), module: "Shelly".to_string(),
params: HashMap::new(), params: HashMap::new(),
}); });
initiators.insert("Initiator".to_string(), ModuleConfig { initiators.insert("Initiator".to_string(), ModuleConfig {
name: "TCP-Listen".to_string(), module: "TCP-Listen".to_string(),
params: HashMap::new(), params: HashMap::new(),
}); });
machines.insert("Testmachine".to_string(), MachineDescription {
name: "Testmachine".to_string(),
description: Some("A test machine".to_string()),
privs: PrivilegesBuf {
disclose: PermissionBuf::from_string("lab.test.read".to_string()),
read: PermissionBuf::from_string("lab.test.read".to_string()),
write: PermissionBuf::from_string("lab.test.write".to_string()),
manage: PermissionBuf::from_string("lab.test.admin".to_string()),
},
});
Config { Config {
listens: Box::new([ listens: Box::new([
Listen { Listen {
@ -74,10 +89,16 @@ impl Default for Config {
port: Some(DEFAULT_PORT), port: Some(DEFAULT_PORT),
} }
]), ]),
machines: HashMap::new(), machines: machines,
actors: actors, actors: actors,
initiators: initiators, initiators: initiators,
mqtt_url: "tcp://localhost:1883".to_string(), mqtt_url: "tcp://localhost:1883".to_string(),
actor_connections: Box::new([
("Testmachine".to_string(), "Actor".to_string()),
]),
init_connections: Box::new([
("Initiator".to_string(), "Testmachine".to_string()),
]),
} }
} }
} }

View File

@ -2,8 +2,13 @@ use std::pin::Pin;
use std::task::{Poll, Context}; use std::task::{Poll, Context};
use std::future::Future; use std::future::Future;
use std::collections::HashMap; use std::collections::HashMap;
use smol::{Task, Timer}; use smol::{Task, Timer};
use slog::Logger;
use paho_mqtt::AsyncClient;
use futures::FutureExt; use futures::FutureExt;
use futures::future::BoxFuture; use futures::future::BoxFuture;
@ -17,6 +22,7 @@ use crate::db::user::{User, UserId, UserData};
use crate::network::InitMap; use crate::network::InitMap;
use crate::error::Result; use crate::error::Result;
use crate::config::Config;
pub trait Sensor { pub trait Sensor {
fn run_sensor(&mut self) -> BoxFuture<'static, (Option<User>, MachineState)>; fn run_sensor(&mut self) -> BoxFuture<'static, (Option<User>, MachineState)>;
@ -82,14 +88,44 @@ impl Future for Initiator {
} }
} }
pub fn load() -> Result<(InitMap, Vec<Initiator>)> { pub fn load(log: &Logger, client: &AsyncClient, config: &Config) -> Result<(InitMap, Vec<Initiator>)> {
let d = Box::new(Dummy::new());
let (m, i) = Initiator::wrap(d);
let mut map = HashMap::new(); let mut map = HashMap::new();
map.insert("Dummy".to_string(), m);
Ok((map, vec![i])) let initiators = config.initiators.iter()
.map(|(k,v)| (k, load_single(log, client, k, &v.module, &v.params)))
.filter_map(|(k,n)| match n {
None => None,
Some(i) => Some((k, i)),
});
let mut v = Vec::new();
for (name, initiator) in initiators {
let (m, i) = Initiator::wrap(initiator);
map.insert(name.clone(), m);
v.push(i);
}
Ok((map, v))
}
fn load_single(
log: &Logger,
client: &AsyncClient,
name: &String,
module_name: &String,
params: &HashMap<String, String>
) -> Option<BoxSensor>
{
match module_name.as_ref() {
"Dummy" => {
Some(Box::new(Dummy::new()))
},
_ => {
error!(log, "No initiator found with name \"{}\", configured as \"{}\"",
module_name, name);
None
}
}
} }
pub struct Dummy { pub struct Dummy {

View File

@ -224,7 +224,7 @@ pub struct MachineDescription {
/// The permission required /// The permission required
#[serde(flatten)] #[serde(flatten)]
privs: access::PrivilegesBuf, pub privs: access::PrivilegesBuf,
} }
impl MachineDescription { impl MachineDescription {

View File

@ -139,16 +139,26 @@ fn maybe(matches: clap::ArgMatches, log: Arc<Logger>) -> Result<(), Error> {
let mqtt = AsyncClient::new(config.mqtt_url.clone())?; let mqtt = AsyncClient::new(config.mqtt_url.clone())?;
let tok = mqtt.connect(paho_mqtt::ConnectOptions::new()); let tok = mqtt.connect(paho_mqtt::ConnectOptions::new());
smol::block_on(tok); smol::block_on(tok)?;
let machines = machine::load(&config)?; let machines = machine::load(&config)?;
let (mut actor_map, actors) = actor::load(&log, &mqtt, &config)?; let (mut actor_map, actors) = actor::load(&log, &mqtt, &config)?;
let (mut init_map, initiators) = initiator::load()?; let (mut init_map, initiators) = initiator::load(&log, &mqtt, &config)?;
let network = network::Network::new(machines, actor_map, init_map); // TODO: restore connections between initiators, machines, actors
let mut network = network::Network::new(machines, actor_map, init_map);
for (a,b) in config.actor_connections.iter() {
if let Err(e) = network.connect_actor(a,b) {
error!(log, "{}", e);
}
}
// TODO HERE: restore connections between initiators, machines, actors for (a,b) in config.init_connections.iter() {
if let Err(e) = network.connect_init(a,b) {
error!(log, "{}", e);
}
}
let actor_tasks = actors.into_iter().map(|actor| ex.spawn(actor)); let actor_tasks = actors.into_iter().map(|actor| ex.spawn(actor));
let init_tasks = initiators.into_iter().map(|init| ex.spawn(init)); let init_tasks = initiators.into_iter().map(|init| ex.spawn(init));

View File

@ -32,6 +32,7 @@ pub struct Shelly {
impl Shelly { impl Shelly {
pub fn new(log_view: &Logger, name: String, client: mqtt::AsyncClient) -> Self { pub fn new(log_view: &Logger, name: String, client: mqtt::AsyncClient) -> Self {
let log = log_view.new(o!("shelly_name" => name.clone())); let log = log_view.new(o!("shelly_name" => name.clone()));
debug!(log, "Starting shelly module for {}", &name);
Shelly { log, name, client, } Shelly { log, name, client, }
} }