Skip to content

Commit da450a0

Browse files
committed
Implement JSON
1 parent 532d286 commit da450a0

File tree

5 files changed

+77
-9
lines changed

5 files changed

+77
-9
lines changed

Cargo.lock

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ clap = { version = "4.3", features = [ "derive" ]}
4242
log = "0.4"
4343
binary-layout = "4.0.2"
4444
chrono = "0.4.38"
45+
serde = { version = "1.0.200", default-features = false, features = ["derive"] }
46+
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

README.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,40 @@ The original C code can be found here: [ipmitool 1.8.19](https://github.com/ipmi
2121

2222
Special thanks to the library [ipmi-rs](https://github.com/datdenkikniet/ipmi-rs) that made this possible.
2323

24+
## Use
25+
26+
```text
27+
A tool to fetch the power reading with ipmi dcmi
28+
29+
Usage: ipmitool-dcmi-power-reading [OPTIONS]
30+
31+
Options:
32+
-c, --connection-uri <CONNECTION_URI>
33+
The connection URI to use [default: file:///dev/ipmi0]
34+
--timeout-ms <TIMEOUT_MS>
35+
How many milliseconds to wait before timing out while waiting for a response [default: 2000]
36+
--format <FORMAT>
37+
The format to output [default: text] [possible values: text, json]
38+
-h, --help
39+
Print help
40+
-V, --version
41+
Print version
42+
```
43+
2444
## Example (text)
2545

2646
```text
27-
Instantaneous power reading : 214 Watts
47+
Instantaneous power reading : 212 Watts
2848
Minimum during sampling period : 2 Watts
2949
Maximum during sampling period : 468 Watts
3050
Average power reading over sample period : 184 Watts
31-
IPMI timestamp : 2024-05-05 13:06:44 UTC
51+
IPMI timestamp : 2024-05-05 14:17:17 UTC
3252
Sampling period : 1000 Milliseconds
3353
Power reading state is : activated
3454
```
3555

36-
## TODO
56+
## Example (json)
3757

38-
- [ ] Document options on the README
39-
- [ ] Add JSON support
58+
```json
59+
{"grp_id":220,"curr_pwr":209,"min_sample":2,"max_sample":468,"avg_pwr":184,"time_stamp":1714918638,"sample":1000,"state":64}
60+
```

src/common.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clap::{Args, Parser};
1+
use clap::{Args, Parser, ValueEnum};
22
use ipmi_rs::{
33
connection::{
44
rmcp::{Active, Rmcp},
@@ -18,11 +18,17 @@ pub enum IpmiConnectionEnum {
1818
}
1919

2020
#[derive(Parser)]
21-
pub struct CliOpts {
21+
struct CliOpts {
2222
#[clap(flatten)]
2323
pub common: CommonOpts,
2424
}
2525

26+
#[derive(ValueEnum, Clone, Copy)]
27+
pub enum OutputFormats {
28+
Text,
29+
Json,
30+
}
31+
2632
#[derive(Args)]
2733
pub struct CommonOpts {
2834
/// The connection URI to use
@@ -31,6 +37,9 @@ pub struct CommonOpts {
3137
/// How many milliseconds to wait before timing out while waiting for a response
3238
#[clap(default_value = "2000", long)]
3339
timeout_ms: u64,
40+
/// The format to output
41+
#[clap(default_value = "text", value_enum, long)]
42+
format: OutputFormats,
3443
}
3544

3645
fn error<T>(val: T) -> std::io::Error
@@ -41,6 +50,9 @@ where
4150
}
4251

4352
impl CommonOpts {
53+
pub fn get_format(&self) -> OutputFormats {
54+
self.format
55+
}
4456
pub fn get_connection(&self) -> std::io::Result<IpmiConnectionEnum> {
4557
let timeout = Duration::from_millis(self.timeout_ms);
4658

src/main.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ use std::io::Error;
33
use binary_layout::binary_layout;
44
use chrono::{TimeZone, Utc};
55
use clap::Parser;
6-
use common::{CommonOpts, IpmiConnectionEnum};
6+
use common::{CommonOpts, IpmiConnectionEnum, OutputFormats};
77
use ipmi_rs::connection::{IpmiConnection, LogicalUnit, Message, NetFn, Request};
8+
use serde::{Deserialize, Serialize};
89

910
mod common;
1011

1112
#[derive(Parser)]
13+
#[clap(name = "ipmitool-dcmi-power-reading")]
14+
#[clap(about = "A tool to fetch the power reading with ipmi dcmi")]
15+
#[clap(author = "William Desportes <williamdes@wdes.fr>")]
16+
#[clap(version = "1.0.0")]
1217
struct Command {
1318
#[clap(flatten)]
1419
common: CommonOpts,
@@ -34,7 +39,9 @@ fn get_message() -> std::io::Result<Message> {
3439
))
3540
}
3641

42+
#[derive(Serialize, Deserialize)]
3743
pub struct PowerConsumption {
44+
#[allow(dead_code)]
3845
grp_id: u8, /* first byte: Group Extension ID */
3946
curr_pwr: u16,
4047
min_sample: u16,
@@ -134,6 +141,10 @@ pub fn ipmi_dcmi_pwr_format_text(pwr: PowerConsumption) {
134141
println!("");
135142
}
136143

144+
pub fn ipmi_dcmi_pwr_format_json(pwr: PowerConsumption) {
145+
print!("{}", serde_json::to_string(&pwr).unwrap());
146+
}
147+
137148
fn main() -> std::io::Result<()> {
138149
pretty_env_logger::formatted_builder()
139150
.parse_filters(&std::env::var("RUST_LOG").unwrap_or("info".to_string()))
@@ -142,7 +153,10 @@ fn main() -> std::io::Result<()> {
142153
let command = Command::parse();
143154
let ipmi = command.common.get_connection()?;
144155
match ipmi_dcmi_pwr_rd(ipmi) {
145-
Ok(data) => Ok(ipmi_dcmi_pwr_format_text(data)),
156+
Ok(data) => match command.common.get_format() {
157+
OutputFormats::Json => Ok(ipmi_dcmi_pwr_format_json(data)),
158+
OutputFormats::Text => Ok(ipmi_dcmi_pwr_format_text(data)),
159+
},
146160
Err(err) => Err(err),
147161
}
148162
}

0 commit comments

Comments
 (0)