|
|
@ -1,7 +1,7 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* model.c
|
|
|
|
* model.c
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Copyright 2013-2022 Michael Zillgith
|
|
|
|
* Copyright 2013-2024 Michael Zillgith
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This file is part of libIEC61850.
|
|
|
|
* This file is part of libIEC61850.
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -23,21 +23,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include "iec61850_model.h"
|
|
|
|
#include "iec61850_model.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "stack_config.h"
|
|
|
|
|
|
|
|
#include "libiec61850_platform_includes.h"
|
|
|
|
#include "libiec61850_platform_includes.h"
|
|
|
|
|
|
|
|
#include "stack_config.h"
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
setAttributeValuesToNull(ModelNode* node)
|
|
|
|
setAttributeValuesToNull(ModelNode* node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (node->modelType == DataAttributeModelType) {
|
|
|
|
if (node->modelType == DataAttributeModelType)
|
|
|
|
DataAttribute* da = (DataAttribute*) node;
|
|
|
|
{
|
|
|
|
|
|
|
|
DataAttribute* da = (DataAttribute*)node;
|
|
|
|
|
|
|
|
|
|
|
|
da->mmsValue = NULL;
|
|
|
|
da->mmsValue = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ModelNode* child = node->firstChild;
|
|
|
|
ModelNode* child = node->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (child != NULL) {
|
|
|
|
while (child != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
setAttributeValuesToNull(child);
|
|
|
|
setAttributeValuesToNull(child);
|
|
|
|
child = child->sibling;
|
|
|
|
child = child->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -46,7 +48,7 @@ setAttributeValuesToNull(ModelNode* node)
|
|
|
|
void
|
|
|
|
void
|
|
|
|
IedModel_setIedName(IedModel* self, const char* name)
|
|
|
|
IedModel_setIedName(IedModel* self, const char* name)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
self->name = (char*) name;
|
|
|
|
self->name = (char*)name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@ -54,22 +56,25 @@ IedModel_setAttributeValuesToNull(IedModel* iedModel)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogicalDevice* ld = iedModel->firstChild;
|
|
|
|
LogicalDevice* ld = iedModel->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (ld != NULL) {
|
|
|
|
while (ld != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
LogicalNode* ln = (LogicalNode*) ld->firstChild;
|
|
|
|
LogicalNode* ln = (LogicalNode*)ld->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (ln != NULL) {
|
|
|
|
while (ln != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
ModelNode* node = ln->firstChild;
|
|
|
|
ModelNode* node = ln->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (node != NULL) {
|
|
|
|
while (node != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
setAttributeValuesToNull(node);
|
|
|
|
setAttributeValuesToNull(node);
|
|
|
|
node = node->sibling;
|
|
|
|
node = node->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ln = (LogicalNode*) ln->sibling;
|
|
|
|
ln = (LogicalNode*)ln->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ld = (LogicalDevice*) ld->sibling;
|
|
|
|
ld = (LogicalDevice*)ld->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -83,8 +88,9 @@ IedModel_getLogicalDeviceCount(IedModel* self)
|
|
|
|
|
|
|
|
|
|
|
|
int ldCount = 1;
|
|
|
|
int ldCount = 1;
|
|
|
|
|
|
|
|
|
|
|
|
while (logicalDevice->sibling != NULL) {
|
|
|
|
while (logicalDevice->sibling != NULL)
|
|
|
|
logicalDevice = (LogicalDevice*) logicalDevice->sibling;
|
|
|
|
{
|
|
|
|
|
|
|
|
logicalDevice = (LogicalDevice*)logicalDevice->sibling;
|
|
|
|
ldCount++;
|
|
|
|
ldCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -112,31 +118,37 @@ IedModel_lookupDataSet(IedModel* self, const char* dataSetReference /* e.g. ied
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(domainName, self->name, modelNameLen);
|
|
|
|
memcpy(domainName, self->name, modelNameLen);
|
|
|
|
|
|
|
|
|
|
|
|
while (dataSet != NULL) {
|
|
|
|
while (dataSet != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
LogicalDevice* ld = IedModel_getDeviceByInst(self, dataSet->logicalDeviceName);
|
|
|
|
LogicalDevice* ld = IedModel_getDeviceByInst(self, dataSet->logicalDeviceName);
|
|
|
|
|
|
|
|
|
|
|
|
if (ld) {
|
|
|
|
if (ld)
|
|
|
|
if (ld->ldName == NULL) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ld->ldName == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* LD name = IEDName + ldInst */
|
|
|
|
/* LD name = IEDName + ldInst */
|
|
|
|
domainName[modelNameLen] = 0;
|
|
|
|
domainName[modelNameLen] = 0;
|
|
|
|
StringUtils_appendString(domainName, 65, dataSet->logicalDeviceName);
|
|
|
|
StringUtils_appendString(domainName, 65, dataSet->logicalDeviceName);
|
|
|
|
|
|
|
|
|
|
|
|
if (strncmp(domainName, dataSetReference, ldNameLen) == 0) {
|
|
|
|
if (strncmp(domainName, dataSetReference, ldNameLen) == 0)
|
|
|
|
if (strcmp(dataSet->name, separator + 1) == 0) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (strcmp(dataSet->name, separator + 1) == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
return dataSet;
|
|
|
|
return dataSet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
/* functional naming */
|
|
|
|
/* functional naming */
|
|
|
|
if (strncmp(ld->ldName, dataSetReference, ldNameLen) == 0) {
|
|
|
|
if (strncmp(ld->ldName, dataSetReference, ldNameLen) == 0)
|
|
|
|
if (strcmp(dataSet->name, separator + 1) == 0) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (strcmp(dataSet->name, separator + 1) == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
return dataSet;
|
|
|
|
return dataSet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dataSet = dataSet->sibling;
|
|
|
|
dataSet = dataSet->sibling;
|
|
|
@ -150,14 +162,16 @@ IedModel_getDevice(IedModel* self, const char* deviceName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogicalDevice* device = self->firstChild;
|
|
|
|
LogicalDevice* device = self->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (device) {
|
|
|
|
while (device)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (device->ldName) {
|
|
|
|
if (device->ldName)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* functional naming */
|
|
|
|
/* functional naming */
|
|
|
|
if (strcmp(device->ldName, deviceName) == 0)
|
|
|
|
if (strcmp(device->ldName, deviceName) == 0)
|
|
|
|
return device;
|
|
|
|
return device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
/* LD name = IEDName + ldInst */
|
|
|
|
/* LD name = IEDName + ldInst */
|
|
|
|
char domainName[65];
|
|
|
|
char domainName[65];
|
|
|
|
|
|
|
|
|
|
|
@ -167,7 +181,7 @@ IedModel_getDevice(IedModel* self, const char* deviceName)
|
|
|
|
return device;
|
|
|
|
return device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
device = (LogicalDevice*) device->sibling;
|
|
|
|
device = (LogicalDevice*)device->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
@ -183,7 +197,7 @@ IedModel_getDeviceByInst(IedModel* self, const char* ldInst)
|
|
|
|
if (strcmp(device->name, ldInst) == 0)
|
|
|
|
if (strcmp(device->name, ldInst) == 0)
|
|
|
|
return device;
|
|
|
|
return device;
|
|
|
|
|
|
|
|
|
|
|
|
device = (LogicalDevice*) device->sibling;
|
|
|
|
device = (LogicalDevice*)device->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
@ -196,14 +210,14 @@ IedModel_getDeviceByIndex(IedModel* self, int index)
|
|
|
|
|
|
|
|
|
|
|
|
int currentIndex = 0;
|
|
|
|
int currentIndex = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (logicalDevice) {
|
|
|
|
while (logicalDevice)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (currentIndex == index)
|
|
|
|
if (currentIndex == index)
|
|
|
|
return logicalDevice;
|
|
|
|
return logicalDevice;
|
|
|
|
|
|
|
|
|
|
|
|
currentIndex++;
|
|
|
|
currentIndex++;
|
|
|
|
|
|
|
|
|
|
|
|
logicalDevice = (LogicalDevice*) logicalDevice->sibling;
|
|
|
|
logicalDevice = (LogicalDevice*)logicalDevice->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
@ -214,9 +228,11 @@ ModelNode_getDataAttributeByMmsValue(ModelNode* self, MmsValue* value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ModelNode* node = self->firstChild;
|
|
|
|
ModelNode* node = self->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (node != NULL) {
|
|
|
|
while (node != NULL)
|
|
|
|
if (node->modelType == DataAttributeModelType) {
|
|
|
|
{
|
|
|
|
DataAttribute* da = (DataAttribute*) node;
|
|
|
|
if (node->modelType == DataAttributeModelType)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
DataAttribute* da = (DataAttribute*)node;
|
|
|
|
|
|
|
|
|
|
|
|
if (da->mmsValue == value)
|
|
|
|
if (da->mmsValue == value)
|
|
|
|
return da;
|
|
|
|
return da;
|
|
|
@ -238,16 +254,14 @@ IedModel_lookupDataAttributeByMmsValue(IedModel* model, MmsValue* value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogicalDevice* ld = model->firstChild;
|
|
|
|
LogicalDevice* ld = model->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (ld != NULL) {
|
|
|
|
while (ld != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
DataAttribute* da =
|
|
|
|
DataAttribute* da = ModelNode_getDataAttributeByMmsValue((ModelNode*)ld, value);
|
|
|
|
ModelNode_getDataAttributeByMmsValue((ModelNode*) ld, value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (da != NULL)
|
|
|
|
if (da != NULL)
|
|
|
|
return da;
|
|
|
|
return da;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ld = (LogicalDevice*)ld->sibling;
|
|
|
|
ld = (LogicalDevice*) ld->sibling;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
@ -260,9 +274,11 @@ getChildWithShortAddress(ModelNode* node, uint32_t sAddr)
|
|
|
|
|
|
|
|
|
|
|
|
child = node->firstChild;
|
|
|
|
child = node->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (child != NULL) {
|
|
|
|
while (child != NULL)
|
|
|
|
if (child->modelType == DataAttributeModelType) {
|
|
|
|
{
|
|
|
|
DataAttribute* da = (DataAttribute*) child;
|
|
|
|
if (child->modelType == DataAttributeModelType)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
DataAttribute* da = (DataAttribute*)child;
|
|
|
|
|
|
|
|
|
|
|
|
if (da->sAddr == sAddr)
|
|
|
|
if (da->sAddr == sAddr)
|
|
|
|
return child;
|
|
|
|
return child;
|
|
|
@ -284,17 +300,18 @@ IedModel_getModelNodeByShortAddress(IedModel* model, uint32_t sAddr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ModelNode* node = NULL;
|
|
|
|
ModelNode* node = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
LogicalDevice* ld = (LogicalDevice*) model->firstChild;
|
|
|
|
LogicalDevice* ld = (LogicalDevice*)model->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (ld != NULL) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LogicalNode* ln = (LogicalNode*) ld->firstChild;
|
|
|
|
while (ld != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
while (ln != NULL) {
|
|
|
|
LogicalNode* ln = (LogicalNode*)ld->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (ln != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
ModelNode* doNode = ln->firstChild;
|
|
|
|
ModelNode* doNode = ln->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (doNode != NULL) {
|
|
|
|
while (doNode != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
ModelNode* matchingNode = getChildWithShortAddress(doNode, sAddr);
|
|
|
|
ModelNode* matchingNode = getChildWithShortAddress(doNode, sAddr);
|
|
|
|
|
|
|
|
|
|
|
|
if (matchingNode != NULL)
|
|
|
|
if (matchingNode != NULL)
|
|
|
@ -303,10 +320,10 @@ IedModel_getModelNodeByShortAddress(IedModel* model, uint32_t sAddr)
|
|
|
|
doNode = doNode->sibling;
|
|
|
|
doNode = doNode->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ln = (LogicalNode*) ln->sibling;
|
|
|
|
ln = (LogicalNode*)ln->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ld = (LogicalDevice*) ld->sibling;
|
|
|
|
ld = (LogicalDevice*)ld->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return node;
|
|
|
|
return node;
|
|
|
@ -328,12 +345,13 @@ IedModel_getModelNodeByObjectReference(IedModel* model, const char* objectRefere
|
|
|
|
|
|
|
|
|
|
|
|
LogicalDevice* ld = IedModel_getDevice(model, objRef);
|
|
|
|
LogicalDevice* ld = IedModel_getDevice(model, objRef);
|
|
|
|
|
|
|
|
|
|
|
|
if (ld == NULL) return NULL;
|
|
|
|
if (ld == NULL)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
if ((separator == NULL) || (*(separator + 1) == 0))
|
|
|
|
if ((separator == NULL) || (*(separator + 1) == 0))
|
|
|
|
return (ModelNode*) ld;
|
|
|
|
return (ModelNode*)ld;
|
|
|
|
|
|
|
|
|
|
|
|
return ModelNode_getChild((ModelNode*) ld, separator + 1);
|
|
|
|
return ModelNode_getChild((ModelNode*)ld, separator + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
|
|
|
|
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
|
|
|
@ -345,13 +363,14 @@ IedModel_getSVControlBlock(IedModel* self, LogicalNode* parentLN, const char* sv
|
|
|
|
|
|
|
|
|
|
|
|
SVControlBlock* svCb = self->svCBs;
|
|
|
|
SVControlBlock* svCb = self->svCBs;
|
|
|
|
|
|
|
|
|
|
|
|
while (svCb != NULL) {
|
|
|
|
while (svCb != NULL)
|
|
|
|
if ((svCb->parent == parentLN) && (strcmp(svCb->name, svcbName) == 0)) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((svCb->parent == parentLN) && (strcmp(svCb->name, svcbName) == 0))
|
|
|
|
|
|
|
|
{
|
|
|
|
retVal = svCb;
|
|
|
|
retVal = svCb;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
svCb = svCb->sibling;
|
|
|
|
svCb = svCb->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -379,8 +398,10 @@ IedModel_getModelNodeByShortObjectReference(IedModel* model, const char* objectR
|
|
|
|
|
|
|
|
|
|
|
|
LogicalDevice* ld = IedModel_getDeviceByInst(model, ldInst);
|
|
|
|
LogicalDevice* ld = IedModel_getDeviceByInst(model, ldInst);
|
|
|
|
|
|
|
|
|
|
|
|
if (ld == NULL) {
|
|
|
|
if (ld == NULL)
|
|
|
|
if (DEBUG_IED_SERVER) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (DEBUG_IED_SERVER)
|
|
|
|
|
|
|
|
{
|
|
|
|
printf("IED_SERVER: LD (%s) not found\n", ldInst);
|
|
|
|
printf("IED_SERVER: LD (%s) not found\n", ldInst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -388,9 +409,9 @@ IedModel_getModelNodeByShortObjectReference(IedModel* model, const char* objectR
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((separator == NULL) || (*(separator + 1) == 0))
|
|
|
|
if ((separator == NULL) || (*(separator + 1) == 0))
|
|
|
|
return (ModelNode*) ld;
|
|
|
|
return (ModelNode*)ld;
|
|
|
|
|
|
|
|
|
|
|
|
return ModelNode_getChild((ModelNode*) ld, separator + 1);
|
|
|
|
return ModelNode_getChild((ModelNode*)ld, separator + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
bool
|
|
|
@ -398,17 +419,18 @@ DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ModelNode* modelNode = dataObject->firstChild;
|
|
|
|
ModelNode* modelNode = dataObject->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (modelNode != NULL) {
|
|
|
|
while (modelNode != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (modelNode->modelType == DataAttributeModelType) {
|
|
|
|
if (modelNode->modelType == DataAttributeModelType)
|
|
|
|
DataAttribute* dataAttribute = (DataAttribute*) modelNode;
|
|
|
|
{
|
|
|
|
|
|
|
|
DataAttribute* dataAttribute = (DataAttribute*)modelNode;
|
|
|
|
|
|
|
|
|
|
|
|
if (dataAttribute->fc == fc)
|
|
|
|
if (dataAttribute->fc == fc)
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (modelNode->modelType == DataObjectModelType) {
|
|
|
|
else if (modelNode->modelType == DataObjectModelType)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (DataObject_hasFCData((DataObject*) modelNode, fc))
|
|
|
|
if (DataObject_hasFCData((DataObject*)modelNode, fc))
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -421,13 +443,14 @@ DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc)
|
|
|
|
bool
|
|
|
|
bool
|
|
|
|
LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc)
|
|
|
|
LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DataObject* dataObject = (DataObject*) node->firstChild;
|
|
|
|
DataObject* dataObject = (DataObject*)node->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (dataObject != NULL) {
|
|
|
|
while (dataObject != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (DataObject_hasFCData(dataObject, fc))
|
|
|
|
if (DataObject_hasFCData(dataObject, fc))
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
dataObject = (DataObject*) dataObject->sibling;
|
|
|
|
dataObject = (DataObject*)dataObject->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
@ -441,11 +464,12 @@ LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName)
|
|
|
|
|
|
|
|
|
|
|
|
char dsName[66];
|
|
|
|
char dsName[66];
|
|
|
|
|
|
|
|
|
|
|
|
LogicalDevice* ld = (LogicalDevice*) self->parent;
|
|
|
|
LogicalDevice* ld = (LogicalDevice*)self->parent;
|
|
|
|
|
|
|
|
|
|
|
|
if (strlen(dataSetName) > 32) {
|
|
|
|
if (strlen(dataSetName) > 32)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (DEBUG_IED_SERVER) {
|
|
|
|
if (DEBUG_IED_SERVER)
|
|
|
|
|
|
|
|
{
|
|
|
|
printf("IED_SERVER: LogicalNode_getDataSet - data set name %s too long!\n", dataSetName);
|
|
|
|
printf("IED_SERVER: LogicalNode_getDataSet - data set name %s too long!\n", dataSetName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -454,13 +478,16 @@ LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName)
|
|
|
|
|
|
|
|
|
|
|
|
StringUtils_createStringInBuffer(dsName, 66, 3, self->name, "$", dataSetName);
|
|
|
|
StringUtils_createStringInBuffer(dsName, 66, 3, self->name, "$", dataSetName);
|
|
|
|
|
|
|
|
|
|
|
|
IedModel* iedModel = (IedModel*) ld->parent;
|
|
|
|
IedModel* iedModel = (IedModel*)ld->parent;
|
|
|
|
|
|
|
|
|
|
|
|
DataSet* ds = iedModel->dataSets;
|
|
|
|
DataSet* ds = iedModel->dataSets;
|
|
|
|
|
|
|
|
|
|
|
|
while (ds != NULL) {
|
|
|
|
while (ds != NULL)
|
|
|
|
if (strcmp(ds->logicalDeviceName, ld->name) == 0) {
|
|
|
|
{
|
|
|
|
if (strcmp(ds->name, dsName) == 0) {
|
|
|
|
if (strcmp(ds->logicalDeviceName, ld->name) == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (strcmp(ds->name, dsName) == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
return ds;
|
|
|
|
return ds;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -468,7 +495,6 @@ LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName)
|
|
|
|
ds = ds->sibling;
|
|
|
|
ds = ds->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exit_error:
|
|
|
|
exit_error:
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -478,10 +504,11 @@ LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int lnCount = 0;
|
|
|
|
int lnCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
LogicalNode* logicalNode = (LogicalNode*) logicalDevice->firstChild;
|
|
|
|
LogicalNode* logicalNode = (LogicalNode*)logicalDevice->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (logicalNode != NULL) {
|
|
|
|
while (logicalNode != NULL)
|
|
|
|
logicalNode = (LogicalNode*) logicalNode->sibling;
|
|
|
|
{
|
|
|
|
|
|
|
|
logicalNode = (LogicalNode*)logicalNode->sibling;
|
|
|
|
lnCount++;
|
|
|
|
lnCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -491,12 +518,13 @@ LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice)
|
|
|
|
ModelNode*
|
|
|
|
ModelNode*
|
|
|
|
LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char* mmsVariableName)
|
|
|
|
LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char* mmsVariableName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const char* separator = strchr(mmsVariableName,'$');
|
|
|
|
const char* separator = strchr(mmsVariableName, '$');
|
|
|
|
|
|
|
|
|
|
|
|
if (separator == NULL)
|
|
|
|
if (separator == NULL)
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
if (strlen(separator) > 4) {
|
|
|
|
if (strlen(separator) > 4)
|
|
|
|
|
|
|
|
{
|
|
|
|
char fcString[3];
|
|
|
|
char fcString[3];
|
|
|
|
char nameRef[65];
|
|
|
|
char nameRef[65];
|
|
|
|
|
|
|
|
|
|
|
@ -508,7 +536,8 @@ LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char
|
|
|
|
|
|
|
|
|
|
|
|
int targetPos = 0;
|
|
|
|
int targetPos = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (strpos < separator) {
|
|
|
|
while (strpos < separator)
|
|
|
|
|
|
|
|
{
|
|
|
|
nameRef[targetPos++] = strpos[0];
|
|
|
|
nameRef[targetPos++] = strpos[0];
|
|
|
|
strpos++;
|
|
|
|
strpos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -517,7 +546,8 @@ LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char
|
|
|
|
|
|
|
|
|
|
|
|
strpos = separator + 4;
|
|
|
|
strpos = separator + 4;
|
|
|
|
|
|
|
|
|
|
|
|
while (strpos[0] != 0) {
|
|
|
|
while (strpos[0] != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
nameRef[targetPos++] = strpos[0];
|
|
|
|
nameRef[targetPos++] = strpos[0];
|
|
|
|
strpos++;
|
|
|
|
strpos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -528,7 +558,7 @@ LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char
|
|
|
|
|
|
|
|
|
|
|
|
FunctionalConstraint fc = FunctionalConstraint_fromString(fcString);
|
|
|
|
FunctionalConstraint fc = FunctionalConstraint_fromString(fcString);
|
|
|
|
|
|
|
|
|
|
|
|
return ModelNode_getChildWithFc((ModelNode*) logicalDevice, nameRef, fc);
|
|
|
|
return ModelNode_getChildWithFc((ModelNode*)logicalDevice, nameRef, fc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
@ -566,11 +596,11 @@ createObjectReference(ModelNode* node, char* objectReference, int bufSize, bool
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogicalNode* lNode = (LogicalNode*) node;
|
|
|
|
LogicalNode* lNode = (LogicalNode*)node;
|
|
|
|
|
|
|
|
|
|
|
|
LogicalDevice* lDevice = (LogicalDevice*) lNode->parent;
|
|
|
|
LogicalDevice* lDevice = (LogicalDevice*)lNode->parent;
|
|
|
|
|
|
|
|
|
|
|
|
IedModel* iedModel = (IedModel*) lDevice->parent;
|
|
|
|
IedModel* iedModel = (IedModel*)lDevice->parent;
|
|
|
|
|
|
|
|
|
|
|
|
bufPos = 0;
|
|
|
|
bufPos = 0;
|
|
|
|
|
|
|
|
|
|
|
@ -581,10 +611,12 @@ createObjectReference(ModelNode* node, char* objectReference, int bufSize, bool
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (lDevice->ldName) {
|
|
|
|
if (lDevice->ldName)
|
|
|
|
|
|
|
|
{
|
|
|
|
StringUtils_copyStringMax(objectReference, bufSize, lDevice->ldName);
|
|
|
|
StringUtils_copyStringMax(objectReference, bufSize, lDevice->ldName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
StringUtils_concatString(objectReference, bufSize, iedModel->name, lDevice->name);
|
|
|
|
StringUtils_concatString(objectReference, bufSize, iedModel->name, lDevice->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -605,13 +637,15 @@ createObjectReference(ModelNode* node, char* objectReference, int bufSize, bool
|
|
|
|
if (bufPos + nameLength < bufSize)
|
|
|
|
if (bufPos + nameLength < bufSize)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < nameLength; i++) {
|
|
|
|
for (i = 0; i < nameLength; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
objectReference[bufPos++] = node->name[i];
|
|
|
|
objectReference[bufPos++] = node->name[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return bufPos;
|
|
|
|
return bufPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -630,7 +664,8 @@ createObjectReference(ModelNode* node, char* objectReference, int bufSize, bool
|
|
|
|
|
|
|
|
|
|
|
|
objectReference[bufPos++] = '(';
|
|
|
|
objectReference[bufPos++] = '(';
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < arrayIndexStrLength; i++) {
|
|
|
|
for (i = 0; i < arrayIndexStrLength; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
objectReference[bufPos++] = arrayIndexStr[i];
|
|
|
|
objectReference[bufPos++] = arrayIndexStr[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
objectReference[bufPos++] = ')';
|
|
|
|
objectReference[bufPos++] = ')';
|
|
|
@ -655,7 +690,7 @@ ModelNode_getObjectReferenceEx(ModelNode* node, char* objectReference, bool with
|
|
|
|
|
|
|
|
|
|
|
|
if (objectReference == NULL)
|
|
|
|
if (objectReference == NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
objectReference = (char*) GLOBAL_MALLOC(130);
|
|
|
|
objectReference = (char*)GLOBAL_MALLOC(130);
|
|
|
|
allocated = true;
|
|
|
|
allocated = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -681,12 +716,14 @@ ModelNode_getObjectReferenceEx(ModelNode* node, char* objectReference, bool with
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
int
|
|
|
|
ModelNode_getChildCount(ModelNode* modelNode) {
|
|
|
|
ModelNode_getChildCount(ModelNode* modelNode)
|
|
|
|
|
|
|
|
{
|
|
|
|
int childCount = 0;
|
|
|
|
int childCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
ModelNode* child = modelNode->firstChild;
|
|
|
|
ModelNode* child = modelNode->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (child != NULL) {
|
|
|
|
while (child != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
childCount++;
|
|
|
|
childCount++;
|
|
|
|
child = child->sibling;
|
|
|
|
child = child->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -713,7 +750,7 @@ ModelNode_getChild(ModelNode* self, const char* name)
|
|
|
|
|
|
|
|
|
|
|
|
if (arraySeparator2)
|
|
|
|
if (arraySeparator2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int idx = (int) strtol(arraySeparator + 1, NULL, 10);
|
|
|
|
int idx = (int)strtol(arraySeparator + 1, NULL, 10);
|
|
|
|
|
|
|
|
|
|
|
|
ModelNode* arrayNode = NULL;
|
|
|
|
ModelNode* arrayNode = NULL;
|
|
|
|
|
|
|
|
|
|
|
@ -740,7 +777,8 @@ ModelNode_getChild(ModelNode* self, const char* name)
|
|
|
|
|
|
|
|
|
|
|
|
ModelNode* childNode = ModelNode_getChild(self, nameCopy);
|
|
|
|
ModelNode* childNode = ModelNode_getChild(self, nameCopy);
|
|
|
|
|
|
|
|
|
|
|
|
if (childNode) {
|
|
|
|
if (childNode)
|
|
|
|
|
|
|
|
{
|
|
|
|
arrayNode = ModelNode_getChildWithIdx(childNode, idx);
|
|
|
|
arrayNode = ModelNode_getChildWithIdx(childNode, idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -764,11 +802,11 @@ ModelNode_getChild(ModelNode* self, const char* name)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
/* invalid name */
|
|
|
|
/* invalid name */
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int nameElementLength = 0;
|
|
|
|
int nameElementLength = 0;
|
|
|
@ -784,7 +822,8 @@ ModelNode_getChild(ModelNode* self, const char* name)
|
|
|
|
|
|
|
|
|
|
|
|
while (nextNode)
|
|
|
|
while (nextNode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (nextNode->name == NULL) {
|
|
|
|
if (nextNode->name == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
break; /* is an array element */
|
|
|
|
break; /* is an array element */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -802,7 +841,8 @@ ModelNode_getChild(ModelNode* self, const char* name)
|
|
|
|
nextNode = nextNode->sibling;
|
|
|
|
nextNode = nextNode->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((separator != NULL) && (matchingNode != NULL)) {
|
|
|
|
if ((separator != NULL) && (matchingNode != NULL))
|
|
|
|
|
|
|
|
{
|
|
|
|
return ModelNode_getChild(matchingNode, separator + 1);
|
|
|
|
return ModelNode_getChild(matchingNode, separator + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -866,9 +906,10 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (nextNode->modelType == DataAttributeModelType)
|
|
|
|
if (nextNode->modelType == DataAttributeModelType)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DataAttribute* da = (DataAttribute*) nextNode;
|
|
|
|
DataAttribute* da = (DataAttribute*)nextNode;
|
|
|
|
|
|
|
|
|
|
|
|
if (da->fc == fc) {
|
|
|
|
if (da->fc == fc)
|
|
|
|
|
|
|
|
{
|
|
|
|
matchingNode = nextNode;
|
|
|
|
matchingNode = nextNode;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -878,7 +919,7 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (nextNode->modelType == DataAttributeModelType)
|
|
|
|
if (nextNode->modelType == DataAttributeModelType)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DataAttribute* da = (DataAttribute*) nextNode;
|
|
|
|
DataAttribute* da = (DataAttribute*)nextNode;
|
|
|
|
|
|
|
|
|
|
|
|
if (da->fc == fc)
|
|
|
|
if (da->fc == fc)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -886,7 +927,8 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
matchingNode = nextNode;
|
|
|
|
matchingNode = nextNode;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -897,7 +939,8 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
|
|
|
|
nextNode = nextNode->sibling;
|
|
|
|
nextNode = nextNode->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((separator != NULL) && (matchingNode != NULL)) {
|
|
|
|
if ((separator != NULL) && (matchingNode != NULL))
|
|
|
|
|
|
|
|
{
|
|
|
|
return ModelNode_getChildWithFc(matchingNode, separator + 1, fc);
|
|
|
|
return ModelNode_getChildWithFc(matchingNode, separator + 1, fc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -932,7 +975,8 @@ ModelNode_getChildren(ModelNode* self)
|
|
|
|
|
|
|
|
|
|
|
|
ModelNode* childNode = self->firstChild;
|
|
|
|
ModelNode* childNode = self->firstChild;
|
|
|
|
|
|
|
|
|
|
|
|
while (childNode) {
|
|
|
|
while (childNode)
|
|
|
|
|
|
|
|
{
|
|
|
|
LinkedList_add(childNodes, childNode);
|
|
|
|
LinkedList_add(childNodes, childNode);
|
|
|
|
|
|
|
|
|
|
|
|
childNode = childNode->sibling;
|
|
|
|
childNode = childNode->sibling;
|
|
|
@ -944,20 +988,21 @@ ModelNode_getChildren(ModelNode* self)
|
|
|
|
LogicalNode*
|
|
|
|
LogicalNode*
|
|
|
|
LogicalDevice_getLogicalNode(LogicalDevice* self, const char* nodeName)
|
|
|
|
LogicalDevice_getLogicalNode(LogicalDevice* self, const char* nodeName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return (LogicalNode*) ModelNode_getChild((ModelNode*) self, nodeName);
|
|
|
|
return (LogicalNode*)ModelNode_getChild((ModelNode*)self, nodeName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SettingGroupControlBlock*
|
|
|
|
SettingGroupControlBlock*
|
|
|
|
LogicalDevice_getSettingGroupControlBlock(LogicalDevice* self)
|
|
|
|
LogicalDevice_getSettingGroupControlBlock(LogicalDevice* self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
IedModel* model = (IedModel*) self->parent;
|
|
|
|
IedModel* model = (IedModel*)self->parent;
|
|
|
|
|
|
|
|
|
|
|
|
if (model == NULL)
|
|
|
|
if (model == NULL)
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
LogicalNode* ln = LogicalDevice_getLogicalNode(self, "LLN0");
|
|
|
|
LogicalNode* ln = LogicalDevice_getLogicalNode(self, "LLN0");
|
|
|
|
|
|
|
|
|
|
|
|
if (ln == NULL) {
|
|
|
|
if (ln == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (DEBUG_IED_SERVER)
|
|
|
|
if (DEBUG_IED_SERVER)
|
|
|
|
printf("IED_SERVER: logical node LLN0 not found!\n");
|
|
|
|
printf("IED_SERVER: logical node LLN0 not found!\n");
|
|
|
|
|
|
|
|
|
|
|
@ -966,7 +1011,8 @@ LogicalDevice_getSettingGroupControlBlock(LogicalDevice* self)
|
|
|
|
|
|
|
|
|
|
|
|
SettingGroupControlBlock* sgcb = model->sgcbs;
|
|
|
|
SettingGroupControlBlock* sgcb = model->sgcbs;
|
|
|
|
|
|
|
|
|
|
|
|
while (sgcb != NULL) {
|
|
|
|
while (sgcb != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (sgcb->parent == ln)
|
|
|
|
if (sgcb->parent == ln)
|
|
|
|
return sgcb;
|
|
|
|
return sgcb;
|
|
|
|
|
|
|
|
|
|
|
|