matroskin 0.1.0

whatsminer api client lib
Documentation
//! Implement `get.system.setting` command
//!
//! This command is used to get the miner settings summary.
//!
//! - Command: [GetSystemSetting]
//! - ApiDoc: <https://apidoc.whatsminer.com/#api-System-get_system_settings>
use core::str;

use serde::Deserialize;

use crate::{
    command::{Command, CommandLevel},
    error::Result,
    permission::PermissionLevel,
};

/// This command represents the `get.system.setting` operation.
///
/// Retrieves a summary of the device's current system settings.
///
/// - ApiDoc: <https://apidoc.whatsminer.com/#api-System-get_system_settings>
///
/// # Example
/// ```rust,no_run
/// use matroskin::actor::Actor;
/// use matroskin::command::get_system_setting::GetSystemSetting;
/// use matroskin::account::Account;
/// use matroskin::password::Password;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     let addr = "10.10.10.10:4433";
///     let username = Account::Super;
///     let password = Password::Super;
///
///     let actor = Actor::new(addr, username, password);
///     actor.connect()?;
///
///     let cmd = GetSystemSetting::default();
///     let response = actor.send(cmd).await?;
///     println!("Response: {:#?}", response);
///
///     Ok(())
/// }
/// ```
#[derive(Debug, Default)]
pub struct GetSystemSetting;

/// [GetSystemSetting] Response
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct GetSystemSettingResponse {
    /// Is web panel on?
    pub web_pool: i64,
    /// TimeZone UTC
    pub timezone: String,
    /// Zone name
    pub zonename: String,
    /// Current hostname for NET
    pub hostname: String,
    /// Log upload configuration (optional, not available on all devices)
    pub log_upload: Option<GetSystemSettingsResponseLogUpload>,
    pub time_randomized: GetSystemSettingsResponseTimeRandomized,
    /// Time servers
    pub ntp_server: Vec<String>,
}
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct GetSystemSettingsResponseLogUpload {
    pub ip: String,
    pub port: String,
    pub proto: String,
}
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct GetSystemSettingsResponseTimeRandomized {
    pub start: i64,
    pub stop: i64,
}

impl Command for GetSystemSetting {
    type Response = GetSystemSettingResponse;
    const CMD_NAME: &'static str = "get.system.setting";
    const LEVEL: CommandLevel = CommandLevel::Public;
    const MINIMAL_PERMISSIONS: PermissionLevel = PermissionLevel::ReadOnly;

    fn params(&self) -> Result<Option<impl serde::Serialize>> {
        Ok(None::<()>)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    const RESPONSE_JSON: &str = r#"{"code":0,"when":1766168299,"msg":{"web-pool":1,"timezone":"CST-8","zonename":"Asia/Shanghai","hostname":"WhatsMiner","time-randomized":{"start":0,"stop":0},"ntp-server":["0.cn.pool.ntp.org","0.openwrt.pool.ntp.org","0.asia.pool.ntp.org","0.pool.ntp.org"]},"desc":"get.system.setting"}"#;

    #[test]
    fn request_no_params_no_auth() {
        let cmd = GetSystemSetting;
        let encoded = cmd.encode(None).unwrap();
        let json: serde_json::Value = serde_json::from_slice(&encoded.0).unwrap();
        assert_eq!(json["cmd"], "get.system.setting");
        assert!(json.get("param").is_none());
        assert!(json.get("token").is_none());
    }

    #[test]
    fn deserialize_response_fixture() {
        let response = GetSystemSetting::parse_response(RESPONSE_JSON.as_bytes()).unwrap();
        assert!(response.code.is_success());
        assert_eq!(response.desc, "get.system.setting");
        assert_eq!(response.when, 1766168299);
        assert_eq!(response.msg.web_pool, 1);
        assert_eq!(response.msg.timezone, "CST-8");
        assert_eq!(response.msg.zonename, "Asia/Shanghai");
        assert_eq!(response.msg.hostname, "WhatsMiner");
        assert_eq!(response.msg.time_randomized.start, 0);
        assert_eq!(response.msg.time_randomized.stop, 0);
        assert_eq!(response.msg.ntp_server.len(), 4);
        assert_eq!(response.msg.ntp_server[0], "0.cn.pool.ntp.org");
    }
}