- IEC 61850 client: improved support for segmented report handling

pull/93/head
Michael Zillgith 7 years ago
parent e90d5d44fa
commit 836892849c

@ -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
------------------------
- 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
- some more small bug fixes and optimizations
Changes to version 1.2.2
------------------------

@ -1,7 +1,7 @@
/*
* Reporting.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2018 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -147,6 +147,15 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
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 dataSetValues = IntPtr.Zero;
@ -213,16 +222,55 @@ namespace IEC61850
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 ()
{
return ClientReport_hasSeqNum(self);
}
/// <summary>
/// Gets the value of the SeqNum field
/// </summary>
/// <returns>The report sequence number</returns>
public UInt16 GetSeqNum ()
{
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 ()
{
return ClientReport_hasReasonForInclusion(self);

@ -3,7 +3,7 @@
*
* Client implementation for IEC 61850 reporting.
*
* Copyright 2013, 2014 Michael Zillgith
* Copyright 2013-2018 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -56,11 +56,15 @@ struct sClientReport
bool hasConfRev;
bool hasTimestamp;
bool hasBufOverflow;
bool hasSubSequenceNumber;
uint64_t timestamp;
uint16_t seqNum;
uint32_t confRev;
bool bufOverflow;
uint16_t subSeqNum;
bool moreSegementsFollow;
};
char*
@ -242,6 +246,24 @@ ClientReport_getDataSetValues(ClientReport self)
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
lookupReportHandler(IedConnection self, const char* rcbReference)
{
@ -386,6 +408,7 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
matchingReport->hasConfRev = false;
matchingReport->hasDataSetName = false;
matchingReport->hasBufOverflow = false;
matchingReport->hasSubSequenceNumber = false;
if (DEBUG_IED_CLIENT)
printf("IED_CLIENT: received report with ID %s\n", MmsValue_toString(rptIdValue));
@ -535,10 +558,43 @@ iedConnection_handleReport(IedConnection self, MmsValue* value)
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 */
if (MmsValue_getBitStringBit(optFlds, 9) == true)
inclusionIndex += 2;
matchingReport->hasSequenceNumber = true;
}
else {
matchingReport->subSeqNum = 0;
matchingReport->moreSegementsFollow = false;
}
MmsValue* inclusion = MmsValue_getElement(value, inclusionIndex);

@ -1336,6 +1336,42 @@ ClientReport_getDataReference(ClientReport self, int elementIndex);
LIB61850_API uint64_t
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
*

Loading…
Cancel
Save