diff --git a/examples/server_example3/simpleIO_direct_control.icd b/examples/server_example3/simpleIO_direct_control.icd
index df5636b9..b48a383e 100644
--- a/examples/server_example3/simpleIO_direct_control.icd
+++ b/examples/server_example3/simpleIO_direct_control.icd
@@ -85,7 +85,15 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/examples/server_example3/static_model.c b/examples/server_example3/static_model.c
index 84faec82..d28f3abd 100644
--- a/examples/server_example3/static_model.c
+++ b/examples/server_example3/static_model.c
@@ -1955,6 +1955,16 @@ ReportControlBlock iedModel_GenericIO_LLN0_report6 = {&iedModel_GenericIO_LLN0,
+extern LogControlBlock iedModel_GenericIO_LLN0_lcb0;
+extern LogControlBlock iedModel_GenericIO_LLN0_lcb1;
+LogControlBlock iedModel_GenericIO_LLN0_lcb0 = {&iedModel_GenericIO_LLN0, "EventLog", "Events", "EventLog", 19, 0, true, true, &iedModel_GenericIO_LLN0_lcb1};
+LogControlBlock iedModel_GenericIO_LLN0_lcb1 = {&iedModel_GenericIO_LLN0, "GeneralLog", "", "", 19, 0, true, true, NULL};
+
+extern Log iedModel_GenericIO_LLN0_log0;
+extern Log iedModel_GenericIO_LLN0_log1;
+Log iedModel_GenericIO_LLN0_log0 = {&iedModel_GenericIO_LLN0, "GeneralLog", &iedModel_GenericIO_LLN0_log1};
+Log iedModel_GenericIO_LLN0_log1 = {&iedModel_GenericIO_LLN0, "EventLog", NULL};
+
IedModel iedModel = {
"simpleIO",
@@ -1964,6 +1974,8 @@ IedModel iedModel = {
NULL,
NULL,
NULL,
+ &iedModel_GenericIO_LLN0_lcb0,
+ &iedModel_GenericIO_LLN0_log0,
initializeValues
};
diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h
index 6e3c66a0..961e640d 100644
--- a/src/iec61850/inc/iec61850_model.h
+++ b/src/iec61850/inc/iec61850_model.h
@@ -270,9 +270,11 @@ struct sLogControlBlock {
char* logRef; /* object reference to the journal. Defaults to /$GeneralLog */
uint8_t trgOps; /* TrgOps - trigger conditions */
- uint8_t options; /* OptFlds */
uint32_t intPeriod; /* IntgPd - integrity period */
+ bool logEna; /* enable log by default */
+ bool reasonCode; /* include reason code in log */
+
LogControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
};
diff --git a/src/iec61850/inc_private/logging.h b/src/iec61850/inc_private/logging.h
index 33de8a89..9aedaadb 100644
--- a/src/iec61850/inc_private/logging.h
+++ b/src/iec61850/inc_private/logging.h
@@ -30,6 +30,8 @@ typedef struct {
DataSet* dataSet;
+ MmsDomain* domain;
+
bool enabled;
int triggerOps;
@@ -37,10 +39,13 @@ typedef struct {
} LogControl;
LogControl*
-LogControl_create(bool buffered, LogicalNode* parentLN);
+LogControl_create(LogicalNode* parentLN);
void
LogControl_destroy(LogControl* self);
+MmsVariableSpecification*
+Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode,
+ int lcbCount);
#endif /* LIBIEC61850_SRC_IEC61850_INC_PRIVATE_LOGGING_H_ */
diff --git a/src/iec61850/inc_private/mms_mapping_internal.h b/src/iec61850/inc_private/mms_mapping_internal.h
index 367d0e4a..82660792 100644
--- a/src/iec61850/inc_private/mms_mapping_internal.h
+++ b/src/iec61850/inc_private/mms_mapping_internal.h
@@ -36,7 +36,7 @@ struct sMmsMapping {
LinkedList reportControls;
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
- LinkedList* logControls;
+ LinkedList logControls;
#endif
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
diff --git a/src/iec61850/server/mms_mapping/logging.c b/src/iec61850/server/mms_mapping/logging.c
index 46632d88..33ba25a9 100644
--- a/src/iec61850/server/mms_mapping/logging.c
+++ b/src/iec61850/server/mms_mapping/logging.c
@@ -25,10 +25,19 @@
#include "stack_config.h"
#include "mms_mapping.h"
#include "logging.h"
+#include "linked_list.h"
+#include "array_list.h"
+#include "hal_thread.h"
+
+#include "simple_allocator.h"
+#include "mem_alloc_linked_list.h"
+
+#include "mms_mapping_internal.h"
+#include "mms_value_internal.h"
LogControl*
-LogControl_create(bool buffered, LogicalNode* parentLN)
+LogControl_create(LogicalNode* parentLN)
{
LogControl* self = (LogControl*) GLOBAL_MALLOC(sizeof(LogControl));
@@ -46,3 +55,228 @@ LogControl_destroy(LogControl* self)
GLOBAL_FREEMEM(self);
}
}
+
+static LogControlBlock*
+getLCBForLogicalNodeWithIndex(MmsMapping* self, LogicalNode* logicalNode, int index)
+{
+ int lcbCount = 0;
+
+ LogControlBlock* nextLcb = self->model->lcbs;
+
+ while (nextLcb != NULL ) {
+ if (nextLcb->parent == logicalNode) {
+
+ if (lcbCount == index)
+ return nextLcb;
+
+ lcbCount++;
+
+ }
+
+ nextLcb = nextLcb->sibling;
+ }
+
+ return NULL ;
+}
+
+static char*
+createDataSetReferenceForDefaultDataSet(LogControlBlock* lcb, LogControl* logControl)
+{
+ char* dataSetReference;
+
+ char* domainName = MmsDomain_getName(logControl->domain);
+ char* lnName = lcb->parent->name;
+
+ dataSetReference = createString(5, domainName, "/", lnName, "$", lcb->dataSetName);
+
+ return dataSetReference;
+}
+
+static MmsValue*
+createTrgOps(LogControlBlock* reportControlBlock) {
+ MmsValue* trgOps = MmsValue_newBitString(-6);
+
+ uint8_t triggerOps = reportControlBlock->trgOps;
+
+ if (triggerOps & TRG_OPT_DATA_CHANGED)
+ MmsValue_setBitStringBit(trgOps, 1, true);
+ if (triggerOps & TRG_OPT_QUALITY_CHANGED)
+ MmsValue_setBitStringBit(trgOps, 2, true);
+ if (triggerOps & TRG_OPT_DATA_UPDATE)
+ MmsValue_setBitStringBit(trgOps, 3, true);
+ if (triggerOps & TRG_OPT_INTEGRITY)
+ MmsValue_setBitStringBit(trgOps, 4, true);
+
+ //TODO remove - GI doesn't exist here!
+ if (triggerOps & TRG_OPT_GI)
+ MmsValue_setBitStringBit(trgOps, 5, true);
+
+ return trgOps;
+}
+
+static MmsVariableSpecification*
+createLogControlBlock(LogControlBlock* logControlBlock,
+ LogControl* logControl)
+{
+ MmsVariableSpecification* rcb = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ rcb->name = copyString(logControlBlock->name);
+ rcb->type = MMS_STRUCTURE;
+
+ MmsValue* mmsValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
+ mmsValue->deleteValue = false;
+ mmsValue->type = MMS_STRUCTURE;
+
+ int structSize = 9;
+
+ mmsValue->value.structure.size = structSize;
+ mmsValue->value.structure.components = (MmsValue**) GLOBAL_CALLOC(structSize, sizeof(MmsValue*));
+
+ rcb->typeSpec.structure.elementCount = structSize;
+
+ rcb->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(structSize,
+ sizeof(MmsVariableSpecification*));
+
+ /* LogEna */
+ MmsVariableSpecification* namedVariable =
+ (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+
+ namedVariable->name = copyString("LogEna");
+ namedVariable->type = MMS_BOOLEAN;
+
+ rcb->typeSpec.structure.elements[0] = namedVariable;
+ mmsValue->value.structure.components[0] = MmsValue_newBoolean(logControlBlock->logEna);
+
+ /* LogRef */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("LogRef");
+ namedVariable->typeSpec.visibleString = -129;
+ namedVariable->type = MMS_VISIBLE_STRING;
+ rcb->typeSpec.structure.elements[1] = namedVariable;
+
+ if (logControlBlock->logRef != NULL) {
+ mmsValue->value.structure.components[1] = MmsValue_newVisibleString(logControlBlock->logRef);
+ }
+ else {
+ char* logRef = createString(4, logControl->domain->domainName, "/", logControlBlock->parent->name,
+ "$GeneralLog");
+
+ mmsValue->value.structure.components[1] = MmsValue_newVisibleString(logRef);
+
+ GLOBAL_FREEMEM(logRef);
+ }
+
+ /* DatSet */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("DatSet");
+ namedVariable->typeSpec.visibleString = -129;
+ namedVariable->type = MMS_VISIBLE_STRING;
+ rcb->typeSpec.structure.elements[2] = namedVariable;
+
+ if (logControlBlock->dataSetName != NULL) {
+ char* dataSetReference = createDataSetReferenceForDefaultDataSet(logControlBlock, logControl);
+
+ mmsValue->value.structure.components[2] = MmsValue_newVisibleString(dataSetReference);
+ GLOBAL_FREEMEM(dataSetReference);
+ }
+ else
+ mmsValue->value.structure.components[2] = MmsValue_newVisibleString("");
+
+ /* OldEntrTm */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("OldEntrTm");
+ namedVariable->type = MMS_BINARY_TIME;
+ namedVariable->typeSpec.binaryTime = 6;
+ rcb->typeSpec.structure.elements[3] = namedVariable;
+
+ mmsValue->value.structure.components[3] = MmsValue_newBinaryTime(false);
+
+ /* NewEntrTm */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("NewEntrTm");
+ namedVariable->type = MMS_BINARY_TIME;
+ namedVariable->typeSpec.binaryTime = 6;
+ rcb->typeSpec.structure.elements[4] = namedVariable;
+
+ mmsValue->value.structure.components[4] = MmsValue_newBinaryTime(false);
+
+ /* OldEntr */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("OldEntr");
+ namedVariable->type = MMS_OCTET_STRING;
+ namedVariable->typeSpec.octetString = 8;
+
+ rcb->typeSpec.structure.elements[5] = namedVariable;
+
+ mmsValue->value.structure.components[5] = MmsValue_newOctetString(8, 8);
+
+ /* NewEntr */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("NewEntr");
+ namedVariable->type = MMS_OCTET_STRING;
+ namedVariable->typeSpec.octetString = 8;
+
+ rcb->typeSpec.structure.elements[6] = namedVariable;
+
+ mmsValue->value.structure.components[6] = MmsValue_newOctetString(8, 8);
+
+ /* TrgOps */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("TrgOps");
+ namedVariable->type = MMS_BIT_STRING;
+ namedVariable->typeSpec.bitString = -6;
+ rcb->typeSpec.structure.elements[7] = namedVariable;
+ mmsValue->value.structure.components[7] = createTrgOps(logControlBlock);
+
+ /* IntgPd */
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("IntgPd");
+ namedVariable->type = MMS_UNSIGNED;
+ namedVariable->typeSpec.unsignedInteger = 32;
+ rcb->typeSpec.structure.elements[8] = namedVariable;
+ mmsValue->value.structure.components[8] =
+ MmsValue_newUnsignedFromUint32(logControlBlock->intPeriod);
+
+
+ //TODO logControl->rcbValues = mmsValue;
+
+ return rcb;
+}
+
+
+
+MmsVariableSpecification*
+Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode,
+ int lcbCount)
+{
+ MmsVariableSpecification* namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1,
+ sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("LG");
+ namedVariable->type = MMS_STRUCTURE;
+
+ namedVariable->typeSpec.structure.elementCount = lcbCount;
+ namedVariable->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(lcbCount,
+ sizeof(MmsVariableSpecification*));
+
+ int currentLcb = 0;
+
+ while (currentLcb < lcbCount) {
+
+ LogControl* logControl = LogControl_create(logicalNode);
+
+ LogControlBlock* logControlBlock = getLCBForLogicalNodeWithIndex(self, logicalNode, currentLcb);
+
+ logControl->name = createString(3, logicalNode->name, "$LG$", logControlBlock->name);
+ logControl->domain = domain;
+
+ namedVariable->typeSpec.structure.elements[currentLcb] =
+ createLogControlBlock(logControlBlock, logControl);
+
+ LinkedList_add(self->logControls, logControl);
+
+ currentLcb++;
+ }
+
+ return namedVariable;
+}
+
+
diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c
index 3b1b1425..60d0767f 100644
--- a/src/iec61850/server/mms_mapping/mms_mapping.c
+++ b/src/iec61850/server/mms_mapping/mms_mapping.c
@@ -1,7 +1,7 @@
/*
* mms_mapping.c
*
- * Copyright 2013, 2014, 2015 Michael Zillgith
+ * Copyright 2013-2016 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -30,6 +30,7 @@
#include "mms_goose.h"
#include "mms_sv.h"
#include "reporting.h"
+#include "logging.h"
#include "control.h"
#include "ied_server_private.h"
@@ -756,6 +757,25 @@ countReportControlBlocksForLogicalNode(MmsMapping* self, LogicalNode* logicalNod
}
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
+#if (CONFIG_IEC61850_LOG_SERVICE == 1)
+static int
+countLogControlBlocksForLogicalNode (MmsMapping* self, LogicalNode* logicalNode)
+{
+ int lcbCount = 0;
+
+ LogControlBlock* lcb = self->model->lcbs;
+
+ while (lcb != NULL) {
+ if (lcb->parent == logicalNode)
+ lcbCount++;
+
+ lcb = lcb->sibling;
+ }
+
+ return lcbCount;
+}
+#endif /* (CONFIG_IEC61850_LOG_SERVICE == 1) */
+
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
@@ -870,6 +890,19 @@ createNamedVariableFromLogicalNode(MmsMapping* self, MmsDomain* domain,
}
#endif /* (CONFIG_IEC61850_REPORT_SERVICE == 1) */
+#if (CONFIG_IEC61850_LOG_SERVICE == 1)
+
+ int lcbCount = countLogControlBlocksForLogicalNode(self, logicalNode);
+
+ if (lcbCount > 0) {
+ if (DEBUG_IED_SERVER)
+ printf(" and %i LOG control blocks\n", lcbCount);
+
+ componentCount++;
+ }
+
+#endif /* (CONFIG_IEC61850_LOG_SERVICE == 1) */
+
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
int gseCount = countGSEControlBlocksForLogicalNode(self, logicalNode);
@@ -969,7 +1002,15 @@ createNamedVariableFromLogicalNode(MmsMapping* self, MmsDomain* domain,
}
#endif /* (CONFIG_IEC61850_REPORT_SERVICE == 1) */
- /* TODO create LCBs here */
+#if (CONFIG_IEC61850_LOG_SERVICE == 1)
+ if (lcbCount > 0) {
+ namedVariable->typeSpec.structure.elements[currentComponent] =
+ Logging_createLCBs(self, domain, logicalNode, lcbCount);
+
+ currentComponent++;
+ }
+#endif /* (CONFIG_IEC61850_LOG_SERVICE == 1) */
+
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
if (brcbCount > 0) {
@@ -1069,6 +1110,18 @@ createMmsDomainFromIedDevice(MmsMapping* self, LogicalDevice* logicalDevice)
if (domain == NULL)
goto exit_function;
+#if (CONFIG_IEC61850_LOG_SERVICE == 1)
+ /* add logs (journals) */
+ Log* log = self->model->logs;
+
+ while (log != NULL) {
+
+ MmsDomain_addJournal(domain, log->name);
+
+ log = log->sibling;
+ }
+#endif /* (CONFIG_IEC61850_LOG_SERVICE == 1) */
+
int nodesCount = LogicalDevice_getLogicalNodeCount(logicalDevice);
/* Logical nodes are first level named variables */
diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c
index 22163fcd..8d16731a 100644
--- a/src/iec61850/server/mms_mapping/reporting.c
+++ b/src/iec61850/server/mms_mapping/reporting.c
@@ -770,7 +770,7 @@ createUnbufferedReportControlBlock(ReportControlBlock* reportControlBlock,
rcb->typeSpec.structure.elementCount = structSize;
- rcb->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(12,
+ rcb->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(structSize,
sizeof(MmsVariableSpecification*));
MmsVariableSpecification* namedVariable =
diff --git a/src/mms/inc/mms_device_model.h b/src/mms/inc/mms_device_model.h
index 6bed93ee..b2290ab4 100644
--- a/src/mms/inc/mms_device_model.h
+++ b/src/mms/inc/mms_device_model.h
@@ -89,7 +89,7 @@ char*
MmsDomain_getName(MmsDomain* self);
void
-MmsDomain_addJournal(MmsDomain* self, MmsJournal journal);
+MmsDomain_addJournal(MmsDomain* self, const char* name);
/**
* Delete a MmsDomain instance
diff --git a/src/mms/iso_mms/server/mms_domain.c b/src/mms/iso_mms/server/mms_domain.c
index b2ceb194..6f406422 100644
--- a/src/mms/iso_mms/server/mms_domain.c
+++ b/src/mms/iso_mms/server/mms_domain.c
@@ -74,11 +74,13 @@ MmsDomain_getName(MmsDomain* self)
}
void
-MmsDomain_addJournal(MmsDomain* self, MmsJournal journal)
+MmsDomain_addJournal(MmsDomain* self, const char* name)
{
if (self->journals == NULL)
self->journals = LinkedList_create();
+ MmsJournal journal = MmsJournal_create(name);
+
LinkedList_add(self->journals, (void*) journal);
}
diff --git a/src/mms/iso_mms/server/mms_get_namelist_service.c b/src/mms/iso_mms/server/mms_get_namelist_service.c
index a36dbedb..fe93737f 100644
--- a/src/mms/iso_mms/server/mms_get_namelist_service.c
+++ b/src/mms/iso_mms/server/mms_get_namelist_service.c
@@ -173,6 +173,35 @@ addSubNamedVaribleNamesToList(LinkedList nameList, char* prefix, MmsVariableSpec
#endif /* (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) */
+
+
+
+static LinkedList
+getJournalListDomainSpecific(MmsServerConnection connection, char* domainName)
+{
+ MmsDevice* device = MmsServer_getDevice(connection->server);
+
+ LinkedList nameList = NULL;
+
+ MmsDomain* domain = MmsDevice_getDomain(device, domainName);
+
+ if (domain != NULL) {
+ nameList = LinkedList_create();
+
+ LinkedList journalList = domain->journals;
+
+ while ((journalList = LinkedList_getNext(journalList)) != NULL) {
+
+ MmsJournal journal = (MmsJournal) LinkedList_getData(journalList);
+
+ LinkedList_add(nameList, (void*) journal->name);
+ }
+
+ }
+
+ return nameList;
+}
+
static LinkedList
getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
{
@@ -503,6 +532,16 @@ mmsServer_handleGetNameListRequest(
LinkedList_destroy(nameList);
}
}
+ else if (objectClass == OBJECT_CLASS_JOURNAL) {
+ LinkedList nameList = getJournalListDomainSpecific(connection, domainSpecificName);
+
+ if (nameList == NULL)
+ mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
+ else {
+ createNameListResponse(connection, invokeId, nameList, response, continueAfterId);
+ LinkedList_destroy(nameList);
+ }
+ }
#if (MMS_DATA_SET_SERVICE == 1)
else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE_LIST) {
LinkedList nameList = getNamedVariableListsDomainSpecific(connection, domainSpecificName);
diff --git a/tools/model_generator/genmodel.jar b/tools/model_generator/genmodel.jar
index 784ac0ac..3c50d337 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/scl/model/LogControl.java b/tools/model_generator/src/com/libiec61850/scl/model/LogControl.java
index b781aca2..82cd3576 100644
--- a/tools/model_generator/src/com/libiec61850/scl/model/LogControl.java
+++ b/tools/model_generator/src/com/libiec61850/scl/model/LogControl.java
@@ -6,7 +6,7 @@ import com.libiec61850.scl.ParserUtils;
import com.libiec61850.scl.SclParserException;
/*
- * Copyright 2014 Michael Zillgith
+ * Copyright 2014-2016 Michael Zillgith
*
* This file is part of libIEC61850.
*
diff --git a/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java b/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java
index 021dfc80..c43c5860 100644
--- a/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java
+++ b/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java
@@ -280,6 +280,14 @@ public class LogicalNode implements DataModelNode {
return settingGroupControlBlocks;
}
+ public List getLogControlBlocks() {
+ return logControlBlocks;
+ }
+
+ public List getLogs() {
+ return logs;
+ }
+
@Override
public DataModelNode getChildByName(String childName) {
for (DataObject dataObject : dataObjects) {
diff --git a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
index ea88eeee..fca09171 100644
--- a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
+++ b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
@@ -48,6 +48,8 @@ import com.libiec61850.scl.model.FunctionalConstraint;
import com.libiec61850.scl.model.FunctionalConstraintData;
import com.libiec61850.scl.model.GSEControl;
import com.libiec61850.scl.model.IED;
+import com.libiec61850.scl.model.Log;
+import com.libiec61850.scl.model.LogControl;
import com.libiec61850.scl.model.LogicalDevice;
import com.libiec61850.scl.model.LogicalNode;
import com.libiec61850.scl.model.ReportControlBlock;
@@ -70,7 +72,11 @@ public class StaticModelGenerator {
private StringBuffer logControlBlocks;
private List lcbVariableNames;
- private int currentLcbVariableNumber;
+ private int currentLcbVariableNumber = 0;
+
+ private StringBuffer logs;
+ private List logVariableNames;
+ private int currentLogVariableNumber = 0;
private StringBuffer gseControlBlocks;
private List gseVariableNames;
@@ -104,9 +110,12 @@ public class StaticModelGenerator {
{
this.cOut = cOut;
this.hOut = hOut;
+
this.initializerBuffer = new StringBuffer();
+
this.reportControlBlocks = new StringBuffer();
this.rcbVariableNames = new LinkedList();
+
this.gseControlBlocks = new StringBuffer();
this.gseVariableNames = new LinkedList();
@@ -116,6 +125,12 @@ public class StaticModelGenerator {
this.settingGroupControlBlocks = new StringBuffer();
this.sgcbVariableNames = new LinkedList();
+ this.logControlBlocks = new StringBuffer();
+ this.lcbVariableNames = new LinkedList();
+
+ this.logs = new StringBuffer();
+ this.logVariableNames = new LinkedList();
+
SclParser sclParser = new SclParser(stream);
this.outputFileName = outputFileName;
@@ -256,15 +271,6 @@ public class StaticModelGenerator {
}
}
-// private String getLogicalDeviceName(LogicalDevice logicalDevice) {
-// String logicalDeviceName = logicalDevice.getLdName();
-//
-// if (logicalDeviceName == null)
-// logicalDeviceName = ied.getName() + logicalDevice.getInst();
-//
-// return logicalDeviceName;
-// }
-
private String getLogicalDeviceInst(LogicalDevice logicalDevice) {
return logicalDevice.getInst();
}
@@ -277,6 +283,10 @@ public class StaticModelGenerator {
createReportVariableList(logicalDevices);
+ createLogControlVariableList(logicalDevices);
+
+ createLogVariableList(logicalDevices);
+
createGooseVariableList(logicalDevices);
createSmvVariableList(logicalDevices);
@@ -322,6 +332,7 @@ public class StaticModelGenerator {
cOut.println(reportControlBlocks);
+
for (String smv : smvVariableNames)
cOut.println("extern SVControlBlock " + smv + ";");
@@ -336,7 +347,17 @@ public class StaticModelGenerator {
cOut.println("extern SettingGroupControlBlock " + sgcb + ";");
cOut.println(settingGroupControlBlocks);
-
+
+ for (String lcb : lcbVariableNames)
+ cOut.println("extern LogControlBlock " + lcb + ";");
+
+ cOut.println(logControlBlocks);
+
+ for (String log : logVariableNames)
+ cOut.println("extern Log " + log + ";");
+
+ cOut.println(logs);
+
String firstLogicalDeviceName = logicalDevices.get(0).getInst();
cOut.println("\nIedModel " + modelPrefix + " = {");
cOut.println(" \"" + ied.getName() + "\",");
@@ -367,6 +388,16 @@ public class StaticModelGenerator {
else
cOut.println(" NULL,");
+ if (lcbVariableNames.size() > 0)
+ cOut.println(" &" + lcbVariableNames.get(0) + ",");
+ else
+ cOut.println(" NULL,");
+
+ if (logVariableNames.size() > 0)
+ cOut.println(" &" + logVariableNames.get(0) + ",");
+ else
+ cOut.println(" NULL,");
+
cOut.println(" initializeValues\n};");
}
@@ -442,6 +473,54 @@ public class StaticModelGenerator {
}
}
+ private void createLogControlVariableList(List logicalDevices)
+ {
+ for (LogicalDevice ld : logicalDevices) {
+ List lnodes = ld.getLogicalNodes();
+
+ String ldName = ld.getInst();
+
+ for (LogicalNode ln : lnodes) {
+ List lcbs = ln.getLogControlBlocks();
+
+ int lcbCount = 0;
+
+ for (LogControl logControl : lcbs) {
+
+ String lcbVariableName = modelPrefix + "_" + ldName + "_" + ln.getName() + "_lcb" + lcbCount;
+
+ lcbVariableNames.add(lcbVariableName);
+
+ lcbCount++;
+ }
+ }
+ }
+ }
+
+ private void createLogVariableList(List logicalDevices)
+ {
+ for (LogicalDevice ld : logicalDevices) {
+ List lnodes = ld.getLogicalNodes();
+
+ String ldName = ld.getInst();
+
+ for (LogicalNode ln : lnodes) {
+ List logs = ln.getLogs();
+
+ int logCount = 0;
+
+ for (Log log : logs) {
+
+ String logVariableName = modelPrefix + "_" + ldName + "_" + ln.getName() + "_log" + logCount;
+
+ logVariableNames.add(logVariableName);
+
+ logCount++;
+ }
+ }
+ }
+ }
+
private void createSettingControlsVariableList(List logicalDevices) {
for (LogicalDevice ld : logicalDevices) {
List lnodes = ld.getLogicalNodes();
@@ -488,6 +567,10 @@ public class StaticModelGenerator {
printDataObjectDefinitions(lnName, logicalNode.getDataObjects(), null);
printReportControlBlocks(lnName, logicalNode);
+
+ printLogControlBlocks(lnName, logicalNode);
+
+ printLogs(lnName, logicalNode);
printGSEControlBlocks(ldName, lnName, logicalNode);
@@ -994,6 +1077,34 @@ public class StaticModelGenerator {
}
}
+ private void printLogControlBlocks(String lnPrefix, LogicalNode logicalNode)
+ {
+ List logControlBlocks = logicalNode.getLogControlBlocks();
+
+ int lcbCount = logControlBlocks.size();
+
+ int lcbNumber = 0;
+
+ for (LogControl lcb : logControlBlocks) {
+ printLogControlBlock(lnPrefix, lcb, lcbNumber, lcbCount);
+ lcbNumber++;
+ }
+ }
+
+ private void printLogs(String lnPrefix, LogicalNode logicalNode)
+ {
+ List logs = logicalNode.getLogs();
+
+ int logCount = logs.size();
+
+ int logNumber = 0;
+
+ for (Log log : logs) {
+ printLog(lnPrefix, log, logNumber, logCount);
+ logNumber++;
+ }
+ }
+
private void printSettingControlBlock(String lnPrefix, LogicalNode logicalNode)
{
List settingControls = logicalNode.getSettingGroupControlBlocks();
@@ -1023,8 +1134,85 @@ public class StaticModelGenerator {
currentSGCBVariableNumber++;
}
}
+
+ private void printLog(String lnPrefix, Log log, int logNumber, int logCount)
+ {
+ String logVariableName = lnPrefix + "_log" + logNumber;
+
+ String logString = "Log " + logVariableName + " = {";
+
+ logString += "&" + lnPrefix + ", ";
+
+ logString += "\"" + log.getName() + "\", ";
+
+ currentLogVariableNumber++;
+
+ if (currentLogVariableNumber < logVariableNames.size())
+ logString += "&" + logVariableNames.get(currentLogVariableNumber);
+ else
+ logString += "NULL";
+
+ logString += "};\n";
- private void printReportControlBlockInstance(String lnPrefix, ReportControlBlock rcb, String index, int reportNumber, int reportsCount) {
+ this.logs.append(logString);
+ }
+
+ private void printLogControlBlock(String lnPrefix, LogControl lcb, int lcbNumber, int lcbCount)
+ {
+ String lcbVariableName = lnPrefix + "_lcb" + lcbNumber;
+
+ String lcbString = "LogControlBlock " + lcbVariableName + " = {";
+
+ lcbString += "&" + lnPrefix + ", ";
+
+ lcbString += "\"" + lcb.getName() + "\", ";
+
+ if (lcb.getDataSet() != null)
+ lcbString += "\"" + lcb.getDataSet() + "\", ";
+ else
+ lcbString += "NULL, ";
+
+ if (lcb.getLogName() != null)
+ lcbString += "\"" + lcb.getLogName() + "\", ";
+ else
+ lcbString += "NULL, ";
+
+ int triggerOps = 16;
+
+ if (lcb.getTriggerOptions() != null)
+ triggerOps = lcb.getTriggerOptions().getIntValue();
+
+ lcbString += triggerOps + ", ";
+
+ if (lcb.getIntgPd() != 0)
+ lcbString += lcb.getIntgPd() + ", ";
+ else
+ lcbString += "0, ";
+
+ if (lcb.isLogEna())
+ lcbString += "true, ";
+ else
+ lcbString += "false, ";
+
+ if (lcb.isReasonCode())
+ lcbString += "true, ";
+ else
+ lcbString += "false, ";
+
+ currentLcbVariableNumber++;
+
+ if (currentLcbVariableNumber < lcbVariableNames.size())
+ lcbString += "&" + lcbVariableNames.get(currentLcbVariableNumber);
+ else
+ lcbString += "NULL";
+
+ lcbString += "};\n";
+
+ this.logControlBlocks.append(lcbString);
+ }
+
+ private void printReportControlBlockInstance(String lnPrefix, ReportControlBlock rcb, String index, int reportNumber, int reportsCount)
+ {
String rcbVariableName = lnPrefix + "_report" + reportNumber;
String rcbString = "ReportControlBlock " + rcbVariableName + " = {";