use crate::integration_types;
use crate::model::common::DataSource;
use crate::model::entity_id::EntityId;
use crate::model::wifi::{WifiBroadcast, WifiBroadcastType, WifiSecurityMode};
use super::helpers::{extra_bool, extra_frequencies, origin_from_metadata};
impl From<integration_types::WifiBroadcastResponse> for WifiBroadcast {
fn from(w: integration_types::WifiBroadcastResponse) -> Self {
let broadcast_type = match w.broadcast_type.as_str() {
"IOT_OPTIMIZED" => WifiBroadcastType::IotOptimized,
_ => WifiBroadcastType::Standard,
};
let security = w
.security_configuration
.get("type")
.or_else(|| w.security_configuration.get("mode"))
.and_then(|v| v.as_str())
.map_or(WifiSecurityMode::Open, |mode| match mode {
"WPA2_PERSONAL" => WifiSecurityMode::Wpa2Personal,
"WPA3_PERSONAL" => WifiSecurityMode::Wpa3Personal,
"WPA2_WPA3_PERSONAL" => WifiSecurityMode::Wpa2Wpa3Personal,
"WPA2_ENTERPRISE" => WifiSecurityMode::Wpa2Enterprise,
"WPA3_ENTERPRISE" => WifiSecurityMode::Wpa3Enterprise,
"WPA2_WPA3_ENTERPRISE" => WifiSecurityMode::Wpa2Wpa3Enterprise,
_ => WifiSecurityMode::Open,
});
WifiBroadcast {
id: EntityId::Uuid(w.id),
name: w.name,
enabled: w.enabled,
broadcast_type,
security,
network_id: w
.network
.as_ref()
.and_then(|v| v.get("networkId").or_else(|| v.get("id")))
.and_then(|v| v.as_str())
.and_then(|s| uuid::Uuid::parse_str(s).ok())
.map(EntityId::Uuid),
frequencies_ghz: extra_frequencies(&w.extra, "broadcastingFrequenciesGHz"),
hidden: extra_bool(&w.extra, "hideName"),
client_isolation: extra_bool(&w.extra, "clientIsolationEnabled"),
band_steering: extra_bool(&w.extra, "bandSteeringEnabled"),
mlo_enabled: extra_bool(&w.extra, "mloEnabled"),
fast_roaming: extra_bool(&w.extra, "bssTransitionEnabled"),
hotspot_enabled: w.extra.contains_key("hotspotConfiguration"),
origin: origin_from_metadata(&w.metadata),
source: DataSource::IntegrationApi,
}
}
}
impl From<integration_types::WifiBroadcastDetailsResponse> for WifiBroadcast {
fn from(w: integration_types::WifiBroadcastDetailsResponse) -> Self {
let overview = integration_types::WifiBroadcastResponse {
id: w.id,
name: w.name,
broadcast_type: w.broadcast_type,
enabled: w.enabled,
security_configuration: w.security_configuration,
metadata: w.metadata,
network: w.network,
broadcasting_device_filter: w.broadcasting_device_filter,
extra: w.extra,
};
Self::from(overview)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
use serde_json::json;
#[test]
fn integration_wifi_broadcast_preserves_standard_fields() {
let response = integration_types::WifiBroadcastResponse {
id: uuid::Uuid::nil(),
name: "Main".into(),
broadcast_type: "STANDARD".into(),
enabled: true,
security_configuration: json!({"mode": "WPA2_PERSONAL"}),
metadata: json!({"origin": "USER"}),
network: Some(json!({"id": uuid::Uuid::nil().to_string()})),
broadcasting_device_filter: None,
extra: HashMap::from([
("broadcastingFrequenciesGHz".into(), json!([2.4, 5.0])),
("hideName".into(), json!(true)),
("clientIsolationEnabled".into(), json!(true)),
("bandSteeringEnabled".into(), json!(true)),
("mloEnabled".into(), json!(false)),
("bssTransitionEnabled".into(), json!(true)),
(
"hotspotConfiguration".into(),
json!({"type": "CAPTIVE_PORTAL"}),
),
]),
};
let wifi = WifiBroadcast::from(response);
assert_eq!(wifi.frequencies_ghz.len(), 2);
assert!((wifi.frequencies_ghz[0] - 2.4).abs() < f32::EPSILON);
assert!((wifi.frequencies_ghz[1] - 5.0).abs() < f32::EPSILON);
assert!(wifi.hidden);
assert!(wifi.client_isolation);
assert!(wifi.band_steering);
assert!(wifi.fast_roaming);
assert!(wifi.hotspot_enabled);
}
}