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:
+20
-6
@@ -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
@@ -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
@@ -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())?;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user