diff --git a/config/stack_config.h b/config/stack_config.h index 72245fd..7462281 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 c09466e..cea381c 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 960073a..201fcf9 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 f8d36e6..338c503 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 263f6f5..834a467 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 527a72c..11e7a77 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 d630087..d7622e3 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 - -#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) - MmsMapping_triggerGooseObservers(self->mmsMapping, dataAttribute->mmsValue); -#endif } else if (dataAttribute->triggerOptions & TRG_OPT_QUALITY_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_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 e4c0678..8b9d723 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 c3fcc93..7d14eab 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 ad1bd59..a6513c7 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 3b4f033..59d52ab 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 f0c858a..21472b0 100644 Binary files a/tools/model_generator/genmodel.jar and b/tools/model_generator/genmodel.jar differ