- added cmake support to build sqlite log driver

- made logging ready to be compiled with Visual Studio
- added functions to create LCBs and LOGs to dynamic model API
- client: added GetLogicalNodeDirectory(LOG) ACSI function
pull/6/head
Michael Zillgith 9 years ago
parent 23e695dae8
commit 2b28c0fed3

@ -14,6 +14,8 @@ set(LIB_VERSION_MAJOR "0")
set(LIB_VERSION_MINOR "9") set(LIB_VERSION_MINOR "9")
set(LIB_VERSION_PATCH "2") set(LIB_VERSION_PATCH "2")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/third_party/cmake/modules/")
# feature checks # feature checks
include(CheckLibraryExists) include(CheckLibraryExists)
check_library_exists(rt clock_gettime "time.h" CONFIG_SYSTEM_HAS_CLOCK_GETTIME) check_library_exists(rt clock_gettime "time.h" CONFIG_SYSTEM_HAS_CLOCK_GETTIME)
@ -28,7 +30,7 @@ set(CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 5 CACHE STRING "Configure the maximum
option(BUILD_EXAMPLES "Build the examples" ON) option(BUILD_EXAMPLES "Build the examples" ON)
option(BUILD_PYTHON_BINDINGS "Build Python bindings" OFF) option(BUILD_PYTHON_BINDINGS "Build Python bindings" OFF)
option(CONFIG_MMS_SINGLE_THREADED "Compile for single threaded version" OFF) option(CONFIG_MMS_SINGLE_THREADED "Compile for single threaded version" ON)
option(CONFIG_MMS_THREADLESS_STACK "Optimize stack for threadless operation (warning: single- or multi-threaded server will not work!)" OFF) option(CONFIG_MMS_THREADLESS_STACK "Optimize stack for threadless operation (warning: single- or multi-threaded server will not work!)" OFF)
# choose the library features which shall be included # choose the library features which shall be included
@ -38,6 +40,8 @@ option(CONFIG_IEC61850_CONTROL_SERVICE "Build with support for IEC 61850 control
option(CONFIG_IEC61850_REPORT_SERVICE "Build with support for IEC 61850 reporting services" ON) option(CONFIG_IEC61850_REPORT_SERVICE "Build with support for IEC 61850 reporting services" ON)
option(CONFIG_IEC61850_LOG_SERVICE "Build with support for IEC 61850 logging services" ON)
option(CONFIG_IEC61850_SETTING_GROUPS "Build with support for IEC 61850 setting group services" ON) option(CONFIG_IEC61850_SETTING_GROUPS "Build with support for IEC 61850 setting group services" ON)
option(CONFIG_ACTIVATE_TCP_KEEPALIVE "Activate TCP keepalive" ON) option(CONFIG_ACTIVATE_TCP_KEEPALIVE "Activate TCP keepalive" ON)
@ -68,6 +72,7 @@ include_directories(
src/mms/inc src/mms/inc
src/mms/inc_private src/mms/inc_private
src/mms/iso_mms/asn1c src/mms/iso_mms/asn1c
src/logging
) )
set(API_HEADERS set(API_HEADERS
@ -102,6 +107,7 @@ set(API_HEADERS
src/goose/goose_publisher.h src/goose/goose_publisher.h
src/sampled_values/sv_subscriber.h src/sampled_values/sv_subscriber.h
src/sampled_values/sv_publisher.h src/sampled_values/sv_publisher.h
src/logging/logging_api.h
) )
IF(MSVC) IF(MSVC)

@ -156,10 +156,10 @@
/* include support for IEC 61850 log services */ /* include support for IEC 61850 log services */
#define CONFIG_IEC61850_LOG_SERVICE 1 #define CONFIG_IEC61850_LOG_SERVICE 1
/* default results for MMS identify service */ /* overwrite default results for MMS identify service */
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" //#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"
#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" //#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850"
#define CONFIG_DEFAULT_MMS_REVISION "0.9.2" //#define CONFIG_DEFAULT_MMS_REVISION "0.9.2"
/* MMS virtual file store base path - where file services are looking for files */ /* MMS virtual file store base path - where file services are looking for files */
#define CONFIG_VIRTUAL_FILESTORE_BASEPATH "./vmd-filestore/" #define CONFIG_VIRTUAL_FILESTORE_BASEPATH "./vmd-filestore/"

@ -142,6 +142,9 @@
/* default reservation time of a setting group control block in s */ /* default reservation time of a setting group control block in s */
#define CONFIG_IEC61850_SG_RESVTMS 100 #define CONFIG_IEC61850_SG_RESVTMS 100
/* include support for IEC 61850 log services */
#cmakedefine01 CONFIG_IEC61850_LOG_SERVICE
/* default results for MMS identify service */ /* default results for MMS identify service */
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"
#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" #define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850"

@ -10,6 +10,7 @@ add_subdirectory(server_example_complex_array)
add_subdirectory(server_example_threadless) add_subdirectory(server_example_threadless)
add_subdirectory(server_example_61400_25) add_subdirectory(server_example_61400_25)
add_subdirectory(server_example_setting_groups) add_subdirectory(server_example_setting_groups)
add_subdirectory(server_example_logging)
add_subdirectory(iec61850_client_example1) add_subdirectory(iec61850_client_example1)
add_subdirectory(iec61850_client_example2) add_subdirectory(iec61850_client_example2)
add_subdirectory(iec61850_client_example3) add_subdirectory(iec61850_client_example3)

@ -12,7 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include <inttypes.h>
static int running = 1; static int running = 1;
@ -28,7 +28,7 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
printf(" stNum: %u sqNum: %u\n", GooseSubscriber_getStNum(subscriber), printf(" stNum: %u sqNum: %u\n", GooseSubscriber_getStNum(subscriber),
GooseSubscriber_getSqNum(subscriber)); GooseSubscriber_getSqNum(subscriber));
printf(" timeToLive: %u\n", GooseSubscriber_getTimeAllowedToLive(subscriber)); printf(" timeToLive: %u\n", GooseSubscriber_getTimeAllowedToLive(subscriber));
printf(" timestamp: %llu\n", GooseSubscriber_getTimestamp(subscriber)); printf(" timestamp: %"PRIu64"\n", GooseSubscriber_getTimestamp(subscriber));
MmsValue* values = GooseSubscriber_getDataSetValues(subscriber); MmsValue* values = GooseSubscriber_getDataSetValues(subscriber);

@ -947,6 +947,8 @@ SVControlBlock iedModel_MUnn_LLN0_smv0 = {&iedModel_MUnn_LLN0, "MSVCB01", "xxxxM
IedModel iedModel = { IedModel iedModel = {
"TEMPLATE", "TEMPLATE",
&iedModel_MUnn, &iedModel_MUnn,
@ -955,6 +957,8 @@ IedModel iedModel = {
NULL, NULL,
&iedModel_MUnn_LLN0_smv0, &iedModel_MUnn_LLN0_smv0,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -212,21 +212,6 @@ int main(int argc, char** argv) {
char* name = (char*) element->data; char* name = (char*) element->data;
printf(" %s\n", name); printf(" %s\n", name);
#if 0
uint64_t timestamp = Hal_getTimeInMs();
MmsValue* startTime = MmsValue_newBinaryTime(false);
MmsValue_setBinaryTime(startTime, timestamp - 60000);
MmsValue* entrySpec = MmsValue_newOctetString(8, 8);
MmsConnection_readJournalStartAfter(con, &error, domainName, name, startTime, entrySpec);
#endif
} }
LinkedList_destroy(variableList); LinkedList_destroy(variableList);

@ -1596,6 +1596,8 @@ ReportControlBlock iedModel_Device1_LLN0_report0 = {&iedModel_Device1_LLN0, "LLN
IedModel iedModel = { IedModel iedModel = {
"SampleIED", "SampleIED",
&iedModel_Device1, &iedModel_Device1,
@ -1604,6 +1606,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -3586,6 +3586,8 @@ ReportControlBlock iedModel_Inverter_LLN0_report0 = {&iedModel_Inverter_LLN0, "r
IedModel iedModel = { IedModel iedModel = {
"ied1", "ied1",
&iedModel_Inverter, &iedModel_Inverter,
@ -3594,6 +3596,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -1957,8 +1957,8 @@ ReportControlBlock iedModel_GenericIO_LLN0_report6 = {&iedModel_GenericIO_LLN0,
extern LogControlBlock iedModel_GenericIO_LLN0_lcb0; extern LogControlBlock iedModel_GenericIO_LLN0_lcb0;
extern LogControlBlock iedModel_GenericIO_LLN0_lcb1; 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_lcb0 = {&iedModel_GenericIO_LLN0, "EventLog", "Events", "GenericIO/LLN0$EventLog", 3, 0, true, true, &iedModel_GenericIO_LLN0_lcb1};
LogControlBlock iedModel_GenericIO_LLN0_lcb1 = {&iedModel_GenericIO_LLN0, "GeneralLog", "", "", 19, 0, true, true, NULL}; LogControlBlock iedModel_GenericIO_LLN0_lcb1 = {&iedModel_GenericIO_LLN0, "GeneralLog", NULL, NULL, 3, 0, true, true, NULL};
extern Log iedModel_GenericIO_LLN0_log0; extern Log iedModel_GenericIO_LLN0_log0;
extern Log iedModel_GenericIO_LLN0_log1; extern Log iedModel_GenericIO_LLN0_log1;

@ -1779,6 +1779,8 @@ ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0,
IedModel iedModel = { IedModel iedModel = {
"simpleIO", "simpleIO",
&iedModel_GenericIO, &iedModel_GenericIO,
@ -1787,6 +1789,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -3586,6 +3586,8 @@ ReportControlBlock iedModel_Inverter_LLN0_report0 = {&iedModel_Inverter_LLN0, "r
IedModel iedModel = { IedModel iedModel = {
"ied1", "ied1",
&iedModel_Inverter, &iedModel_Inverter,
@ -3594,6 +3596,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -4134,6 +4134,8 @@ DataAttribute iedModel_WTG_WTUR1_SetTurOp_cmAcs = {
IedModel iedModel = { IedModel iedModel = {
"WIND", "WIND",
&iedModel_WTG, &iedModel_WTG,
@ -4142,6 +4144,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -544,6 +544,8 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_frequency = {
IedModel iedModel = { IedModel iedModel = {
"test", "test",
&iedModel_ComplexArray, &iedModel_ComplexArray,
@ -552,6 +554,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -3874,6 +3874,8 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind4_t = {
IedModel iedModel = { IedModel iedModel = {
"simpleIO", "simpleIO",
&iedModel_GenericIO, &iedModel_GenericIO,
@ -3882,6 +3884,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -1909,6 +1909,8 @@ GSEControlBlock iedModel_GenericIO_LLN0_gse1 = {&iedModel_GenericIO_LLN0, "gcbAn
IedModel iedModel = { IedModel iedModel = {
"simpleIO", "simpleIO",
&iedModel_GenericIO, &iedModel_GenericIO,
@ -1917,6 +1919,8 @@ IedModel iedModel = {
&iedModel_GenericIO_LLN0_gse0, &iedModel_GenericIO_LLN0_gse0,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -0,0 +1,34 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = server_example_logging
PROJECT_SOURCES = server_example_logging.c
PROJECT_SOURCES += static_model.c
PROJECT_SOURCES += $(LIBIEC_HOME)/src/logging/drivers/sqlite/log_storage_sqlite.c
PROJECT_SOURCES += $(LIBIEC_HOME)/third_party/sqlite/sqlite3.c
PROJECT_ICD_FILE = simpleIO_direct_control.icd
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk
CFLAGS += -I$(LIBIEC_HOME)/third_party/sqlite
CFLAGS += -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DHAVE_USLEEP
LDLIBS += -lm
CP = cp
model: $(PROJECT_ICD_FILE)
java -jar $(LIBIEC_HOME)/tools/model_generator/genmodel.jar $(PROJECT_ICD_FILE)
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
clean:
rm -f $(PROJECT_BINARY_NAME)

@ -0,0 +1,8 @@
BUILD THE EXAMPLE:
To build the logging example it is required to have sqlite present!
If you have sqlite installed on the system (including the header files) e.g. in an Ubuntu installation with the sqlite3 package installed, you can simply use the Makefile.
If you don't have sqlite installed you have to download the sqlite amalgamation package and install the files sqlite3.c, sqlite3.h in the libiec61850/third_party/sqlite folder and use the Makefile.sqliteStatic instead. This will build a version of the example with the sqlite code statically linked.

@ -17,6 +17,8 @@
#include "logging_api.h" #include "logging_api.h"
LogStorage SqliteLogStorage_createInstance(const char*);
/* import IEC 61850 device model created from SCL-File */ /* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel; extern IedModel iedModel;
@ -164,7 +166,7 @@ main(int argc, char** argv)
LogStorage_addEntryData(statusLog, entryID, "simpleIOGenerioIO/GPIO1$ST$SPCSO1$t", blob, blobSize, 0); LogStorage_addEntryData(statusLog, entryID, "simpleIOGenerioIO/GPIO1$ST$SPCSO1$t", blob, blobSize, 0);
LogStorage_getEntries(statusLog, 0, Hal_getTimeInMs(), entryCallback, entryDataCallback, NULL); LogStorage_getEntries(statusLog, 0, Hal_getTimeInMs(), entryCallback, (LogEntryDataCallback) entryDataCallback, NULL);
/* MMS server will be instructed to start listening to client connections. */ /* MMS server will be instructed to start listening to client connections. */
IedServer_start(iedServer, 102); IedServer_start(iedServer, 102);

@ -1108,6 +1108,8 @@ extern SettingGroupControlBlock iedModel_PROT_LLN0_sgcb;
SettingGroupControlBlock iedModel_PROT_LLN0_sgcb = {&iedModel_PROT_LLN0, 1, 5, 0, false, 0, 0, NULL}; SettingGroupControlBlock iedModel_PROT_LLN0_sgcb = {&iedModel_PROT_LLN0, 1, 5, 0, false, 0, 0, NULL};
IedModel iedModel = { IedModel iedModel = {
"DEMO", "DEMO",
&iedModel_PROT, &iedModel_PROT,
@ -1116,6 +1118,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
&iedModel_PROT_LLN0_sgcb, &iedModel_PROT_LLN0_sgcb,
NULL,
NULL,
initializeValues initializeValues
}; };

@ -1851,6 +1851,10 @@ ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0,
extern LogControlBlock iedModel_GenericIO_LLN0_lcb0;
LogControlBlock iedModel_GenericIO_LLN0_lcb0 = {&iedModel_GenericIO_LLN0, "EventLog", "Events", "GenericIO/LLN0$EventLog", 3, 0, true, true, NULL};
IedModel iedModel = { IedModel iedModel = {
"simpleIO", "simpleIO",
@ -1860,6 +1864,8 @@ IedModel iedModel = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
&iedModel_GenericIO_LLN0_lcb0,
NULL,
initializeValues initializeValues
}; };

@ -76,6 +76,8 @@ set (lib_common_SRCS
./iec61850/server/mms_mapping/reporting.c ./iec61850/server/mms_mapping/reporting.c
./iec61850/server/mms_mapping/mms_goose.c ./iec61850/server/mms_mapping/mms_goose.c
./iec61850/server/mms_mapping/mms_sv.c ./iec61850/server/mms_mapping/mms_sv.c
./iec61850/server/mms_mapping/logging.c
./logging/log_storage.c
) )
set (lib_asn1c_SRCS set (lib_asn1c_SRCS

@ -15,7 +15,7 @@
#include "platform_endian.h" #include "platform_endian.h"
#define LIBIEC61850_VERSION "0.9.1" #define LIBIEC61850_VERSION "0.9.2"
#ifndef CONFIG_DEFAULT_MMS_VENDOR_NAME #ifndef CONFIG_DEFAULT_MMS_VENDOR_NAME
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"

@ -31,6 +31,8 @@
#include "libiec61850_platform_includes.h" #include "libiec61850_platform_includes.h"
#include <inttypes.h>
struct sClientReport struct sClientReport
{ {
ReportCallbackFunction callback; ReportCallbackFunction callback;
@ -405,7 +407,7 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
matchingReport->timestamp = MmsValue_getBinaryTimeAsUtcMs(timeStampValue); matchingReport->timestamp = MmsValue_getBinaryTimeAsUtcMs(timeStampValue);
if (DEBUG_IED_CLIENT) if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: report has timestamp %llu\n", matchingReport->timestamp); printf("DEBUG_IED_CLIENT: report has timestamp %" PRIu64 "\n", matchingReport->timestamp);
} }
inclusionIndex++; inclusionIndex++;

@ -1306,6 +1306,56 @@ addVariablesWithFc(char* fc, char* lnName, LinkedList variables, LinkedList lnDi
} }
} }
static LinkedList
getLogicalNodeDirectoryLogs(IedConnection self, IedClientError* error, const char* logicalDeviceName,
const char* logicalNodeName)
{
MmsConnection mmsCon = self->connection;
MmsError mmsError;
LinkedList journals = MmsConnection_getDomainJournals(mmsCon, &mmsError, logicalDeviceName);
if (mmsError != MMS_ERROR_NONE) {
*error = iedConnection_mapMmsErrorToIedError(mmsError);
return NULL;
}
LinkedList logs = LinkedList_create();
LinkedList journal = LinkedList_getNext(journals);
while (journal != NULL) {
char* journalName = (char*) LinkedList_getData(journal);
char* logName = strchr(journalName, '$');
if (logName != NULL) {
logName[0] = 0;
logName += 1;
if (strcmp(journalName, logicalNodeName) == 0) {
char* log = copyString(logName);
LinkedList_add(logs, (void*) log);
}
}
journal = LinkedList_getNext(journal);
}
LinkedList_destroy(journals);
return logs;
}
static LinkedList
getLogicalNodeDirectoryDataSets(IedConnection self, IedClientError* error, const char* logicalDeviceName,
const char* logicalNodeName)
{
MmsConnection mmsCon = self->connection;
}
LinkedList /*<char*>*/ LinkedList /*<char*>*/
IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error, IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
const char* logicalNodeReference, ACSIClass acsiClass) const char* logicalNodeReference, ACSIClass acsiClass)
@ -1317,12 +1367,6 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
return NULL; return NULL;
} }
if (self->logicalDevices == NULL)
IedConnection_getDeviceModelFromServer(self, error);
if (*error != IED_ERROR_OK)
return NULL;
char lnRefCopy[130]; char lnRefCopy[130];
strncpy(lnRefCopy, logicalNodeReference, 129); strncpy(lnRefCopy, logicalNodeReference, 129);
@ -1341,6 +1385,16 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error,
char* logicalNodeName = ldSep + 1; char* logicalNodeName = ldSep + 1;
if (acsiClass == ACSI_CLASS_LOG) {
return getLogicalNodeDirectoryLogs(self, error, logicalDeviceName, logicalNodeName);
}
if (self->logicalDevices == NULL)
IedConnection_getDeviceModelFromServer(self, error);
if (*error != IED_ERROR_OK)
return NULL;
/* search for logical device */ /* search for logical device */
LinkedList device = LinkedList_getNext(self->logicalDevices); LinkedList device = LinkedList_getNext(self->logicalDevices);

@ -146,7 +146,7 @@ DataAttribute_create(const char* name, ModelNode* parent, DataAttributeType type
* \param parent the parent LN. * \param parent the parent LN.
* \param rptId of the report. If NULL the default report ID (object reference) is used. * \param rptId of the report. If NULL the default report ID (object reference) is used.
* \param isBuffered true for a buffered RCB - false for unbuffered RCB * \param isBuffered true for a buffered RCB - false for unbuffered RCB
* \param dataSetName name (object reference) of the default data set or NULL if no data * \param dataSetName name (object reference) of the default data set or NULL if no data set
* is set by default * is set by default
* \param confRef the configuration revision * \param confRef the configuration revision
* \param trgOps the trigger options supported by this RCB (bit set) * \param trgOps the trigger options supported by this RCB (bit set)
@ -160,6 +160,38 @@ ReportControlBlock*
ReportControlBlock_create(const char* name, LogicalNode* parent, char* rptId, bool isBuffered, char* ReportControlBlock_create(const char* name, LogicalNode* parent, char* rptId, bool isBuffered, char*
dataSetName, uint32_t confRef, uint8_t trgOps, uint8_t options, uint32_t bufTm, uint32_t intgPd); dataSetName, uint32_t confRef, uint8_t trgOps, uint8_t options, uint32_t bufTm, uint32_t intgPd);
/**
* \brief create a new log control block (LCB)
*
* Create a new log control block (LCB) and add it to the given logical node (LN).
*
* \param name name of the LCB relative to the parent LN
* \param parent the parent LN.
* \param dataSetName name (object reference) of the default data set or NULL if no data set
* is set by default
* \param logRef name (object reference) of the default log or NULL if no log is set by default
* \param trgOps the trigger options supported by this LCB (bit set)
* \param intgPd integrity period in milliseconds
* \param logEna if true the log will be enabled by default, false otherwise
* \param reasonCode if true the reasonCode will be included in the log (this is always true in MMS mapping)
*
* \return the new LCB instance
*/
LogControlBlock*
LogControlBlock_create(const char* name, LogicalNode* parent, char* dataSetName, char* logRef, uint8_t trgOps,
uint32_t intgPd, bool logEna, bool reasonCode);
/**
* \brief create a log (used by the IEC 61850 log service)
*
* \param name name of the LOG relative to the parent LN
* \param parent the parent LN
*
* \return the new LOG instance
*/
Log*
Log_create(const char* name, LogicalNode* parent);
/** /**
* \brief create a setting group control block (SGCB) * \brief create a setting group control block (SGCB)
* *

@ -517,9 +517,6 @@ LogicalNode_hasUnbufferedReports(LogicalNode* node);
DataSet* DataSet*
LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName); LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName);
void
LogicalNode_setLogStorage(LogicalNode* self, const char* logName, LogStorage logStorage);
bool bool
DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc); DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc);

@ -42,6 +42,7 @@ struct sIedServer
MmsMapping* mmsMapping; MmsMapping* mmsMapping;
LinkedList clientConnections; LinkedList clientConnections;
uint8_t writeAccessPolicies; uint8_t writeAccessPolicies;
bool running;
}; };

@ -48,6 +48,7 @@ typedef struct {
DataSet* dataSet; DataSet* dataSet;
char* dataSetRef; char* dataSetRef;
bool isDynamicDataSet;
LogicalNode* logicalNode; LogicalNode* logicalNode;
MmsDomain* domain; MmsDomain* domain;

@ -404,6 +404,8 @@ IedServer_create(IedModel* iedModel)
self->model = iedModel; self->model = iedModel;
// self->running = false; /* not required due to CALLOC */
self->mmsMapping = MmsMapping_create(iedModel); self->mmsMapping = MmsMapping_create(iedModel);
self->mmsDevice = MmsMapping_getMmsDeviceModel(self->mmsMapping); self->mmsDevice = MmsMapping_getMmsDeviceModel(self->mmsMapping);
@ -445,6 +447,16 @@ IedServer_create(IedModel* iedModel)
void void
IedServer_destroy(IedServer self) IedServer_destroy(IedServer self)
{ {
/* Stop server if running */
if (self->running) {
#if (CONFIG_MMS_THREADLESS_STACK == 1)
IedServer_stopThreadless(self);
#else
IedServer_stop(self);
#endif
}
MmsServer_destroy(self->mmsServer); MmsServer_destroy(self->mmsServer);
IsoServer_destroy(self->isoServer); IsoServer_destroy(self->isoServer);
@ -525,17 +537,22 @@ singleThreadedServerThread(void* parameter)
void void
IedServer_start(IedServer self, int tcpPort) IedServer_start(IedServer self, int tcpPort)
{ {
if (self->running == false) {
#if (CONFIG_MMS_SINGLE_THREADED == 1) #if (CONFIG_MMS_SINGLE_THREADED == 1)
MmsServer_startListeningThreadless(self->mmsServer, tcpPort); MmsServer_startListeningThreadless(self->mmsServer, tcpPort);
Thread serverThread = Thread_create((ThreadExecutionFunction) singleThreadedServerThread, (void*) self, true); Thread serverThread = Thread_create((ThreadExecutionFunction) singleThreadedServerThread, (void*) self, true);
Thread_start(serverThread); Thread_start(serverThread);
#else #else
MmsServer_startListening(self->mmsServer, tcpPort); MmsServer_startListening(self->mmsServer, tcpPort);
MmsMapping_startEventWorkerThread(self->mmsMapping); MmsMapping_startEventWorkerThread(self->mmsMapping);
#endif #endif
self->running = true;
}
} }
#endif #endif
@ -558,13 +575,17 @@ IedServer_getDataModel(IedServer self)
void void
IedServer_stop(IedServer self) IedServer_stop(IedServer self)
{ {
MmsMapping_stopEventWorkerThread(self->mmsMapping); if (self->running) {
self->running = false;
MmsMapping_stopEventWorkerThread(self->mmsMapping);
#if (CONFIG_MMS_SINGLE_THREADED == 1) #if (CONFIG_MMS_SINGLE_THREADED == 1)
MmsServer_stopListeningThreadless(self->mmsServer); MmsServer_stopListeningThreadless(self->mmsServer);
#else #else
MmsServer_stopListening(self->mmsServer); MmsServer_stopListening(self->mmsServer);
#endif #endif
}
} }
#endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */ #endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */
@ -572,7 +593,10 @@ IedServer_stop(IedServer self)
void void
IedServer_startThreadless(IedServer self, int tcpPort) IedServer_startThreadless(IedServer self, int tcpPort)
{ {
MmsServer_startListeningThreadless(self->mmsServer, tcpPort); if (self->running == false) {
MmsServer_startListeningThreadless(self->mmsServer, tcpPort);
self->running = true;
}
} }
int int
@ -590,7 +614,11 @@ IedServer_processIncomingData(IedServer self)
void void
IedServer_stopThreadless(IedServer self) IedServer_stopThreadless(IedServer self)
{ {
MmsServer_stopListeningThreadless(self->mmsServer); if (self->running) {
self->running = false;
MmsServer_stopListeningThreadless(self->mmsServer);
}
} }
void void

@ -35,6 +35,8 @@
#include "mms_mapping_internal.h" #include "mms_mapping_internal.h"
#include "mms_value_internal.h" #include "mms_value_internal.h"
#include "logging_api.h"
#if (CONFIG_IEC61850_LOG_SERVICE == 1) #if (CONFIG_IEC61850_LOG_SERVICE == 1)
LogInstance* LogInstance*
@ -74,7 +76,7 @@ LogInstance_logSingleData(LogInstance* self, const char* dataRef, MmsValue* valu
self->locked = true; self->locked = true;
//if (DEBUG_IED_SERVER) if (DEBUG_IED_SERVER)
printf("IED_SERVER: Log value - dataRef: %s flag: %i\n", dataRef, flag); printf("IED_SERVER: Log value - dataRef: %s flag: %i\n", dataRef, flag);
uint64_t timestamp = Hal_getTimeInMs(); uint64_t timestamp = Hal_getTimeInMs();
@ -83,7 +85,7 @@ LogInstance_logSingleData(LogInstance* self, const char* dataRef, MmsValue* valu
int dataSize = MmsValue_encodeMmsData(value, NULL, 0, false); int dataSize = MmsValue_encodeMmsData(value, NULL, 0, false);
uint8_t* data = GLOBAL_MALLOC(dataSize); uint8_t* data = (uint8_t*) GLOBAL_MALLOC(dataSize);
MmsValue_encodeMmsData(value, data, 0, true); MmsValue_encodeMmsData(value, data, 0, true);
@ -137,7 +139,7 @@ LogInstance_logEntryData(LogInstance* self, uint64_t entryID, const char* dataRe
int dataSize = MmsValue_encodeMmsData(value, NULL, 0, false); int dataSize = MmsValue_encodeMmsData(value, NULL, 0, false);
uint8_t* data = GLOBAL_MALLOC(dataSize); uint8_t* data = (uint8_t*) GLOBAL_MALLOC(dataSize);
MmsValue_encodeMmsData(value, data, 0, true); MmsValue_encodeMmsData(value, data, 0, true);
@ -171,6 +173,7 @@ LogControl_create(LogicalNode* parentLN, MmsMapping* mmsMapping)
self->enabled = false; self->enabled = false;
self->dataSet = NULL; self->dataSet = NULL;
self->isDynamicDataSet = false;
self->triggerOps = 0; self->triggerOps = 0;
self->logicalNode = parentLN; self->logicalNode = parentLN;
self->mmsMapping = mmsMapping; self->mmsMapping = mmsMapping;
@ -207,16 +210,14 @@ static void
prepareLogControl(LogControl* logControl) prepareLogControl(LogControl* logControl)
{ {
if (logControl->dataSetRef == NULL) { if (logControl->dataSetRef == NULL) {
printf(" no data set specified!\n"); logControl->enabled = false;
return; return;
} }
DataSet* dataSet = IedModel_lookupDataSet(logControl->mmsMapping->model, logControl->dataSetRef); DataSet* dataSet = IedModel_lookupDataSet(logControl->mmsMapping->model, logControl->dataSetRef);
if (dataSet == NULL) { if (dataSet == NULL)
printf(" data set (%s) not found!\n", logControl->dataSetRef);
return; return;
}
else else
logControl->dataSet = dataSet; logControl->dataSet = dataSet;
} }
@ -322,7 +323,7 @@ getLogInstanceByLogRef(MmsMapping* self, const char* logRef)
while (instance != NULL) { while (instance != NULL) {
LogInstance* logInstance = LinkedList_getData(instance); LogInstance* logInstance = (LogInstance*) LinkedList_getData(instance);
if (strcmp(logInstance->name, logName) == 0) { if (strcmp(logInstance->name, logName) == 0) {
@ -355,6 +356,18 @@ updateLogStatusInLCB(LogControl* self)
} }
static void
freeDynamicDataSet(LogControl* self)
{
if (self->isDynamicDataSet) {
if (self->dataSet != NULL) {
MmsMapping_freeDynamicallyCreatedDataSet(self->dataSet);
self->isDynamicDataSet = false;
self->dataSet = NULL;
}
}
}
MmsDataAccessError MmsDataAccessError
LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
MmsValue* value, MmsServerConnection connection) MmsValue* value, MmsServerConnection connection)
@ -460,7 +473,6 @@ LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* doma
if (logControl->enabled == false) { if (logControl->enabled == false) {
/* check if datSet is valid or NULL/empty */ /* check if datSet is valid or NULL/empty */
const char* dataSetRef = MmsValue_toString(value); const char* dataSetRef = MmsValue_toString(value);
if (strlen(dataSetRef) == 0) { if (strlen(dataSetRef) == 0) {
@ -470,16 +482,51 @@ LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* doma
else { else {
DataSet* dataSet = IedModel_lookupDataSet(logControl->mmsMapping->model, dataSetRef); DataSet* dataSet = IedModel_lookupDataSet(logControl->mmsMapping->model, dataSetRef);
if (dataSet != NULL) {
freeDynamicDataSet(logControl);
logControl->dataSet = dataSet;
updateValue = true;
}
#if (MMS_DYNAMIC_DATA_SETS == 1)
if (dataSet == NULL) {
dataSet = MmsMapping_getDomainSpecificDataSet(self, dataSetRef);
if (dataSet == NULL) {
if (dataSetRef[0] == '/') { /* check for VMD specific data set */
MmsNamedVariableList mmsVariableList =
MmsDevice_getNamedVariableListWithName(self->mmsDevice, dataSetRef + 1);
if (mmsVariableList != NULL)
dataSet = MmsMapping_createDataSetByNamedVariableList(self, mmsVariableList);
}
}
if (dataSet != NULL) {
freeDynamicDataSet(logControl);
logControl->dataSet = dataSet;
logControl->isDynamicDataSet = true;
updateValue = true;
}
}
#endif /*(MMS_DYNAMIC_DATA_SETS == 1) */
if (dataSet == NULL) { if (dataSet == NULL) {
if (DEBUG_IED_SERVER) if (DEBUG_IED_SERVER)
printf("IED_SERVER: data set (%s) not found!\n", logControl->dataSetRef); printf("IED_SERVER: data set (%s) not found!\n", logControl->dataSetRef);
return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
} }
else {
logControl->dataSet = dataSet;
updateValue = true;
}
} }
} }
else else
return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
@ -589,7 +636,11 @@ createTrgOps(LogControlBlock* logControlBlock) {
return trgOps; return trgOps;
} }
static void
LogControl_updateLogEna(LogControl* self)
{
MmsValue_setBoolean(MmsValue_getElement(self->mmsValue, 0), self->enabled);
}
static MmsVariableSpecification* static MmsVariableSpecification*
createLogControlBlock(MmsMapping* self, LogControlBlock* logControlBlock, createLogControlBlock(MmsMapping* self, LogControlBlock* logControlBlock,
@ -743,6 +794,8 @@ createLogControlBlock(MmsMapping* self, LogControlBlock* logControlBlock,
if (logControl->enabled) if (logControl->enabled)
enableLogging(logControl); enableLogging(logControl);
LogControl_updateLogEna(logControl);
return lcb; return lcb;
} }
@ -871,7 +924,7 @@ MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logSto
MmsJournal mmsJournal = NULL; MmsJournal mmsJournal = NULL;
char* logName = strchr(logRef, '/'); const char* logName = strchr(logRef, '/');
if (logName != NULL) { if (logName != NULL) {
logName += 1; logName += 1;

@ -2501,6 +2501,14 @@ variableListChangedHandler (void* parameter, bool create, MmsVariableListType li
} }
} }
} }
else if (listType == MMS_VMD_SPECIFIC) {
if (rc->dataSet->logicalDeviceName == NULL) {
if (strcmp(rc->dataSet->name, listName) == 0) {
allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
break;
}
}
}
else if (listType == MMS_ASSOCIATION_SPECIFIC) { else if (listType == MMS_ASSOCIATION_SPECIFIC) {
if (rc->dataSet->logicalDeviceName == NULL) { if (rc->dataSet->logicalDeviceName == NULL) {
if (strcmp(rc->dataSet->name, listName) == 0) { if (strcmp(rc->dataSet->name, listName) == 0) {
@ -2514,7 +2522,41 @@ variableListChangedHandler (void* parameter, bool create, MmsVariableListType li
} }
} }
//TODO check if data set is referenced in a log control block
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
/* check if data set is referenced in a log control block*/
LinkedList logElement = self->logControls;
while ((logElement = LinkedList_getNext(logElement)) != NULL) {
LogControl* lc = (LogControl*) logElement->data;
if (lc->isDynamicDataSet) {
if (lc->dataSet != NULL) {
if (listType == MMS_DOMAIN_SPECIFIC) {
if (lc->dataSet->logicalDeviceName != NULL) {
if (strcmp(lc->dataSet->name, listName) == 0) {
if (strcmp(lc->dataSet->logicalDeviceName, MmsDomain_getName(domain)) == 0) {
allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
break;
}
}
}
}
else if (listType == MMS_VMD_SPECIFIC) {
if (lc->dataSet->logicalDeviceName == NULL) {
if (strcmp(lc->dataSet->name, listName) == 0) {
allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT;
break;
}
}
}
}
}
}
#endif /* (CONFIG_IEC61850_LOG_SERVICE == 1) */
} }
return allow; return allow;

@ -58,6 +58,10 @@ IedModel_create(const char* name/*, MemoryAllocator allocator*/)
self->sgcbs = NULL; self->sgcbs = NULL;
self->lcbs = NULL;
self->logs = NULL;
self->initializer = iedModel_emptyVariableInitializer; self->initializer = iedModel_emptyVariableInitializer;
return self; return self;
@ -97,6 +101,36 @@ IedModel_addLogicalDevice(IedModel* self, LogicalDevice* lDevice)
} }
} }
static void
IedModel_addLog(IedModel* self, Log* log)
{
if (self->logs == NULL)
self->logs = log;
else {
Log* lastLog = self->logs;
while (lastLog->sibling != NULL)
lastLog = lastLog->sibling;
lastLog->sibling = log;
}
}
static void
IedModel_addLogControlBlock(IedModel* self, LogControlBlock* lcb)
{
if (self->lcbs == NULL)
self->lcbs = lcb;
else {
LogControlBlock* lastLcb = self->lcbs;
while (lastLcb->sibling != NULL)
lastLcb = lastLcb->sibling;
lastLcb->sibling = lcb;
}
}
static void static void
IedModel_addReportControlBlock(IedModel* self, ReportControlBlock* rcb) IedModel_addReportControlBlock(IedModel* self, ReportControlBlock* rcb)
{ {
@ -231,6 +265,65 @@ LogicalNode_addDataObject(LogicalNode* self, DataObject* dataObject)
} }
} }
static void
LogicalNode_addLog(LogicalNode* self, Log* log)
{
IedModel* model = (IedModel*) self->parent->parent;
IedModel_addLog(model, log);
}
Log*
Log_create(const char* name, LogicalNode* parent)
{
Log* self = (Log*) GLOBAL_MALLOC(sizeof(Log));
self->name = copyString(name);
self->parent = parent;
self->sibling = NULL;
LogicalNode_addLog(parent, self);
return self;
}
static void
LogicalNode_addLogControlBlock(LogicalNode* self, LogControlBlock* lcb)
{
IedModel* model = (IedModel*) self->parent->parent;
IedModel_addLogControlBlock(model, lcb);
}
LogControlBlock*
LogControlBlock_create(const char* name, LogicalNode* parent, char* dataSetName, char* logRef, uint8_t trgOps,
uint32_t intPeriod, bool logEna, bool reasonCode)
{
LogControlBlock* self = (LogControlBlock*) GLOBAL_MALLOC(sizeof(LogControlBlock));
self->name = copyString(name);
self->parent = parent;
if (dataSetName)
self->dataSetName = copyString(dataSetName);
else
dataSetName = NULL;
if (logRef)
self->logRef = copyString(logRef);
else
logRef = NULL;
self->trgOps = trgOps;
self->intPeriod = intPeriod;
self->logEna = logEna;
self->reasonCode = reasonCode;
LogicalNode_addLogControlBlock(parent, self);
return self;
}
static void static void
LogicalNode_addReportControlBlock(LogicalNode* self, ReportControlBlock* rcb) LogicalNode_addReportControlBlock(LogicalNode* self, ReportControlBlock* rcb)
{ {
@ -743,6 +836,28 @@ IedModel_destroy(IedModel* model)
sgcb = nextSgcb; sgcb = nextSgcb;
} }
/* delete all LCBs */
LogControlBlock* lcb = model->lcbs;
while (lcb != NULL) {
LogControlBlock* nextLcb = lcb->sibling;
GLOBAL_FREEMEM(lcb);
lcb = nextLcb;
}
/* delete all LOGs */
Log* log = model->logs;
while (log != NULL) {
Log* nextLog = log->sibling;
GLOBAL_FREEMEM(log);
log = nextLog;
}
/* delete generic model parts */ /* delete generic model parts */

@ -409,20 +409,6 @@ exit_error:
return NULL; 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 int
LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice) LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice)
{ {

@ -166,7 +166,8 @@ exit_with_error:
static uint64_t static uint64_t
SqliteLogStorage_addEntry(LogStorage self, uint64_t timestamp) SqliteLogStorage_addEntry(LogStorage self, uint64_t timestamp)
{ {
printf("SQLITE-DRIVER: add entry\n"); if (DEBUG_LOG_STORAGE_DRIVER)
printf("LOG_STORAGE_DRIVER: sqlite - add entry\n");
SqliteLogStorage* instanceData = (SqliteLogStorage*) (self->instanceData); SqliteLogStorage* instanceData = (SqliteLogStorage*) (self->instanceData);
@ -269,8 +270,8 @@ getEntryData(LogStorage self, uint64_t entryID, LogEntryDataCallback entryDataCa
while ((rc = sqlite3_step(instanceData->getEntryData)) == SQLITE_ROW) { while ((rc = sqlite3_step(instanceData->getEntryData)) == SQLITE_ROW) {
const char* dataRef = sqlite3_column_text(instanceData->getEntryData, 0); const char* dataRef = (const char*) sqlite3_column_text(instanceData->getEntryData, 0);
const uint8_t* data = sqlite3_column_blob(instanceData->getEntryData, 1); uint8_t* data = (uint8_t*) sqlite3_column_blob(instanceData->getEntryData, 1);
int dataSize = sqlite3_column_bytes(instanceData->getEntryData, 1); int dataSize = sqlite3_column_bytes(instanceData->getEntryData, 1);
int reasonCode = sqlite3_column_int(instanceData->getEntryData, 2); int reasonCode = sqlite3_column_int(instanceData->getEntryData, 2);
@ -317,7 +318,6 @@ SqliteLogStorage_getEntries(LogStorage self, uint64_t startingTime, uint64_t end
bool sendFinalEvent = true; bool sendFinalEvent = true;
while((rc = sqlite3_step(instanceData->getEntriesWithRange)) == SQLITE_ROW) { while((rc = sqlite3_step(instanceData->getEntriesWithRange)) == SQLITE_ROW) {
int col;
uint64_t entryID = sqlite3_column_int64(instanceData->getEntriesWithRange, 0); uint64_t entryID = sqlite3_column_int64(instanceData->getEntriesWithRange, 0);
uint64_t timestamp = sqlite3_column_int64(instanceData->getEntriesWithRange, 1); uint64_t timestamp = sqlite3_column_int64(instanceData->getEntriesWithRange, 1);
@ -412,7 +412,6 @@ SqliteLogStorage_getEntriesAfter(LogStorage self, uint64_t startingTime, uint64_
bool sendFinalEvent = true; bool sendFinalEvent = true;
while ((rc = sqlite3_step(instanceData->getEntriesAfter)) == SQLITE_ROW) { while ((rc = sqlite3_step(instanceData->getEntriesAfter)) == SQLITE_ROW) {
int col;
uint64_t entryID = sqlite3_column_int64(instanceData->getEntriesAfter, 0); uint64_t entryID = sqlite3_column_int64(instanceData->getEntriesAfter, 0);
uint64_t timestamp = sqlite3_column_int64(instanceData->getEntriesAfter, 1); uint64_t timestamp = sqlite3_column_int64(instanceData->getEntriesAfter, 1);

@ -24,6 +24,10 @@
#ifndef LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ #ifndef LIBIEC61850_SRC_LOGGING_LOGGING_API_H_
#define LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ #define LIBIEC61850_SRC_LOGGING_LOGGING_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -37,7 +41,7 @@ typedef struct sLogStorage* LogStorage;
*/ */
typedef bool (*LogEntryCallback) (void* parameter, uint64_t timestamp, uint64_t entryID, bool moreFollow); typedef bool (*LogEntryCallback) (void* parameter, uint64_t timestamp, uint64_t entryID, bool moreFollow);
typedef bool (*LogEntryDataCallback) (void* parameter, const char* dataRef, const uint8_t* data, int dataSize, uint8_t reasonCode, bool moreFollow); typedef bool (*LogEntryDataCallback) (void* parameter, const char* dataRef, uint8_t* data, int dataSize, uint8_t reasonCode, bool moreFollow);
struct sLogStorage { struct sLogStorage {
@ -82,4 +86,8 @@ LogStorage_getOldestAndNewestEntries(LogStorage self, uint64_t* newEntry, uint64
void void
LogStorage_destroy(LogStorage self); LogStorage_destroy(LogStorage self);
#ifdef __cplusplus
}
#endif
#endif /* LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ */ #endif /* LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ */

@ -76,8 +76,6 @@ MmsDomain_getName(MmsDomain* self)
void void
MmsDomain_addJournal(MmsDomain* self, const char* name) MmsDomain_addJournal(MmsDomain* self, const char* name)
{ {
printf("CREATE JOURNAL\n");
if (self->journals == NULL) if (self->journals == NULL)
self->journals = LinkedList_create(); self->journals = LinkedList_create();
@ -96,8 +94,6 @@ MmsDomain_getJournal(MmsDomain* self, const char* name)
MmsJournal mmsJournal = (MmsJournal) LinkedList_getData(journal); MmsJournal mmsJournal = (MmsJournal) LinkedList_getData(journal);
printf(" MMS journal: %s (%s)\n", mmsJournal->name, name);
if (strcmp(mmsJournal->name, name) == 0) if (strcmp(mmsJournal->name, name) == 0)
return mmsJournal; return mmsJournal;

@ -538,6 +538,10 @@ mmsServer_handleGetNameListRequest(
if (nameList == NULL) if (nameList == NULL)
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
else { else {
#if (CONFIG_MMS_SORT_NAME_LIST == 1)
StringUtils_sortList(nameList);
#endif
createNameListResponse(connection, invokeId, nameList, response, continueAfterId); createNameListResponse(connection, invokeId, nameList, response, continueAfterId);
LinkedList_destroyStatic(nameList); LinkedList_destroyStatic(nameList);
} }

@ -68,7 +68,7 @@ entryCallback(void* parameter, uint64_t timestamp, uint64_t entryID, bool moreFo
JournalEncoder encoder = (JournalEncoder) parameter; JournalEncoder encoder = (JournalEncoder) parameter;
if (moreFollow) { if (moreFollow) {
//printf("Encode entry ID:%" PRIu64 " timestamp:%" PRIu64 "\n", entryID, timestamp);
if (encoder->moreFollows) { if (encoder->moreFollows) {
printf("entryCallback return false\n"); printf("entryCallback return false\n");
return false; return false;
@ -128,7 +128,7 @@ entryDataCallback (void* parameter, const char* dataRef, uint8_t* data, int data
uint32_t totalLen = firstVariableLen + secondVariableLen; uint32_t totalLen = firstVariableLen + secondVariableLen;
if ((bufPos + totalLen) > encoder->maxSize) { if ((int) (bufPos + totalLen) > encoder->maxSize) {
encoder->moreFollows = true; encoder->moreFollows = true;
encoder->bufPos = encoder->currentEntryBufPos; /* remove last entry */ encoder->bufPos = encoder->currentEntryBufPos; /* remove last entry */
return false; return false;
@ -241,8 +241,6 @@ mmsServer_handleReadJournalRequest(
uint32_t invokeId, uint32_t invokeId,
ByteBuffer* response) ByteBuffer* response)
{ {
printf("READ-JOURNAL\n");
char domainId[65]; char domainId[65];
char logName[65]; char logName[65];
uint8_t entryIdBuf[64]; /* maximum size of entry id is 64 bytes! */ uint8_t entryIdBuf[64]; /* maximum size of entry id is 64 bytes! */
@ -276,7 +274,6 @@ mmsServer_handleReadJournalRequest(
case 0xa0: /* journalName */ case 0xa0: /* journalName */
{ {
uint8_t objectIdTag = requestBuffer[bufPos++]; uint8_t objectIdTag = requestBuffer[bufPos++];
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos); bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);

@ -0,0 +1,20 @@
1 VERSIONINFO
FILEVERSION @LIB_VERSION_MAJOR@,@LIB_VERSION_MINOR@,@LIB_VERSION_PATCH@,0
PRODUCTVERSION @LIB_VERSION_MAJOR@,@LIB_VERSION_MINOR@,@LIB_VERSION_PATCH@,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileVersion", "@LIB_VERSION_MAJOR@.@LIB_VERSION_MINOR@.@LIB_VERSION_PATCH@.0"
VALUE "ProductVersion", "@LIB_VERSION_MAJOR@.@LIB_VERSION_MINOR@.@LIB_VERSION_PATCH@.0"
VALUE "ProductName", "libIEC61850"
VALUE "FileDescription", "libIEC61850 - open source library for IEC 61850"
VALUE "LegalCopyright", "Dual license : Commercial or GPLv3"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x400, 1252
END
END

@ -528,4 +528,20 @@ EXPORTS
MmsValue_encodeMmsData MmsValue_encodeMmsData
ControlObjectClient_setInterlockCheck ControlObjectClient_setInterlockCheck
ControlObjectClient_setSynchroCheck ControlObjectClient_setSynchroCheck
LogStorage_addEntry
LogStorage_addEntryData
LogStorage_getEntries
LogStorage_getEntriesAfter
LogStorage_getOldestAndNewestEntries
LogStorage_destroy
IedServer_setLogStorage
MmsJournalEntry_destroy
MmsJournalEntry_getEntryID
MmsJournalEntry_getOccurenceTime
MmsJournalEntry_getJournalVariables
MmsJournalVariable_getTag
MmsJournalVariable_getValue
MmsConnection_readJournalTimeRange
MmsConnection_readJournalStartAfter
LogControlBlock_create
Log_create

@ -604,3 +604,20 @@ EXPORTS
IedServer_updateVisibleStringAttributeValue IedServer_updateVisibleStringAttributeValue
ControlObjectClient_setInterlockCheck ControlObjectClient_setInterlockCheck
ControlObjectClient_setSynchroCheck ControlObjectClient_setSynchroCheck
LogStorage_addEntry
LogStorage_addEntryData
LogStorage_getEntries
LogStorage_getEntriesAfter
LogStorage_getOldestAndNewestEntries
LogStorage_destroy
IedServer_setLogStorage
MmsJournalEntry_destroy
MmsJournalEntry_getEntryID
MmsJournalEntry_getOccurenceTime
MmsJournalEntry_getJournalVariables
MmsJournalVariable_getTag
MmsJournalVariable_getValue
MmsConnection_readJournalTimeRange
MmsConnection_readJournalStartAfter
LogControlBlock_create
Log_create

@ -0,0 +1,48 @@
# - Try to find the sqlite library
# Once done this will define
#
# SQLITE_FOUND - system has sqlite
# SQLITE_INCLUDE_DIRS - the sqlite include directory
# SQLITE_LIBRARIES - Link these to use sqlite
#
# Define SQLITE_MIN_VERSION for which version desired.
#
INCLUDE(FindPkgConfig)
IF(Sqlite_FIND_REQUIRED)
SET(_pkgconfig_REQUIRED "REQUIRED")
ELSE(Sqlite_FIND_REQUIRED)
SET(_pkgconfig_REQUIRED "")
ENDIF(Sqlite_FIND_REQUIRED)
IF(SQLITE_MIN_VERSION)
PKG_SEARCH_MODULE(SQLITE ${_pkgconfig_REQUIRED} sqlite>=${SQLITE_MIN_VERSION} sqlite${SQLITE_MIN_VERSION})
ELSE(SQLITE_MIN_VERSION)
PKG_SEARCH_MODULE(SQLITE ${_pkgconfig_REQUIRED} sqlite)
ENDIF(SQLITE_MIN_VERSION)
IF(NOT SQLITE_FOUND AND NOT PKG_CONFIG_FOUND)
FIND_PATH(SQLITE_INCLUDE_DIRS sqlite${SQLITE_MIN_VERSION}.h)
FIND_LIBRARY(SQLITE_LIBRARIES sqlite${SQLITE_MIN_VERSION})
# Report results
IF(SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIRS)
SET(SQLITE_FOUND 1)
IF(NOT Sqlite_FIND_QUIETLY)
MESSAGE(STATUS "Found Sqlite: ${SQLITE_LIBRARIES}")
ENDIF(NOT Sqlite_FIND_QUIETLY)
ELSE(SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIRS)
IF(Sqlite_FIND_REQUIRED)
MESSAGE(SEND_ERROR "Could not find Sqlite")
ELSE(Sqlite_FIND_REQUIRED)
IF(NOT Sqlite_FIND_QUIETLY)
MESSAGE(STATUS "Could not find Sqlite")
ENDIF(NOT Sqlite_FIND_QUIETLY)
ENDIF(Sqlite_FIND_REQUIRED)
ENDIF(SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIRS)
ENDIF(NOT SQLITE_FOUND AND NOT PKG_CONFIG_FOUND)
# Hide advanced variables from CMake GUIs
MARK_AS_ADVANCED(SQLITE_LIBRARIES SQLITE_INCLUDE_DIRS)
Loading…
Cancel
Save