Compare commits
	
		
			No commits in common. "63c86ab80e5a063eb20ddee8d20dc5e1ac7fa3e0" and "7aab7f726c60a2ba83e78fd17eaf629aa29a57e0" have entirely different histories.
		
	
	
		
			63c86ab80e
			...
			7aab7f726c
		
	
		
							
								
								
									
										36
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										36
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							@ -6,11 +6,11 @@
 | 
				
			|||||||
        "nixpkgs": "nixpkgs"
 | 
					        "nixpkgs": "nixpkgs"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1663445644,
 | 
					        "lastModified": 1655976588,
 | 
				
			||||||
        "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
 | 
					        "narHash": "sha256-VreHyH6ITkf/1EX/8h15UqhddJnUleb0HgbC3gMkAEQ=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "devshell",
 | 
					        "repo": "devshell",
 | 
				
			||||||
        "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
 | 
					        "rev": "899ca4629020592a13a46783587f6e674179d1db",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@ -36,11 +36,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_2": {
 | 
					    "flake-utils_2": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1659877975,
 | 
					        "lastModified": 1656928814,
 | 
				
			||||||
        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
 | 
					        "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
        "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
 | 
					        "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@ -51,11 +51,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_3": {
 | 
					    "flake-utils_3": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1659877975,
 | 
					        "lastModified": 1656065134,
 | 
				
			||||||
        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
 | 
					        "narHash": "sha256-oc6E6ByIw3oJaIyc67maaFcnjYOz1mMcOtHxbEf9NwQ=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
        "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
 | 
					        "rev": "bee6a7250dd1b01844a2de7e02e4df7d8a0a206c",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@ -69,11 +69,11 @@
 | 
				
			|||||||
        "nixpkgs": "nixpkgs_2"
 | 
					        "nixpkgs": "nixpkgs_2"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1662220400,
 | 
					        "lastModified": 1655042882,
 | 
				
			||||||
        "narHash": "sha256-9o2OGQqu4xyLZP9K6kNe1pTHnyPz0Wr3raGYnr9AIgY=",
 | 
					        "narHash": "sha256-9BX8Fuez5YJlN7cdPO63InoyBy7dm3VlJkkmTt6fS1A=",
 | 
				
			||||||
        "owner": "nix-community",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "naersk",
 | 
					        "repo": "naersk",
 | 
				
			||||||
        "rev": "6944160c19cb591eb85bbf9b2f2768a935623ed3",
 | 
					        "rev": "cddffb5aa211f50c4b8750adbec0bbbdfb26bb9f",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@ -124,11 +124,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs_4": {
 | 
					    "nixpkgs_4": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1665296151,
 | 
					        "lastModified": 1656401090,
 | 
				
			||||||
        "narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
 | 
					        "narHash": "sha256-bUS2nfQsvTQW2z8SK7oEFSElbmoBahOPtbXPm0AL3I4=",
 | 
				
			||||||
        "owner": "NixOS",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
 | 
					        "rev": "16de63fcc54e88b9a106a603038dd5dd2feb21eb",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@ -153,11 +153,11 @@
 | 
				
			|||||||
        "nixpkgs": "nixpkgs_4"
 | 
					        "nixpkgs": "nixpkgs_4"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1665457114,
 | 
					        "lastModified": 1657075953,
 | 
				
			||||||
        "narHash": "sha256-Rtut6Q81u1pDS3Y44Syhy436IrESmvPCdGDtl47E4eo=",
 | 
					        "narHash": "sha256-xVgbASGI/wODPpUiMexxZau+XDVOZMBbFmw2KsZyFKA=",
 | 
				
			||||||
        "owner": "oxalica",
 | 
					        "owner": "oxalica",
 | 
				
			||||||
        "repo": "rust-overlay",
 | 
					        "repo": "rust-overlay",
 | 
				
			||||||
        "rev": "5066af8707c4b598ad2dbfb2fdac73714bee3438",
 | 
					        "rev": "339de634e6f19e420e81d5a6acaa39364a726999",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@
 | 
				
			|||||||
       */
 | 
					       */
 | 
				
			||||||
      devShells.default = pkgs.mkShell {
 | 
					      devShells.default = pkgs.mkShell {
 | 
				
			||||||
        nativeBuildInputs = with pkgs; [
 | 
					        nativeBuildInputs = with pkgs; [
 | 
				
			||||||
          (rust-bin.nightly.latest.default.override {extensions = ["rls"];})
 | 
					          (rust-bin.stable.latest.default.override {extensions = ["rls"];})
 | 
				
			||||||
          udev
 | 
					          udev
 | 
				
			||||||
          pkgconfig
 | 
					          pkgconfig
 | 
				
			||||||
          mosquitto  # For testing mqtt with mosquitto_pub
 | 
					          mosquitto  # For testing mqtt with mosquitto_pub
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										43
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								src/lib.rs
									
									
									
									
									
								
							@ -17,15 +17,9 @@ enum Command {
 | 
				
			|||||||
    Monitor((usize, MonitorCommand)),
 | 
					    Monitor((usize, MonitorCommand)),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
pub enum MonitorBrightnessCmd {
 | 
					 | 
				
			||||||
    Absolute(u8),
 | 
					 | 
				
			||||||
    Relative(i8),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub enum MonitorCommand {
 | 
					pub enum MonitorCommand {
 | 
				
			||||||
    Brightness(MonitorBrightnessCmd),
 | 
					    Brightness(u8),
 | 
				
			||||||
    Input(u8),
 | 
					    Input(u8),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -57,42 +51,17 @@ fn run_i2c(idx: usize, mut dev: I2cDeviceDdc, command_channel: Receiver<MonitorC
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        event!(Level::INFO, monitor_index = idx, ?cmd, "Sending DDC comand");
 | 
					        event!(Level::INFO, monitor_index = idx, ?cmd, "Sending DDC comand");
 | 
				
			||||||
        if let Err(e) = handle_monitor_cmd(&cmd, &mut dev) {
 | 
					        if let Err(e) = match cmd {
 | 
				
			||||||
 | 
					            MonitorCommand::Brightness(b) => dev.set_vcp_feature(cmd.vcp(), b.into()),
 | 
				
			||||||
 | 
					            // Hack - add 15 to align with DELL monitors
 | 
				
			||||||
 | 
					            MonitorCommand::Input(i) => dev.set_vcp_feature(cmd.vcp(), (i + 15).into()),
 | 
				
			||||||
 | 
					        } {
 | 
				
			||||||
            event!(Level::WARN, err = %e, "Error sending DDC command");
 | 
					            event!(Level::WARN, err = %e, "Error sending DDC command");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        last_sent_command.insert(cmd.cmd_str(), Some(Instant::now()));
 | 
					        last_sent_command.insert(cmd.cmd_str(), Some(Instant::now()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn handle_monitor_cmd(cmd: &MonitorCommand, dev: &mut I2cDeviceDdc) -> StdError<()> {
 | 
					 | 
				
			||||||
    match cmd {
 | 
					 | 
				
			||||||
        MonitorCommand::Brightness(MonitorBrightnessCmd::Absolute(b)) => {
 | 
					 | 
				
			||||||
            event!(Level::INFO, brightness = b, "Setting monitor brightness");
 | 
					 | 
				
			||||||
            dev.set_vcp_feature(cmd.vcp(), (*b).into())
 | 
					 | 
				
			||||||
                .map_err(|e| e.into())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        MonitorCommand::Brightness(MonitorBrightnessCmd::Relative(b)) => {
 | 
					 | 
				
			||||||
            let current = dev.get_vcp_feature(cmd.vcp())?;
 | 
					 | 
				
			||||||
            let (current, max) = (current.value(), current.maximum());
 | 
					 | 
				
			||||||
            event!(Level::INFO, current, max, "Got brightness of monitor");
 | 
					 | 
				
			||||||
            if max != 100 {
 | 
					 | 
				
			||||||
                return Err(format!("Expected maximum brightness to be 100, got {}", max).into());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            let mut new = current.saturating_add_signed(*b as i16);
 | 
					 | 
				
			||||||
            // Clamp to 0-100
 | 
					 | 
				
			||||||
            if new > 100 {
 | 
					 | 
				
			||||||
                new = 100;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            event!(Level::INFO, brightness = new, "Setting monitor brightness");
 | 
					 | 
				
			||||||
            dev.set_vcp_feature(cmd.vcp(), new).map_err(|e| e.into())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // Hack - add 15 to align with DELL monitors
 | 
					 | 
				
			||||||
        MonitorCommand::Input(i) => dev
 | 
					 | 
				
			||||||
            .set_vcp_feature(cmd.vcp(), (i + 15).into())
 | 
					 | 
				
			||||||
            .map_err(|e| e.into()),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn main() -> StdError<()> {
 | 
					pub fn main() -> StdError<()> {
 | 
				
			||||||
    event!(Level::INFO, "Starting");
 | 
					    event!(Level::INFO, "Starting");
 | 
				
			||||||
    let displays = I2cDeviceEnumerator::new().unwrap().collect::<Vec<_>>();
 | 
					    let displays = I2cDeviceEnumerator::new().unwrap().collect::<Vec<_>>();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										19
									
								
								src/mqtt.rs
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/mqtt.rs
									
									
									
									
									
								
							@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::{handle_cmd, Command, MonitorBrightnessCmd, MonitorCommand, StdError};
 | 
					use crate::{handle_cmd, Command, MonitorCommand, StdError};
 | 
				
			||||||
use rumqttc::mqttbytes::v4::Packet;
 | 
					use rumqttc::mqttbytes::v4::Packet;
 | 
				
			||||||
use rumqttc::{Client, Event, MqttOptions, QoS};
 | 
					use rumqttc::{Client, Event, MqttOptions, QoS};
 | 
				
			||||||
use std::env;
 | 
					use std::env;
 | 
				
			||||||
@ -8,7 +8,6 @@ use tracing::{event, Level};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub fn run_mqtt(txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
 | 
					pub fn run_mqtt(txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
 | 
				
			||||||
    let client_id = env::var("MQTT_CLIENT_ID").unwrap_or("ddcmqtt".into());
 | 
					    let client_id = env::var("MQTT_CLIENT_ID").unwrap_or("ddcmqtt".into());
 | 
				
			||||||
    let topic_prefix = env::var("MQTT_TOPIC_PREFIX").unwrap_or("ddcmqtt".into());
 | 
					 | 
				
			||||||
    let mqtt_host = env::var("MQTT_HOST").unwrap_or("localhost".into());
 | 
					    let mqtt_host = env::var("MQTT_HOST").unwrap_or("localhost".into());
 | 
				
			||||||
    let mqtt_port = env::var("MQTT_PORT")
 | 
					    let mqtt_port = env::var("MQTT_PORT")
 | 
				
			||||||
        .unwrap_or("1883".into())
 | 
					        .unwrap_or("1883".into())
 | 
				
			||||||
@ -25,7 +24,7 @@ pub fn run_mqtt(txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
 | 
				
			|||||||
    mqttoptions.set_keep_alive(Duration::from_secs(5));
 | 
					    mqttoptions.set_keep_alive(Duration::from_secs(5));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (mut client, mut connection) = Client::new(mqttoptions, 10);
 | 
					    let (mut client, mut connection) = Client::new(mqttoptions, 10);
 | 
				
			||||||
    client.subscribe([&topic_prefix, "#"].join("/"), QoS::AtMostOnce)?;
 | 
					    client.subscribe("ddcmqtt/#", QoS::AtMostOnce)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    event!(Level::INFO, mqtt_host, mqtt_port, "Running MQTT client");
 | 
					    event!(Level::INFO, mqtt_host, mqtt_port, "Running MQTT client");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,7 +40,7 @@ pub fn run_mqtt(txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
 | 
				
			|||||||
                );
 | 
					                );
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if topic[0] != topic_prefix {
 | 
					            if topic[0] != "ddcmqtt" {
 | 
				
			||||||
                event!(
 | 
					                event!(
 | 
				
			||||||
                    Level::ERROR,
 | 
					                    Level::ERROR,
 | 
				
			||||||
                    ?topic,
 | 
					                    ?topic,
 | 
				
			||||||
@ -59,18 +58,6 @@ pub fn run_mqtt(txes: &Vec<Sender<MonitorCommand>>) -> StdError<()> {
 | 
				
			|||||||
                        &txes,
 | 
					                        &txes,
 | 
				
			||||||
                    )?;
 | 
					                    )?;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                (Ok(idx), "brightness") => {
 | 
					 | 
				
			||||||
                    let brightness = std::str::from_utf8(&p.payload)?;
 | 
					 | 
				
			||||||
                    let cmd = if brightness.starts_with('+') | brightness.starts_with('-') {
 | 
					 | 
				
			||||||
                        MonitorBrightnessCmd::Relative(brightness.parse::<i8>()?)
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        MonitorBrightnessCmd::Absolute(brightness.parse::<u8>()?)
 | 
					 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
                    handle_cmd(
 | 
					 | 
				
			||||||
                        Command::Monitor((idx.into(), MonitorCommand::Brightness(cmd))),
 | 
					 | 
				
			||||||
                        &txes,
 | 
					 | 
				
			||||||
                    )?;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
                    event!(Level::ERROR, ?topic, "Unrecognised or invalid topic");
 | 
					                    event!(Level::ERROR, ?topic, "Unrecognised or invalid topic");
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::{handle_cmd, Command, MonitorBrightnessCmd, MonitorCommand, StdError};
 | 
					use crate::{handle_cmd, Command, MonitorCommand, StdError};
 | 
				
			||||||
use rosc;
 | 
					use rosc;
 | 
				
			||||||
use std::net::UdpSocket;
 | 
					use std::net::UdpSocket;
 | 
				
			||||||
use std::sync::mpsc::Sender;
 | 
					use std::sync::mpsc::Sender;
 | 
				
			||||||
@ -36,9 +36,9 @@ fn osc_message_to_command(msg: rosc::OscMessage) -> StdError<Command> {
 | 
				
			|||||||
        ["monitor", idx, control] => {
 | 
					        ["monitor", idx, control] => {
 | 
				
			||||||
            println!("Monitor {}, control {}, args {:?}", idx, control, msg.args);
 | 
					            println!("Monitor {}, control {}, args {:?}", idx, control, msg.args);
 | 
				
			||||||
            let command = match *control {
 | 
					            let command = match *control {
 | 
				
			||||||
                "brightness" => Some(MonitorCommand::Brightness(MonitorBrightnessCmd::Absolute(
 | 
					                "brightness" => Some(MonitorCommand::Brightness(
 | 
				
			||||||
                    (msg.args[0].clone().float().unwrap() * 100.0) as u8,
 | 
					                    (msg.args[0].clone().float().unwrap() * 100.0) as u8,
 | 
				
			||||||
                ))),
 | 
					                )),
 | 
				
			||||||
                "input" => Some(MonitorCommand::Input(
 | 
					                "input" => Some(MonitorCommand::Input(
 | 
				
			||||||
                    (msg.args[0].clone().int().unwrap()) as u8,
 | 
					                    (msg.args[0].clone().int().unwrap()) as u8,
 | 
				
			||||||
                )),
 | 
					                )),
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user