Rearrange mappings/actions, swap fmt for tracing

Some mappings made more sense as actions. This clears the way for
triggering multiple actions.
This commit is contained in:
2022-07-08 13:22:12 +01:00
parent 4515e8d15d
commit c3361915a4
5 changed files with 131 additions and 106 deletions
+20 -6
View File
@@ -2,20 +2,34 @@ use serde::Deserialize;
use serde_dhall::StaticType;
use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::path::Path;
#[derive(Deserialize, StaticType, Debug)]
pub enum Action {
MQTTPub { topic: String, payload: String }, // Publish something (server, topic, payload)
ActivateLayer(String), // Activate a layer
Print(String), // Print a string to console
MQTTPub { topic: String, payload: String }, // Publish payload on topic via MQTT
}
impl fmt::Display for Action {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
Action::ActivateLayer(layer) => write!(f, "ActivateLayer({})", layer),
Action::Print(p) => write!(f, "Print({})", p),
Action::MQTTPub { topic, payload } => {
write!(f, "MQTTPub(topic={},payload={})", topic, payload)
}
}
}
}
#[derive(Deserialize, StaticType, Debug)]
pub enum Mapping {
NOP, // Do nothing.
Passthrough, // Passthrough to the layer below
ActivateLayer(String), // Activate a layer
Print(String), // Print a string to console
Trigger(Action), // Trigger an action
NOP, // Do nothing.
Passthrough, // Passthrough to the layer below
Trigger(Action), // Trigger an action
TriggerMulti(Vec<Action>), // Trigger multiple actions in sequence
}
#[derive(Deserialize, Debug)]
+13 -1
View File
@@ -2,6 +2,8 @@ use bitvec::prelude::*;
use hidapi::{DeviceInfo, HidApi, HidDevice};
use std::collections::VecDeque;
use std::error::Error;
use std::fmt;
use tracing::{event, Level};
const HID_USAGE_PAGE: u16 = 0xFF;
const HID_USAGE: u16 = 0x1;
@@ -37,6 +39,16 @@ pub enum ButtonEvent {
KeyUp(u8),
}
impl fmt::Display for ButtonEvent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let vals = match *self {
Self::KeyDown(key) => ("KeyDown", key),
Self::KeyUp(key) => ("KeyUp", key),
};
write!(f, "{}(key={})", vals.0, vals.1)
}
}
type State = u16;
pub struct ButtonPad<'a> {
@@ -67,7 +79,7 @@ impl Iterator for ButtonPad<'_> {
// Read from the device, blocking until the next report
let mut buf: [u8; 2] = [0; 2];
self.dev.read(&mut buf).expect("error reading");
log::info!("{:?}", buf);
event!(Level::INFO, ?buf, "Read from device");
let new: u16 = buf[0] as u16 | (buf[1] as u16) << 8;
+23 -15
View File
@@ -1,23 +1,23 @@
use env_logger::Env;
mod config;
mod device;
use config::{Action, Config};
use hidapi::HidApi;
use log::info;
use rumqttc::{Client, MqttOptions, QoS};
use std::collections::HashMap;
use std::error::Error;
use std::path::Path;
use std::thread;
mod config;
mod device;
use tracing::{event, Level};
struct State<'a> {
mqtt_servers: HashMap<String, Client>,
conf: &'a config::Config,
conf: &'a Config,
key_state: [bool; 16],
}
impl<'a> State<'a> {
fn init(c: &'a config::Config) -> Self {
fn init(c: &'a Config) -> Self {
let mut s = State {
mqtt_servers: HashMap::new(),
conf: &c,
@@ -71,10 +71,9 @@ impl<'a> State<'a> {
}
}
fn execute_mapping(&mut self, m: &config::Mapping) {
match m {
config::Mapping::Print(s) => println!("{}", s),
config::Mapping::Trigger(config::Action::MQTTPub { topic, payload }) => {
fn execute_action(&mut self, action: &Action) {
match action {
Action::MQTTPub { topic, payload } => {
let mut topic = topic.to_owned();
let srv = &self.conf.mqtt_servers["default"];
if let Some(prefix) = &srv.topic_prefix {
@@ -84,6 +83,14 @@ impl<'a> State<'a> {
cli.publish(topic, QoS::AtLeastOnce, false, payload.as_bytes())
.unwrap();
}
Action::Print(s) => println!("{}", s),
_ => event!(Level::WARN, %action, "Ignoring unimplemented action"),
}
}
fn execute_mapping(&mut self, m: &config::Mapping) {
match m {
config::Mapping::Trigger(t) => self.execute_action(t),
_ => {}
}
}
@@ -100,8 +107,9 @@ impl<'a> State<'a> {
}
fn main() -> Result<(), Box<dyn Error>> {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let conf = config::Config::from_file(Path::new("./config.dhall"))?;
tracing_subscriber::fmt::init();
event!(Level::INFO, "Starting...");
let conf = Config::from_file(Path::new("./config.dhall"))?;
let mut state = State::init(&conf);
@@ -117,12 +125,12 @@ fn main() -> Result<(), Box<dyn Error>> {
let pad = device::ButtonPad::new(&device);
for ev in pad {
if let Ok(ev) = ev {
info!("{:?}", ev);
event!(Level::INFO, ?ev, "Got event");
state.handle_button(&ev);
let mut data = state.get_led_data().to_vec();
data.insert(0, 0x0);
data.insert(0, 0x0);
log::info!("{:?}", data);
event!(Level::INFO, ?data, "Sending LED data");
device.write(data.as_slice())?;
}
}