Skip to content

Commit

Permalink
osdpctl: WIP: Add CP and PD support for running as a service
Browse files Browse the repository at this point in the history
Signed-off-by: Siddharth Chandrasekaran <[email protected]>
  • Loading branch information
sidcha committed Nov 11, 2023
1 parent 98fe5cd commit 6cc85a9
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 91 deletions.
3 changes: 3 additions & 0 deletions osdpctl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ configparser = "3.0.2"
daemonize = "0.5.0"
dirs = "5.0.1"
libosdp = { version = "0.1.2", path = "../rust" }
log = "0.4.20"
log4rs = "1.2.0"
toml = "0.8.8"
2 changes: 1 addition & 1 deletion osdpctl/config/devices/cp-multiple-pd.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ NumPd = 2

[Service]
LogLevel = INFO
LogFile = /tmp/single-cp.log
LogDir = /tmp/osdpctl
PidFile = /tmp/cp-002.pid

[PD-0]
Expand Down
2 changes: 1 addition & 1 deletion osdpctl/config/devices/cp-single-pd.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ NumPd = 1

[Service]
LogLevel = INFO
LogFile = /tmp/single-cp.log
LogDir = /tmp/osdpctl
PidFile = /tmp/cp-002.pid

[PD-0]
Expand Down
2 changes: 1 addition & 1 deletion osdpctl/config/devices/pd-0.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ KeyStore = /tmp/pd-0.key

[Service]
LogLevel = INFO
LogFile = /tmp/pd-0.log
LogDir = /tmp/osdpctl
PidFile = /tmp/pd-0.pid

[PdCapability]
Expand Down
2 changes: 1 addition & 1 deletion osdpctl/config/devices/pd-1.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Flags = EnforceSecure

[Service]
LogLevel = INFO
LogFile = /tmp/pd-0.log
LogDir = /tmp/osdpctl
PidFile = /tmp/pd-1.pid

[PdCapability]
Expand Down
3 changes: 2 additions & 1 deletion osdpctl/config/osdpctl.cfg
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
device_config_dir = ./devices
DeviceDir = ./devices
LogDir = /tmp/osdpctls
67 changes: 40 additions & 27 deletions osdpctl/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
use configparser::ini::Ini;
use libosdp::{
channel::{unix_channel::UnixChannel, OsdpChannel},
common::{OsdpFlag, PdCapability, PdId, PdInfo},
};
use std::{
fmt::Write,
path::{Path, PathBuf},
str::FromStr,
fmt::Write
};
use configparser::ini::Ini;
use libosdp::{
common::{
OsdpFlag, PdId, PdCapability, PdInfo
},
channel::{
unix_channel::UnixChannel, OsdpChannel
}
};

type Result<T> = anyhow::Result<T, anyhow::Error>;

pub struct AppConfig {
pub device_config_dir: PathBuf
pub device_config_dir: PathBuf,
}

impl AppConfig {
Expand All @@ -29,8 +25,8 @@ impl AppConfig {
});
}
let mut config = Ini::new();
let _ = config.load(cfg).unwrap();
let s = config.get("default", "device_config_dir").unwrap();
config.load(cfg).map_err(|e| anyhow::anyhow!(e))?;
let s = config.get("default", "DeviceDir").unwrap();
let device_config_dir = if s.starts_with("./") {
let mut path = PathBuf::from(cfg);
path.pop();
Expand All @@ -51,15 +47,13 @@ fn vec_to_array<T, const N: usize>(v: Vec<T>) -> [T; N] {
}

pub struct KeyStore {
store: PathBuf
store: PathBuf,
}

impl KeyStore {
pub fn from_path(path: &str) -> Self {
let store = PathBuf::from_str(path).unwrap();
Self {
store,
}
Self { store }
}

pub fn decode_hex(&self, s: &str) -> anyhow::Result<Vec<u8>, std::num::ParseIntError> {
Expand Down Expand Up @@ -102,14 +96,14 @@ pub struct PdData {
channel: String,
address: i32,
pub key_store: KeyStore,
flags: OsdpFlag
flags: OsdpFlag,
}

pub struct CpConfig {
pub name: String,
pd_data: Vec<PdData>,
pub pid_file: PathBuf,
pub log_file: PathBuf,
pub log_dir: PathBuf,
pub log_level: String,
}

Expand All @@ -129,9 +123,15 @@ impl CpConfig {
});
}
let pid_file = PathBuf::from_str(&config.get("Service", "PidFile").unwrap())?;
let log_file = PathBuf::from_str(&config.get("Service", "LogFile").unwrap())?;
let log_dir = PathBuf::from_str(&config.get("Service", "LogDir").unwrap())?;
let log_level = config.get("Service", "LogLevel").unwrap();
Ok(Self { name, pd_data, pid_file, log_level, log_file })
Ok(Self {
name,
pd_data,
pid_file,
log_level,
log_dir,
})
}

pub fn pd_info(&self) -> Result<Vec<PdInfo>> {
Expand All @@ -155,7 +155,7 @@ impl CpConfig {
}

pub struct PdConfig {
name: String,
pub name: String,
channel: String,
address: i32,
pub key_store: KeyStore,
Expand All @@ -164,7 +164,7 @@ pub struct PdConfig {
flags: OsdpFlag,
pub pid_file: PathBuf,
pub log_level: String,
pub log_file: PathBuf,
pub log_dir: PathBuf,
}

impl PdConfig {
Expand All @@ -174,7 +174,7 @@ impl PdConfig {
model: config.getuint("PdId", "Model").unwrap().unwrap() as i32,
vendor_code: config.getuint("PdId", "VendorCode").unwrap().unwrap() as u32,
serial_number: config.getuint("PdId", "SerialNumber").unwrap().unwrap() as u32,
firmware_version: config.getuint("PdId", "FirmwareVersion").unwrap().unwrap() as u32
firmware_version: config.getuint("PdId", "FirmwareVersion").unwrap().unwrap() as u32,
};
let mut flags = OsdpFlag::empty();
if let Some(val) = config.get("default", "Flags") {
Expand All @@ -191,12 +191,25 @@ impl PdConfig {
let cap_map = map.get("PdCapability").unwrap();
let mut pd_cap = Vec::new();
for (key, val) in cap_map {
pd_cap.push(PdCapability::from_str(format!("{}:{}", key, val.as_deref().unwrap()).as_str())?);
pd_cap.push(PdCapability::from_str(
format!("{}:{}", key, val.as_deref().unwrap()).as_str(),
)?);
}
let pid_file = PathBuf::from_str(&config.get("Service", "PidFile").unwrap())?;
let log_file = PathBuf::from_str(&config.get("Service", "LogFile").unwrap())?;
let log_dir = PathBuf::from_str(&config.get("Service", "LogDir").unwrap())?;
let log_level = config.get("Service", "LogLevel").unwrap();
Ok(Self { name, channel, address, key_store, pd_id, pd_cap, flags, pid_file, log_level, log_file })
Ok(Self {
name,
channel,
address,
key_store,
pd_id,
pd_cap,
flags,
pid_file,
log_level,
log_dir,
})
}

pub fn pd_info(&self) -> Result<PdInfo> {
Expand Down
42 changes: 24 additions & 18 deletions osdpctl/src/cp.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::{fs::File, thread, time::Duration};
use daemonize::Daemonize;
use libosdp::{
cp::ControlPanel, events::OsdpEvent
};
use crate::config::CpConfig;
use daemonize::Daemonize;
use libosdp::{cp::ControlPanel, events::OsdpEvent};
use std::{fs::File, thread, time::Duration};

type Result<T> = anyhow::Result<T, anyhow::Error>;

Expand All @@ -18,25 +16,33 @@ impl CpDaemon {
cp.set_event_callback(|pd, event| {
match event {
OsdpEvent::CardRead(e) => {
println!("Event: PD-{pd} {:?}", e);
},
log::info!("Event: PD-{pd} {:?}", e);
}
OsdpEvent::KeyPress(e) => {
println!("Event: PD-{pd} {:?}", e);
},
log::info!("Event: PD-{pd} {:?}", e);
}
OsdpEvent::MfgReply(e) => {
println!("Event: PD-{pd} {:?}", e);
},
log::info!("Event: PD-{pd} {:?}", e);
}
OsdpEvent::IO(e) => {
println!("Event: PD-{pd} {:?}", e);
},
log::info!("Event: PD-{pd} {:?}", e);
}
OsdpEvent::Status(e) => {
println!("Event: PD-{pd} {:?}", e);
},
log::info!("Event: PD-{pd} {:?}", e);
}
}
0
});
let stdout = File::create("/tmp/daemon.out").unwrap();
let stderr = File::create("/tmp/daemon.err").unwrap();
let stdout = File::create(
dev.log_dir
.as_path()
.join(format!("pd-{}.out.log", &dev.name).as_str()),
)?;
let stderr = File::create(
dev.log_dir
.as_path()
.join(format!("pd-{}.err.log", &dev.name).as_str()),
)?;
let daemon = Daemonize::new()
.pid_file(&dev.pid_file)
.chown_pid_file(true)
Expand All @@ -56,4 +62,4 @@ impl CpDaemon {
thread::sleep(Duration::from_millis(50));
}
}
}
}
40 changes: 25 additions & 15 deletions osdpctl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ mod config;
mod cp;
mod pd;

use std::{
path::PathBuf,
collections::HashMap,
};
use std::{collections::HashMap, path::PathBuf};

use clap::{arg, Command};
use config::{AppConfig, DeviceConfig};
use cp::CpDaemon;
use log4rs::{
append::console::ConsoleAppender,
config::{Appender, Root},
Config,
};
use pd::PdDaemon;

type Result<T> = anyhow::Result<T, anyhow::Error>;
Expand All @@ -20,10 +22,7 @@ fn cli() -> Command {
.subcommand_required(true)
.arg_required_else_help(true)
.allow_external_subcommands(true)
.subcommand(
Command::new("list")
.about("List configured OSDP devices")
)
.subcommand(Command::new("list").about("List configured OSDP devices"))
.subcommand(
Command::new("start")
.about("Start a OSDP device")
Expand All @@ -50,7 +49,8 @@ fn osdpctl_config_dir() -> Result<PathBuf> {
cfg_dir = std::fs::canonicalize(&dir)?;
} else {
cfg_dir = dirs::config_dir()
.or_else(|| Some(PathBuf::from("/tmp/.config/"))).unwrap();
.or_else(|| Some(PathBuf::from("/tmp/.config/")))
.unwrap();
cfg_dir.push("osdp");
if !cfg_dir.is_dir() {
std::fs::create_dir_all(&cfg_dir)?;
Expand All @@ -60,6 +60,13 @@ fn osdpctl_config_dir() -> Result<PathBuf> {
}

fn main() -> Result<()> {
let stdout = ConsoleAppender::builder().build();
let log_level = log::LevelFilter::Info;
let config = Config::builder()
.appender(Appender::builder().build("stdout", Box::new(stdout)))
.build(Root::builder().appender("stdout").build(log_level))?;
let _ = log4rs::init_config(config).unwrap();

let cfg_dir = osdpctl_config_dir()?;
let config = AppConfig::from(&cfg_dir.join("osdpctl.cfg"))?;

Expand All @@ -82,30 +89,33 @@ fn main() -> Result<()> {
}
}
Some(("start", sub_matches)) => {
let name = sub_matches.get_one::<String>("DEV")
let name = sub_matches
.get_one::<String>("DEV")
.expect("device name is required");
if let Some(dev) = device_map.get(name) {
match dev {
DeviceConfig::CpConfig(c) => {
let mut daemon = CpDaemon::new(c)?;
daemon.run();
},
}
DeviceConfig::PdConfig(c) => {
let mut daemon = PdDaemon::new(c)?;
daemon.run();
},
}
};
}
}
Some(("stop", sub_matches)) => {
let name = sub_matches.get_one::<String>("DEV")
let name = sub_matches
.get_one::<String>("DEV")
.expect("device name is required");
if let Some(dev) = device_map.get(name) {
println!("stop: {}", dev.name());
}
}
Some(("attach", sub_matches)) => {
let name = sub_matches.get_one::<String>("DEV")
let name = sub_matches
.get_one::<String>("DEV")
.expect("device name is required");
if let Some(dev) = device_map.get(name) {
println!("attach: {}", dev.name());
Expand All @@ -114,4 +124,4 @@ fn main() -> Result<()> {
_ => unreachable!(),
}
Ok(())
}
}
Loading

0 comments on commit 6cc85a9

Please sign in to comment.