1use 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#[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#[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#[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#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
89#[serde(rename_all = "lowercase")]
90pub enum PortMode {
91 Access,
93 Trunk,
95 Mirror,
97 Unknown,
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
103#[serde(rename_all = "lowercase")]
104pub enum StpState {
105 Disabled,
106 Blocking,
107 Listening,
108 Learning,
109 Forwarding,
110 Broken,
111 Unknown,
112}
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
116#[serde(rename_all = "lowercase")]
117pub enum PoeMode {
118 Auto,
120 Off,
122 Passive24V,
124 Passthrough,
126 Other,
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
134#[serde(rename_all = "lowercase")]
135pub enum PortSpeedSetting {
136 Auto,
137 Mbps10,
138 Mbps100,
139 Mbps1000,
140 Mbps2500,
141 Mbps5000,
142 Mbps10000,
143}
144
145impl PortSpeedSetting {
146 pub fn as_mbps(self) -> Option<u32> {
151 match self {
152 Self::Auto => None,
153 Self::Mbps10 => Some(10),
154 Self::Mbps100 => Some(100),
155 Self::Mbps1000 => Some(1000),
156 Self::Mbps2500 => Some(2500),
157 Self::Mbps5000 => Some(5000),
158 Self::Mbps10000 => Some(10000),
159 }
160 }
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct PortProfile {
167 pub index: u32,
169 pub name: Option<String>,
171 pub link_state: PortState,
173 pub mode: PortMode,
175 pub native_network_id: Option<String>,
177 pub native_vlan_id: Option<u16>,
179 pub native_network_name: Option<String>,
181 pub tagged_network_ids: Vec<String>,
183 pub tagged_vlan_ids: Vec<u16>,
185 pub tagged_network_names: Vec<String>,
187 pub tagged_all: bool,
189 pub poe_mode: Option<PoeMode>,
191 pub speed_setting: Option<PortSpeedSetting>,
193 pub link_speed_mbps: Option<u32>,
195 pub stp_state: StpState,
197 pub port_profile_id: Option<String>,
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct Radio {
204 pub frequency_ghz: f32,
205 pub channel: Option<u32>,
206 pub channel_width_mhz: Option<u32>,
207 pub wlan_standard: Option<String>,
208 pub tx_retries_pct: Option<f64>,
209 pub channel_utilization_pct: Option<f64>,
210}
211
212#[derive(Debug, Clone, Default, Serialize, Deserialize)]
214pub struct DeviceStats {
215 pub uptime_secs: Option<u64>,
216 pub cpu_utilization_pct: Option<f64>,
217 pub memory_utilization_pct: Option<f64>,
218 pub load_average_1m: Option<f64>,
219 pub load_average_5m: Option<f64>,
220 pub load_average_15m: Option<f64>,
221 pub uplink_bandwidth: Option<Bandwidth>,
222 pub last_heartbeat: Option<DateTime<Utc>>,
223 pub next_heartbeat: Option<DateTime<Utc>>,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
228#[allow(clippy::struct_excessive_bools)]
229pub struct Device {
230 pub id: EntityId,
231 pub mac: MacAddress,
232 pub ip: Option<IpAddr>,
233 pub wan_ipv6: Option<String>,
234 pub name: Option<String>,
235 pub model: Option<String>,
236 pub device_type: DeviceType,
237 pub state: DeviceState,
238
239 pub firmware_version: Option<String>,
241 pub firmware_updatable: bool,
242
243 pub adopted_at: Option<DateTime<Utc>>,
245 pub provisioned_at: Option<DateTime<Utc>>,
246 pub last_seen: Option<DateTime<Utc>>,
247
248 pub serial: Option<String>,
250 pub supported: bool,
251
252 pub ports: Vec<Port>,
254 pub radios: Vec<Radio>,
255
256 pub uplink_device_id: Option<EntityId>,
258 pub uplink_device_mac: Option<MacAddress>,
259 pub uplink_port_idx: Option<u32>,
263
264 pub has_switching: bool,
266 pub has_access_point: bool,
267
268 pub stats: DeviceStats,
270
271 pub client_count: Option<u32>,
273
274 pub origin: Option<EntityOrigin>,
276
277 #[serde(skip)]
278 #[allow(dead_code)]
279 pub(crate) source: DataSource,
280 #[serde(skip)]
281 #[allow(dead_code)]
282 pub(crate) updated_at: DateTime<Utc>,
283}