Skip to main content

huawei_dongle_api/api/
network.rs

1//! Network API endpoints
2
3use crate::{
4    client::Client,
5    error::{Error, Result},
6    models::{common::Response, network::*},
7};
8use tracing::{debug, trace};
9
10/// Network API for network configuration and status
11pub struct NetworkApi<'a> {
12    client: &'a Client,
13}
14
15impl<'a> NetworkApi<'a> {
16    pub fn new(client: &'a Client) -> Self {
17        Self { client }
18    }
19
20    /// This endpoint does not require authentication.
21    /// Returns the current network mode, network bands, and LTE bands.
22    pub async fn get_mode(&self) -> Result<NetworkMode> {
23        debug!("Fetching network mode configuration");
24
25        let response = self.client.get("/api/net/net-mode").await?;
26        let text = response.text().await?;
27
28        trace!("Network mode response: {}", text);
29
30        self.client.check_xml_for_errors(&text).await?;
31
32        let mode: NetworkMode = serde_xml_rs::from_str(&text)
33            .map_err(|e| Error::generic(format!("Failed to parse network mode: {e}")))?;
34
35        debug!(
36            "Current network mode: {} ({})",
37            mode.network_mode,
38            mode.mode_text()
39        );
40        Ok(mode)
41    }
42
43    /// This endpoint requires authentication and a valid CSRF token.
44    /// **Warning**: This will temporarily disconnect the device while it reconnects.
45    pub async fn set_mode(&self, request: &NetworkModeRequest) -> Result<()> {
46        debug!(
47            "Setting network mode to: {} ({})",
48            request.network_mode,
49            NetworkMode {
50                network_mode: request.network_mode,
51                network_band: request.network_band.clone(),
52                lte_band: request.lte_band.clone(),
53            }
54            .mode_text()
55        );
56
57        let xml = serde_xml_rs::to_string(request).map_err(|e| {
58            Error::generic(format!("Failed to serialize network mode request: {e}"))
59        })?;
60
61        let response = self.client.post_xml("/api/net/net-mode", &xml).await?;
62        let text = response.text().await?;
63
64        trace!("Network mode set response: {}", text);
65
66        self.client.check_xml_for_errors(&text).await?;
67
68        let result: Response = serde_xml_rs::from_str(&text)
69            .map_err(|e| Error::generic(format!("Failed to parse network mode response: {e}")))?;
70
71        if !result.is_success() {
72            return Err(Error::api(
73                result.error_code().unwrap_or(-1),
74                result
75                    .error_message()
76                    .unwrap_or("Network mode change failed")
77                    .to_string(),
78            ));
79        }
80
81        debug!("Network mode changed successfully");
82        Ok(())
83    }
84
85    /// This endpoint does not require authentication.
86    /// Returns information about the current cellular network operator.
87    pub async fn current_plmn(&self) -> Result<CurrentPlmn> {
88        debug!("Fetching current PLMN information");
89
90        let response = self.client.get("/api/net/current-plmn").await?;
91        let text = response.text().await?;
92
93        trace!("Current PLMN response: {}", text);
94
95        self.client.check_xml_for_errors(&text).await?;
96
97        let plmn: CurrentPlmn = serde_xml_rs::from_str(&text)
98            .map_err(|e| Error::generic(format!("Failed to parse PLMN information: {e}")))?;
99
100        if let Some(name) = plmn.operator_name() {
101            debug!(
102                "Current operator: {} ({})",
103                name,
104                plmn.numeric.as_deref().unwrap_or("unknown")
105            );
106        }
107
108        Ok(plmn)
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115    use crate::config::Config;
116
117    #[test]
118    fn test_network_api_creation() {
119        let config = Config::default();
120        let client = crate::Client::new(config).unwrap();
121        let network_api = client.network();
122
123        assert_eq!(
124            std::mem::size_of_val(&network_api),
125            std::mem::size_of::<&Client>()
126        );
127    }
128}