From 2b28c0fed35c98df01b635d31da843be2045027a Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 9 Jun 2016 00:00:02 +0200 Subject: [PATCH] - 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 --- CMakeLists.txt | 8 +- config/stack_config.h | 8 +- config/stack_config.h.cmake | 3 + examples/CMakeLists.txt | 1 + .../goose_subscriber_example.c | 4 +- .../iec61850_9_2_LE_example/static_model.c | 4 + examples/mms_utility/mms_utility.c | 15 --- examples/server_example1/static_model.c | 4 + examples/server_example2/static_model.c | 4 + examples/server_example3/static_model.c | 4 +- examples/server_example4/static_model.c | 4 + examples/server_example5/static_model.c | 4 + .../server_example_61400_25/static_model.c | 4 + .../static_model.c | 4 + .../server_example_control/static_model.c | 4 + examples/server_example_goose/static_model.c | 4 + .../Makefile.sqliteStatic | 34 ++++++ examples/server_example_logging/README | 8 ++ .../server_example_logging.c | 4 +- .../static_model.c | 4 + .../server_example_threadless/static_model.c | 6 + src/CMakeLists.txt | 2 + .../inc/libiec61850_platform_includes.h | 2 +- src/iec61850/client/client_report.c | 4 +- src/iec61850/client/ied_connection.c | 66 +++++++++- src/iec61850/inc/iec61850_dynamic_model.h | 34 +++++- src/iec61850/inc/iec61850_model.h | 3 - src/iec61850/inc_private/ied_server_private.h | 1 + src/iec61850/inc_private/logging.h | 1 + src/iec61850/server/impl/ied_server.c | 48 ++++++-- src/iec61850/server/mms_mapping/logging.c | 83 ++++++++++--- src/iec61850/server/mms_mapping/mms_mapping.c | 44 ++++++- src/iec61850/server/model/dynamic_model.c | 115 ++++++++++++++++++ src/iec61850/server/model/model.c | 14 --- .../drivers/sqlite/log_storage_sqlite.c | 9 +- src/logging/logging_api.h | 10 +- src/mms/iso_mms/server/mms_domain.c | 4 - .../iso_mms/server/mms_get_namelist_service.c | 4 + src/mms/iso_mms/server/mms_journal_service.c | 7 +- src/version.rc.in | 20 +++ src/vs/libiec61850-wo-goose.def | 18 ++- src/vs/libiec61850.def | 17 +++ third_party/cmake/modules/Findsqlite.cmake | 48 ++++++++ 43 files changed, 596 insertions(+), 93 deletions(-) create mode 100644 examples/server_example_logging/Makefile.sqliteStatic create mode 100644 examples/server_example_logging/README create mode 100644 src/version.rc.in create mode 100644 third_party/cmake/modules/Findsqlite.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a24cbc3..30066a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ set(LIB_VERSION_MAJOR "0") set(LIB_VERSION_MINOR "9") set(LIB_VERSION_PATCH "2") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/third_party/cmake/modules/") + # feature checks include(CheckLibraryExists) 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_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) # 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_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_ACTIVATE_TCP_KEEPALIVE "Activate TCP keepalive" ON) @@ -68,6 +72,7 @@ include_directories( src/mms/inc src/mms/inc_private src/mms/iso_mms/asn1c + src/logging ) set(API_HEADERS @@ -102,6 +107,7 @@ set(API_HEADERS src/goose/goose_publisher.h src/sampled_values/sv_subscriber.h src/sampled_values/sv_publisher.h + src/logging/logging_api.h ) IF(MSVC) diff --git a/config/stack_config.h b/config/stack_config.h index 5cbdecb..ae1a58d 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -156,10 +156,10 @@ /* include support for IEC 61850 log services */ #define CONFIG_IEC61850_LOG_SERVICE 1 -/* default results for MMS identify service */ -#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" -#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" -#define CONFIG_DEFAULT_MMS_REVISION "0.9.2" +/* overwrite default results for MMS identify service */ +//#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" +//#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" +//#define CONFIG_DEFAULT_MMS_REVISION "0.9.2" /* MMS virtual file store base path - where file services are looking for files */ #define CONFIG_VIRTUAL_FILESTORE_BASEPATH "./vmd-filestore/" diff --git a/config/stack_config.h.cmake b/config/stack_config.h.cmake index d169816..78bf6f8 100644 --- a/config/stack_config.h.cmake +++ b/config/stack_config.h.cmake @@ -142,6 +142,9 @@ /* default reservation time of a setting group control block in s */ #define CONFIG_IEC61850_SG_RESVTMS 100 +/* include support for IEC 61850 log services */ +#cmakedefine01 CONFIG_IEC61850_LOG_SERVICE + /* default results for MMS identify service */ #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" #define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d5be930..9337d69 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(server_example_complex_array) add_subdirectory(server_example_threadless) add_subdirectory(server_example_61400_25) add_subdirectory(server_example_setting_groups) +add_subdirectory(server_example_logging) add_subdirectory(iec61850_client_example1) add_subdirectory(iec61850_client_example2) add_subdirectory(iec61850_client_example3) diff --git a/examples/goose_subscriber/goose_subscriber_example.c b/examples/goose_subscriber/goose_subscriber_example.c index 4295f47..a3ac574 100644 --- a/examples/goose_subscriber/goose_subscriber_example.c +++ b/examples/goose_subscriber/goose_subscriber_example.c @@ -12,7 +12,7 @@ #include #include #include - +#include static int running = 1; @@ -28,7 +28,7 @@ gooseListener(GooseSubscriber subscriber, void* parameter) printf(" stNum: %u sqNum: %u\n", GooseSubscriber_getStNum(subscriber), GooseSubscriber_getSqNum(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); diff --git a/examples/iec61850_9_2_LE_example/static_model.c b/examples/iec61850_9_2_LE_example/static_model.c index 5962f83..ada63aa 100644 --- a/examples/iec61850_9_2_LE_example/static_model.c +++ b/examples/iec61850_9_2_LE_example/static_model.c @@ -947,6 +947,8 @@ SVControlBlock iedModel_MUnn_LLN0_smv0 = {&iedModel_MUnn_LLN0, "MSVCB01", "xxxxM + + IedModel iedModel = { "TEMPLATE", &iedModel_MUnn, @@ -955,6 +957,8 @@ IedModel iedModel = { NULL, &iedModel_MUnn_LLN0_smv0, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/mms_utility/mms_utility.c b/examples/mms_utility/mms_utility.c index b158f63..28d4379 100644 --- a/examples/mms_utility/mms_utility.c +++ b/examples/mms_utility/mms_utility.c @@ -212,21 +212,6 @@ int main(int argc, char** argv) { char* name = (char*) element->data; 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); diff --git a/examples/server_example1/static_model.c b/examples/server_example1/static_model.c index 3f4b234..f4bb1e6 100644 --- a/examples/server_example1/static_model.c +++ b/examples/server_example1/static_model.c @@ -1596,6 +1596,8 @@ ReportControlBlock iedModel_Device1_LLN0_report0 = {&iedModel_Device1_LLN0, "LLN + + IedModel iedModel = { "SampleIED", &iedModel_Device1, @@ -1604,6 +1606,8 @@ IedModel iedModel = { NULL, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example2/static_model.c b/examples/server_example2/static_model.c index 2e935ca..91d0dcb 100644 --- a/examples/server_example2/static_model.c +++ b/examples/server_example2/static_model.c @@ -3586,6 +3586,8 @@ ReportControlBlock iedModel_Inverter_LLN0_report0 = {&iedModel_Inverter_LLN0, "r + + IedModel iedModel = { "ied1", &iedModel_Inverter, @@ -3594,6 +3596,8 @@ IedModel iedModel = { NULL, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example3/static_model.c b/examples/server_example3/static_model.c index d28f3ab..07b5b4a 100644 --- a/examples/server_example3/static_model.c +++ b/examples/server_example3/static_model.c @@ -1957,8 +1957,8 @@ ReportControlBlock iedModel_GenericIO_LLN0_report6 = {&iedModel_GenericIO_LLN0, extern LogControlBlock iedModel_GenericIO_LLN0_lcb0; extern LogControlBlock iedModel_GenericIO_LLN0_lcb1; -LogControlBlock iedModel_GenericIO_LLN0_lcb0 = {&iedModel_GenericIO_LLN0, "EventLog", "Events", "EventLog", 19, 0, true, true, &iedModel_GenericIO_LLN0_lcb1}; -LogControlBlock iedModel_GenericIO_LLN0_lcb1 = {&iedModel_GenericIO_LLN0, "GeneralLog", "", "", 19, 0, true, true, NULL}; +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", NULL, NULL, 3, 0, true, true, NULL}; extern Log iedModel_GenericIO_LLN0_log0; extern Log iedModel_GenericIO_LLN0_log1; diff --git a/examples/server_example4/static_model.c b/examples/server_example4/static_model.c index c2c99bf..bf02f9d 100644 --- a/examples/server_example4/static_model.c +++ b/examples/server_example4/static_model.c @@ -1779,6 +1779,8 @@ ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, + + IedModel iedModel = { "simpleIO", &iedModel_GenericIO, @@ -1787,6 +1789,8 @@ IedModel iedModel = { NULL, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example5/static_model.c b/examples/server_example5/static_model.c index 2e935ca..91d0dcb 100644 --- a/examples/server_example5/static_model.c +++ b/examples/server_example5/static_model.c @@ -3586,6 +3586,8 @@ ReportControlBlock iedModel_Inverter_LLN0_report0 = {&iedModel_Inverter_LLN0, "r + + IedModel iedModel = { "ied1", &iedModel_Inverter, @@ -3594,6 +3596,8 @@ IedModel iedModel = { NULL, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example_61400_25/static_model.c b/examples/server_example_61400_25/static_model.c index b34a03f..3f18092 100644 --- a/examples/server_example_61400_25/static_model.c +++ b/examples/server_example_61400_25/static_model.c @@ -4134,6 +4134,8 @@ DataAttribute iedModel_WTG_WTUR1_SetTurOp_cmAcs = { + + IedModel iedModel = { "WIND", &iedModel_WTG, @@ -4142,6 +4144,8 @@ IedModel iedModel = { NULL, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example_complex_array/static_model.c b/examples/server_example_complex_array/static_model.c index 3bc9396..7600619 100644 --- a/examples/server_example_complex_array/static_model.c +++ b/examples/server_example_complex_array/static_model.c @@ -544,6 +544,8 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_frequency = { + + IedModel iedModel = { "test", &iedModel_ComplexArray, @@ -552,6 +554,8 @@ IedModel iedModel = { NULL, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example_control/static_model.c b/examples/server_example_control/static_model.c index b538b20..6921b4f 100644 --- a/examples/server_example_control/static_model.c +++ b/examples/server_example_control/static_model.c @@ -3874,6 +3874,8 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind4_t = { + + IedModel iedModel = { "simpleIO", &iedModel_GenericIO, @@ -3882,6 +3884,8 @@ IedModel iedModel = { NULL, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example_goose/static_model.c b/examples/server_example_goose/static_model.c index 69df5e7..4c3d6c9 100644 --- a/examples/server_example_goose/static_model.c +++ b/examples/server_example_goose/static_model.c @@ -1909,6 +1909,8 @@ GSEControlBlock iedModel_GenericIO_LLN0_gse1 = {&iedModel_GenericIO_LLN0, "gcbAn + + IedModel iedModel = { "simpleIO", &iedModel_GenericIO, @@ -1917,6 +1919,8 @@ IedModel iedModel = { &iedModel_GenericIO_LLN0_gse0, NULL, NULL, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example_logging/Makefile.sqliteStatic b/examples/server_example_logging/Makefile.sqliteStatic new file mode 100644 index 0000000..65ff899 --- /dev/null +++ b/examples/server_example_logging/Makefile.sqliteStatic @@ -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) + + diff --git a/examples/server_example_logging/README b/examples/server_example_logging/README new file mode 100644 index 0000000..d82ecf4 --- /dev/null +++ b/examples/server_example_logging/README @@ -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. + diff --git a/examples/server_example_logging/server_example_logging.c b/examples/server_example_logging/server_example_logging.c index 76c71d8..7690725 100644 --- a/examples/server_example_logging/server_example_logging.c +++ b/examples/server_example_logging/server_example_logging.c @@ -17,6 +17,8 @@ #include "logging_api.h" +LogStorage SqliteLogStorage_createInstance(const char*); + /* import IEC 61850 device model created from SCL-File */ 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_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. */ IedServer_start(iedServer, 102); diff --git a/examples/server_example_setting_groups/static_model.c b/examples/server_example_setting_groups/static_model.c index 2c10dc4..53fdbb3 100644 --- a/examples/server_example_setting_groups/static_model.c +++ b/examples/server_example_setting_groups/static_model.c @@ -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}; + + IedModel iedModel = { "DEMO", &iedModel_PROT, @@ -1116,6 +1118,8 @@ IedModel iedModel = { NULL, NULL, &iedModel_PROT_LLN0_sgcb, + NULL, + NULL, initializeValues }; diff --git a/examples/server_example_threadless/static_model.c b/examples/server_example_threadless/static_model.c index 1fdf97c..4f37bde 100644 --- a/examples/server_example_threadless/static_model.c +++ b/examples/server_example_threadless/static_model.c @@ -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 = { "simpleIO", @@ -1860,6 +1864,8 @@ IedModel iedModel = { NULL, NULL, NULL, + &iedModel_GenericIO_LLN0_lcb0, + NULL, initializeValues }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e9c60fb..c126643 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,6 +76,8 @@ set (lib_common_SRCS ./iec61850/server/mms_mapping/reporting.c ./iec61850/server/mms_mapping/mms_goose.c ./iec61850/server/mms_mapping/mms_sv.c +./iec61850/server/mms_mapping/logging.c +./logging/log_storage.c ) set (lib_asn1c_SRCS diff --git a/src/common/inc/libiec61850_platform_includes.h b/src/common/inc/libiec61850_platform_includes.h index d2639c3..97ae275 100644 --- a/src/common/inc/libiec61850_platform_includes.h +++ b/src/common/inc/libiec61850_platform_includes.h @@ -15,7 +15,7 @@ #include "platform_endian.h" -#define LIBIEC61850_VERSION "0.9.1" +#define LIBIEC61850_VERSION "0.9.2" #ifndef CONFIG_DEFAULT_MMS_VENDOR_NAME #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" diff --git a/src/iec61850/client/client_report.c b/src/iec61850/client/client_report.c index 20cc3c1..a0b7c8a 100644 --- a/src/iec61850/client/client_report.c +++ b/src/iec61850/client/client_report.c @@ -31,6 +31,8 @@ #include "libiec61850_platform_includes.h" +#include + struct sClientReport { ReportCallbackFunction callback; @@ -405,7 +407,7 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value) matchingReport->timestamp = MmsValue_getBinaryTimeAsUtcMs(timeStampValue); 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++; diff --git a/src/iec61850/client/ied_connection.c b/src/iec61850/client/ied_connection.c index e6c46d1..3b87f4e 100644 --- a/src/iec61850/client/ied_connection.c +++ b/src/iec61850/client/ied_connection.c @@ -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 /**/ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error, const char* logicalNodeReference, ACSIClass acsiClass) @@ -1317,12 +1367,6 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error, return NULL; } - if (self->logicalDevices == NULL) - IedConnection_getDeviceModelFromServer(self, error); - - if (*error != IED_ERROR_OK) - return NULL; - char lnRefCopy[130]; strncpy(lnRefCopy, logicalNodeReference, 129); @@ -1341,6 +1385,16 @@ IedConnection_getLogicalNodeDirectory(IedConnection self, IedClientError* error, 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 */ LinkedList device = LinkedList_getNext(self->logicalDevices); diff --git a/src/iec61850/inc/iec61850_dynamic_model.h b/src/iec61850/inc/iec61850_dynamic_model.h index 967c764..bb82faa 100644 --- a/src/iec61850/inc/iec61850_dynamic_model.h +++ b/src/iec61850/inc/iec61850_dynamic_model.h @@ -146,7 +146,7 @@ DataAttribute_create(const char* name, ModelNode* parent, DataAttributeType type * \param parent the parent LN. * \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 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 * \param confRef the configuration revision * \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* 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) * diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h index 969b35d..961e640 100644 --- a/src/iec61850/inc/iec61850_model.h +++ b/src/iec61850/inc/iec61850_model.h @@ -517,9 +517,6 @@ 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); diff --git a/src/iec61850/inc_private/ied_server_private.h b/src/iec61850/inc_private/ied_server_private.h index d2ae3ae..c32e43e 100644 --- a/src/iec61850/inc_private/ied_server_private.h +++ b/src/iec61850/inc_private/ied_server_private.h @@ -42,6 +42,7 @@ struct sIedServer MmsMapping* mmsMapping; LinkedList clientConnections; uint8_t writeAccessPolicies; + bool running; }; diff --git a/src/iec61850/inc_private/logging.h b/src/iec61850/inc_private/logging.h index 365f7a0..ea3793d 100644 --- a/src/iec61850/inc_private/logging.h +++ b/src/iec61850/inc_private/logging.h @@ -48,6 +48,7 @@ typedef struct { DataSet* dataSet; char* dataSetRef; + bool isDynamicDataSet; LogicalNode* logicalNode; MmsDomain* domain; diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index 7dd9eec..f2dc0b8 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -404,6 +404,8 @@ IedServer_create(IedModel* iedModel) self->model = iedModel; + // self->running = false; /* not required due to CALLOC */ + self->mmsMapping = MmsMapping_create(iedModel); self->mmsDevice = MmsMapping_getMmsDeviceModel(self->mmsMapping); @@ -445,6 +447,16 @@ IedServer_create(IedModel* iedModel) void 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); IsoServer_destroy(self->isoServer); @@ -525,17 +537,22 @@ singleThreadedServerThread(void* parameter) void IedServer_start(IedServer self, int tcpPort) { + if (self->running == false) { + #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 - MmsServer_startListening(self->mmsServer, tcpPort); - MmsMapping_startEventWorkerThread(self->mmsMapping); + MmsServer_startListening(self->mmsServer, tcpPort); + MmsMapping_startEventWorkerThread(self->mmsMapping); #endif + + self->running = true; + } } #endif @@ -558,13 +575,17 @@ IedServer_getDataModel(IedServer self) void IedServer_stop(IedServer self) { - MmsMapping_stopEventWorkerThread(self->mmsMapping); + if (self->running) { + self->running = false; + + MmsMapping_stopEventWorkerThread(self->mmsMapping); #if (CONFIG_MMS_SINGLE_THREADED == 1) - MmsServer_stopListeningThreadless(self->mmsServer); + MmsServer_stopListeningThreadless(self->mmsServer); #else - MmsServer_stopListening(self->mmsServer); + MmsServer_stopListening(self->mmsServer); #endif + } } #endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */ @@ -572,7 +593,10 @@ IedServer_stop(IedServer self) void IedServer_startThreadless(IedServer self, int tcpPort) { - MmsServer_startListeningThreadless(self->mmsServer, tcpPort); + if (self->running == false) { + MmsServer_startListeningThreadless(self->mmsServer, tcpPort); + self->running = true; + } } int @@ -590,7 +614,11 @@ IedServer_processIncomingData(IedServer self) void IedServer_stopThreadless(IedServer self) { - MmsServer_stopListeningThreadless(self->mmsServer); + if (self->running) { + self->running = false; + + MmsServer_stopListeningThreadless(self->mmsServer); + } } void diff --git a/src/iec61850/server/mms_mapping/logging.c b/src/iec61850/server/mms_mapping/logging.c index 70d6138..a7b6ad5 100644 --- a/src/iec61850/server/mms_mapping/logging.c +++ b/src/iec61850/server/mms_mapping/logging.c @@ -35,6 +35,8 @@ #include "mms_mapping_internal.h" #include "mms_value_internal.h" +#include "logging_api.h" + #if (CONFIG_IEC61850_LOG_SERVICE == 1) LogInstance* @@ -74,7 +76,7 @@ LogInstance_logSingleData(LogInstance* self, const char* dataRef, MmsValue* valu self->locked = true; - //if (DEBUG_IED_SERVER) + if (DEBUG_IED_SERVER) printf("IED_SERVER: Log value - dataRef: %s flag: %i\n", dataRef, flag); 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); - uint8_t* data = GLOBAL_MALLOC(dataSize); + uint8_t* data = (uint8_t*) GLOBAL_MALLOC(dataSize); 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); - uint8_t* data = GLOBAL_MALLOC(dataSize); + uint8_t* data = (uint8_t*) GLOBAL_MALLOC(dataSize); MmsValue_encodeMmsData(value, data, 0, true); @@ -171,6 +173,7 @@ LogControl_create(LogicalNode* parentLN, MmsMapping* mmsMapping) self->enabled = false; self->dataSet = NULL; + self->isDynamicDataSet = false; self->triggerOps = 0; self->logicalNode = parentLN; self->mmsMapping = mmsMapping; @@ -207,16 +210,14 @@ static void prepareLogControl(LogControl* logControl) { if (logControl->dataSetRef == NULL) { - printf(" no data set specified!\n"); + logControl->enabled = false; return; } DataSet* dataSet = IedModel_lookupDataSet(logControl->mmsMapping->model, logControl->dataSetRef); - if (dataSet == NULL) { - printf(" data set (%s) not found!\n", logControl->dataSetRef); + if (dataSet == NULL) return; - } else logControl->dataSet = dataSet; } @@ -322,7 +323,7 @@ getLogInstanceByLogRef(MmsMapping* self, const char* logRef) while (instance != NULL) { - LogInstance* logInstance = LinkedList_getData(instance); + LogInstance* logInstance = (LogInstance*) LinkedList_getData(instance); 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 LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, MmsValue* value, MmsServerConnection connection) @@ -460,7 +473,6 @@ LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* doma if (logControl->enabled == false) { /* check if datSet is valid or NULL/empty */ - const char* dataSetRef = MmsValue_toString(value); if (strlen(dataSetRef) == 0) { @@ -470,16 +482,51 @@ LIBIEC61850_LOG_SVC_writeAccessLogControlBlock(MmsMapping* self, MmsDomain* doma else { 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 (DEBUG_IED_SERVER) printf("IED_SERVER: data set (%s) not found!\n", logControl->dataSetRef); return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; } - else { - logControl->dataSet = dataSet; - updateValue = true; - } } + + } else return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; @@ -589,7 +636,11 @@ createTrgOps(LogControlBlock* logControlBlock) { return trgOps; } - +static void +LogControl_updateLogEna(LogControl* self) +{ + MmsValue_setBoolean(MmsValue_getElement(self->mmsValue, 0), self->enabled); +} static MmsVariableSpecification* createLogControlBlock(MmsMapping* self, LogControlBlock* logControlBlock, @@ -743,6 +794,8 @@ createLogControlBlock(MmsMapping* self, LogControlBlock* logControlBlock, if (logControl->enabled) enableLogging(logControl); + LogControl_updateLogEna(logControl); + return lcb; } @@ -871,7 +924,7 @@ MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logSto MmsJournal mmsJournal = NULL; - char* logName = strchr(logRef, '/'); + const char* logName = strchr(logRef, '/'); if (logName != NULL) { logName += 1; diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index bed90c8..4a56618 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -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) { if (rc->dataSet->logicalDeviceName == NULL) { 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; diff --git a/src/iec61850/server/model/dynamic_model.c b/src/iec61850/server/model/dynamic_model.c index 206e7b8..6482c46 100644 --- a/src/iec61850/server/model/dynamic_model.c +++ b/src/iec61850/server/model/dynamic_model.c @@ -58,6 +58,10 @@ IedModel_create(const char* name/*, MemoryAllocator allocator*/) self->sgcbs = NULL; + self->lcbs = NULL; + + self->logs = NULL; + self->initializer = iedModel_emptyVariableInitializer; 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 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 LogicalNode_addReportControlBlock(LogicalNode* self, ReportControlBlock* rcb) { @@ -743,6 +836,28 @@ IedModel_destroy(IedModel* model) 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 */ diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c index b6ced89..b2998ec 100644 --- a/src/iec61850/server/model/model.c +++ b/src/iec61850/server/model/model.c @@ -409,20 +409,6 @@ 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) { diff --git a/src/logging/drivers/sqlite/log_storage_sqlite.c b/src/logging/drivers/sqlite/log_storage_sqlite.c index 867e0f0..7ef5417 100644 --- a/src/logging/drivers/sqlite/log_storage_sqlite.c +++ b/src/logging/drivers/sqlite/log_storage_sqlite.c @@ -166,7 +166,8 @@ exit_with_error: static uint64_t 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); @@ -269,8 +270,8 @@ getEntryData(LogStorage self, uint64_t entryID, LogEntryDataCallback entryDataCa while ((rc = sqlite3_step(instanceData->getEntryData)) == SQLITE_ROW) { - const char* dataRef = sqlite3_column_text(instanceData->getEntryData, 0); - const uint8_t* data = sqlite3_column_blob(instanceData->getEntryData, 1); + const char* dataRef = (const char*) sqlite3_column_text(instanceData->getEntryData, 0); + uint8_t* data = (uint8_t*) sqlite3_column_blob(instanceData->getEntryData, 1); int dataSize = sqlite3_column_bytes(instanceData->getEntryData, 1); 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; while((rc = sqlite3_step(instanceData->getEntriesWithRange)) == SQLITE_ROW) { - int col; uint64_t entryID = sqlite3_column_int64(instanceData->getEntriesWithRange, 0); uint64_t timestamp = sqlite3_column_int64(instanceData->getEntriesWithRange, 1); @@ -412,7 +412,6 @@ SqliteLogStorage_getEntriesAfter(LogStorage self, uint64_t startingTime, uint64_ bool sendFinalEvent = true; while ((rc = sqlite3_step(instanceData->getEntriesAfter)) == SQLITE_ROW) { - int col; uint64_t entryID = sqlite3_column_int64(instanceData->getEntriesAfter, 0); uint64_t timestamp = sqlite3_column_int64(instanceData->getEntriesAfter, 1); diff --git a/src/logging/logging_api.h b/src/logging/logging_api.h index 726e25f..92f77c5 100644 --- a/src/logging/logging_api.h +++ b/src/logging/logging_api.h @@ -24,6 +24,10 @@ #ifndef LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ #define LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include #include @@ -37,7 +41,7 @@ typedef struct sLogStorage* LogStorage; */ 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 { @@ -82,4 +86,8 @@ LogStorage_getOldestAndNewestEntries(LogStorage self, uint64_t* newEntry, uint64 void LogStorage_destroy(LogStorage self); +#ifdef __cplusplus +} +#endif + #endif /* LIBIEC61850_SRC_LOGGING_LOGGING_API_H_ */ diff --git a/src/mms/iso_mms/server/mms_domain.c b/src/mms/iso_mms/server/mms_domain.c index ca54284..689fcc0 100644 --- a/src/mms/iso_mms/server/mms_domain.c +++ b/src/mms/iso_mms/server/mms_domain.c @@ -76,8 +76,6 @@ MmsDomain_getName(MmsDomain* self) void MmsDomain_addJournal(MmsDomain* self, const char* name) { - printf("CREATE JOURNAL\n"); - if (self->journals == NULL) self->journals = LinkedList_create(); @@ -96,8 +94,6 @@ MmsDomain_getJournal(MmsDomain* self, const char* name) MmsJournal mmsJournal = (MmsJournal) LinkedList_getData(journal); - printf(" MMS journal: %s (%s)\n", mmsJournal->name, name); - if (strcmp(mmsJournal->name, name) == 0) return mmsJournal; diff --git a/src/mms/iso_mms/server/mms_get_namelist_service.c b/src/mms/iso_mms/server/mms_get_namelist_service.c index e90c4f1..48e3182 100644 --- a/src/mms/iso_mms/server/mms_get_namelist_service.c +++ b/src/mms/iso_mms/server/mms_get_namelist_service.c @@ -538,6 +538,10 @@ mmsServer_handleGetNameListRequest( if (nameList == NULL) mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { +#if (CONFIG_MMS_SORT_NAME_LIST == 1) + StringUtils_sortList(nameList); +#endif + createNameListResponse(connection, invokeId, nameList, response, continueAfterId); LinkedList_destroyStatic(nameList); } diff --git a/src/mms/iso_mms/server/mms_journal_service.c b/src/mms/iso_mms/server/mms_journal_service.c index e1b3d29..c055f5e 100644 --- a/src/mms/iso_mms/server/mms_journal_service.c +++ b/src/mms/iso_mms/server/mms_journal_service.c @@ -68,7 +68,7 @@ entryCallback(void* parameter, uint64_t timestamp, uint64_t entryID, bool moreFo JournalEncoder encoder = (JournalEncoder) parameter; if (moreFollow) { - //printf("Encode entry ID:%" PRIu64 " timestamp:%" PRIu64 "\n", entryID, timestamp); + if (encoder->moreFollows) { printf("entryCallback return false\n"); return false; @@ -128,7 +128,7 @@ entryDataCallback (void* parameter, const char* dataRef, uint8_t* data, int data uint32_t totalLen = firstVariableLen + secondVariableLen; - if ((bufPos + totalLen) > encoder->maxSize) { + if ((int) (bufPos + totalLen) > encoder->maxSize) { encoder->moreFollows = true; encoder->bufPos = encoder->currentEntryBufPos; /* remove last entry */ return false; @@ -241,8 +241,6 @@ mmsServer_handleReadJournalRequest( uint32_t invokeId, ByteBuffer* response) { - printf("READ-JOURNAL\n"); - char domainId[65]; char logName[65]; uint8_t entryIdBuf[64]; /* maximum size of entry id is 64 bytes! */ @@ -276,7 +274,6 @@ mmsServer_handleReadJournalRequest( case 0xa0: /* journalName */ { - uint8_t objectIdTag = requestBuffer[bufPos++]; bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos); diff --git a/src/version.rc.in b/src/version.rc.in new file mode 100644 index 0000000..377bdc7 --- /dev/null +++ b/src/version.rc.in @@ -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 diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def index acec320..72f0779 100644 --- a/src/vs/libiec61850-wo-goose.def +++ b/src/vs/libiec61850-wo-goose.def @@ -528,4 +528,20 @@ EXPORTS MmsValue_encodeMmsData ControlObjectClient_setInterlockCheck 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 diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def index d3322ec..9441519 100644 --- a/src/vs/libiec61850.def +++ b/src/vs/libiec61850.def @@ -604,3 +604,20 @@ EXPORTS IedServer_updateVisibleStringAttributeValue ControlObjectClient_setInterlockCheck 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 diff --git a/third_party/cmake/modules/Findsqlite.cmake b/third_party/cmake/modules/Findsqlite.cmake new file mode 100644 index 0000000..cfdd566 --- /dev/null +++ b/third_party/cmake/modules/Findsqlite.cmake @@ -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) +