Skip to content

Commit

Permalink
Allow for ONDEMAND DNP3Outstation ports
Browse files Browse the repository at this point in the history
  • Loading branch information
neilstephens committed Feb 20, 2024
1 parent 6eba11c commit 4c962c0
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 7 deletions.
1 change: 1 addition & 0 deletions Code/Ports/DNP3Port/AppIINFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#ifndef APPIINFLAGS_H
#define APPIINFLAGS_H

#include <cstdint>
#include <opendatacon/EnumClassFlags.h>
#include <string>

Expand Down
5 changes: 2 additions & 3 deletions Code/Ports/DNP3Port/DNP3MasterPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ void DNP3MasterPort::Disable()

if(stack_enabled)
{
stack_enabled = false;
pMaster->Disable(); //this will trigger comms down
DisableStack(); //this will trigger comms down
if(auto log = odc::spdlog_get("DNP3Port"))
log->debug("{}: DNP3 stack disabled", Name);
}
Expand Down Expand Up @@ -411,7 +410,7 @@ inline void DNP3MasterPort::LoadT(const opendnp3::ICollection<opendnp3::Indexed<
if ((pConf->pPointConf->TimestampOverride == DNP3PointConf::TimestampOverride_t::ALWAYS) ||
((pConf->pPointConf->TimestampOverride == DNP3PointConf::TimestampOverride_t::ZERO) && (pair.value.time.value == 0)))
{
event->SetTimestamp();
event->SetTimestamp();
}
PublishEvent(event);
pDB->Set(event);
Expand Down
55 changes: 52 additions & 3 deletions Code/Ports/DNP3Port/DNP3OutstationPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include "DNP3OutstationPort.h"
#include "DNP3PortConf.h"
#include "DNP3OutstationPortCollection.h"
#include "OpenDNP3Helpers.h"
#include "TypeConversion.h"
#include <opendnp3/outstation/UpdateBuilder.h>
#include <opendnp3/outstation/Updates.h>
Expand All @@ -44,6 +43,7 @@
DNP3OutstationPort::DNP3OutstationPort(const std::string& aName, const std::string& aConfFilename, const Json::Value& aConfOverrides):
DNP3Port(aName, aConfFilename, aConfOverrides),
pOutstation(nullptr),
stack_enabled(false),
master_time_offset(0),
IINFlags(AppIINFlags::NONE),
last_time_sync(msSinceEpoch()),
Expand Down Expand Up @@ -95,7 +95,13 @@ void DNP3OutstationPort::Enable()
auto pConf = static_cast<DNP3PortConf*>(this->pConf.get());
if(pConf->pPointConf->TimeSyncOnStart)
SetIINFlags(AppIINFlags::NEED_TIME);
pOutstation->Enable();

if(!stack_enabled && !(pConf->mAddrConf.ServerType == server_type_t::MANUAL))
{
if(pConf->mAddrConf.ServerType == server_type_t::PERSISTENT || InDemand())
EnableStack();
}

enabled = true;

PublishEvent(ConnectState::PORT_UP);
Expand All @@ -106,7 +112,7 @@ void DNP3OutstationPort::Disable()
return;
enabled = false;

pOutstation->Disable();
DisableStack();
if(auto log = odc::spdlog_get("DNP3Port"))
log->debug("{}: DNP3 stack disabled", Name);
}
Expand Down Expand Up @@ -140,9 +146,20 @@ void DNP3OutstationPort::LinkDeadnessChange(LinkDeadness from, LinkDeadness to)

if(from == LinkDeadness::LinkUpChannelUp) //must be on link down
{
auto pConf = static_cast<DNP3PortConf*>(this->pConf.get());
if(auto log = odc::spdlog_get("DNP3Port"))
log->debug("{}: Link down.", Name);

PublishEvent(ConnectState::DISCONNECTED);

if(pConf->mAddrConf.ServerType == server_type_t::MANUAL
||(pConf->mAddrConf.ServerType == server_type_t::ONDEMAND && !InDemand()))
{
pIOS->post([this]()
{
DisableStack();
});
}
}
}
void DNP3OutstationPort::ChannelWatchdogTrigger(bool on)
Expand Down Expand Up @@ -484,6 +501,7 @@ void DNP3OutstationPort::Event(std::shared_ptr<const EventInfo> event, const std
EventT(FromODC<opendnp3::AnalogQuality>(event), event->GetIndex(), opendnp3::FlagsType::AnalogInput);
break;
case EventType::ConnectState:
Event(event->GetPayload<EventType::ConnectState>());
break;
default:
(*pStatusCallback)(CommandStatus::NOT_SUPPORTED);
Expand Down Expand Up @@ -524,6 +542,37 @@ inline void DNP3OutstationPort::EventT<opendnp3::OctetString>(opendnp3::OctetStr
pOutstation->Apply(builder.Build());
}

inline void DNP3OutstationPort::Event(odc::ConnectState state)
{
//TODO: this is common code with DNP3MasterPort. It can move to DNP3Port,
// and should be refactored out into a synchronised state machine for the stack state
auto pConf = static_cast<DNP3PortConf*>(this->pConf.get());

// If an upstream port is connected, attempt a connection (if on demand)
if (!stack_enabled && state == ConnectState::CONNECTED && pConf->mAddrConf.ServerType == server_type_t::ONDEMAND)
{
if(auto log = odc::spdlog_get("DNP3Port"))
log->info("{}: Upstream port connected, performing on-demand connection.", Name);

pIOS->post([this]()
{
EnableStack();
});
}

// If an upstream port is disconnected, disconnect ourselves if it was the last active connection (if on demand)
if (stack_enabled && !InDemand() && pConf->mAddrConf.ServerType == server_type_t::ONDEMAND)
{
if(auto log = odc::spdlog_get("DNP3Port"))
log->info("{}: No upstream connections left, performing on-demand disconnection.", Name);

pIOS->post([this]()
{
DisableStack();
});
}
}

inline void DNP3OutstationPort::SetIINFlags(const AppIINFlags& flags) const
{
AppIINFlags ExIINs, OldIINs = IINFlags;
Expand Down
12 changes: 12 additions & 0 deletions Code/Ports/DNP3Port/DNP3OutstationPort.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class DNP3OutstationPort: public DNP3Port, public opendnp3::ICommandHandler, pub

private:
std::shared_ptr<opendnp3::IOutstation> pOutstation;
std::atomic_bool stack_enabled;
std::atomic<int64_t> master_time_offset;
mutable std::atomic<AppIINFlags> IINFlags;
std::atomic<msSinceEpoch_t> last_time_sync;
Expand All @@ -105,6 +106,17 @@ class DNP3OutstationPort: public DNP3Port, public opendnp3::ICommandHandler, pub
void UpdateQuality(const EventType event_type, const uint16_t index, const QualityFlags qual);
template<typename T> void EventT(T meas, uint16_t index);
template<typename T> void EventT(T qual, uint16_t index, opendnp3::FlagsType FT);
void Event(odc::ConnectState state);
inline void EnableStack()
{
pOutstation->Enable();
stack_enabled = true;
}
inline void DisableStack()
{
stack_enabled = false;
pOutstation->Disable();
}

template<typename T> opendnp3::CommandStatus SupportsT(T& arCommand, uint16_t aIndex);
template<typename T> opendnp3::CommandStatus PerformT(T& arCommand, uint16_t aIndex);
Expand Down
2 changes: 1 addition & 1 deletion install/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# limitations under the License.
#
project (opendatacon_installer)
cmake_minimum_required (VERSION 2.8)
cmake_minimum_required (VERSION 3.5)

set(CPACK_PACKAGE_NAME "opendatacon")
set(CPACK_PACKAGE_VENDOR "opendatacon.net")
Expand Down

0 comments on commit 4c962c0

Please sign in to comment.