Switch to mqtt adaptor
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
use ::ddcmqtt::{main as main_, StdError};
|
||||
use tracing_subscriber;
|
||||
|
||||
fn main() -> StdError<()> {
|
||||
tracing_subscriber::fmt::init();
|
||||
main_()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use ddc::Ddc;
|
||||
use ddc_i2c::{I2cDeviceDdc, I2cDeviceEnumerator};
|
||||
|
||||
use ::ddcmqtt::StdError;
|
||||
|
||||
|
||||
+76
-5
@@ -1,12 +1,16 @@
|
||||
use ddc::Ddc;
|
||||
use ddc_i2c::{I2cDeviceDdc, I2cDeviceEnumerator};
|
||||
use rosc;
|
||||
use rumqttc::mqttbytes::v4::Packet;
|
||||
use rumqttc::{Client, Event, MqttOptions, QoS};
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
use rosc;
|
||||
use tracing::{event, Level};
|
||||
|
||||
pub type StdError<T> = Result<T, Box<dyn Error>>;
|
||||
|
||||
@@ -47,9 +51,9 @@ fn run_i2c(mut dev: I2cDeviceDdc, command_channel: Receiver<MonitorCommand>) {
|
||||
}
|
||||
}
|
||||
match cmd {
|
||||
MonitorCommand::Brightness(b) => dev.set_vcp_feature(0x10, b.into()).unwrap(),
|
||||
MonitorCommand::Brightness(b) => dev.set_vcp_feature(cmd.vcp(), b.into()).unwrap(),
|
||||
// Hack - add 15 to align with DELL monitors
|
||||
MonitorCommand::Input(i) => dev.set_vcp_feature(0x60, (i + 15).into()).unwrap(),
|
||||
MonitorCommand::Input(i) => dev.set_vcp_feature(cmd.vcp(), (i + 15).into()).unwrap(),
|
||||
}
|
||||
last_sent_command.insert(cmd.cmd_str(), Some(Instant::now()));
|
||||
}
|
||||
@@ -66,7 +70,74 @@ pub fn main() -> StdError<()> {
|
||||
tx
|
||||
})
|
||||
.collect();
|
||||
let sock = UdpSocket::bind("0.0.0.0:1234").unwrap();
|
||||
run_mqtt(&txes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_mqtt(txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
|
||||
let client_id = env::var("MQTT_CLIENT_ID").unwrap_or("ddcmqtt".into());
|
||||
let mqtt_host = env::var("MQTT_HOST").unwrap_or("localhost".into());
|
||||
let mqtt_port = env::var("MQTT_PORT")
|
||||
.unwrap_or("1883".into())
|
||||
.parse::<u16>()?;
|
||||
let mqtt_user = env::var("MQTT_USER").ok();
|
||||
let mqtt_pass = env::var("MQTT_PASS").ok();
|
||||
let mut mqttoptions = MqttOptions::new(client_id, mqtt_host.clone(), mqtt_port);
|
||||
// Set credentials if we have user and pass specified.
|
||||
// TODO: warn if only one maybe?
|
||||
if let (Some(u), Some(p)) = (mqtt_user, mqtt_pass) {
|
||||
event!(Level::INFO, user = u, "Using MQTT user/pass from env");
|
||||
mqttoptions.set_credentials(u, p);
|
||||
}
|
||||
mqttoptions.set_keep_alive(Duration::from_secs(5));
|
||||
|
||||
let (mut client, mut connection) = Client::new(mqttoptions, 10);
|
||||
client.subscribe("ddcmqtt/#", QoS::AtMostOnce)?;
|
||||
|
||||
event!(Level::INFO, mqtt_host, mqtt_port, "Running MQTT client");
|
||||
|
||||
for notification in connection.iter() {
|
||||
event!(Level::INFO, ?notification, "Got notification");
|
||||
if let Ok(Event::Incoming(Packet::Publish(p))) = notification {
|
||||
let topic: Vec<_> = p.topic.split("/").collect();
|
||||
if topic.len() != 3 {
|
||||
event!(
|
||||
Level::WARN,
|
||||
?topic,
|
||||
"Publish topic has wrong format, ignoring."
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if topic[0] != "ddcmqtt" {
|
||||
event!(
|
||||
Level::ERROR,
|
||||
?topic,
|
||||
"Got publish that we didn't subscribe to!"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
let mon_idx = topic[1].parse::<u8>();
|
||||
match (mon_idx, topic[2]) {
|
||||
(Ok(idx), "input") => {
|
||||
// TODO: don't crash on these ?s - I'm feeling lazy
|
||||
let input_id = std::str::from_utf8(&p.payload)?.parse::<u8>()?;
|
||||
handle_cmd(
|
||||
Command::Monitor((idx.into(), MonitorCommand::Input(input_id))),
|
||||
&txes,
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
event!(Level::ERROR, ?topic, "Unrecognised or invalid topic");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_osc(txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
|
||||
let sock = UdpSocket::bind("0.0.0.0:1234")?;
|
||||
let mut buf = [0u8; rosc::decoder::MTU];
|
||||
|
||||
loop {
|
||||
@@ -89,7 +160,6 @@ pub fn main() -> StdError<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_cmd(cmd: Command, txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
|
||||
@@ -98,6 +168,7 @@ fn handle_cmd(cmd: Command, txes: &Vec<Sender<MonitorCommand>>) -> StdError<()>
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn osc_message_to_command(msg: rosc::OscMessage) -> StdError<Command> {
|
||||
println!("OSC: {}, args: {:?}", msg.addr, msg.args);
|
||||
let splitaddr: Vec<_> = msg.addr.split("/").collect();
|
||||
|
||||
Reference in New Issue
Block a user