Skip to content

Commit

Permalink
Added some of the slave configuration types
Browse files Browse the repository at this point in the history
  • Loading branch information
jadamcrain committed Jun 6, 2012
1 parent 2e086d3 commit 0482406
Show file tree
Hide file tree
Showing 5 changed files with 324 additions and 3 deletions.
15 changes: 15 additions & 0 deletions DNP.sln
Expand Up @@ -44,6 +44,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetMasterDemo", "DotNet\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetInterface", "DotNet\DotNetInterface\DotNetInterface.csproj", "{C280F8AA-8461-4126-BF88-454891422FD8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetSlaveDemo", "DotNet\DotNetSlaveDemo\DotNetSlaveDemo.csproj", "{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -310,6 +312,18 @@ Global
{C280F8AA-8461-4126-BF88-454891422FD8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C280F8AA-8461-4126-BF88-454891422FD8}.Release|Win32.ActiveCfg = Release|Any CPU
{C280F8AA-8461-4126-BF88-454891422FD8}.Release|x86.ActiveCfg = Release|Any CPU
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Debug|Any CPU.ActiveCfg = Debug|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Debug|Mixed Platforms.Build.0 = Debug|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Debug|Win32.ActiveCfg = Debug|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Debug|x86.ActiveCfg = Debug|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Debug|x86.Build.0 = Debug|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Release|Any CPU.ActiveCfg = Release|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Release|Mixed Platforms.ActiveCfg = Release|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Release|Mixed Platforms.Build.0 = Release|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Release|Win32.ActiveCfg = Release|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Release|x86.ActiveCfg = Release|x86
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -320,5 +334,6 @@ Global
{686B212F-3FE0-455A-B78B-0980D9F2F837} = {9A7489FE-BBB2-41B1-A4F8-BCC01DE1C89B}
{9BEAD0C0-833F-4368-82D1-BAE30F38E6C5} = {9A7489FE-BBB2-41B1-A4F8-BCC01DE1C89B}
{C280F8AA-8461-4126-BF88-454891422FD8} = {9A7489FE-BBB2-41B1-A4F8-BCC01DE1C89B}
{96F33EA8-6CE5-4D70-82AD-9C9DA664A688} = {9A7489FE-BBB2-41B1-A4F8-BCC01DE1C89B}
EndGlobalSection
EndGlobal
47 changes: 47 additions & 0 deletions DotNet/DotNetAdapter/Conversions.cpp
Expand Up @@ -281,6 +281,44 @@ namespace DNPDotNet {
return apl::dnp::AppConfig(config->rspTimeout, config->numRetry, config->fragSize);
}

apl::dnp::ClassMask Conversions::convertClassMask(ClassMask^ cm)
{
return apl::dnp::ClassMask(cm->class1, cm->class2, cm->class3);
}

apl::dnp::EventMaxConfig Conversions::convertEventMaxConfig(EventMaxConfig^ cm)
{
return apl::dnp::EventMaxConfig(cm->maxBinaryEvents, cm->maxAnalogEvents, cm->maxCounterEvents, 0);
}

apl::dnp::GrpVar Conversions::convertGrpVar(GrpVar^ gv)
{
return apl::dnp::GrpVar(gv->grp, gv->var);
}

apl::dnp::SlaveConfig Conversions::convertConfig(SlaveConfig^ config)
{
apl::dnp::SlaveConfig sc;

sc.mMaxControls = config->maxControls;
sc.mUnsolMask = convertClassMask(config->unsolMask);
sc.mAllowTimeSync = config->allowTimeSync;
sc.mTimeSyncPeriod = config->timeSyncPeriod;
sc.mUnsolPackDelay = config->unsolPackDelay;
sc.mUnsolRetryDelay = config->unsolRetryDelay;
sc.mMaxFragSize = config->maxFragSize;
sc.mEventMaxConfig = convertEventMaxConfig(config->eventMaxConfig);
sc.mStaticBinary = convertGrpVar(config->staticBinary);
sc.mStaticAnalog = convertGrpVar(config->staticAnalog);
sc.mStaticCounter = convertGrpVar(config->staticCounter);
sc.mStaticSetpointStatus = convertGrpVar(config->staticSetpointStatus);
sc.mEventBinary = convertGrpVar(config->eventBinary);
sc.mEventAnalog = convertGrpVar(config->eventAnalog);
sc.mEventCounter = convertGrpVar(config->eventCounter);

return sc;
}

apl::dnp::MasterConfig Conversions::convertConfig(MasterConfig^ config)
{
apl::dnp::MasterConfig mc;
Expand Down Expand Up @@ -308,4 +346,13 @@ namespace DNPDotNet {
cfg.link = convertConfig(config->link);
return cfg;
}

apl::dnp::SlaveStackConfig Conversions::convertConfig(SlaveStackConfig^ config)
{
apl::dnp::SlaveStackConfig cfg;
cfg.slave = convertConfig(config->slave);
cfg.app = convertConfig(config->app);
cfg.link = convertConfig(config->link);
return cfg;
}
}
7 changes: 7 additions & 0 deletions DotNet/DotNetAdapter/Conversions.h
Expand Up @@ -7,6 +7,7 @@
#include <APL/LogTypes.h>
#include <APL/DataTypes.h>

#include <DNP3/SlaveStackConfig.h>
#include <DNP3/MasterStackConfig.h>

using namespace DNP3::Interface;
Expand Down Expand Up @@ -59,10 +60,16 @@ namespace DNPDotNet {
static apl::ControlStatus convertMeas(ControlStatus^ meas);

//Convert the configuration types
static apl::dnp::ClassMask convertClassMask(ClassMask^ cm);
static apl::dnp::EventMaxConfig convertEventMaxConfig(EventMaxConfig^ cm);
static apl::dnp::GrpVar convertGrpVar(GrpVar^ gv);

static apl::dnp::LinkConfig convertConfig(LinkConfig^ config);
static apl::dnp::AppConfig convertConfig(AppConfig^ config);
static apl::dnp::MasterConfig convertConfig(MasterConfig^ config);
static apl::dnp::SlaveConfig convertConfig(SlaveConfig^ config);
static apl::dnp::MasterStackConfig convertConfig(MasterStackConfig^ config);
static apl::dnp::SlaveStackConfig convertConfig(SlaveStackConfig^ config);
};

}
Expand Down
256 changes: 254 additions & 2 deletions DotNet/DotNetInterface/ConfigObjects.cs
Expand Up @@ -184,7 +184,243 @@ public void AddExceptionScan(System.Int32 classMask, System.Int64 period)
/// vector that holds exception scans
/// </summary>
public readonly List<ExceptionScan> scans;
};
}

public struct ClassMask
{
public ClassMask(bool c1, bool c2, bool c3)
{
this.class1 = c1;
this.class2 = c2;
this.class3 = c3;
}

public bool class1;
public bool class2;
public bool class3;
}

// Group/Variation pair
public struct GrpVar {

public GrpVar(int grp, int var)
{
this.grp = grp;
this.var = var;
}

public readonly int grp;
public readonly int var;
}

public class EventMaxConfig {

public EventMaxConfig(System.UInt32 maxBinaryEvents, System.UInt32 maxAnalogEvents, System.UInt32 maxCounterEvents)
{
this.maxBinaryEvents = maxBinaryEvents;
this.maxAnalogEvents = maxAnalogEvents;
this.maxCounterEvents = maxCounterEvents;
}

public EventMaxConfig()
{
this.maxBinaryEvents = 1000;
this.maxAnalogEvents = 1000;
this.maxCounterEvents = 1000;
}

/// <summary>
/// The number of binary events the slave will buffer before overflowing */
/// </summary>
public readonly System.UInt32 maxBinaryEvents;

/// <summary>
/// The number of analog events the slave will buffer before overflowing
/// </summary>
public readonly System.UInt32 maxAnalogEvents;

/// <summary>
/// The number of counter events the slave will buffer before overflowing
/// </summary>
public readonly System.UInt32 maxCounterEvents;
}


/// <summary>
/// Configuration information for a dnp3 slave (outstation)
/// Used as both input describing the startup configuration of the slave, and as configuration state of mutable properties (i.e. unsolicited responses).
/// Major feature areas are unsolicited responses, time synchronization requests, event buffer limits, and the DNP3 object/variations to use by default
/// when the master requests class data or variation 0.
/// </summary>
public class SlaveConfig
{
public SlaveConfig()
{
this.maxControls = 1;
this.disableUnsol = false;
this.unsolMask = new ClassMask(true, true, true);
this.allowTimeSync = false;
this.timeSyncPeriod = 10 * 60 * 1000; // every 10 min
this.unsolPackDelay = 200;
this.unsolRetryDelay = 2000;
this.maxFragSize = 2048;
this.eventMaxConfig = new EventMaxConfig();
this.staticBinary = new GrpVar(1, 2);
this.staticAnalog = new GrpVar(30, 1);
this.staticCounter = new GrpVar(20, 1);
this.staticSetpointStatus = new GrpVar(40, 1);
this.eventBinary = new GrpVar(2, 1);
this.eventAnalog = new GrpVar(32, 1);
this.eventCounter = new GrpVar(22, 1);
}

/// <summary>
/// The maximum number of controls the slave will attempt to process from a single APDU
/// </summary>
public System.UInt32 maxControls;

/// <summary>
/// if true, fully disables unsolicited mode as if the slave didn't support it
/// </summary>
public bool disableUnsol;

/// <summary>
/// controls what unsol classes are enabled
/// </summary>
public ClassMask unsolMask;

/// <summary>
/// if true, the slave will request time synchronization on an interval
/// </summary>
public bool allowTimeSync;

/// <summary>
/// The period of time sync interval in milliseconds
/// </summary>
public System.Int64 timeSyncPeriod;

/// <summary>
/// The amount of time the slave will wait before sending new unsolicited data ( <= 0 == immediate)
/// </summary>
public System.Int64 unsolPackDelay;

/// <summary>
/// How long the slave will wait before retrying an unsuccessful unsol response
/// </summary>
public System.Int64 unsolRetryDelay;


/// <summary>
/// The maximum fragment size the slave will use for data it sends
/// </summary>
public System.UInt32 maxFragSize;

/// <summary>
/// Structure that defines the maximum number of events to buffer
/// </summary>
public EventMaxConfig eventMaxConfig;

/// <summary>
/// The default group/variation to use for static binary responses
/// </summary>
public GrpVar staticBinary;

/// <summary>
/// The default group/variation to use for static analog responses
/// </summary>
public GrpVar staticAnalog;

/// <summary>
/// The default group/variation to use for static analog responses
/// </summary>
public GrpVar staticCounter;

/// <summary>
/// The default group/variation to use for static setpoint status responses
/// </summary>
public GrpVar staticSetpointStatus;

/// <summary>
/// The default group/variation to use for binary event responses
/// </summary>
public GrpVar eventBinary;

/// <summary>
/// The default group/variation to use for analog event responses
/// </summary>
public GrpVar eventAnalog;

/// <summary>
/// The default group/variation to use for counter event responses
/// </summary>
public GrpVar eventCounter;
}

public class PointRecord
{

};

public class EventPointRecord : PointRecord
{
public EventPointRecord(PointClass pointClass) : base()
{
this.pointClass = pointClass;
}

public PointClass pointClass;
};

public class DeadbandEventPointRecord : EventPointRecord
{
public DeadbandEventPointRecord(PointClass pointClass, double deadband) : base(pointClass)
{
this.deadband = deadband;
}

public double deadband;
};

public class ControlRecord : PointRecord
{
public ControlRecord(CommandModes mode, System.Int64 selectTimeoutMs) : base()
{
this.mode = mode;
this.selectTimeoutMs = selectTimeoutMs;
}

CommandModes mode;
System.Int64 selectTimeoutMs;
};

public class DeviceTemplate
{
public DeviceTemplate( System.UInt32 numBinary,
System.UInt32 numAnalog,
System.UInt32 numCounter,
System.UInt32 numControlStatus,
System.UInt32 numSetpointStatus,
System.UInt32 numControls,
System.UInt32 numSetpoints)
{
binaries = Enumerable.Range(0, (int) numBinary).Select(i => new EventPointRecord(PointClass.PC_CLASS_0)).ToList();
counters = Enumerable.Range(0, (int) numCounter).Select(i => new EventPointRecord(PointClass.PC_CLASS_0)).ToList();
analogs = Enumerable.Range(0, (int) numAnalog).Select(i => new DeadbandEventPointRecord(PointClass.PC_CLASS_0, 0.0)).ToList();
controlStatii = Enumerable.Range(0, (int) numControlStatus).Select(i => new PointRecord()).ToList();
controlStatii = Enumerable.Range(0, (int) numSetpointStatus).Select(i => new PointRecord()).ToList();
controls = Enumerable.Range(0, (int) numControls).Select(i => new ControlRecord(CommandModes.CM_SBO_ONLY, 5000)).ToList();
setpoints = Enumerable.Range(0, (int )numSetpoints).Select(i => new ControlRecord(CommandModes.CM_SBO_ONLY, 5000)).ToList();
}

public readonly List<EventPointRecord> binaries;
public readonly List<EventPointRecord> counters;
public readonly List<DeadbandEventPointRecord> analogs;
public readonly List<PointRecord> controlStatii;
public readonly List<PointRecord> setpointStatii;

public readonly List<ControlRecord> controls;
public readonly List<ControlRecord> setpoints;
};

public class MasterStackConfig
{
Expand All @@ -198,5 +434,21 @@ public MasterStackConfig()
public readonly MasterConfig master;
public readonly AppConfig app;
public readonly LinkConfig link;
};
}

public class SlaveStackConfig
{
public SlaveStackConfig()
{
this.slave = new SlaveConfig();
this.link = new LinkConfig(false, false);
this.app = new AppConfig();

}

public SlaveConfig slave; // Slave config
//DeviceTemplate device; // Device template that specifies database layout, control behavior
public AppConfig app; // Application layer config
public LinkConfig link; // Link layer config
}
}
2 changes: 1 addition & 1 deletion DotNet/DotNetSlaveDemo/Program.cs
Expand Up @@ -33,7 +33,7 @@ static void Main(string[] args)
{
var sm = new StackManager();
sm.AddTCPServer("server", FilterLevel.LEV_INFO, 5000, "127.0.0.1", 20000);
IDataObserver observer = sm.AddSlave("server", "slave", FilterLevel.LEV_INFO, new RejectingCommandAcceptor());
var observer = sm.AddSlave("server", "slave", FilterLevel.LEV_INFO, new RejectingCommandAcceptor());

Console.WriteLine("Press <Enter> to randomly change a value");

Expand Down

0 comments on commit 0482406

Please sign in to comment.