mirror of
https://github.com/aramperes/nut-rs.git
synced 2025-09-09 05:28:31 -04:00
parent
ff77c1bdbd
commit
1e3481e18d
4 changed files with 1450 additions and 0 deletions
|
@ -12,6 +12,12 @@ pub use var::*;
|
||||||
|
|
||||||
/// Blocking client implementation for NUT.
|
/// Blocking client implementation for NUT.
|
||||||
pub mod blocking;
|
pub mod blocking;
|
||||||
|
/// NUT protocol implementation (v1.2).
|
||||||
|
///
|
||||||
|
/// Reference: <https://networkupstools.org/docs/developer-guide.chunked/ar01s09.html>
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[macro_use]
|
||||||
|
pub mod proto;
|
||||||
/// Async client implementation for NUT, using Tokio.
|
/// Async client implementation for NUT, using Tokio.
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
pub mod tokio;
|
pub mod tokio;
|
||||||
|
|
666
rups/src/proto/client.rs
Normal file
666
rups/src/proto/client.rs
Normal file
|
@ -0,0 +1,666 @@
|
||||||
|
use crate::proto::impl_sentences;
|
||||||
|
|
||||||
|
impl_sentences! {
|
||||||
|
/// A generic successful response with no additional data.
|
||||||
|
GenericOk (
|
||||||
|
{
|
||||||
|
0: Ok,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Forced shut down (FSD) successful.
|
||||||
|
FsdOk (
|
||||||
|
{
|
||||||
|
0: Ok,
|
||||||
|
1: FsdSet,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Server acknowledges TLS upgrade.
|
||||||
|
StartTLSOk (
|
||||||
|
{
|
||||||
|
0: Ok,
|
||||||
|
1: StartTLS,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Server confirms logout.
|
||||||
|
LogoutOk (
|
||||||
|
{
|
||||||
|
0: Ok,
|
||||||
|
1: Goodbye,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Server returns an error.
|
||||||
|
RespondErr (
|
||||||
|
{
|
||||||
|
0: Err,
|
||||||
|
1: Arg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The error code.
|
||||||
|
1: message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// Extra information about the error.
|
||||||
|
2...: extras
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the number of prior logins to the given `ups_name` device.
|
||||||
|
RespondNumLogins (
|
||||||
|
{
|
||||||
|
0: NumLogins,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The number of logins to the UPS device.
|
||||||
|
2: num_logins,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the description of the UPS device.
|
||||||
|
RespondUpsDesc (
|
||||||
|
{
|
||||||
|
0: UpsDesc,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The description of the UPS device.
|
||||||
|
2: description,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the value of the given `var_name` variable for the UPS device.
|
||||||
|
RespondVar (
|
||||||
|
{
|
||||||
|
0: Var,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
2: var_name,
|
||||||
|
/// The current value of the variable.
|
||||||
|
3: value,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the type of the given `var_name` variable for the UPS device.
|
||||||
|
RespondType (
|
||||||
|
{
|
||||||
|
0: Type,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
2: var_name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The variable definition (RW, ENUN, STRING...)
|
||||||
|
3...: var_types
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the description of the given `var_name` variable for the UPS device.
|
||||||
|
RespondDesc (
|
||||||
|
{
|
||||||
|
0: Desc,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
2: var_name,
|
||||||
|
/// The description of the variable.
|
||||||
|
3: description,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the description of the given `cmd_name` command for the UPS device.
|
||||||
|
RespondCmdDesc (
|
||||||
|
{
|
||||||
|
0: CmdDesc,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the command.
|
||||||
|
2: cmd_name,
|
||||||
|
/// The description of the command.
|
||||||
|
3: description,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the name and description of a UPS device.
|
||||||
|
RespondUps (
|
||||||
|
{
|
||||||
|
0: Ups,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the command.
|
||||||
|
2: description,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the name and description of a mutable variable.
|
||||||
|
RespondRw (
|
||||||
|
{
|
||||||
|
0: Rw,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
2: var_name,
|
||||||
|
/// The current value of the variable.
|
||||||
|
3: value,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with the name of a command.
|
||||||
|
RespondCmd (
|
||||||
|
{
|
||||||
|
0: Cmd,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the command.
|
||||||
|
2: cmd_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with a possible value of an enumerable variable.
|
||||||
|
RespondEnum (
|
||||||
|
{
|
||||||
|
0: Enum,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
2: var_name,
|
||||||
|
/// A possible value of the variable.
|
||||||
|
3: enum_value,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with a possible range of an numeric variable.
|
||||||
|
RespondRange (
|
||||||
|
{
|
||||||
|
0: Range,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: Arg,
|
||||||
|
5: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
2: var_name,
|
||||||
|
/// The minimum value of the range.
|
||||||
|
3: min_value,
|
||||||
|
/// The maximum value of the range.
|
||||||
|
4: max_value,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server responds with a client connected to a UPS device.
|
||||||
|
RespondClient (
|
||||||
|
{
|
||||||
|
0: Client,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The IP address of the client.
|
||||||
|
2: client_ip,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server begins returning a list of UPS devices.
|
||||||
|
BeginListUps (
|
||||||
|
{
|
||||||
|
0: Begin,
|
||||||
|
1: List,
|
||||||
|
2: Ups,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Server ends returning a list of UPS devices.
|
||||||
|
EndListUps (
|
||||||
|
{
|
||||||
|
0: End,
|
||||||
|
1: List,
|
||||||
|
2: Ups,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Server begins returning a list of variables for a UPS device.
|
||||||
|
BeginListVar (
|
||||||
|
{
|
||||||
|
0: Begin,
|
||||||
|
1: List,
|
||||||
|
2: Var,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server ends returning a list of variables for a UPS device.
|
||||||
|
EndListVar (
|
||||||
|
{
|
||||||
|
0: End,
|
||||||
|
1: List,
|
||||||
|
2: Var,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server begins returning a list of mutable variables for a UPS device.
|
||||||
|
BeginListRw (
|
||||||
|
{
|
||||||
|
0: Begin,
|
||||||
|
1: List,
|
||||||
|
2: Rw,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server ends returning a list of mutable variables for a UPS device.
|
||||||
|
EndListRw (
|
||||||
|
{
|
||||||
|
0: End,
|
||||||
|
1: List,
|
||||||
|
2: Rw,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server begins returning a list of commands for a UPS device.
|
||||||
|
BeginListCmd (
|
||||||
|
{
|
||||||
|
0: Begin,
|
||||||
|
1: List,
|
||||||
|
2: Cmd,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server ends returning a list of commands for a UPS device.
|
||||||
|
EndListCmd (
|
||||||
|
{
|
||||||
|
0: End,
|
||||||
|
1: List,
|
||||||
|
2: Cmd,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server begins returning a list of possible values for an enumerable variable.
|
||||||
|
BeginListEnum (
|
||||||
|
{
|
||||||
|
0: Begin,
|
||||||
|
1: List,
|
||||||
|
2: Enum,
|
||||||
|
3: Arg,
|
||||||
|
4: Arg,
|
||||||
|
5: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
4: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server ends returning a list of possible values for an enumerable variable.
|
||||||
|
EndListEnum (
|
||||||
|
{
|
||||||
|
0: End,
|
||||||
|
1: List,
|
||||||
|
2: Enum,
|
||||||
|
3: Arg,
|
||||||
|
4: Arg,
|
||||||
|
5: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
4: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server begins returning a list of possible ranges for an enumerable variable.
|
||||||
|
BeginListRange (
|
||||||
|
{
|
||||||
|
0: Begin,
|
||||||
|
1: List,
|
||||||
|
2: Range,
|
||||||
|
3: Arg,
|
||||||
|
4: Arg,
|
||||||
|
5: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
4: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server ends returning a list of possible ranges for an enumerable variable.
|
||||||
|
EndListRange (
|
||||||
|
{
|
||||||
|
0: End,
|
||||||
|
1: List,
|
||||||
|
2: Range,
|
||||||
|
3: Arg,
|
||||||
|
4: Arg,
|
||||||
|
5: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
4: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server begins returning a list of clients for a UPS device.
|
||||||
|
BeginListClient (
|
||||||
|
{
|
||||||
|
0: Begin,
|
||||||
|
1: List,
|
||||||
|
2: Client,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Server ends returning a list of clients for a UPS device.
|
||||||
|
EndListClient (
|
||||||
|
{
|
||||||
|
0: End,
|
||||||
|
1: List,
|
||||||
|
2: Client,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
3: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::proto::test_encode_decode;
|
||||||
|
|
||||||
|
use super::Sentences;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encode_decode() {
|
||||||
|
test_encode_decode!(
|
||||||
|
["OK"] <=>
|
||||||
|
Sentences::GenericOk {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["OK", "FSD-SET"] <=>
|
||||||
|
Sentences::FsdOk {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["OK", "STARTTLS"] <=>
|
||||||
|
Sentences::StartTLSOk {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["OK", "Goodbye"] <=>
|
||||||
|
Sentences::LogoutOk {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["ERR", "ACCESS-DENIED"] <=>
|
||||||
|
Sentences::RespondErr {
|
||||||
|
message: "ACCESS-DENIED".into(),
|
||||||
|
extras: vec![],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["ERR", "ACCESS-DENIED", "extra1", "extra2"] <=>
|
||||||
|
Sentences::RespondErr {
|
||||||
|
message: "ACCESS-DENIED".into(),
|
||||||
|
extras: vec!["extra1".into(), "extra2".into()],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["NUMLOGINS", "nutdev", "42"] <=>
|
||||||
|
Sentences::RespondNumLogins {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
num_logins: "42".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["UPSDESC", "nutdev", "Development box"] <=>
|
||||||
|
Sentences::RespondUpsDesc {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
description: "Development box".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["VAR", "nutdev", "ups.status", "OL"] <=>
|
||||||
|
Sentences::RespondVar {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "ups.status".into(),
|
||||||
|
value: "OL".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["TYPE", "nutdev", "input.transfer.low", "ENUM", "RW"] <=>
|
||||||
|
Sentences::RespondType {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "input.transfer.low".into(),
|
||||||
|
var_types: vec!["ENUM".into(), "RW".into()],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["DESC", "nutdev", "ups.status", "UPS status"] <=>
|
||||||
|
Sentences::RespondDesc {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "ups.status".into(),
|
||||||
|
description: "UPS status".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["CMDDESC", "nutdev", "load.on", "Turn on the load immediately"] <=>
|
||||||
|
Sentences::RespondCmdDesc {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
cmd_name: "load.on".into(),
|
||||||
|
description: "Turn on the load immediately".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["UPS", "nutdev", "Development box"] <=>
|
||||||
|
Sentences::RespondUps {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
description: "Development box".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["RW", "nutdev", "ups.mfr", "APC"] <=>
|
||||||
|
Sentences::RespondRw {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "ups.mfr".into(),
|
||||||
|
value: "APC".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["CMD", "nutdev", "do.something"] <=>
|
||||||
|
Sentences::RespondCmd {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
cmd_name: "do.something".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["ENUM", "nutdev", "input.transfer.low", "103"] <=>
|
||||||
|
Sentences::RespondEnum {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "input.transfer.low".into(),
|
||||||
|
enum_value: "103".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["RANGE", "nutdev", "input.transfer.low", "90", "100"] <=>
|
||||||
|
Sentences::RespondRange {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "input.transfer.low".into(),
|
||||||
|
min_value: "90".into(),
|
||||||
|
max_value: "100".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["CLIENT", "nutdev", "127.0.0.1"] <=>
|
||||||
|
Sentences::RespondClient {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
client_ip: "127.0.0.1".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["BEGIN", "LIST", "VAR", "nutdev"] <=>
|
||||||
|
Sentences::BeginListVar {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["END", "LIST", "VAR", "nutdev"] <=>
|
||||||
|
Sentences::EndListVar {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["BEGIN", "LIST", "RW", "nutdev"] <=>
|
||||||
|
Sentences::BeginListRw {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["END", "LIST", "RW", "nutdev"] <=>
|
||||||
|
Sentences::EndListRw {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["BEGIN", "LIST", "CMD", "nutdev"] <=>
|
||||||
|
Sentences::BeginListCmd {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["END", "LIST", "CMD", "nutdev"] <=>
|
||||||
|
Sentences::EndListCmd {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["BEGIN", "LIST", "ENUM", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::BeginListEnum {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["END", "LIST", "ENUM", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::EndListEnum {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["BEGIN", "LIST", "RANGE", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::BeginListRange {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["END", "LIST", "RANGE", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::EndListRange {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["BEGIN", "LIST", "CLIENT", "nutdev"] <=>
|
||||||
|
Sentences::BeginListClient {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["END", "LIST", "CLIENT", "nutdev"] <=>
|
||||||
|
Sentences::EndListClient {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
306
rups/src/proto/mod.rs
Normal file
306
rups/src/proto/mod.rs
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
/// Client-bound protocol implementation.
|
||||||
|
///
|
||||||
|
/// "Client-bound" implies commands RECEIVED and DECODED by the client. The server implementation
|
||||||
|
/// must use the same messages to ENCODE and SEND.
|
||||||
|
pub mod client;
|
||||||
|
/// Server-bound protocol implementation.
|
||||||
|
///
|
||||||
|
/// "Server-bound" implies commands RECEIVED and DECODED by the server. The client implementation
|
||||||
|
/// must use the same messages to ENCODE and SEND.
|
||||||
|
pub mod server;
|
||||||
|
|
||||||
|
/// Macro that implements the list of "words" in the NUT network protocol.
|
||||||
|
macro_rules! impl_words {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
$(#[$attr:meta])+
|
||||||
|
$name:ident($word:tt),
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub(crate) enum Word {
|
||||||
|
/// A string argument.
|
||||||
|
Arg,
|
||||||
|
/// End-of-line.
|
||||||
|
EOL,
|
||||||
|
$(
|
||||||
|
/// Protocol word.
|
||||||
|
$(#[$attr])*
|
||||||
|
#[allow(dead_code)]
|
||||||
|
$name,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Word {
|
||||||
|
/// Matches a raw string into the corresponding word.
|
||||||
|
/// Passing `None` will always return `EOL`. Passing an unrecognized
|
||||||
|
/// string returns `None`.
|
||||||
|
pub(crate) fn decode(raw: Option<&str>) -> Option<Self> {
|
||||||
|
if let Some(raw) = raw {
|
||||||
|
match raw {
|
||||||
|
$($word => Some(Self::$name),)*
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(Self::EOL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decodes a sequence of words.
|
||||||
|
/// Unrecognized words will be `None`
|
||||||
|
/// Returns a `Vec` of the same length as the given slice.
|
||||||
|
pub(crate) fn decode_words<T: AsRef<str>>(raw: &[T]) -> Vec<Option<Self>> {
|
||||||
|
let mut words = Vec::new();
|
||||||
|
for r in raw.iter() {
|
||||||
|
words.push(Self::decode(Some(r.as_ref())));
|
||||||
|
}
|
||||||
|
words.push(Some(Self::EOL));
|
||||||
|
words
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes a `Word` into a string.
|
||||||
|
/// This function cannot encode `Arg` or `EOL` (either returns `None`).
|
||||||
|
pub(crate) fn encode(&self) -> Option<&str> {
|
||||||
|
match self {
|
||||||
|
Self::Arg | Self::EOL => None,
|
||||||
|
$(Self::$name => Some($word),)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the `Word` matches another.
|
||||||
|
pub(crate) fn matches(&self, other: Option<&Option<Self>>) -> bool {
|
||||||
|
if let Some(other) = other {
|
||||||
|
if self == &Word::Arg {
|
||||||
|
true
|
||||||
|
} else if let Some(other) = other {
|
||||||
|
self == other
|
||||||
|
} else {
|
||||||
|
self == &Word::EOL
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the `Word` matches all words in the vec, starting at the given index.
|
||||||
|
pub(crate) fn matches_until_end(&self, start: usize, others: &[Option<Self>]) -> bool {
|
||||||
|
for i in start..others.len() {
|
||||||
|
if i == others.len() {
|
||||||
|
return others[i] == Some(Self::EOL);
|
||||||
|
}
|
||||||
|
if !self.matches(others.get(i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements the list of sentences, which are combinations
|
||||||
|
/// of words that form commands (serverbound) and responses (clientbound).
|
||||||
|
macro_rules! impl_sentences {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
$(#[$attr:meta])+
|
||||||
|
$name:ident(
|
||||||
|
{
|
||||||
|
$($wordidx:tt: $word:ident,)*
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$(
|
||||||
|
$(#[$argattr:meta])+
|
||||||
|
$argidx:tt: $arg:ident,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
$(
|
||||||
|
,{
|
||||||
|
$(#[$varargattr:meta])+
|
||||||
|
$varargidx:tt...: $vararg:ident
|
||||||
|
}
|
||||||
|
)?
|
||||||
|
),
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
/// Protocol sentences.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub enum Sentences {
|
||||||
|
$(
|
||||||
|
$(#[$attr])*
|
||||||
|
$name {
|
||||||
|
$(
|
||||||
|
$(#[$argattr])*
|
||||||
|
$arg: String,
|
||||||
|
)*
|
||||||
|
$(
|
||||||
|
$(#[$varargattr])*
|
||||||
|
$vararg: Vec<String>,
|
||||||
|
)*
|
||||||
|
},
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sentences {
|
||||||
|
/// Decodes a sentence. Returns `None` if the pattern cannot be recognized.
|
||||||
|
pub(crate) fn decode(raw: Vec<String>) -> Option<Sentences> {
|
||||||
|
use super::{Word::*, *};
|
||||||
|
use Sentences::*;
|
||||||
|
let words = Word::decode_words(raw.as_slice());
|
||||||
|
|
||||||
|
$(
|
||||||
|
if true
|
||||||
|
$(&& $word.matches(words.get($wordidx)))*
|
||||||
|
$(&& Arg.matches_until_end($varargidx, &words))*
|
||||||
|
{
|
||||||
|
return Some($name {
|
||||||
|
$($arg: raw[$argidx].to_owned(),)*
|
||||||
|
$($vararg: raw[$varargidx..].to_owned(),)*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes the sentence.
|
||||||
|
pub(crate) fn encode(&self) -> Vec<&str> {
|
||||||
|
use super::Word::*;
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
Self::$name {
|
||||||
|
$($arg,)*
|
||||||
|
$($vararg,)*
|
||||||
|
} => {
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut words = vec![
|
||||||
|
$(
|
||||||
|
$word.encode(),
|
||||||
|
)*
|
||||||
|
];
|
||||||
|
|
||||||
|
$(
|
||||||
|
words[$argidx] = Some($arg);
|
||||||
|
)*
|
||||||
|
|
||||||
|
$(
|
||||||
|
for vararg in $vararg {
|
||||||
|
words.push(Some(vararg));
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
words
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro that asserts the encoding and decoding of a valid sentence.
|
||||||
|
///
|
||||||
|
/// The two arguments, separated by `<=>`, are:
|
||||||
|
/// 1. the encoded sentence, e.g. `["GET", "VAR", "nutdev", "test.var"]`
|
||||||
|
/// 2. the decoded sentence
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// test_encode_decode!(
|
||||||
|
/// ["GET", "VAR", "nutdev", "test.var"] <=>
|
||||||
|
/// Sentences::QueryVar {
|
||||||
|
/// ups_name: "nutdev".into(),
|
||||||
|
/// var_name: "test.var".into(),
|
||||||
|
/// }
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! test_encode_decode {
|
||||||
|
([$($word:expr$(,)?)+] <=> $expected:expr) => {
|
||||||
|
assert_eq!(
|
||||||
|
Sentences::decode(vec![
|
||||||
|
$(String::from($word),)*
|
||||||
|
]),
|
||||||
|
Some($expected)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
vec![
|
||||||
|
$(String::from($word),)*
|
||||||
|
],
|
||||||
|
$expected.encode()
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_words! {
|
||||||
|
/// Begins a `LIST`.
|
||||||
|
Begin("BEGIN"),
|
||||||
|
/// Describes a client connected to a UPS.
|
||||||
|
Client("CLIENT"),
|
||||||
|
/// Represents an executable command.
|
||||||
|
Cmd("CMD"),
|
||||||
|
/// Describes a command (`CMD`).
|
||||||
|
CmdDesc("CMDDESC"),
|
||||||
|
/// Describes a variable (`VAR` or `RW`).
|
||||||
|
Desc("DESC"),
|
||||||
|
/// Ends a block of sentences.
|
||||||
|
End("END"),
|
||||||
|
/// An enumerable type.
|
||||||
|
Enum("ENUM"),
|
||||||
|
/// An error response.
|
||||||
|
Err("ERR"),
|
||||||
|
/// Executes a forced shut down (FSD).
|
||||||
|
Fsd("FSD"),
|
||||||
|
/// Server confirms forced shut down (FSD).
|
||||||
|
FsdSet("FSD-SET"),
|
||||||
|
/// Serverbound query.
|
||||||
|
Get("GET"),
|
||||||
|
/// Server confirms logout (this is lower-case on purpose).
|
||||||
|
Goodbye("Goodbye"),
|
||||||
|
/// Client requesting a list of commands supported by the server.
|
||||||
|
Help("HELP"),
|
||||||
|
/// Executes an instant command.
|
||||||
|
InstCmd("INSTCMD"),
|
||||||
|
/// Queries or describes a list.
|
||||||
|
List("LIST"),
|
||||||
|
/// Client requests login to a UPS device.
|
||||||
|
Login("LOGIN"),
|
||||||
|
/// Client logs out.
|
||||||
|
Logout("LOGOUT"),
|
||||||
|
/// Client verifying it has master-level access to the UPS device.
|
||||||
|
Master("MASTER"),
|
||||||
|
/// Client requests the network version.
|
||||||
|
NetworkVersion("NETVER"),
|
||||||
|
/// Represents the amount of logins to a UPS device.
|
||||||
|
NumLogins("NUMLOGINS"),
|
||||||
|
/// Clientbound response for a good outcome.
|
||||||
|
Ok("OK"),
|
||||||
|
/// Client setting password.
|
||||||
|
Password("PASSWORD"),
|
||||||
|
/// Represents a range of numerical values.
|
||||||
|
Range("RANGE"),
|
||||||
|
/// Represents a mutable variable.
|
||||||
|
Rw("RW"),
|
||||||
|
/// Client requests to set the value of a mutable variable.
|
||||||
|
Set("SET"),
|
||||||
|
/// Client requests the connection be upgraded to TLS.
|
||||||
|
StartTLS("STARTTLS"),
|
||||||
|
/// Represents the type of a variable.
|
||||||
|
Type("TYPE"),
|
||||||
|
/// Represents a UPS device.
|
||||||
|
Ups("UPS"),
|
||||||
|
/// Represents the description of a UPS device.
|
||||||
|
UpsDesc("UPSDESC"),
|
||||||
|
/// Client setting username.
|
||||||
|
Username("USERNAME"),
|
||||||
|
/// Represents a variable.
|
||||||
|
Var("VAR"),
|
||||||
|
/// Client requests the server version.
|
||||||
|
Version("VERSION"),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use impl_sentences;
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) use test_encode_decode;
|
472
rups/src/proto/server.rs
Normal file
472
rups/src/proto/server.rs
Normal file
|
@ -0,0 +1,472 @@
|
||||||
|
use crate::proto::impl_sentences;
|
||||||
|
|
||||||
|
impl_sentences! {
|
||||||
|
/// Client requests the number of prior logins to the given `ups_name` device.
|
||||||
|
QueryNumLogins (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: NumLogins,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the description of the given `ups_name` device.
|
||||||
|
QueryUpsDesc (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: UpsDesc,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the value of the given `var_name` variable in the given `ups_name` device.
|
||||||
|
QueryVar (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: Var,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the type of the given `var_name` variable in the given `ups_name` device.
|
||||||
|
QueryType (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: Type,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the description of the given `var_name` variable in the given `ups_name` device.
|
||||||
|
QueryDesc (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: Desc,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the description of the given `cmd_name` command in the given `ups_name` device.
|
||||||
|
QueryCmdDesc (
|
||||||
|
{
|
||||||
|
0: Get,
|
||||||
|
1: CmdDesc,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the command.
|
||||||
|
3: cmd_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of variables for the given `ups_name` device.
|
||||||
|
QueryListVar (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Var,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of mutable variables for the given `ups_name` device.
|
||||||
|
QueryListRw (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Rw,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of commands for the given `ups_name` device.
|
||||||
|
QueryListCmd (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Cmd,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of possible values of the enumerable variable `var_name`
|
||||||
|
/// for the given `ups_name` device.
|
||||||
|
QueryListEnum (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Enum,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of possible ranges of the numerical variable `var_name`
|
||||||
|
/// for the given `ups_name` device.
|
||||||
|
QueryListRange (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Range,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the list of clients connected to the given `ups_name` device.
|
||||||
|
QueryListClient (
|
||||||
|
{
|
||||||
|
0: List,
|
||||||
|
1: Client,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests to set the value `value` of the `var_name` variable on the `ups_name` device.
|
||||||
|
ExecSetVar (
|
||||||
|
{
|
||||||
|
0: Set,
|
||||||
|
1: Var,
|
||||||
|
2: Arg,
|
||||||
|
3: Arg,
|
||||||
|
4: Arg,
|
||||||
|
5: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
2: ups_name,
|
||||||
|
/// The name of the variable.
|
||||||
|
3: var_name,
|
||||||
|
/// The new value of the variable.
|
||||||
|
4: value,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the execution of an instant command `cmd_name` on the `ups_name` device.
|
||||||
|
ExecInstCmd (
|
||||||
|
{
|
||||||
|
0: InstCmd,
|
||||||
|
1: Arg,
|
||||||
|
2: Arg,
|
||||||
|
3: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
/// The name of the command.
|
||||||
|
2: cmd_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client logs-out of the current UPS device.
|
||||||
|
ExecLogout (
|
||||||
|
{
|
||||||
|
0: Logout,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client logs-into the given `ups_name` device.
|
||||||
|
ExecLogin (
|
||||||
|
{
|
||||||
|
0: Login,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client asserts master-level access to the `ups_name` device.
|
||||||
|
ExecMaster (
|
||||||
|
{
|
||||||
|
0: Master,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the forced shut-down of the `ups_name` device.
|
||||||
|
ExecForcedShutDown (
|
||||||
|
{
|
||||||
|
0: Fsd,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The name of the UPS device.
|
||||||
|
1: ups_name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client sets the password on the connection.
|
||||||
|
SetPassword (
|
||||||
|
{
|
||||||
|
0: Password,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The password to set.
|
||||||
|
1: password,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client sets the username on the connection.
|
||||||
|
SetUsername (
|
||||||
|
{
|
||||||
|
0: Username,
|
||||||
|
1: Arg,
|
||||||
|
2: EOL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// The username to set.
|
||||||
|
1: username,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/// Client requests the connection be upgraded to TLS.
|
||||||
|
ExecStartTLS (
|
||||||
|
{
|
||||||
|
0: StartTLS,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client requests the list of commands supported by the server.
|
||||||
|
QueryHelp (
|
||||||
|
{
|
||||||
|
0: Help,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client requests the server version.
|
||||||
|
QueryVersion (
|
||||||
|
{
|
||||||
|
0: Version,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
/// Client requests the network version.
|
||||||
|
QueryNetworkVersion (
|
||||||
|
{
|
||||||
|
0: NetworkVersion,
|
||||||
|
1: EOL,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::Sentences;
|
||||||
|
use crate::proto::test_encode_decode;
|
||||||
|
#[test]
|
||||||
|
fn test_encode_decode() {
|
||||||
|
test_encode_decode!(
|
||||||
|
["GET", "NUMLOGINS", "nutdev"] <=>
|
||||||
|
Sentences::QueryNumLogins {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["GET", "NUMLOGINS", "nutdev"] <=>
|
||||||
|
Sentences::QueryNumLogins {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["GET", "UPSDESC", "nutdev"] <=>
|
||||||
|
Sentences::QueryUpsDesc {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["GET", "VAR", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::QueryVar {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["GET", "TYPE", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::QueryType {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["GET", "DESC", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::QueryDesc {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["GET", "CMDDESC", "nutdev", "test.cmd"] <=>
|
||||||
|
Sentences::QueryCmdDesc {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
cmd_name: "test.cmd".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LIST", "VAR", "nutdev"] <=>
|
||||||
|
Sentences::QueryListVar {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LIST", "RW", "nutdev"] <=>
|
||||||
|
Sentences::QueryListRw {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LIST", "CMD", "nutdev"] <=>
|
||||||
|
Sentences::QueryListCmd {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LIST", "ENUM", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::QueryListEnum {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LIST", "RANGE", "nutdev", "test.var"] <=>
|
||||||
|
Sentences::QueryListRange {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LIST", "CLIENT", "nutdev"] <=>
|
||||||
|
Sentences::QueryListClient {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["SET", "VAR", "nutdev", "test.var", "something"] <=>
|
||||||
|
Sentences::ExecSetVar {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
var_name: "test.var".into(),
|
||||||
|
value: "something".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["INSTCMD", "nutdev", "test.cmd"] <=>
|
||||||
|
Sentences::ExecInstCmd {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
cmd_name: "test.cmd".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LOGOUT"] <=>
|
||||||
|
Sentences::ExecLogout {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["LOGIN", "nutdev"] <=>
|
||||||
|
Sentences::ExecLogin {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["MASTER", "nutdev"] <=>
|
||||||
|
Sentences::ExecMaster {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["FSD", "nutdev"] <=>
|
||||||
|
Sentences::ExecForcedShutDown {
|
||||||
|
ups_name: "nutdev".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["PASSWORD", "topsecret"] <=>
|
||||||
|
Sentences::SetPassword {
|
||||||
|
password: "topsecret".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["USERNAME", "john"] <=>
|
||||||
|
Sentences::SetUsername {
|
||||||
|
username: "john".into(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["STARTTLS"] <=>
|
||||||
|
Sentences::ExecStartTLS {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["HELP"] <=>
|
||||||
|
Sentences::QueryHelp {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["VERSION"] <=>
|
||||||
|
Sentences::QueryVersion {}
|
||||||
|
);
|
||||||
|
test_encode_decode!(
|
||||||
|
["NETVER"] <=>
|
||||||
|
Sentences::QueryNetworkVersion {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue