diff --git a/src/iec61850/inc_private/logging.h b/src/iec61850/inc_private/logging.h index 70b36f8b..afa3084b 100644 --- a/src/iec61850/inc_private/logging.h +++ b/src/iec61850/inc_private/logging.h @@ -30,6 +30,13 @@ typedef struct { LogicalNode* parentLN; LogStorage logStorage; + + uint64_t newEntryId; + uint64_t newEntryTime; + + uint64_t oldEntryId; + uint64_t oldEntryTime; + } LogInstance; typedef struct { @@ -46,6 +53,11 @@ typedef struct { MmsValue* mmsValue; MmsVariableSpecification* mmsType; + MmsValue* oldEntr; + MmsValue* oldEntrTm; + MmsValue* newEntr; + MmsValue* newEntrTm; + LogInstance* logInstance; bool enabled; @@ -58,6 +70,12 @@ typedef struct { LogInstance* LogInstance_create(LogicalNode* parentLN, const char* name); +void +LogInstance_setLogStorage(LogInstance* self, LogStorage logStorage); + +void +LogInstance_logSingleData(LogInstance* self, const char* dataRef, MmsValue* value, uint8_t flag); + void LogInstance_destroy(LogInstance* self); diff --git a/src/iec61850/inc_private/mms_mapping.h b/src/iec61850/inc_private/mms_mapping.h index 24a74484..0a1bb5a2 100644 --- a/src/iec61850/inc_private/mms_mapping.h +++ b/src/iec61850/inc_private/mms_mapping.h @@ -147,6 +147,9 @@ MmsMapping_setIedServer(MmsMapping* self, IedServer iedServer); void MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicationHandler handler, void* parameter); +void +MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logStorage); + void MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter); diff --git a/src/iec61850/server/mms_mapping/logging.c b/src/iec61850/server/mms_mapping/logging.c index cdef07fe..905e0978 100644 --- a/src/iec61850/server/mms_mapping/logging.c +++ b/src/iec61850/server/mms_mapping/logging.c @@ -41,11 +41,15 @@ LogInstance_create(LogicalNode* parentLN, const char* name) { LogInstance* self = (LogInstance*) GLOBAL_MALLOC(sizeof(LogInstance)); - self->name = copyString(name); self->parentLN = parentLN; self->logStorage = NULL; + self->oldEntryId = 0; + self->oldEntryTime = 0; + self->newEntryId = 0; + self->newEntryTime = 0; + return self; } @@ -56,6 +60,49 @@ LogInstance_destroy(LogInstance* self) GLOBAL_FREEMEM(self); } +void +LogInstance_logSingleData(LogInstance* self, const char* dataRef, MmsValue* value, uint8_t flag) +{ + LogStorage logStorage = self->logStorage; + + if (logStorage != NULL) { + + printf("Log value - dataRef: %s flag: %i\n", dataRef, flag); + + uint64_t timestamp = Hal_getTimeInMs(); + + uint64_t entryID = LogStorage_addEntry(logStorage, timestamp); + + int dataSize = MmsValue_encodeMmsData(value, NULL, 0, false); + + uint8_t* data = GLOBAL_MALLOC(dataSize); + + MmsValue_encodeMmsData(value, data, 0, true); + + LogStorage_addEntryData(logStorage, entryID, dataRef, data, dataSize, flag); + + self->newEntryId = entryID; + self->newEntryTime = timestamp; + + } + else + printf("no log storage available!\n"); +} + +void +LogInstance_setLogStorage(LogInstance* self, LogStorage logStorage) +{ + self->logStorage = logStorage; + + LogStorage_getOldestAndNewestEntries(logStorage, &(self->newEntryId), &(self->newEntryTime), + &(self->oldEntryId), &(self->oldEntryTime)); + + printf("Attached storage to log: %s\n", self->name); + printf(" oldEntryID: %llu oldEntryTm: %llu\n", self->oldEntryId, self->oldEntryTime); + printf(" newEntryID: %llu newEntryTm: %llu\n", self->newEntryId, self->newEntryTime); + +} + LogControl* LogControl_create(LogicalNode* parentLN, MmsMapping* mmsMapping) { @@ -131,6 +178,20 @@ lookupLogControl(MmsMapping* self, MmsDomain* domain, char* lnName, char* object return NULL; } +static void +updateLogStatusInLCB(LogControl* self) +{ + LogInstance* logInstance = self->logInstance; + + if (logInstance != NULL) { + + MmsValue_setBinaryTime(self->oldEntrTm, logInstance->oldEntryTime); + MmsValue_setBinaryTime(self->newEntrTm, logInstance->newEntryTime); + + MmsValue_setOctetString(self->oldEntr, &(logInstance->oldEntryId), 8); + MmsValue_setOctetString(self->newEntr, &(logInstance->newEntryId), 8); + } +} MmsValue* @@ -138,6 +199,8 @@ LIBIEC61850_LOG_SVC_readAccessControlBlock(MmsMapping* self, MmsDomain* domain, { MmsValue* value = NULL; + printf("READ ACCESS LOG CB\n"); + char variableId[130]; strncpy(variableId, variableIdOrig, 129); @@ -164,6 +227,9 @@ LIBIEC61850_LOG_SVC_readAccessControlBlock(MmsMapping* self, MmsDomain* domain, LogControl* logControl = lookupLogControl(self, domain, lnName, objectName); if (logControl != NULL) { + + updateLogStatusInLCB(logControl); + if (varName != NULL) { value = MmsValue_getSubElement(logControl->mmsValue, logControl->mmsType, varName); } @@ -210,7 +276,13 @@ createTrgOps(LogControlBlock* reportControlBlock) { static bool enableLogging(LogControl* logControl) { - printf("enableLogging\n"); + printf("Enable LCB %s...\n", logControl->name); + + if (logControl->dataSetRef == NULL) { + printf(" no data set specified!\n"); + return false; + } + DataSet* dataSet = IedModel_lookupDataSet(logControl->mmsMapping->model, logControl->dataSetRef); if (dataSet == NULL) { @@ -220,11 +292,13 @@ enableLogging(LogControl* logControl) else logControl->dataSet = dataSet; + printf(" enabled\n"); + return true; } static MmsVariableSpecification* -createLogControlBlock(LogControlBlock* logControlBlock, +createLogControlBlock(MmsMapping* self, LogControlBlock* logControlBlock, LogControl* logControl) { MmsVariableSpecification* lcb = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); @@ -263,7 +337,14 @@ createLogControlBlock(LogControlBlock* logControlBlock, lcb->typeSpec.structure.elements[1] = namedVariable; if (logControlBlock->logRef != NULL) { - mmsValue->value.structure.components[1] = MmsValue_newVisibleString(logControlBlock->logRef); + char logRef[130]; + + int maxLogRefLength = 129 - strlen(self->model->name); + + strcpy(logRef, self->model->name); + strncat(logRef, logControlBlock->logRef, maxLogRefLength); + + mmsValue->value.structure.components[1] = MmsValue_newVisibleString(logRef); } else { char* logRef = createString(4, logControl->domain->domainName, "/", logControlBlock->parent->name, @@ -303,6 +384,8 @@ createLogControlBlock(LogControlBlock* logControlBlock, mmsValue->value.structure.components[3] = MmsValue_newBinaryTime(false); + logControl->oldEntrTm = mmsValue->value.structure.components[3]; + /* NewEntrTm */ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable->name = copyString("NewEntrTm"); @@ -312,6 +395,8 @@ createLogControlBlock(LogControlBlock* logControlBlock, mmsValue->value.structure.components[4] = MmsValue_newBinaryTime(false); + logControl->newEntrTm = mmsValue->value.structure.components[4]; + /* OldEntr */ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable->name = copyString("OldEntr"); @@ -322,6 +407,8 @@ createLogControlBlock(LogControlBlock* logControlBlock, mmsValue->value.structure.components[5] = MmsValue_newOctetString(8, 8); + logControl->oldEntr = mmsValue->value.structure.components[5]; + /* NewEntr */ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable->name = copyString("NewEntr"); @@ -332,6 +419,8 @@ createLogControlBlock(LogControlBlock* logControlBlock, mmsValue->value.structure.components[6] = MmsValue_newOctetString(8, 8); + logControl->newEntr = mmsValue->value.structure.components[6]; + /* TrgOps */ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable->name = copyString("TrgOps"); @@ -426,9 +515,13 @@ getLogInstanceByLogRef(MmsMapping* self, const char* logRef) return NULL; } +#if 0 static LogInstance* getLogInstance(MmsMapping* self, LogicalNode* logicalNode, const char* logName) { + if (logName == NULL) + return NULL; + LinkedList logInstance = LinkedList_getNext(self->logInstances); while (logInstance != NULL) { @@ -444,6 +537,7 @@ getLogInstance(MmsMapping* self, LogicalNode* logicalNode, const char* logName) return NULL; } +#endif MmsVariableSpecification* Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode, @@ -470,10 +564,13 @@ Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode logControl->domain = domain; namedVariable->typeSpec.structure.elements[currentLcb] = - createLogControlBlock(logControlBlock, logControl); + createLogControlBlock(self, logControlBlock, logControl); //getLogInstanceByLogRef(self, logControlBlock->logRef); - logControl->logInstance = getLogInstance(self, logicalNode, logControlBlock->logRef); + //logControl->logInstance = getLogInstance(self, logicalNode, logControlBlock->logRef); + + if (logControlBlock->logRef != NULL) + logControl->logInstance = getLogInstanceByLogRef(self, logControlBlock->logRef); LinkedList_add(self->logControls, logControl); @@ -489,7 +586,7 @@ MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logSto LogInstance* logInstance = getLogInstanceByLogRef(self, logRef); if (logInstance != NULL) - logInstance->logStorage = logStorage; + LogInstance_setLogStorage(logInstance, logStorage); //if (DEBUG_IED_SERVER) if (logInstance == NULL) diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index ae7d351e..32c159c3 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -1116,13 +1116,25 @@ createMmsDomainFromIedDevice(MmsMapping* self, LogicalDevice* logicalDevice) while (log != NULL) { - MmsDomain_addJournal(domain, log->name); + char journalName[65]; - printf("log->name: %s\n", log->name); + int nameLength = strlen(log->parent->name) + strlen(log->name); - LogInstance* logInstance = LogInstance_create(log->parent, log->name); + if (nameLength > 63) { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: Log name %s invalid! Resulting journal name too long! Skip log\n", log->name); + } + else { + strcpy(journalName, log->parent->name); + strcat(journalName, "$"); + strcat(journalName, log->name); - LinkedList_add(self->logInstances, (void*) logInstance); + MmsDomain_addJournal(domain, journalName); + + LogInstance* logInstance = LogInstance_create(log->parent, log->name); + + LinkedList_add(self->logInstances, (void*) logInstance); + } log = log->sibling; } @@ -2586,7 +2598,7 @@ DataSet_isMemberValue(DataSet* dataSet, MmsValue* value, int* index) #if (CONFIG_IEC61850_LOG_SERVICE == 1) static bool -DataSet_isMemberValueWithRef(DataSet* dataSet, MmsValue* value, char* dataRef) +DataSet_isMemberValueWithRef(DataSet* dataSet, MmsValue* value, char* dataRef, const char* iedName) { int i = 0; @@ -2599,7 +2611,7 @@ DataSet_isMemberValueWithRef(DataSet* dataSet, MmsValue* value, char* dataRef) if (dataSetValue != NULL) { /* prevent invalid data set members */ if (isMemberValueRecursive(dataSetValue, value)) { if (dataRef != NULL) - sprintf(dataRef, "%s/%s", dataSetEntry->logicalDeviceName, dataSetEntry->variableName); + sprintf(dataRef, "%s%s/%s", iedName, dataSetEntry->logicalDeviceName, dataSetEntry->variableName); return true; } @@ -2695,30 +2707,13 @@ MmsMapping_triggerLogging(MmsMapping* self, MmsValue* value, LogInclusionFlag fl char dataRef[130]; - if (DataSet_isMemberValueWithRef(lc->dataSet, value, dataRef)) { - printf("Log value - dataRef: %s flag: %i\n", dataRef, flag); - - //TODO log to logInstance + if (DataSet_isMemberValueWithRef(lc->dataSet, value, dataRef, self->model->name)) { if (lc->logInstance != NULL) { - - LogStorage logStorage = lc->logInstance->logStorage; - - if (logStorage != NULL) { - - uint64_t entryID = LogStorage_addEntry(logStorage, Hal_getTimeInMs()); - - int dataSize = MmsValue_encodeMmsData(value, NULL, 0, false); - - uint8_t* data = GLOBAL_MALLOC(dataSize); - - MmsValue_encodeMmsData(value, data, 0, true); - - LogStorage_addEntryData(logStorage, entryID, dataRef, data, dataSize, flag); - - - } + LogInstance_logSingleData(lc->logInstance, dataRef, value, flag); } + else + printf("No log instance available!\n"); } diff --git a/src/logging/logging_api.h b/src/logging/logging_api.h index 575e5900..0f3b36fd 100644 --- a/src/logging/logging_api.h +++ b/src/logging/logging_api.h @@ -58,6 +58,9 @@ struct sLogStorage { bool (*getEntriesAfter) (LogStorage self, uint64_t startingTime, uint64_t entryID); + bool (*getOldestAndNewestEntries) (LogStorage self, uint64_t* newEntry, uint64_t* newEntryTime, + uint64_t* oldEntry, uint64_t* oldEntryTime); + void (*destroy) (LogStorage self); }; @@ -78,6 +81,10 @@ LogStorage_getEntriesAfter(LogStorage self, uint64_t startingTime, uint64_t entr void LogStorage_setCallbacks(LogStorage self, LogEntryCallback entryCallback, LogEntryDataCallback entryDataCallback, void* callbackParameter); +bool +LogStorage_getOldestAndNewestEntries(LogStorage self, uint64_t* newEntry, uint64_t* newEntryTime, + uint64_t* oldEntry, uint64_t* oldEntryTime); + void LogStorage_destroy(LogStorage self); diff --git a/src/mms/inc/mms_device_model.h b/src/mms/inc/mms_device_model.h index b2290ab4..404b8c8a 100644 --- a/src/mms/inc/mms_device_model.h +++ b/src/mms/inc/mms_device_model.h @@ -91,6 +91,9 @@ MmsDomain_getName(MmsDomain* self); void MmsDomain_addJournal(MmsDomain* self, const char* name); +MmsJournal +MmsDomain_getJournal(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 6f406422..f8db8aed 100644 --- a/src/mms/iso_mms/server/mms_domain.c +++ b/src/mms/iso_mms/server/mms_domain.c @@ -84,6 +84,24 @@ MmsDomain_addJournal(MmsDomain* self, const char* name) LinkedList_add(self->journals, (void*) journal); } +MmsJournal +MmsDomain_getJournal(MmsDomain* self, const char* name) +{ + LinkedList journal = LinkedList_getNext(self->journals); + + while (journal != NULL) { + + MmsJournal mmsJournal = (MmsJournal) LinkedList_getData(journal); + + if (strcmp(mmsJournal->name, name) == 0) + return mmsJournal; + + journal = LinkedList_getNext(journal); + } + + return NULL; +} + bool MmsDomain_addNamedVariableList(MmsDomain* self, MmsNamedVariableList variableList) { diff --git a/src/mms/iso_mms/server/mms_journal_service.c b/src/mms/iso_mms/server/mms_journal_service.c index 8b8843c2..e0a2a4e5 100644 --- a/src/mms/iso_mms/server/mms_journal_service.c +++ b/src/mms/iso_mms/server/mms_journal_service.c @@ -27,6 +27,90 @@ #if (MMS_JOURNAL_SERVICE == 1) + +typedef struct sJournalVariable* JournalVariable; + +struct sJournalVariable { + char* tag; /* UTF8(1..255) */ + int tagSize; + + uint8_t* data; + int dataSize; + + JournalVariable next; +}; + +typedef struct { + uint8_t* entryID; + int entryIDSize; + + uint64_t timestamp; + + JournalVariable listOfVariables; +} JournalEntry; + + +struct sJournalEncoder { + uint8_t* buffer; + int maxSize; + int bufPos; + int currentEntryBufPos; /* store start buffer position of current entry in case the whole JournalEntry will become too long */ + +}; + +static bool +entryCallback(void* parameter, uint64_t timestamp, uint64_t entryID, bool moreFollow) +{ + if (moreFollow) + printf("Found entry ID:%llu timestamp:%llu\n", entryID, timestamp); + + return true; +} + +static bool +entryDataCallback (void* parameter, const char* dataRef, uint8_t* data, int dataSize, uint8_t reasonCode, bool moreFollow) +{ + if (moreFollow) { + printf(" EntryData: ref: %s\n", dataRef); + + MmsValue* value = MmsValue_decodeMmsData(data, 0, dataSize); + + char buffer[256]; + + MmsValue_printToBuffer(value, buffer, 256); + + printf(" value: %s\n", buffer); + } + + return true; +} + + +bool +MmsJournal_queryJournalByRange(MmsJournal self, uint64_t startTime, uint64_t endTime, ByteBuffer* response) +{ + // forward request to implementation class + + //TODO get handle of LogStorage + + struct sJournalEncoder encoderData; + + LogStorage logStorage; + + LogStorage_setCallbacks(logStorage, entryCallback, entryDataCallback, &encoderData); + + LogStorage_getEntries(logStorage, startTime, endTime); + + /* actual encoding will happen in callback handler. When getEntries returns the data is + * already encoded in the buffer. + */ + + // encoder header in response buffer + + // move encoded JournalEntry data to continue the buffer header +} + + static bool parseStringWithMaxLength(char* filename, int maxLength, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response) { @@ -268,6 +352,30 @@ mmsServer_handleReadJournalRequest( } //TODO check if required fields are present + //TODO check valid field combinations + + /* lookup journal */ + MmsServer server = connection->server; + + MmsDevice* mmsDevice = MmsServer_getDevice(connection->server); + + MmsDomain* mmsDomain = MmsDevice_getDomain(mmsDevice, domainId); + + if (mmsDomain == NULL) { + printf("Domain %s not found\n", domainId); + mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); + return; + } + + MmsJournal mmsJournal = MmsDomain_getJournal(mmsDomain, logName); + + if (mmsJournal == NULL) { + printf("Journal %s not found\n", logName); + mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); + return; + } + + printf("Read journal %s ...\n", mmsJournal->name); } #endif /* (MMS_JOURNAL_SERVICE == 1) */ diff --git a/tools/model_generator/genmodel.jar b/tools/model_generator/genmodel.jar index 3c50d337..89a9b09a 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 82cd3576..9960ee53 100644 --- a/tools/model_generator/src/com/libiec61850/scl/model/LogControl.java +++ b/tools/model_generator/src/com/libiec61850/scl/model/LogControl.java @@ -34,6 +34,7 @@ public class LogControl { private String ldInst = null; private String prefix = ""; private String lnClass = "LLN0"; + private String lnInst = ""; private String logName; private boolean logEna = true; private boolean reasonCode = true; @@ -49,6 +50,10 @@ public class LogControl { desc = ParserUtils.parseAttribute(logControlNode, "desc"); dataSet = ParserUtils.parseAttribute(logControlNode, "datSet"); + if (dataSet != null) + if (dataSet.equals("")) + dataSet = null; + ldInst = ParserUtils.parseAttribute(logControlNode, "ldInst"); prefix = ParserUtils.parseAttribute(logControlNode, "prefix"); @@ -57,11 +62,19 @@ public class LogControl { if (lnClassString != null) lnClass = lnClassString; + String lnInstString = ParserUtils.parseAttribute(logControlNode, "lnInst"); + + if (lnInstString != null) + lnInst = lnInstString; + logName = ParserUtils.parseAttribute(logControlNode, "logName"); if (logName == null) throw new SclParserException(logControlNode, "LogControl is missing required attribute \"logName\""); + if (logName.equals("")) + logName = null; + String intgPdString = ParserUtils.parseAttribute(logControlNode, "intgPd"); if (intgPdString != null) diff --git a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java index fca09171..bd40376a 100644 --- a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java +++ b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java @@ -321,7 +321,7 @@ public class StaticModelGenerator { cOut.println(" (ModelNode*) &" + firstChildName); cOut.println("};\n"); - printLogicalNodeDefinitions(ldName, logicalDevice.getLogicalNodes()); + printLogicalNodeDefinitions(ldName, logicalDevice, logicalDevice.getLogicalNodes()); } @@ -541,7 +541,7 @@ public class StaticModelGenerator { } } - private void printLogicalNodeDefinitions(String ldName, List logicalNodes) { + private void printLogicalNodeDefinitions(String ldName, LogicalDevice logicalDevice, List logicalNodes) { for (int i = 0; i < logicalNodes.size(); i++) { LogicalNode logicalNode = logicalNodes.get(i); @@ -568,7 +568,7 @@ public class StaticModelGenerator { printReportControlBlocks(lnName, logicalNode); - printLogControlBlocks(lnName, logicalNode); + printLogControlBlocks(ldName, lnName, logicalNode, logicalDevice); printLogs(lnName, logicalNode); @@ -1077,7 +1077,7 @@ public class StaticModelGenerator { } } - private void printLogControlBlocks(String lnPrefix, LogicalNode logicalNode) + private void printLogControlBlocks(String ldName, String lnPrefix, LogicalNode logicalNode, LogicalDevice logicalDevice) { List logControlBlocks = logicalNode.getLogControlBlocks(); @@ -1086,7 +1086,7 @@ public class StaticModelGenerator { int lcbNumber = 0; for (LogControl lcb : logControlBlocks) { - printLogControlBlock(lnPrefix, lcb, lcbNumber, lcbCount); + printLogControlBlock(logicalDevice, lnPrefix, lcb, lcbNumber, lcbCount); lcbNumber++; } } @@ -1157,7 +1157,7 @@ public class StaticModelGenerator { this.logs.append(logString); } - private void printLogControlBlock(String lnPrefix, LogControl lcb, int lcbNumber, int lcbCount) + private void printLogControlBlock(LogicalDevice logicalDevice, String lnPrefix, LogControl lcb, int lcbNumber, int lcbCount) { String lcbVariableName = lnPrefix + "_lcb" + lcbNumber; @@ -1172,8 +1172,21 @@ public class StaticModelGenerator { else lcbString += "NULL, "; + + String logRef; + + if (lcb.getLdInst() == null) + logRef = logicalDevice.getInst() + "/"; + else + logRef = lcb.getLdInst() + "/"; + + if (lcb.getLnClass().equals("LLN0")) + logRef += "LLN0$"; + else + logRef += lcb.getLnClass() + "$"; + if (lcb.getLogName() != null) - lcbString += "\"" + lcb.getLogName() + "\", "; + lcbString += "\"" + logRef + lcb.getLogName() + "\", "; else lcbString += "NULL, ";