Skip to main content

huawei_dongle_api/models/
monitoring.rs

1//! Monitoring models for connection status and signal information
2
3use super::enums::{ConnectionStatus, NetworkType, RoamingStatus, ServiceStatus, SimStatus};
4use serde::{Deserialize, Serialize};
5
6/// Connection status response from `/api/monitoring/status`.
7///
8/// Contains comprehensive information about the device's current state including
9/// connection status, network type, signal strength, and service availability.
10///
11/// # Example
12///
13/// ```no_run
14/// # use huawei_dongle_api::{Client, Config};
15/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
16/// let client = Client::new(Config::default())?;
17/// let status = client.monitoring().status().await?;
18///
19/// if status.is_connected() {
20///     println!("Connected to {}", status.network_type_text());
21///     println!("Signal: {}/5", status.signal_level().unwrap_or(0));
22/// }
23/// # Ok(())
24/// # }
25/// ```
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(rename = "response")]
28pub struct MonitoringStatus {
29    #[serde(rename = "ConnectionStatus")]
30    pub connection_status: ConnectionStatus,
31
32    #[serde(rename = "WifiConnectionStatus")]
33    pub wifi_connection_status: Option<String>,
34
35    #[serde(rename = "SignalStrength")]
36    pub signal_strength: Option<String>,
37
38    #[serde(rename = "SignalIcon")]
39    pub signal_icon: Option<String>,
40
41    #[serde(rename = "CurrentNetworkType")]
42    pub current_network_type: NetworkType,
43
44    #[serde(rename = "CurrentServiceDomain")]
45    pub current_service_domain: Option<String>,
46
47    #[serde(rename = "RoamingStatus")]
48    pub roaming_status: RoamingStatus,
49
50    #[serde(rename = "BatteryStatus")]
51    pub battery_status: Option<String>,
52
53    #[serde(rename = "BatteryLevel")]
54    pub battery_level: Option<String>,
55
56    #[serde(rename = "BatteryPercent")]
57    pub battery_percent: Option<String>,
58
59    #[serde(rename = "simlockStatus")]
60    pub simlock_status: String,
61
62    #[serde(rename = "PrimaryDns")]
63    pub primary_dns: Option<String>,
64
65    #[serde(rename = "SecondaryDns")]
66    pub secondary_dns: Option<String>,
67
68    #[serde(rename = "wififrequence")]
69    pub wifi_frequency: Option<String>,
70
71    #[serde(rename = "flymode")]
72    pub fly_mode: String,
73
74    #[serde(rename = "PrimaryIPv6Dns")]
75    pub primary_ipv6_dns: Option<String>,
76
77    #[serde(rename = "SecondaryIPv6Dns")]
78    pub secondary_ipv6_dns: Option<String>,
79
80    #[serde(rename = "CurrentWifiUser")]
81    pub current_wifi_user: Option<String>,
82
83    #[serde(rename = "TotalWifiUser")]
84    pub total_wifi_user: Option<String>,
85
86    #[serde(rename = "currenttotalwifiuser")]
87    pub current_total_wifi_user: String,
88
89    #[serde(rename = "ServiceStatus")]
90    pub service_status: ServiceStatus,
91
92    #[serde(rename = "SimStatus")]
93    pub sim_status: SimStatus,
94
95    #[serde(rename = "WifiStatus")]
96    pub wifi_status: Option<String>,
97
98    #[serde(rename = "CurrentNetworkTypeEx")]
99    pub current_network_type_ex: Option<NetworkType>,
100
101    #[serde(rename = "maxsignal")]
102    pub max_signal: String,
103
104    #[serde(rename = "wifiindooronly")]
105    pub wifi_indoor_only: String,
106
107    #[serde(rename = "classify")]
108    pub classify: Option<String>,
109
110    #[serde(rename = "usbup")]
111    pub usb_up: String,
112
113    #[serde(rename = "wifiswitchstatus")]
114    pub wifi_switch_status: String,
115
116    #[serde(rename = "WifiStatusExCustom")]
117    pub wifi_status_ex_custom: Option<String>,
118
119    #[serde(rename = "hvdcp_online")]
120    pub hvdcp_online: Option<String>,
121
122    #[serde(rename = "speedLimitStatus")]
123    pub speed_limit_status: Option<String>,
124
125    #[serde(rename = "poorSignalStatus")]
126    pub poor_signal_status: Option<String>,
127}
128
129impl MonitoringStatus {
130    pub fn is_connected(&self) -> bool {
131        self.connection_status.is_connected()
132    }
133
134    /// Get connection status as human-readable string
135    pub fn connection_status_text(&self) -> String {
136        self.connection_status.to_string()
137    }
138
139    /// Get network type as human-readable string
140    pub fn network_type_text(&self) -> String {
141        self.current_network_type.to_string()
142    }
143
144    /// Get extended network type as human-readable string
145    pub fn network_type_ex_text(&self) -> String {
146        match &self.current_network_type_ex {
147            Some(network_type) => network_type.extended_text().to_string(),
148            None => "N/A".to_string(),
149        }
150    }
151
152    pub fn is_sim_ready(&self) -> bool {
153        self.sim_status.is_ready()
154    }
155
156    pub fn is_roaming(&self) -> bool {
157        self.roaming_status.is_roaming()
158    }
159
160    /// Get signal strength level (0-5)
161    pub fn signal_level(&self) -> Option<u8> {
162        self.signal_icon.as_ref().and_then(|s| s.parse().ok())
163    }
164
165    /// Get signal strength as percentage (0-100%)
166    pub fn signal_percentage(&self) -> Option<u8> {
167        self.signal_level().map(|level| match level {
168            0 => 0,
169            1 => 20,
170            2 => 40,
171            3 => 60,
172            4 => 80,
173            5 => 100,
174            _ => 0,
175        })
176    }
177
178    pub fn is_service_available(&self) -> bool {
179        self.service_status.is_available()
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186
187    #[test]
188    fn test_connection_status_parsing() {
189        let status = MonitoringStatus {
190            connection_status: ConnectionStatus::Connected,
191            current_network_type: NetworkType::Lte,
192            signal_icon: Some("5".to_string()),
193            sim_status: SimStatus::Ready,
194            roaming_status: RoamingStatus::NotRoaming,
195            service_status: ServiceStatus::FullService,
196            wifi_connection_status: None,
197            signal_strength: None,
198            current_service_domain: None,
199            battery_status: None,
200            battery_level: None,
201            battery_percent: None,
202            simlock_status: "0".to_string(),
203            primary_dns: None,
204            secondary_dns: None,
205            wifi_frequency: None,
206            fly_mode: "0".to_string(),
207            primary_ipv6_dns: None,
208            secondary_ipv6_dns: None,
209            current_wifi_user: None,
210            total_wifi_user: None,
211            current_total_wifi_user: "0".to_string(),
212            wifi_status: None,
213            current_network_type_ex: Some(NetworkType::FiveGNsa),
214            max_signal: "5".to_string(),
215            wifi_indoor_only: "0".to_string(),
216            classify: Some("hilink".to_string()),
217            usb_up: "0".to_string(),
218            wifi_switch_status: "0".to_string(),
219            wifi_status_ex_custom: None,
220            hvdcp_online: None,
221            speed_limit_status: None,
222            poor_signal_status: None,
223        };
224
225        assert_eq!(status.connection_status, ConnectionStatus::Connected);
226        assert_eq!(status.connection_status_text(), "CONNECTED");
227        assert_eq!(status.network_type_text(), "LTE (4G)");
228        assert_eq!(status.network_type_ex_text(), "5G Non-Standalone");
229        assert!(status.is_connected());
230        assert!(status.is_sim_ready());
231        assert!(!status.is_roaming());
232        assert_eq!(status.signal_level(), Some(5));
233        assert_eq!(status.signal_percentage(), Some(100));
234        assert!(status.is_service_available());
235    }
236}