Skip to main content

unifly_api/model/
device.rs

1// ── Device domain types ──
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use std::net::IpAddr;
6
7use super::common::{Bandwidth, DataSource, EntityOrigin};
8use super::entity_id::{EntityId, MacAddress};
9
10/// Canonical device type -- normalized from both API surfaces.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12#[non_exhaustive]
13pub enum DeviceType {
14    Gateway,
15    Switch,
16    AccessPoint,
17    Other,
18}
19
20/// Device operational state.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
22#[non_exhaustive]
23pub enum DeviceState {
24    Online,
25    Offline,
26    PendingAdoption,
27    Updating,
28    GettingReady,
29    Adopting,
30    Deleting,
31    ConnectionInterrupted,
32    Isolated,
33    Unknown,
34}
35
36impl DeviceState {
37    pub fn is_online(&self) -> bool {
38        matches!(self, Self::Online)
39    }
40
41    pub fn is_transitional(&self) -> bool {
42        matches!(
43            self,
44            Self::Updating | Self::GettingReady | Self::Adopting | Self::PendingAdoption
45        )
46    }
47}
48
49/// Port on a switch or gateway.
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct Port {
52    pub index: u32,
53    pub name: Option<String>,
54    pub state: PortState,
55    pub speed_mbps: Option<u32>,
56    pub max_speed_mbps: Option<u32>,
57    pub connector: Option<PortConnector>,
58    pub poe: Option<PoeInfo>,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
62pub enum PortState {
63    Up,
64    Down,
65    Unknown,
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
69pub enum PortConnector {
70    Rj45,
71    Sfp,
72    SfpPlus,
73    Sfp28,
74    Qsfp28,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct PoeInfo {
79    pub standard: Option<String>,
80    pub enabled: bool,
81    pub state: PortState,
82}
83
84/// Radio on an access point.
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct Radio {
87    pub frequency_ghz: f32,
88    pub channel: Option<u32>,
89    pub channel_width_mhz: Option<u32>,
90    pub wlan_standard: Option<String>,
91    pub tx_retries_pct: Option<f64>,
92    pub channel_utilization_pct: Option<f64>,
93}
94
95/// Real-time device statistics.
96#[derive(Debug, Clone, Default, Serialize, Deserialize)]
97pub struct DeviceStats {
98    pub uptime_secs: Option<u64>,
99    pub cpu_utilization_pct: Option<f64>,
100    pub memory_utilization_pct: Option<f64>,
101    pub load_average_1m: Option<f64>,
102    pub load_average_5m: Option<f64>,
103    pub load_average_15m: Option<f64>,
104    pub uplink_bandwidth: Option<Bandwidth>,
105    pub last_heartbeat: Option<DateTime<Utc>>,
106    pub next_heartbeat: Option<DateTime<Utc>>,
107}
108
109/// The canonical Device type. Merges data from Integration + Session API.
110#[derive(Debug, Clone, Serialize, Deserialize)]
111#[allow(clippy::struct_excessive_bools)]
112pub struct Device {
113    pub id: EntityId,
114    pub mac: MacAddress,
115    pub ip: Option<IpAddr>,
116    pub wan_ipv6: Option<String>,
117    pub name: Option<String>,
118    pub model: Option<String>,
119    pub device_type: DeviceType,
120    pub state: DeviceState,
121
122    // Firmware
123    pub firmware_version: Option<String>,
124    pub firmware_updatable: bool,
125
126    // Lifecycle
127    pub adopted_at: Option<DateTime<Utc>>,
128    pub provisioned_at: Option<DateTime<Utc>>,
129    pub last_seen: Option<DateTime<Utc>>,
130
131    // Hardware
132    pub serial: Option<String>,
133    pub supported: bool,
134
135    // Interfaces
136    pub ports: Vec<Port>,
137    pub radios: Vec<Radio>,
138
139    // Uplink
140    pub uplink_device_id: Option<EntityId>,
141    pub uplink_device_mac: Option<MacAddress>,
142
143    // Features (from Integration API)
144    pub has_switching: bool,
145    pub has_access_point: bool,
146
147    // Real-time stats (populated from statistics endpoint or WebSocket)
148    pub stats: DeviceStats,
149
150    // Client count (if known)
151    pub client_count: Option<u32>,
152
153    // Metadata
154    pub origin: Option<EntityOrigin>,
155
156    #[serde(skip)]
157    #[allow(dead_code)]
158    pub(crate) source: DataSource,
159    #[serde(skip)]
160    #[allow(dead_code)]
161    pub(crate) updated_at: DateTime<Utc>,
162}