umshctl/command/
duty.rs

1//! `duty`: report or bound the combined duty-cycle budget.
2//!
3//! The limit spans every radio client on the device — host transmits,
4//! delegated acks, and the on-board node's own traffic all draw from one
5//! ledger — and `PROP_PHY_DUTY_NOW` reports that combined figure.
6
7use anyhow::{Result, anyhow};
8
9use umsh::ulcp_wire::ids::prop;
10
11use super::values::DutyLimitArg;
12use super::{decode_u16, duty_percent, persist};
13use crate::App;
14
15#[derive(Debug, clap::Subcommand)]
16pub enum DutyOp {
17    /// Print current usage and the limit in force.
18    Show,
19    /// Set the limit on its raw 0-65535 scale (655 ≈ 1% of the hour),
20    /// or `off` to stop enforcing one.
21    Limit {
22        #[arg(value_name = "N|off")]
23        value: DutyLimitArg,
24    },
25}
26
27pub async fn run(app: &mut App, op: Option<DutyOp>) -> Result<()> {
28    let no_save = app.no_save;
29    let device = app.device()?;
30    match op.unwrap_or(DutyOp::Show) {
31        DutyOp::Show => {
32            let now = device.get_prop(prop::PHY_DUTY_NOW).await?;
33            let now = decode_u16(&now).ok_or_else(|| anyhow!("malformed PHY_DUTY_NOW"))?;
34            let limit = device.get_prop(prop::PHY_DUTY_LIMIT).await?;
35            println!("duty now   {now} ({:.2}% of the hour)", duty_percent(now));
36            print_limit(decode_u16(&limit).ok_or_else(|| anyhow!("malformed PHY_DUTY_LIMIT"))?);
37            Ok(())
38        }
39        DutyOp::Limit { value } => {
40            let echoed = device
41                .set_prop(prop::PHY_DUTY_LIMIT, &value.0.to_le_bytes())
42                .await?;
43            print_limit(
44                decode_u16(&echoed).ok_or_else(|| anyhow!("malformed PHY_DUTY_LIMIT echo"))?,
45            );
46            persist(device, no_save).await
47        }
48    }
49}
50
51fn print_limit(raw: u16) {
52    match raw {
53        u16::MAX => println!("duty limit off (enforcement disabled)"),
54        raw => println!("duty limit {raw} ({:.2}% of the hour)", duty_percent(raw)),
55    }
56}