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 + " = {";