From a55d072d7882626004bab4fb16a81e3227123fe4 Mon Sep 17 00:00:00 2001 From: Paul Lecuq Date: Thu, 9 Sep 2021 00:50:28 +0200 Subject: [PATCH] updated zabbixlaunch --- Cargo.lock | 63 +++++++++++++++++++++++++++++ Cargo.toml | 9 +++-- src/api/mod.rs | 32 --------------- src/config/mod.rs | 70 +++++++++++++++++++++++++++----- src/main.rs | 93 +++++++++---------------------------------- src/padcontrol/mod.rs | 60 ++++++++++++++++++++++++++++ src/zabbix/mod.rs | 62 +++++++++++++++++++++++++++++ 7 files changed, 267 insertions(+), 122 deletions(-) delete mode 100644 src/api/mod.rs create mode 100644 src/padcontrol/mod.rs create mode 100644 src/zabbix/mod.rs diff --git a/Cargo.lock b/Cargo.lock index eddfbf3..3d40d4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,26 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -84,6 +104,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "core-foundation" version = "0.2.3" @@ -886,6 +921,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "syn" version = "1.0.76" @@ -911,6 +952,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "time" version = "0.1.44" @@ -1024,6 +1074,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -1048,6 +1104,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "void" version = "1.0.2" @@ -1183,6 +1245,7 @@ dependencies = [ name = "zabbixlaunch" version = "0.1.0" dependencies = [ + "clap", "ctrlc", "embedded-graphics", "launchy", diff --git a/Cargo.toml b/Cargo.toml index 3376e36..4dfe8c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,10 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -launchy = { path = "launchy" } -embedded-graphics = { version = "0.7", optional = true } +clap = { version = "2.33.3" } ctrlc = "3.2.0" -serde_json = "1.0.67" +embedded-graphics = { version = "0.7", optional = true } +launchy = { path = "launchy" } +reqwest = { version = "0.11.4", features = ["blocking", "json"] } serde = { version = "1.0.130", features = ["derive"] } -reqwest = { version = "0.11.4", features = ["blocking","json"] } \ No newline at end of file +serde_json = "1.0.67" \ No newline at end of file diff --git a/src/api/mod.rs b/src/api/mod.rs deleted file mode 100644 index 7ab31e4..0000000 --- a/src/api/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -use serde_json::{json, Value}; - -pub fn query_auth_token(username: &String, password: &String) -> Value { - json!({ - "jsonrpc": "2.0", - "method": "user.login", - "params": { - "user": username, - "password": password - }, - "id": 1 - }) -} - -pub fn query_problems(token: &String, limit: Option) -> Value { - json!({ - "jsonrpc": "2.0", - "method": "problem.get", - "params": { - "output": "extend", - "selectAcknowledges": "extend", - "selectTags": "extend", - "selectSuppressionData": "extend", - "recent": "true", - "sortfield": ["eventid"], - "sortorder": "DESC", - "limit": limit.unwrap_or(10) - }, - "auth": token, - "id": 1 - }) -} \ No newline at end of file diff --git a/src/config/mod.rs b/src/config/mod.rs index 706473c..2cd258e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,27 +1,75 @@ -use std::{fs::File, io::Read}; -use std::string::String; use serde::{Deserialize, Serialize}; +use serde_json::Error; +use std::string::String; +use std::{fs::File, io::Read}; +use clap::{App, Arg, ArgMatches}; #[derive(Debug, Deserialize, Serialize)] pub struct Config { pub server: String, pub username: String, pub password: String, - pub authtoken: String, - pub limit: i8, + pub authtoken: Option, + pub limit: Option, } impl Config { - pub fn save(&self, configfile: &'static str) { + pub fn new() -> Self { + Self { + server: String::from("https://zabbix.acme.com/api_jsonrpc.php"), + username: String::from("bob"), + password: String::from("password"), + authtoken: Some(String::from("token")), + limit: Some(20i64) + } + } + + pub fn load<'a>(&mut self, configfile: &'a str) { + let fileopen: Result; + let filemeta = std::fs::metadata(configfile); + let fileexists = match filemeta { + Ok(_) => true, + Err(_err) => false, + }; + + if !fileexists { + let _a = File::create(configfile); + } + fileopen = File::open(configfile); + + let mut file = match fileopen { + Ok(f) => f, + Err(e) => { + panic!("{e}", e=e); + }, + }; + let mut contents = String::from(""); + file.read_to_string(&mut contents).unwrap(); + let parse: Result = serde_json::from_str(contents.as_str()); + let cfg = match parse { + Ok(cfg) => cfg, + Err(_e) => Config::new(), + }; + *self = cfg; + self.save(configfile); + } + + pub fn save<'a>(&self, configfile: &'a str) { let file = File::create(configfile).unwrap(); serde_json::to_writer_pretty(file, &self).unwrap(); } } -pub fn read(configfile: &'static str) -> Config { - let mut file = File::open(configfile).unwrap(); - let mut contents = String::new(); - file.read_to_string(&mut contents).unwrap(); - let config: Config = serde_json::from_str(contents.as_str()).unwrap(); - config +pub fn argparse<'a>() -> ArgMatches<'a> { + App::new("Zabbix Launch") + .version("1.0") + .author("PaulBSD ") + .about("Lights up Launchpad mini using Zabbix data") + .arg(Arg::with_name("config") + .short("c") + .long("config") + .value_name("FILE") + .help("Sets a custom config file") + .takes_value(true)) + .get_matches() } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6f11007..35eaa39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,82 +1,25 @@ -mod config; -mod api; +pub mod config; +mod padcontrol; +mod zabbix; + +use std::borrow::Borrow; + -use launchy::{self, Canvas, CanvasLayout, CanvasLayoutPoller, MsgPollingWrapper, Pad}; -use launchy::{Color}; use config::Config; -use serde_json::Value; +fn main() { + let matches = config::argparse(); + let configfile= matches.value_of("config").unwrap_or("config.json").to_owned(); -pub fn main() { - let (mut canvas, mut poller) = initpad(); - let mut cfg = config::read("config.json"); - get_zabbix_authtoken(&mut cfg); - get_zabbix_problems(&mut cfg); - clear(&mut canvas); - testinput(&mut canvas, &mut poller); -} + // init and clear the launchpad + let (mut canvas, mut poller) = padcontrol::initpad(); + let mut cfg = Config::new(); + cfg.load(&configfile); -pub fn get_zabbix_authtoken(cfg: &mut Config) { - let body = api::query_auth_token(&cfg.username, &cfg.password); - let response = reqwest::blocking::Client::new() - .post(&cfg.server) - .json(&body) - .send() - .unwrap(); + padcontrol::input(&mut canvas, &mut poller); - let values: Value = response - .json() - .unwrap(); - cfg.authtoken = values["result"].as_str().unwrap().to_string(); - //cfg.save("config.json"); -} - -fn get_zabbix_problems(cfg: &mut Config) { - let body = api::query_problems(&cfg.authtoken, Some(cfg.limit)); - let response = reqwest::blocking::Client::new() - .post(&cfg.server) - .json(&body) - .send() - .unwrap(); - - let values: Value = response - .json() - .unwrap(); - for i in values["result"].as_array().unwrap() { - println!("{}", i); - }; -} - -fn initpad() -> (CanvasLayout<'static>, CanvasLayoutPoller) { - let (mut canvas, poller) = launchy::CanvasLayout::new_polling(); - canvas.add_by_guess_rotated::(10, 18, launchy::Rotation::UpsideDown).unwrap(); - (canvas, poller) -} - -fn testinput(canvas: &mut CanvasLayout, poller: &mut CanvasLayoutPoller) { - for color in (0u64..).map(|f| Color::red_green_color(f as f32 / 60.0 / 2.5)) { - for msg in poller.iter_for_millis(17).filter(|msg| msg.is_press()) { - canvas[msg.pad()] = color; - println!("{:?}", msg.pad()) - } - let _res =canvas.flush(); - - canvas.iter().for_each(|pad| { - let surrounding_color = pad.neighbors_5().iter() - .map(|&p| canvas.get(p).unwrap_or(Color::GREEN)) - .sum::() / 5.0 / 1.05; - - canvas[pad] = canvas[pad].mix(surrounding_color, 0.4); - }); - } -} - - -fn clear(canvas: &mut CanvasLayout) { - for a in 3..11 { - for b in 10..18 { - canvas[Pad { x: a, y: b }] = Color{r: 0f32, g: 0f32, b:1f32}; - } - } - let _res =canvas.flush(); + // fetch zabbix informations + zabbix::get_zabbix_authtoken(&mut cfg); + zabbix::get_zabbix_problems(&mut cfg); + cfg.save(&configfile); } \ No newline at end of file diff --git a/src/padcontrol/mod.rs b/src/padcontrol/mod.rs new file mode 100644 index 0000000..d7d5272 --- /dev/null +++ b/src/padcontrol/mod.rs @@ -0,0 +1,60 @@ +use launchy::Color; +use launchy::{self, Canvas, CanvasLayout, CanvasLayoutPoller, MsgPollingWrapper, Pad}; + +pub fn initpad() -> (CanvasLayout<'static>, CanvasLayoutPoller) { + let (mut canvas, poller) = launchy::CanvasLayout::new_polling(); + let res = canvas + .add_by_guess_rotated::(0, 0, launchy::Rotation::None); + match res { + Ok(o) => o, + _ => panic!("Error connecting to midi device !"), + } + println!("Connected to device"); + clear(&mut canvas); + (canvas, poller) +} + +pub fn input(canvas: &mut CanvasLayout, poller: &mut CanvasLayoutPoller) { + for color in (0u64..).map(|f| Color::red_green_color(f as f32 / 60.0 / 2.5)) { + for msg in poller.iter_for_millis(17).filter(|msg| msg.is_press()) { + canvas[msg.pad()] = color; + println!("{:?}", msg.pad()) + } + let _res = canvas.flush(); + } +} + +fn _effect(canvas: &mut CanvasLayout, poller: &mut CanvasLayoutPoller) { + for color in (0u64..).map(|f| Color::red_green_color(f as f32 / 60.0 / 2.5)) { + for msg in poller.iter_for_millis(17).filter(|msg| msg.is_press()) { + canvas[msg.pad()] = color; + println!("{:?}", msg.pad()) + } + let _res = canvas.flush(); + + canvas.iter().for_each(|pad| { + let surrounding_color = pad + .neighbors_5() + .iter() + .map(|&p| canvas.get(p).unwrap_or(Color::GREEN)) + .sum::() + / 5.0 + / 1.05; + + canvas[pad] = canvas[pad].mix(surrounding_color, 0.4); + }); + } +} + +fn clear(canvas: &mut CanvasLayout) { + for a in 0..8 { + for b in 0..8 { + canvas[Pad { x: a, y: b }] = Color { + r: 0f32, + g: 0f32, + b: 1f32, + }; + } + } + let _res = canvas.flush(); +} \ No newline at end of file diff --git a/src/zabbix/mod.rs b/src/zabbix/mod.rs new file mode 100644 index 0000000..d3214c4 --- /dev/null +++ b/src/zabbix/mod.rs @@ -0,0 +1,62 @@ +use crate::config::Config; +use serde_json::{json, Value}; + +pub fn get_zabbix_authtoken(cfg: &mut Config) { + let body = query_auth_token(&cfg.username, &cfg.password); + let response = reqwest::blocking::Client::new() + .post(&cfg.server) + .json(&body) + .send() + .unwrap(); + + let values: Value = response.json().unwrap(); + cfg.authtoken = Some(values["result"].as_str().unwrap().to_string()); +} + +pub fn get_zabbix_problems(cfg: &mut Config) { + let body = query_problems(&cfg.authtoken.as_ref().unwrap_or(&String::from("")), + cfg.limit.unwrap()); + let response = reqwest::blocking::Client::new() + .post(&cfg.server) + .json(&body) + .send() + .unwrap(); + + let _values: Value = response.json().unwrap(); + // for i in values["result"].as_array().unwrap() { + // println!("{}", i); + // } +} + +pub fn query_auth_token(username: &String, + password: &String) -> Value { + json!({ + "jsonrpc": "2.0", + "method": "user.login", + "params": { + "user": username, + "password": password + }, + "id": 1 + }) +} + +pub fn query_problems(token: &String, + limit: i64) -> Value { + json!({ + "jsonrpc": "2.0", + "method": "problem.get", + "params": { + "output": "extend", + "selectAcknowledges": "extend", + "selectTags": "extend", + "selectSuppressionData": "extend", + "recent": "true", + "sortfield": ["eventid"], + "sortorder": "DESC", + "limit": limit + }, + "auth": token, + "id": 1 + }) +} \ No newline at end of file