- 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
This commit is contained in:
parent
23e695dae8
commit
2b28c0fed3
43 changed files with 596 additions and 93 deletions
|
@ -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)
|
||||
|
|
|
@ -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/"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
34
examples/server_example_logging/Makefile.sqliteStatic
Normal file
34
examples/server_example_logging/Makefile.sqliteStatic
Normal file
|
@ -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)
|
||||
|
||||
|
8
examples/server_example_logging/README
Normal file
8
examples/server_example_logging/README
Normal file
|
@ -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"
|
||||
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "libiec61850_platform_includes.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
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++;
|
||||
|
|
|
@ -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*>*/
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ struct sIedServer
|
|||
MmsMapping* mmsMapping;
|
||||
LinkedList clientConnections;
|
||||
uint8_t writeAccessPolicies;
|
||||
bool running;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef struct {
|
|||
|
||||
DataSet* dataSet;
|
||||
char* dataSetRef;
|
||||
bool isDynamicDataSet;
|
||||
|
||||
LogicalNode* logicalNode;
|
||||
MmsDomain* domain;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#ifndef LIBIEC61850_SRC_LOGGING_LOGGING_API_H_
|
||||
#define LIBIEC61850_SRC_LOGGING_LOGGING_API_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.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 (*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_ */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
20
src/version.rc.in
Normal file
20
src/version.rc.in
Normal file
|
@ -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
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
48
third_party/cmake/modules/Findsqlite.cmake
vendored
Normal file
48
third_party/cmake/modules/Findsqlite.cmake
vendored
Normal file
|
@ -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…
Add table
Reference in a new issue