diff --git a/examples/server_example_basic_io/simpleIO_direct_control.cid b/examples/server_example_basic_io/simpleIO_direct_control.cid index ef8f1b7c..a0228a20 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_config_file/server_example_config_file.c b/examples/server_example_config_file/server_example_config_file.c index 88252991..e91f2720 100644 --- a/examples/server_example_config_file/server_example_config_file.c +++ b/examples/server_example_config_file/server_example_config_file.c @@ -51,10 +51,10 @@ main(int argc, char** argv) /* Access to data attributes by object reference */ DataAttribute* anIn1_mag_f = (DataAttribute*) - IedModel_getModelNodeByObjectReference(model, "simpleIOGenericIO/GGIO1.AnIn1.mag.f"); + IedModel_getModelNodeByShortObjectReference(model, "GenericIO/GGIO1.AnIn1.mag.f"); DataAttribute* anIn1_t = (DataAttribute*) - IedModel_getModelNodeByObjectReference(model, "simpleIOGenericIO/GGIO1.AnIn1.t"); + IedModel_getModelNodeByShortObjectReference(model, "GenericIO/GGIO1.AnIn1.t"); if (anIn1_mag_f == NULL) printf("Error getting AnIn1.mag.f data attribute!\n"); diff --git a/src/iec61850/inc/iec61850_dynamic_model.h b/src/iec61850/inc/iec61850_dynamic_model.h index 4138d13c..20de3cbe 100644 --- a/src/iec61850/inc/iec61850_dynamic_model.h +++ b/src/iec61850/inc/iec61850_dynamic_model.h @@ -82,7 +82,7 @@ LIB61850_API void IedModel_destroy(IedModel* model); /** - * \brief Create a new logical device model and add it to the IED model + * \brief Create a new logical device and add it to the IED model * * \param name the name of the new logical device * \param parent the parent IED model @@ -92,6 +92,17 @@ IedModel_destroy(IedModel* model); LIB61850_API LogicalDevice* LogicalDevice_create(const char* name, IedModel* parent); +/** + * \brief Create a new logical device and add it to the IED model + * + * \param name the name of the new logical device + * \param parent the parent IED model + * \param ldName when not NULL functional naming is used for this LD (ldName <= 64 chars) + * + * \return the newly created LogicalDevice instance + */ +LIB61850_API LogicalDevice* +LogicalDevice_createEx(const char* inst, IedModel* parent, const char* ldName); /** * \brief Create a new logical mode and add it to a logical device diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h index 1f10db3c..77cb5c5d 100644 --- a/src/iec61850/inc/iec61850_model.h +++ b/src/iec61850/inc/iec61850_model.h @@ -183,11 +183,11 @@ struct sIedModel { struct sLogicalDevice { ModelNodeType modelType; - char* name; + char* name; /* LD instance */ ModelNode* parent; ModelNode* sibling; ModelNode* firstChild; - char* ldName; + char* ldName; /* ldName (when using functional naming) */ }; struct sModelNode { @@ -489,7 +489,9 @@ IedModel_getSVControlBlock(IedModel* self, LogicalNode* parentLN, const char* sv * \brief Lookup a model node by its short (normalized) reference * * This version uses the object reference that does not contain the - * IED name as part of the logical device name. This function is useful for + * IED name or functional name as part of the logical device name. + * Instead the LD part consists of the LD instance name ("inst" attribute). + * This function is useful for * devices where the IED name can be configured. * * \param self the IedModel instance that holds the model node diff --git a/src/iec61850/server/model/config_file_parser.c b/src/iec61850/server/model/config_file_parser.c index ee9d2aec..37560994 100644 --- a/src/iec61850/server/model/config_file_parser.c +++ b/src/iec61850/server/model/config_file_parser.c @@ -172,12 +172,22 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle) if (StringUtils_startsWith((char*) lineBuffer, "LD")) { indendation = 2; - if (sscanf((char*) lineBuffer, "LD(%s)", nameString) < 1) + char ldName[65]; + ldName[0] = 0; + + if (sscanf((char*) lineBuffer, "LD(%s %s)", nameString, ldName) < 1) goto exit_error; terminateString(nameString, ')'); - currentLD = LogicalDevice_create(nameString, model); + if (ldName[0] != 0) { + terminateString(ldName, ')'); + + currentLD = LogicalDevice_createEx(nameString, model, ldName); + } + else { + currentLD = LogicalDevice_create(nameString, model); + } } else goto exit_error; diff --git a/src/iec61850/server/model/dynamic_model.c b/src/iec61850/server/model/dynamic_model.c index b8e9816b..0843d713 100644 --- a/src/iec61850/server/model/dynamic_model.c +++ b/src/iec61850/server/model/dynamic_model.c @@ -180,20 +180,33 @@ IedModel_addGSEControlBlock(IedModel* self, GSEControlBlock* gcb) } LogicalDevice* -LogicalDevice_create(const char* name, IedModel* parent) +LogicalDevice_createEx(const char* inst, IedModel* parent, const char* ldName) { LogicalDevice* self = (LogicalDevice*) GLOBAL_CALLOC(1, sizeof(LogicalDevice)); - self->name = StringUtils_copyString(name); - self->modelType = LogicalDeviceModelType; - self->parent = (ModelNode*) parent; - self->sibling = NULL; + if (self) { + self->name = StringUtils_copyString(inst); + self->modelType = LogicalDeviceModelType; + self->parent = (ModelNode*) parent; + self->sibling = NULL; - IedModel_addLogicalDevice(parent, self); + if (ldName) + self->ldName = StringUtils_copyString(ldName); + else + self->ldName = NULL; + + IedModel_addLogicalDevice(parent, self); + } return self; } +LogicalDevice* +LogicalDevice_create(const char* inst, IedModel* parent) +{ + return LogicalDevice_createEx(inst, parent, NULL); +} + static LogicalNode* LogicalDevice_getLastLogicalNode(LogicalDevice* self) { @@ -779,6 +792,9 @@ IedModel_destroy(IedModel* model) while (ld != NULL) { GLOBAL_FREEMEM (ld->name); + if (ld->ldName) + GLOBAL_FREEMEM (ld->ldName); + LogicalNode* ln = (LogicalNode*) ld->firstChild; while (ln != NULL) { diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c index 7c3ef542..6d8a3e58 100644 --- a/src/iec61850/server/model/model.c +++ b/src/iec61850/server/model/model.c @@ -375,11 +375,11 @@ IedModel_getModelNodeByShortObjectReference(IedModel* model, const char* objectR if (separator != NULL) *separator = 0; - char ldName[65]; - strcpy(ldName, model->name); - strcat(ldName, objRef); + char ldInst[65]; + strncpy(ldInst, objRef, 64); + ldInst[64] = 0; - LogicalDevice* ld = IedModel_getDevice(model, ldName); + LogicalDevice* ld = IedModel_getDeviceByInst(model, ldInst); if (ld == NULL) return NULL; @@ -557,12 +557,22 @@ createObjectReference(ModelNode* node, char* objectReference, bool withoutIedNam if (withoutIedName) { nameLength = strlen(lDevice->name); strncpy(objectReference, lDevice->name, 64); + objectReference[64] = 0; } else { - nameLength = strlen (iedModel->name) + strlen(lDevice->name); + if (lDevice->ldName) { + nameLength = strlen(lDevice->ldName); + strncpy(objectReference, lDevice->ldName, 64); + objectReference[64] = 0; + } + else { + nameLength = strlen (iedModel->name) + strlen(lDevice->name); + + strncpy(objectReference, iedModel->name, 64); + strncat(objectReference, lDevice->name, 64); - strncpy(objectReference, iedModel->name, 64); - strncat(objectReference, lDevice->name, 64); + objectReference[64] = 0; + } } bufPos += nameLength; diff --git a/tools/model_generator/genconfig.jar b/tools/model_generator/genconfig.jar index 8b2670b0..2c9ed1fc 100644 Binary files a/tools/model_generator/genconfig.jar and b/tools/model_generator/genconfig.jar differ diff --git a/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java b/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java index d5ec7ffc..cd1d4593 100644 --- a/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java +++ b/tools/model_generator/src/com/libiec61850/tools/DynamicModelGenerator.java @@ -100,7 +100,10 @@ public class DynamicModelGenerator { output.println("MODEL(" + ied.getName() + "){"); for (LogicalDevice logicalDevice : logicalDevices) { output.print("LD("); - output.print(logicalDevice.getInst() + "){\n"); + output.print(logicalDevice.getInst()); + if (logicalDevice.getLdName() != null) + output.print(" " + logicalDevice.getLdName()); + output.print("){\n"); exportLogicalNodes(output, logicalDevice);