From 47c1c09cd22a36ee2fa06a72497b541b0240f9ed Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Wed, 22 May 2024 19:28:41 -0700 Subject: [PATCH 1/3] first pass at way to update flags on database --- .../outstation/database/details/database.rs | 57 ++++++++++++++++++- .../database/details/range/static_db.rs | 52 +++++++++++++++++ dnp3/src/outstation/database/mod.rs | 49 ++++++++++++++++ 3 files changed, 156 insertions(+), 2 deletions(-) diff --git a/dnp3/src/outstation/database/details/database.rs b/dnp3/src/outstation/database/details/database.rs index 31d73d80..f90e8165 100644 --- a/dnp3/src/outstation/database/details/database.rs +++ b/dnp3/src/outstation/database/details/database.rs @@ -2,13 +2,17 @@ use crate::app::Iin2; use crate::master::EventClasses; use crate::outstation::database::details::event::buffer::{EventBuffer, InsertError}; use crate::outstation::database::details::range::static_db::{ - PointConfig, StaticDatabase, Updatable, + PointConfig, StaticDatabase, Updatable, UpdatableFlags, }; use crate::outstation::database::read::ReadHeader; use crate::outstation::database::{ - ClassZeroConfig, EventBufferConfig, ResponseInfo, UpdateInfo, UpdateOptions, + ClassZeroConfig, EventBufferConfig, ResponseInfo, UpdateFlagsType, UpdateInfo, UpdateOptions, }; +use crate::app::measurement::{ + AnalogInput, AnalogOutputStatus, BinaryInput, BinaryOutputStatus, Counter, + DoubleBitBinaryInput, Flags, FrozenCounter, Time, +}; use crate::outstation::database::details::attrs::map::SetMap; use crate::outstation::{BufferState, OutstationApplication}; use scursor::WriteCursor; @@ -98,6 +102,55 @@ impl Database { self.static_db.get::(index) } + pub(crate) fn update_flags( + &mut self, + index: u16, + flags_type: UpdateFlagsType, + flags: Flags, + time: Time, + options: UpdateOptions, + ) -> UpdateInfo { + match flags_type { + UpdateFlagsType::BinaryInput => { + self.update_flags_by_type::(index, flags, time, options) + } + UpdateFlagsType::DoubleBitBinaryInput => { + self.update_flags_by_type::(index, flags, time, options) + } + UpdateFlagsType::BinaryOutputStatus => { + self.update_flags_by_type::(index, flags, time, options) + } + UpdateFlagsType::Counter => { + self.update_flags_by_type::(index, flags, time, options) + } + UpdateFlagsType::FrozenCounter => { + self.update_flags_by_type::(index, flags, time, options) + } + UpdateFlagsType::AnalogInput => { + self.update_flags_by_type::(index, flags, time, options) + } + UpdateFlagsType::AnalogOutputStatus => { + self.update_flags_by_type::(index, flags, time, options) + } + } + } + + pub(crate) fn update_flags_by_type( + &mut self, + index: u16, + flags: Flags, + timestamp: Time, + options: UpdateOptions, + ) -> UpdateInfo { + match self.static_db.get::(index) { + None => UpdateInfo::NoPoint, + Some(mut x) => { + x.update_flags(flags, timestamp); + self.update::(&x, index, options) + } + } + } + pub(crate) fn update(&mut self, value: &T, index: u16, options: UpdateOptions) -> UpdateInfo where T: Updatable, diff --git a/dnp3/src/outstation/database/details/range/static_db.rs b/dnp3/src/outstation/database/details/range/static_db.rs index 23e86c91..ccb53779 100644 --- a/dnp3/src/outstation/database/details/range/static_db.rs +++ b/dnp3/src/outstation/database/details/range/static_db.rs @@ -32,6 +32,10 @@ pub(crate) trait Updatable: Insertable + Clone + Default { fn enabled_class_zero(config: &ClassZeroConfig) -> bool; } +pub(crate) trait UpdatableFlags: Updatable { + fn update_flags(&mut self, flags: Flags, time: Time); +} + #[derive(Copy, Clone)] pub(crate) struct IndexRange { start: u16, @@ -743,6 +747,13 @@ impl Updatable for BinaryInput { } } +impl UpdatableFlags for BinaryInput { + fn update_flags(&mut self, flags: Flags, time: Time) { + self.flags = flags; + self.time = Some(time); + } +} + impl Updatable for DoubleBitBinaryInput { type StaticVariation = StaticDoubleBitBinaryInputVariation; type Detector = FlagsDetector; @@ -764,6 +775,13 @@ impl Updatable for DoubleBitBinaryInput { } } +impl UpdatableFlags for DoubleBitBinaryInput { + fn update_flags(&mut self, flags: Flags, time: Time) { + self.flags = flags; + self.time = Some(time); + } +} + impl Updatable for BinaryOutputStatus { type StaticVariation = StaticBinaryOutputStatusVariation; type Detector = FlagsDetector; @@ -785,6 +803,12 @@ impl Updatable for BinaryOutputStatus { } } +impl UpdatableFlags for BinaryOutputStatus { + fn update_flags(&mut self, flags: Flags, time: Time) { + self.flags = flags; + self.time = Some(time); + } +} impl Updatable for Counter { type StaticVariation = StaticCounterVariation; type Detector = Deadband; @@ -806,6 +830,13 @@ impl Updatable for Counter { } } +impl UpdatableFlags for Counter { + fn update_flags(&mut self, flags: Flags, time: Time) { + self.flags = flags; + self.time = Some(time); + } +} + impl Updatable for FrozenCounter { type StaticVariation = StaticFrozenCounterVariation; type Detector = Deadband; @@ -827,6 +858,13 @@ impl Updatable for FrozenCounter { } } +impl UpdatableFlags for FrozenCounter { + fn update_flags(&mut self, flags: Flags, time: Time) { + self.flags = flags; + self.time = Some(time); + } +} + impl Updatable for AnalogInput { type StaticVariation = StaticAnalogInputVariation; type Detector = Deadband; @@ -848,6 +886,13 @@ impl Updatable for AnalogInput { } } +impl UpdatableFlags for AnalogInput { + fn update_flags(&mut self, flags: Flags, time: Time) { + self.flags = flags; + self.time = Some(time); + } +} + impl Updatable for AnalogOutputStatus { type StaticVariation = StaticAnalogOutputStatusVariation; type Detector = Deadband; @@ -869,6 +914,13 @@ impl Updatable for AnalogOutputStatus { } } +impl UpdatableFlags for AnalogOutputStatus { + fn update_flags(&mut self, flags: Flags, time: Time) { + self.flags = flags; + self.time = Some(time); + } +} + impl Updatable for OctetString { type StaticVariation = StaticOctetStringVariation; type Detector = OctetStringDetector; diff --git a/dnp3/src/outstation/database/mod.rs b/dnp3/src/outstation/database/mod.rs index 913736b2..fca36482 100644 --- a/dnp3/src/outstation/database/mod.rs +++ b/dnp3/src/outstation/database/mod.rs @@ -307,6 +307,41 @@ pub trait Update { fn update2(&mut self, index: u16, value: &T, options: UpdateOptions) -> UpdateInfo; } +/// Point on which to update the flags +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum UpdateFlagsType { + /// Binary input + BinaryInput, + /// Double-bit binary input + DoubleBitBinaryInput, + /// Binary output status + BinaryOutputStatus, + /// Counter + Counter, + /// Frozen counter + FrozenCounter, + /// Analog input + AnalogInput, + /// Analog output status + AnalogOutputStatus, +} + +/// Trait for updating flags on a point without changing the current value of the point +pub trait UpdateFlags { + /// Update the flags for the specified point without changing the value + /// + /// This is equivalent to getting the current value, changing the flags and the value, then updating + fn update_flags( + &mut self, + index: u16, + flags_type: UpdateFlagsType, + flags: Flags, + time: Time, + options: UpdateOptions, + ) -> UpdateInfo; +} + /// Trait for getting the current value in the database pub trait Get { /// retrieve the current value off the database. @@ -477,6 +512,20 @@ impl DatabaseHandle { } } +impl UpdateFlags for Database { + fn update_flags( + &mut self, + index: u16, + flags_type: UpdateFlagsType, + flags: Flags, + time: Time, + options: UpdateOptions, + ) -> UpdateInfo { + self.inner + .update_flags(index, flags_type, flags, time, options) + } +} + impl Update for Database { fn update2(&mut self, index: u16, value: &BinaryInput, options: UpdateOptions) -> UpdateInfo { self.inner.update(value, index, options) From 4f47e993810b12c81319794b9214991a4946c83d Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Wed, 22 May 2024 19:35:56 -0700 Subject: [PATCH 2/3] demonstrate how to update flags in the rust example --- dnp3/examples/outstation.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dnp3/examples/outstation.rs b/dnp3/examples/outstation.rs index 6f1b6491..591e65d2 100644 --- a/dnp3/examples/outstation.rs +++ b/dnp3/examples/outstation.rs @@ -491,6 +491,15 @@ async fn run_outstation( ); }) } + "aif" => outstation.transaction(|db| { + db.update_flags( + 7, + UpdateFlagsType::AnalogInput, + Flags::COMM_LOST, + get_current_time(), + UpdateOptions::detect_event(), + ); + }), "aos" => { analog_output_status_value += 1.0; outstation.transaction(|db| { From 61f78f1451fdae2b1e2eb6e74b4bf59412c2c135 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Thu, 23 May 2024 15:31:56 -0700 Subject: [PATCH 3/3] UpdateFlags(..) in the FFI --- dnp3/examples/outstation.rs | 2 +- .../outstation/database/details/database.rs | 4 +- .../database/details/range/static_db.rs | 30 +++++++-------- dnp3/src/outstation/database/mod.rs | 8 ++-- .../dotnet/examples/outstation/Program.cs | 8 ++++ ffi/dnp3-ffi/src/outstation/database.rs | 37 +++++++++++++++++++ ffi/dnp3-schema/src/database.rs | 35 +++++++++++++++++- ffi/dnp3-schema/src/shared.rs | 4 ++ 8 files changed, 105 insertions(+), 23 deletions(-) diff --git a/dnp3/examples/outstation.rs b/dnp3/examples/outstation.rs index 591e65d2..7b4b9a69 100644 --- a/dnp3/examples/outstation.rs +++ b/dnp3/examples/outstation.rs @@ -496,7 +496,7 @@ async fn run_outstation( 7, UpdateFlagsType::AnalogInput, Flags::COMM_LOST, - get_current_time(), + Some(get_current_time()), UpdateOptions::detect_event(), ); }), diff --git a/dnp3/src/outstation/database/details/database.rs b/dnp3/src/outstation/database/details/database.rs index f90e8165..41308893 100644 --- a/dnp3/src/outstation/database/details/database.rs +++ b/dnp3/src/outstation/database/details/database.rs @@ -107,7 +107,7 @@ impl Database { index: u16, flags_type: UpdateFlagsType, flags: Flags, - time: Time, + time: Option