- IEC 61850 client: improved support for segmented report handling

pull/80/head
Michael Zillgith 7 years ago
parent cd81f9b13d
commit 59e2d19acc

@ -1,3 +1,12 @@
Changes to version 1.3.1
------------------------
- IEC 61850 client: improved support for handling segmented reports
- .NET API: Added some additional access function to ReportControlBlock
- Java SCL parser: added support for timestamp values in "Val" elements
- fixed bug in cmake file (winpcap support)
- added C# example code for client side setting group handling
- .NET API: added some additional wrapper code for MmsVariableSpecification functions
Changes to version 1.3.0 Changes to version 1.3.0
------------------------ ------------------------
- IEC 61850 server: more features configurable at runtime - IEC 61850 server: more features configurable at runtime
@ -17,7 +26,6 @@ Changes to version 1.3.0
- MMS server: fixed bug in delete variable list service - scope of delete was not considered optional - MMS server: fixed bug in delete variable list service - scope of delete was not considered optional
- some more small bug fixes and optimizations - some more small bug fixes and optimizations
Changes to version 1.2.2 Changes to version 1.2.2
------------------------ ------------------------

@ -1,7 +1,7 @@
/* /*
* Reporting.cs * Reporting.cs
* *
* Copyright 2014 Michael Zillgith * Copyright 2014-2018 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -147,6 +147,15 @@ namespace IEC61850
[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);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool ClientReport_hasSubSeqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientReport_getSubSeqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool ClientReport_getMoreSeqmentsFollow(IntPtr self);
private IntPtr self; private IntPtr self;
private IntPtr dataSetValues = IntPtr.Zero; private IntPtr dataSetValues = IntPtr.Zero;
@ -213,16 +222,55 @@ namespace IEC61850
return ClientReport_getBufOvfl(self); return ClientReport_getBufOvfl(self);
} }
/// <summary>
/// Indicates if the report contains a sequence number (SeqNum) field
/// </summary>
/// <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);
} }
/// <summary>
/// Gets the value of the SeqNum field
/// </summary>
/// <returns>The report sequence number</returns>
public UInt16 GetSeqNum () public UInt16 GetSeqNum ()
{ {
return ClientReport_getSeqNum(self); return ClientReport_getSeqNum(self);
} }
/// <summary>
/// Indicates if the report contains a sub sequence number (SubSeqNum) and more segments follow (MoreSegmentsFollow) field
/// </summary>
/// <returns><c>true</c> if this instance has SubSeqNum and MoreSegmentsFollow; otherwise, <c>false</c>.</returns>
public bool HasSubSeqNum()
{
return ClientReport_hasSubSeqNum(self);
}
/// <summary>
/// Gets the sub sequence number (SubSeqNum) value of a segmented report
/// </summary>
/// <returns>The sub sequence number.</returns>
public UInt16 GetSubSeqNum()
{
return ClientReport_getSubSeqNum(self);
}
/// <summary>
/// Gets the more segments follow (MoreSegmentsFollow) flag
/// </summary>
/// <returns><c>true</c>, if more report segments follow, <c>false</c> otherwise.</returns>
public bool GetMoreSegmentsFollow()
{
return ClientReport_getMoreSeqmentsFollow(self);
}
/// <summary>
/// Determines whether this report contains reason for inclusion information
/// </summary>
/// <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);

@ -3,7 +3,7 @@
* *
* Client implementation for IEC 61850 reporting. * Client implementation for IEC 61850 reporting.
* *
* Copyright 2013, 2014 Michael Zillgith * Copyright 2013-2018 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -56,11 +56,15 @@ struct sClientReport
bool hasConfRev; bool hasConfRev;
bool hasTimestamp; bool hasTimestamp;
bool hasBufOverflow; bool hasBufOverflow;
bool hasSubSequenceNumber;
uint64_t timestamp; uint64_t timestamp;
uint16_t seqNum; uint16_t seqNum;
uint32_t confRev; uint32_t confRev;
bool bufOverflow; bool bufOverflow;
uint16_t subSeqNum;
bool moreSegementsFollow;
}; };
char* char*
@ -242,6 +246,24 @@ ClientReport_getDataSetValues(ClientReport self)
return self->dataSetValues; return self->dataSetValues;
} }
bool
ClientReport_hasSubSeqNum(ClientReport self)
{
return self->hasSubSequenceNumber;
}
uint16_t
ClientReport_getSubSeqNum(ClientReport self)
{
return self->subSeqNum;
}
bool
ClientReport_getMoreSeqmentsFollow(ClientReport self)
{
return self->moreSegementsFollow;
}
static ClientReport static ClientReport
lookupReportHandler(IedConnection self, const char* rcbReference) lookupReportHandler(IedConnection self, const char* rcbReference)
{ {
@ -386,6 +408,7 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
matchingReport->hasConfRev = false; matchingReport->hasConfRev = false;
matchingReport->hasDataSetName = false; matchingReport->hasDataSetName = false;
matchingReport->hasBufOverflow = false; matchingReport->hasBufOverflow = false;
matchingReport->hasSubSequenceNumber = false;
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received report with ID %s\n", MmsValue_toString(rptIdValue)); printf("IED_CLIENT: received report with ID %s\n", MmsValue_toString(rptIdValue));
@ -535,10 +558,43 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
inclusionIndex++; inclusionIndex++;
} }
/* handle segmentation fields (check ReportedOptFlds.segmentation) */
if (MmsValue_getBitStringBit(optFlds, 9) == true) {
MmsValue* subSeqNum = MmsValue_getElement(value, inclusionIndex);
inclusionIndex++;
if ((subSeqNum == NULL) || (MmsValue_getType(subSeqNum) != MMS_UNSIGNED)) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (SubSeqNum)\n");
goto exit_function;
}
else {
matchingReport->subSeqNum = (uint16_t) MmsValue_toUint32(subSeqNum);
}
MmsValue* moreSegmentsFollow = MmsValue_getElement(value, inclusionIndex);
inclusionIndex++;
if ((moreSegmentsFollow == NULL) || (MmsValue_getType(moreSegmentsFollow) != MMS_BOOLEAN)) {
if ((subSeqNum == NULL) || (MmsValue_getType(subSeqNum) != MMS_UNSIGNED)) {
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received malformed report (MoreSegmentsFollow)\n");
goto exit_function;
}
}
else {
matchingReport->moreSegementsFollow = MmsValue_getBoolean(moreSegmentsFollow);
}
/* skip segmentation fields */ matchingReport->hasSequenceNumber = true;
if (MmsValue_getBitStringBit(optFlds, 9) == true) }
inclusionIndex += 2; else {
matchingReport->subSeqNum = 0;
matchingReport->moreSegementsFollow = false;
}
MmsValue* inclusion = MmsValue_getElement(value, inclusionIndex); MmsValue* inclusion = MmsValue_getElement(value, inclusionIndex);

@ -1057,6 +1057,42 @@ ClientReport_getDataReference(ClientReport self, int elementIndex);
uint64_t uint64_t
ClientReport_getTimestamp(ClientReport self); ClientReport_getTimestamp(ClientReport self);
/**
* \brief indicates if the report contains a sub sequence number and a more segments follow flags (for segmented reporting)
*
* \param self the ClientReport instance
*
* \returns true if the report contains sub-sequence-number and more-follows-flag, false otherwise
*/
LIB61850_API bool
ClientReport_hasSubSeqNum(ClientReport self);
/**
* \brief get the sub sequence number of the report (for segmented reporting)
*
* Returns the sub sequence number of the report. This is 0 for the first report of a segmented report and
* will be increased by one for each report segment.
*
* \param self the ClientReport instance
*
* \return the sub sequence number of the last received report message.
*/
LIB61850_API uint16_t
ClientReport_getSubSeqNum(ClientReport self);
/**
* \brief get the more segments follow flag of the received report segment (for segmented reporting)
*
* Will return true in case this is part of a segmented report and more report segments will follow or false, if
* the current report is not a segmented report or is the last segment of a segmented report.
*
* \param self the ClientReport instance
*
* \return true when more segments of the current report will follow, false otherwise
*/
LIB61850_API bool
ClientReport_getMoreSeqmentsFollow(ClientReport self);
/** /**
* \brief get the reason for inclusion of as a human readable string * \brief get the reason for inclusion of as a human readable string
* *

Loading…
Cancel
Save