1use serde::{Deserialize,Serialize};
18use serde_json::{Map,Value};
19
20#[derive(Debug,Clone,Serialize,Deserialize)]
22pub struct MistDeviceUpDowns {
23 #[serde(skip_serializing_if = "Option::is_none")]
25 pub ap : Option<String>,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub ap_name : Option<String>,
29 pub device_name : String,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub device_type : Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub ev_type : Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub ext_ip : Option<String>,
40 pub mac : String,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub reason : Option<String>,
45 pub org_id : String,
47 pub site_id : String,
49 pub site_name : String,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub text : Option<String>,
54 pub timestamp : i64,
56 pub r#type : String,
58}
59
60#[derive(Debug,Clone,Serialize,Deserialize)]
62pub struct MistDeviceEvents {
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub ap : Option<String>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub ap_name : Option<String>,
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub audit_id : Option<String>,
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub band : Option<String>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub bandwidth : Option<u16>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub channel : Option<u16>,
81 pub device_name : String,
83 pub device_type : String,
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub ev_type : Option<String>,
88 pub mac : String,
90 pub org_id : String,
92 #[serde(skip_serializing_if = "Option::is_none")]
94 pub power : Option<u16>,
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub pre_bandwidth : Option<u16>,
98 #[serde(skip_serializing_if = "Option::is_none")]
100 pub pre_channel : Option<u16>,
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub pre_power : Option<u16>,
104 #[serde(skip_serializing_if = "Option::is_none")]
106 pub pre_usage : Option<u16>,
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub reason : Option<String>,
110 pub site_id : String,
112 pub site_name : String,
114 #[serde(skip_serializing_if = "Option::is_none")]
116 pub text : Option<String>,
117 pub timestamp : i64,
119 pub r#type : String,
121 #[serde(skip_serializing_if = "Option::is_none")]
123 pub usage : Option<u16>,
124}
125
126#[derive(Clone,Serialize,Deserialize,Debug)]
128pub struct MistAlarmDetails {
129 pub action : String,
131 pub category : String,
133 pub status : String,
135 pub symptom : String,
137}
138
139#[derive(Clone,Serialize,Deserialize,Debug)]
141pub struct MistEmailContent {
142 #[serde(rename = "Connected switch")]
144 pub connected_switch: String,
145 #[serde(rename = "Reason")]
147 pub reason: String,
148 #[serde(rename = "Status")]
150 pub status: String,
151 pub ap : String,
153}
154
155#[derive(Clone,Serialize,Deserialize,Debug)]
157pub struct MistImpactedEntity {
158 #[serde(skip_serializing_if = "Option::is_none")]
160 pub connected_switch_mac : Option<String>,
161 pub connected_switch_name : String,
163 pub entity_mac : String,
165 pub entity_name : String,
167 pub entity_type : String,
169 pub port_id : String,
171}
172
173#[derive(Clone,Serialize,Deserialize,Debug)]
175pub struct MistAlarm {
176 #[serde(skip_serializing_if = "Option::is_none")]
178 pub alert_id : Option<String>,
179 #[serde(skip_serializing_if = "Option::is_none")]
181 pub category : Option<String>,
182 #[serde(skip_serializing_if = "Option::is_none")]
184 pub aps : Option<Vec<String>>,
185 pub count : u32,
187 #[serde(skip_serializing_if = "Option::is_none")]
189 pub detail : Option<String>,
190 #[serde(skip_serializing_if = "Option::is_none")]
192 pub details : Option<MistAlarmDetails>,
193 #[serde(skip_serializing_if = "Option::is_none")]
195 pub email_content : Option<MistEmailContent>,
196 #[serde(skip_serializing_if = "Option::is_none")]
198 pub fw_version : Option<String>,
199 pub group : String,
201 #[serde(skip_serializing_if = "Option::is_none")]
203 pub hostnames : Option<Vec<String>>,
204 pub id : String,
206 #[serde(skip_serializing_if = "Option::is_none")]
209 pub impacted_entities : Option<Vec<MistImpactedEntity>>,
210 #[serde(skip_serializing_if = "Option::is_none")]
212 pub impacted_entity_count : Option<u16>,
213 pub last_seen: String,
215 #[serde(skip_serializing_if = "Option::is_none")]
217 pub model : Option<String>,
218 pub org_id : String,
220 #[serde(skip_serializing_if = "Option::is_none")]
222 pub org_name : Option<String>,
223 #[serde(skip_serializing_if = "Option::is_none")]
225 pub peer : Option<Map<String,Value>>,
226 #[serde(skip_serializing_if = "Option::is_none")]
228 pub port_id : Option<String>,
229 #[serde(skip_serializing_if = "Option::is_none")]
231 pub port_ids : Option<Vec<String>>,
232 #[serde(skip_serializing_if = "Option::is_none")]
234 pub reasons : Option<Vec<String>>,
235 #[serde(skip_serializing_if = "Option::is_none")]
238 pub root_cause : Option<String>,
239 pub severity: String,
241 pub site_id : String,
243 pub site_name: String,
245 #[serde(skip_serializing_if = "Option::is_none")]
247 pub status : Option<String>,
248 #[serde(skip_serializing_if = "Option::is_none")]
250 pub suggestion : Option<String>,
251 #[serde(skip_serializing_if = "Option::is_none")]
253 pub switches : Option<Vec<String>>,
254 pub timestamp: f64,
256 pub r#type : String,
258}
259
260#[derive(Clone,Serialize,Deserialize,Debug)]
262pub struct MistAudits {
263 pub admin_name : String,
265 #[serde(skip_serializing_if = "Option::is_none")]
267 pub after : Option<String>,
268 #[serde(skip_serializing_if = "Option::is_none")]
270 pub before : Option<String>,
271 pub id : String,
273 pub message : String,
275 pub org_id : String,
277 #[serde(skip_serializing_if = "Option::is_none")]
279 pub site_id : Option<String>,
280 #[serde(skip_serializing_if = "Option::is_none")]
282 pub site_name : Option<String>,
283 pub src_ip : String,
285 pub timestamp : f64,
287 pub user_agent : String,
289 #[serde(skip_serializing_if = "Option::is_none")]
291 pub webhook_id : Option<String>,
292}
293
294#[derive(Clone,Serialize,Deserialize,Debug)]
296pub struct MistClientSessions {
297 pub ap : String,
299 pub ap_name : String,
301 pub band : String,
303 pub bssid : String,
305 pub client_family : String,
307 pub client_manufacture : String,
309 pub client_model : String,
311 pub client_os : String,
313 pub connect : i64,
315 pub connect_float : f64,
317 pub disconnect : i64,
319 pub disconnect_float : f64,
321 pub duration : f64,
323 pub mac : String,
325 pub next_ap : String,
327 pub org_id : String,
329 pub random_mac : bool,
331 pub rssi : i32,
333 pub site_id : String,
335 pub site_name : String,
337 pub ssid : String,
339 pub termination_reason : i32,
341 pub timestamp : i64,
343 pub version : i32,
345 pub wlan_id : String,
347}
348
349#[derive(Clone,Serialize,Deserialize,Debug)]
351pub struct MistClientJoin {
352 pub ap : String,
354 pub ap_name : String,
356 pub band : String,
358 pub bssid : String,
360 pub connect : i64,
362 pub connect_float : f64,
364 pub mac : String,
366 pub org_id : String,
368 pub random_mac : bool,
370 pub rssi : i32,
372 pub site_id : String,
374 pub site_name : String,
376 pub ssid : String,
378 pub timestamp : i64,
380 pub version : i32,
382 pub wlan_id : String,
384}
385
386#[derive(Debug,Clone,Serialize,Deserialize)]
388#[serde(tag = "topic")]
389pub enum MistMessage {
390 #[serde(rename = "alarms")]
392 Alarms {
393 events : Vec<MistAlarm>
395 },
396 #[serde(rename = "audits")]
398 Audits {
399 events : Vec<MistAudits>
401 },
402 #[serde(rename = "client-sessions")]
404 ClientSessions {
405 events : Vec<MistClientSessions>
407 },
408 #[serde(rename = "device-updowns")]
410 DeviceUpDowns {
411 events : Vec<MistDeviceUpDowns>
413 },
414 #[serde(rename = "device-events")]
416 DeviceEvents {
417 events : Vec<MistDeviceEvents>
419 },
420 #[serde(rename = "client-join")]
422 ClientJoin {
423 events : Vec<MistClientJoin>
425 },
426}
427
428#[derive(Serialize,Deserialize,Debug)]
430pub struct Mist {
431 topic : String,
433 pub events : Vec<MistAlarm>,
435}
436
437impl Default for Mist {
438 fn default() -> Self {
439 Mist {
440 topic : "undefined".to_string(),
441 events : vec![],
442 }
443 }
444}
445
446impl MistAlarm {
447 pub fn split<F>(event : &MistAlarm, get_ci : F) -> Option<Vec<MistAlarm>>
453 where F : FnOnce(String) -> String {
454 let mut output :Vec<MistAlarm> = vec![];
456 let mut match_count = 0;
458 match &event.hostnames {
459 Some(v) => {
460 let cv = v.clone();
462 cv.iter().for_each(|e| {
463 let mut new_event = event.clone();
464 new_event.hostnames = Some(vec![e.to_string()]);
465 new_event.id.push_str(format!(".{match_count}").as_ref());
466 output.push(new_event);
467 match_count += 1;
468 });
469 Some(output)
470 },
471 None => {
472 match &event.impacted_entities {
474 Some(ie) => {
475 ie.iter().for_each(|e| {
476 let mut new_event = event.clone();
477 new_event.hostnames = Some(vec![e.clone().entity_name]);
478 output.push(new_event);
479 match_count += 1;
480 });
481 Some(output)
482 },
483 None => {
484 let mut new_event = event.clone();
485 new_event.hostnames = Some(vec![get_ci(event.org_id.clone())]);
486 output.push(new_event);
487 Some(output)
488 },
489 }
490 },
491 }
492 }
493}