Merge branch 'v1.6_develop_415' into v1.6_develop

pull/515/head
Michael Zillgith 1 year ago
commit 75cf6ba0c3

@ -1,7 +1,7 @@
/* /*
* config_file_parser.c * config_file_parser.c
* *
* Copyright 2014-2022 Michael Zillgith * Copyright 2014-2023 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -28,6 +28,8 @@
#include "libiec61850_platform_includes.h" #include "libiec61850_platform_includes.h"
#include "stack_config.h" #include "stack_config.h"
#include <ctype.h>
#define READ_BUFFER_MAX_SIZE 1024 #define READ_BUFFER_MAX_SIZE 1024
static int static int
@ -112,6 +114,112 @@ ConfigFileParser_createModelFromConfigFileEx(const char* filename)
return model; return model;
} }
static bool
setValue(char* lineBuffer, DataAttribute* dataAttribute)
{
char* valueIndicator = strchr((char*) lineBuffer, '=');
if (valueIndicator != NULL) {
switch (dataAttribute->type) {
case IEC61850_UNICODE_STRING_255:
{
char* stringStart = valueIndicator + 2;
terminateString(stringStart, '"');
dataAttribute->mmsValue = MmsValue_newMmsString(stringStart);
}
break;
case IEC61850_VISIBLE_STRING_255:
case IEC61850_VISIBLE_STRING_129:
case IEC61850_VISIBLE_STRING_65:
case IEC61850_VISIBLE_STRING_64:
case IEC61850_VISIBLE_STRING_32:
case IEC61850_CURRENCY:
{
char* stringStart = valueIndicator + 2;
terminateString(stringStart, '"');
dataAttribute->mmsValue = MmsValue_newVisibleString(stringStart);
}
break;
case IEC61850_INT8:
case IEC61850_INT16:
case IEC61850_INT32:
case IEC61850_INT64:
case IEC61850_INT128:
case IEC61850_ENUMERATED:
{
int32_t intValue;
if (sscanf(valueIndicator + 1, "%i", &intValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newIntegerFromInt32(intValue);
}
break;
case IEC61850_INT8U:
case IEC61850_INT16U:
case IEC61850_INT24U:
case IEC61850_INT32U:
{
uint32_t uintValue;
if (sscanf(valueIndicator + 1, "%u", &uintValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newUnsignedFromUint32(uintValue);
}
break;
case IEC61850_FLOAT32:
{
float floatValue;
if (sscanf(valueIndicator + 1, "%f", &floatValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newFloat(floatValue);
}
break;
case IEC61850_FLOAT64:
{
double doubleValue;
if (sscanf(valueIndicator + 1, "%lf", &doubleValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newDouble(doubleValue);
}
break;
case IEC61850_BOOLEAN:
{
int boolean;
if (sscanf(valueIndicator + 1, "%i", &boolean) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newBoolean((bool) boolean);
}
break;
case IEC61850_OPTFLDS:
{
int value;
if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newBitString(-10);
MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value);
}
break;
case IEC61850_TRGOPS:
{
int value;
if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newBitString(-6);
MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value);
}
break;
default:
break;
}
}
return true;
exit_error:
return false;
}
IedModel* IedModel*
ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle) ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
{ {
@ -124,11 +232,14 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
bool stateInModel = false; bool stateInModel = false;
int indendation = 0; int indendation = 0;
bool inArray = false;
bool inArrayElement = false;
IedModel* model = NULL; IedModel* model = NULL;
LogicalDevice* currentLD = NULL; LogicalDevice* currentLD = NULL;
LogicalNode* currentLN = NULL; LogicalNode* currentLN = NULL;
ModelNode* currentModelNode = NULL; ModelNode* currentModelNode = NULL;
ModelNode* currentArrayNode = NULL;
DataSet* currentDataSet = NULL; DataSet* currentDataSet = NULL;
GSEControlBlock* currentGoCB = NULL; GSEControlBlock* currentGoCB = NULL;
SVControlBlock* currentSMVCB = NULL; SVControlBlock* currentSMVCB = NULL;
@ -147,6 +258,18 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
if (bytesRead > 0) { if (bytesRead > 0) {
lineBuffer[bytesRead] = 0; lineBuffer[bytesRead] = 0;
/* trim trailing spaces */
while (bytesRead > 1) {
bytesRead--;
if (isspace(lineBuffer[bytesRead])) {
lineBuffer[bytesRead] = 0;
}
else {
break;
}
}
if (stateInModel) { if (stateInModel) {
if (StringUtils_startsWith((char*) lineBuffer, "}")) { if (StringUtils_startsWith((char*) lineBuffer, "}")) {
@ -164,11 +287,21 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
indendation = 3; indendation = 3;
} }
else if (indendation > 4) { else if (indendation > 4) {
currentModelNode = currentModelNode->parent;
if (inArrayElement && currentModelNode->parent == currentArrayNode) {
inArrayElement = false;
}
else {
indendation--; indendation--;
} }
if (inArray && currentModelNode == currentArrayNode) {
inArray = false;
} }
currentModelNode = currentModelNode->parent;
}
}
else if (indendation == 1) { else if (indendation == 1) {
if (StringUtils_startsWith((char*) lineBuffer, "LD")) { if (StringUtils_startsWith((char*) lineBuffer, "LD")) {
indendation = 2; indendation = 2;
@ -213,7 +346,9 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
int arrayElements = 0; int arrayElements = 0;
sscanf((char*) lineBuffer, "DO(%129s %i)", nameString, &arrayElements); if (sscanf((char*)lineBuffer, "DO(%129s %i)", nameString, &arrayElements) != 2) {
goto exit_error;
}
currentModelNode = (ModelNode*) currentModelNode = (ModelNode*)
DataObject_create(nameString, (ModelNode*) currentLN, arrayElements); DataObject_create(nameString, (ModelNode*) currentLN, arrayElements);
@ -221,7 +356,10 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
else if (StringUtils_startsWith((char*) lineBuffer, "DS")) { else if (StringUtils_startsWith((char*) lineBuffer, "DS")) {
indendation = 4; indendation = 4;
sscanf((char*) lineBuffer, "DS(%129s)", nameString); if (sscanf((char*)lineBuffer, "DS(%129s)", nameString) != 1) {
goto exit_error;
}
terminateString(nameString, ')'); terminateString(nameString, ')');
currentDataSet = DataSet_create(nameString, currentLN); currentDataSet = DataSet_create(nameString, currentLN);
@ -299,7 +437,6 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
nameString3, confRef, fixedOffs, minTime, maxTime); nameString3, confRef, fixedOffs, minTime, maxTime);
indendation = 4; indendation = 4;
} }
else if (StringUtils_startsWith((char*) lineBuffer, "SMVC")) { else if (StringUtils_startsWith((char*) lineBuffer, "SMVC")) {
uint32_t confRev; uint32_t confRev;
@ -316,7 +453,6 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
currentSMVCB = SVControlBlock_create(nameString, currentLN, nameString2, nameString3, confRev, smpMod, smpRate, optFlds, (bool) isUnicast); currentSMVCB = SVControlBlock_create(nameString, currentLN, nameString2, nameString3, confRev, smpMod, smpRate, optFlds, (bool) isUnicast);
indendation = 4; indendation = 4;
} }
#if (CONFIG_IEC61850_SETTING_GROUPS == 1) #if (CONFIG_IEC61850_SETTING_GROUPS == 1)
else if (StringUtils_startsWith((char*) lineBuffer, "SG")) { else if (StringUtils_startsWith((char*) lineBuffer, "SG")) {
@ -360,117 +496,64 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
currentModelNode = (ModelNode*) DataObject_create(nameString, currentModelNode, arrayElements); currentModelNode = (ModelNode*) DataObject_create(nameString, currentModelNode, arrayElements);
} }
else if (StringUtils_startsWith((char*) lineBuffer, "DA")) { else if (StringUtils_startsWith((char*) lineBuffer, "[")) {
if (inArray == false) {
int arrayElements = 0; goto exit_error;
}
int attributeType = 0;
int functionalConstraint = 0;
int triggerOptions = 0;
uint32_t sAddr = 0;
sscanf((char*) lineBuffer, "DA(%129s %i %i %i %i %u)", nameString, &arrayElements, &attributeType, &functionalConstraint, &triggerOptions, &sAddr); int arrayIndex;
DataAttribute* dataAttribute = DataAttribute_create(nameString, currentModelNode, if (sscanf((char*)lineBuffer, "[%i]", &arrayIndex) != 1) {
(DataAttributeType) attributeType, (FunctionalConstraint) functionalConstraint, triggerOptions, arrayElements, sAddr); goto exit_error;
}
char* valueIndicator = strchr((char*) lineBuffer, '='); if (StringUtils_endsWith((char*)lineBuffer, ";")) {
/* array of basic data attribute */
ModelNode* arrayElementNode = ModelNode_getChildWithIdx(currentArrayNode, arrayIndex);
if (valueIndicator != NULL) { if (arrayElementNode) {
switch (dataAttribute->type) { setValue((char*)lineBuffer, (DataAttribute*)arrayElementNode);
case IEC61850_UNICODE_STRING_255:
{
char* stringStart = valueIndicator + 2;
terminateString(stringStart, '"');
dataAttribute->mmsValue = MmsValue_newMmsString(stringStart);
} }
break; else {
goto exit_error;
case IEC61850_VISIBLE_STRING_255:
case IEC61850_VISIBLE_STRING_129:
case IEC61850_VISIBLE_STRING_65:
case IEC61850_VISIBLE_STRING_64:
case IEC61850_VISIBLE_STRING_32:
case IEC61850_CURRENCY:
{
char* stringStart = valueIndicator + 2;
terminateString(stringStart, '"');
dataAttribute->mmsValue = MmsValue_newVisibleString(stringStart);
} }
break;
case IEC61850_INT8:
case IEC61850_INT16:
case IEC61850_INT32:
case IEC61850_INT64:
case IEC61850_INT128:
case IEC61850_ENUMERATED:
{
int32_t intValue;
if (sscanf(valueIndicator + 1, "%i", &intValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newIntegerFromInt32(intValue);
} }
break; else if (StringUtils_endsWith((char*)lineBuffer, "{")) {
/* array of constructed data attribtute */
currentModelNode = ModelNode_getChildWithIdx(currentArrayNode, arrayIndex);
case IEC61850_INT8U: if (currentModelNode) {
case IEC61850_INT16U: inArrayElement = true;
case IEC61850_INT24U:
case IEC61850_INT32U:
{
uint32_t uintValue;
if (sscanf(valueIndicator + 1, "%u", &uintValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newUnsignedFromUint32(uintValue);
} }
break; else {
goto exit_error;
case IEC61850_FLOAT32:
{
float floatValue;
if (sscanf(valueIndicator + 1, "%f", &floatValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newFloat(floatValue);
} }
break;
case IEC61850_FLOAT64:
{
double doubleValue;
if (sscanf(valueIndicator + 1, "%lf", &doubleValue) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newDouble(doubleValue);
} }
break;
case IEC61850_BOOLEAN:
{
int boolean;
if (sscanf(valueIndicator + 1, "%i", &boolean) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newBoolean((bool) boolean);
} }
break; else if (StringUtils_startsWith((char*) lineBuffer, "DA")) {
case IEC61850_OPTFLDS: int arrayElements = 0;
{
int value;
if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error;
dataAttribute->mmsValue = MmsValue_newBitString(-10);
MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value);
}
break;
case IEC61850_TRGOPS: int attributeType = 0;
{ int functionalConstraint = 0;
int value; int triggerOptions = 0;
if (sscanf(valueIndicator + 1, "%i", &value) != 1) goto exit_error; uint32_t sAddr = 0;
dataAttribute->mmsValue = MmsValue_newBitString(-6);
MmsValue_setBitStringFromIntegerBigEndian(dataAttribute->mmsValue, value); if (sscanf((char*)lineBuffer, "DA(%129s %i %i %i %i %u)", nameString, &arrayElements, &attributeType, &functionalConstraint, &triggerOptions, &sAddr) != 6) {
goto exit_error;
} }
break;
default: DataAttribute* dataAttribute = DataAttribute_create(nameString, currentModelNode,
break; (DataAttributeType) attributeType, (FunctionalConstraint) functionalConstraint, triggerOptions, arrayElements, sAddr);
} if (arrayElements > 0) {
inArray = true;
currentArrayNode = (ModelNode*)dataAttribute;
} }
setValue((char*)lineBuffer, dataAttribute);
int lineLength = (int) strlen((char*) lineBuffer); int lineLength = (int) strlen((char*) lineBuffer);
if (lineBuffer[lineLength - 1] == '{') { if (lineBuffer[lineLength - 1] == '{') {
@ -553,7 +636,9 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
indendation = 1; indendation = 1;
} }
else if (StringUtils_startsWith((char*) lineBuffer, "MODEL(")) { else if (StringUtils_startsWith((char*) lineBuffer, "MODEL(")) {
sscanf((char*) lineBuffer, "MODEL(%129s)", nameString); if (sscanf((char*)lineBuffer, "MODEL(%129s)", nameString) != 1)
goto exit_error;
terminateString(nameString, ')'); terminateString(nameString, ')');
model = IedModel_create(nameString); model = IedModel_create(nameString);
stateInModel = true; stateInModel = true;

Loading…
Cancel
Save