- extended logging implementation
This commit is contained in:
parent
2d45c2d679
commit
a23b584d13
15 changed files with 460 additions and 92 deletions
2
Makefile
2
Makefile
|
@ -59,6 +59,7 @@ LIB_INCLUDE_DIRS += src/goose
|
|||
LIB_INCLUDE_DIRS += src/sampled_values
|
||||
LIB_INCLUDE_DIRS += src/iec61850/inc
|
||||
LIB_INCLUDE_DIRS += src/iec61850/inc_private
|
||||
LIB_INCLUDE_DIRS += src/logging
|
||||
ifeq ($(HAL_IMPL), WIN32)
|
||||
LIB_INCLUDE_DIRS += third_party/winpcap/Include
|
||||
endif
|
||||
|
@ -100,6 +101,7 @@ LIB_API_HEADER_FILES += src/goose/goose_receiver.h
|
|||
LIB_API_HEADER_FILES += src/goose/goose_publisher.h
|
||||
LIB_API_HEADER_FILES += src/sampled_values/sv_subscriber.h
|
||||
LIB_API_HEADER_FILES += src/sampled_values/sv_publisher.h
|
||||
LIB_API_HEADER_FILES += src/logging/logging_api.h
|
||||
|
||||
get_sources_from_directory = $(wildcard $1/*.c)
|
||||
get_sources = $(foreach dir, $1, $(call get_sources_from_directory,$(dir)))
|
||||
|
|
|
@ -172,7 +172,7 @@ int main(int argc, char** argv) {
|
|||
printf(" read journal...\n");
|
||||
// MmsConnection_readJournal(con, &error, domainName, name);
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
uint64_t timestamp = Hal_getTimeInMs();
|
||||
|
||||
MmsValue* startTime = MmsValue_newBinaryTime(false);
|
||||
|
@ -184,7 +184,7 @@ int main(int argc, char** argv) {
|
|||
MmsConnection_readJournalTimeRange(con, &error, domainName, name, startTime, endTime);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
uint64_t timestamp = Hal_getTimeInMs();
|
||||
|
||||
MmsValue* startTime = MmsValue_newBinaryTime(false);
|
||||
|
|
|
@ -8,3 +8,4 @@ INCLUDES += -I$(LIBIEC_HOME)/src/iec61850/inc_private
|
|||
INCLUDES += -I$(LIBIEC_HOME)/src/hal/inc
|
||||
INCLUDES += -I$(LIBIEC_HOME)/src/goose
|
||||
INCLUDES += -I$(LIBIEC_HOME)/src/sampled_values
|
||||
INCLUDES += -I$(LIBIEC_HOME)/src/logging
|
||||
|
|
|
@ -30,6 +30,7 @@ extern "C" {
|
|||
|
||||
|
||||
#include "libiec61850_common_api.h"
|
||||
#include "logging_api.h"
|
||||
|
||||
/**
|
||||
* @defgroup iec61850_common_api_group IEC 61850 API common parts
|
||||
|
|
|
@ -517,6 +517,9 @@ LogicalNode_hasUnbufferedReports(LogicalNode* node);
|
|||
DataSet*
|
||||
LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName);
|
||||
|
||||
void
|
||||
LogicalNode_setLogStorage(LogicalNode* self, const char* logName, LogStorage logStorage);
|
||||
|
||||
bool
|
||||
DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc);
|
||||
|
||||
|
|
|
@ -650,6 +650,9 @@ IedServer_updateQuality(IedServer self, DataAttribute* dataAttribute, Quality qu
|
|||
/**@}*/
|
||||
|
||||
|
||||
void
|
||||
IedServer_setLogStorage(IedServer self, const char* logRef, LogStorage logStorage);
|
||||
|
||||
/**
|
||||
* @defgroup IEC61850_SERVER_SETTING_GROUPS Server side setting group handling
|
||||
*
|
||||
|
|
|
@ -25,6 +25,13 @@
|
|||
#ifndef LIBIEC61850_SRC_IEC61850_INC_PRIVATE_LOGGING_H_
|
||||
#define LIBIEC61850_SRC_IEC61850_INC_PRIVATE_LOGGING_H_
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
LogicalNode* parentLN;
|
||||
|
||||
LogStorage logStorage;
|
||||
} LogInstance;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
LogControlBlock* logControlBlock;
|
||||
|
@ -39,6 +46,7 @@ typedef struct {
|
|||
MmsValue* mmsValue;
|
||||
MmsVariableSpecification* mmsType;
|
||||
|
||||
LogInstance* logInstance;
|
||||
|
||||
bool enabled;
|
||||
|
||||
|
@ -46,12 +54,22 @@ typedef struct {
|
|||
|
||||
} LogControl;
|
||||
|
||||
|
||||
LogInstance*
|
||||
LogInstance_create(LogicalNode* parentLN, const char* name);
|
||||
|
||||
void
|
||||
LogInstance_destroy(LogInstance* self);
|
||||
|
||||
LogControl*
|
||||
LogControl_create(LogicalNode* parentLN, MmsMapping* mmsMapping);
|
||||
|
||||
void
|
||||
LogControl_destroy(LogControl* self);
|
||||
|
||||
void
|
||||
LogControl_setLogStorage(LogControl* self, LogStorage logStorage);
|
||||
|
||||
MmsVariableSpecification*
|
||||
Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode,
|
||||
int lcbCount);
|
||||
|
|
|
@ -37,6 +37,7 @@ struct sMmsMapping {
|
|||
|
||||
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
||||
LinkedList logControls;
|
||||
LinkedList logInstances;
|
||||
#endif
|
||||
|
||||
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
|
||||
|
|
|
@ -1244,6 +1244,14 @@ IedServer_setEditSettingGroupConfirmationHandler(IedServer self, SettingGroupCon
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
IedServer_setLogStorage(IedServer self, const char* logRef, LogStorage logStorage)
|
||||
{
|
||||
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
||||
MmsMapping_setLogStorage(self->mmsMapping, logRef, logStorage);
|
||||
#endif
|
||||
}
|
||||
|
||||
ClientConnection
|
||||
private_IedServer_getClientConnectionByHandle(IedServer self, void* serverConnectionHandle)
|
||||
{
|
||||
|
|
|
@ -36,6 +36,26 @@
|
|||
#include "mms_value_internal.h"
|
||||
|
||||
|
||||
LogInstance*
|
||||
LogInstance_create(LogicalNode* parentLN, const char* name)
|
||||
{
|
||||
LogInstance* self = (LogInstance*) GLOBAL_MALLOC(sizeof(LogInstance));
|
||||
|
||||
|
||||
self->name = copyString(name);
|
||||
self->parentLN = parentLN;
|
||||
self->logStorage = NULL;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
LogInstance_destroy(LogInstance* self)
|
||||
{
|
||||
GLOBAL_FREEMEM(self->name);
|
||||
GLOBAL_FREEMEM(self);
|
||||
}
|
||||
|
||||
LogControl*
|
||||
LogControl_create(LogicalNode* parentLN, MmsMapping* mmsMapping)
|
||||
{
|
||||
|
@ -47,6 +67,7 @@ LogControl_create(LogicalNode* parentLN, MmsMapping* mmsMapping)
|
|||
self->logicalNode = parentLN;
|
||||
self->mmsMapping = mmsMapping;
|
||||
self->dataSetRef = NULL;
|
||||
self->logInstance = NULL;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -59,6 +80,12 @@ LogControl_destroy(LogControl* self)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogControl_setLog(LogControl* self, LogInstance* logInstance)
|
||||
{
|
||||
self->logInstance = logInstance;
|
||||
}
|
||||
|
||||
static LogControlBlock*
|
||||
getLCBForLogicalNodeWithIndex(MmsMapping* self, LogicalNode* logicalNode, int index)
|
||||
{
|
||||
|
@ -337,7 +364,86 @@ createLogControlBlock(LogControlBlock* logControlBlock,
|
|||
return lcb;
|
||||
}
|
||||
|
||||
static LogInstance*
|
||||
getLogInstanceByLogRef(MmsMapping* self, const char* logRef)
|
||||
{
|
||||
char refStr[130];
|
||||
char* domainName;
|
||||
char* lnName;
|
||||
char* logName;
|
||||
|
||||
strncpy(refStr, logRef, 129);
|
||||
|
||||
printf("getLogInst... %s\n", refStr);
|
||||
|
||||
domainName = refStr;
|
||||
|
||||
lnName = strchr(refStr, '/');
|
||||
|
||||
if (lnName == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((lnName - domainName) > 64)
|
||||
return NULL;
|
||||
|
||||
lnName[0] = 0;
|
||||
lnName++;
|
||||
|
||||
logName = strchr(lnName, '$');
|
||||
|
||||
if (logName == NULL)
|
||||
return NULL;
|
||||
|
||||
logName[0] = 0;
|
||||
logName++;
|
||||
|
||||
printf("LOG: dn: %s ln: %s name: %s\n", domainName, lnName, logName);
|
||||
|
||||
LinkedList instance = LinkedList_getNext(self->logInstances);
|
||||
|
||||
while (instance != NULL) {
|
||||
|
||||
LogInstance* logInstance = LinkedList_getData(instance);
|
||||
|
||||
printf("logInstance: %s\n", logInstance->name);
|
||||
|
||||
if (strcmp(logInstance->name, logName) == 0) {
|
||||
printf (" lnName: %s\n", logInstance->parentLN->name);
|
||||
|
||||
if (strcmp(lnName, logInstance->parentLN->name) == 0) {
|
||||
LogicalDevice* ld = (LogicalDevice*) logInstance->parentLN->parent;
|
||||
|
||||
printf(" ldName: %s\n", ld->name);
|
||||
|
||||
if (strcmp(ld->name, domainName) == 0)
|
||||
return logInstance;
|
||||
}
|
||||
}
|
||||
|
||||
instance = LinkedList_getNext(instance);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LogInstance*
|
||||
getLogInstance(MmsMapping* self, LogicalNode* logicalNode, const char* logName)
|
||||
{
|
||||
LinkedList logInstance = LinkedList_getNext(self->logInstances);
|
||||
|
||||
while (logInstance != NULL) {
|
||||
LogInstance* instance = (LogInstance*) LinkedList_getData(logInstance);
|
||||
|
||||
printf("LOG: %s (%s)\n", instance->name, logName);
|
||||
|
||||
if ((strcmp(instance->name, logName) == 0) && (logicalNode == instance->parentLN))
|
||||
return instance;
|
||||
|
||||
logInstance = LinkedList_getNext(logInstance);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MmsVariableSpecification*
|
||||
Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode,
|
||||
|
@ -366,6 +472,9 @@ Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode
|
|||
namedVariable->typeSpec.structure.elements[currentLcb] =
|
||||
createLogControlBlock(logControlBlock, logControl);
|
||||
|
||||
//getLogInstanceByLogRef(self, logControlBlock->logRef);
|
||||
logControl->logInstance = getLogInstance(self, logicalNode, logControlBlock->logRef);
|
||||
|
||||
LinkedList_add(self->logControls, logControl);
|
||||
|
||||
currentLcb++;
|
||||
|
@ -374,4 +483,15 @@ Logging_createLCBs(MmsMapping* self, MmsDomain* domain, LogicalNode* logicalNode
|
|||
return namedVariable;
|
||||
}
|
||||
|
||||
void
|
||||
MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logStorage)
|
||||
{
|
||||
LogInstance* logInstance = getLogInstanceByLogRef(self, logRef);
|
||||
|
||||
if (logInstance != NULL)
|
||||
logInstance->logStorage = logStorage;
|
||||
|
||||
//if (DEBUG_IED_SERVER)
|
||||
if (logInstance == NULL)
|
||||
printf("IED_SERVER: MmsMapping_setLogStorage no matching log for %s found!\n", logRef);
|
||||
}
|
||||
|
|
|
@ -1118,6 +1118,12 @@ createMmsDomainFromIedDevice(MmsMapping* self, LogicalDevice* logicalDevice)
|
|||
|
||||
MmsDomain_addJournal(domain, log->name);
|
||||
|
||||
printf("log->name: %s\n", log->name);
|
||||
|
||||
LogInstance* logInstance = LogInstance_create(log->parent, log->name);
|
||||
|
||||
LinkedList_add(self->logInstances, (void*) logInstance);
|
||||
|
||||
log = log->sibling;
|
||||
}
|
||||
#endif /* (CONFIG_IEC61850_LOG_SERVICE == 1) */
|
||||
|
@ -1248,6 +1254,7 @@ MmsMapping_create(IedModel* model)
|
|||
|
||||
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
||||
self->logControls = LinkedList_create();
|
||||
self->logInstances = LinkedList_create();
|
||||
#endif
|
||||
|
||||
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
|
||||
|
@ -1311,6 +1318,11 @@ MmsMapping_destroy(MmsMapping* self)
|
|||
LinkedList_destroy(self->settingGroups);
|
||||
#endif
|
||||
|
||||
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
||||
LinkedList_destroyDeep(self->logControls, (LinkedListValueDeleteFunction) LogControl_destroy);
|
||||
LinkedList_destroyDeep(self->logInstances, (LinkedListValueDeleteFunction) LogInstance_destroy);
|
||||
#endif
|
||||
|
||||
LinkedList_destroy(self->observedObjects);
|
||||
|
||||
LinkedList_destroy(self->attributeAccessHandlers);
|
||||
|
@ -2512,7 +2524,7 @@ MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicat
|
|||
self->connectionIndicationHandlerParameter = parameter;
|
||||
}
|
||||
|
||||
#if ((CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1))
|
||||
|
||||
|
||||
static bool
|
||||
isMemberValueRecursive(MmsValue* container, MmsValue* value)
|
||||
|
@ -2540,6 +2552,8 @@ isMemberValueRecursive(MmsValue* container, MmsValue* value)
|
|||
return isMemberValue;
|
||||
}
|
||||
|
||||
#if ((CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT == 1))
|
||||
|
||||
static bool
|
||||
DataSet_isMemberValue(DataSet* dataSet, MmsValue* value, int* index)
|
||||
{
|
||||
|
@ -2569,6 +2583,38 @@ DataSet_isMemberValue(DataSet* dataSet, MmsValue* value, int* index)
|
|||
}
|
||||
#endif /* ((CONFIG_IEC61850_REPORT_SERVICE == 1) || (CONFIG_INCLUDE_GOOSE_SUPPORT)) */
|
||||
|
||||
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
||||
|
||||
static bool
|
||||
DataSet_isMemberValueWithRef(DataSet* dataSet, MmsValue* value, char* dataRef)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
DataSetEntry* dataSetEntry = dataSet->fcdas;
|
||||
|
||||
while (dataSetEntry != NULL) {
|
||||
|
||||
MmsValue* dataSetValue = dataSetEntry->value;
|
||||
|
||||
if (dataSetValue != NULL) { /* prevent invalid data set members */
|
||||
if (isMemberValueRecursive(dataSetValue, value)) {
|
||||
if (dataRef != NULL)
|
||||
sprintf(dataRef, "%s/%s", dataSetEntry->logicalDeviceName, dataSetEntry->variableName);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
dataSetEntry = dataSetEntry->sibling;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* (CONFIG_IEC61850_LOG_SERVICE == 1) */
|
||||
|
||||
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
|
||||
void
|
||||
MmsMapping_triggerReportObservers(MmsMapping* self, MmsValue* value, ReportInclusionFlag flag)
|
||||
|
@ -2622,9 +2668,6 @@ MmsMapping_triggerLogging(MmsMapping* self, MmsValue* value, LogInclusionFlag fl
|
|||
|
||||
if ((lc->enabled) && (lc->dataSet != NULL)) {
|
||||
|
||||
|
||||
int index;
|
||||
|
||||
switch (flag) {
|
||||
|
||||
case LOG_CONTROL_VALUE_UPDATE:
|
||||
|
@ -2650,8 +2693,32 @@ MmsMapping_triggerLogging(MmsMapping* self, MmsValue* value, LogInclusionFlag fl
|
|||
continue;
|
||||
}
|
||||
|
||||
if (DataSet_isMemberValue(lc->dataSet, value, &index)) {
|
||||
printf("Log value - flag:%i\n", flag);
|
||||
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 (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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc)
|
|||
DataSet*
|
||||
LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName)
|
||||
{
|
||||
assert(self->modelType == LogicalNodeModelType);
|
||||
assert(self->modelType == LogicalNodeModelType);
|
||||
assert(dataSetName != NULL);
|
||||
|
||||
char dsName[66];
|
||||
|
@ -409,6 +409,20 @@ exit_error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LogicalNode_setLogStorage(LogicalNode* self, const char* logName, LogStorage logStorage)
|
||||
{
|
||||
assert(self->modelType == LogicalNodeModelType);
|
||||
assert(logName != NULL);
|
||||
|
||||
LogicalDevice* ld = (LogicalDevice*) self->parent;
|
||||
|
||||
IedModel* iedModel = (IedModel*) ld->parent;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice)
|
||||
{
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* log_storage_sqlite.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "logging_api.h"
|
||||
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_initializeLog(const char* logName, int logSize);
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_storeEntry(const char* logName, uint64_t entryID, MmsValue* timestamp,
|
||||
int entrySize, uint8_t* entryData);
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_getEntries(const char* logName, MmsValue* timestamp,
|
||||
LogEntryCallback callback, void* parameter);
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_getEntriesAfter(const char* logName, MmsValue* timestamp, uint64_t entryID,
|
||||
LogEntryCallback callback, void* parameter);
|
||||
|
||||
static struct sLogStorage logStorageInstance = {
|
||||
SqLiteLogStorage_initializeLog,
|
||||
SqLiteLogStorage_storeEntry,
|
||||
SqLiteLogStorage_getEntries,
|
||||
SqLiteLogStorage_getEntriesAfter
|
||||
};
|
||||
|
||||
LogStorage
|
||||
SqLiteStorage_createInstance()
|
||||
{
|
||||
return &logStorageInstance;
|
||||
}
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_initializeLog(const char* logName, int logSize)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_storeEntry(const char* logName, uint64_t entryID, MmsValue* timestamp,
|
||||
int entrySize, uint8_t* entryData)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_getEntries(const char* logName, MmsValue* timestamp,
|
||||
LogEntryCallback callback, void* parameter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SqLiteLogStorage_getEntriesAfter(const char* logName, MmsValue* timestamp, uint64_t entryID,
|
||||
LogEntryCallback callback, void* parameter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,24 @@
|
|||
/*
|
||||
* logging_api.h
|
||||
* logging_api.h
|
||||
*
|
||||
* Copyright 2016 Michael Zillgith
|
||||
*
|
||||
* This file is part of libIEC61850.
|
||||
*
|
||||
* libIEC61850 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libIEC61850 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* See COPYING file for the complete license text.
|
||||
*/
|
||||
|
||||
#ifndef LIBIEC61850_SRC_LOGGING_LOGGING_API_H_
|
||||
|
@ -8,24 +26,59 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "mms_value.h"
|
||||
|
||||
typedef struct sLogStorage* LogStorage;
|
||||
|
||||
typedef void (*LogEntryCallback) (void* parameter, MmsValue* timestamp, uint64_t entryID, int entrySize,
|
||||
uint8_t* entryData);
|
||||
/**
|
||||
*
|
||||
* \param moreFollow - more data will follow - if false, the data is not valid
|
||||
*
|
||||
* \return true ready to receive new data, false abort operation
|
||||
*/
|
||||
typedef bool (*LogEntryCallback) (void* parameter, uint64_t timestamp, uint64_t entryID, bool moreFollow);
|
||||
|
||||
typedef bool (*LogEntryDataCallback) (void* parameter, const char* dataRef, uint8_t* data, int dataSize, uint8_t reasonCode, bool moreFollow);
|
||||
|
||||
struct sLogStorage {
|
||||
bool (*initializeLog) (const char* logName, int logSize);
|
||||
|
||||
bool (*storeEntry) (const char* logName, uint64_t entryID, MmsValue* timestamp, int entrySize,
|
||||
uint8_t* entryData);
|
||||
void* instanceData;
|
||||
|
||||
bool (*getEntries) (const char* logName, MmsValue* timestamp,
|
||||
LogEntryCallback callback, void* parameter);
|
||||
LogEntryCallback entryCallback;
|
||||
LogEntryDataCallback entryDataCallback;
|
||||
|
||||
bool (*getEntriesAfter) (const char* logName, MmsValue* timestamp, uint64_t entryID,
|
||||
LogEntryCallback callback, void* parameter);
|
||||
void* callbackParameter;
|
||||
|
||||
// bool (*initializeLog) (const char* logName, int logSize);
|
||||
|
||||
uint64_t (*addEntry) (LogStorage self, uint64_t timestamp);
|
||||
|
||||
bool (*addEntryData) (LogStorage self, uint64_t entryID, const char* dataRef, uint8_t* data, int dataSize, uint8_t reasonCode);
|
||||
|
||||
bool (*getEntries) (LogStorage self, uint64_t startingTime, uint64_t endingTime);
|
||||
|
||||
bool (*getEntriesAfter) (LogStorage self, uint64_t startingTime, uint64_t entryID);
|
||||
|
||||
void (*destroy) (LogStorage self);
|
||||
};
|
||||
|
||||
|
||||
|
||||
uint64_t
|
||||
LogStorage_addEntry(LogStorage self, uint64_t timestamp);
|
||||
|
||||
bool
|
||||
LogStorage_addEntryData(LogStorage self, uint64_t entryID, const char* dataRef, uint8_t* data, int dataSize, uint8_t reasonCode);
|
||||
|
||||
bool
|
||||
LogStorage_getEntries(LogStorage self, uint64_t startingTime, uint64_t endingTime);
|
||||
|
||||
bool
|
||||
LogStorage_getEntriesAfter(LogStorage self, uint64_t startingTime, uint64_t entryID);
|
||||
|
||||
void
|
||||
LogStorage_setCallbacks(LogStorage self, LogEntryCallback entryCallback, LogEntryDataCallback entryDataCallback, void* callbackParameter);
|
||||
|
||||
void
|
||||
LogStorage_destroy(LogStorage self);
|
||||
|
||||
#endif /* LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "libiec61850_platform_includes.h"
|
||||
#include "mms_server_internal.h"
|
||||
#include "mms_value_internal.h"
|
||||
|
||||
#if (MMS_JOURNAL_SERVICE == 1)
|
||||
|
||||
|
@ -69,8 +70,21 @@ mmsServer_handleReadJournalRequest(
|
|||
|
||||
char domainId[65];
|
||||
char logName[65];
|
||||
char entryIdBuf[64]; /* maximum size of entry id is 64 bytes! */
|
||||
|
||||
MmsValue entrySpec;
|
||||
entrySpec.type = MMS_OCTET_STRING;
|
||||
entrySpec.value.octetString.buf = entryIdBuf;
|
||||
entrySpec.value.octetString.maxSize = 64;
|
||||
|
||||
MmsValue rangeStart;
|
||||
MmsValue rangeStop;
|
||||
|
||||
bool hasNames = false;
|
||||
bool hasRangeStartSpec = false;
|
||||
bool hasRangeStopSpec = false;
|
||||
bool hasTimeSpec = false;
|
||||
bool hasEntrySpec = false;
|
||||
|
||||
while (bufPos < maxBufPos) {
|
||||
uint8_t tag = requestBuffer[bufPos++];
|
||||
|
@ -85,7 +99,7 @@ mmsServer_handleReadJournalRequest(
|
|||
|
||||
switch (tag) {
|
||||
|
||||
case 0xa0:
|
||||
case 0xa0: /* journalName */
|
||||
{
|
||||
|
||||
uint8_t objectIdTag = requestBuffer[bufPos++];
|
||||
|
@ -93,7 +107,7 @@ mmsServer_handleReadJournalRequest(
|
|||
|
||||
switch (objectIdTag) {
|
||||
case 0xa1: /* domain-specific */
|
||||
printf(" domain-specific-log\n");
|
||||
printf("domain-specific-log \n");
|
||||
|
||||
if (!parseStringWithMaxLength(domainId, 64, requestBuffer, &bufPos, bufPos + length, invokeId, response)) {
|
||||
return;
|
||||
|
@ -105,8 +119,9 @@ mmsServer_handleReadJournalRequest(
|
|||
|
||||
printf(" domain: %s log: %s\n", domainId, logName);
|
||||
|
||||
break;
|
||||
hasNames = true;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_MODIFIER, response);
|
||||
|
@ -117,13 +132,142 @@ mmsServer_handleReadJournalRequest(
|
|||
|
||||
break;
|
||||
|
||||
case 0xa1: /* rangeStartSpecification */
|
||||
{
|
||||
uint8_t subTag = requestBuffer[bufPos++];
|
||||
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
|
||||
|
||||
if (subTag != 0x80) {
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_MODIFIER, response);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((length == 4) || (length == 6)) {
|
||||
|
||||
rangeStart.type = MMS_BINARY_TIME;
|
||||
rangeStart.value.binaryTime.size = length;
|
||||
|
||||
memcpy(rangeStart.value.binaryTime.buf, requestBuffer + bufPos, length);
|
||||
|
||||
char stringBuf[100];
|
||||
MmsValue_printToBuffer(&rangeStart, stringBuf, 100);
|
||||
|
||||
printf("rangeStartSpec: %s\n", stringBuf);
|
||||
|
||||
hasRangeStartSpec = true;
|
||||
}
|
||||
else {
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
|
||||
return;
|
||||
}
|
||||
|
||||
bufPos += length;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0xa2: /* rangeStopSpecification */
|
||||
{
|
||||
uint8_t subTag = requestBuffer[bufPos++];
|
||||
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
|
||||
|
||||
if (subTag != 0x80) {
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_MODIFIER, response);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((length == 4) || (length == 6)) {
|
||||
rangeStop.type = MMS_BINARY_TIME;
|
||||
rangeStop.value.binaryTime.size = length;
|
||||
|
||||
memcpy(rangeStop.value.binaryTime.buf, requestBuffer + bufPos, length);
|
||||
|
||||
char stringBuf[100];
|
||||
MmsValue_printToBuffer(&rangeStop, stringBuf, 100);
|
||||
|
||||
printf("rangeStopSpec: %s\n", stringBuf);
|
||||
|
||||
hasRangeStopSpec = true;
|
||||
}
|
||||
else {
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
|
||||
return;
|
||||
}
|
||||
|
||||
bufPos += length;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0xa5: /* entryToStartAfter */
|
||||
{
|
||||
printf("entryToStartAfter\n");
|
||||
int maxSubBufPos = bufPos + length;
|
||||
|
||||
while (bufPos < maxSubBufPos) {
|
||||
uint8_t subTag = requestBuffer[bufPos++];
|
||||
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
|
||||
|
||||
switch (subTag) {
|
||||
case 0x80: /* timeSpecification */
|
||||
|
||||
if ((length == 4) || (length == 6)) {
|
||||
rangeStart.type = MMS_BINARY_TIME;
|
||||
rangeStart.value.binaryTime.size = length;
|
||||
|
||||
memcpy(rangeStart.value.binaryTime.buf, requestBuffer + bufPos, length);
|
||||
|
||||
char stringBuf[100];
|
||||
MmsValue_printToBuffer(&rangeStart, stringBuf, 100);
|
||||
|
||||
printf("timeSpecification: %s\n", stringBuf);
|
||||
|
||||
hasRangeStopSpec = true;
|
||||
}
|
||||
else {
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x81: /* entrySpecification */
|
||||
|
||||
if (length <= entrySpec.value.octetString.maxSize) {
|
||||
memcpy(entrySpec.value.octetString.buf, requestBuffer + bufPos, length);
|
||||
entrySpec.value.octetString.size = length;
|
||||
|
||||
printf("EntrySpecification with size %i\n", length);
|
||||
|
||||
hasEntrySpec = true;
|
||||
}
|
||||
else {
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_MODIFIER, response);
|
||||
return;
|
||||
}
|
||||
|
||||
bufPos += length;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
|
||||
return;
|
||||
}
|
||||
|
||||
bufPos += length;
|
||||
}
|
||||
|
||||
//TODO check if required fields are present
|
||||
}
|
||||
|
||||
#endif /* (MMS_JOURNAL_SERVICE == 1) */
|
||||
|
|
Loading…
Add table
Reference in a new issue