From bbccffb65af645f99bf9eaa41cd25e2a0c3abea7 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Mon, 20 Jul 2015 10:37:40 +0200 Subject: [PATCH] - added function LogicalNode_getDataSet --- config/stack_config.h | 6 +-- src/goose/goose_publisher.c | 5 +++ src/goose/goose_receiver.c | 7 +++ src/iec61850/inc/iec61850_model.h | 11 +++++ src/iec61850/inc/iec61850_server.h | 6 ++- src/iec61850/inc_private/mms_mapping.h | 2 +- src/iec61850/server/impl/ied_server.c | 35 +++++++++------ src/iec61850/server/mms_mapping/mms_goose.c | 1 - src/iec61850/server/mms_mapping/mms_mapping.c | 13 ++++-- src/iec61850/server/model/model.c | 40 ++++++++++++++++++ src/mms/iso_mms/server/mms_access_result.c | 18 ++++---- tools/model_generator/genmodel.jar | Bin 75201 -> 75201 bytes 12 files changed, 111 insertions(+), 33 deletions(-) diff --git a/config/stack_config.h b/config/stack_config.h index 72245fdd..74622810 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -10,7 +10,7 @@ #define STACK_CONFIG_H_ /* include asserts if set to 1 */ -#define DEBUG 1 +#define DEBUG 0 /* print debugging information with printf if set to 1 */ #define DEBUG_SOCKET 0 @@ -21,7 +21,7 @@ #define DEBUG_IED_CLIENT 0 #define DEBUG_MMS_CLIENT 0 #define DEBUG_MMS_SERVER 0 -#define DEBUG_GOOSE_SUBSCRIBER 1 +#define DEBUG_GOOSE_SUBSCRIBER 0 #define DEBUG_GOOSE_PUBLISHER 0 /* Maximum MMS PDU SIZE - default is 65000 */ @@ -136,7 +136,7 @@ #define CONFIG_IEC61850_SETTING_GROUPS 1 /* default reservation time of a setting group control block in s */ -#define CONFIG_IEC61850_SG_RESVTMS 10 +#define CONFIG_IEC61850_SG_RESVTMS 300 /* default results for MMS identify service */ #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" diff --git a/src/goose/goose_publisher.c b/src/goose/goose_publisher.c index c09466ee..cea381c4 100644 --- a/src/goose/goose_publisher.c +++ b/src/goose/goose_publisher.c @@ -376,6 +376,11 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet) if (DEBUG_GOOSE_PUBLISHER) printf("GOOSE_PUBLISHER: send GOOSE message\n"); + struct timeval tv; + + gettimeofday(&tv,NULL/*&tz*/); + printf("GOOSE SEND: %ld %ld\n",tv.tv_sec, tv.tv_usec); + Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + payloadLength); return 0; diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c index 960073a3..201fcf93 100644 --- a/src/goose/goose_receiver.c +++ b/src/goose/goose_receiver.c @@ -612,6 +612,13 @@ exit_with_fault: static void parseGooseMessage(GooseReceiver self, int numbytes) { + struct timeval tv; + + gettimeofday(&tv,NULL/*&tz*/); + + printf("RCVD GOOSE: %ld %ld\n",tv.tv_sec, tv.tv_usec); + + int bufPos; bool subscriberFound = false; uint8_t* buffer = self->buffer; diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h index f8d36e63..338c5038 100644 --- a/src/iec61850/inc/iec61850_model.h +++ b/src/iec61850/inc/iec61850_model.h @@ -416,6 +416,17 @@ LogicalNode_hasBufferedReports(LogicalNode* node); bool LogicalNode_hasUnbufferedReports(LogicalNode* node); +/** + * \brief get a data set instance + * + * \param self the logical node instance of the data set + * \param dataSetName the name of the data set + * + * \return the data set instance or NULL if the data set does not exist + */ +DataSet* +LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName); + bool DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc); diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 263f6f52..834a4673 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -960,11 +960,12 @@ IedServer_observeDataAttribute(IedServer self, DataAttribute* dataAttribute, * \param the data attribute that has been written by an MMS client. * \param the value the client want to write to the data attribute * \param connection the connection object of the client connection that invoked the write operation + * \param parameter the user provided parameter * * \return true if access is accepted, false if access is denied. */ typedef MmsDataAccessError -(*WriteAccessHandler) (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection); +(*WriteAccessHandler) (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter); /** * \brief Install a WriteAccessHandler for a data attribute. @@ -979,10 +980,11 @@ typedef MmsDataAccessError * \param dataAttribute the data attribute to monitor * \param handler the callback function that is invoked if a client tries to write to * the monitored data attribute. + * \param parameter a user provided parameter that is passed to the WriteAccessHandler when called. */ void IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, - WriteAccessHandler handler); + WriteAccessHandler handler, void* parameter); typedef enum { ACCESS_POLICY_ALLOW, diff --git a/src/iec61850/inc_private/mms_mapping.h b/src/iec61850/inc_private/mms_mapping.h index 527a72c9..11e7a778 100644 --- a/src/iec61850/inc_private/mms_mapping.h +++ b/src/iec61850/inc_private/mms_mapping.h @@ -139,7 +139,7 @@ void MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicationHandler handler, void* parameter); void -MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler); +MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter); MmsDataAccessError Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index d630087f..d7622e37 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -476,7 +476,7 @@ singleThreadedServerThread(void* parameter) while (running) { - if (IedServer_waitReady(self, 100) > 0) { + if (IedServer_waitReady(self, 25) > 0) { MmsServer_handleIncomingMessages(self->mmsServer); IedServer_performPeriodicTasks(self); } @@ -770,26 +770,26 @@ checkForChangedTriggers(IedServer self, DataAttribute* dataAttribute) #if (CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) if (dataAttribute->triggerOptions & TRG_OPT_DATA_CHANGED) { +#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) + MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue); +#endif + #if (CONFIG_IEC61850_REPORT_SERVICE == 1) MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue, REPORT_CONTROL_VALUE_CHANGED); #endif + } + + else if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) { #if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue); #endif - } - - else if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) { #if (CONFIG_IEC61850_REPORT_SERVICE == 1) MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue, REPORT_CONTROL_QUALITY_CHANGED); #endif - -#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) - MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue); -#endif } #endif /* (CONFIG_IEC61850_REPORT_SERVICE== 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */ @@ -916,9 +916,16 @@ IedServer_updateBooleanAttributeValue(IedServer self, DataAttribute* dataAttribu bool currentValue = MmsValue_getBoolean(dataAttribute->mmsValue); if (currentValue == value) { + checkForUpdateTrigger(self, dataAttribute); } else { +// struct timeval tv; +// +// gettimeofday(&tv,NULL/*&tz*/); +// printf("UPDATE BOOL: %ld %ld\n",tv.tv_sec, tv.tv_usec); + + MmsValue_setBoolean(dataAttribute->mmsValue, value); checkForChangedTriggers(self, dataAttribute); @@ -993,15 +1000,15 @@ IedServer_updateQuality(IedServer self, DataAttribute* dataAttribute, Quality qu if (oldQuality != (uint32_t) quality) { MmsValue_setBitStringFromInteger(dataAttribute->mmsValue, (uint32_t) quality); +#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) + MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue); +#endif + #if (CONFIG_IEC61850_REPORT_SERVICE == 1) if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_CHANGED) MmsMapping_triggerReportObservers(self->mmsMapping, dataAttribute->mmsValue, REPORT_CONTROL_QUALITY_CHANGED); #endif - -#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) - MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue); -#endif } @@ -1079,12 +1086,12 @@ IedServer_setWriteAccessPolicy(IedServer self, FunctionalConstraint fc, AccessPo } void -IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler) +IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter) { if (dataAttribute == NULL) *((int*) NULL) = 1; - MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler); + MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler, parameter); } void diff --git a/src/iec61850/server/mms_mapping/mms_goose.c b/src/iec61850/server/mms_mapping/mms_goose.c index e4c0678c..8b9d723f 100644 --- a/src/iec61850/server/mms_mapping/mms_goose.c +++ b/src/iec61850/server/mms_mapping/mms_goose.c @@ -169,7 +169,6 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self) if (!MmsGooseControlBlock_isEnabled(self)) { - if (self->dataSetRef != NULL) { GLOBAL_FREEMEM(self->dataSetRef); diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index c3fcc93c..7d14eabf 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -50,6 +50,7 @@ typedef struct { DataAttribute* attribute; WriteAccessHandler handler; + void* parameter; } AttributeAccessHandler; @@ -1759,6 +1760,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, sg->editSgConfirmedHandler(sg->editSgConfirmedHandlerParameter, sg->sgcb, sg->sgcb->editSG); + unselectSettingGroup(sg); + return DATA_ACCESS_ERROR_SUCCESS; } else @@ -1826,7 +1829,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, if (matchingValue != NULL) { MmsDataAccessError handlerResult = - accessHandler->handler(dataAttribute, matchingValue, (ClientConnection) connection); + accessHandler->handler(dataAttribute, matchingValue, (ClientConnection) connection, + accessHandler->parameter); if (handlerResult == DATA_ACCESS_ERROR_SUCCESS) handlerFound = true; @@ -1838,8 +1842,8 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, else { /* if ACCESS_POLICY_DENY only allow direct access to handled data attribute */ if (dataAttribute->mmsValue == cachedValue) { MmsDataAccessError handlerResult = - accessHandler->handler(dataAttribute, value, (ClientConnection) connection); - + accessHandler->handler(dataAttribute, value, (ClientConnection) connection, + accessHandler->parameter); if (handlerResult == DATA_ACCESS_ERROR_SUCCESS) { handlerFound = true; @@ -1923,7 +1927,7 @@ getAccessHandlerForAttribute(MmsMapping* self, DataAttribute* dataAttribute) } void -MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler) +MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter) { AttributeAccessHandler* accessHandler = getAccessHandlerForAttribute(self, dataAttribute); @@ -1931,6 +1935,7 @@ MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttrib accessHandler = (AttributeAccessHandler*) GLOBAL_MALLOC(sizeof(AttributeAccessHandler)); accessHandler->attribute = dataAttribute; + accessHandler->parameter = parameter; LinkedList_add(self->attributeAccessHandlers, (void*) accessHandler); } diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c index ad1bd598..a6513c73 100644 --- a/src/iec61850/server/model/model.c +++ b/src/iec61850/server/model/model.c @@ -345,6 +345,46 @@ LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc) return false; } +DataSet* +LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName) +{ + assert(self->modelType == LogicalNodeModelType); + assert(dataSetName != NULL); + + char dsName[66]; + + LogicalDevice* ld = (LogicalDevice*) self->parent; + + if (strlen(dataSetName) > 32) { + + if (DEBUG_IED_SERVER) { + printf("IED_SERVER: LogicalNode_getDataSet - data set name %s too long!\n", dataSetName); + } + + goto exit_error; + } + + StringUtils_createStringInBuffer(dsName, 3, self->name, "$", dataSetName); + + IedModel* iedModel = (IedModel*) ld->parent; + + DataSet* ds = iedModel->dataSets; + + while (ds != NULL) { + if (strcmp(ds->logicalDeviceName, ld->name) == 0) { + if (strcmp(ds->name, dsName) == 0) { + return ds; + } + } + + ds = ds->sibling; + } + + +exit_error: + return NULL; +} + int LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice) { diff --git a/src/mms/iso_mms/server/mms_access_result.c b/src/mms/iso_mms/server/mms_access_result.c index 3b4f033c..59d52ab6 100644 --- a/src/mms/iso_mms/server/mms_access_result.c +++ b/src/mms/iso_mms/server/mms_access_result.c @@ -103,12 +103,19 @@ encodeStructuredAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool int mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode) { - if (value == NULL) // TODO report internal error - return 0; +// if (value == NULL) // TODO report internal error +// return 0; int size; switch (value->type) { + case MMS_BOOLEAN: + if (encode) + bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos); + else + size = 3; + break; + case MMS_STRUCTURE: if (encode) bufPos = encodeStructuredAccessResult(value, buffer, bufPos, true); @@ -166,12 +173,7 @@ mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool else size = BerEncoder_determineEncodedBitStringSize(value->value.bitString.size); break; - case MMS_BOOLEAN: - if (encode) - bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos); - else - size = 3; - break; + case MMS_BINARY_TIME: if (encode) bufPos = BerEncoder_encodeOctetString(0x8c, value->value.binaryTime.buf, diff --git a/tools/model_generator/genmodel.jar b/tools/model_generator/genmodel.jar index f0c858a9a7ceec6bf3138f8655f41317876dd160..21472b0a386fd369defe16bc120a8e647299e0cd 100644 GIT binary patch delta 1278 zcmYjPT}V@57~bprnNzpfHm7HEKW_7)BdA1>iDZRAX={c*)wGEwkqLRzZX^)82ojY% z!ABI4Na#RG{Q@&Hm68YvDHFV~>?Rl(Yldj_qn-19pX6@7XV3fmeCIu9c0PV~K0eJ~ zu8udUG#ZVnYb5M3(K&vd3YK0(Oaey+qAhaSQ#R4uGwExIMeN}lro>MDc5)>erh#8=# zugc%XDKzcz6(r$&W0TEkta>g1nP-86D2WAZ@kqo1qU3K&p=AyC(JZBOdZms~BGok& zv$Trl1tuK{D-$h=W`cp%xA4S@W|8{a7EwZ8=mFiNKMSl<>-BHg(c|;dj!-pA(JkYh z^fa|SH=vPlh#@=vEH;suJ9L?Vxp$S((I>7%)0X-LbV)UcS#c3QOb zfdSp}5VKFM{9zBHln=V(@~tl+HfsAi%*4(}H&)QmXeoQNjm;HyLHXU#pT7rDC-rZa zV5KwSB?b@JY3|M?3?G-jtINz#wB#i-ZqSic4|-lw?w5lqm(Y8v#E>GHirmWY&yu6hXcT>JW6BpdLZg1Q!vUF+%{su$kw4H$yEl zCo{NfFa!L^+z`M@GAytk{~fn*Yu_%|vA|gzRb|2j1f!X79zj|bXIiqL0hxDMJU&kV zA2M=$8G<>1yIfWt7_#!Nk5)b^u)#SLciNx{!MY795tL;^5Wzq;7pv{OqRI}{I2y8Z zdy<2LMh71~cR&qlj84v6b#mslljoRSd`Z__T=T}oyWBZ^$2W6$^5-1Bzd|?Hbh+U) YR(x`Eafye&kcS@LwdLWXS}(Nx1EhBx1^@s6 delta 1278 zcmYjPT}V@57~bp8oSU1oZT_6i{kYAGCa6S^iDbos(rku5)igzu$b`Jf8w-RkfWhx)3rd^{(X+@wK(Wa3GO zRQjsyU7SqQzKVh*oNsKhIgM7&BqH<7zaJ%0za;^QsNW;{+BMYMcn{5@rrRxcbttK> zxtOJux6CnVFd$FVB$5ewTHneO%Ue9u*FKLD@*)+`O$M{TEVfEXp^Tro;;rEqI7DN+Q2(pr#LJj%bmVLaBZ}m+iD@ z;UfdO#SvzoSo*^rMlK(ANab5!I@qZF>nIc3S9`I7h9afx(Ka@h*af9`Lx27rMx8jg zU4oVNRX5SQz)Evt7ce|5eODKmp=iNPrktQ7D=tV5?@NLq=9N7%AJ(fOfZt45dZ~xd zPPX^J0Xdlz86-*uod&>9k&GIk7@0K#97d3DggOMhMyN*+F~WHSr%d2SFlypC-%U`9 z%<**Y8cqivGS>w#lk^POi~o*haO=Phh-JWO993n)IRv3hIEz4=#hKPDXhi0H7LU&p zpaK~w-iu&H;4X)m2X>fw*C#U{6