From bafe27a0e8a17ffb86bbed6a1c393f51e5cfbd05 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Tue, 29 Sep 2020 17:41:42 +0200 Subject: [PATCH] - IED server: add support for tissue 807 (owner attribute in RCB is only present when ReportSettings@owner attribute is true) --- src/iec61850/inc/iec61850_common.h | 3 + src/iec61850/inc_private/reporting.h | 2 + src/iec61850/server/mms_mapping/reporting.c | 88 ++++++++++++--------- 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/iec61850/inc/iec61850_common.h b/src/iec61850/inc/iec61850_common.h index 345d57e3..c3202ef3 100644 --- a/src/iec61850/inc/iec61850_common.h +++ b/src/iec61850/inc/iec61850_common.h @@ -107,6 +107,9 @@ typedef enum { /** Report will be triggered by GI (general interrogation) request */ #define TRG_OPT_GI 16 +/** RCB has the owner attribute */ +#define RPT_OPT_HAS_OWNER 64 + /** Report will be triggered only on rising edge (transient variable */ #define TRG_OPT_TRANSIENT 128 /** @} */ diff --git a/src/iec61850/inc_private/reporting.h b/src/iec61850/inc_private/reporting.h index 784bd300..b6d0bb75 100644 --- a/src/iec61850/inc_private/reporting.h +++ b/src/iec61850/inc_private/reporting.h @@ -79,6 +79,8 @@ typedef struct { int triggerOps; + bool hasOwner; /* indicate that owner field is present */ + /* information for segmented reporting */ bool segmented; /* indicates that a segmented report is in process */ int startIndexForNextSegment; /* start data set index for the next report segment */ diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index f049219a..8f870227 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -122,6 +122,7 @@ ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize, self->timeOfEntry = NULL; self->reservationTimeout = 0; self->triggerOps = 0; + self->hasOwner = false; #if (CONFIG_MMS_THREADLESS_STACK != 1) self->createNotificationsMutex = Semaphore_create(1); @@ -941,12 +942,12 @@ createUnbufferedReportControlBlock(ReportControlBlock* reportControlBlock, mmsValue->deleteValue = false; mmsValue->type = MMS_STRUCTURE; - int structSize; + int structSize = 11; - if (reportControl->server->edition >= IEC_61850_EDITION_2) - structSize = 12; - else - structSize = 11; + if (reportControl->server->edition >= IEC_61850_EDITION_2) { + if (reportControl->hasOwner) + structSize = 12; + } mmsValue->value.structure.size = structSize; mmsValue->value.structure.components = (MmsValue**) GLOBAL_CALLOC(structSize, sizeof(MmsValue*)); @@ -1049,21 +1050,24 @@ createUnbufferedReportControlBlock(ReportControlBlock* reportControlBlock, mmsValue->value.structure.components[10] = MmsValue_newBoolean(false); if (reportControl->server->edition >= IEC_61850_EDITION_2) { - namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); - namedVariable->name = StringUtils_copyString("Owner"); - namedVariable->type = MMS_OCTET_STRING; - namedVariable->typeSpec.octetString = -64; - rcb->typeSpec.structure.elements[11] = namedVariable; - mmsValue->value.structure.components[11] = MmsValue_newOctetString(0, 16); /* size 16 is enough to store client IPv6 address */ - /* initialize pre configured owner */ - if (reportControlBlock->clientReservation[0] == 4) { - reportControl->resvTms = -1; - MmsValue_setOctetString(mmsValue->value.structure.components[11], reportControlBlock->clientReservation + 1, 4); - } - else if (reportControlBlock->clientReservation[0] == 6) { - reportControl->resvTms = -1; - MmsValue_setOctetString(mmsValue->value.structure.components[11], reportControlBlock->clientReservation + 1, 16); + if (reportControl->hasOwner) { + namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); + namedVariable->name = StringUtils_copyString("Owner"); + namedVariable->type = MMS_OCTET_STRING; + namedVariable->typeSpec.octetString = -64; + rcb->typeSpec.structure.elements[11] = namedVariable; + mmsValue->value.structure.components[11] = MmsValue_newOctetString(0, 16); /* size 16 is enough to store client IPv6 address */ + + /* initialize pre configured owner */ + if (reportControlBlock->clientReservation[0] == 4) { + reportControl->resvTms = -1; + MmsValue_setOctetString(mmsValue->value.structure.components[11], reportControlBlock->clientReservation + 1, 4); + } + else if (reportControlBlock->clientReservation[0] == 6) { + reportControl->resvTms = -1; + MmsValue_setOctetString(mmsValue->value.structure.components[11], reportControlBlock->clientReservation + 1, 16); + } } } @@ -1094,7 +1098,8 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock, brcbElementCount++; #endif - brcbElementCount++; + if (reportControl->hasOwner) + brcbElementCount++; } MmsValue* mmsValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); @@ -1221,6 +1226,9 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock, int currentIndex = 13; #if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) + + int resvTmsIndex = currentIndex; + namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable->name = StringUtils_copyString("ResvTms"); namedVariable->type = MMS_INTEGER; @@ -1230,25 +1238,27 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock, currentIndex++; #endif /* (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) */ - namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); - namedVariable->name = StringUtils_copyString("Owner"); - namedVariable->type = MMS_OCTET_STRING; - namedVariable->typeSpec.octetString = -64; - rcb->typeSpec.structure.elements[currentIndex] = namedVariable; - mmsValue->value.structure.components[currentIndex] = MmsValue_newOctetString(0, 16); /* size 16 is enough to store client IPv6 address */ + if (reportControl->hasOwner) { + namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); + namedVariable->name = StringUtils_copyString("Owner"); + namedVariable->type = MMS_OCTET_STRING; + namedVariable->typeSpec.octetString = -64; + rcb->typeSpec.structure.elements[currentIndex] = namedVariable; + mmsValue->value.structure.components[currentIndex] = MmsValue_newOctetString(0, 16); /* size 16 is enough to store client IPv6 address */ - /* initialize pre configured owner */ - if (reportControlBlock->clientReservation[0] == 4) { - reportControl->resvTms = -1; - MmsValue_setOctetString(mmsValue->value.structure.components[currentIndex], reportControlBlock->clientReservation + 1, 4); - } - else if (reportControlBlock->clientReservation[0] == 6) { - reportControl->resvTms = -1; - MmsValue_setOctetString(mmsValue->value.structure.components[currentIndex], reportControlBlock->clientReservation + 1, 16); + /* initialize pre configured owner */ + if (reportControlBlock->clientReservation[0] == 4) { + reportControl->resvTms = -1; + MmsValue_setOctetString(mmsValue->value.structure.components[currentIndex], reportControlBlock->clientReservation + 1, 4); + } + else if (reportControlBlock->clientReservation[0] == 6) { + reportControl->resvTms = -1; + MmsValue_setOctetString(mmsValue->value.structure.components[currentIndex], reportControlBlock->clientReservation + 1, 16); + } } #if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) - MmsValue_setInt16(mmsValue->value.structure.components[13], reportControl->resvTms); + MmsValue_setInt16(mmsValue->value.structure.components[resvTmsIndex], reportControl->resvTms); #endif } @@ -1311,6 +1321,9 @@ Reporting_createMmsBufferedRCBs(MmsMapping* self, MmsDomain* domain, ReportControlBlock* reportControlBlock = getRCBForLogicalNodeWithIndex( self, logicalNode, currentReport, true); + if (reportControlBlock->trgOps & RPT_OPT_HAS_OWNER) + rc->hasOwner = true; + rc->name = StringUtils_createString(3, logicalNode->name, "$BR$", reportControlBlock->name); @@ -1348,6 +1361,9 @@ Reporting_createMmsUnbufferedRCBs(MmsMapping* self, MmsDomain* domain, ReportControlBlock* reportControlBlock = getRCBForLogicalNodeWithIndex( self, logicalNode, currentReport, false); + if (reportControlBlock->trgOps & RPT_OPT_HAS_OWNER) + rc->hasOwner = true; + rc->name = StringUtils_createString(3, logicalNode->name, "$RP$", reportControlBlock->name); @@ -1393,7 +1409,7 @@ updateOwner(ReportControl* rc, MmsServerConnection connection) { rc->clientConnection = connection; - if (rc->server->edition >= IEC_61850_EDITION_2) { + if (rc->server->edition >= IEC_61850_EDITION_2 && rc->hasOwner) { MmsValue* owner = ReportControl_getRCBValue(rc, "Owner");