- added IED_ERROR_TYPE_INCONSISTENT value to client API

- server now reponds with type-inconsistent error when client tries to write a value of wrong type
pull/6/head
Michael Zillgith 10 years ago
parent 4af2e5420d
commit a603b7af48

@ -1143,6 +1143,9 @@ namespace IEC61850
/** The server does not support the requested access method */ /** The server does not support the requested access method */
IED_ERROR_OBJECT_ACCESS_UNSUPPORTED = 24, IED_ERROR_OBJECT_ACCESS_UNSUPPORTED = 24,
/** The server expected an object of another type */
IED_ERROR_TYPE_INCONSISTENT = 25,
/* unknown error */ /* unknown error */
IED_ERROR_UNKNOWN = 99 IED_ERROR_UNKNOWN = 99
} }

@ -120,6 +120,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getRptId(IntPtr self); static extern IntPtr ClientReport_getRptId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getEntryId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getDataReference(IntPtr self, int elementIndex); static extern IntPtr ClientReport_getDataReference(IntPtr self, int elementIndex);
@ -286,6 +289,23 @@ namespace IEC61850
return Marshal.PtrToStringAnsi (rptId); return Marshal.PtrToStringAnsi (rptId);
} }
/// <summary>
/// Gets the EntryID of this report.
/// </summary>
/// <returns>The entryID as a byte array representing an MMS octet string.</returns>
public byte[] GetEntryId ()
{
IntPtr entryIdRef = ClientReport_getEntryId (self);
if (entryIdRef == IntPtr.Zero)
return null;
else {
MmsValue entryId = new MmsValue (entryIdRef);
return entryId.getOctetString ();
}
}
} }
} }

@ -32,7 +32,7 @@ namespace control
{ {
con.Connect(hostname, 102); con.Connect(hostname, 102);
/* direct control with normal security */ /* direct control with normal security or SBO with normal security */
string objectReference = "simpleIOGenericIO/GGIO1.SPCSO1"; string objectReference = "simpleIOGenericIO/GGIO1.SPCSO1";
ControlObject control = con.CreateControlObject(objectReference); ControlObject control = con.CreateControlObject(objectReference);
@ -41,11 +41,35 @@ namespace control
Console.WriteLine(objectReference + " has control model " + controlModel.ToString()); Console.WriteLine(objectReference + " has control model " + controlModel.ToString());
if (controlModel != ControlModel.STATUS_ONLY)
control.Operate(true);
switch (controlModel) {
case ControlModel.STATUS_ONLY:
Console.WriteLine("Control is status-only!");
break;
case ControlModel.DIRECT_NORMAL:
case ControlModel.DIRECT_ENHANCED:
if (!control.Operate(true)) if (!control.Operate(true))
Console.WriteLine("operate failed!"); Console.WriteLine("operate failed!");
else
Console.WriteLine("operated successfully!");
break;
case ControlModel.SBO_NORMAL:
case ControlModel.SBO_ENHANCED:
if (control.Select()) {
if (!control.Operate(true))
Console.WriteLine("operate failed!");
else
Console.WriteLine("operated successfully!");
}
else
Console.WriteLine("Select failed!");
break;
}
/* direct control with enhanced security */ /* direct control with enhanced security */
objectReference = "simpleIOGenericIO/GGIO1.SPCSO3"; objectReference = "simpleIOGenericIO/GGIO1.SPCSO3";

@ -4,6 +4,7 @@ using System.Threading;
using IEC61850.Client; using IEC61850.Client;
using IEC61850.Common; using IEC61850.Common;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
namespace reporting namespace reporting
{ {
@ -21,6 +22,14 @@ namespace reporting
MmsValue values = report.GetDataSetValues (); MmsValue values = report.GetDataSetValues ();
byte[] entryId = report.GetEntryId ();
if (entryId != null) {
SoapHexBinary shb = new SoapHexBinary(entryId);
Console.WriteLine (" entryID: " + shb.ToString ());
}
Console.WriteLine (" report dataset contains " + values.Size () + " elements"); Console.WriteLine (" report dataset contains " + values.Size () + " elements");
for (int i = 0; i < values.Size(); i++) { for (int i = 0; i < values.Size(); i++) {
@ -55,8 +64,6 @@ namespace reporting
else else
hostname = "localhost"; hostname = "localhost";
hostname = "10.0.2.2";
Console.WriteLine ("Connect to " + hostname); Console.WriteLine ("Connect to " + hostname);
try { try {
@ -64,9 +71,11 @@ namespace reporting
string rcbReference1 = "simpleIOGenericIO/LLN0.RP.EventsRCB01"; string rcbReference1 = "simpleIOGenericIO/LLN0.RP.EventsRCB01";
string rcbReference2 = "simpleIOGenericIO/LLN0.RP.EventsIndexed01"; string rcbReference2 = "simpleIOGenericIO/LLN0.RP.EventsIndexed01";
string rcbReference3 = "simpleIOGenericIO/LLN0.BR.Measurements01";
ReportControlBlock rcb1 = con.GetReportControlBlock(rcbReference1); ReportControlBlock rcb1 = con.GetReportControlBlock(rcbReference1);
ReportControlBlock rcb2 = con.GetReportControlBlock(rcbReference2); ReportControlBlock rcb2 = con.GetReportControlBlock(rcbReference2);
ReportControlBlock rcb3 = con.GetReportControlBlock(rcbReference3);
rcb1.GetRCBValues(); rcb1.GetRCBValues();
@ -84,6 +93,9 @@ namespace reporting
rcb2.GetRCBValues(); rcb2.GetRCBValues();
if (rcb2.IsBuffered())
Console.WriteLine ("RCB: " + rcbReference2 + " is buffered");
rcb2.InstallReportHandler(reportHandler, rcb2); rcb2.InstallReportHandler(reportHandler, rcb2);
rcb2.SetOptFlds(ReportOptions.REASON_FOR_INCLUSION | ReportOptions.SEQ_NUM | ReportOptions.TIME_STAMP | rcb2.SetOptFlds(ReportOptions.REASON_FOR_INCLUSION | ReportOptions.SEQ_NUM | ReportOptions.TIME_STAMP |
@ -94,6 +106,21 @@ namespace reporting
rcb2.SetRCBValues(); rcb2.SetRCBValues();
rcb3.GetRCBValues();
if (rcb3.IsBuffered())
Console.WriteLine ("RCB: " + rcbReference3 + " is buffered");
rcb3.InstallReportHandler(reportHandler, rcb2);
rcb3.SetOptFlds(ReportOptions.REASON_FOR_INCLUSION | ReportOptions.SEQ_NUM | ReportOptions.TIME_STAMP |
ReportOptions.CONF_REV | ReportOptions.ENTRY_ID | ReportOptions.DATA_REFERENCE | ReportOptions.DATA_SET);
rcb3.SetTrgOps(TriggerOptions.DATA_CHANGED | TriggerOptions.INTEGRITY);
rcb3.SetIntgPd(2000);
rcb3.SetRptEna(true);
rcb3.SetRCBValues();
/* run until Ctrl-C is pressed */ /* run until Ctrl-C is pressed */
Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) {

@ -76,6 +76,9 @@ iedConnection_mapMmsErrorToIedError(MmsError mmsError)
case MMS_ERROR_DEFINITION_OBJECT_EXISTS: case MMS_ERROR_DEFINITION_OBJECT_EXISTS:
return IED_ERROR_OBJECT_EXISTS; return IED_ERROR_OBJECT_EXISTS;
case MMS_ERROR_DEFINITION_TYPE_INCONSISTENT:
return IED_ERROR_TYPE_INCONSISTENT;
case MMS_ERROR_SERVICE_TIMEOUT: case MMS_ERROR_SERVICE_TIMEOUT:
return IED_ERROR_TIMEOUT; return IED_ERROR_TIMEOUT;

@ -129,6 +129,9 @@ typedef enum {
/** The server does not support the requested access method */ /** The server does not support the requested access method */
IED_ERROR_OBJECT_ACCESS_UNSUPPORTED = 24, IED_ERROR_OBJECT_ACCESS_UNSUPPORTED = 24,
/** The server expected an object of another type */
IED_ERROR_TYPE_INCONSISTENT = 25,
/* unknown error */ /* unknown error */
IED_ERROR_UNKNOWN = 99 IED_ERROR_UNKNOWN = 99
} IedClientError; } IedClientError;

@ -212,6 +212,14 @@ mmsServer_handleWriteRequest(
continue; continue;
} }
/* Check for correct type */
if (MmsValue_getType(value) != MmsVariableSpecification_getType(variable)) {
GLOBAL_FREEMEM(nameIdStr);
MmsValue_delete(value);
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
continue;
}
if (alternateAccess != NULL) { if (alternateAccess != NULL) {
if (domain != NULL) if (domain != NULL)

Loading…
Cancel
Save