Skip to content
This repository has been archived by the owner on Sep 1, 2022. It is now read-only.

Add Freeze support #320

Merged
merged 9 commits into from
Jul 8, 2019
Merged
7 changes: 6 additions & 1 deletion cpp/examples/outstation/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ using namespace opendnp3;

DatabaseConfig ConfigureDatabase()
{
DatabaseConfig config(10); // 10 of each type
DatabaseConfig config(1); // 10 of each type
emgre marked this conversation as resolved.
Show resolved Hide resolved

config.analog_input[0].clazz = PointClass::Class2;
config.analog_input[0].svariation = StaticAnalogVariation::Group30Var5;
Expand Down Expand Up @@ -97,6 +97,11 @@ int main(int argc, char* argv[])
auto outstation = channel->AddOutstation("outstation", SuccessCommandHandler::Create(),
app, config);

UpdateBuilder builder;
builder.Modify(FlagsType::Counter, 0, 9, 0x01);
builder.Modify(FlagsType::FrozenCounter, 0, 9, 0x01);
outstation->Apply(builder.Build());

// Enable the outstation and start communications
outstation->Enable();

Expand Down
9 changes: 9 additions & 0 deletions cpp/lib/include/opendnp3/outstation/IUpdateHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ class IUpdateHandler
*/
virtual bool Update(const Counter& meas, uint16_t index, EventMode mode = EventMode::Detect) = 0;

/**
* Freeze a Counter measurement
* @param index index of the measurement
* @param clear clear the original counter
* @param mode Describes how event generation is handled for this method
* @return true if the value exists and it was updated
*/
virtual bool FreezeCounter(uint16_t index, bool clear = false, EventMode mode = EventMode::Detect) = 0;

/**
* Update a BinaryOutputStatus measurement
* @param meas measurement to be processed
Expand Down
1 change: 1 addition & 0 deletions cpp/lib/include/opendnp3/outstation/UpdateBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class UpdateBuilder
UpdateBuilder& Update(const DoubleBitBinary& meas, uint16_t index, EventMode mode = EventMode::Detect);
UpdateBuilder& Update(const Analog& meas, uint16_t index, EventMode mode = EventMode::Detect);
UpdateBuilder& Update(const Counter& meas, uint16_t index, EventMode mode = EventMode::Detect);
UpdateBuilder& FreezeCounter(uint16_t index, bool clear, EventMode mode = EventMode::Detect);
UpdateBuilder& Update(const BinaryOutputStatus& meas, uint16_t index, EventMode mode = EventMode::Detect);
UpdateBuilder& Update(const AnalogOutputStatus& meas, uint16_t index, EventMode mode = EventMode::Detect);
UpdateBuilder& Update(const OctetString& meas, uint16_t index, EventMode mode = EventMode::Detect);
Expand Down
16 changes: 13 additions & 3 deletions cpp/lib/src/outstation/Database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,14 @@ bool Database::Update(const Counter& meas, uint16_t index, EventMode mode)
return this->counter.update(meas, index, mode, event_receiver);
}

bool Database::FreezeCounter(uint16_t index, bool clear, EventMode mode)
{
auto num_selected = this->counter.select(Range::From(index, index));
this->FreezeSelectedCounters(clear, mode);

return num_selected > 0;
}

bool Database::Update(const BinaryOutputStatus& meas, uint16_t index, EventMode mode)
{
return this->binary_output_status.update(meas, index, mode, event_receiver);
Expand Down Expand Up @@ -402,21 +410,23 @@ bool Database::Modify(FlagsType type, uint16_t start, uint16_t stop, uint8_t fla
return false;
}

bool Database::FreezeSelectedCounters(bool clear)
bool Database::FreezeSelectedCounters(bool clear, EventMode mode)
{
for(auto c : this->counter)
{
FrozenCounter new_value(c.second.value.value, c.second.value.flags, time_source.Now());
this->frozen_counter.update(new_value, c.first, EventMode::Detect, this->event_receiver);
this->frozen_counter.update(new_value, c.first, mode, this->event_receiver);

if(clear)
{
c.second.value.value = 0;
c.second.value.time = time_source.Now();
this->counter.update(c.second.value, c.first, EventMode::Detect, this->event_receiver);
this->counter.update(c.second.value, c.first, mode, this->event_receiver);
}
}

this->counter.clear_selection();

return true;
}

Expand Down
3 changes: 2 additions & 1 deletion cpp/lib/src/outstation/Database.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,14 @@ class Database final : public IStaticSelector, public IClassAssigner, public IRe
bool Update(const DoubleBitBinary& meas, uint16_t index, EventMode mode) override;
bool Update(const Analog& meas, uint16_t index, EventMode mode) override;
bool Update(const Counter& meas, uint16_t index, EventMode mode) override;
bool FreezeCounter(uint16_t index, bool clear, EventMode mode) override;
bool Update(const BinaryOutputStatus& meas, uint16_t index, EventMode mode) override;
bool Update(const AnalogOutputStatus& meas, uint16_t index, EventMode mode) override;
bool Update(const OctetString& meas, uint16_t index, EventMode mode) override;
bool Update(const TimeAndInterval& meas, uint16_t index) override;
bool Modify(FlagsType type, uint16_t start, uint16_t stop, uint8_t flags) override;

bool FreezeSelectedCounters(bool clear);
bool FreezeSelectedCounters(bool clear, EventMode mode = EventMode::Detect);

private:

Expand Down
2 changes: 2 additions & 0 deletions cpp/lib/src/outstation/StaticDataMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ template<class Spec> class StaticDataMap : private Uncopyable

iterator end();

iterator find(uint16_t index);

private:
map_t map;
Range selected;
Expand Down
6 changes: 6 additions & 0 deletions cpp/lib/src/outstation/UpdateBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ UpdateBuilder& UpdateBuilder::Update(const Counter& meas, uint16_t index, EventM
return this->AddMeas(meas, index, mode);
}

UpdateBuilder& UpdateBuilder::FreezeCounter(uint16_t index, bool clear, EventMode mode)
{
this->Add([=](IUpdateHandler& handler) { handler.FreezeCounter(index, clear, mode); });
return *this;
}

UpdateBuilder& UpdateBuilder::Update(const BinaryOutputStatus& meas, uint16_t index, EventMode mode)
{
return this->AddMeas(meas, index, mode);
Expand Down
138 changes: 71 additions & 67 deletions dotnet/CLRAdapter/src/ChangeSetAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright 2013-2019 Automatak, LLC
*
* Licensed to Green Energy Corp (www.greenenergycorp.com) and Automatak
* LLC (www.automatak.com) under one or more contributor license agreements.
* LLC (www.automatak.com) under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Green Energy Corp and Automatak LLC license
* this file to you under the Apache License, Version 2.0 (the "License"); you
Expand All @@ -23,69 +23,73 @@

namespace Automatak
{
namespace DNP3
{
namespace Adapter
{

ChangeSetAdapter::ChangeSetAdapter() : builder(new opendnp3::UpdateBuilder())
{}

ChangeSetAdapter::~ChangeSetAdapter()
{
this->!ChangeSetAdapter();
}

ChangeSetAdapter::!ChangeSetAdapter()
{
delete builder;
}

void ChangeSetAdapter::Apply(opendnp3::IOutstation& proxy)
{
proxy.Apply(builder->Build());
}

void ChangeSetAdapter::Update(Binary^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode) mode);
}

void ChangeSetAdapter::Update(DoubleBitBinary^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode) mode);
}

void ChangeSetAdapter::Update(Analog^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode) mode);
}

void ChangeSetAdapter::Update(Counter^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode) mode);
}

void ChangeSetAdapter::Update(BinaryOutputStatus^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode) mode);
}

void ChangeSetAdapter::Update(AnalogOutputStatus^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode) mode);
}

void ChangeSetAdapter::Update(OctetString^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode) mode);
}

void ChangeSetAdapter::Update(TimeAndInterval^ update, System::UInt16 index)
{
builder->Update(Conversions::ConvertMeas(update), index);
}

}
}
}
namespace DNP3
{
namespace Adapter
{

ChangeSetAdapter::ChangeSetAdapter() : builder(new opendnp3::UpdateBuilder()) {}

ChangeSetAdapter::~ChangeSetAdapter()
{
this->!ChangeSetAdapter();
}

ChangeSetAdapter::!ChangeSetAdapter()
{
delete builder;
}

void ChangeSetAdapter::Apply(opendnp3::IOutstation& proxy)
{
proxy.Apply(builder->Build());
}

void ChangeSetAdapter::Update(Binary ^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::Update(DoubleBitBinary ^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::Update(Analog ^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::Update(Counter ^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::FreezeCounter(System::UInt16 index, System::Boolean clear, EventMode mode)
{
builder->FreezeCounter(index, clear, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::Update(BinaryOutputStatus ^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::Update(AnalogOutputStatus ^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::Update(OctetString ^ update, System::UInt16 index, EventMode mode)
{
builder->Update(Conversions::ConvertMeas(update), index, (opendnp3::EventMode)mode);
}

void ChangeSetAdapter::Update(TimeAndInterval ^ update, System::UInt16 index)
{
builder->Update(Conversions::ConvertMeas(update), index);
}

} // namespace Adapter
} // namespace DNP3
} // namespace Automatak
1 change: 1 addition & 0 deletions dotnet/CLRAdapter/src/ChangeSetAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace Automatak
virtual void Update(DoubleBitBinary^ update, System::UInt16 index, EventMode mode);
virtual void Update(Analog^ update, System::UInt16 index, EventMode mode);
virtual void Update(Counter^ update, System::UInt16 index, EventMode mode);
virtual void FreezeCounter(System::UInt16 index, System::Boolean clear, EventMode mode);
virtual void Update(BinaryOutputStatus^ update, System::UInt16 index, EventMode mode);
virtual void Update(AnalogOutputStatus^ update, System::UInt16 index, EventMode mode);
virtual void Update(OctetString^ update, System::UInt16 index, EventMode mode);
Expand Down
5 changes: 5 additions & 0 deletions dotnet/CLRInterface/src/ChangeSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ public void Update(Counter update, ushort index, EventMode mode = EventMode.Dete
updates.Add((IDatabase db) => db.Update(update, index, mode));
}

public void FreezeCounter(ushort index, bool clear, EventMode mode = EventMode.Detect)
{
updates.Add((IDatabase db) => db.FreezeCounter(index, clear, mode));
}

public void Update(BinaryOutputStatus update, ushort index, EventMode mode = EventMode.Detect)
{
updates.Add((IDatabase db) => db.Update(update, index, mode));
Expand Down
29 changes: 19 additions & 10 deletions dotnet/CLRInterface/src/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@ namespace Automatak.DNP3.Interface
/// </summary>
public interface IDatabase
{

/// <summary>
/// Update a Binary input
/// </summary>
/// <param name="update">measurement to update</param>
/// <param name="index">index of measurement</param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(Binary update, System.UInt16 index, EventMode mode = EventMode.Detect);
void Update(Binary update, System.UInt16 index, EventMode mode = EventMode.Detect);

/// <summary>
/// Update a Binary input
/// </summary>
/// <param name="update">measurement to update</param>
/// <param name="index">index of measurement</param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(DoubleBitBinary update, System.UInt16 index, EventMode mode = EventMode.Detect);

Expand All @@ -52,7 +52,7 @@ public interface IDatabase
/// </summary>
/// <param name="update">measurement to update</param>
/// <param name="index">index of measurement</param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(Analog update, System.UInt16 index, EventMode mode = EventMode.Detect);

Expand All @@ -61,16 +61,25 @@ public interface IDatabase
/// </summary>
/// <param name="update">measurement to update</param>
/// <param name="index">index of measurement</param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(Counter update, System.UInt16 index, EventMode mode = EventMode.Detect);

/// <summary>
/// Freeze a Counter
/// </summary>
/// <param name="index">index of measurement</param>
/// <param name="clear">clear original counter</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void FreezeCounter(System.UInt16 index, bool clear, EventMode mode = EventMode.Detect);

/// <summary>
/// Update a BinaryOutputStatus
/// </summary>
/// <param name="update">measurement to update</param>
/// <param name="index">index of measurement</param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(BinaryOutputStatus update, System.UInt16 index, EventMode mode = EventMode.Detect);

Expand All @@ -79,7 +88,7 @@ public interface IDatabase
/// </summary>
/// <param name="update">measurement to update</param>
/// <param name="index">index of measurement</param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(AnalogOutputStatus update, System.UInt16 index, EventMode mode = EventMode.Detect);

Expand All @@ -88,7 +97,7 @@ public interface IDatabase
/// </summary>
/// <param name="update">measurement to update</param>
/// <param name="index">index of measurement</param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(OctetString update, System.UInt16 index, EventMode mode = EventMode.Detect);

Expand All @@ -97,7 +106,7 @@ public interface IDatabase
/// </summary>
/// <param name="update"></param>
/// <param name="index"></param>
/// <param name="forceEvent"> if true, an event is created regardess of the last reported value</param>
/// <param name="mode"> EventMode to use</param>
/// <returns> true if the point exists </returns>
void Update(TimeAndInterval update, System.UInt16 index);
}
Expand Down
Loading