Compare commits

...
4 Commits
Author SHA1 Message Date
samw 83c94f8802 wip from deskpi? 2026-07-06 12:00:54 +00:00
samw 7cd6639283 Add logo 2023-02-10 12:38:12 +00:00
samw 3065040189 Update and format config example
Also add dhall-json for testing json/yaml conversion
2022-07-11 14:07:39 +00:00
samw 7b2a92012b Streamline configuration
Fixes triggermulti deserialization
Add 'generate-dhall' argument, which generates dhall for the config
enums.
2022-07-11 14:03:13 +00:00
11 changed files with 907 additions and 467 deletions
Generated
+728 -400
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -4,10 +4,11 @@ version = "0.1.0"
edition = "2021"
[dependencies]
hidapi = "1"
hidapi = "2"
rumqttc = "0.12"
bitvec = "1"
serde = "1"
serde_dhall = "0.11"
tracing = "0.1.35"
tracing-subscriber = "0.3.14"
chrono = "0.4.19"
+13
View File
@@ -0,0 +1,13 @@
use std::error::Error;
use std::process::Command;
fn main() -> Result<(), Box<dyn Error>> {
let hash = Command::new("git")
.arg("rev-parse")
.arg("--short")
.arg("HEAD")
.output()?
.stdout;
println!("cargo:rustc-env=VERSION={}", std::str::from_utf8(&hash)?);
Ok(())
}
+16 -6
View File
@@ -1,16 +1,26 @@
{ mqtt_servers.default = { host = "1.2.3.4", user = Some "username", pass = Some
"password" }
let T = ./types.dhall
in { mqtt_servers.default
=
{ host = "1.2.3.4", user = Some "username", pass = Some "password" }
, layers.default
=
{ default_mapping = Mapping.Print "no mapping!"
{ default_mapping = T.Action.Print "no mapping!"
, mappings =
let sometopic = "homeassistant/switch/something/set"
in { key_0 =
Mapping.Trigger (Action.MQTTPub { topic = sometopic, payload = "ON" })
T.Mapping.Trigger
(T.Action.MQTTPub { topic = sometopic, payload = "ON" })
, key_1 =
Mapping.Trigger
(Action.MQTTPub { topic = sometopic, payload = "OFF" })
T.Mapping.Trigger
(T.Action.MQTTPub { topic = sometopic, payload = "OFF" })
, key_2 =
T.Mapping.TriggerMulti
[ T.Action.Print "Doing a thing"
, T.Action.MQTTPub
{ topic = "thing/foo/bar", payload = "boop" }
]
}
}
}
Generated
+50 -34
View File
@@ -6,11 +6,11 @@
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1650900878,
"narHash": "sha256-qhNncMBSa9STnhiLfELEQpYC1L4GrYHNIzyCZ/pilsI=",
"lastModified": 1678957337,
"narHash": "sha256-Gw4nVbuKRdTwPngeOZQOzH/IFowmz4LryMPDiJN/ah4=",
"owner": "numtide",
"repo": "devshell",
"rev": "d97df53b5ddaa1cfbea7cddbd207eb2634304733",
"rev": "3e0e60ab37cd0bf7ab59888f5c32499d851edb47",
"type": "github"
},
"original": {
@@ -36,11 +36,11 @@
},
"flake-utils_2": {
"locked": {
"lastModified": 1656065134,
"narHash": "sha256-oc6E6ByIw3oJaIyc67maaFcnjYOz1mMcOtHxbEf9NwQ=",
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "bee6a7250dd1b01844a2de7e02e4df7d8a0a206c",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
@@ -54,11 +54,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1651574473,
"narHash": "sha256-wQhFORvRjo8LB2hTmETmv6cbyKGDPbfWqvZ/0chnDE4=",
"lastModified": 1679567394,
"narHash": "sha256-ZvLuzPeARDLiQUt6zSZFGOs+HZmE+3g4QURc8mkBsfM=",
"owner": "nix-community",
"repo": "naersk",
"rev": "f21309b38e1da0d61b881b6b6d41b81c1aed4e1d",
"rev": "88cd22380154a2c36799fe8098888f0f59861a15",
"type": "github"
},
"original": {
@@ -69,11 +69,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1643381941,
"narHash": "sha256-pHTwvnN4tTsEKkWlXQ8JMY423epos8wUOhthpwJjtpc=",
"lastModified": 1677383253,
"narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5efc8ca954272c4376ac929f4c5ffefcc20551d5",
"rev": "9952d6bc395f5841262b006fbace8dd7e143b634",
"type": "github"
},
"original": {
@@ -85,12 +85,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1652059086,
"narHash": "sha256-CjHSbr6LSFkN4YBdTB6+8ZQmSqhsbiXqAeQ9hQJ/gBI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "934e076a441e318897aa17540f6cf7caadc69028",
"type": "github"
"lastModified": 1678500271,
"narHash": "sha256-tRBLElf6f02HJGG0ZR7znMNFv/Uf7b2fFInpTHiHaSE=",
"path": "/nix/store/x00nwwv3ima5ri9q6wi7mq9vml4djjgn-source",
"rev": "5eb98948b66de29f899c7fe27ae112a47964baf8",
"type": "path"
},
"original": {
"id": "nixpkgs",
@@ -99,12 +98,11 @@
},
"nixpkgs_3": {
"locked": {
"lastModified": 1652059086,
"narHash": "sha256-CjHSbr6LSFkN4YBdTB6+8ZQmSqhsbiXqAeQ9hQJ/gBI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "934e076a441e318897aa17540f6cf7caadc69028",
"type": "github"
"lastModified": 1678500271,
"narHash": "sha256-tRBLElf6f02HJGG0ZR7znMNFv/Uf7b2fFInpTHiHaSE=",
"path": "/nix/store/x00nwwv3ima5ri9q6wi7mq9vml4djjgn-source",
"rev": "5eb98948b66de29f899c7fe27ae112a47964baf8",
"type": "path"
},
"original": {
"id": "nixpkgs",
@@ -113,11 +111,11 @@
},
"nixpkgs_4": {
"locked": {
"lastModified": 1656401090,
"narHash": "sha256-bUS2nfQsvTQW2z8SK7oEFSElbmoBahOPtbXPm0AL3I4=",
"lastModified": 1665296151,
"narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "16de63fcc54e88b9a106a603038dd5dd2feb21eb",
"rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
"type": "github"
},
"original": {
@@ -142,11 +140,11 @@
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1657248581,
"narHash": "sha256-VSAhHCruQCFWzTz7ZSW5QLb2xIKrBGeEyEfKds4MXeY=",
"lastModified": 1681179516,
"narHash": "sha256-Ij/3YM5Gz5AiDKnP77ODJp2RGRRWmGTWYlfnuUT3z78=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "6bd9919005ab6bf72464c9ebdd80f89b0cf82f97",
"rev": "9e7373ba5627ffe952f66a3e82e3a375bdc38565",
"type": "github"
},
"original": {
@@ -155,13 +153,31 @@
"type": "github"
}
},
"utils": {
"systems": {
"locked": {
"lastModified": 1649676176,
"narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=",
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "a4b154ebbdc88c8498a5c7b01589addc9e9cb678",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
+4 -2
View File
@@ -27,16 +27,17 @@
pkgs = import nixpkgs {
inherit system;
overlays = [devshell.overlay (import rust-overlay)];
overlays = [devshell.overlays.default (import rust-overlay)];
};
in
pkgs.mkShell {
buildInputs = with pkgs; [
# Dhall (config) stuff
dhall
dhall-json
dhall-lsp-server
# Rust!
(rust-bin.stable.latest.default.override {
(rust-bin.stable."1.68.1".default.override {
extensions = ["rls"];
})
# Build requirements
@@ -45,6 +46,7 @@
openssl
# Utils
mosquitto # So we can poke mqtt
usbutils
];
};
formatter = pkgs.alejandra;
BIN
View File
Binary file not shown.
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g id="Layer1">
<rect x="0" y="0" width="256" height="256" style="fill:rgb(57,57,57);"/>
</g>
<g transform="matrix(0.933333,0,0,0.933333,8.53333,8.53333)">
<path d="M185.333,209C185.333,201.825 179.508,196 172.333,196L146.333,196C139.158,196 133.333,201.825 133.333,209L133.333,235C133.333,242.175 139.158,248 146.333,248L172.333,248C179.508,248 185.333,242.175 185.333,235L185.333,209ZM248,209C248,201.825 242.175,196 235,196L209,196C201.825,196 196,201.825 196,209L196,235C196,242.175 201.825,248 209,248L235,248C242.175,248 248,242.175 248,235L248,209ZM122.667,209C122.667,201.825 116.842,196 109.667,196L83.667,196C76.492,196 70.667,201.825 70.667,209L70.667,235C70.667,242.175 76.492,248 83.667,248L109.667,248C116.842,248 122.667,242.175 122.667,235L122.667,209ZM60,209C60,201.825 54.175,196 47,196L21,196C13.825,196 8,201.825 8,209L8,235C8,242.175 13.825,248 21,248L47,248C54.175,248 60,242.175 60,235L60,209ZM122.667,146.333C122.667,139.158 116.842,133.333 109.667,133.333L83.667,133.333C76.492,133.333 70.667,139.158 70.667,146.333L70.667,172.333C70.667,179.508 76.492,185.333 83.667,185.333L109.667,185.333C116.842,185.333 122.667,179.508 122.667,172.333L122.667,146.333ZM60,146.333C60,139.158 54.175,133.333 47,133.333L21,133.333C13.825,133.333 8,139.158 8,146.333L8,172.333C8,179.508 13.825,185.333 21,185.333L47,185.333C54.175,185.333 60,179.508 60,172.333L60,146.333ZM185.333,146.333C185.333,139.158 179.508,133.333 172.333,133.333L146.333,133.333C139.158,133.333 133.333,139.158 133.333,146.333L133.333,172.333C133.333,179.508 139.158,185.333 146.333,185.333L172.333,185.333C179.508,185.333 185.333,179.508 185.333,172.333L185.333,146.333ZM248,146.333C248,139.158 242.175,133.333 235,133.333L209,133.333C201.825,133.333 196,139.158 196,146.333L196,172.333C196,179.508 201.825,185.333 209,185.333L235,185.333C242.175,185.333 248,179.508 248,172.333L248,146.333ZM185.333,83.667C185.333,76.492 179.508,70.667 172.333,70.667L146.333,70.667C139.158,70.667 133.333,76.492 133.333,83.667L133.333,109.667C133.333,116.842 139.158,122.667 146.333,122.667L172.333,122.667C179.508,122.667 185.333,116.842 185.333,109.667L185.333,83.667ZM248,83.667C248,76.492 242.175,70.667 235,70.667L209,70.667C201.825,70.667 196,76.492 196,83.667L196,109.667C196,116.842 201.825,122.667 209,122.667L235,122.667C242.175,122.667 248,116.842 248,109.667L248,83.667ZM122.667,83.667C122.667,76.492 116.842,70.667 109.667,70.667L83.667,70.667C76.492,70.667 70.667,76.492 70.667,83.667L70.667,109.667C70.667,116.842 76.492,122.667 83.667,122.667L109.667,122.667C116.842,122.667 122.667,116.842 122.667,109.667L122.667,83.667ZM60,83.667C60,76.492 54.175,70.667 47,70.667L21,70.667C13.825,70.667 8,76.492 8,83.667L8,109.667C8,116.842 13.825,122.667 21,122.667L47,122.667C54.175,122.667 60,116.842 60,109.667L60,83.667ZM185.333,21C185.333,13.825 179.508,8 172.333,8L146.333,8C139.158,8 133.333,13.825 133.333,21L133.333,47C133.333,54.175 139.158,60 146.333,60L172.333,60C179.508,60 185.333,54.175 185.333,47L185.333,21ZM248,21C248,13.825 242.175,8 235,8L209,8C201.825,8 196,13.825 196,21L196,47C196,54.175 201.825,60 209,60L235,60C242.175,60 248,54.175 248,47L248,21ZM60,21C60,13.825 54.175,8 47,8L21,8C13.825,8 8,13.825 8,21L8,47C8,54.175 13.825,60 21,60L47,60C54.175,60 60,54.175 60,47L60,21ZM122.667,21C122.667,13.825 116.842,8 109.667,8L83.667,8C76.492,8 70.667,13.825 70.667,21L70.667,47C70.667,54.175 76.492,60 83.667,60L109.667,60C116.842,60 122.667,54.175 122.667,47L122.667,21Z" style="fill:url(#_Linear1);"/>
</g>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(224,224,-224,224,16,16)"><stop offset="0" style="stop-color:rgb(255,173,77);stop-opacity:1"/><stop offset="0.58" style="stop-color:rgb(174,222,199);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(137,245,255);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

+32 -11
View File
@@ -1,5 +1,7 @@
use crate::StdError;
use chrono::Utc;
use serde::Deserialize;
use serde_dhall::StaticType;
use serde_dhall::{SimpleType, StaticType};
use std::collections::HashMap;
use std::error::Error;
use std::fmt;
@@ -24,7 +26,11 @@ impl fmt::Display for Action {
}
}
#[derive(Deserialize, StaticType, Debug)]
// Newtype wrapper around a Vec of actions.
// serde(transparent) and the imp StaticType below ensures we ignore the outer struct and
// transparently deserialize into the inner vec.
#[derive(Deserialize, Debug)]
#[serde(transparent)]
pub struct Actions(Vec<Action>);
impl Actions {
@@ -40,6 +46,12 @@ impl fmt::Display for Actions {
}
}
impl StaticType for Actions {
fn static_type() -> SimpleType {
SimpleType::List(Box::new(Action::static_type()))
}
}
#[derive(Deserialize, StaticType, Debug)]
pub enum Mapping {
NOP, // Do nothing.
@@ -87,16 +99,25 @@ pub struct Config {
impl Config {
pub fn from_file(p: &Path) -> Result<Self, Box<dyn Error>> {
match serde_dhall::from_file(p)
.with_builtin_type("Mapping".to_string(), Mapping::static_type())
.with_builtin_type("Action".to_string(), Action::static_type())
serde_dhall::from_file(p)
.parse::<Self>()
{
Ok(c) => Ok(c),
Err(e) => {
println!("{}", e);
Err(Box::new(e))
.map_err(|e| e.into())
}
}
pub fn generate_prelude() -> StdError<()> {
let mut m = HashMap::new();
m.insert("Action".to_string(), Action::static_type());
m.insert("Mapping".to_string(), Mapping::static_type());
println!(
"-- Sampad Dhall types, autogenerated by git#{} on {}",
option_env!("VERSION").unwrap_or("unknown"),
Utc::now(),
);
println!(
"{{ Action = {}, Mapping = {} }}",
Action::static_type(),
Mapping::static_type()
);
Ok(())
}
}
+17 -3
View File
@@ -5,11 +5,14 @@ use config::{Action, Config, Mapping};
use hidapi::HidApi;
use rumqttc::{Client, MqttOptions, QoS};
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::path::Path;
use std::thread;
use tracing::{event, Level};
type StdError<T> = Result<T, Box<dyn Error>>;
struct State<'a> {
mqtt_servers: HashMap<String, Client>,
conf: &'a Config,
@@ -107,7 +110,19 @@ impl<'a> State<'a> {
}
}
fn main() -> Result<(), Box<dyn Error>> {
fn main() -> StdError<()> {
let args: Vec<_> = env::args().collect();
if let [prog, args @ ..] = &args[..] {
if args == ["generate-dhall"] {
return Config::generate_prelude();
} else if args.len() > 0 {
eprintln!("Usage: {} [generate-dhall]", prog);
return Err("Invalid usage".into());
}
} else {
unreachable!();
}
tracing_subscriber::fmt::init();
event!(Level::INFO, "Starting...");
let conf = Config::from_file(Path::new("./config.dhall"))?;
@@ -120,8 +135,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let device = device::get_devices(&hid, true)
.get(0)
.expect("No device found")
.open_device(&hid)
.expect("Couldn't open device");
.open_device(&hid)?;
let pad = device::ButtonPad::new(&device);
for ev in pad {
+22
View File
@@ -0,0 +1,22 @@
-- Sampad Dhall types, autogenerated by git#3065040 on 2022-07-12 12:53:11.933270598 UTC
{ Action =
< ActivateLayer : Text
| MQTTPub : { payload : Text, topic : Text }
| Print : Text
>
, Mapping =
< NOP
| Passthrough
| Trigger :
< ActivateLayer : Text
| MQTTPub : { payload : Text, topic : Text }
| Print : Text
>
| TriggerMulti :
List
< ActivateLayer : Text
| MQTTPub : { payload : Text, topic : Text }
| Print : Text
>
>
}