Skip to main content

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}