diff --git a/config/stack_config.h b/config/stack_config.h index 8bbe5d1e..369ef2f1 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -17,7 +17,7 @@ #define DEBUG_COTP 0 #define DEBUG_ISO_SERVER 0 #define DEBUG_ISO_CLIENT 0 -#define DEBUG_IED_SERVER 0 +#define DEBUG_IED_SERVER 1 #define DEBUG_IED_CLIENT 0 #define DEBUG_MMS_CLIENT 0 #define DEBUG_MMS_SERVER 0 diff --git a/examples/server_example_basic_io/server_example_basic_io.c b/examples/server_example_basic_io/server_example_basic_io.c index b6f86630..954be4d2 100644 --- a/examples/server_example_basic_io/server_example_basic_io.c +++ b/examples/server_example_basic_io/server_example_basic_io.c @@ -177,6 +177,7 @@ main(int argc, char** argv) if (((int) t % 2) == 0) Timestamp_setClockNotSynchronized(&iecTimestamp, true); +#if 1 IedServer_lockDataModel(iedServer); IedServer_updateTimestampAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn1_t, &iecTimestamp); @@ -192,6 +193,7 @@ main(int argc, char** argv) IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_AnIn4_mag_f, an4); IedServer_unlockDataModel(iedServer); +#endif Thread_sleep(100); } diff --git a/examples/server_example_basic_io/simpleIO_direct_control.cid b/examples/server_example_basic_io/simpleIO_direct_control.cid index a0228a20..ef8f1b7c 100644 --- a/examples/server_example_basic_io/simpleIO_direct_control.cid +++ b/examples/server_example_basic_io/simpleIO_direct_control.cid @@ -52,7 +52,7 @@ - + diff --git a/examples/server_example_basic_io/static_model.c b/examples/server_example_basic_io/static_model.c index 6084f911..9f9243ad 100644 --- a/examples/server_example_basic_io/static_model.c +++ b/examples/server_example_basic_io/static_model.c @@ -20,7 +20,7 @@ extern DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda3; DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda0 = { "GenericIO", false, - "GGIO1$ST$SPCSO1$stVal", + "GGIO1$ST$SPCSO1$stVal", -1, NULL, NULL, @@ -30,7 +30,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda0 = { DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda1 = { "GenericIO", false, - "GGIO1$ST$SPCSO2$stVal", + "GGIO1$ST$SPCSO2$stVal", -1, NULL, NULL, @@ -40,7 +40,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda1 = { DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda2 = { "GenericIO", false, - "GGIO1$ST$SPCSO3$stVal", + "GGIO1$ST$SPCSO3$stVal", -1, NULL, NULL, @@ -50,7 +50,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda2 = { DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda3 = { "GenericIO", false, - "GGIO1$ST$SPCSO4$stVal", + "GGIO1$ST$SPCSO4$stVal", -1, NULL, NULL, @@ -73,7 +73,7 @@ extern DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda3; DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda0 = { "GenericIO", false, - "GGIO1$ST$SPCSO1", + "GGIO1$ST$SPCSO1", -1, NULL, NULL, @@ -83,7 +83,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda0 = { DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda1 = { "GenericIO", false, - "GGIO1$ST$SPCSO2", + "GGIO1$ST$SPCSO2", -1, NULL, NULL, @@ -93,7 +93,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda1 = { DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda2 = { "GenericIO", false, - "GGIO1$ST$SPCSO3", + "GGIO1$ST$SPCSO3", -1, NULL, NULL, @@ -103,7 +103,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda2 = { DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda3 = { "GenericIO", false, - "GGIO1$ST$SPCSO4", + "GGIO1$ST$SPCSO4", -1, NULL, NULL, @@ -130,7 +130,7 @@ extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda7; DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda0 = { "GenericIO", false, - "GGIO1$MX$AnIn1$mag$f", + "GGIO1$MX$AnIn1$mag$f", -1, NULL, NULL, @@ -140,7 +140,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda0 = { DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda1 = { "GenericIO", false, - "GGIO1$MX$AnIn1$q", + "GGIO1$MX$AnIn1$q", -1, NULL, NULL, @@ -150,7 +150,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda1 = { DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda2 = { "GenericIO", false, - "GGIO1$MX$AnIn2$mag$f", + "GGIO1$MX$AnIn2$mag$f", -1, NULL, NULL, @@ -160,7 +160,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda2 = { DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda3 = { "GenericIO", false, - "GGIO1$MX$AnIn2$q", + "GGIO1$MX$AnIn2$q", -1, NULL, NULL, @@ -170,7 +170,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda3 = { DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda4 = { "GenericIO", false, - "GGIO1$MX$AnIn3$mag$f", + "GGIO1$MX$AnIn3$mag$f", -1, NULL, NULL, @@ -180,7 +180,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda4 = { DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda5 = { "GenericIO", false, - "GGIO1$MX$AnIn3$q", + "GGIO1$MX$AnIn3$q", -1, NULL, NULL, @@ -190,7 +190,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda5 = { DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda6 = { "GenericIO", false, - "GGIO1$MX$AnIn4$mag$f", + "GGIO1$MX$AnIn4$mag$f", -1, NULL, NULL, @@ -200,7 +200,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda6 = { DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda7 = { "GenericIO", false, - "GGIO1$MX$AnIn4$q", + "GGIO1$MX$AnIn4$q", -1, NULL, NULL, @@ -220,7 +220,8 @@ LogicalDevice iedModel_GenericIO = { "GenericIO", (ModelNode*) &iedModel, NULL, - (ModelNode*) &iedModel_GenericIO_LLN0 + (ModelNode*) &iedModel_GenericIO_LLN0, + "Q1E1P2" }; LogicalNode iedModel_GenericIO_LLN0 = { diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h index dc5fa918..b788838c 100644 --- a/src/iec61850/inc/iec61850_model.h +++ b/src/iec61850/inc/iec61850_model.h @@ -187,6 +187,7 @@ struct sLogicalDevice { ModelNode* parent; ModelNode* sibling; ModelNode* firstChild; + char* ldName; }; struct sModelNode { @@ -212,7 +213,8 @@ struct sDataObject { ModelNode* sibling; ModelNode* firstChild; - int elementCount; /* > 0 if this is an array */ + int elementCount; /* value > 0 if this is an array */ + //int arrayIndex; /* value > -1 when this is an array element */ }; struct sDataAttribute { @@ -222,7 +224,8 @@ struct sDataAttribute { ModelNode* sibling; ModelNode* firstChild; - int elementCount; /* > 0 if this is an array */ + int elementCount; /* value > 0 if this is an array */ + // int arrayIndex; /* value > -1 when this is an array element */ FunctionalConstraint fc; DataAttributeType type; @@ -235,7 +238,7 @@ struct sDataAttribute { }; typedef struct sDataSetEntry { - char* logicalDeviceName; + char* logicalDeviceName; /* logical device instance name */ bool isLDNameDynamicallyAllocated; char* variableName; int index; @@ -245,7 +248,7 @@ typedef struct sDataSetEntry { } DataSetEntry; struct sDataSet { - char* logicalDeviceName; + char* logicalDeviceName; /* logical device instance name */ char* name; /* eg. MMXU1$dataset1 */ int elementCount; DataSetEntry* fcdas; @@ -425,6 +428,8 @@ IedModel_setIedName(IedModel* self, const char* iedName); * This function uses the full logical device name as part of the object reference * as it happens to appear on the wire. E.g. if IED name in SCL file would be "IED1" * and the logical device "WD1" the resulting LD name would be "IED1WD". + * When using functional naming in the LD (with ldName attribute) then the logical + * device name is identical with the ldName attribute. * * \param self the IedModel instance that holds the model node * \param objectReference the IEC 61850 object reference diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index ccf6e3d0..5aba1695 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -221,7 +221,7 @@ createMmsServerCache(IedServer self) goto exit_function; if (DEBUG_IED_SERVER) - printf("ied_server.c: Insert into cache %s - %s\n", logicalDevice->domainName, variableName); + printf("IED_SERVER: Insert into cache %s - %s\n", logicalDevice->domainName, variableName); MmsServer_insertIntoCache(self->mmsServer, logicalDevice, variableName, defaultValue); } @@ -236,7 +236,7 @@ exit_function: } static void -installDefaultValuesForDataAttribute(IedServer self, DataAttribute* dataAttribute, +installDefaultValuesForDataAttribute(IedServer self, LogicalDevice* ld, DataAttribute* dataAttribute, char* objectReference, int position) { sprintf(objectReference + position, ".%s", dataAttribute->name); @@ -248,8 +248,12 @@ installDefaultValuesForDataAttribute(IedServer self, DataAttribute* dataAttribut MmsMapping_createMmsVariableNameFromObjectReference(objectReference, dataAttribute->fc, mmsVariableName); char domainName[65]; + domainName[0] = 0; - strncpy(domainName, self->model->name, 64); + if (ld->ldName == NULL) { + strncpy(domainName, self->model->name, 64); + domainName[64] = 0; + } MmsMapping_getMmsDomainFromObjectReference(objectReference, domainName + strlen(domainName)); @@ -284,14 +288,14 @@ installDefaultValuesForDataAttribute(IedServer self, DataAttribute* dataAttribut DataAttribute* subDataAttribute = (DataAttribute*) dataAttribute->firstChild; while (subDataAttribute != NULL) { - installDefaultValuesForDataAttribute(self, subDataAttribute, objectReference, childPosition); + installDefaultValuesForDataAttribute(self, ld, subDataAttribute, objectReference, childPosition); subDataAttribute = (DataAttribute*) subDataAttribute->sibling; } } static void -installDefaultValuesForDataObject(IedServer self, DataObject* dataObject, +installDefaultValuesForDataObject(IedServer self, LogicalDevice* ld, DataObject* dataObject, char* objectReference, int position) { if (dataObject->elementCount > 0) { @@ -309,10 +313,10 @@ installDefaultValuesForDataObject(IedServer self, DataObject* dataObject, while (childNode != NULL) { if (childNode->modelType == DataObjectModelType) { - installDefaultValuesForDataObject(self, (DataObject*) childNode, objectReference, childPosition); + installDefaultValuesForDataObject(self, ld, (DataObject*) childNode, objectReference, childPosition); } else if (childNode->modelType == DataAttributeModelType) { - installDefaultValuesForDataAttribute(self, (DataAttribute*) childNode, objectReference, childPosition); + installDefaultValuesForDataAttribute(self, ld, (DataAttribute*) childNode, objectReference, childPosition); } childNode = childNode->sibling; @@ -329,7 +333,11 @@ installDefaultValuesInCache(IedServer self) LogicalDevice* logicalDevice = model->firstChild; while (logicalDevice != NULL) { - sprintf(objectReference, "%s", logicalDevice->name); + + if (logicalDevice->ldName) + sprintf(objectReference, "%s", logicalDevice->ldName); + else + sprintf(objectReference, "%s", logicalDevice->name); LogicalNode* logicalNode = (LogicalNode*) logicalDevice->firstChild; @@ -343,7 +351,7 @@ installDefaultValuesInCache(IedServer self) int refPosition = strlen(objectReference); while (dataObject != NULL) { - installDefaultValuesForDataObject(self, dataObject, objectReference, refPosition); + installDefaultValuesForDataObject(self, logicalDevice, dataObject, objectReference, refPosition); dataObject = (DataObject*) dataObject->sibling; } @@ -370,12 +378,30 @@ updateDataSetsWithCachedValues(IedServer self) while (dataSetEntry != NULL) { - char domainName[65]; + MmsDomain* domain = NULL; + + LogicalDevice* ld = IedModel_getDeviceByInst(self->model, dataSetEntry->logicalDeviceName); + + if (ld) { + + if (ld->ldName) { + domain = MmsDevice_getDomain(self->mmsDevice, ld->ldName); + } - strncpy(domainName, self->model->name, 64); - strncat(domainName, dataSetEntry->logicalDeviceName, 64 - iedNameLength); + if (domain == NULL) { + char domainName[65]; - MmsDomain* domain = MmsDevice_getDomain(self->mmsDevice, domainName); + strncpy(domainName, self->model->name, 64); + strncat(domainName, dataSetEntry->logicalDeviceName, 64 - iedNameLength); + + domain = MmsDevice_getDomain(self->mmsDevice, domainName); + } + + } + else { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: ERROR - LD %s not found\n", dataSetEntry->logicalDeviceName); + } char variableName[66]; diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index 47348dd3..81d8a12a 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -1790,13 +1790,23 @@ createMmsDomainFromIedDevice(MmsMapping* self, LogicalDevice* logicalDevice) MmsDomain* domain = NULL; char domainName[65]; - int modelNameLength = strlen(self->model->name); + if (logicalDevice->ldName == NULL) { + int modelNameLength = strlen(self->model->name); - if (modelNameLength > 64) - goto exit_function; + if (modelNameLength > 64) + goto exit_function; + + strncpy(domainName, self->model->name, 64); + strncat(domainName, logicalDevice->name, 64 - modelNameLength); + domainName[64] = 0; + } + else { + if (strlen(logicalDevice->ldName) > 64) + goto exit_function; - strncpy(domainName, self->model->name, 64); - strncat(domainName, logicalDevice->name, 64 - modelNameLength); + strncpy(domainName, logicalDevice->ldName, 64); + domainName[64] = 0; + } domain = MmsDomain_create(domainName); @@ -1902,45 +1912,72 @@ createDataSets(MmsDevice* mmsDevice, IedModel* iedModel) } while (dataset != NULL) { - strncpy(domainName, iedModel->name, 64); - strncat(domainName, dataset->logicalDeviceName, 64 - iedModelNameLength); - MmsDomain* dataSetDomain = MmsDevice_getDomain(mmsDevice, domainName); + LogicalDevice* ld = IedModel_getDeviceByInst(iedModel, dataset->logicalDeviceName); + + if (ld) { - if (dataSetDomain == NULL) { + if (ld->ldName) { + strncpy(domainName, ld->ldName, 64); + domainName[64] = 0; + } + else { + strncpy(domainName, iedModel->name, 64); + strncat(domainName, dataset->logicalDeviceName, 64 - iedModelNameLength); + domainName[64] = 0; + } + + MmsDomain* dataSetDomain = MmsDevice_getDomain(mmsDevice, domainName); + + if (dataSetDomain == NULL) { + + if (DEBUG_IED_SERVER) + printf("IED_SERVER: MMS domain for dataset does not exist!\n"); + + goto exit_function; + } if (DEBUG_IED_SERVER) - printf("IED_SERVER: LD for dataset does not exist!\n"); + printf("IED_SERVER: create dataset: %s/%s\n", domainName, dataset->name); - goto exit_function; - } + MmsNamedVariableList varList = MmsNamedVariableList_create(dataSetDomain, dataset->name, false); - MmsNamedVariableList varList = MmsNamedVariableList_create(dataSetDomain, dataset->name, false); + DataSetEntry* dataSetEntry = dataset->fcdas; - DataSetEntry* dataSetEntry = dataset->fcdas; + while (dataSetEntry != NULL) { - while (dataSetEntry != NULL) { + MmsAccessSpecifier accessSpecifier; - MmsAccessSpecifier accessSpecifier; + if (ld->ldName) { + strncpy(domainName, ld->ldName, 64); + domainName[64] = 0; + } + else { + strncpy(domainName, iedModel->name, 64); + strncat(domainName, dataset->logicalDeviceName, 64 - iedModelNameLength); + domainName[64] = 0; + } - strncpy(domainName, iedModel->name, 64); - strncat(domainName, dataSetEntry->logicalDeviceName, 64 - iedModelNameLength); + accessSpecifier.domain = MmsDevice_getDomain(mmsDevice, domainName); - accessSpecifier.domain = MmsDevice_getDomain(mmsDevice, domainName); + accessSpecifier.variableName = dataSetEntry->variableName; + accessSpecifier.arrayIndex = dataSetEntry->index; + accessSpecifier.componentName = dataSetEntry->componentName; - accessSpecifier.variableName = dataSetEntry->variableName; - accessSpecifier.arrayIndex = dataSetEntry->index; - accessSpecifier.componentName = dataSetEntry->componentName; + MmsNamedVariableListEntry variableListEntry = + MmsNamedVariableListEntry_create(accessSpecifier); - MmsNamedVariableListEntry variableListEntry = - MmsNamedVariableListEntry_create(accessSpecifier); + MmsNamedVariableList_addVariable(varList, variableListEntry); - MmsNamedVariableList_addVariable(varList, variableListEntry); + dataSetEntry = dataSetEntry->sibling; + } - dataSetEntry = dataSetEntry->sibling; + MmsDomain_addNamedVariableList(dataSetDomain, varList); + } + else { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: LD for dataset does not exist!\n"); } - - MmsDomain_addNamedVariableList(dataSetDomain, varList); dataset = dataset->sibling; } diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c index 0c6e4d62..b8083ea0 100644 --- a/src/iec61850/server/model/model.c +++ b/src/iec61850/server/model/model.c @@ -73,8 +73,6 @@ IedModel_setAttributeValuesToNull(IedModel* iedModel) } } - - int IedModel_getLogicalDeviceCount(IedModel* self) { @@ -113,15 +111,30 @@ IedModel_lookupDataSet(IedModel* self, const char* dataSetReference /* e.g. ied while (dataSet != NULL) { - domainName[modelNameLen] = 0; + LogicalDevice* ld = IedModel_getDeviceByInst(self, dataSet->logicalDeviceName); - strncat(domainName, dataSet->logicalDeviceName, 64); + if (ld) { + if (ld->ldName == NULL) { + domainName[modelNameLen] = 0; - if (strncmp(domainName, dataSetReference, ldNameLen) == 0) { - if (strcmp(dataSet->name, separator + 1) == 0) { - return dataSet; - } - } + strncat(domainName, dataSet->logicalDeviceName, 64); + + if (strncmp(domainName, dataSetReference, ldNameLen) == 0) { + if (strcmp(dataSet->name, separator + 1) == 0) { + return dataSet; + } + } + } + else { + /* functional naming */ + if (strncmp(ld->ldName, dataSetReference, ldNameLen) == 0) { + if (strcmp(dataSet->name, separator + 1) == 0) { + return dataSet; + } + } + } + + } dataSet = dataSet->sibling; } @@ -136,13 +149,21 @@ IedModel_getDevice(IedModel* self, const char* deviceName) while (device != NULL) { - char domainName[65]; + if (device->ldName) { + /* functional naming */ + if (strcmp(device->ldName, deviceName) == 0) + return device; + } + else { + char domainName[65]; - strncpy(domainName, self->name, 64); - strncat(domainName, device->name, 64); + strncpy(domainName, self->name, 64); + strncat(domainName, device->name, 64); + domainName[64] = 0; - if (strcmp(domainName, deviceName) == 0) - return device; + if (strcmp(domainName, deviceName) == 0) + return device; + } device = (LogicalDevice*) device->sibling; } diff --git a/tools/model_generator/genmodel.jar b/tools/model_generator/genmodel.jar index e2b4f93f..af906018 100644 Binary files a/tools/model_generator/genmodel.jar and b/tools/model_generator/genmodel.jar differ diff --git a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java index c17b86a4..d47fff4a 100644 --- a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java +++ b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java @@ -295,9 +295,9 @@ public class StaticModelGenerator { } } - private String getLogicalDeviceInst(LogicalDevice logicalDevice) { - return logicalDevice.getInst(); - } +// private String getLogicalDeviceInst(LogicalDevice logicalDevice) { +// return logicalDevice.getInst(); +// } private void printDeviceModelDefinitions() { @@ -320,18 +320,18 @@ public class StaticModelGenerator { for (int i = 0; i < logicalDevices.size(); i++) { LogicalDevice logicalDevice = logicalDevices.get(i); - + + String ldInst = logicalDevice.getInst(); + String ldName = modelPrefix + "_" + logicalDevice.getInst(); variablesList.add(ldName); - String logicalDeviceName = getLogicalDeviceInst(logicalDevice); - cOut.println("\nLogicalDevice " + ldName + " = {"); cOut.println(" LogicalDeviceModelType,"); - cOut.println(" \"" + logicalDeviceName + "\","); + cOut.println(" \"" + ldInst + "\","); cOut.println(" (ModelNode*) &" + modelPrefix + ","); @@ -342,7 +342,13 @@ public class StaticModelGenerator { String firstChildName = ldName + "_" + logicalDevice.getLogicalNodes().get(0).getName(); - cOut.println(" (ModelNode*) &" + firstChildName); + cOut.println(" (ModelNode*) &" + firstChildName + ","); + + if (logicalDevice.getLdName() != null) + cOut.println(" \"" + logicalDevice.getLdName() + "\""); + else + cOut.println(" NULL"); + cOut.println("};\n"); printLogicalNodeDefinitions(ldName, logicalDevice, logicalDevice.getLogicalNodes());