diff --git a/examples/iec61850_9_2_LE_example/CMakeLists.txt b/examples/iec61850_9_2_LE_example/CMakeLists.txt
new file mode 100644
index 00000000..994caae3
--- /dev/null
+++ b/examples/iec61850_9_2_LE_example/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(
+ .
+)
+
+set(server_example2_SRCS
+ server_example2.c
+ static_model.c
+)
+
+IF(WIN32)
+set_source_files_properties(${server_example2_SRCS}
+ PROPERTIES LANGUAGE CXX)
+ENDIF(WIN32)
+
+add_executable(server_example2
+ ${server_example2_SRCS}
+)
+
+target_link_libraries(server_example2
+ iec61850
+)
diff --git a/examples/iec61850_9_2_LE_example/Makefile b/examples/iec61850_9_2_LE_example/Makefile
new file mode 100644
index 00000000..3781758b
--- /dev/null
+++ b/examples/iec61850_9_2_LE_example/Makefile
@@ -0,0 +1,24 @@
+LIBIEC_HOME=../..
+
+PROJECT_BINARY_NAME = server_example2
+PROJECT_SOURCES = server_example2.c
+PROJECT_SOURCES += static_model.c
+
+PROJECT_ICD_FILE = complexModel.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
+
+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) $(LDFLAGS) $(LDLIBS)
+
+clean:
+ rm -f $(PROJECT_BINARY_NAME)
+
diff --git a/examples/iec61850_9_2_LE_example/server_example2.c b/examples/iec61850_9_2_LE_example/server_example2.c
new file mode 100644
index 00000000..662cf501
--- /dev/null
+++ b/examples/iec61850_9_2_LE_example/server_example2.c
@@ -0,0 +1,86 @@
+/*
+ * server_example2.c
+ *
+ * Copyright 2013 Michael Zillgith
+ *
+ * This file is part of libIEC61850.
+ *
+ * libIEC61850 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libIEC61850 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libIEC61850. If not, see .
+ *
+ * See COPYING file for the complete license text.
+ */
+
+#include "iec61850_server.h"
+#include "hal_thread.h"
+#include
+#include
+#include
+
+
+/* Include the generated header with the model access handles */
+#include "static_model.h"
+
+/* import IEC 61850 device model created from SCL-File */
+extern IedModel iedModel;
+
+static int running = 0;
+
+void sigint_handler(int signalId)
+{
+ running = 0;
+}
+
+int
+main(int argc, char** argv)
+{
+ IedServer iedServer = IedServer_create(&iedModel);
+
+ // TODO get stored values from persistent storage
+
+ // TODO set initial measurement and status values from process
+
+ /* MMS server will be instructed to start listening to client connections. */
+ IedServer_start(iedServer, 102);
+
+ if (!IedServer_isRunning(iedServer)) {
+ printf("Starting server failed! Exit.\n");
+ IedServer_destroy(iedServer);
+ exit(-1);
+ }
+
+ running = 1;
+
+ signal(SIGINT, sigint_handler);
+
+ float power = 500.f;
+
+ while (running) {
+
+ uint64_t timeval = Hal_getTimeInMs();
+
+ IedServer_unlockDataModel(iedServer);
+
+ power += 0.1f;
+
+ Thread_sleep(500);
+ }
+
+ /* stop MMS server - close TCP server socket and all client sockets */
+ IedServer_stop(iedServer);
+
+ /* Cleanup - free all resources */
+ IedServer_destroy(iedServer);
+
+ return 0;
+} /* main() */
diff --git a/examples/iec61850_9_2_LE_example/static_model.c b/examples/iec61850_9_2_LE_example/static_model.c
new file mode 100644
index 00000000..ecc29bfb
--- /dev/null
+++ b/examples/iec61850_9_2_LE_example/static_model.c
@@ -0,0 +1,1009 @@
+/*
+ * static_model.c
+ *
+ * automatically generated from sv.icd
+ */
+#include "static_model.h"
+
+static void initializeValues();
+
+extern DataSet iedModelds_MUnn_LLN0_PhsMeas1;
+
+
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda0;
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda1;
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda2;
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda3;
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda4;
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda5;
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda6;
+extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda7;
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda0 = {
+ "1",
+ false,
+ "TCTR$MX$Amp",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda1
+};
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda1 = {
+ "2",
+ false,
+ "TCTR$MX$Amp",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda2
+};
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda2 = {
+ "3",
+ false,
+ "TCTR$MX$Amp",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda3
+};
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda3 = {
+ "4",
+ false,
+ "TCTR$MX$Amp",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda4
+};
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda4 = {
+ "1",
+ false,
+ "TVTR$MX$Vol",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda5
+};
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda5 = {
+ "2",
+ false,
+ "TVTR$MX$Vol",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda6
+};
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda6 = {
+ "3",
+ false,
+ "TVTR$MX$Vol",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda7
+};
+
+DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda7 = {
+ "4",
+ false,
+ "TVTR$MX$Vol",
+ -1,
+ NULL,
+ NULL,
+ NULL
+};
+
+DataSet iedModelds_MUnn_LLN0_PhsMeas1 = {
+ "MUnn",
+ "LLN0$PhsMeas1",
+ 8,
+ &iedModelds_MUnn_LLN0_PhsMeas1_fcda0,
+ NULL
+};
+
+LogicalDevice iedModel_MUnn = {
+ LogicalDeviceModelType,
+ "MUnn",
+ (ModelNode*) &iedModel,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_LLN0
+};
+
+LogicalNode iedModel_MUnn_LLN0 = {
+ LogicalNodeModelType,
+ "LLN0",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TCTR1,
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod,
+};
+
+DataObject iedModel_MUnn_LLN0_Mod = {
+ DataObjectModelType,
+ "Mod",
+ (ModelNode*) &iedModel_MUnn_LLN0,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod_ctlVal,
+ 0
+};
+
+DataAttribute iedModel_MUnn_LLN0_Mod_ctlVal = {
+ DataAttributeModelType,
+ "ctlVal",
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod,
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod_stVal,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_LLN0_Mod_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod,
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_INT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_LLN0_Mod_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod,
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_LLN0_Mod_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_MUnn_LLN0_Mod,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TCTR1 = {
+ LogicalNodeModelType,
+ "TCTR1",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TCTR2,
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp,
+};
+
+DataObject iedModel_MUnn_TCTR1_Amp = {
+ DataObjectModelType,
+ "Amp",
+ (ModelNode*) &iedModel_MUnn_TCTR1,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TCTR1_Amp_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_q,
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR1_Amp_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR1_Amp_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR1_Amp_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_sVC,
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TCTR1_Amp_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TCTR2 = {
+ LogicalNodeModelType,
+ "TCTR2",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TCTR3,
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp,
+};
+
+DataObject iedModel_MUnn_TCTR2_Amp = {
+ DataObjectModelType,
+ "Amp",
+ (ModelNode*) &iedModel_MUnn_TCTR2,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TCTR2_Amp_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_q,
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR2_Amp_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR2_Amp_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR2_Amp_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_sVC,
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TCTR2_Amp_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TCTR3 = {
+ LogicalNodeModelType,
+ "TCTR3",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TCTR4,
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp,
+};
+
+DataObject iedModel_MUnn_TCTR3_Amp = {
+ DataObjectModelType,
+ "Amp",
+ (ModelNode*) &iedModel_MUnn_TCTR3,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TCTR3_Amp_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_q,
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR3_Amp_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR3_Amp_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR3_Amp_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_sVC,
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TCTR3_Amp_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TCTR4 = {
+ LogicalNodeModelType,
+ "TCTR4",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TVTR1,
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp,
+};
+
+DataObject iedModel_MUnn_TCTR4_Amp = {
+ DataObjectModelType,
+ "Amp",
+ (ModelNode*) &iedModel_MUnn_TCTR4,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TCTR4_Amp_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_q,
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR4_Amp_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR4_Amp_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp,
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR4_Amp_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_sVC,
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TCTR4_Amp_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TVTR1 = {
+ LogicalNodeModelType,
+ "TVTR1",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TVTR2,
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol,
+};
+
+DataObject iedModel_MUnn_TVTR1_Vol = {
+ DataObjectModelType,
+ "Vol",
+ (ModelNode*) &iedModel_MUnn_TVTR1,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TVTR1_Vol_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_q,
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR1_Vol_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR1_Vol_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR1_Vol_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_sVC,
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TVTR1_Vol_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TVTR2 = {
+ LogicalNodeModelType,
+ "TVTR2",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TVTR3,
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol,
+};
+
+DataObject iedModel_MUnn_TVTR2_Vol = {
+ DataObjectModelType,
+ "Vol",
+ (ModelNode*) &iedModel_MUnn_TVTR2,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TVTR2_Vol_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_q,
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR2_Vol_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR2_Vol_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR2_Vol_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_sVC,
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TVTR2_Vol_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TVTR3 = {
+ LogicalNodeModelType,
+ "TVTR3",
+ (ModelNode*) &iedModel_MUnn,
+ (ModelNode*) &iedModel_MUnn_TVTR4,
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol,
+};
+
+DataObject iedModel_MUnn_TVTR3_Vol = {
+ DataObjectModelType,
+ "Vol",
+ (ModelNode*) &iedModel_MUnn_TVTR3,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TVTR3_Vol_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_q,
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR3_Vol_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR3_Vol_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR3_Vol_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_sVC,
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TVTR3_Vol_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_MUnn_TVTR4 = {
+ LogicalNodeModelType,
+ "TVTR4",
+ (ModelNode*) &iedModel_MUnn,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol,
+};
+
+DataObject iedModel_MUnn_TVTR4_Vol = {
+ DataObjectModelType,
+ "Vol",
+ (ModelNode*) &iedModel_MUnn_TVTR4,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_instMag,
+ 0
+};
+
+DataAttribute iedModel_MUnn_TVTR4_Vol_instMag = {
+ DataAttributeModelType,
+ "instMag",
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_q,
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_instMag_i,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR4_Vol_instMag_i = {
+ DataAttributeModelType,
+ "i",
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_instMag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_INT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR4_Vol_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol,
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_sVC,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR4_Vol_sVC = {
+ DataAttributeModelType,
+ "sVC",
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol,
+ NULL,
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor = {
+ DataAttributeModelType,
+ "scaleFactor",
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_sVC,
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_sVC_offset,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_offset = {
+ DataAttributeModelType,
+ "offset",
+ (ModelNode*) &iedModel_MUnn_TVTR4_Vol_sVC,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_FLOAT32,
+ 0,
+ NULL,
+ 0};
+
+
+
+extern SVControlBlock iedModel_MUnn_LLN0_smv0;
+
+static PhyComAddress iedModel_MUnn_LLN0_smv0_address = {
+ 4,
+ 1,
+ 4097,
+ {0x1, 0xc, 0xcd, 0x4, 0x0, 0x1}
+};
+
+SVControlBlock iedModel_MUnn_LLN0_smv0 = {&iedModel_MUnn_LLN0, "MSVCB01", "xxxxMUnn01", "PhsMeas1", 2, 0, 80, 1, &iedModel_MUnn_LLN0_smv0_address, true, 1, NULL};
+
+
+
+
+IedModel iedModel = {
+ "TEMPLATE",
+ &iedModel_MUnn,
+ &iedModelds_MUnn_LLN0_PhsMeas1,
+ NULL,
+ NULL,
+ &iedModel_MUnn_LLN0_smv0,
+ NULL,
+ initializeValues
+};
+
+static void
+initializeValues()
+{
+
+iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.001);
+
+iedModel_MUnn_TCTR1_Amp_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+
+iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.001);
+
+iedModel_MUnn_TCTR2_Amp_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+
+iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.001);
+
+iedModel_MUnn_TCTR3_Amp_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+
+iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.001);
+
+iedModel_MUnn_TCTR4_Amp_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+
+iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.01);
+
+iedModel_MUnn_TVTR1_Vol_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+
+iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.01);
+
+iedModel_MUnn_TVTR2_Vol_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+
+iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.01);
+
+iedModel_MUnn_TVTR3_Vol_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+
+iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor.mmsValue = MmsValue_newFloat(0.01);
+
+iedModel_MUnn_TVTR4_Vol_sVC_offset.mmsValue = MmsValue_newFloat(0.0);
+}
diff --git a/examples/iec61850_9_2_LE_example/static_model.h b/examples/iec61850_9_2_LE_example/static_model.h
new file mode 100644
index 00000000..f45de247
--- /dev/null
+++ b/examples/iec61850_9_2_LE_example/static_model.h
@@ -0,0 +1,161 @@
+/*
+ * static_model.h
+ *
+ * automatically generated from sv.icd
+ */
+
+#ifndef STATIC_MODEL_H_
+#define STATIC_MODEL_H_
+
+#include
+#include "iec61850_model.h"
+
+extern IedModel iedModel;
+extern LogicalDevice iedModel_MUnn;
+extern LogicalNode iedModel_MUnn_LLN0;
+extern DataObject iedModel_MUnn_LLN0_Mod;
+extern DataAttribute iedModel_MUnn_LLN0_Mod_ctlVal;
+extern DataAttribute iedModel_MUnn_LLN0_Mod_stVal;
+extern DataAttribute iedModel_MUnn_LLN0_Mod_q;
+extern DataAttribute iedModel_MUnn_LLN0_Mod_t;
+extern LogicalNode iedModel_MUnn_TCTR1;
+extern DataObject iedModel_MUnn_TCTR1_Amp;
+extern DataAttribute iedModel_MUnn_TCTR1_Amp_instMag;
+extern DataAttribute iedModel_MUnn_TCTR1_Amp_instMag_i;
+extern DataAttribute iedModel_MUnn_TCTR1_Amp_q;
+extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC;
+extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_offset;
+extern LogicalNode iedModel_MUnn_TCTR2;
+extern DataObject iedModel_MUnn_TCTR2_Amp;
+extern DataAttribute iedModel_MUnn_TCTR2_Amp_instMag;
+extern DataAttribute iedModel_MUnn_TCTR2_Amp_instMag_i;
+extern DataAttribute iedModel_MUnn_TCTR2_Amp_q;
+extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC;
+extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_offset;
+extern LogicalNode iedModel_MUnn_TCTR3;
+extern DataObject iedModel_MUnn_TCTR3_Amp;
+extern DataAttribute iedModel_MUnn_TCTR3_Amp_instMag;
+extern DataAttribute iedModel_MUnn_TCTR3_Amp_instMag_i;
+extern DataAttribute iedModel_MUnn_TCTR3_Amp_q;
+extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC;
+extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_offset;
+extern LogicalNode iedModel_MUnn_TCTR4;
+extern DataObject iedModel_MUnn_TCTR4_Amp;
+extern DataAttribute iedModel_MUnn_TCTR4_Amp_instMag;
+extern DataAttribute iedModel_MUnn_TCTR4_Amp_instMag_i;
+extern DataAttribute iedModel_MUnn_TCTR4_Amp_q;
+extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC;
+extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_offset;
+extern LogicalNode iedModel_MUnn_TVTR1;
+extern DataObject iedModel_MUnn_TVTR1_Vol;
+extern DataAttribute iedModel_MUnn_TVTR1_Vol_instMag;
+extern DataAttribute iedModel_MUnn_TVTR1_Vol_instMag_i;
+extern DataAttribute iedModel_MUnn_TVTR1_Vol_q;
+extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC;
+extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_offset;
+extern LogicalNode iedModel_MUnn_TVTR2;
+extern DataObject iedModel_MUnn_TVTR2_Vol;
+extern DataAttribute iedModel_MUnn_TVTR2_Vol_instMag;
+extern DataAttribute iedModel_MUnn_TVTR2_Vol_instMag_i;
+extern DataAttribute iedModel_MUnn_TVTR2_Vol_q;
+extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC;
+extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_offset;
+extern LogicalNode iedModel_MUnn_TVTR3;
+extern DataObject iedModel_MUnn_TVTR3_Vol;
+extern DataAttribute iedModel_MUnn_TVTR3_Vol_instMag;
+extern DataAttribute iedModel_MUnn_TVTR3_Vol_instMag_i;
+extern DataAttribute iedModel_MUnn_TVTR3_Vol_q;
+extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC;
+extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_offset;
+extern LogicalNode iedModel_MUnn_TVTR4;
+extern DataObject iedModel_MUnn_TVTR4_Vol;
+extern DataAttribute iedModel_MUnn_TVTR4_Vol_instMag;
+extern DataAttribute iedModel_MUnn_TVTR4_Vol_instMag_i;
+extern DataAttribute iedModel_MUnn_TVTR4_Vol_q;
+extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC;
+extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor;
+extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_offset;
+
+
+
+#define IEDMODEL_MUnn (&iedModel_MUnn)
+#define IEDMODEL_MUnn_LLN0 (&iedModel_MUnn_LLN0)
+#define IEDMODEL_MUnn_LLN0_Mod (&iedModel_MUnn_LLN0_Mod)
+#define IEDMODEL_MUnn_LLN0_Mod_ctlVal (&iedModel_MUnn_LLN0_Mod_ctlVal)
+#define IEDMODEL_MUnn_LLN0_Mod_stVal (&iedModel_MUnn_LLN0_Mod_stVal)
+#define IEDMODEL_MUnn_LLN0_Mod_q (&iedModel_MUnn_LLN0_Mod_q)
+#define IEDMODEL_MUnn_LLN0_Mod_t (&iedModel_MUnn_LLN0_Mod_t)
+#define IEDMODEL_MUnn_TCTR1 (&iedModel_MUnn_TCTR1)
+#define IEDMODEL_MUnn_TCTR1_Amp (&iedModel_MUnn_TCTR1_Amp)
+#define IEDMODEL_MUnn_TCTR1_Amp_instMag (&iedModel_MUnn_TCTR1_Amp_instMag)
+#define IEDMODEL_MUnn_TCTR1_Amp_instMag_i (&iedModel_MUnn_TCTR1_Amp_instMag_i)
+#define IEDMODEL_MUnn_TCTR1_Amp_q (&iedModel_MUnn_TCTR1_Amp_q)
+#define IEDMODEL_MUnn_TCTR1_Amp_sVC (&iedModel_MUnn_TCTR1_Amp_sVC)
+#define IEDMODEL_MUnn_TCTR1_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TCTR1_Amp_sVC_offset (&iedModel_MUnn_TCTR1_Amp_sVC_offset)
+#define IEDMODEL_MUnn_TCTR2 (&iedModel_MUnn_TCTR2)
+#define IEDMODEL_MUnn_TCTR2_Amp (&iedModel_MUnn_TCTR2_Amp)
+#define IEDMODEL_MUnn_TCTR2_Amp_instMag (&iedModel_MUnn_TCTR2_Amp_instMag)
+#define IEDMODEL_MUnn_TCTR2_Amp_instMag_i (&iedModel_MUnn_TCTR2_Amp_instMag_i)
+#define IEDMODEL_MUnn_TCTR2_Amp_q (&iedModel_MUnn_TCTR2_Amp_q)
+#define IEDMODEL_MUnn_TCTR2_Amp_sVC (&iedModel_MUnn_TCTR2_Amp_sVC)
+#define IEDMODEL_MUnn_TCTR2_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TCTR2_Amp_sVC_offset (&iedModel_MUnn_TCTR2_Amp_sVC_offset)
+#define IEDMODEL_MUnn_TCTR3 (&iedModel_MUnn_TCTR3)
+#define IEDMODEL_MUnn_TCTR3_Amp (&iedModel_MUnn_TCTR3_Amp)
+#define IEDMODEL_MUnn_TCTR3_Amp_instMag (&iedModel_MUnn_TCTR3_Amp_instMag)
+#define IEDMODEL_MUnn_TCTR3_Amp_instMag_i (&iedModel_MUnn_TCTR3_Amp_instMag_i)
+#define IEDMODEL_MUnn_TCTR3_Amp_q (&iedModel_MUnn_TCTR3_Amp_q)
+#define IEDMODEL_MUnn_TCTR3_Amp_sVC (&iedModel_MUnn_TCTR3_Amp_sVC)
+#define IEDMODEL_MUnn_TCTR3_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TCTR3_Amp_sVC_offset (&iedModel_MUnn_TCTR3_Amp_sVC_offset)
+#define IEDMODEL_MUnn_TCTR4 (&iedModel_MUnn_TCTR4)
+#define IEDMODEL_MUnn_TCTR4_Amp (&iedModel_MUnn_TCTR4_Amp)
+#define IEDMODEL_MUnn_TCTR4_Amp_instMag (&iedModel_MUnn_TCTR4_Amp_instMag)
+#define IEDMODEL_MUnn_TCTR4_Amp_instMag_i (&iedModel_MUnn_TCTR4_Amp_instMag_i)
+#define IEDMODEL_MUnn_TCTR4_Amp_q (&iedModel_MUnn_TCTR4_Amp_q)
+#define IEDMODEL_MUnn_TCTR4_Amp_sVC (&iedModel_MUnn_TCTR4_Amp_sVC)
+#define IEDMODEL_MUnn_TCTR4_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TCTR4_Amp_sVC_offset (&iedModel_MUnn_TCTR4_Amp_sVC_offset)
+#define IEDMODEL_MUnn_TVTR1 (&iedModel_MUnn_TVTR1)
+#define IEDMODEL_MUnn_TVTR1_Vol (&iedModel_MUnn_TVTR1_Vol)
+#define IEDMODEL_MUnn_TVTR1_Vol_instMag (&iedModel_MUnn_TVTR1_Vol_instMag)
+#define IEDMODEL_MUnn_TVTR1_Vol_instMag_i (&iedModel_MUnn_TVTR1_Vol_instMag_i)
+#define IEDMODEL_MUnn_TVTR1_Vol_q (&iedModel_MUnn_TVTR1_Vol_q)
+#define IEDMODEL_MUnn_TVTR1_Vol_sVC (&iedModel_MUnn_TVTR1_Vol_sVC)
+#define IEDMODEL_MUnn_TVTR1_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TVTR1_Vol_sVC_offset (&iedModel_MUnn_TVTR1_Vol_sVC_offset)
+#define IEDMODEL_MUnn_TVTR2 (&iedModel_MUnn_TVTR2)
+#define IEDMODEL_MUnn_TVTR2_Vol (&iedModel_MUnn_TVTR2_Vol)
+#define IEDMODEL_MUnn_TVTR2_Vol_instMag (&iedModel_MUnn_TVTR2_Vol_instMag)
+#define IEDMODEL_MUnn_TVTR2_Vol_instMag_i (&iedModel_MUnn_TVTR2_Vol_instMag_i)
+#define IEDMODEL_MUnn_TVTR2_Vol_q (&iedModel_MUnn_TVTR2_Vol_q)
+#define IEDMODEL_MUnn_TVTR2_Vol_sVC (&iedModel_MUnn_TVTR2_Vol_sVC)
+#define IEDMODEL_MUnn_TVTR2_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TVTR2_Vol_sVC_offset (&iedModel_MUnn_TVTR2_Vol_sVC_offset)
+#define IEDMODEL_MUnn_TVTR3 (&iedModel_MUnn_TVTR3)
+#define IEDMODEL_MUnn_TVTR3_Vol (&iedModel_MUnn_TVTR3_Vol)
+#define IEDMODEL_MUnn_TVTR3_Vol_instMag (&iedModel_MUnn_TVTR3_Vol_instMag)
+#define IEDMODEL_MUnn_TVTR3_Vol_instMag_i (&iedModel_MUnn_TVTR3_Vol_instMag_i)
+#define IEDMODEL_MUnn_TVTR3_Vol_q (&iedModel_MUnn_TVTR3_Vol_q)
+#define IEDMODEL_MUnn_TVTR3_Vol_sVC (&iedModel_MUnn_TVTR3_Vol_sVC)
+#define IEDMODEL_MUnn_TVTR3_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TVTR3_Vol_sVC_offset (&iedModel_MUnn_TVTR3_Vol_sVC_offset)
+#define IEDMODEL_MUnn_TVTR4 (&iedModel_MUnn_TVTR4)
+#define IEDMODEL_MUnn_TVTR4_Vol (&iedModel_MUnn_TVTR4_Vol)
+#define IEDMODEL_MUnn_TVTR4_Vol_instMag (&iedModel_MUnn_TVTR4_Vol_instMag)
+#define IEDMODEL_MUnn_TVTR4_Vol_instMag_i (&iedModel_MUnn_TVTR4_Vol_instMag_i)
+#define IEDMODEL_MUnn_TVTR4_Vol_q (&iedModel_MUnn_TVTR4_Vol_q)
+#define IEDMODEL_MUnn_TVTR4_Vol_sVC (&iedModel_MUnn_TVTR4_Vol_sVC)
+#define IEDMODEL_MUnn_TVTR4_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor)
+#define IEDMODEL_MUnn_TVTR4_Vol_sVC_offset (&iedModel_MUnn_TVTR4_Vol_sVC_offset)
+
+#endif /* STATIC_MODEL_H_ */
+
diff --git a/examples/iec61850_9_2_LE_example/sv.icd b/examples/iec61850_9_2_LE_example/sv.icd
new file mode 100644
index 00000000..78ade53b
--- /dev/null
+++ b/examples/iec61850_9_2_LE_example/sv.icd
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+ Station bus
+ 10
+
+
+ 10.0.0.2
+ 255.255.255.0
+ 10.0.0.1
+ 0001
+ 00000001
+ 0001
+
+
+
+
+ 1
+ 4
+ 01-0c-cd-04-00-01
+ 1001
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0.001
+
+
+0
+
+
+
+
+0.01
+
+
+0
+
+
+
+
+
diff --git a/examples/mms_utility/mms_utility.c b/examples/mms_utility/mms_utility.c
index b59d3337..51976a6f 100644
--- a/examples/mms_utility/mms_utility.c
+++ b/examples/mms_utility/mms_utility.c
@@ -15,6 +15,8 @@ print_help()
printf("-d show list of MMS domains\n");
printf("-i show server identity\n");
printf("-t show domain directory\n");
+ printf("-r read domain variable\n");
+ printf("-a specify domain for read or write command");
}
int main(int argc, char** argv) {
@@ -24,14 +26,18 @@ int main(int argc, char** argv) {
int maxPduSize = 65000;
char* domainName = NULL;
+ char* variableName = NULL;
int readDeviceList = 0;
int getDeviceDirectory = 0;
int identifyDevice = 0;
+ int readWriteHasDomain = 0;
+ int readVariable = 0;
+
int c;
- while ((c = getopt(argc, argv, "idh:p:l:t:")) != -1)
+ while ((c = getopt(argc, argv, "idh:p:l:t:a:r:")) != -1)
switch (c) {
case 'h':
hostname = copyString(optarg);
@@ -52,6 +58,15 @@ int main(int argc, char** argv) {
getDeviceDirectory = 1;
domainName = copyString(optarg);
break;
+ case 'a':
+ readWriteHasDomain = 1;
+ domainName = copyString(optarg);
+ break;
+ case 'r':
+ readVariable = 1;
+ variableName = copyString(optarg);
+ break;
+
default:
print_help();
return 0;
@@ -103,12 +118,39 @@ int main(int argc, char** argv) {
while ((element = LinkedList_getNext(element)) != NULL) {
char* name = (char*) element->data;
- if (strchr(name, '$') == NULL)
- printf(" %s\n", name);
+ printf(" %s\n", name);
}
}
+ if (readVariable) {
+ if (readWriteHasDomain) {
+ MmsValue* result = MmsConnection_readVariable(con, &error, domainName, variableName);
+
+ if (error != MMS_ERROR_NONE) {
+ printf("Reading variable failed: (ERROR %i)\n", error);
+ }
+ else {
+ printf("Read SUCCESS\n");
+
+
+ if (result != NULL) {
+ char outbuf[1024];
+
+ MmsValue_printToBuffer(result, outbuf, 1024);
+
+ printf("%s\n", outbuf);
+ }
+ else
+ printf("result: NULL\n");
+ }
+
+ }
+ else
+ printf("Reading VMD scope variable not yet supported!\n");
+ }
+
+
exit:
MmsConnection_destroy(con);
}
diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h
index 258c9b10..376593b0 100644
--- a/src/iec61850/inc/iec61850_model.h
+++ b/src/iec61850/inc/iec61850_model.h
@@ -1,7 +1,7 @@
/*
* model.h
*
- * Copyright 2013, 2014 Michael Zillgith
+ * Copyright 2013, 2014, 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
diff --git a/src/iec61850/inc_private/mms_sv.h b/src/iec61850/inc_private/mms_sv.h
index 4af77fe5..6f59a374 100644
--- a/src/iec61850/inc_private/mms_sv.h
+++ b/src/iec61850/inc_private/mms_sv.h
@@ -24,8 +24,20 @@
#ifndef LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_
#define LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_
+
+typedef struct sMmsSampledValueControlBlock* MmsSampledValueControlBlock;
+
+MmsSampledValueControlBlock
+MmsSampledValueControlBlock_create(void);
+
+void
+MmsSampledValueControlBlock_destroy(MmsSampledValueControlBlock self);
+
MmsVariableSpecification*
LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int svCount, bool unicast);
+MmsValue*
+LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig);
+
#endif /* LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_ */
diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c
index 7652650a..83a3a9ef 100644
--- a/src/iec61850/server/impl/ied_server.c
+++ b/src/iec61850/server/impl/ied_server.c
@@ -188,7 +188,16 @@ createMmsServerCache(IedServer self)
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
if ((strcmp(fcName, "BR") != 0) && (strcmp(fcName, "RP") != 0)
- && (strcmp(fcName, "GO") != 0))
+
+#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
+ && (strcmp(fcName, "GO") != 0)
+#endif
+
+#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
+ && (strcmp(fcName, "MS") != 0) && (strcmp(fcName, "US") != 0)
+#endif
+
+ )
{
char* variableName = createString(3, lnName, "$", fcName);
diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c
index 0a488866..7e873698 100644
--- a/src/iec61850/server/mms_mapping/mms_mapping.c
+++ b/src/iec61850/server/mms_mapping/mms_mapping.c
@@ -1,7 +1,7 @@
/*
* mms_mapping.c
*
- * Copyright 2013, 2014 Michael Zillgith
+ * Copyright 2013, 2014, 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -28,6 +28,7 @@
#include "stack_config.h"
#include "mms_goose.h"
+#include "mms_sv.h"
#include "reporting.h"
#include "control.h"
#include "ied_server_private.h"
@@ -1008,14 +1009,14 @@ createNamedVariableFromLogicalNode(MmsMapping* self, MmsDomain* domain,
/* Add MS and US named variables */
if (msvcbCount > 0) {
namedVariable->typeSpec.structure.elements[currentComponent] =
- LIBIEC61850_SV_creatSVControlBlocks(self, domain, logicalNode, msvcbCount, false);
+ LIBIEC61850_SV_createSVControlBlocks(self, domain, logicalNode, msvcbCount, false);
currentComponent++;
}
if (usvcbCount > 0) {
namedVariable->typeSpec.structure.elements[currentComponent] =
- LIBIEC61850_SV_creatSVControlBlocks(self, domain, logicalNode, msvcbCount, true);
+ LIBIEC61850_SV_createSVControlBlocks(self, domain, logicalNode, msvcbCount, true);
currentComponent++;
}
@@ -1243,7 +1244,7 @@ MmsMapping_destroy(MmsMapping* self)
#endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
- LinkedList_destroyDeep(self->svControls, (LinkedListValueDeleteFunction) MmsSvControlBlock_destroy);
+ LinkedList_destroyDeep(self->svControls, (LinkedListValueDeleteFunction) MmsSampledValueControlBlock_destroy);
#endif
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
@@ -1353,6 +1354,23 @@ isGooseControlBlock(char* separator)
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
+
+#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
+
+static bool
+isSampledValueControlBlock(char* separator)
+{
+ if (strncmp(separator + 1, "MS", 2) == 0)
+ return true;
+
+ if (strncmp(separator + 1, "US", 2) == 0)
+ return true;
+
+ return false;
+}
+
+#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
+
char*
MmsMapping_getNextNameElement(char* name)
{
@@ -1679,6 +1697,14 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
}
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
+#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
+ /* Sampled Value control block - MS/US */
+ if (isSampledValueControlBlock(separator)) {
+ //TODO handle write access to SVCB
+ }
+#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
+
+
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
/* Report control blocks - BR, RP */
if (isReportControlBlock(separator)) {
@@ -2075,6 +2101,7 @@ readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableI
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
+
static MmsValue*
mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection)
{
@@ -2100,14 +2127,23 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
}
#endif
- /* GOOSE control blocks - GO */
+
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
+ /* GOOSE control blocks - GO */
if (isGooseControlBlock(separator)) {
retValue = readAccessGooseControlBlock(self, domain, variableId);
goto exit_function;
}
#endif
+#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
+ /* Sampled Value control blocks - MS/US */
+ if (isSampledValueControlBlock(separator)) {
+ retValue = LIBIEC61850_SV_readAccessSampledValueControlBlock(self, domain, variableId);
+ goto exit_function;
+ }
+#endif
+
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
/* Report control blocks - BR, RP */
if (isReportControlBlock(separator)) {
diff --git a/src/iec61850/server/mms_mapping/mms_sv.c b/src/iec61850/server/mms_mapping/mms_sv.c
index 56e8674b..c4f1c1ce 100644
--- a/src/iec61850/server/mms_mapping/mms_sv.c
+++ b/src/iec61850/server/mms_mapping/mms_sv.c
@@ -30,10 +30,109 @@
#include "linked_list.h"
#include "array_list.h"
+#include "mms_sv.h"
+
#include "mms_mapping_internal.h"
+struct sMmsSampledValueControlBlock {
+ char* name;
+ bool svEna;
+
+ char* dstAddress;
+
+ MmsDomain* domain;
+ LogicalNode* logicalNode;
+
+ MmsVariableSpecification* mmsType;
+ MmsValue* mmsValue;
+
+ //MmsMapping* mmsMapping;
+};
+
+MmsSampledValueControlBlock
+MmsSampledValueControlBlock_create()
+{
+ MmsSampledValueControlBlock self = (MmsSampledValueControlBlock) GLOBAL_CALLOC(1, sizeof(struct sMmsSampledValueControlBlock));
+
+ return self;
+}
+
+
+void
+MmsSampledValueControlBlock_destroy(MmsSampledValueControlBlock self)
+{
+ MmsValue_delete(self->mmsValue);
+
+ GLOBAL_FREEMEM(self);
+}
+
+static MmsSampledValueControlBlock
+lookupSVCB(MmsMapping* self, MmsDomain* domain, char* lnName, char* objectName)
+{
+ LinkedList element = LinkedList_getNext(self->svControls);
+
+ while (element != NULL) {
+ MmsSampledValueControlBlock mmsSVCB = (MmsSampledValueControlBlock) element->data;
+
+ if (mmsSVCB->domain == domain) {
+ if (strcmp(mmsSVCB->logicalNode->name, lnName) == 0) {
+ if (strcmp(mmsSVCB->name, objectName) == 0) {
+ return mmsSVCB;
+ }
+ }
+ }
+
+ element = LinkedList_getNext(element);
+ }
+
+ return NULL;
+}
+
+
+MmsValue*
+LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig)
+{
+ MmsValue* value = NULL;
+
+ char variableId[130];
+
+ strncpy(variableId, variableIdOrig, 129);
+
+ char* separator = strchr(variableId, '$');
+
+ *separator = 0;
+
+ char* lnName = variableId;
+
+ if (lnName == NULL)
+ return NULL;
+
+ char* objectName = MmsMapping_getNextNameElement(separator + 1);
-static GSEControlBlock*
+ if (objectName == NULL)
+ return NULL;
+
+ char* varName = MmsMapping_getNextNameElement(objectName);
+
+ if (varName != NULL)
+ *(varName - 1) = 0;
+
+ MmsSampledValueControlBlock mmsSVCB = lookupSVCB(self, domain, lnName, objectName);
+
+ if (mmsSVCB != NULL) {
+ if (varName != NULL) {
+ value = MmsValue_getSubElement(mmsSVCB->mmsValue, mmsSVCB->mmsType, varName);
+ }
+ else {
+ value = mmsSVCB->mmsValue;
+ }
+ }
+
+ return value;
+}
+
+
+static SVControlBlock*
getSVCBForLogicalNodeWithIndex(MmsMapping* self, LogicalNode* logicalNode, int index, bool isUnicast)
{
int svCount = 0;
@@ -88,6 +187,8 @@ createSVControlBlockMmsStructure(char* gcbName, bool isUnicast)
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("Resv");
namedVariable->type = MMS_BOOLEAN;
+
+ gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
}
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
@@ -128,6 +229,13 @@ createSVControlBlockMmsStructure(char* gcbName, bool isUnicast)
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
+ namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
+ namedVariable->name = copyString("SmpMod");
+ namedVariable->type = MMS_INTEGER;
+ namedVariable->typeSpec.integer = 8;
+
+ gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
+
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("DstAddress");
MmsMapping_createPhyComAddrStructure(namedVariable);
@@ -205,7 +313,7 @@ LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
/* SmpMod */
MmsValue* smpMod = MmsValue_getElement(svValues, currentIndex++);
- MmsValue_setInt32(smpRate, svControlBlock->smpMod);
+ MmsValue_setInt32(smpMod, svControlBlock->smpMod);
/* Set communication parameters - DstAddress */
uint8_t priority = CONFIG_GOOSE_DEFAULT_PRIORITY;
@@ -242,6 +350,16 @@ LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
MmsValue* noASDU = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setInt32(noASDU, svControlBlock->noASDU);
+ MmsSampledValueControlBlock mmsSvCb = MmsSampledValueControlBlock_create();
+
+ mmsSvCb->mmsValue = svValues;
+ mmsSvCb->mmsType = svTypeSpec;
+ mmsSvCb->domain = domain;
+ mmsSvCb->logicalNode = logicalNode;
+ mmsSvCb->name = svControlBlock->name;
+
+ LinkedList_add(self->svControls, (void*) mmsSvCb);
+
currentSVCB++;
}
diff --git a/src/mms/inc/mms_client_connection.h b/src/mms/inc/mms_client_connection.h
index d87667e2..621bbb51 100644
--- a/src/mms/inc/mms_client_connection.h
+++ b/src/mms/inc/mms_client_connection.h
@@ -292,7 +292,8 @@ MmsConnection_getVariableListNamesAssociationSpecific(MmsConnection self, MmsErr
* \param itemId name of the variable to be read
*
* \return Returns a MmsValue object or NULL if the request failed. The MmsValue object can
- * either be a simple value or a complex value or array.
+ * either be a simple value or a complex value or array. It is also possible that the return value is NULL
+ * even if mmsError = MMS_ERROR_NON. This is the case when the servers returns an empty result list.
*/
MmsValue*
MmsConnection_readVariable(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId);
diff --git a/tools/model_generator/genconfig.jar b/tools/model_generator/genconfig.jar
index 3a36f546..9e3e43d5 100644
Binary files a/tools/model_generator/genconfig.jar and b/tools/model_generator/genconfig.jar differ
diff --git a/tools/model_generator/genmodel.jar b/tools/model_generator/genmodel.jar
index 2fdd70a9..784ac0ac 100644
Binary files a/tools/model_generator/genmodel.jar and b/tools/model_generator/genmodel.jar differ
diff --git a/tools/model_generator/src/com/libiec61850/scl/communication/ConnectedAP.java b/tools/model_generator/src/com/libiec61850/scl/communication/ConnectedAP.java
index 2aceca49..bfa61d39 100644
--- a/tools/model_generator/src/com/libiec61850/scl/communication/ConnectedAP.java
+++ b/tools/model_generator/src/com/libiec61850/scl/communication/ConnectedAP.java
@@ -48,17 +48,15 @@ public class ConnectedAP {
List gseNodes = ParserUtils.getChildNodesWithTag(node, "GSE");
- for (Node gseNode : gseNodes) {
+ for (Node gseNode : gseNodes)
gses.add(new GSE(gseNode));
- }
-
+
smvs = new LinkedList();
List smvNodes = ParserUtils.getChildNodesWithTag(node, "SMV");
- for (Node smvNode : smvNodes) {
- smvs.add(new SMV(smvNode));
- }
+ for (Node smvNode : smvNodes)
+ smvs.add(new SMV(smvNode));
}
public String getIedName() {
diff --git a/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java b/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java
index 5d34675f..6033732f 100644
--- a/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java
+++ b/tools/model_generator/src/com/libiec61850/scl/model/LogicalNode.java
@@ -116,7 +116,10 @@ public class LogicalNode implements DataModelNode {
/* Parse Sampled Values (SV) control block definitions */
smvControlBlocks = new LinkedList();
-
+
+ List svControlNodes = ParserUtils.getChildNodesWithTag(lnNode, "SampledValueControl");
+ for (Node svControlNode : svControlNodes)
+ smvControlBlocks.add(new SampledValueControl(svControlNode));
/* Parse log control block definitions */
logControlBlocks = new LinkedList();
diff --git a/tools/model_generator/src/com/libiec61850/scl/model/SampledValueControl.java b/tools/model_generator/src/com/libiec61850/scl/model/SampledValueControl.java
index 77993e77..f2f03b66 100644
--- a/tools/model_generator/src/com/libiec61850/scl/model/SampledValueControl.java
+++ b/tools/model_generator/src/com/libiec61850/scl/model/SampledValueControl.java
@@ -14,7 +14,7 @@ public class SampledValueControl {
private String smvID;
private int smpRate;
private int nofASDU;
- private boolean multicast;
+ private boolean multicast = false;
private SmvOpts smvOpts;
@@ -31,7 +31,10 @@ public class SampledValueControl {
this.smvID = ParserUtils.parseAttribute(smvControlNode, "smvID");
- this.multicast = ParserUtils.parseBooleanAttribute(smvControlNode, "multicast");
+ Boolean multicast = ParserUtils.parseBooleanAttribute(smvControlNode, "multicast");
+
+ if (multicast != null)
+ this.multicast = multicast;
String smpRateString = ParserUtils.parseAttribute(smvControlNode, "smpRate");
diff --git a/tools/model_generator/src/com/libiec61850/scl/model/SmvOpts.java b/tools/model_generator/src/com/libiec61850/scl/model/SmvOpts.java
index 1dcd59ad..02646af9 100644
--- a/tools/model_generator/src/com/libiec61850/scl/model/SmvOpts.java
+++ b/tools/model_generator/src/com/libiec61850/scl/model/SmvOpts.java
@@ -8,11 +8,12 @@ import com.libiec61850.scl.SclParserException;
public class SmvOpts {
- private boolean refreshTime = false;
- private boolean sampleRate = false;
- private boolean dataSet = false;
- private boolean security = false;
- private boolean sampleSynchronized = false;
+ private boolean refreshTime = false; /* 1 */
+ private boolean sampleSynchronized = false; /* 2 */
+ private boolean sampleRate = false; /* 4 */
+ private boolean dataSet = false; /* 8 */
+ private boolean security = false; /* 16 */
+
public SmvOpts(Node smvOptsNode) throws SclParserException {
@@ -38,4 +39,16 @@ public class SmvOpts {
}
+
+ public int getIntValue() {
+ int intValue = 0;
+
+ if (refreshTime) intValue += 1;
+ if (sampleSynchronized) intValue += 2;
+ if (sampleRate) intValue += 4;
+ if (dataSet) intValue += 8;
+ if (security) intValue += 16;
+
+ return intValue;
+ }
}
diff --git a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
index a7e3ff42..cad7d5ec 100644
--- a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
+++ b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
@@ -51,6 +51,7 @@ import com.libiec61850.scl.model.IED;
import com.libiec61850.scl.model.LogicalDevice;
import com.libiec61850.scl.model.LogicalNode;
import com.libiec61850.scl.model.ReportControlBlock;
+import com.libiec61850.scl.model.SampledValueControl;
import com.libiec61850.scl.model.Server;
import com.libiec61850.scl.model.SettingControl;
import com.libiec61850.scl.model.TriggerOptions;
@@ -71,6 +72,10 @@ public class StaticModelGenerator {
private List gseVariableNames;
private int currentGseVariableNumber = 0;
+ private StringBuffer smvControlBlocks;
+ private List smvVariableNames;
+ private int currentSvCBVariableNumber = 0;
+
private StringBuffer settingGroupControlBlocks;
private List sgcbVariableNames;
private int currentSGCBVariableNumber = 0;
@@ -101,6 +106,9 @@ public class StaticModelGenerator {
this.gseControlBlocks = new StringBuffer();
this.gseVariableNames = new LinkedList();
+ this.smvControlBlocks = new StringBuffer();
+ this.smvVariableNames = new LinkedList();
+
this.settingGroupControlBlocks = new StringBuffer();
this.sgcbVariableNames = new LinkedList();
@@ -267,6 +275,8 @@ public class StaticModelGenerator {
createGooseVariableList(logicalDevices);
+ createSmvVariableList(logicalDevices);
+
createSettingControlsVariableList(logicalDevices);
for (int i = 0; i < logicalDevices.size(); i++) {
@@ -308,6 +318,11 @@ public class StaticModelGenerator {
cOut.println(reportControlBlocks);
+ for (String smv : smvVariableNames)
+ cOut.println("extern SVControlBlock " + smv + ";");
+
+ cOut.println(smvControlBlocks);
+
for (String gcb : gseVariableNames)
cOut.println("extern GSEControlBlock " + gcb + ";");
@@ -338,6 +353,11 @@ public class StaticModelGenerator {
else
cOut.println(" NULL,");
+ if (smvVariableNames.size() > 0)
+ cOut.println(" &" + smvVariableNames.get(0) + ",");
+ else
+ cOut.println(" NULL,");
+
if (sgcbVariableNames.size() > 0)
cOut.println(" &" + sgcbVariableNames.get(0) + ",");
else
@@ -366,6 +386,28 @@ public class StaticModelGenerator {
}
}
+
+ private void createSmvVariableList(List logicalDevices) {
+ for (LogicalDevice ld : logicalDevices) {
+ List lnodes = ld.getLogicalNodes();
+
+ String ldName = ld.getInst();
+
+
+ for (LogicalNode ln : lnodes) {
+ List svCBs = ln.getSampledValueControlBlocks();
+
+ int smvCount = 0;
+
+ for (SampledValueControl smv : svCBs) {
+ String smvVariableName = modelPrefix + "_" + ldName + "_" + ln.getName() + "_smv" + smvCount;
+ smvVariableNames.add(smvVariableName);
+ smvCount++;
+ }
+ }
+ }
+ }
+
private void createReportVariableList(List logicalDevices) {
for (LogicalDevice ld : logicalDevices) {
@@ -445,6 +487,8 @@ public class StaticModelGenerator {
printGSEControlBlocks(ldName, lnName, logicalNode);
+ printSVControlBlocks(ldName, lnName, logicalNode);
+
printSettingControlBlock(lnName, logicalNode);
}
}
@@ -742,11 +786,100 @@ public class StaticModelGenerator {
hOut.println("#endif /* " + hDefineName + " */\n");
}
+ private void printSVControlBlocks(String ldName, String lnPrefix, LogicalNode logicalNode) {
+ List svControlBlocks = logicalNode.getSampledValueControlBlocks();
+
+ /* strip "iedModel_" from ldName */
+ String[] ldNameComponents = ldName.split("_");
+ String logicalDeviceName = ldNameComponents[1];
+
+ int smvControlNumber = 0;
+
+ for (SampledValueControl svCB : svControlBlocks) {
+
+ System.out.println("SVCB: " + svCB.getName());
+
+ PhyComAddress svAddress = connectedAP.lookupSMVAddress(logicalDeviceName, svCB.getName());
+
+ String svString = "";
+
+ String phyComAddrName = "";
+
+ if (svAddress != null) {
+ phyComAddrName = lnPrefix + "_smv" + smvControlNumber + "_address";
+
+ svString += "\nstatic PhyComAddress " + phyComAddrName + " = {\n";
+ svString += " " + svAddress.getVlanPriority() + ",\n";
+ svString += " " + svAddress.getVlanId() + ",\n";
+ svString += " " + svAddress.getAppId() + ",\n";
+ svString += " {";
+
+ for (int i = 0; i < 6; i++) {
+ svString += "0x" + Integer.toHexString(svAddress.getMacAddress()[i]);
+ if (i == 5)
+ svString += "}\n";
+ else
+ svString += ", ";
+ }
+
+ svString += "};\n\n";
+ }
+
+ String smvVariableName = lnPrefix + "_smv" + smvControlNumber;
+
+ svString += "SVControlBlock " + smvVariableName + " = {";
+ svString += "&" + lnPrefix + ", ";
+
+ svString += "\"" + svCB.getName() + "\", ";
+
+ if (svCB.getSmvID() == null)
+ svString += "NULL, ";
+ else
+ svString += "\"" + svCB.getSmvID() + "\", ";
+
+ if (svCB.getDatSet() != null)
+ svString += "\"" + svCB.getDatSet() + "\", ";
+ else
+ svString += "NULL, ";
+
+ svString += svCB.getSmvOpts().getIntValue() + ", ";
+
+ svString += "0, " + svCB.getSmpRate() + ", ";
+
+ svString += svCB.getConfRev() + ", ";
+
+ if (svAddress != null)
+ svString += "&" + phyComAddrName + ", ";
+ else
+ svString += "NULL, ";
+
+ if (svCB.isMulticast())
+ svString += "false, ";
+ else
+ svString += "true, ";
+
+ svString += svCB.getNofASDI() + ", ";
+
+ currentSvCBVariableNumber++;
+
+ if (currentSvCBVariableNumber < smvVariableNames.size())
+ svString += "&" + smvVariableNames.get(currentSvCBVariableNumber);
+ else
+ svString += "NULL";
+
+ svString += "};\n";
+
+ this.smvControlBlocks.append(svString);
+
+ smvControlNumber++;
+ }
+ }
+
private void printGSEControlBlocks(String ldName, String lnPrefix, LogicalNode logicalNode) {
List gseControlBlocks = logicalNode.getGSEControlBlocks();
+ /* strip "iedModel_" from ldName */
String[] ldNameComponents = ldName.split("_");
-
String logicalDeviceName = ldNameComponents[1];
int gseControlNumber = 0;