surge_network/network/net_ops.rs
1// SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0
2//! Network Operations data types — switching plans, outage scheduling, and crew dispatch.
3//!
4//! These types model the IEC 61968 / CIM Operations & Maintenance domain:
5//! - **SwitchingPlan** — ordered sequence of switching steps for planned outages
6//! - **OutageRecord** — planned or forced equipment outages with cause classification
7//! - **OutageScheduleData** — scheduling horizon containing multiple outage references
8//! - **CrewRecord** — field crew assignments and dispatch status
9//! - **WorkTaskRecord** — maintenance work tasks linked to crews and outages
10
11use chrono::{DateTime, Utc};
12use serde::{Deserialize, Serialize};
13
14/// The kind of action performed in a switching step.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16pub enum SwitchingStepKind {
17 Open,
18 Close,
19 Energize,
20 DeEnergize,
21 Ground,
22 Unground,
23}
24
25/// A single step within a switching plan.
26#[derive(Debug, Clone, Default, Serialize, Deserialize)]
27pub struct SwitchingStep {
28 /// Order of execution within the parent switching plan.
29 pub sequence_number: u32,
30 /// Action to perform (open, close, energize, etc.).
31 pub kind: Option<SwitchingStepKind>,
32 /// mRID of the switch device to operate (if applicable).
33 pub switch_mrid: Option<String>,
34 /// mRID of the equipment being switched (if applicable).
35 pub equipment_mrid: Option<String>,
36 /// Free-text description of this step.
37 pub description: Option<String>,
38 /// Whether this step can be executed in any order relative to siblings.
39 pub is_free_sequence: bool,
40 /// Timestamp when this step was actually executed.
41 pub executed_date_time: Option<DateTime<Utc>>,
42}
43
44/// An ordered sequence of switching actions for a planned outage or restoration.
45#[derive(Debug, Clone, Default, Serialize, Deserialize)]
46pub struct SwitchingPlan {
47 /// Unique CIM mRID.
48 pub mrid: String,
49 /// Human-readable name.
50 pub name: String,
51 /// Purpose or reason for the switching plan.
52 pub purpose: Option<String>,
53 /// Planned start time.
54 pub planned_start: Option<DateTime<Utc>>,
55 /// Planned end time.
56 pub planned_end: Option<DateTime<Utc>>,
57 /// Timestamp when the plan was approved.
58 pub approved_date_time: Option<DateTime<Utc>>,
59 /// Ordered switching steps (sorted by `sequence_number`).
60 pub steps: Vec<SwitchingStep>,
61}
62
63/// Classification of the cause of an outage.
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
65pub enum OutageCause {
66 Maintenance,
67 Construction,
68 Repair,
69 Testing,
70 Environmental,
71 ForcedEquipment,
72 ForcedWeather,
73 ForcedProtection,
74 Other,
75}
76
77/// A planned or forced equipment outage record.
78#[derive(Debug, Clone, Default, Serialize, Deserialize)]
79pub struct OutageRecord {
80 /// Unique CIM mRID.
81 pub mrid: String,
82 /// Human-readable name.
83 pub name: String,
84 /// Whether this is a planned (true) or forced (false) outage.
85 pub is_planned: bool,
86 /// Cause classification.
87 pub cause: Option<OutageCause>,
88 /// mRIDs of affected equipment.
89 pub equipment_mrids: Vec<String>,
90 /// Planned start time.
91 pub planned_start: Option<DateTime<Utc>>,
92 /// Planned end time.
93 pub planned_end: Option<DateTime<Utc>>,
94 /// Actual start time.
95 pub actual_start: Option<DateTime<Utc>>,
96 /// Actual end time.
97 pub actual_end: Option<DateTime<Utc>>,
98 /// Timestamp when the outage was cancelled (if applicable).
99 pub cancelled_date_time: Option<DateTime<Utc>>,
100 /// Estimated restoration time.
101 pub estimated_restore: Option<DateTime<Utc>>,
102 /// Name of the area affected by this outage.
103 pub area_name: Option<String>,
104}
105
106/// A scheduling horizon containing references to multiple outage records.
107#[derive(Debug, Clone, Default, Serialize, Deserialize)]
108pub struct OutageScheduleData {
109 /// Unique CIM mRID.
110 pub mrid: String,
111 /// Human-readable name.
112 pub name: String,
113 /// Start of the scheduling horizon.
114 pub horizon_start: Option<DateTime<Utc>>,
115 /// End of the scheduling horizon.
116 pub horizon_end: Option<DateTime<Utc>>,
117 /// mRIDs of outage records within this schedule.
118 pub outages: Vec<String>,
119}
120
121/// Dispatch status of a field crew.
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
123pub enum CrewStatus {
124 Available,
125 Dispatched,
126 EnRoute,
127 OnSite,
128 Released,
129}
130
131/// A field crew record.
132#[derive(Debug, Clone, Default, Serialize, Deserialize)]
133pub struct CrewRecord {
134 /// Unique CIM mRID.
135 pub mrid: String,
136 /// Human-readable name.
137 pub name: String,
138 /// Type of crew (e.g., "Line", "Substation", "Transmission").
139 pub crew_type: Option<String>,
140 /// Current dispatch status.
141 pub status: Option<CrewStatus>,
142}
143
144/// Classification of a maintenance work task.
145#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
146pub enum WorkTaskKind {
147 Install,
148 Remove,
149 Inspect,
150 Repair,
151 Replace,
152}
153
154/// Execution status of a work task.
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
156pub enum WorkTaskStatus {
157 Scheduled,
158 Dispatched,
159 InProgress,
160 Completed,
161 Cancelled,
162}
163
164/// A maintenance work task linked to a crew and/or outage.
165#[derive(Debug, Clone, Default, Serialize, Deserialize)]
166pub struct WorkTaskRecord {
167 /// Unique CIM mRID.
168 pub mrid: String,
169 /// Human-readable name.
170 pub name: String,
171 /// mRID of the assigned crew.
172 pub crew_mrid: Option<String>,
173 /// mRID of the associated outage.
174 pub outage_mrid: Option<String>,
175 /// Scheduled start time.
176 pub scheduled_start: Option<DateTime<Utc>>,
177 /// Scheduled end time.
178 pub scheduled_end: Option<DateTime<Utc>>,
179 /// Kind of work to be performed.
180 pub task_kind: Option<WorkTaskKind>,
181 /// Numeric priority (lower = higher priority).
182 pub priority: Option<u32>,
183 /// Current execution status.
184 pub status: Option<WorkTaskStatus>,
185}
186
187/// Aggregate container for all network operations data.
188#[derive(Debug, Clone, Default, Serialize, Deserialize)]
189pub struct NetworkOperationsData {
190 /// Switching plans with ordered steps.
191 pub switching_plans: Vec<SwitchingPlan>,
192 /// Planned and forced outage records.
193 pub outage_records: Vec<OutageRecord>,
194 /// Outage scheduling horizons.
195 pub outage_schedules: Vec<OutageScheduleData>,
196 /// Field crew records.
197 pub crews: Vec<CrewRecord>,
198 /// Maintenance work tasks.
199 pub work_tasks: Vec<WorkTaskRecord>,
200}
201
202impl NetworkOperationsData {
203 /// Returns `true` if all collections are empty.
204 pub fn is_empty(&self) -> bool {
205 self.switching_plans.is_empty()
206 && self.outage_records.is_empty()
207 && self.outage_schedules.is_empty()
208 && self.crews.is_empty()
209 && self.work_tasks.is_empty()
210 }
211}