Add support for running commands (#33)

This commit is contained in:
Rajasekharan Vengalil 2022-08-08 19:55:47 +05:30 committed by GitHub
parent 35d40d3111
commit 821414d9cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 8 deletions

View file

@ -26,6 +26,7 @@ default = []
ssl = ["rustls", "rustls/dangerous_configuration", "webpki", "webpki-roots"] ssl = ["rustls", "rustls/dangerous_configuration", "webpki", "webpki-roots"]
async = ["tokio"] async = ["tokio"]
async-ssl = ["async", "tokio-rustls", "ssl"] async-ssl = ["async", "tokio-rustls", "ssl"]
write = []
# a feature gate for examples # a feature gate for examples
async-rt = ["async", "tokio/rt-multi-thread", "tokio/macros"] async-rt = ["async", "tokio/rt-multi-thread", "tokio/macros"]

View file

@ -18,6 +18,9 @@ pub enum Command<'a> {
NetworkVersion, NetworkVersion,
/// Queries the server version. /// Queries the server version.
Version, Version,
#[cfg(feature = "write")]
/// Run a command. Allow for on additional optional param.
Run(&'a str, Option<&'a str>),
/// Gracefully shuts down the connection. /// Gracefully shuts down the connection.
Logout, Logout,
} }
@ -33,6 +36,8 @@ impl<'a> Command<'a> {
Self::StartTLS => "STARTTLS", Self::StartTLS => "STARTTLS",
Self::NetworkVersion => "NETVER", Self::NetworkVersion => "NETVER",
Self::Version => "VER", Self::Version => "VER",
#[cfg(feature = "write")]
Self::Run(_, _) => "INSTCMD",
Self::Logout => "LOGOUT", Self::Logout => "LOGOUT",
} }
} }
@ -44,6 +49,10 @@ impl<'a> Command<'a> {
Self::SetUsername(username) => vec![username], Self::SetUsername(username) => vec![username],
Self::SetPassword(password) => vec![password], Self::SetPassword(password) => vec![password],
Self::List(query) => query.to_vec(), Self::List(query) => query.to_vec(),
#[cfg(feature = "write")]
Self::Run(cmd, param) => param
.map(|param| vec![*cmd, param])
.unwrap_or_else(|| vec![cmd]),
_ => Vec::new(), _ => Vec::new(),
} }
} }
@ -826,7 +835,7 @@ implement_simple_commands! {
pub fn get_network_version() -> String { pub fn get_network_version() -> String {
( (
{ Command::NetworkVersion }, { Command::NetworkVersion },
{ |row: String| Ok(row) }, { Ok },
) )
} }
@ -834,7 +843,7 @@ implement_simple_commands! {
pub fn get_server_version() -> String { pub fn get_server_version() -> String {
( (
{ Command::Version }, { Command::Version },
{ |row: String| Ok(row) }, { Ok },
) )
} }
} }
@ -855,3 +864,31 @@ implement_action_commands! {
Command::Logout Command::Logout
} }
} }
#[cfg(feature = "write")]
impl crate::blocking::Connection {
/// Runs a command on the UPS.
pub fn run_command(&mut self, cmd: &str, param: Option<&str>) -> crate::Result<()> {
match self {
Self::Tcp(conn) => {
conn.write_cmd(Command::Run(cmd, param))?;
conn.read_response()?.expect_ok()?;
Ok(())
}
}
}
}
#[cfg(all(feature = "write", feature = "async"))]
impl crate::tokio::Connection {
/// Runs a command on the UPS.
pub async fn run_command(&mut self, cmd: &str, param: Option<&str>) -> crate::Result<()> {
match self {
Self::Tcp(conn) => {
conn.write_cmd(Command::Run(cmd, param)).await?;
conn.read_response().await?.expect_ok()?;
Ok(())
}
}
}
}

View file

@ -213,6 +213,9 @@ macro_rules! impl_sentences {
/// 2. the decoded sentence /// 2. the decoded sentence
/// ///
/// ``` /// ```
/// # #[macro_use] extern crate rups;
/// # fn main() {
/// # #[cfg(test)]
/// test_encode_decode!( /// test_encode_decode!(
/// ["GET", "VAR", "nutdev", "test.var"] <=> /// ["GET", "VAR", "nutdev", "test.var"] <=>
/// Sentences::QueryVar { /// Sentences::QueryVar {
@ -220,6 +223,7 @@ macro_rules! impl_sentences {
/// var_name: "test.var".into(), /// var_name: "test.var".into(),
/// } /// }
/// ); /// );
/// # }
/// ``` /// ```
#[allow(unused_macros)] #[allow(unused_macros)]
macro_rules! test_encode_decode { macro_rules! test_encode_decode {

View file

@ -5,7 +5,7 @@ use std::time::Duration;
/// Well-known variable keys for NUT UPS devices. /// Well-known variable keys for NUT UPS devices.
/// ///
/// List retrieved from: https://networkupstools.org/docs/user-manual.chunked/apcs01.html /// List retrieved from: <https://networkupstools.org/docs/user-manual.chunked/apcs01.html>
pub mod key { pub mod key {
/// Device model. /// Device model.
pub const DEVICE_MODEL: &str = "device.model"; pub const DEVICE_MODEL: &str = "device.model";
@ -31,7 +31,7 @@ pub mod key {
/// Well-known variables for NUT UPS devices. /// Well-known variables for NUT UPS devices.
/// ///
/// List retrieved from: https://networkupstools.org/docs/user-manual.chunked/apcs01.html /// List retrieved from: <https://networkupstools.org/docs/user-manual.chunked/apcs01.html>
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub enum Variable { pub enum Variable {
/// Device model. /// Device model.
@ -196,10 +196,8 @@ impl TryFrom<&str> for VariableType {
other => { other => {
if other.starts_with("STRING:") { if other.starts_with("STRING:") {
let size = other let size = other
.splitn(2, ':') .split_once(':')
.nth(1) .and_then(|(_, s)| s.parse().ok())
.map(|s| s.parse().ok())
.flatten()
.ok_or_else(|| crate::ClientError::generic("Invalid STRING definition"))?; .ok_or_else(|| crate::ClientError::generic("Invalid STRING definition"))?;
Ok(Self::String(size)) Ok(Self::String(size))
} else { } else {