- IEC 61850 client: reporting - support data set entries with multiple reasons for inclusion

pull/239/head
Michael Zillgith 5 years ago
parent b3c5ecdcf2
commit d85b7ac777

@ -35,26 +35,29 @@ namespace IEC61850
private List<ReportControlBlock> activeRCBs = null; private List<ReportControlBlock> activeRCBs = null;
public ReportControlBlock GetReportControlBlock (string rcbObjectReference) public ReportControlBlock GetReportControlBlock(string rcbObjectReference)
{ {
var newRCB = new ReportControlBlock (rcbObjectReference, this, connection); var newRCB = new ReportControlBlock(rcbObjectReference, this, connection);
if (activeRCBs == null) if (activeRCBs == null)
activeRCBs = new List<ReportControlBlock> (); activeRCBs = new List<ReportControlBlock>();
activeRCBs.Add (newRCB); activeRCBs.Add(newRCB);
return newRCB; return newRCB;
} }
internal void RemoveRCB(ReportControlBlock rcb) { internal void RemoveRCB(ReportControlBlock rcb)
if (activeRCBs != null) { {
activeRCBs.Remove (rcb); if (activeRCBs != null)
{
activeRCBs.Remove(rcb);
} }
} }
} }
[Flags]
public enum ReasonForInclusion public enum ReasonForInclusion
{ {
/** the element is not included in the received report */ /** the element is not included in the received report */
@ -67,16 +70,16 @@ namespace IEC61850
REASON_QUALITY_CHANGE = 2, REASON_QUALITY_CHANGE = 2,
/** the element is included due to an update of the data value */ /** the element is included due to an update of the data value */
REASON_DATA_UPDATE = 3, REASON_DATA_UPDATE = 4,
/** the element is included due to a periodic integrity report task */ /** the element is included due to a periodic integrity report task */
REASON_INTEGRITY = 4, REASON_INTEGRITY = 8,
/** the element is included due to a general interrogation by the client */ /** the element is included due to a general interrogation by the client */
REASON_GI = 5, REASON_GI = 16,
/** the reason for inclusion is unknown */ /** the reason for inclusion is unknown */
REASON_UNKNOWN = 6 REASON_UNKNOWN = 32
} }
/// <summary> /// <summary>
@ -87,10 +90,10 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)] [return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReport_hasTimestamp (IntPtr self); static extern bool ClientReport_hasTimestamp(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt64 ClientReport_getTimestamp (IntPtr self); static extern UInt64 ClientReport_getTimestamp(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getDataSetValues(IntPtr self); static extern IntPtr ClientReport_getDataSetValues(IntPtr self);
@ -162,7 +165,7 @@ namespace IEC61850
private MmsValue values = null; private MmsValue values = null;
internal Report (IntPtr self) internal Report(IntPtr self)
{ {
this.self = self; this.self = self;
} }
@ -173,9 +176,9 @@ namespace IEC61850
/// <returns> /// <returns>
/// <c>true</c> if this report has a timestamp; otherwise, <c>false</c>. /// <c>true</c> if this report has a timestamp; otherwise, <c>false</c>.
/// </returns> /// </returns>
public bool HasTimestamp () public bool HasTimestamp()
{ {
return ClientReport_hasTimestamp (self); return ClientReport_hasTimestamp(self);
} }
/// <summary> /// <summary>
@ -184,40 +187,40 @@ namespace IEC61850
/// <returns> /// <returns>
/// The timestamp as milliseconds since 1.1.1970 UTC 00:00 or 0 if no timestamp is present. /// The timestamp as milliseconds since 1.1.1970 UTC 00:00 or 0 if no timestamp is present.
/// </returns> /// </returns>
public UInt64 GetTimestamp () public UInt64 GetTimestamp()
{ {
if (HasTimestamp ()) if (HasTimestamp())
return ClientReport_getTimestamp (self); return ClientReport_getTimestamp(self);
else else
return 0; return 0;
} }
public bool HasDataSetName () public bool HasDataSetName()
{ {
return ClientReport_hasDataSetName(self); return ClientReport_hasDataSetName(self);
} }
public bool HasDataReference () public bool HasDataReference()
{ {
return ClientReport_hasDataReference(self); return ClientReport_hasDataReference(self);
} }
public bool HasConfRev () public bool HasConfRev()
{ {
return ClientReport_hasConfRev(self); return ClientReport_hasConfRev(self);
} }
public UInt32 GetConfRev () public UInt32 GetConfRev()
{ {
return ClientReport_getConfRev(self); return ClientReport_getConfRev(self);
} }
public bool HasBufOvfl () public bool HasBufOvfl()
{ {
return ClientReport_hasBufOvfl(self); return ClientReport_hasBufOvfl(self);
} }
public bool GetBufOvfl () public bool GetBufOvfl()
{ {
return ClientReport_getBufOvfl(self); return ClientReport_getBufOvfl(self);
} }
@ -226,7 +229,7 @@ namespace IEC61850
/// Indicates if the report contains a sequence number (SeqNum) field /// Indicates if the report contains a sequence number (SeqNum) field
/// </summary> /// </summary>
/// <returns><c>true</c> if this instance has SeqNum; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if this instance has SeqNum; otherwise, <c>false</c>.</returns>
public bool HasSeqNum () public bool HasSeqNum()
{ {
return ClientReport_hasSeqNum(self); return ClientReport_hasSeqNum(self);
} }
@ -235,7 +238,7 @@ namespace IEC61850
/// Gets the value of the SeqNum field /// Gets the value of the SeqNum field
/// </summary> /// </summary>
/// <returns>The report sequence number</returns> /// <returns>The report sequence number</returns>
public UInt16 GetSeqNum () public UInt16 GetSeqNum()
{ {
return ClientReport_getSeqNum(self); return ClientReport_getSeqNum(self);
} }
@ -271,7 +274,7 @@ namespace IEC61850
/// Determines whether this report contains reason for inclusion information /// Determines whether this report contains reason for inclusion information
/// </summary> /// </summary>
/// <returns><c>true</c> if this report contains reason for inclusion information; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if this report contains reason for inclusion information; otherwise, <c>false</c>.</returns>
public bool HasReasonForInclusion () public bool HasReasonForInclusion()
{ {
return ClientReport_hasReasonForInclusion(self); return ClientReport_hasReasonForInclusion(self);
} }
@ -282,9 +285,10 @@ namespace IEC61850
/// <returns> /// <returns>
/// The data set values. /// The data set values.
/// </returns> /// </returns>
public MmsValue GetDataSetValues () public MmsValue GetDataSetValues()
{
if (dataSetValues == IntPtr.Zero)
{ {
if (dataSetValues == IntPtr.Zero) {
dataSetValues = ClientReport_getDataSetValues(self); dataSetValues = ClientReport_getDataSetValues(self);
if (dataSetValues == IntPtr.Zero) if (dataSetValues == IntPtr.Zero)
@ -305,10 +309,11 @@ namespace IEC61850
/// <param name='index'> /// <param name='index'>
/// index of the data set member in the data set /// index of the data set member in the data set
/// </param> /// </param>
public ReasonForInclusion GetReasonForInclusion (int index) public ReasonForInclusion GetReasonForInclusion(int index)
{ {
if (values == null) { if (values == null)
GetDataSetValues (); {
GetDataSetValues();
if (values == null) if (values == null)
throw new IedConnectionException("No ReasonForInclusion available yet"); throw new IedConnectionException("No ReasonForInclusion available yet");
@ -319,21 +324,21 @@ namespace IEC61850
if (index >= dataSetSize) if (index >= dataSetSize)
throw new IedConnectionException("data set index out of range (count = " + dataSetSize + ")"); throw new IedConnectionException("data set index out of range (count = " + dataSetSize + ")");
return (ReasonForInclusion) ClientReport_getReasonForInclusion(self, index); return (ReasonForInclusion)ClientReport_getReasonForInclusion(self, index);
} }
public string GetRcbReference () public string GetRcbReference()
{ {
IntPtr rcbRef = ClientReport_getRcbReference(self); IntPtr rcbRef = ClientReport_getRcbReference(self);
return Marshal.PtrToStringAnsi (rcbRef); return Marshal.PtrToStringAnsi(rcbRef);
} }
public string GetDataSetName () public string GetDataSetName()
{ {
IntPtr dataSetName = ClientReport_getDataSetName (self); IntPtr dataSetName = ClientReport_getDataSetName(self);
return Marshal.PtrToStringAnsi (dataSetName); return Marshal.PtrToStringAnsi(dataSetName);
} }
/// <summary> /// <summary>
@ -345,7 +350,7 @@ namespace IEC61850
/// <param name='index'> /// <param name='index'>
/// index of the data set element starting with 0 /// index of the data set element starting with 0
/// </param> /// </param>
public string GetDataReference (int index) public string GetDataReference(int index)
{ {
IntPtr dataRef = ClientReport_getDataReference(self, index); IntPtr dataRef = ClientReport_getDataReference(self, index);
@ -355,30 +360,31 @@ namespace IEC61850
return null; return null;
} }
public string GetRptId () public string GetRptId()
{ {
IntPtr rptId = ClientReport_getRptId(self); IntPtr rptId = ClientReport_getRptId(self);
if (rptId == IntPtr.Zero) if (rptId == IntPtr.Zero)
return GetRcbReference(); return GetRcbReference();
else else
return Marshal.PtrToStringAnsi (rptId); return Marshal.PtrToStringAnsi(rptId);
} }
/// <summary> /// <summary>
/// Gets the EntryID of this report. /// Gets the EntryID of this report.
/// </summary> /// </summary>
/// <returns>The entryID as a byte array representing an MMS octet string.</returns> /// <returns>The entryID as a byte array representing an MMS octet string.</returns>
public byte[] GetEntryId () public byte[] GetEntryId()
{ {
IntPtr entryIdRef = ClientReport_getEntryId (self); IntPtr entryIdRef = ClientReport_getEntryId(self);
if (entryIdRef == IntPtr.Zero) if (entryIdRef == IntPtr.Zero)
return null; return null;
else { else
MmsValue entryId = new MmsValue (entryIdRef); {
MmsValue entryId = new MmsValue(entryIdRef);
return entryId.getOctetString (); return entryId.getOctetString();
} }
} }

@ -716,16 +716,18 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
goto exit_function; goto exit_function;
} }
matchingReport->reasonForInclusion[i] = 0;
if (MmsValue_getBitStringBit(reasonForInclusion, 1) == true) if (MmsValue_getBitStringBit(reasonForInclusion, 1) == true)
matchingReport->reasonForInclusion[i] = IEC61850_REASON_DATA_CHANGE; matchingReport->reasonForInclusion[i] |= IEC61850_REASON_DATA_CHANGE;
else if (MmsValue_getBitStringBit(reasonForInclusion, 2) == true) if (MmsValue_getBitStringBit(reasonForInclusion, 2) == true)
matchingReport->reasonForInclusion[i] = IEC61850_REASON_QUALITY_CHANGE; matchingReport->reasonForInclusion[i] |= IEC61850_REASON_QUALITY_CHANGE;
else if (MmsValue_getBitStringBit(reasonForInclusion, 3) == true) if (MmsValue_getBitStringBit(reasonForInclusion, 3) == true)
matchingReport->reasonForInclusion[i] = IEC61850_REASON_DATA_UPDATE; matchingReport->reasonForInclusion[i] |= IEC61850_REASON_DATA_UPDATE;
else if (MmsValue_getBitStringBit(reasonForInclusion, 4) == true) if (MmsValue_getBitStringBit(reasonForInclusion, 4) == true)
matchingReport->reasonForInclusion[i] = IEC61850_REASON_INTEGRITY; matchingReport->reasonForInclusion[i] |= IEC61850_REASON_INTEGRITY;
else if (MmsValue_getBitStringBit(reasonForInclusion, 5) == true) if (MmsValue_getBitStringBit(reasonForInclusion, 5) == true)
matchingReport->reasonForInclusion[i] = IEC61850_REASON_GI; matchingReport->reasonForInclusion[i] |= IEC61850_REASON_GI;
} }
else { else {
matchingReport->reasonForInclusion[i] = IEC61850_REASON_UNKNOWN; matchingReport->reasonForInclusion[i] = IEC61850_REASON_UNKNOWN;

@ -1116,16 +1116,16 @@ typedef enum {
IEC61850_REASON_QUALITY_CHANGE = 2, IEC61850_REASON_QUALITY_CHANGE = 2,
/** the element is included due to an update of the data value */ /** the element is included due to an update of the data value */
IEC61850_REASON_DATA_UPDATE = 3, IEC61850_REASON_DATA_UPDATE = 4,
/** the element is included due to a periodic integrity report task */ /** the element is included due to a periodic integrity report task */
IEC61850_REASON_INTEGRITY = 4, IEC61850_REASON_INTEGRITY = 8,
/** the element is included due to a general interrogation by the client */ /** the element is included due to a general interrogation by the client */
IEC61850_REASON_GI = 5, IEC61850_REASON_GI = 16,
/** the reason for inclusion is unknown (e.g. report is not configured to include reason-for-inclusion) */ /** the reason for inclusion is unknown (e.g. report is not configured to include reason-for-inclusion) */
IEC61850_REASON_UNKNOWN = 6 IEC61850_REASON_UNKNOWN = 32
} ReasonForInclusion; } ReasonForInclusion;
#define REASON_NOT_INCLUDED IEC61850_REASON_NOT_INCLUDED #define REASON_NOT_INCLUDED IEC61850_REASON_NOT_INCLUDED

Loading…
Cancel
Save