diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..c1b0da08
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,25 @@
+language: c
+
+compiler:
+ - clang
+ - gcc
+
+addons:
+ apt:
+ packages:
+ - cmake
+ - swig
+ - libsqlite3-dev
+ - python-dev
+
+before_install:
+ - if [ "$TRAVIS_OS_NAME" == "osx" ]; then
+ brew update;
+ brew install swig python sqlite;
+ fi
+ - mkdir -p build && cd build
+
+script:
+ - cmake .. -DBUILD_PYTHON_BINDINGS=ON
+ - make
+ - make test
diff --git a/CHANGELOG b/CHANGELOG
index ea68a97c..25ac39bf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,57 @@
+Changes to version 1.1.1
+------------------------
+
+- IEC 61850 client: fixed bug in APC control handling
+- IEC 61850 client: ClientReportControlBlock now accepts "$" and "." as seperator for RCB object reference
+- MMS client: fixed bug in MmsConnection_connect (COTP payload buffer was not reset in case of an error during connect -> connection failed in case of reuse of MmsConnection object
+- MMS client: delete named variable list service supports VMD specific lists
+- SV subscriber/publisher: additional features and bug fixes
+- SV: fixed data type for smpRate
+- SV: fixed encoding of optional smpMod attribute
+- SV receiver: Added semaphore to make subscriber list thread-safe
+- .NET API: ControlObject implements IDisposable interface
+- IED server: added new function IedServer_udpateDbposValue
+- fixed problem with cmake include folders
+- MMS client: file services -fixed encoding problem with long file names
+- MMS server: ACSE authenticator passes application reference (ap-title and ae-qualifier)
+- example directory cleanup
+- MMS: fixed potential memory leak in asn1 code that can be caused by malformed MMS messages
+- MMS client: MmsConnection_getVariableAccessAttributes support for VMD specific variables
+- Java SCL parser: added support for "Val" elements for Octet64 types
+
+
+Changes to version 1.1.0
+------------------------
+
+- MMS client/server: added write support for named variable lists
+- IEC 61850 client/server: added support for SetDataSet service
+- C# API: client - added support to write data set values
+- IEC 61850 client: Changed result strings of IedConnection_getDataDirectoryByFC. Removed appended FC string.
+- MMS client/server: extended BER encoder to support MMS PDU sizes with more than 64k
+- C# API: server - keep references to internal control handler delegates to avoid garbage collection
+- IEC 61850 server: added IedModel_getDeviceByInst function
+- SV subscriber: added subscriber side handling for RefrTm
+- SV publisher: Changed SampledValuesPublisher_create to support setting of Communication parameters at runtime
+- socket-win32: updated WSA initialization handling
+- all: small fixes and code optimizations
+
+
+Changes to version 1.0.2
+------------------------
+- server: added MmsFileAccessHandler for server side monitoring and control of file services
+- file services: added support to set filestore basepath at runtime
+- added IedConnection_getFileDirectoryEx to better control receiving file directories
+- common: added timestamp handling functions Timestamp_create, Timestamp_destroy, Timestamp_setByMmsUtcTime, Timestamp_toMmsValue
+- .NET API: Added Timestamp class
+- .NET API: Added missing UpdateAttribute methods to IedServer
+- common: added support for Currency BasicType
+- MMS file services: fixed problem with negative frsmId
+- java scl tools: fixed bug with SDOs in dynamic code generator
+- java scl tools: fixed parsing bug in OptionFields.java
+- server: added functions to restrict local IP address IedServer_setLocalIpAddress, IedServer.SetLocalIpAddress
+- .NET: IedConnection: added internal reference to IsoConnectionParameters object to avoid deletion of internal AcseAuthenticationParameters by garbage collector
+
+
Changes to version 1.0.1
------------------------
- server: fixed problem in COTP src/dst reference handling (returning zero src reference)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cd880bbb..95e47983 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,17 +2,17 @@ cmake_minimum_required(VERSION 2.8)
# automagically detect if we should cross-compile
if(DEFINED ENV{TOOLCHAIN})
- set(CMAKE_C_COMPILER $ENV{TOOLCHAIN}gcc)
- set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN}g++)
- set(CMAKE_AR "$ENV{TOOLCHAIN}ar" CACHE FILEPATH "CW archiver" FORCE)
+ set(CMAKE_C_COMPILER $ENV{TOOLCHAIN}gcc)
+ set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN}g++)
+ set(CMAKE_AR "$ENV{TOOLCHAIN}ar" CACHE FILEPATH "CW archiver" FORCE)
endif()
project(libiec61850)
ENABLE_TESTING()
set(LIB_VERSION_MAJOR "1")
-set(LIB_VERSION_MINOR "0")
-set(LIB_VERSION_PATCH "2")
+set(LIB_VERSION_MINOR "1")
+set(LIB_VERSION_PATCH "1")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/third_party/cmake/modules/")
@@ -32,20 +32,15 @@ option(BUILD_PYTHON_BINDINGS "Build Python bindings" 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
+option(CONFIG_ACTIVATE_TCP_KEEPALIVE "Activate TCP keepalive" ON)
option(CONFIG_INCLUDE_GOOSE_SUPPORT "Build with GOOSE support" ON)
+# choose the library features which shall be included
option(CONFIG_IEC61850_CONTROL_SERVICE "Build with support for IEC 61850 control features" ON)
-
option(CONFIG_IEC61850_REPORT_SERVICE "Build with support for IEC 61850 reporting services" ON)
-
option(CONFIG_IEC61850_LOG_SERVICE "Build with support for IEC 61850 logging services" ON)
-
option(CONFIG_IEC61850_SETTING_GROUPS "Build with support for IEC 61850 setting group services" ON)
-option(CONFIG_ACTIVATE_TCP_KEEPALIVE "Activate TCP keepalive" ON)
-
set(CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE "8000" CACHE STRING "Default buffer size for buffered reports in byte" )
# advanced options
@@ -62,17 +57,17 @@ option(DEBUG_MMS_CLIENT "Enable MMS CLIENT printf debugging" OFF)
# DEBUG_IED_CLIENT DEBUG_MMS_SERVER DEBUG_MMS_CLIENT)
include_directories(
- ${CMAKE_CURRENT_LIST_DIR}/config
- ${CMAKE_CURRENT_LIST_DIR}/src/common/inc
- ${CMAKE_CURRENT_LIST_DIR}/src/goose
- ${CMAKE_CURRENT_LIST_DIR}/src/sampled_values
- ${CMAKE_CURRENT_LIST_DIR}/src/hal/inc
- ${CMAKE_CURRENT_LIST_DIR}/src/iec61850/inc
- ${CMAKE_CURRENT_LIST_DIR}/src/iec61850/inc_private
- ${CMAKE_CURRENT_LIST_DIR}/src/mms/inc
- ${CMAKE_CURRENT_LIST_DIR}/src/mms/inc_private
- ${CMAKE_CURRENT_LIST_DIR}/src/mms/iso_mms/asn1c
- ${CMAKE_CURRENT_LIST_DIR}/src/logging
+ ${CMAKE_CURRENT_BINARY_DIR}/config
+ src/common/inc
+ src/goose
+ src/sampled_values
+ src/hal/inc
+ src/iec61850/inc
+ src/iec61850/inc_private
+ src/mms/inc
+ src/mms/inc_private
+ src/mms/iso_mms/asn1c
+ src/logging
)
set(API_HEADERS
@@ -114,42 +109,45 @@ set(API_HEADERS
${CMAKE_CURRENT_BINARY_DIR}/config/stack_config.h
)
-IF(MSVC)
-include_directories(
- src/vs
-)
-ENDIF(MSVC)
+if(MSVC)
+ include_directories(
+ src/vs
+ )
+endif(MSVC)
# write the detected stuff to this file
-configure_file(${CMAKE_CURRENT_LIST_DIR}/config/stack_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config/stack_config.h)
+configure_file(
+ ${CMAKE_CURRENT_LIST_DIR}/config/stack_config.h.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/config/stack_config.h
+)
if(BUILD_EXAMPLES)
- add_subdirectory(examples)
+ add_subdirectory(examples)
endif(BUILD_EXAMPLES)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/src)
-INSTALL(FILES ${API_HEADERS} DESTINATION include/libiec61850 COMPONENT Development)
-
-IF(BUILD_PYTHON_BINDINGS)
- add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/pyiec61850)
-ENDIF(BUILD_PYTHON_BINDINGS)
-
-IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
-INCLUDE(InstallRequiredSystemLibraries)
-
-SET(CPACK_PACKAGE_DESCRIPTION "IEC 61850 MMS/GOOSE client and server library")
-SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "IEC 61850 MMS/GOOSE client and server library")
-SET(CPACK_PACKAGE_VENDOR "MZ Automation GmbH")
-SET(CPACK_PACKAGE_CONTACT "info@libiec61850.com")
-SET(CPACK_PACKAGE_VERSION_MAJOR "${LIB_VERSION_MAJOR}")
-SET(CPACK_PACKAGE_VERSION_MINOR "${LIB_VERSION_MINOR}")
-SET(CPACK_PACKAGE_VERSION_PATCH "${LIB_VERSION_PATCH}")
-SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${CMAKE_SYSTEM_PROCESSOR}")
-SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
-
-SET(CPACK_COMPONENTS_ALL Libraries Development Applications)
-#set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}")
-INCLUDE(CPack)
-
-ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
+install(FILES ${API_HEADERS} DESTINATION include/libiec61850 COMPONENT Development)
+
+if(BUILD_PYTHON_BINDINGS)
+ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/pyiec61850)
+endif(BUILD_PYTHON_BINDINGS)
+
+if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
+ include(InstallRequiredSystemLibraries)
+
+ set(CPACK_PACKAGE_DESCRIPTION "IEC 61850 MMS/GOOSE client and server library")
+ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "IEC 61850 MMS/GOOSE client and server library")
+ set(CPACK_PACKAGE_VENDOR "MZ Automation GmbH")
+ set(CPACK_PACKAGE_CONTACT "info@libiec61850.com")
+ set(CPACK_PACKAGE_VERSION_MAJOR "${LIB_VERSION_MAJOR}")
+ set(CPACK_PACKAGE_VERSION_MINOR "${LIB_VERSION_MINOR}")
+ set(CPACK_PACKAGE_VERSION_PATCH "${LIB_VERSION_PATCH}")
+ set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${CMAKE_SYSTEM_PROCESSOR}")
+ set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+
+ set(CPACK_COMPONENTS_ALL Libraries Development Applications)
+ #set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}")
+
+ include(CPack)
+endif(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
diff --git a/README.md b/README.md
index 53f5cd97..1cd1ac84 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# README libIEC61850
+[](https://travis-ci.org/mz-automation/libiec61850)
+
This file is part of the documentation of **libIEC61850**. More documentation can be found online at http://libiec61850.com or in the provided doxygen documentation. Also consider to review the examples to understand how to use the library
Content:
@@ -73,15 +75,17 @@ To build the library and run libiec61850 applications with GOOSE support on Wind
## Building with the cmake build script
-With the help of the cmake build script it is possible to create platform independet project descriptions and let cmake create specific project or build files for other tools like Make or Visual Studio.
+With the help of the cmake build script it is possible to create platform independent project descriptions and let cmake create specific project or build files for other tools like Make or Visual Studio.
+
+If you have cmake installed fire up a command line (cmd.exe) and create a new subdirectory in the libiec61850 folder. Change to this subdirectory. Then you can invoke cmake. As an command line argument you have to supply a "generator" that is used by cmake to create the project file for the actual build tool (in our case Visual Studio 2015).
-If you have cmake installed fire up a command line (cmd.exe) and create a new subdirectory in the libiec61850 folder. Change to this subdirectory. Then you can invoke cmake. As an command line argument you have to supply a "generator" that is used by cmake to create the project file for the actual build tool (in our case Visual Studio).
+`cmake -G "Visual Studio 14 2015" ..`
-`cmake -G "Visual Studio 11" ..`
+will instruct cmake to create a "solution" for Visual Studio 2015. The resulting project files will be 32 bit.
-will instruct cmake to create a "solution" for Visual Studio 2012. To do the same thing for Visual Studio 2010 type
+To build 64 bit libraries the "Win64" generator option has to be added.
-`cmake -G "Visual Studio 10" ..`
+`cmake -G "Visual Studio 14 2015 Win64" ..`
Note: The ".." at the end of the command line tells cmake where to find the main build script file (called CMakeLists.txt). This should point to the folder libiec61850 which is in our case the parent directory (..).
diff --git a/config/stack_config.h b/config/stack_config.h
index a3052809..b25c7da1 100644
--- a/config/stack_config.h
+++ b/config/stack_config.h
@@ -37,7 +37,7 @@
* 0 ==> server runs in multi-threaded mode (one thread for each connection and
* one server background thread )
*/
-#define CONFIG_MMS_SINGLE_THREADED 0
+#define CONFIG_MMS_SINGLE_THREADED 1
/*
* Optimize stack for threadless operation - don't use semaphores
@@ -224,4 +224,9 @@
/* Support user access to raw messages */
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 1
+/* Allow to set the virtual filestore basepath for MMS file services at runtime with the
+ * MmsServer_setFilestoreBasepath function
+ */
+#define CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME 1
+
#endif /* STACK_CONFIG_H_ */
diff --git a/config/stack_config.h.cmake b/config/stack_config.h.cmake
index c9ea73d7..c36f782d 100644
--- a/config/stack_config.h.cmake
+++ b/config/stack_config.h.cmake
@@ -29,6 +29,9 @@
#cmakedefine01 DEBUG_MMS_SERVER
#cmakedefine01 DEBUG_GOOSE_SUBSCRIBER
#cmakedefine01 DEBUG_GOOSE_PUBLISHER
+#cmakedefine01 DEBUG_SV_SUBSCRIBER
+#cmakedefine01 DEBUG_SV_PUBLISHER
+#cmakedefine01 DEBUG_HAL_ETHERNET
/* 1 ==> server runs in single threaded mode (one dedicated thread for the server)
* 0 ==> server runs in multi threaded mode (one thread for each connection and
@@ -103,14 +106,14 @@
#define CONFIG_GOOSE_EVENT_RETRANSMISSION_COUNT 2
/* Define if GOOSE control block elements are writable (1) or read-only (0) */
-#define CONFIG_GOOSE_GOID_WRITABLE 1
-#define CONFIG_GOOSE_DATSET_WRITABLE 1
-#define CONFIG_GOOSE_CONFREV_WRITABLE 1
-#define CONFIG_GOOSE_NDSCOM_WRITABLE 1
-#define CONFIG_GOOSE_DSTADDRESS_WRITABLE 1
-#define CONFIG_GOOSE_MINTIME_WRITABLE 1
-#define CONFIG_GOOSE_MAXTIME_WRITABLE 1
-#define CONFIG_GOOSE_FIXEDOFFS_WRITABLE 1
+#define CONFIG_GOOSE_GOID_WRITABLE 0
+#define CONFIG_GOOSE_DATSET_WRITABLE 0
+#define CONFIG_GOOSE_CONFREV_WRITABLE 0
+#define CONFIG_GOOSE_NDSCOM_WRITABLE 0
+#define CONFIG_GOOSE_DSTADDRESS_WRITABLE 0
+#define CONFIG_GOOSE_MINTIME_WRITABLE 0
+#define CONFIG_GOOSE_MAXTIME_WRITABLE 0
+#define CONFIG_GOOSE_FIXEDOFFS_WRITABLE 0
/* The default value for the priority field of the 802.1Q header (allowed range 0-7) */
#define CONFIG_GOOSE_DEFAULT_PRIORITY 4
@@ -133,6 +136,9 @@
/* include support for IEC 61850 reporting services */
#cmakedefine01 CONFIG_IEC61850_REPORT_SERVICE
+/* support buffered report control blocks with ResvTms field */
+#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0
+
/* The default buffer size of buffered RCBs in bytes */
#cmakedefine CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE @CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE@
@@ -194,10 +200,21 @@
#define CONFIG_IEC61850_CONTROL_SERVICE 0
#endif
+/* Sort getNameList response according to the MMS specified collation order - this is required by the standard
+ * Set to 0 only for performance reasons and when no certification is required! */
+#define CONFIG_MMS_SORT_NAME_LIST 1
+
+#define CONFIG_INCLUDE_PLATFORM_SPECIFIC_HEADERS 0
+
/* use short FC defines as in old API */
#define CONFIG_PROVIDE_OLD_FC_DEFINES 0
/* Support user acccess to raw messages */
#cmakedefine01 CONFIG_MMS_RAW_MESSAGE_LOGGING
+/* Allow to set the virtual filestore basepath for MMS file services at runtime with the
+ * MmsServer_setFilestoreBasepath function
+ */
+#define CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME 1
+
#endif /* STACK_CONFIG_H_ */
diff --git a/dotnet/IEC61850forCSharp/Control.cs b/dotnet/IEC61850forCSharp/Control.cs
index 8604e3e5..711542c7 100644
--- a/dotnet/IEC61850forCSharp/Control.cs
+++ b/dotnet/IEC61850forCSharp/Control.cs
@@ -104,7 +104,7 @@ namespace IEC61850
///
/// Control object.
///
- public class ControlObject
+ public class ControlObject : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern LastApplErrorInternal ControlObjectClient_getLastApplError(IntPtr self);
@@ -183,12 +183,6 @@ namespace IEC61850
ControlObjectClient_setCommandTerminationHandler(controlObject, intCommandTerminationHandler, controlObject);
}
- ~ControlObject ()
- {
- if (this.controlObject != System.IntPtr.Zero)
- ControlObjectClient_destroy(controlObject);
- }
-
///
/// Gets the control model.
///
@@ -443,6 +437,18 @@ namespace IEC61850
this.commandTerminationHandlerParameter = parameter;
}
+ protected virtual void Dispose(bool disposing) {
+ if (this.controlObject != System.IntPtr.Zero) {
+ ControlObjectClient_destroy (controlObject);
+ this.controlObject = System.IntPtr.Zero;
+ }
+ }
+
+ public void Dispose() {
+ Dispose (true);
+ }
+
+
}
}
diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
index 374d3a88..aef42ee1 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
@@ -335,6 +335,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedConnection_readDataSetValues (IntPtr self, out int error, [MarshalAs(UnmanagedType.LPStr)] string dataSetReference, IntPtr dataSet);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedConnection_writeDataSetValues (IntPtr self, out int error, [MarshalAs(UnmanagedType.LPStr)] string dataSetReference, IntPtr values, out IntPtr accessResults);
+
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedConnection_createDataSet (IntPtr self, out int error, [MarshalAs(UnmanagedType.LPStr)] string dataSetReference, IntPtr dataSet);
@@ -823,7 +826,7 @@ namespace IEC61850
return QueryLogByTime (logRef, startTimeMs, stopTimeMs, out moreFollows);
}
- /// Read the variable specification (type description of a DA or FDCO
+ /// Read the variable specification (type description of a DA or FCDO
/// The object reference of a DA or FCDO.
/// The functional constraint (FC) of the object
/// This exception is thrown if there is a connection or service error
@@ -1241,6 +1244,56 @@ namespace IEC61850
return dataSet;
}
+ ///
+ /// Writes the values of a data set (SetDataSetValues service).
+ ///
+ /// The list of access results
+ /// The object reference of the data set
+ /// The new values for the data set members. The values have to be of the same number and type as the data set members
+ public List WriteDataSetValues(string dataSetReference, List values)
+ {
+ int error;
+ IntPtr accessResults = IntPtr.Zero;
+
+ IntPtr valueList = LinkedList_create ();
+
+ foreach (MmsValue mmsValue in values) {
+ LinkedList_add (valueList, mmsValue.valueReference);
+ }
+
+ IedConnection_writeDataSetValues (connection, out error, dataSetReference, valueList, out accessResults);
+
+ LinkedList_destroyStatic (valueList);
+
+ /* handle access results */
+
+ List accessResultList = null;
+
+ if (accessResults != IntPtr.Zero) {
+
+ IntPtr element = LinkedList_getNext (accessResults);
+
+ while (element != IntPtr.Zero) {
+ IntPtr elementData = LinkedList_getData (element);
+
+ MmsValue accessResultValue = new MmsValue (elementData, true);
+
+ MmsDataAccessError dataAccessError = accessResultValue.GetDataAccessError ();
+
+ accessResultList.Add (dataAccessError);
+
+ element = LinkedList_getNext (element);
+ }
+
+ LinkedList_destroyStatic (accessResults);
+ }
+
+ if (error != 0)
+ throw new IedConnectionException ("Writing data set failed", error);
+
+ return accessResultList;
+ }
+
///
/// Create a new data set.
///
diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
index 926d008f..fc08dd8f 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
@@ -561,6 +561,9 @@ namespace IEC61850
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr IedServer_create(IntPtr modelRef);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_setLocalIpAddress(IntPtr self, string localIpAddress);
+
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
static extern void IedServer_start(IntPtr self, int tcpPort);
@@ -656,7 +659,9 @@ namespace IEC61850
private IntPtr self = IntPtr.Zero;
-
+ private InternalControlHandler internalControlHandlerRef = null;
+ private InternalControlPerformCheckHandler internalControlPerformCheckHandlerRef = null;
+ private InternalControlWaitForExecutionHandler internalControlWaitForExecutionHandlerRef = null;
private class ControlHandlerInfo {
public DataObject controlObject = null;
@@ -796,7 +801,28 @@ namespace IEC61850
private InternalConnectionHandler internalConnectionHandler = null;
+ ///
+ /// Sets the local ip address for listening
+ ///
+ /// Local IP address.
+ public void SetLocalIpAddress(string localIpAddress)
+ {
+ IedServer_setLocalIpAddress (self, localIpAddress);
+ }
+
+ ///
+ /// Start MMS server
+ ///
+ /// Local IP address.
+ /// TCP port to use
+ public void Start(string localIpAddress, int tcpPort)
+ {
+ SetLocalIpAddress (localIpAddress);
+ Start (tcpPort);
+ }
+
/// Start MMS server
+ /// TCP port to use
public void Start(int tcpPort)
{
if (internalConnectionHandler == null)
@@ -860,7 +886,10 @@ namespace IEC61850
info.controlHandler = handler;
info.controlHandlerParameter = parameter;
- IedServer_setControlHandler(self, controlObject.self, internalControlHandler, GCHandle.ToIntPtr(info.handle));
+ if (internalControlHandlerRef == null)
+ internalControlHandlerRef = new InternalControlHandler (internalControlHandler);
+
+ IedServer_setControlHandler(self, controlObject.self, internalControlHandlerRef, GCHandle.ToIntPtr(info.handle));
}
public void SetCheckHandler (DataObject controlObject, CheckHandler handler, object parameter)
@@ -870,7 +899,10 @@ namespace IEC61850
info.checkHandler = handler;
info.checkHandlerParameter = parameter;
- IedServer_setPerformCheckHandler(self, controlObject.self, internalCheckHandler, GCHandle.ToIntPtr(info.handle));
+ if (internalControlPerformCheckHandlerRef == null)
+ internalControlPerformCheckHandlerRef = new InternalControlPerformCheckHandler (internalCheckHandler);
+
+ IedServer_setPerformCheckHandler(self, controlObject.self, internalControlPerformCheckHandlerRef, GCHandle.ToIntPtr(info.handle));
}
public void SetWaitForExecutionHandler (DataObject controlObject, ControlWaitForExecutionHandler handler, object parameter)
@@ -880,7 +912,10 @@ namespace IEC61850
info.waitForExecHandler = handler;
info.waitForExecHandlerParameter = parameter;
- IedServer_setWaitForExecutionHandler(self, controlObject.self, internalControlWaitForExecutionHandler, GCHandle.ToIntPtr(info.handle));
+ if (internalControlWaitForExecutionHandlerRef == null)
+ internalControlWaitForExecutionHandlerRef = new InternalControlWaitForExecutionHandler (internalControlWaitForExecutionHandler);
+
+ IedServer_setWaitForExecutionHandler(self, controlObject.self, internalControlWaitForExecutionHandlerRef, GCHandle.ToIntPtr(info.handle));
}
public void HandleWriteAccess (DataAttribute dataAttr, WriteAccessHandler handler, object parameter)
diff --git a/dotnet/control/ControlExample.cs b/dotnet/control/ControlExample.cs
index 5504f317..7bce2eec 100644
--- a/dotnet/control/ControlExample.cs
+++ b/dotnet/control/ControlExample.cs
@@ -86,7 +86,10 @@ namespace control
Thread.Sleep(1000);
}
- con.Abort();
+ // has to be called before IedConnection dispose method!
+ control.Dispose();
+
+ con.Abort();
}
catch (IedConnectionException e)
{
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 398e901d..2502ff10 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,8 +1,7 @@
-add_subdirectory(server_example1)
-add_subdirectory(server_example2)
-add_subdirectory(server_example3)
-add_subdirectory(server_example4)
-add_subdirectory(server_example5)
+add_subdirectory(server_example_simple)
+add_subdirectory(server_example_basic_io)
+add_subdirectory(server_example_password_auth)
+add_subdirectory(server_example_write_handler)
add_subdirectory(server_example_control)
add_subdirectory(server_example_dynamic)
add_subdirectory(server_example_config_file)
@@ -11,36 +10,35 @@ add_subdirectory(server_example_threadless)
add_subdirectory(server_example_61400_25)
add_subdirectory(server_example_setting_groups)
add_subdirectory(server_example_logging)
+add_subdirectory(server_example_files)
+
add_subdirectory(iec61850_client_example1)
add_subdirectory(iec61850_client_example2)
add_subdirectory(iec61850_client_example3)
add_subdirectory(iec61850_client_example4)
add_subdirectory(iec61850_client_example5)
-add_subdirectory(iec61850_client_example_files)
add_subdirectory(iec61850_client_example_reporting)
add_subdirectory(iec61850_client_example_log)
-add_subdirectory(mms_client_example1)
-add_subdirectory(mms_client_example2)
-add_subdirectory(mms_client_example3)
-add_subdirectory(mms_client_example4)
-IF(WIN32)
-if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib")
-message("Found winpcap -> compile examples for GOOSE and SV")
-add_subdirectory(server_example_goose)
-add_subdirectory(goose_subscriber)
-add_subdirectory(goose_publisher)
-add_subdirectory(sv_subscriber)
-add_subdirectory(iec61850_9_2_LE_example)
-add_subdirectory(iec61850_sv_client_example)
-add_subdirectory(sv_publisher)
+if(NOT WIN32)
+ add_subdirectory(iec61850_client_example_files)
endif()
+
+if(WIN32)
+ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib")
+ set(BUILD_SV_GOOSE_EXAMPLES ON)
+ message("Found winpcap -> compile examples for GOOSE and SV")
+ endif()
else()
-add_subdirectory(server_example_goose)
-add_subdirectory(goose_subscriber)
-add_subdirectory(goose_publisher)
-add_subdirectory(sv_subscriber)
-add_subdirectory(iec61850_9_2_LE_example)
-add_subdirectory(iec61850_sv_client_example)
-add_subdirectory(sv_publisher)
+ set(BUILD_SV_GOOSE_EXAMPLES ON)
+endif()
+
+if(${BUILD_SV_GOOSE_EXAMPLES})
+ add_subdirectory(server_example_goose)
+ add_subdirectory(goose_subscriber)
+ add_subdirectory(goose_publisher)
+ add_subdirectory(sv_subscriber)
+ add_subdirectory(iec61850_9_2_LE_example)
+ add_subdirectory(iec61850_sv_client_example)
+ add_subdirectory(sv_publisher)
endif()
diff --git a/examples/Makefile b/examples/Makefile
index 38262219..543cb03b 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,21 +1,15 @@
-EXAMPLE_DIRS = mms_client_example1
-EXAMPLE_DIRS += mms_client_example2
-EXAMPLE_DIRS += mms_client_example3
-EXAMPLE_DIRS += mms_client_example4
-EXAMPLE_DIRS += mms_client_example5
-EXAMPLE_DIRS += iec61850_client_example1
+EXAMPLE_DIRS = iec61850_client_example1
EXAMPLE_DIRS += iec61850_client_example2
EXAMPLE_DIRS += iec61850_client_example3
EXAMPLE_DIRS += iec61850_client_example4
EXAMPLE_DIRS += iec61850_client_example5
EXAMPLE_DIRS += iec61850_client_example_reporting
EXAMPLE_DIRS += iec61850_client_example_log
-EXAMPLE_DIRS += server_example1
-EXAMPLE_DIRS += server_example2
-EXAMPLE_DIRS += server_example3
-EXAMPLE_DIRS += server_example4
-EXAMPLE_DIRS += server_example5
+EXAMPLE_DIRS += server_example_simple
+EXAMPLE_DIRS += server_example_basic_io
+EXAMPLE_DIRS += server_example_password_auth
+EXAMPLE_DIRS += server_example_write_handler
EXAMPLE_DIRS += server_example_goose
EXAMPLE_DIRS += server_example_control
EXAMPLE_DIRS += server_example_config_file
@@ -25,6 +19,7 @@ EXAMPLE_DIRS += server_example_61400_25
EXAMPLE_DIRS += server_example_threadless
EXAMPLE_DIRS += server_example_setting_groups
EXAMPLE_DIRS += server_example_logging
+EXAMPLE_DIRS += server_example_files
EXAMPLE_DIRS += goose_subscriber
EXAMPLE_DIRS += goose_publisher
EXAMPLE_DIRS += sv_subscriber
@@ -34,11 +29,10 @@ EXAMPLE_DIRS += iec61850_sv_client_example
EXAMPLE_DIRS += sv_publisher
EXAMPLE_DIRS += sv_subscriber
-MODEL_DIRS += server_example1
-MODEL_DIRS += server_example2
-MODEL_DIRS += server_example3
-MODEL_DIRS += server_example4
-MODEL_DIRS += server_example5
+MODEL_DIRS += server_example_simple
+MODEL_DIRS += server_example_basic_io
+MODEL_DIRS += server_example_password_auth
+MODEL_DIRS += server_example_write_handler
MODEL_DIRS += server_example_goose
MODEL_DIRS += server_example_control
MODEL_DIRS += server_example_config_file
@@ -47,6 +41,7 @@ MODEL_DIRS += server_example_61400_25
MODEL_DIRS += server_example_threadless
MODEL_DIRS += server_example_setting_groups
MODEL_DIRS += server_example_logging
+MODEL_DIRS += server_example_files
MODEL_DIRS += iec61850_9_2_LE_example
all: examples
diff --git a/examples/goose_subscriber/goose_subscriber_example.c b/examples/goose_subscriber/goose_subscriber_example.c
index c9a7e103..5d28534b 100644
--- a/examples/goose_subscriber/goose_subscriber_example.c
+++ b/examples/goose_subscriber/goose_subscriber_example.c
@@ -12,8 +12,6 @@
#include
#include
#include
-#define __STDC_FORMAT_MACROS /* otherwise PRIu64 is not defined for MinGW */
-#include
static int running = 1;
@@ -29,9 +27,10 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
printf(" stNum: %u sqNum: %u\n", GooseSubscriber_getStNum(subscriber),
GooseSubscriber_getSqNum(subscriber));
printf(" timeToLive: %u\n", GooseSubscriber_getTimeAllowedToLive(subscriber));
-#ifndef _WIN32
- printf(" timestamp: %"PRIu64"\n", GooseSubscriber_getTimestamp(subscriber));
-#endif
+
+ uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber);
+
+ printf(" timestamp: %u.%u\n", (uint32_t) (timestamp / 1000), (uint32_t) (timestamp % 1000));
MmsValue* values = GooseSubscriber_getDataSetValues(subscriber);
@@ -45,14 +44,6 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
int
main(int argc, char** argv)
{
- MmsValue* dataSetValues = MmsValue_createEmptyArray(4);
-
- int i;
- for (i = 0; i < 4; i++) {
- MmsValue* dataSetEntry = MmsValue_newBoolean(false);
- MmsValue_setElement(dataSetValues, i, dataSetEntry);
- }
-
GooseReceiver receiver = GooseReceiver_create();
if (argc > 1) {
@@ -80,5 +71,7 @@ main(int argc, char** argv)
Thread_sleep(100);
}
- GooseSubscriber_destroy(subscriber);
+ GooseReceiver_stop(receiver);
+
+ GooseReceiver_destroy(receiver);
}
diff --git a/examples/iec61850_9_2_LE_example/README b/examples/iec61850_9_2_LE_example/README
new file mode 100644
index 00000000..ca64b3a9
--- /dev/null
+++ b/examples/iec61850_9_2_LE_example/README
@@ -0,0 +1,9 @@
+
+The default ethernet interface is eth0. You can specify another interface at the command line.
+
+ ./sv_9_2LE_example eth1
+
+In order for the SV publisher to start the SVCB has to be enabled by an MMS client.
+
+
+
diff --git a/examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c b/examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c
index 71223023..e4c9407d 100644
--- a/examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c
+++ b/examples/iec61850_9_2_LE_example/iec61850_9_2_LE_example.c
@@ -36,7 +36,7 @@
extern IedModel iedModel;
static int running = 0;
-static int svcbEnabled = 0;
+static int svcbEnabled = 1;
void sigint_handler(int signalId)
{
@@ -57,9 +57,9 @@ static SampledValuesPublisher svPublisher;
static SV_ASDU asdu;
static void
-setupSVPublisher()
+setupSVPublisher(const char* svInterface)
{
- svPublisher = SampledValuesPublisher_create("eth1");
+ svPublisher = SampledValuesPublisher_create(NULL, svInterface);
asdu = SampledValuesPublisher_addASDU(svPublisher, "xxxxMUnn01", NULL, 1);
@@ -87,6 +87,13 @@ static void sVCBEventHandler (SVControlBlock* svcb, int event, void* parameter)
int
main(int argc, char** argv)
{
+ char* svInterface;
+
+ if (argc > 1)
+ svInterface = argv[1];
+ else
+ svInterface = "eth0";
+
IedServer iedServer = IedServer_create(&iedModel);
/* MMS server will be instructed to start listening to client connections. */
@@ -102,7 +109,7 @@ main(int argc, char** argv)
signal(SIGINT, sigint_handler);
- setupSVPublisher();
+ setupSVPublisher(svInterface);
int voltage = 1;
int current = 1;
diff --git a/examples/iec61850_client_example1/client_example1.c b/examples/iec61850_client_example1/client_example1.c
index e20a2327..1142c768 100644
--- a/examples/iec61850_client_example1/client_example1.c
+++ b/examples/iec61850_client_example1/client_example1.c
@@ -50,6 +50,8 @@ int main(int argc, char** argv) {
if (error == IED_ERROR_OK) {
+ IedConnection_getServerDirectory(con, &error, false);
+
/* read an analog measurement value from server */
MmsValue* value = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", IEC61850_FC_MX);
diff --git a/examples/iec61850_client_example_files/CMakeLists.txt b/examples/iec61850_client_example_files/CMakeLists.txt
index 36cba273..9178d240 100644
--- a/examples/iec61850_client_example_files/CMakeLists.txt
+++ b/examples/iec61850_client_example_files/CMakeLists.txt
@@ -1,6 +1,6 @@
set(iec61850_client_example_files_SRCS
- client_example_files.c
+ file-tool.c
)
IF(MSVC)
@@ -8,10 +8,10 @@ set_source_files_properties(${iec61850_client_example_files_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(MSVC)
-add_executable(iec61850_client_example_files
+add_executable(file-tool
${iec61850_client_example_files_SRCS}
)
-target_link_libraries(iec61850_client_example_files
+target_link_libraries(file-tool
iec61850
)
diff --git a/examples/iec61850_client_example_files/Makefile b/examples/iec61850_client_example_files/Makefile
index eea5d9f8..c4d0ecbc 100644
--- a/examples/iec61850_client_example_files/Makefile
+++ b/examples/iec61850_client_example_files/Makefile
@@ -1,7 +1,7 @@
LIBIEC_HOME=../..
-PROJECT_BINARY_NAME = client_example_files
-PROJECT_SOURCES = client_example_files.c
+PROJECT_BINARY_NAME = file-tool
+PROJECT_SOURCES = file-tool.c
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
diff --git a/examples/iec61850_client_example_files/client_example_files.c b/examples/iec61850_client_example_files/client_example_files.c
deleted file mode 100644
index 33c6750b..00000000
--- a/examples/iec61850_client_example_files/client_example_files.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * client_example_files.c
- *
- * This example demonstrates the usage of the file services
- *
- * - How to browse the file system of the server
- * - How to download a file from the server
- *
- * Note: intended to be used with server_example3
- *
- */
-
-#include "iec61850_client.h"
-
-#include
-#include
-
-#include "hal_thread.h"
-
-#define MAX_BUFFER_SIZE 2000000
-
-static uint8_t downloadBuffer[MAX_BUFFER_SIZE];
-static int bufferPosition = 0;
-
-static bool
-downloadHandler(void* parameter, uint8_t* buffer, uint32_t bytesRead)
-{
- printf("received %i bytes\n", bytesRead);
-
- if (bufferPosition + bytesRead < MAX_BUFFER_SIZE) {
- memcpy(downloadBuffer + bufferPosition, buffer, bytesRead);
- return true;
- }
- else
- return false;
-}
-
-int main(int argc, char** argv) {
-
- char* hostname;
- int tcpPort = 102;
-
- if (argc > 1)
- hostname = argv[1];
- else
- hostname = "localhost";
-
- if (argc > 2)
- tcpPort = atoi(argv[2]);
-
- IedClientError error;
-
- IedConnection con = IedConnection_create();
-
- IedConnection_connect(con, &error, hostname, tcpPort);
-
- if (error == IED_ERROR_OK) {
-
- /* Get the root directory */
- LinkedList rootDirectory =
- IedConnection_getFileDirectory(con, &error, NULL);
-
- if (error != IED_ERROR_OK) {
- printf("Error retrieving file directory\n");
- goto abort_connection;
- }
-
-
- LinkedList directoryEntry = LinkedList_getNext(rootDirectory);
-
- while (directoryEntry != NULL) {
-
- FileDirectoryEntry entry = (FileDirectoryEntry) directoryEntry->data;
-
- printf("%s %i\n", FileDirectoryEntry_getFileName(entry), FileDirectoryEntry_getFileSize(entry));
-
- directoryEntry = LinkedList_getNext(directoryEntry);
- }
-
-
- /* Download a file from the server */
- IedConnection_getFile(con, &error, "IEDSERVER.BIN", downloadHandler, NULL);
-
- if (error != IED_ERROR_OK)
- printf("Failed to get file!\n");
-
- /* Delete file at server */
- IedConnection_deleteFile(con, &error, "IEDSERVER.BIN");
-
- if (error != IED_ERROR_OK)
- printf("Failed to delete file! (code=%i)\n", error);
-
- abort_connection:
-
- IedConnection_abort(con, &error);
- }
- else {
- printf("Failed to connect to %s:%i\n", hostname, tcpPort);
- }
-
- IedConnection_destroy(con);
-}
-
-
diff --git a/examples/iec61850_client_example_files/file-tool.c b/examples/iec61850_client_example_files/file-tool.c
new file mode 100644
index 00000000..53f23086
--- /dev/null
+++ b/examples/iec61850_client_example_files/file-tool.c
@@ -0,0 +1,265 @@
+/*
+ * file-tool.c
+ *
+ * This example demonstrates the usage of the file services
+ *
+ * - How to browse the file system of the server
+ * - How to download a file from the server
+ *
+ * Note: intended to be used with server_example3 or server_example_files
+ *
+ * Note: DOES NOT WORK WITH VISUAL STUDIO because of libgen.h
+ *
+ */
+
+#include "iec61850_client.h"
+
+#include
+#include
+#include
+
+static char* hostname = "localhost";
+static int tcpPort = 102;
+static char* filename = NULL;
+
+typedef enum {
+ FileOperationType_None = 0,
+ FileOperationType_Dir,
+ FileOperationType_Info,
+ FileOperationType_Del,
+ FileOperationType_Get,
+ FileOperationType_Set
+} FileOperationType;
+
+static FileOperationType operation = FileOperationType_None;
+
+
+
+static bool
+downloadHandler(void* parameter, uint8_t* buffer, uint32_t bytesRead)
+{
+ FILE* fp = (FILE*) parameter;
+
+ printf("received %i bytes\n", bytesRead);
+
+ if (fwrite(buffer, bytesRead, 1, fp) == 1)
+ return true;
+ else {
+ printf("Failed to write local file!\n");
+ return false;
+ }
+
+}
+
+static void
+printHelp()
+{
+ printf("file-tool [options] []\n");
+ printf(" Options:\n");
+ printf(" -h \n");
+ printf(" -p portnumber\n");
+ printf(" Operations\n");
+ printf(" dir - show directory\n");
+ printf(" info - show file info\n");
+ printf(" del - delete file\n");
+ printf(" get - get file\n");
+ printf(" set - set file\n");
+}
+
+
+static int
+parseOptions(int argc, char** argv)
+{
+ int currentArgc = 1;
+
+ int retVal = 0;
+
+ while (currentArgc < argc) {
+ if (strcmp(argv[currentArgc], "-h") == 0) {
+ hostname = argv[++currentArgc];
+ }
+ else if (strcmp(argv[currentArgc], "-p") == 0) {
+ tcpPort = atoi(argv[++currentArgc]);
+ }
+ else if (strcmp(argv[currentArgc], "del") == 0) {
+ operation = FileOperationType_Del;
+ filename = argv[++currentArgc];
+ }
+ else if (strcmp(argv[currentArgc], "dir") == 0) {
+ operation = FileOperationType_Dir;
+ }
+ else if (strcmp(argv[currentArgc], "info") == 0) {
+ operation = FileOperationType_Info;
+ filename = argv[++currentArgc];
+ }
+ else if (strcmp(argv[currentArgc], "get") == 0) {
+ operation = FileOperationType_Get;
+ filename = argv[++currentArgc];
+ }
+ else if (strcmp(argv[currentArgc], "set") == 0) {
+ operation = FileOperationType_Set;
+ filename = argv[++currentArgc];
+ }
+ else {
+ printf("Unknown operation!\n");
+ return 1;
+ }
+
+ currentArgc++;
+ }
+
+ return retVal;
+}
+
+void
+showDirectory(IedConnection con)
+{
+ IedClientError error;
+
+ /* Get the root directory */
+ LinkedList rootDirectory =
+ IedConnection_getFileDirectory(con, &error, NULL);
+
+ if (error != IED_ERROR_OK) {
+ printf("Error retrieving file directory\n");
+ }
+ else {
+ LinkedList directoryEntry = LinkedList_getNext(rootDirectory);
+
+ while (directoryEntry != NULL) {
+
+ FileDirectoryEntry entry = (FileDirectoryEntry) directoryEntry->data;
+
+ printf("%s %i\n", FileDirectoryEntry_getFileName(entry), FileDirectoryEntry_getFileSize(entry));
+
+ directoryEntry = LinkedList_getNext(directoryEntry);
+ }
+
+ LinkedList_destroyDeep(rootDirectory, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
+ }
+}
+
+void
+getFile(IedConnection con)
+{
+ IedClientError error;
+
+ char* bname = strdup(filename);
+
+ char* localFilename = basename(bname);
+
+ FILE* fp = fopen(localFilename, "w");
+
+ if (fp != NULL) {
+
+ /* Download a file from the server */
+ IedConnection_getFile(con, &error, filename, downloadHandler, (void*) fp);
+
+ if (error != IED_ERROR_OK)
+ printf("Failed to get file!\n");
+
+ fclose(fp);
+ }
+ else
+ printf("Failed to open file %s\n", localFilename);
+
+ free(bname);
+}
+
+void
+setFile(IedConnection con)
+{
+ IedClientError error;
+
+ char* dirc = strdup(filename);
+ char* basec = strdup(filename);
+
+ char* localDirName = dirname(dirc);
+ char* localFileName = basename(basec);
+
+ printf("local dir: %s\n", localDirName);
+ printf("local file: %s\n", localFileName);
+
+ /* IedConnection_setFilestoreBasepath requires the file separator at the end! */
+ strcpy(dirc, localDirName);
+ strcat(dirc, "/");
+
+ printf("filestore basepath: %s\n", dirc);
+
+ IedConnection_setFilestoreBasepath(con, dirc);
+
+ IedConnection_setFile(con, &error, localFileName, localFileName);
+
+ if (error != IED_ERROR_OK)
+ printf("Failed to set file! (code=%i)\n", error);
+
+ free(dirc);
+ free(basec);
+}
+
+void
+deleteFile(IedConnection con)
+{
+ IedClientError error;
+
+ /* Delete file at server */
+ IedConnection_deleteFile(con, &error, filename);
+
+ if (error != IED_ERROR_OK)
+ printf("Failed to delete file! (code=%i)\n", error);
+}
+
+int
+main(int argc, char** argv)
+{
+ if (argc < 2) {
+ printHelp();
+ return 0;
+ }
+
+ parseOptions(argc, argv);
+
+ if (operation == FileOperationType_None) {
+ printHelp();
+ return 0;
+ }
+
+ IedClientError error;
+
+ IedConnection con = IedConnection_create();
+
+ IedConnection_connect(con, &error, hostname, tcpPort);
+
+ if (error == IED_ERROR_OK) {
+
+
+ switch (operation) {
+ case FileOperationType_Dir:
+ showDirectory(con);
+ break;
+ case FileOperationType_Get:
+ getFile(con);
+ break;
+ case FileOperationType_Del:
+ deleteFile(con);
+ break;
+ case FileOperationType_Info:
+ break;
+ case FileOperationType_Set:
+ setFile(con);
+ break;
+ case FileOperationType_None:
+ break;
+ }
+
+
+ IedConnection_abort(con, &error);
+ }
+ else {
+ printf("Failed to connect to %s:%i\n", hostname, tcpPort);
+ }
+
+ IedConnection_destroy(con);
+}
+
+
diff --git a/examples/iec61850_client_example_reporting/client_example_reporting.c b/examples/iec61850_client_example_reporting/client_example_reporting.c
index 1f531171..00c0472c 100644
--- a/examples/iec61850_client_example_reporting/client_example_reporting.c
+++ b/examples/iec61850_client_example_reporting/client_example_reporting.c
@@ -132,7 +132,9 @@ int main(int argc, char** argv) {
Thread_sleep(1000);
- IedConnection_triggerGIReport(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB01");
+ /* Trigger GI Report */
+ ClientReportControlBlock_setGI(rcb, true);
+ IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);
if (error != IED_ERROR_OK) {
printf("Error triggering a GI report (code: %i)\n", error);
diff --git a/examples/mms_client_example1/CMakeLists.txt b/examples/mms_client_example1/CMakeLists.txt
deleted file mode 100644
index 5f5a0273..00000000
--- a/examples/mms_client_example1/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-set(mms_client_example1_SRCS
- mms_client_example1.c
-)
-
-IF(WIN32)
-set_source_files_properties(${mms_client_example1_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(WIN32)
-
-add_executable(mms_client_example1
- ${mms_client_example1_SRCS}
-)
-
-target_link_libraries(mms_client_example1
- iec61850
-)
diff --git a/examples/mms_client_example1/Makefile b/examples/mms_client_example1/Makefile
deleted file mode 100644
index 0e1aeffd..00000000
--- a/examples/mms_client_example1/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-LIBIEC_HOME=../..
-
-PROJECT_BINARY_NAME = mms_client_example1
-PROJECT_SOURCES = mms_client_example1.c
-
-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
-
-$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
-
-clean:
- rm -f $(PROJECT_BINARY_NAME)
diff --git a/examples/mms_client_example1/mms_client_example1.c b/examples/mms_client_example1/mms_client_example1.c
deleted file mode 100644
index d8ad47c6..00000000
--- a/examples/mms_client_example1/mms_client_example1.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * mms_client_example.c
- *
- * This is the most simple example. It illustrates how to create an MmsConnection
- * object and connect to a MMS server.
- *
- * 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
-#include
-#include "mms_client_connection.h"
-#include "hal_thread.h"
-
-int main(int argc, char** argv) {
-
- MmsConnection con = MmsConnection_create();
-
- MmsError mmsError;
-
- if (MmsConnection_connect(con, &mmsError, "localhost", 102)) {
- // add application code here
-
- Thread_sleep(1000);
-
- printf("Send abort\n");
- MmsConnection_abort(con, &mmsError);
- }
- else
- printf("Connect to server failed!\n");
-
- MmsConnection_destroy(con);
-}
-
diff --git a/examples/mms_client_example2/CMakeLists.txt b/examples/mms_client_example2/CMakeLists.txt
deleted file mode 100644
index 15016df7..00000000
--- a/examples/mms_client_example2/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-set(mms_client_example2_SRCS
- mms_client_example2.c
-)
-
-IF(MSVC)
-set_source_files_properties(${mms_client_example2_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(MSVC)
-
-add_executable(mms_client_example2
- ${mms_client_example2_SRCS}
-)
-
-target_link_libraries(mms_client_example2
- iec61850
-)
diff --git a/examples/mms_client_example2/Makefile b/examples/mms_client_example2/Makefile
deleted file mode 100644
index 47f34679..00000000
--- a/examples/mms_client_example2/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-LIBIEC_HOME=../..
-
-PROJECT_BINARY_NAME = mms_client_example2
-PROJECT_SOURCES = mms_client_example2.c
-
-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
-
-$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
-
-clean:
- rm -f $(PROJECT_BINARY_NAME)
diff --git a/examples/mms_client_example2/mms_client_example2.c b/examples/mms_client_example2/mms_client_example2.c
deleted file mode 100644
index 908cb912..00000000
--- a/examples/mms_client_example2/mms_client_example2.c
+++ /dev/null
@@ -1,64 +0,0 @@
-
-#include
-#include
-#include "mms_client_connection.h"
-
-int main(int argc, char** argv) {
-
- char* hostname;
- int tcpPort = 102;
-
- if (argc > 1)
- hostname = argv[1];
- else
- hostname = "localhost";
-
- if (argc > 2)
- tcpPort = atoi(argv[2]);
-
- MmsConnection con = MmsConnection_create();
-
- MmsError mmsError;
-
- /* Set maximum MMS PDU size (local detail) to 2000 byte */
- MmsConnection_setLocalDetail(con, 2000);
-
- if (!MmsConnection_connect(con, &mmsError, hostname, tcpPort)) {
- printf("MMS connect failed!\n");
- goto exit;
- }
- else
- printf("MMS connected.\n\n");
-
- printf("Domains present on server:\n--------------------------\n");
- LinkedList nameList = MmsConnection_getDomainNames(con, &mmsError);
- LinkedList_printStringList(nameList);
- printf("\n");
-
- LinkedList element = nameList;
-
- while ((element = LinkedList_getNext(element)) != NULL) {
- printf("\nNamed variables in domain: %s\n-------------------------------------------------\n", (char*) element->data);
-
- LinkedList variableList = MmsConnection_getDomainVariableNames(con, &mmsError, (char*) element->data);
-
- LinkedList_printStringList(variableList);
-
- LinkedList_destroy(variableList);
-
- printf("\nNamed variable lists (data sets) in domain: %s\n", (char*) element->data);
-
- LinkedList dataSetList = MmsConnection_getDomainVariableListNames(con, &mmsError, (char*) element->data);
-
- LinkedList_printStringList(dataSetList);
-
- LinkedList_destroy(dataSetList);
-
- }
-
- LinkedList_destroy(nameList);
-
-exit:
- MmsConnection_destroy(con);
-}
-
diff --git a/examples/mms_client_example3/CMakeLists.txt b/examples/mms_client_example3/CMakeLists.txt
deleted file mode 100644
index df110000..00000000
--- a/examples/mms_client_example3/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-set(mms_client_example3_SRCS
- mms_client_example3.c
-)
-
-IF(MSVC)
-set_source_files_properties(${mms_client_example3_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(MSVC)
-
-add_executable(mms_client_example3
- ${mms_client_example3_SRCS}
-)
-
-target_link_libraries(mms_client_example3
- iec61850
-)
diff --git a/examples/mms_client_example3/Makefile b/examples/mms_client_example3/Makefile
deleted file mode 100644
index eb6fa6c2..00000000
--- a/examples/mms_client_example3/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-LIBIEC_HOME=../..
-
-PROJECT_BINARY_NAME = mms_client_example3
-PROJECT_SOURCES = mms_client_example3.c
-
-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
-
-$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
-
-clean:
- rm -f $(PROJECT_BINARY_NAME)
diff --git a/examples/mms_client_example3/mms_client_example3.c b/examples/mms_client_example3/mms_client_example3.c
deleted file mode 100644
index eb04c1cc..00000000
--- a/examples/mms_client_example3/mms_client_example3.c
+++ /dev/null
@@ -1,41 +0,0 @@
-
-#include
-#include
-#include "mms_client_connection.h"
-
-int main(int argc, char** argv) {
-
- char* hostname;
- int tcpPort = 102;
-
- if (argc > 1)
- hostname = argv[1];
- else
- hostname = "localhost";
-
- if (argc > 2)
- tcpPort = atoi(argv[2]);
-
- MmsConnection con = MmsConnection_create();
-
- MmsError error;
-
- if (!MmsConnection_connect(con, &error, hostname, tcpPort)) {
- printf("MMS connect failed!\n");
- goto exit;
- }
- else
- printf("MMS connected.\n\n");
-
- MmsValue* value =
- MmsConnection_readVariable(con, &error, "simpleIOGenericIO", "LLN0$GO");
-
- if (value == NULL)
- printf("reading value failed!\n");
- else
- MmsValue_delete(value);
-
-exit:
- MmsConnection_destroy(con);
-}
-
diff --git a/examples/mms_client_example4/CMakeLists.txt b/examples/mms_client_example4/CMakeLists.txt
deleted file mode 100644
index 96b9edfc..00000000
--- a/examples/mms_client_example4/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-set(mms_client_example4_SRCS
- mms_client_example4.c
-)
-
-IF(MSVC)
-set_source_files_properties(${mms_client_example4_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(MSVC)
-
-add_executable(mms_client_example4
- ${mms_client_example4_SRCS}
-)
-
-target_link_libraries(mms_client_example4
- iec61850
-)
diff --git a/examples/mms_client_example4/Makefile b/examples/mms_client_example4/Makefile
deleted file mode 100644
index 30451ce5..00000000
--- a/examples/mms_client_example4/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-LIBIEC_HOME=../..
-
-PROJECT_BINARY_NAME = mms_client_example4
-PROJECT_SOURCES = mms_client_example4.c
-
-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
-
-$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
-
-clean:
- rm -f $(PROJECT_BINARY_NAME)
diff --git a/examples/mms_client_example4/mms_client_example4.c b/examples/mms_client_example4/mms_client_example4.c
deleted file mode 100644
index 13a8d225..00000000
--- a/examples/mms_client_example4/mms_client_example4.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * mms_client_example.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
-#include
-#include "mms_client_connection.h"
-
-int main(int argc, char** argv) {
-
- char* hostname;
- int tcpPort = 102;
-
- if (argc > 1)
- hostname = argv[1];
- else
- hostname = "localhost";
-
- if (argc > 2)
- tcpPort = atoi(argv[2]);
-
- MmsConnection con = MmsConnection_create();
-
- MmsError mmsError;
-
- char* password = "testpw";
-
- /* use authentication */
- AcseAuthenticationParameter auth = (AcseAuthenticationParameter) calloc(1, sizeof(struct sAcseAuthenticationParameter));
- auth->mechanism = ACSE_AUTH_PASSWORD;
- auth->value.password.octetString= (uint8_t*) password;
- auth->value.password.passwordLength = strlen(password);
-
- IsoConnectionParameters connectionParameters =
- MmsConnection_getIsoConnectionParameters(con);
-
- IsoConnectionParameters_setAcseAuthenticationParameter(connectionParameters, auth);
-
- if (!MmsConnection_connect(con, &mmsError, hostname, tcpPort)) {
- printf("MMS connect failed!\n");
- goto exit;
- }
- else
- printf("MMS connected.\n\n");
-
- printf("Domains present on server:\n--------------------------\n");
- LinkedList nameList = MmsConnection_getDomainNames(con, &mmsError);
- LinkedList_printStringList(nameList);
- LinkedList_destroy(nameList);
- printf("\n");
-
-
- printf("Named variables for domain SampleIEDDevice1:\n--------------------------------------------\n");
- nameList = MmsConnection_getDomainVariableNames(con, &mmsError, "SampleIEDDevice1");
- LinkedList_printStringList(nameList);
- LinkedList_destroy(nameList);
- printf("\n");
-
- printf("Data sets for domain SampleIEDDevice1:\n--------------------------------------------\n");
- nameList = MmsConnection_getDomainVariableListNames(con, &mmsError, "SampleIEDDevice1");
- LinkedList_printStringList(nameList);
- LinkedList_destroy(nameList);
- printf("\n");
-
-exit:
- MmsConnection_destroy(con);
-}
-
diff --git a/examples/mms_client_example5/CMakeLists.txt b/examples/mms_client_example5/CMakeLists.txt
deleted file mode 100644
index fdc6f0a5..00000000
--- a/examples/mms_client_example5/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-set(mms_client_example5_SRCS
- mms_client_example5.c
-)
-
-IF(WIN32)
-set_source_files_properties(${mms_client_example5_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(WIN32)
-
-add_executable(mms_client_example5
- ${mms_client_example5_SRCS}
-)
-
-target_link_libraries(mms_client_example5
- iec61850
-)
diff --git a/examples/mms_client_example5/Makefile b/examples/mms_client_example5/Makefile
deleted file mode 100644
index 72d220c2..00000000
--- a/examples/mms_client_example5/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-LIBIEC_HOME=../..
-
-PROJECT_BINARY_NAME = mms_client_example5
-PROJECT_SOURCES = mms_client_example5.c
-
-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
-
-$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
-
-clean:
- rm -f $(PROJECT_BINARY_NAME)
diff --git a/examples/mms_client_example5/mms_client_example5.c b/examples/mms_client_example5/mms_client_example5.c
deleted file mode 100644
index ae050406..00000000
--- a/examples/mms_client_example5/mms_client_example5.c
+++ /dev/null
@@ -1,50 +0,0 @@
-
-#include
-#include
-#include "mms_client_connection.h"
-
-int main(int argc, char** argv) {
-
- char* hostname;
- int tcpPort = 102;
-
- if (argc > 1)
- hostname = argv[1];
- else
- hostname = "localhost";
-
- if (argc > 2)
- tcpPort = atoi(argv[2]);
-
- MmsConnection con = MmsConnection_create();
-
- MmsError error;
-
- if (!MmsConnection_connect(con, &error, hostname, tcpPort)) {
- printf("MMS connect failed!\n");
- goto exit;
- }
- else
- printf("MMS connected.\n\n");
-
- LinkedList dataSetEntries = LinkedList_create();
-
- MmsVariableAccessSpecification* dataSetEntry =
- MmsVariableAccessSpecification_create("BayControllerQ", "QA1CSWI1$ST$Pos");
-
- LinkedList_add(dataSetEntries, (void*) dataSetEntry);
-
- dataSetEntry =
- MmsVariableAccessSpecification_create("BayControllerQ", "QA1XCBR1$ST$Pos");
-
- LinkedList_add(dataSetEntries, (void*) dataSetEntry);
-
- MmsConnection_defineNamedVariableList(con, &error, "BayControllerQ", "LLN0$LIBIEC61850_CLIENT", dataSetEntries);
-
- /* delete list and all elements */
- LinkedList_destroy(dataSetEntries);
-
-exit:
- MmsConnection_destroy(con);
-}
-
diff --git a/examples/mms_utility/mms_utility.c b/examples/mms_utility/mms_utility.c
index da6ca126..f505348e 100644
--- a/examples/mms_utility/mms_utility.c
+++ b/examples/mms_utility/mms_utility.c
@@ -21,7 +21,9 @@ print_help()
printf("-a specify domain for read or write command\n");
printf("-f show file list\n");
printf("-g get file attributes\n");
+ printf("-x delete file\n");
printf("-j read journal\n");
+ printf("-v read domain variable list\n");
printf("-m print raw MMS messages\n");
}
@@ -79,7 +81,7 @@ printJournalEntries(LinkedList journalEntries)
}
}
-void*
+void
printRawMmsMessage(void* parameter, uint8_t* message, int messageLength, bool received)
{
if (received)
@@ -115,10 +117,12 @@ int main(int argc, char** argv) {
int getFileAttributes = 0;
int readJournal = 0;
int printRawMmsMessages = 0;
+ int deleteFile = 0;
+ int readVariableList = 0;
int c;
- while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:")) != -1)
+ while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:v:")) != -1)
switch (c) {
case 'm':
printRawMmsMessages = 1;
@@ -151,6 +155,10 @@ int main(int argc, char** argv) {
readVariable = 1;
variableName = StringUtils_copyString(optarg);
break;
+ case 'v':
+ readVariableList = 1;
+ variableName = StringUtils_copyString(optarg);
+ break;
case 'f':
showFileList = 1;
break;
@@ -158,6 +166,10 @@ int main(int argc, char** argv) {
getFileAttributes = 1;
filename = StringUtils_copyString(optarg);
break;
+ case 'x':
+ deleteFile = 1;
+ filename = StringUtils_copyString(optarg);
+ break;
case 'j':
readJournal = 1;
@@ -336,6 +348,21 @@ int main(int argc, char** argv) {
printf("Reading VMD scope variable not yet supported!\n");
}
+ if (readVariableList) {
+ if (readWriteHasDomain) {
+ MmsValue* variables = MmsConnection_readNamedVariableListValues(con, &error, domainName, variableName, true);
+
+ if (error != MMS_ERROR_NONE) {
+ printf("Reading variable failed: (ERROR %i)\n", error);
+ }
+ else {
+ printf("Read SUCCESS\n");
+ }
+ }
+ else
+ printf("Reading VMD scope variable list not yet supported!\n");
+ }
+
if (showFileList) {
char lastName[300];
lastName[0] = 0;
@@ -351,6 +378,17 @@ int main(int argc, char** argv) {
MmsConnection_getFileDirectory(con, &error, filename, NULL, mmsGetFileAttributeHandler, NULL);
}
+ if (deleteFile) {
+ MmsConnection_fileDelete(con, &error, filename);
+
+ if (error != MMS_ERROR_NONE) {
+ printf("Delete file failed: (ERROR %i)\n", error);
+ }
+ else {
+ printf("File deleted\n");
+ }
+ }
+
exit:
free(hostname);
MmsConnection_destroy(con);
diff --git a/examples/server_example1/CMakeLists.txt b/examples/server_example1/CMakeLists.txt
deleted file mode 100644
index 35210905..00000000
--- a/examples/server_example1/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-include_directories(
- .
-)
-
-set(server_example1_SRCS
- server_example1.c
- static_model.c
-)
-
-IF(WIN32)
-set_source_files_properties(${server_example1_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(WIN32)
-
-add_executable(server_example1
- ${server_example1_SRCS}
-)
-
-target_link_libraries(server_example1
- iec61850
-)
diff --git a/examples/server_example2/CMakeLists.txt b/examples/server_example2/CMakeLists.txt
deleted file mode 100644
index 994caae3..00000000
--- a/examples/server_example2/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-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/server_example2/Makefile b/examples/server_example2/Makefile
deleted file mode 100644
index 3781758b..00000000
--- a/examples/server_example2/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-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/server_example2/complexModel.icd b/examples/server_example2/complexModel.icd
deleted file mode 100644
index 52cfec61..00000000
--- a/examples/server_example2/complexModel.icd
+++ /dev/null
@@ -1,347 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- status-only
-
-
-
-
-
-
-
- status-only
-
-
-
-
-
-
- status-only
-
-
-
-
-
-
-
-
- status-only
-
-
-
-
-
-
-
- status-only
-
-
-
-
-
-
- status-only
-
-
-
-
-
-
-
-
- status-only
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- status-only
- direct-with-normal-security
- sbo-with-normal-security
- direct-with-enhanced-security
- sbo-with-enhanced-security
-
-
-
-
- rad
- sr
- m
- Gy
- q
- °C
- Sv
- F
- C
- S
- H
- V
- kg
- ohm
- J
- N
- Hz
- Ix
- Lm
- Wb
- T
- W
- Pa
- s
- m²
- m³
- m/s
- m/s²
- m³/s
- m/m³
- M
- kg/m³
- m²/s
- A
- W/m K
- J/K
- ppm
- 1/s
- rad/s
- K
- VA
- Watts
- VAr
- theta
- cos(theta)
- Vs
- V²
- As
- A²
- mol
- A²t
- VAh
- Wh
- VArh
- V/Hz
- cd
- deg
-
-
- Yocto
- Zepto
- Atto
- Femto
- Pico
- Nano
- Micro
- Milli
- Centi
- Deci
- zeroNoValue
- Deca
- Hecto
- Kilo
- Mega
- Giga
- Tera
- Petra
- Exa
- Zetta
- Yotta
-
-
- normal
- high
- low
- high-high
- low-low
-
-
-
diff --git a/examples/server_example2/server_example2.c b/examples/server_example2/server_example2.c
deleted file mode 100644
index 6d7f3519..00000000
--- a/examples/server_example2/server_example2.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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_lockDataModel(iedServer);
-
- IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_Inverter_MMXU1_TotW_t, timeval);
- IedServer_updateFloatAttributeValue(iedServer, IEDMODEL_Inverter_MMXU1_TotW_mag_f, power);
-
- 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/server_example2/static_model.c b/examples/server_example2/static_model.c
deleted file mode 100644
index 91d0dcb0..00000000
--- a/examples/server_example2/static_model.c
+++ /dev/null
@@ -1,3621 +0,0 @@
-/*
- * static_model.c
- *
- * automatically generated from complexModel.icd
- */
-#include "static_model.h"
-
-static void initializeValues();
-
-extern DataSet iedModelds_Inverter_LLN0_dataset1;
-
-
-extern DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda0;
-extern DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda1;
-extern DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda2;
-extern DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda3;
-extern DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda4;
-
-DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda0 = {
- "Inverter",
- false,
- "LLN0$ST$Mod$q",
- -1,
- NULL,
- NULL,
- &iedModelds_Inverter_LLN0_dataset1_fcda1
-};
-
-DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda1 = {
- "Battery",
- false,
- "LLN0$ST$Mod$q",
- -1,
- NULL,
- NULL,
- &iedModelds_Inverter_LLN0_dataset1_fcda2
-};
-
-DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda2 = {
- "Inverter",
- false,
- "MMXU1$ST$Mod$q",
- -1,
- NULL,
- NULL,
- &iedModelds_Inverter_LLN0_dataset1_fcda3
-};
-
-DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda3 = {
- "Inverter",
- false,
- "MMXU1$CF$Mod$ctlModel",
- -1,
- NULL,
- NULL,
- &iedModelds_Inverter_LLN0_dataset1_fcda4
-};
-
-DataSetEntry iedModelds_Inverter_LLN0_dataset1_fcda4 = {
- "Inverter",
- false,
- "MMXU1$MX$TotW$mag",
- -1,
- NULL,
- NULL,
- NULL
-};
-
-DataSet iedModelds_Inverter_LLN0_dataset1 = {
- "Inverter",
- "LLN0$dataset1",
- 5,
- &iedModelds_Inverter_LLN0_dataset1_fcda0,
- NULL
-};
-
-LogicalDevice iedModel_Inverter = {
- LogicalDeviceModelType,
- "Inverter",
- (ModelNode*) &iedModel,
- (ModelNode*) &iedModel_Battery,
- (ModelNode*) &iedModel_Inverter_LLN0
-};
-
-LogicalNode iedModel_Inverter_LLN0 = {
- LogicalNodeModelType,
- "LLN0",
- (ModelNode*) &iedModel_Inverter,
- (ModelNode*) &iedModel_Inverter_LPHD1,
- (ModelNode*) &iedModel_Inverter_LLN0_Mod,
-};
-
-DataObject iedModel_Inverter_LLN0_Mod = {
- DataObjectModelType,
- "Mod",
- (ModelNode*) &iedModel_Inverter_LLN0,
- (ModelNode*) &iedModel_Inverter_LLN0_Beh,
- (ModelNode*) &iedModel_Inverter_LLN0_Mod_q,
- 0
-};
-
-DataAttribute iedModel_Inverter_LLN0_Mod_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_LLN0_Mod,
- (ModelNode*) &iedModel_Inverter_LLN0_Mod_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_Mod_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_LLN0_Mod,
- (ModelNode*) &iedModel_Inverter_LLN0_Mod_ctlModel,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_Mod_ctlModel = {
- DataAttributeModelType,
- "ctlModel",
- (ModelNode*) &iedModel_Inverter_LLN0_Mod,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_LLN0_Beh = {
- DataObjectModelType,
- "Beh",
- (ModelNode*) &iedModel_Inverter_LLN0,
- (ModelNode*) &iedModel_Inverter_LLN0_Health,
- (ModelNode*) &iedModel_Inverter_LLN0_Beh_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_LLN0_Beh_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_LLN0_Beh,
- (ModelNode*) &iedModel_Inverter_LLN0_Beh_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_Beh_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_LLN0_Beh,
- (ModelNode*) &iedModel_Inverter_LLN0_Beh_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_Beh_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_LLN0_Beh,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_LLN0_Health = {
- DataObjectModelType,
- "Health",
- (ModelNode*) &iedModel_Inverter_LLN0,
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt,
- (ModelNode*) &iedModel_Inverter_LLN0_Health_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_LLN0_Health_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_LLN0_Health,
- (ModelNode*) &iedModel_Inverter_LLN0_Health_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_Health_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_LLN0_Health,
- (ModelNode*) &iedModel_Inverter_LLN0_Health_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_Health_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_LLN0_Health,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_LLN0_NamPlt = {
- DataObjectModelType,
- "NamPlt",
- (ModelNode*) &iedModel_Inverter_LLN0,
- NULL,
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt_vendor,
- 0
-};
-
-DataAttribute iedModel_Inverter_LLN0_NamPlt_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt,
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt_swRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_NamPlt_swRev = {
- DataAttributeModelType,
- "swRev",
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt,
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt_d,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_NamPlt_d = {
- DataAttributeModelType,
- "d",
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt,
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt_configRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_NamPlt_configRev = {
- DataAttributeModelType,
- "configRev",
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt,
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt_ldNs,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LLN0_NamPlt_ldNs = {
- DataAttributeModelType,
- "ldNs",
- (ModelNode*) &iedModel_Inverter_LLN0_NamPlt,
- NULL,
- NULL,
- 0,
- IEC61850_FC_EX,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-LogicalNode iedModel_Inverter_LPHD1 = {
- LogicalNodeModelType,
- "LPHD1",
- (ModelNode*) &iedModel_Inverter,
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyNam,
-};
-
-DataObject iedModel_Inverter_LPHD1_PhyNam = {
- DataObjectModelType,
- "PhyNam",
- (ModelNode*) &iedModel_Inverter_LPHD1,
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyNam_vendor,
- 0
-};
-
-DataAttribute iedModel_Inverter_LPHD1_PhyNam_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyNam,
- NULL,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_LPHD1_PhyHealth = {
- DataObjectModelType,
- "PhyHealth",
- (ModelNode*) &iedModel_Inverter_LPHD1,
- (ModelNode*) &iedModel_Inverter_LPHD1_Proxy,
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyHealth_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_LPHD1_PhyHealth_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyHealth_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LPHD1_PhyHealth_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyHealth_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LPHD1_PhyHealth_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_LPHD1_PhyHealth,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_LPHD1_Proxy = {
- DataObjectModelType,
- "Proxy",
- (ModelNode*) &iedModel_Inverter_LPHD1,
- NULL,
- (ModelNode*) &iedModel_Inverter_LPHD1_Proxy_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_LPHD1_Proxy_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_LPHD1_Proxy,
- (ModelNode*) &iedModel_Inverter_LPHD1_Proxy_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_BOOLEAN,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LPHD1_Proxy_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_LPHD1_Proxy,
- (ModelNode*) &iedModel_Inverter_LPHD1_Proxy_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_LPHD1_Proxy_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_LPHD1_Proxy,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-LogicalNode iedModel_Inverter_ZINV1 = {
- LogicalNodeModelType,
- "ZINV1",
- (ModelNode*) &iedModel_Inverter,
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_ZINV1_Mod,
-};
-
-DataObject iedModel_Inverter_ZINV1_Mod = {
- DataObjectModelType,
- "Mod",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_Beh,
- (ModelNode*) &iedModel_Inverter_ZINV1_Mod_q,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_Mod_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_ZINV1_Mod,
- (ModelNode*) &iedModel_Inverter_ZINV1_Mod_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_Mod_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_ZINV1_Mod,
- (ModelNode*) &iedModel_Inverter_ZINV1_Mod_ctlModel,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_Mod_ctlModel = {
- DataAttributeModelType,
- "ctlModel",
- (ModelNode*) &iedModel_Inverter_ZINV1_Mod,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_Beh = {
- DataObjectModelType,
- "Beh",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_Health,
- (ModelNode*) &iedModel_Inverter_ZINV1_Beh_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_Beh_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_ZINV1_Beh,
- (ModelNode*) &iedModel_Inverter_ZINV1_Beh_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_Beh_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_ZINV1_Beh,
- (ModelNode*) &iedModel_Inverter_ZINV1_Beh_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_Beh_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_ZINV1_Beh,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_Health = {
- DataObjectModelType,
- "Health",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_NamPlt,
- (ModelNode*) &iedModel_Inverter_ZINV1_Health_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_Health_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_ZINV1_Health,
- (ModelNode*) &iedModel_Inverter_ZINV1_Health_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_Health_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_ZINV1_Health,
- (ModelNode*) &iedModel_Inverter_ZINV1_Health_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_Health_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_ZINV1_Health,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_NamPlt = {
- DataObjectModelType,
- "NamPlt",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg,
- (ModelNode*) &iedModel_Inverter_ZINV1_NamPlt_vendor,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_NamPlt_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Inverter_ZINV1_NamPlt,
- (ModelNode*) &iedModel_Inverter_ZINV1_NamPlt_swRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_NamPlt_swRev = {
- DataAttributeModelType,
- "swRev",
- (ModelNode*) &iedModel_Inverter_ZINV1_NamPlt,
- (ModelNode*) &iedModel_Inverter_ZINV1_NamPlt_d,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_NamPlt_d = {
- DataAttributeModelType,
- "d",
- (ModelNode*) &iedModel_Inverter_ZINV1_NamPlt,
- NULL,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_WRtg = {
- DataObjectModelType,
- "WRtg",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg,
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg_setMag,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_WRtg_setMag = {
- DataAttributeModelType,
- "setMag",
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg,
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg_units,
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg_setMag_f,
- 0,
- IEC61850_FC_SP,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_WRtg_setMag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg_setMag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_SP,
- IEC61850_FLOAT32,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_WRtg_units = {
- DataAttributeModelType,
- "units",
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg,
- NULL,
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg_units_SIUnit,
- 0,
- IEC61850_FC_CF,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_WRtg_units_SIUnit = {
- DataAttributeModelType,
- "SIUnit",
- (ModelNode*) &iedModel_Inverter_ZINV1_WRtg_units,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_VarRtg = {
- DataObjectModelType,
- "VarRtg",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_ACTyp,
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg_setMag,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_VarRtg_setMag = {
- DataAttributeModelType,
- "setMag",
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg,
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg_units,
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg_setMag_f,
- 0,
- IEC61850_FC_SP,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_VarRtg_setMag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg_setMag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_SP,
- IEC61850_FLOAT32,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_VarRtg_units = {
- DataAttributeModelType,
- "units",
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg,
- NULL,
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg_units_SIUnit,
- 0,
- IEC61850_FC_CF,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_VarRtg_units_SIUnit = {
- DataAttributeModelType,
- "SIUnit",
- (ModelNode*) &iedModel_Inverter_ZINV1_VarRtg_units,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_ACTyp = {
- DataObjectModelType,
- "ACTyp",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet,
- (ModelNode*) &iedModel_Inverter_ZINV1_ACTyp_setVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_ACTyp_setVal = {
- DataAttributeModelType,
- "setVal",
- (ModelNode*) &iedModel_Inverter_ZINV1_ACTyp,
- NULL,
- NULL,
- 0,
- IEC61850_FC_SP,
- IEC61850_INT32,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_OutWSet = {
- DataObjectModelType,
- "OutWSet",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet_setMag,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_OutWSet_setMag = {
- DataAttributeModelType,
- "setMag",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet_units,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet_setMag_f,
- 0,
- IEC61850_FC_SP,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_OutWSet_setMag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet_setMag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_SP,
- IEC61850_FLOAT32,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_OutWSet_units = {
- DataAttributeModelType,
- "units",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet,
- NULL,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet_units_SIUnit,
- 0,
- IEC61850_FC_CF,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_OutWSet_units_SIUnit = {
- DataAttributeModelType,
- "SIUnit",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutWSet_units,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_ZINV1_OutVarSet = {
- DataObjectModelType,
- "OutVarSet",
- (ModelNode*) &iedModel_Inverter_ZINV1,
- NULL,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet_setMag,
- 0
-};
-
-DataAttribute iedModel_Inverter_ZINV1_OutVarSet_setMag = {
- DataAttributeModelType,
- "setMag",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet_units,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet_setMag_f,
- 0,
- IEC61850_FC_SP,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_OutVarSet_setMag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet_setMag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_SP,
- IEC61850_FLOAT32,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_OutVarSet_units = {
- DataAttributeModelType,
- "units",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet,
- NULL,
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet_units_SIUnit,
- 0,
- IEC61850_FC_CF,
- IEC61850_CONSTRUCTED,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_ZINV1_OutVarSet_units_SIUnit = {
- DataAttributeModelType,
- "SIUnit",
- (ModelNode*) &iedModel_Inverter_ZINV1_OutVarSet_units,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-LogicalNode iedModel_Inverter_MMXU1 = {
- LogicalNodeModelType,
- "MMXU1",
- (ModelNode*) &iedModel_Inverter,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_Mod,
-};
-
-DataObject iedModel_Inverter_MMXU1_Mod = {
- DataObjectModelType,
- "Mod",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_Beh,
- (ModelNode*) &iedModel_Inverter_MMXU1_Mod_q,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_Mod_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_Mod,
- (ModelNode*) &iedModel_Inverter_MMXU1_Mod_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Mod_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_Mod,
- (ModelNode*) &iedModel_Inverter_MMXU1_Mod_ctlModel,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Mod_ctlModel = {
- DataAttributeModelType,
- "ctlModel",
- (ModelNode*) &iedModel_Inverter_MMXU1_Mod,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_Beh = {
- DataObjectModelType,
- "Beh",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_Health,
- (ModelNode*) &iedModel_Inverter_MMXU1_Beh_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_Beh_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_Beh,
- (ModelNode*) &iedModel_Inverter_MMXU1_Beh_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Beh_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_Beh,
- (ModelNode*) &iedModel_Inverter_MMXU1_Beh_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Beh_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_Beh,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_Health = {
- DataObjectModelType,
- "Health",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_NamPlt,
- (ModelNode*) &iedModel_Inverter_MMXU1_Health_stVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_Health_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_Health,
- (ModelNode*) &iedModel_Inverter_MMXU1_Health_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Health_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_Health,
- (ModelNode*) &iedModel_Inverter_MMXU1_Health_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Health_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_Health,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_NamPlt = {
- DataObjectModelType,
- "NamPlt",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW,
- (ModelNode*) &iedModel_Inverter_MMXU1_NamPlt_vendor,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_NamPlt_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Inverter_MMXU1_NamPlt,
- (ModelNode*) &iedModel_Inverter_MMXU1_NamPlt_swRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_NamPlt_swRev = {
- DataAttributeModelType,
- "swRev",
- (ModelNode*) &iedModel_Inverter_MMXU1_NamPlt,
- (ModelNode*) &iedModel_Inverter_MMXU1_NamPlt_d,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_NamPlt_d = {
- DataAttributeModelType,
- "d",
- (ModelNode*) &iedModel_Inverter_MMXU1_NamPlt,
- NULL,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_TotW = {
- DataObjectModelType,
- "TotW",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW_mag,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_TotW_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotW_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotW_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotW_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotW,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_TotVAr = {
- DataObjectModelType,
- "TotVAr",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr_mag,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVAr_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVAr_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVAr_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVAr_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVAr,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_TotVA = {
- DataObjectModelType,
- "TotVA",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA_mag,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVA_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVA_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVA_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA,
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_TotVA_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_TotVA,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_Hz = {
- DataObjectModelType,
- "Hz",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV,
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz_mag,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_Hz_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz,
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Hz_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Hz_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz,
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_Hz_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_Hz,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_PhV = {
- DataObjectModelType,
- "PhV",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_A,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA,
- 0
-};
-
-DataObject iedModel_Inverter_MMXU1_PhV_phsA = {
- DataObjectModelType,
- "phsA",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsA,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_PhV_phsB = {
- DataObjectModelType,
- "phsB",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsB,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_PhV_phsC = {
- DataObjectModelType,
- "phsC",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_phsC,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_PhV_neut = {
- DataObjectModelType,
- "neut",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_neut_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_neut_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_neut_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_neut_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut,
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_PhV_neut_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_PhV_neut,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_A = {
- DataObjectModelType,
- "A",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- (ModelNode*) &iedModel_Inverter_MMXU1_W,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA,
- 0
-};
-
-DataObject iedModel_Inverter_MMXU1_A_phsA = {
- DataObjectModelType,
- "phsA",
- (ModelNode*) &iedModel_Inverter_MMXU1_A,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsA_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsA_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsA_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsA_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsA_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsA,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_A_phsB = {
- DataObjectModelType,
- "phsB",
- (ModelNode*) &iedModel_Inverter_MMXU1_A,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsB_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsB_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsB_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsB_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsB_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsB,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_A_phsC = {
- DataObjectModelType,
- "phsC",
- (ModelNode*) &iedModel_Inverter_MMXU1_A,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsC_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsC_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsC_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsC_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_phsC_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_phsC,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_A_neut = {
- DataObjectModelType,
- "neut",
- (ModelNode*) &iedModel_Inverter_MMXU1_A,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_A_neut_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_neut_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_neut_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_neut_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut,
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_A_neut_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_A_neut,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_W = {
- DataObjectModelType,
- "W",
- (ModelNode*) &iedModel_Inverter_MMXU1,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA,
- 0
-};
-
-DataObject iedModel_Inverter_MMXU1_W_phsA = {
- DataObjectModelType,
- "phsA",
- (ModelNode*) &iedModel_Inverter_MMXU1_W,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsA_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsA_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsA_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsA_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsA_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsA,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_W_phsB = {
- DataObjectModelType,
- "phsB",
- (ModelNode*) &iedModel_Inverter_MMXU1_W,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsB_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsB_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsB_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsB_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsB_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsB,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Inverter_MMXU1_W_phsC = {
- DataObjectModelType,
- "phsC",
- (ModelNode*) &iedModel_Inverter_MMXU1_W,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC_cVal,
- 0
-};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsC_cVal = {
- DataAttributeModelType,
- "cVal",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC_q,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC_cVal_mag,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsC_cVal_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC_cVal,
- NULL,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC_cVal_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsC_cVal_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC_cVal_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsC_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC,
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Inverter_MMXU1_W_phsC_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Inverter_MMXU1_W_phsC,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-
-LogicalDevice iedModel_Battery = {
- LogicalDeviceModelType,
- "Battery",
- (ModelNode*) &iedModel,
- (ModelNode*) &iedModel_Physical_Measurements,
- (ModelNode*) &iedModel_Battery_LLN0
-};
-
-LogicalNode iedModel_Battery_LLN0 = {
- LogicalNodeModelType,
- "LLN0",
- (ModelNode*) &iedModel_Battery,
- (ModelNode*) &iedModel_Battery_LPHD1,
- (ModelNode*) &iedModel_Battery_LLN0_Mod,
-};
-
-DataObject iedModel_Battery_LLN0_Mod = {
- DataObjectModelType,
- "Mod",
- (ModelNode*) &iedModel_Battery_LLN0,
- (ModelNode*) &iedModel_Battery_LLN0_Beh,
- (ModelNode*) &iedModel_Battery_LLN0_Mod_q,
- 0
-};
-
-DataAttribute iedModel_Battery_LLN0_Mod_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_LLN0_Mod,
- (ModelNode*) &iedModel_Battery_LLN0_Mod_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_Mod_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_LLN0_Mod,
- (ModelNode*) &iedModel_Battery_LLN0_Mod_ctlModel,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_Mod_ctlModel = {
- DataAttributeModelType,
- "ctlModel",
- (ModelNode*) &iedModel_Battery_LLN0_Mod,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_LLN0_Beh = {
- DataObjectModelType,
- "Beh",
- (ModelNode*) &iedModel_Battery_LLN0,
- (ModelNode*) &iedModel_Battery_LLN0_Health,
- (ModelNode*) &iedModel_Battery_LLN0_Beh_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_LLN0_Beh_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_LLN0_Beh,
- (ModelNode*) &iedModel_Battery_LLN0_Beh_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_Beh_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_LLN0_Beh,
- (ModelNode*) &iedModel_Battery_LLN0_Beh_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_Beh_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_LLN0_Beh,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_LLN0_Health = {
- DataObjectModelType,
- "Health",
- (ModelNode*) &iedModel_Battery_LLN0,
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt,
- (ModelNode*) &iedModel_Battery_LLN0_Health_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_LLN0_Health_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_LLN0_Health,
- (ModelNode*) &iedModel_Battery_LLN0_Health_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_Health_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_LLN0_Health,
- (ModelNode*) &iedModel_Battery_LLN0_Health_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_Health_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_LLN0_Health,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_LLN0_NamPlt = {
- DataObjectModelType,
- "NamPlt",
- (ModelNode*) &iedModel_Battery_LLN0,
- NULL,
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt_vendor,
- 0
-};
-
-DataAttribute iedModel_Battery_LLN0_NamPlt_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt,
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt_swRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_NamPlt_swRev = {
- DataAttributeModelType,
- "swRev",
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt,
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt_d,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_NamPlt_d = {
- DataAttributeModelType,
- "d",
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt,
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt_configRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_NamPlt_configRev = {
- DataAttributeModelType,
- "configRev",
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt,
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt_ldNs,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LLN0_NamPlt_ldNs = {
- DataAttributeModelType,
- "ldNs",
- (ModelNode*) &iedModel_Battery_LLN0_NamPlt,
- NULL,
- NULL,
- 0,
- IEC61850_FC_EX,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-LogicalNode iedModel_Battery_LPHD1 = {
- LogicalNodeModelType,
- "LPHD1",
- (ModelNode*) &iedModel_Battery,
- (ModelNode*) &iedModel_Battery_ZBAT1,
- (ModelNode*) &iedModel_Battery_LPHD1_PhyNam,
-};
-
-DataObject iedModel_Battery_LPHD1_PhyNam = {
- DataObjectModelType,
- "PhyNam",
- (ModelNode*) &iedModel_Battery_LPHD1,
- (ModelNode*) &iedModel_Battery_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Battery_LPHD1_PhyNam_vendor,
- 0
-};
-
-DataAttribute iedModel_Battery_LPHD1_PhyNam_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Battery_LPHD1_PhyNam,
- NULL,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_LPHD1_PhyHealth = {
- DataObjectModelType,
- "PhyHealth",
- (ModelNode*) &iedModel_Battery_LPHD1,
- (ModelNode*) &iedModel_Battery_LPHD1_Proxy,
- (ModelNode*) &iedModel_Battery_LPHD1_PhyHealth_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_LPHD1_PhyHealth_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Battery_LPHD1_PhyHealth_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LPHD1_PhyHealth_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Battery_LPHD1_PhyHealth_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LPHD1_PhyHealth_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_LPHD1_PhyHealth,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_LPHD1_Proxy = {
- DataObjectModelType,
- "Proxy",
- (ModelNode*) &iedModel_Battery_LPHD1,
- NULL,
- (ModelNode*) &iedModel_Battery_LPHD1_Proxy_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_LPHD1_Proxy_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_LPHD1_Proxy,
- (ModelNode*) &iedModel_Battery_LPHD1_Proxy_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_BOOLEAN,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LPHD1_Proxy_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_LPHD1_Proxy,
- (ModelNode*) &iedModel_Battery_LPHD1_Proxy_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_LPHD1_Proxy_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_LPHD1_Proxy,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-LogicalNode iedModel_Battery_ZBAT1 = {
- LogicalNodeModelType,
- "ZBAT1",
- (ModelNode*) &iedModel_Battery,
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBAT1_Mod,
-};
-
-DataObject iedModel_Battery_ZBAT1_Mod = {
- DataObjectModelType,
- "Mod",
- (ModelNode*) &iedModel_Battery_ZBAT1,
- (ModelNode*) &iedModel_Battery_ZBAT1_Beh,
- (ModelNode*) &iedModel_Battery_ZBAT1_Mod_q,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBAT1_Mod_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBAT1_Mod,
- (ModelNode*) &iedModel_Battery_ZBAT1_Mod_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Mod_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBAT1_Mod,
- (ModelNode*) &iedModel_Battery_ZBAT1_Mod_ctlModel,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Mod_ctlModel = {
- DataAttributeModelType,
- "ctlModel",
- (ModelNode*) &iedModel_Battery_ZBAT1_Mod,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBAT1_Beh = {
- DataObjectModelType,
- "Beh",
- (ModelNode*) &iedModel_Battery_ZBAT1,
- (ModelNode*) &iedModel_Battery_ZBAT1_Health,
- (ModelNode*) &iedModel_Battery_ZBAT1_Beh_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBAT1_Beh_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_ZBAT1_Beh,
- (ModelNode*) &iedModel_Battery_ZBAT1_Beh_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Beh_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBAT1_Beh,
- (ModelNode*) &iedModel_Battery_ZBAT1_Beh_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Beh_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBAT1_Beh,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBAT1_Health = {
- DataObjectModelType,
- "Health",
- (ModelNode*) &iedModel_Battery_ZBAT1,
- (ModelNode*) &iedModel_Battery_ZBAT1_NamPlt,
- (ModelNode*) &iedModel_Battery_ZBAT1_Health_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBAT1_Health_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_ZBAT1_Health,
- (ModelNode*) &iedModel_Battery_ZBAT1_Health_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Health_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBAT1_Health,
- (ModelNode*) &iedModel_Battery_ZBAT1_Health_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Health_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBAT1_Health,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBAT1_NamPlt = {
- DataObjectModelType,
- "NamPlt",
- (ModelNode*) &iedModel_Battery_ZBAT1,
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol,
- (ModelNode*) &iedModel_Battery_ZBAT1_NamPlt_vendor,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBAT1_NamPlt_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Battery_ZBAT1_NamPlt,
- (ModelNode*) &iedModel_Battery_ZBAT1_NamPlt_swRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_NamPlt_swRev = {
- DataAttributeModelType,
- "swRev",
- (ModelNode*) &iedModel_Battery_ZBAT1_NamPlt,
- (ModelNode*) &iedModel_Battery_ZBAT1_NamPlt_d,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_NamPlt_d = {
- DataAttributeModelType,
- "d",
- (ModelNode*) &iedModel_Battery_ZBAT1_NamPlt,
- NULL,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBAT1_Vol = {
- DataObjectModelType,
- "Vol",
- (ModelNode*) &iedModel_Battery_ZBAT1,
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp,
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol_mag,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBAT1_Vol_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol,
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol_q,
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Vol_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Vol_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol,
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Vol_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBAT1_Vol,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBAT1_Amp = {
- DataObjectModelType,
- "Amp",
- (ModelNode*) &iedModel_Battery_ZBAT1,
- NULL,
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp_mag,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBAT1_Amp_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp,
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp_q,
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Amp_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Amp_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp,
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBAT1_Amp_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBAT1_Amp,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-LogicalNode iedModel_Battery_ZBTC1 = {
- LogicalNodeModelType,
- "ZBTC1",
- (ModelNode*) &iedModel_Battery,
- NULL,
- (ModelNode*) &iedModel_Battery_ZBTC1_Mod,
-};
-
-DataObject iedModel_Battery_ZBTC1_Mod = {
- DataObjectModelType,
- "Mod",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_Beh,
- (ModelNode*) &iedModel_Battery_ZBTC1_Mod_q,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBTC1_Mod_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBTC1_Mod,
- (ModelNode*) &iedModel_Battery_ZBTC1_Mod_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_Mod_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBTC1_Mod,
- (ModelNode*) &iedModel_Battery_ZBTC1_Mod_ctlModel,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_Mod_ctlModel = {
- DataAttributeModelType,
- "ctlModel",
- (ModelNode*) &iedModel_Battery_ZBTC1_Mod,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBTC1_Beh = {
- DataObjectModelType,
- "Beh",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_Health,
- (ModelNode*) &iedModel_Battery_ZBTC1_Beh_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBTC1_Beh_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_ZBTC1_Beh,
- (ModelNode*) &iedModel_Battery_ZBTC1_Beh_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_Beh_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBTC1_Beh,
- (ModelNode*) &iedModel_Battery_ZBTC1_Beh_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_Beh_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBTC1_Beh,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBTC1_Health = {
- DataObjectModelType,
- "Health",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_NamPlt,
- (ModelNode*) &iedModel_Battery_ZBTC1_Health_stVal,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBTC1_Health_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Battery_ZBTC1_Health,
- (ModelNode*) &iedModel_Battery_ZBTC1_Health_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_Health_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBTC1_Health,
- (ModelNode*) &iedModel_Battery_ZBTC1_Health_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_Health_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBTC1_Health,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBTC1_NamPlt = {
- DataObjectModelType,
- "NamPlt",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_BatChaSt,
- (ModelNode*) &iedModel_Battery_ZBTC1_NamPlt_vendor,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBTC1_NamPlt_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Battery_ZBTC1_NamPlt,
- (ModelNode*) &iedModel_Battery_ZBTC1_NamPlt_swRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_NamPlt_swRev = {
- DataAttributeModelType,
- "swRev",
- (ModelNode*) &iedModel_Battery_ZBTC1_NamPlt,
- (ModelNode*) &iedModel_Battery_ZBTC1_NamPlt_d,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_NamPlt_d = {
- DataAttributeModelType,
- "d",
- (ModelNode*) &iedModel_Battery_ZBTC1_NamPlt,
- NULL,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBTC1_BatChaSt = {
- DataObjectModelType,
- "BatChaSt",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_BatChaPwr,
- NULL,
- 0
-};
-
-DataObject iedModel_Battery_ZBTC1_BatChaPwr = {
- DataObjectModelType,
- "BatChaPwr",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_BatChaMod,
- NULL,
- 0
-};
-
-DataObject iedModel_Battery_ZBTC1_BatChaMod = {
- DataObjectModelType,
- "BatChaMod",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV,
- NULL,
- 0
-};
-
-DataObject iedModel_Battery_ZBTC1_ChaV = {
- DataObjectModelType,
- "ChaV",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV_mag,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaV_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV_q,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaV_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaV_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaV_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaV,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Battery_ZBTC1_ChaA = {
- DataObjectModelType,
- "ChaA",
- (ModelNode*) &iedModel_Battery_ZBTC1,
- NULL,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA_mag,
- 0
-};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaA_mag = {
- DataAttributeModelType,
- "mag",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA_q,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA_mag_f,
- 0,
- IEC61850_FC_MX,
- IEC61850_CONSTRUCTED,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaA_mag_f = {
- DataAttributeModelType,
- "f",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA_mag,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_FLOAT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaA_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA,
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA_t,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Battery_ZBTC1_ChaA_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Battery_ZBTC1_ChaA,
- NULL,
- NULL,
- 0,
- IEC61850_FC_MX,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-
-LogicalDevice iedModel_Physical_Measurements = {
- LogicalDeviceModelType,
- "Physical_Measurements",
- (ModelNode*) &iedModel,
- NULL,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0
-};
-
-LogicalNode iedModel_Physical_Measurements_LLN0 = {
- LogicalNodeModelType,
- "LLN0",
- (ModelNode*) &iedModel_Physical_Measurements,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Mod,
-};
-
-DataObject iedModel_Physical_Measurements_LLN0_Mod = {
- DataObjectModelType,
- "Mod",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Beh,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Mod_q,
- 0
-};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Mod_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Mod,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Mod_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Mod_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Mod,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Mod_ctlModel,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Mod_ctlModel = {
- DataAttributeModelType,
- "ctlModel",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Mod,
- NULL,
- NULL,
- 0,
- IEC61850_FC_CF,
- IEC61850_ENUMERATED,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Physical_Measurements_LLN0_Beh = {
- DataObjectModelType,
- "Beh",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Health,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Beh_stVal,
- 0
-};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Beh_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Beh,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Beh_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Beh_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Beh,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Beh_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Beh_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Beh,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Physical_Measurements_LLN0_Health = {
- DataObjectModelType,
- "Health",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Health_stVal,
- 0
-};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Health_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Health,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Health_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Health_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Health,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Health_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_Health_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_Health,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Physical_Measurements_LLN0_NamPlt = {
- DataObjectModelType,
- "NamPlt",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0,
- NULL,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt_vendor,
- 0
-};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt_swRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_swRev = {
- DataAttributeModelType,
- "swRev",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt_d,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_d = {
- DataAttributeModelType,
- "d",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt_configRev,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_configRev = {
- DataAttributeModelType,
- "configRev",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt,
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt_ldNs,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_ldNs = {
- DataAttributeModelType,
- "ldNs",
- (ModelNode*) &iedModel_Physical_Measurements_LLN0_NamPlt,
- NULL,
- NULL,
- 0,
- IEC61850_FC_EX,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-LogicalNode iedModel_Physical_Measurements_LPHD1 = {
- LogicalNodeModelType,
- "LPHD1",
- (ModelNode*) &iedModel_Physical_Measurements,
- NULL,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyNam,
-};
-
-DataObject iedModel_Physical_Measurements_LPHD1_PhyNam = {
- DataObjectModelType,
- "PhyNam",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyNam_vendor,
- 0
-};
-
-DataAttribute iedModel_Physical_Measurements_LPHD1_PhyNam_vendor = {
- DataAttributeModelType,
- "vendor",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyNam,
- NULL,
- NULL,
- 0,
- IEC61850_FC_DC,
- IEC61850_VISIBLE_STRING_255,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Physical_Measurements_LPHD1_PhyHealth = {
- DataObjectModelType,
- "PhyHealth",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_Proxy,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyHealth_stVal,
- 0
-};
-
-DataAttribute iedModel_Physical_Measurements_LPHD1_PhyHealth_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyHealth_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_INT32,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LPHD1_PhyHealth_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyHealth,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyHealth_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LPHD1_PhyHealth_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_PhyHealth,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-DataObject iedModel_Physical_Measurements_LPHD1_Proxy = {
- DataObjectModelType,
- "Proxy",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1,
- NULL,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_Proxy_stVal,
- 0
-};
-
-DataAttribute iedModel_Physical_Measurements_LPHD1_Proxy_stVal = {
- DataAttributeModelType,
- "stVal",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_Proxy,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_Proxy_q,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_BOOLEAN,
- 0 + TRG_OPT_DATA_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LPHD1_Proxy_q = {
- DataAttributeModelType,
- "q",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_Proxy,
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_Proxy_t,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_QUALITY,
- 0 + TRG_OPT_QUALITY_CHANGED,
- NULL,
- 0};
-
-DataAttribute iedModel_Physical_Measurements_LPHD1_Proxy_t = {
- DataAttributeModelType,
- "t",
- (ModelNode*) &iedModel_Physical_Measurements_LPHD1_Proxy,
- NULL,
- NULL,
- 0,
- IEC61850_FC_ST,
- IEC61850_TIMESTAMP,
- 0,
- NULL,
- 0};
-
-extern ReportControlBlock iedModel_Inverter_LLN0_report0;
-
-ReportControlBlock iedModel_Inverter_LLN0_report0 = {&iedModel_Inverter_LLN0, "rcb101", "ID", false, "dataset1", 0, 19, 32, 0, 0, NULL};
-
-
-
-
-
-
-
-IedModel iedModel = {
- "ied1",
- &iedModel_Inverter,
- &iedModelds_Inverter_LLN0_dataset1,
- &iedModel_Inverter_LLN0_report0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- initializeValues
-};
-
-static void
-initializeValues()
-{
-
-iedModel_Inverter_LLN0_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
-
-iedModel_Inverter_ZINV1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
-
-iedModel_Inverter_MMXU1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
-
-iedModel_Battery_LLN0_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
-
-iedModel_Battery_ZBAT1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
-
-iedModel_Battery_ZBTC1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
-
-iedModel_Physical_Measurements_LLN0_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
-}
diff --git a/examples/server_example3/CMakeLists.txt b/examples/server_example3/CMakeLists.txt
deleted file mode 100644
index e3dbe438..00000000
--- a/examples/server_example3/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-include_directories(
- .
-)
-
-set(server_example3_SRCS
- server_example3.c
- static_model.c
-)
-
-IF(WIN32)
-set_source_files_properties(${server_example3_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(WIN32)
-
-add_executable(server_example3
- ${server_example3_SRCS}
-)
-
-target_link_libraries(server_example3
- iec61850
-)
diff --git a/examples/server_example3/vmd-filestore/SYSTEM.BIN b/examples/server_example3/vmd-filestore/SYSTEM.BIN
deleted file mode 100644
index e69de29b..00000000
diff --git a/examples/server_example4/CMakeLists.txt b/examples/server_example4/CMakeLists.txt
deleted file mode 100644
index d738b0f7..00000000
--- a/examples/server_example4/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-include_directories(
- .
-)
-
-set(server_example4_SRCS
- server_example4.c
- static_model.c
-)
-
-IF(WIN32)
-set_source_files_properties(${server_example4_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(WIN32)
-
-add_executable(server_example4
- ${server_example4_SRCS}
-)
-
-target_link_libraries(server_example4
- iec61850
-)
diff --git a/examples/server_example5/CMakeLists.txt b/examples/server_example5/CMakeLists.txt
deleted file mode 100644
index 8ca7c4c1..00000000
--- a/examples/server_example5/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-include_directories(
- .
-)
-
-set(server_example5_SRCS
- server_example5.c
- static_model.c
-)
-
-IF(WIN32)
-set_source_files_properties(${server_example5_SRCS}
- PROPERTIES LANGUAGE CXX)
-ENDIF(WIN32)
-
-add_executable(server_example5
- ${server_example5_SRCS}
-)
-
-target_link_libraries(server_example5
- iec61850
-)
diff --git a/examples/server_example5/static_model.h b/examples/server_example5/static_model.h
deleted file mode 100644
index 34623f80..00000000
--- a/examples/server_example5/static_model.h
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * static_model.h
- *
- * automatically generated from complexModel.icd
- */
-
-#ifndef STATIC_MODEL_H_
-#define STATIC_MODEL_H_
-
-#include
-#include "iec61850_model.h"
-
-extern IedModel iedModel;
-extern LogicalDevice iedModel_Inverter;
-extern LogicalNode iedModel_Inverter_LLN0;
-extern DataObject iedModel_Inverter_LLN0_Mod;
-extern DataAttribute iedModel_Inverter_LLN0_Mod_q;
-extern DataAttribute iedModel_Inverter_LLN0_Mod_t;
-extern DataAttribute iedModel_Inverter_LLN0_Mod_ctlModel;
-extern DataObject iedModel_Inverter_LLN0_Beh;
-extern DataAttribute iedModel_Inverter_LLN0_Beh_stVal;
-extern DataAttribute iedModel_Inverter_LLN0_Beh_q;
-extern DataAttribute iedModel_Inverter_LLN0_Beh_t;
-extern DataObject iedModel_Inverter_LLN0_Health;
-extern DataAttribute iedModel_Inverter_LLN0_Health_stVal;
-extern DataAttribute iedModel_Inverter_LLN0_Health_q;
-extern DataAttribute iedModel_Inverter_LLN0_Health_t;
-extern DataObject iedModel_Inverter_LLN0_NamPlt;
-extern DataAttribute iedModel_Inverter_LLN0_NamPlt_vendor;
-extern DataAttribute iedModel_Inverter_LLN0_NamPlt_swRev;
-extern DataAttribute iedModel_Inverter_LLN0_NamPlt_d;
-extern DataAttribute iedModel_Inverter_LLN0_NamPlt_configRev;
-extern DataAttribute iedModel_Inverter_LLN0_NamPlt_ldNs;
-extern LogicalNode iedModel_Inverter_LPHD1;
-extern DataObject iedModel_Inverter_LPHD1_PhyNam;
-extern DataAttribute iedModel_Inverter_LPHD1_PhyNam_vendor;
-extern DataObject iedModel_Inverter_LPHD1_PhyHealth;
-extern DataAttribute iedModel_Inverter_LPHD1_PhyHealth_stVal;
-extern DataAttribute iedModel_Inverter_LPHD1_PhyHealth_q;
-extern DataAttribute iedModel_Inverter_LPHD1_PhyHealth_t;
-extern DataObject iedModel_Inverter_LPHD1_Proxy;
-extern DataAttribute iedModel_Inverter_LPHD1_Proxy_stVal;
-extern DataAttribute iedModel_Inverter_LPHD1_Proxy_q;
-extern DataAttribute iedModel_Inverter_LPHD1_Proxy_t;
-extern LogicalNode iedModel_Inverter_ZINV1;
-extern DataObject iedModel_Inverter_ZINV1_Mod;
-extern DataAttribute iedModel_Inverter_ZINV1_Mod_q;
-extern DataAttribute iedModel_Inverter_ZINV1_Mod_t;
-extern DataAttribute iedModel_Inverter_ZINV1_Mod_ctlModel;
-extern DataObject iedModel_Inverter_ZINV1_Beh;
-extern DataAttribute iedModel_Inverter_ZINV1_Beh_stVal;
-extern DataAttribute iedModel_Inverter_ZINV1_Beh_q;
-extern DataAttribute iedModel_Inverter_ZINV1_Beh_t;
-extern DataObject iedModel_Inverter_ZINV1_Health;
-extern DataAttribute iedModel_Inverter_ZINV1_Health_stVal;
-extern DataAttribute iedModel_Inverter_ZINV1_Health_q;
-extern DataAttribute iedModel_Inverter_ZINV1_Health_t;
-extern DataObject iedModel_Inverter_ZINV1_NamPlt;
-extern DataAttribute iedModel_Inverter_ZINV1_NamPlt_vendor;
-extern DataAttribute iedModel_Inverter_ZINV1_NamPlt_swRev;
-extern DataAttribute iedModel_Inverter_ZINV1_NamPlt_d;
-extern DataObject iedModel_Inverter_ZINV1_WRtg;
-extern DataAttribute iedModel_Inverter_ZINV1_WRtg_setMag;
-extern DataAttribute iedModel_Inverter_ZINV1_WRtg_setMag_f;
-extern DataAttribute iedModel_Inverter_ZINV1_WRtg_units;
-extern DataAttribute iedModel_Inverter_ZINV1_WRtg_units_SIUnit;
-extern DataObject iedModel_Inverter_ZINV1_VarRtg;
-extern DataAttribute iedModel_Inverter_ZINV1_VarRtg_setMag;
-extern DataAttribute iedModel_Inverter_ZINV1_VarRtg_setMag_f;
-extern DataAttribute iedModel_Inverter_ZINV1_VarRtg_units;
-extern DataAttribute iedModel_Inverter_ZINV1_VarRtg_units_SIUnit;
-extern DataObject iedModel_Inverter_ZINV1_ACTyp;
-extern DataAttribute iedModel_Inverter_ZINV1_ACTyp_setVal;
-extern DataObject iedModel_Inverter_ZINV1_OutWSet;
-extern DataAttribute iedModel_Inverter_ZINV1_OutWSet_setMag;
-extern DataAttribute iedModel_Inverter_ZINV1_OutWSet_setMag_f;
-extern DataAttribute iedModel_Inverter_ZINV1_OutWSet_units;
-extern DataAttribute iedModel_Inverter_ZINV1_OutWSet_units_SIUnit;
-extern DataObject iedModel_Inverter_ZINV1_OutVarSet;
-extern DataAttribute iedModel_Inverter_ZINV1_OutVarSet_setMag;
-extern DataAttribute iedModel_Inverter_ZINV1_OutVarSet_setMag_f;
-extern DataAttribute iedModel_Inverter_ZINV1_OutVarSet_units;
-extern DataAttribute iedModel_Inverter_ZINV1_OutVarSet_units_SIUnit;
-extern LogicalNode iedModel_Inverter_MMXU1;
-extern DataObject iedModel_Inverter_MMXU1_Mod;
-extern DataAttribute iedModel_Inverter_MMXU1_Mod_q;
-extern DataAttribute iedModel_Inverter_MMXU1_Mod_t;
-extern DataAttribute iedModel_Inverter_MMXU1_Mod_ctlModel;
-extern DataObject iedModel_Inverter_MMXU1_Beh;
-extern DataAttribute iedModel_Inverter_MMXU1_Beh_stVal;
-extern DataAttribute iedModel_Inverter_MMXU1_Beh_q;
-extern DataAttribute iedModel_Inverter_MMXU1_Beh_t;
-extern DataObject iedModel_Inverter_MMXU1_Health;
-extern DataAttribute iedModel_Inverter_MMXU1_Health_stVal;
-extern DataAttribute iedModel_Inverter_MMXU1_Health_q;
-extern DataAttribute iedModel_Inverter_MMXU1_Health_t;
-extern DataObject iedModel_Inverter_MMXU1_NamPlt;
-extern DataAttribute iedModel_Inverter_MMXU1_NamPlt_vendor;
-extern DataAttribute iedModel_Inverter_MMXU1_NamPlt_swRev;
-extern DataAttribute iedModel_Inverter_MMXU1_NamPlt_d;
-extern DataObject iedModel_Inverter_MMXU1_TotW;
-extern DataAttribute iedModel_Inverter_MMXU1_TotW_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_TotW_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_TotW_q;
-extern DataAttribute iedModel_Inverter_MMXU1_TotW_t;
-extern DataObject iedModel_Inverter_MMXU1_TotVAr;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVAr_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVAr_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVAr_q;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVAr_t;
-extern DataObject iedModel_Inverter_MMXU1_TotVA;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVA_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVA_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVA_q;
-extern DataAttribute iedModel_Inverter_MMXU1_TotVA_t;
-extern DataObject iedModel_Inverter_MMXU1_Hz;
-extern DataAttribute iedModel_Inverter_MMXU1_Hz_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_Hz_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_Hz_q;
-extern DataAttribute iedModel_Inverter_MMXU1_Hz_t;
-extern DataObject iedModel_Inverter_MMXU1_PhV;
-extern DataObject iedModel_Inverter_MMXU1_PhV_phsA;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_q;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsA_t;
-extern DataObject iedModel_Inverter_MMXU1_PhV_phsB;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_q;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsB_t;
-extern DataObject iedModel_Inverter_MMXU1_PhV_phsC;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_q;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_phsC_t;
-extern DataObject iedModel_Inverter_MMXU1_PhV_neut;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_neut_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_neut_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_neut_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_neut_q;
-extern DataAttribute iedModel_Inverter_MMXU1_PhV_neut_t;
-extern DataObject iedModel_Inverter_MMXU1_A;
-extern DataObject iedModel_Inverter_MMXU1_A_phsA;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsA_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsA_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsA_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsA_q;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsA_t;
-extern DataObject iedModel_Inverter_MMXU1_A_phsB;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsB_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsB_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsB_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsB_q;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsB_t;
-extern DataObject iedModel_Inverter_MMXU1_A_phsC;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsC_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsC_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsC_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsC_q;
-extern DataAttribute iedModel_Inverter_MMXU1_A_phsC_t;
-extern DataObject iedModel_Inverter_MMXU1_A_neut;
-extern DataAttribute iedModel_Inverter_MMXU1_A_neut_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_A_neut_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_A_neut_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_A_neut_q;
-extern DataAttribute iedModel_Inverter_MMXU1_A_neut_t;
-extern DataObject iedModel_Inverter_MMXU1_W;
-extern DataObject iedModel_Inverter_MMXU1_W_phsA;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsA_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsA_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsA_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsA_q;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsA_t;
-extern DataObject iedModel_Inverter_MMXU1_W_phsB;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsB_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsB_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsB_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsB_q;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsB_t;
-extern DataObject iedModel_Inverter_MMXU1_W_phsC;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsC_cVal;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsC_cVal_mag;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsC_cVal_mag_f;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsC_q;
-extern DataAttribute iedModel_Inverter_MMXU1_W_phsC_t;
-extern LogicalDevice iedModel_Battery;
-extern LogicalNode iedModel_Battery_LLN0;
-extern DataObject iedModel_Battery_LLN0_Mod;
-extern DataAttribute iedModel_Battery_LLN0_Mod_q;
-extern DataAttribute iedModel_Battery_LLN0_Mod_t;
-extern DataAttribute iedModel_Battery_LLN0_Mod_ctlModel;
-extern DataObject iedModel_Battery_LLN0_Beh;
-extern DataAttribute iedModel_Battery_LLN0_Beh_stVal;
-extern DataAttribute iedModel_Battery_LLN0_Beh_q;
-extern DataAttribute iedModel_Battery_LLN0_Beh_t;
-extern DataObject iedModel_Battery_LLN0_Health;
-extern DataAttribute iedModel_Battery_LLN0_Health_stVal;
-extern DataAttribute iedModel_Battery_LLN0_Health_q;
-extern DataAttribute iedModel_Battery_LLN0_Health_t;
-extern DataObject iedModel_Battery_LLN0_NamPlt;
-extern DataAttribute iedModel_Battery_LLN0_NamPlt_vendor;
-extern DataAttribute iedModel_Battery_LLN0_NamPlt_swRev;
-extern DataAttribute iedModel_Battery_LLN0_NamPlt_d;
-extern DataAttribute iedModel_Battery_LLN0_NamPlt_configRev;
-extern DataAttribute iedModel_Battery_LLN0_NamPlt_ldNs;
-extern LogicalNode iedModel_Battery_LPHD1;
-extern DataObject iedModel_Battery_LPHD1_PhyNam;
-extern DataAttribute iedModel_Battery_LPHD1_PhyNam_vendor;
-extern DataObject iedModel_Battery_LPHD1_PhyHealth;
-extern DataAttribute iedModel_Battery_LPHD1_PhyHealth_stVal;
-extern DataAttribute iedModel_Battery_LPHD1_PhyHealth_q;
-extern DataAttribute iedModel_Battery_LPHD1_PhyHealth_t;
-extern DataObject iedModel_Battery_LPHD1_Proxy;
-extern DataAttribute iedModel_Battery_LPHD1_Proxy_stVal;
-extern DataAttribute iedModel_Battery_LPHD1_Proxy_q;
-extern DataAttribute iedModel_Battery_LPHD1_Proxy_t;
-extern LogicalNode iedModel_Battery_ZBAT1;
-extern DataObject iedModel_Battery_ZBAT1_Mod;
-extern DataAttribute iedModel_Battery_ZBAT1_Mod_q;
-extern DataAttribute iedModel_Battery_ZBAT1_Mod_t;
-extern DataAttribute iedModel_Battery_ZBAT1_Mod_ctlModel;
-extern DataObject iedModel_Battery_ZBAT1_Beh;
-extern DataAttribute iedModel_Battery_ZBAT1_Beh_stVal;
-extern DataAttribute iedModel_Battery_ZBAT1_Beh_q;
-extern DataAttribute iedModel_Battery_ZBAT1_Beh_t;
-extern DataObject iedModel_Battery_ZBAT1_Health;
-extern DataAttribute iedModel_Battery_ZBAT1_Health_stVal;
-extern DataAttribute iedModel_Battery_ZBAT1_Health_q;
-extern DataAttribute iedModel_Battery_ZBAT1_Health_t;
-extern DataObject iedModel_Battery_ZBAT1_NamPlt;
-extern DataAttribute iedModel_Battery_ZBAT1_NamPlt_vendor;
-extern DataAttribute iedModel_Battery_ZBAT1_NamPlt_swRev;
-extern DataAttribute iedModel_Battery_ZBAT1_NamPlt_d;
-extern DataObject iedModel_Battery_ZBAT1_Vol;
-extern DataAttribute iedModel_Battery_ZBAT1_Vol_mag;
-extern DataAttribute iedModel_Battery_ZBAT1_Vol_mag_f;
-extern DataAttribute iedModel_Battery_ZBAT1_Vol_q;
-extern DataAttribute iedModel_Battery_ZBAT1_Vol_t;
-extern DataObject iedModel_Battery_ZBAT1_Amp;
-extern DataAttribute iedModel_Battery_ZBAT1_Amp_mag;
-extern DataAttribute iedModel_Battery_ZBAT1_Amp_mag_f;
-extern DataAttribute iedModel_Battery_ZBAT1_Amp_q;
-extern DataAttribute iedModel_Battery_ZBAT1_Amp_t;
-extern LogicalNode iedModel_Battery_ZBTC1;
-extern DataObject iedModel_Battery_ZBTC1_Mod;
-extern DataAttribute iedModel_Battery_ZBTC1_Mod_q;
-extern DataAttribute iedModel_Battery_ZBTC1_Mod_t;
-extern DataAttribute iedModel_Battery_ZBTC1_Mod_ctlModel;
-extern DataObject iedModel_Battery_ZBTC1_Beh;
-extern DataAttribute iedModel_Battery_ZBTC1_Beh_stVal;
-extern DataAttribute iedModel_Battery_ZBTC1_Beh_q;
-extern DataAttribute iedModel_Battery_ZBTC1_Beh_t;
-extern DataObject iedModel_Battery_ZBTC1_Health;
-extern DataAttribute iedModel_Battery_ZBTC1_Health_stVal;
-extern DataAttribute iedModel_Battery_ZBTC1_Health_q;
-extern DataAttribute iedModel_Battery_ZBTC1_Health_t;
-extern DataObject iedModel_Battery_ZBTC1_NamPlt;
-extern DataAttribute iedModel_Battery_ZBTC1_NamPlt_vendor;
-extern DataAttribute iedModel_Battery_ZBTC1_NamPlt_swRev;
-extern DataAttribute iedModel_Battery_ZBTC1_NamPlt_d;
-extern DataObject iedModel_Battery_ZBTC1_BatChaSt;
-extern DataObject iedModel_Battery_ZBTC1_BatChaPwr;
-extern DataObject iedModel_Battery_ZBTC1_BatChaMod;
-extern DataObject iedModel_Battery_ZBTC1_ChaV;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaV_mag;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaV_mag_f;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaV_q;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaV_t;
-extern DataObject iedModel_Battery_ZBTC1_ChaA;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaA_mag;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaA_mag_f;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaA_q;
-extern DataAttribute iedModel_Battery_ZBTC1_ChaA_t;
-extern LogicalDevice iedModel_Physical_Measurements;
-extern LogicalNode iedModel_Physical_Measurements_LLN0;
-extern DataObject iedModel_Physical_Measurements_LLN0_Mod;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Mod_q;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Mod_t;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Mod_ctlModel;
-extern DataObject iedModel_Physical_Measurements_LLN0_Beh;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Beh_stVal;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Beh_q;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Beh_t;
-extern DataObject iedModel_Physical_Measurements_LLN0_Health;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Health_stVal;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Health_q;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_Health_t;
-extern DataObject iedModel_Physical_Measurements_LLN0_NamPlt;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_vendor;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_swRev;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_d;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_configRev;
-extern DataAttribute iedModel_Physical_Measurements_LLN0_NamPlt_ldNs;
-extern LogicalNode iedModel_Physical_Measurements_LPHD1;
-extern DataObject iedModel_Physical_Measurements_LPHD1_PhyNam;
-extern DataAttribute iedModel_Physical_Measurements_LPHD1_PhyNam_vendor;
-extern DataObject iedModel_Physical_Measurements_LPHD1_PhyHealth;
-extern DataAttribute iedModel_Physical_Measurements_LPHD1_PhyHealth_stVal;
-extern DataAttribute iedModel_Physical_Measurements_LPHD1_PhyHealth_q;
-extern DataAttribute iedModel_Physical_Measurements_LPHD1_PhyHealth_t;
-extern DataObject iedModel_Physical_Measurements_LPHD1_Proxy;
-extern DataAttribute iedModel_Physical_Measurements_LPHD1_Proxy_stVal;
-extern DataAttribute iedModel_Physical_Measurements_LPHD1_Proxy_q;
-extern DataAttribute iedModel_Physical_Measurements_LPHD1_Proxy_t;
-
-
-
-#define IEDMODEL_Inverter (&iedModel_Inverter)
-#define IEDMODEL_Inverter_LLN0 (&iedModel_Inverter_LLN0)
-#define IEDMODEL_Inverter_LLN0_Mod (&iedModel_Inverter_LLN0_Mod)
-#define IEDMODEL_Inverter_LLN0_Mod_q (&iedModel_Inverter_LLN0_Mod_q)
-#define IEDMODEL_Inverter_LLN0_Mod_t (&iedModel_Inverter_LLN0_Mod_t)
-#define IEDMODEL_Inverter_LLN0_Mod_ctlModel (&iedModel_Inverter_LLN0_Mod_ctlModel)
-#define IEDMODEL_Inverter_LLN0_Beh (&iedModel_Inverter_LLN0_Beh)
-#define IEDMODEL_Inverter_LLN0_Beh_stVal (&iedModel_Inverter_LLN0_Beh_stVal)
-#define IEDMODEL_Inverter_LLN0_Beh_q (&iedModel_Inverter_LLN0_Beh_q)
-#define IEDMODEL_Inverter_LLN0_Beh_t (&iedModel_Inverter_LLN0_Beh_t)
-#define IEDMODEL_Inverter_LLN0_Health (&iedModel_Inverter_LLN0_Health)
-#define IEDMODEL_Inverter_LLN0_Health_stVal (&iedModel_Inverter_LLN0_Health_stVal)
-#define IEDMODEL_Inverter_LLN0_Health_q (&iedModel_Inverter_LLN0_Health_q)
-#define IEDMODEL_Inverter_LLN0_Health_t (&iedModel_Inverter_LLN0_Health_t)
-#define IEDMODEL_Inverter_LLN0_NamPlt (&iedModel_Inverter_LLN0_NamPlt)
-#define IEDMODEL_Inverter_LLN0_NamPlt_vendor (&iedModel_Inverter_LLN0_NamPlt_vendor)
-#define IEDMODEL_Inverter_LLN0_NamPlt_swRev (&iedModel_Inverter_LLN0_NamPlt_swRev)
-#define IEDMODEL_Inverter_LLN0_NamPlt_d (&iedModel_Inverter_LLN0_NamPlt_d)
-#define IEDMODEL_Inverter_LLN0_NamPlt_configRev (&iedModel_Inverter_LLN0_NamPlt_configRev)
-#define IEDMODEL_Inverter_LLN0_NamPlt_ldNs (&iedModel_Inverter_LLN0_NamPlt_ldNs)
-#define IEDMODEL_Inverter_LPHD1 (&iedModel_Inverter_LPHD1)
-#define IEDMODEL_Inverter_LPHD1_PhyNam (&iedModel_Inverter_LPHD1_PhyNam)
-#define IEDMODEL_Inverter_LPHD1_PhyNam_vendor (&iedModel_Inverter_LPHD1_PhyNam_vendor)
-#define IEDMODEL_Inverter_LPHD1_PhyHealth (&iedModel_Inverter_LPHD1_PhyHealth)
-#define IEDMODEL_Inverter_LPHD1_PhyHealth_stVal (&iedModel_Inverter_LPHD1_PhyHealth_stVal)
-#define IEDMODEL_Inverter_LPHD1_PhyHealth_q (&iedModel_Inverter_LPHD1_PhyHealth_q)
-#define IEDMODEL_Inverter_LPHD1_PhyHealth_t (&iedModel_Inverter_LPHD1_PhyHealth_t)
-#define IEDMODEL_Inverter_LPHD1_Proxy (&iedModel_Inverter_LPHD1_Proxy)
-#define IEDMODEL_Inverter_LPHD1_Proxy_stVal (&iedModel_Inverter_LPHD1_Proxy_stVal)
-#define IEDMODEL_Inverter_LPHD1_Proxy_q (&iedModel_Inverter_LPHD1_Proxy_q)
-#define IEDMODEL_Inverter_LPHD1_Proxy_t (&iedModel_Inverter_LPHD1_Proxy_t)
-#define IEDMODEL_Inverter_ZINV1 (&iedModel_Inverter_ZINV1)
-#define IEDMODEL_Inverter_ZINV1_Mod (&iedModel_Inverter_ZINV1_Mod)
-#define IEDMODEL_Inverter_ZINV1_Mod_q (&iedModel_Inverter_ZINV1_Mod_q)
-#define IEDMODEL_Inverter_ZINV1_Mod_t (&iedModel_Inverter_ZINV1_Mod_t)
-#define IEDMODEL_Inverter_ZINV1_Mod_ctlModel (&iedModel_Inverter_ZINV1_Mod_ctlModel)
-#define IEDMODEL_Inverter_ZINV1_Beh (&iedModel_Inverter_ZINV1_Beh)
-#define IEDMODEL_Inverter_ZINV1_Beh_stVal (&iedModel_Inverter_ZINV1_Beh_stVal)
-#define IEDMODEL_Inverter_ZINV1_Beh_q (&iedModel_Inverter_ZINV1_Beh_q)
-#define IEDMODEL_Inverter_ZINV1_Beh_t (&iedModel_Inverter_ZINV1_Beh_t)
-#define IEDMODEL_Inverter_ZINV1_Health (&iedModel_Inverter_ZINV1_Health)
-#define IEDMODEL_Inverter_ZINV1_Health_stVal (&iedModel_Inverter_ZINV1_Health_stVal)
-#define IEDMODEL_Inverter_ZINV1_Health_q (&iedModel_Inverter_ZINV1_Health_q)
-#define IEDMODEL_Inverter_ZINV1_Health_t (&iedModel_Inverter_ZINV1_Health_t)
-#define IEDMODEL_Inverter_ZINV1_NamPlt (&iedModel_Inverter_ZINV1_NamPlt)
-#define IEDMODEL_Inverter_ZINV1_NamPlt_vendor (&iedModel_Inverter_ZINV1_NamPlt_vendor)
-#define IEDMODEL_Inverter_ZINV1_NamPlt_swRev (&iedModel_Inverter_ZINV1_NamPlt_swRev)
-#define IEDMODEL_Inverter_ZINV1_NamPlt_d (&iedModel_Inverter_ZINV1_NamPlt_d)
-#define IEDMODEL_Inverter_ZINV1_WRtg (&iedModel_Inverter_ZINV1_WRtg)
-#define IEDMODEL_Inverter_ZINV1_WRtg_setMag (&iedModel_Inverter_ZINV1_WRtg_setMag)
-#define IEDMODEL_Inverter_ZINV1_WRtg_setMag_f (&iedModel_Inverter_ZINV1_WRtg_setMag_f)
-#define IEDMODEL_Inverter_ZINV1_WRtg_units (&iedModel_Inverter_ZINV1_WRtg_units)
-#define IEDMODEL_Inverter_ZINV1_WRtg_units_SIUnit (&iedModel_Inverter_ZINV1_WRtg_units_SIUnit)
-#define IEDMODEL_Inverter_ZINV1_VarRtg (&iedModel_Inverter_ZINV1_VarRtg)
-#define IEDMODEL_Inverter_ZINV1_VarRtg_setMag (&iedModel_Inverter_ZINV1_VarRtg_setMag)
-#define IEDMODEL_Inverter_ZINV1_VarRtg_setMag_f (&iedModel_Inverter_ZINV1_VarRtg_setMag_f)
-#define IEDMODEL_Inverter_ZINV1_VarRtg_units (&iedModel_Inverter_ZINV1_VarRtg_units)
-#define IEDMODEL_Inverter_ZINV1_VarRtg_units_SIUnit (&iedModel_Inverter_ZINV1_VarRtg_units_SIUnit)
-#define IEDMODEL_Inverter_ZINV1_ACTyp (&iedModel_Inverter_ZINV1_ACTyp)
-#define IEDMODEL_Inverter_ZINV1_ACTyp_setVal (&iedModel_Inverter_ZINV1_ACTyp_setVal)
-#define IEDMODEL_Inverter_ZINV1_OutWSet (&iedModel_Inverter_ZINV1_OutWSet)
-#define IEDMODEL_Inverter_ZINV1_OutWSet_setMag (&iedModel_Inverter_ZINV1_OutWSet_setMag)
-#define IEDMODEL_Inverter_ZINV1_OutWSet_setMag_f (&iedModel_Inverter_ZINV1_OutWSet_setMag_f)
-#define IEDMODEL_Inverter_ZINV1_OutWSet_units (&iedModel_Inverter_ZINV1_OutWSet_units)
-#define IEDMODEL_Inverter_ZINV1_OutWSet_units_SIUnit (&iedModel_Inverter_ZINV1_OutWSet_units_SIUnit)
-#define IEDMODEL_Inverter_ZINV1_OutVarSet (&iedModel_Inverter_ZINV1_OutVarSet)
-#define IEDMODEL_Inverter_ZINV1_OutVarSet_setMag (&iedModel_Inverter_ZINV1_OutVarSet_setMag)
-#define IEDMODEL_Inverter_ZINV1_OutVarSet_setMag_f (&iedModel_Inverter_ZINV1_OutVarSet_setMag_f)
-#define IEDMODEL_Inverter_ZINV1_OutVarSet_units (&iedModel_Inverter_ZINV1_OutVarSet_units)
-#define IEDMODEL_Inverter_ZINV1_OutVarSet_units_SIUnit (&iedModel_Inverter_ZINV1_OutVarSet_units_SIUnit)
-#define IEDMODEL_Inverter_MMXU1 (&iedModel_Inverter_MMXU1)
-#define IEDMODEL_Inverter_MMXU1_Mod (&iedModel_Inverter_MMXU1_Mod)
-#define IEDMODEL_Inverter_MMXU1_Mod_q (&iedModel_Inverter_MMXU1_Mod_q)
-#define IEDMODEL_Inverter_MMXU1_Mod_t (&iedModel_Inverter_MMXU1_Mod_t)
-#define IEDMODEL_Inverter_MMXU1_Mod_ctlModel (&iedModel_Inverter_MMXU1_Mod_ctlModel)
-#define IEDMODEL_Inverter_MMXU1_Beh (&iedModel_Inverter_MMXU1_Beh)
-#define IEDMODEL_Inverter_MMXU1_Beh_stVal (&iedModel_Inverter_MMXU1_Beh_stVal)
-#define IEDMODEL_Inverter_MMXU1_Beh_q (&iedModel_Inverter_MMXU1_Beh_q)
-#define IEDMODEL_Inverter_MMXU1_Beh_t (&iedModel_Inverter_MMXU1_Beh_t)
-#define IEDMODEL_Inverter_MMXU1_Health (&iedModel_Inverter_MMXU1_Health)
-#define IEDMODEL_Inverter_MMXU1_Health_stVal (&iedModel_Inverter_MMXU1_Health_stVal)
-#define IEDMODEL_Inverter_MMXU1_Health_q (&iedModel_Inverter_MMXU1_Health_q)
-#define IEDMODEL_Inverter_MMXU1_Health_t (&iedModel_Inverter_MMXU1_Health_t)
-#define IEDMODEL_Inverter_MMXU1_NamPlt (&iedModel_Inverter_MMXU1_NamPlt)
-#define IEDMODEL_Inverter_MMXU1_NamPlt_vendor (&iedModel_Inverter_MMXU1_NamPlt_vendor)
-#define IEDMODEL_Inverter_MMXU1_NamPlt_swRev (&iedModel_Inverter_MMXU1_NamPlt_swRev)
-#define IEDMODEL_Inverter_MMXU1_NamPlt_d (&iedModel_Inverter_MMXU1_NamPlt_d)
-#define IEDMODEL_Inverter_MMXU1_TotW (&iedModel_Inverter_MMXU1_TotW)
-#define IEDMODEL_Inverter_MMXU1_TotW_mag (&iedModel_Inverter_MMXU1_TotW_mag)
-#define IEDMODEL_Inverter_MMXU1_TotW_mag_f (&iedModel_Inverter_MMXU1_TotW_mag_f)
-#define IEDMODEL_Inverter_MMXU1_TotW_q (&iedModel_Inverter_MMXU1_TotW_q)
-#define IEDMODEL_Inverter_MMXU1_TotW_t (&iedModel_Inverter_MMXU1_TotW_t)
-#define IEDMODEL_Inverter_MMXU1_TotVAr (&iedModel_Inverter_MMXU1_TotVAr)
-#define IEDMODEL_Inverter_MMXU1_TotVAr_mag (&iedModel_Inverter_MMXU1_TotVAr_mag)
-#define IEDMODEL_Inverter_MMXU1_TotVAr_mag_f (&iedModel_Inverter_MMXU1_TotVAr_mag_f)
-#define IEDMODEL_Inverter_MMXU1_TotVAr_q (&iedModel_Inverter_MMXU1_TotVAr_q)
-#define IEDMODEL_Inverter_MMXU1_TotVAr_t (&iedModel_Inverter_MMXU1_TotVAr_t)
-#define IEDMODEL_Inverter_MMXU1_TotVA (&iedModel_Inverter_MMXU1_TotVA)
-#define IEDMODEL_Inverter_MMXU1_TotVA_mag (&iedModel_Inverter_MMXU1_TotVA_mag)
-#define IEDMODEL_Inverter_MMXU1_TotVA_mag_f (&iedModel_Inverter_MMXU1_TotVA_mag_f)
-#define IEDMODEL_Inverter_MMXU1_TotVA_q (&iedModel_Inverter_MMXU1_TotVA_q)
-#define IEDMODEL_Inverter_MMXU1_TotVA_t (&iedModel_Inverter_MMXU1_TotVA_t)
-#define IEDMODEL_Inverter_MMXU1_Hz (&iedModel_Inverter_MMXU1_Hz)
-#define IEDMODEL_Inverter_MMXU1_Hz_mag (&iedModel_Inverter_MMXU1_Hz_mag)
-#define IEDMODEL_Inverter_MMXU1_Hz_mag_f (&iedModel_Inverter_MMXU1_Hz_mag_f)
-#define IEDMODEL_Inverter_MMXU1_Hz_q (&iedModel_Inverter_MMXU1_Hz_q)
-#define IEDMODEL_Inverter_MMXU1_Hz_t (&iedModel_Inverter_MMXU1_Hz_t)
-#define IEDMODEL_Inverter_MMXU1_PhV (&iedModel_Inverter_MMXU1_PhV)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsA (&iedModel_Inverter_MMXU1_PhV_phsA)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsA_cVal (&iedModel_Inverter_MMXU1_PhV_phsA_cVal)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsA_cVal_mag (&iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsA_cVal_mag_f (&iedModel_Inverter_MMXU1_PhV_phsA_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsA_q (&iedModel_Inverter_MMXU1_PhV_phsA_q)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsA_t (&iedModel_Inverter_MMXU1_PhV_phsA_t)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsB (&iedModel_Inverter_MMXU1_PhV_phsB)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsB_cVal (&iedModel_Inverter_MMXU1_PhV_phsB_cVal)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsB_cVal_mag (&iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsB_cVal_mag_f (&iedModel_Inverter_MMXU1_PhV_phsB_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsB_q (&iedModel_Inverter_MMXU1_PhV_phsB_q)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsB_t (&iedModel_Inverter_MMXU1_PhV_phsB_t)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsC (&iedModel_Inverter_MMXU1_PhV_phsC)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsC_cVal (&iedModel_Inverter_MMXU1_PhV_phsC_cVal)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsC_cVal_mag (&iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsC_cVal_mag_f (&iedModel_Inverter_MMXU1_PhV_phsC_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsC_q (&iedModel_Inverter_MMXU1_PhV_phsC_q)
-#define IEDMODEL_Inverter_MMXU1_PhV_phsC_t (&iedModel_Inverter_MMXU1_PhV_phsC_t)
-#define IEDMODEL_Inverter_MMXU1_PhV_neut (&iedModel_Inverter_MMXU1_PhV_neut)
-#define IEDMODEL_Inverter_MMXU1_PhV_neut_cVal (&iedModel_Inverter_MMXU1_PhV_neut_cVal)
-#define IEDMODEL_Inverter_MMXU1_PhV_neut_cVal_mag (&iedModel_Inverter_MMXU1_PhV_neut_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_PhV_neut_cVal_mag_f (&iedModel_Inverter_MMXU1_PhV_neut_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_PhV_neut_q (&iedModel_Inverter_MMXU1_PhV_neut_q)
-#define IEDMODEL_Inverter_MMXU1_PhV_neut_t (&iedModel_Inverter_MMXU1_PhV_neut_t)
-#define IEDMODEL_Inverter_MMXU1_A (&iedModel_Inverter_MMXU1_A)
-#define IEDMODEL_Inverter_MMXU1_A_phsA (&iedModel_Inverter_MMXU1_A_phsA)
-#define IEDMODEL_Inverter_MMXU1_A_phsA_cVal (&iedModel_Inverter_MMXU1_A_phsA_cVal)
-#define IEDMODEL_Inverter_MMXU1_A_phsA_cVal_mag (&iedModel_Inverter_MMXU1_A_phsA_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_A_phsA_cVal_mag_f (&iedModel_Inverter_MMXU1_A_phsA_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_A_phsA_q (&iedModel_Inverter_MMXU1_A_phsA_q)
-#define IEDMODEL_Inverter_MMXU1_A_phsA_t (&iedModel_Inverter_MMXU1_A_phsA_t)
-#define IEDMODEL_Inverter_MMXU1_A_phsB (&iedModel_Inverter_MMXU1_A_phsB)
-#define IEDMODEL_Inverter_MMXU1_A_phsB_cVal (&iedModel_Inverter_MMXU1_A_phsB_cVal)
-#define IEDMODEL_Inverter_MMXU1_A_phsB_cVal_mag (&iedModel_Inverter_MMXU1_A_phsB_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_A_phsB_cVal_mag_f (&iedModel_Inverter_MMXU1_A_phsB_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_A_phsB_q (&iedModel_Inverter_MMXU1_A_phsB_q)
-#define IEDMODEL_Inverter_MMXU1_A_phsB_t (&iedModel_Inverter_MMXU1_A_phsB_t)
-#define IEDMODEL_Inverter_MMXU1_A_phsC (&iedModel_Inverter_MMXU1_A_phsC)
-#define IEDMODEL_Inverter_MMXU1_A_phsC_cVal (&iedModel_Inverter_MMXU1_A_phsC_cVal)
-#define IEDMODEL_Inverter_MMXU1_A_phsC_cVal_mag (&iedModel_Inverter_MMXU1_A_phsC_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_A_phsC_cVal_mag_f (&iedModel_Inverter_MMXU1_A_phsC_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_A_phsC_q (&iedModel_Inverter_MMXU1_A_phsC_q)
-#define IEDMODEL_Inverter_MMXU1_A_phsC_t (&iedModel_Inverter_MMXU1_A_phsC_t)
-#define IEDMODEL_Inverter_MMXU1_A_neut (&iedModel_Inverter_MMXU1_A_neut)
-#define IEDMODEL_Inverter_MMXU1_A_neut_cVal (&iedModel_Inverter_MMXU1_A_neut_cVal)
-#define IEDMODEL_Inverter_MMXU1_A_neut_cVal_mag (&iedModel_Inverter_MMXU1_A_neut_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_A_neut_cVal_mag_f (&iedModel_Inverter_MMXU1_A_neut_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_A_neut_q (&iedModel_Inverter_MMXU1_A_neut_q)
-#define IEDMODEL_Inverter_MMXU1_A_neut_t (&iedModel_Inverter_MMXU1_A_neut_t)
-#define IEDMODEL_Inverter_MMXU1_W (&iedModel_Inverter_MMXU1_W)
-#define IEDMODEL_Inverter_MMXU1_W_phsA (&iedModel_Inverter_MMXU1_W_phsA)
-#define IEDMODEL_Inverter_MMXU1_W_phsA_cVal (&iedModel_Inverter_MMXU1_W_phsA_cVal)
-#define IEDMODEL_Inverter_MMXU1_W_phsA_cVal_mag (&iedModel_Inverter_MMXU1_W_phsA_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_W_phsA_cVal_mag_f (&iedModel_Inverter_MMXU1_W_phsA_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_W_phsA_q (&iedModel_Inverter_MMXU1_W_phsA_q)
-#define IEDMODEL_Inverter_MMXU1_W_phsA_t (&iedModel_Inverter_MMXU1_W_phsA_t)
-#define IEDMODEL_Inverter_MMXU1_W_phsB (&iedModel_Inverter_MMXU1_W_phsB)
-#define IEDMODEL_Inverter_MMXU1_W_phsB_cVal (&iedModel_Inverter_MMXU1_W_phsB_cVal)
-#define IEDMODEL_Inverter_MMXU1_W_phsB_cVal_mag (&iedModel_Inverter_MMXU1_W_phsB_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_W_phsB_cVal_mag_f (&iedModel_Inverter_MMXU1_W_phsB_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_W_phsB_q (&iedModel_Inverter_MMXU1_W_phsB_q)
-#define IEDMODEL_Inverter_MMXU1_W_phsB_t (&iedModel_Inverter_MMXU1_W_phsB_t)
-#define IEDMODEL_Inverter_MMXU1_W_phsC (&iedModel_Inverter_MMXU1_W_phsC)
-#define IEDMODEL_Inverter_MMXU1_W_phsC_cVal (&iedModel_Inverter_MMXU1_W_phsC_cVal)
-#define IEDMODEL_Inverter_MMXU1_W_phsC_cVal_mag (&iedModel_Inverter_MMXU1_W_phsC_cVal_mag)
-#define IEDMODEL_Inverter_MMXU1_W_phsC_cVal_mag_f (&iedModel_Inverter_MMXU1_W_phsC_cVal_mag_f)
-#define IEDMODEL_Inverter_MMXU1_W_phsC_q (&iedModel_Inverter_MMXU1_W_phsC_q)
-#define IEDMODEL_Inverter_MMXU1_W_phsC_t (&iedModel_Inverter_MMXU1_W_phsC_t)
-#define IEDMODEL_Battery (&iedModel_Battery)
-#define IEDMODEL_Battery_LLN0 (&iedModel_Battery_LLN0)
-#define IEDMODEL_Battery_LLN0_Mod (&iedModel_Battery_LLN0_Mod)
-#define IEDMODEL_Battery_LLN0_Mod_q (&iedModel_Battery_LLN0_Mod_q)
-#define IEDMODEL_Battery_LLN0_Mod_t (&iedModel_Battery_LLN0_Mod_t)
-#define IEDMODEL_Battery_LLN0_Mod_ctlModel (&iedModel_Battery_LLN0_Mod_ctlModel)
-#define IEDMODEL_Battery_LLN0_Beh (&iedModel_Battery_LLN0_Beh)
-#define IEDMODEL_Battery_LLN0_Beh_stVal (&iedModel_Battery_LLN0_Beh_stVal)
-#define IEDMODEL_Battery_LLN0_Beh_q (&iedModel_Battery_LLN0_Beh_q)
-#define IEDMODEL_Battery_LLN0_Beh_t (&iedModel_Battery_LLN0_Beh_t)
-#define IEDMODEL_Battery_LLN0_Health (&iedModel_Battery_LLN0_Health)
-#define IEDMODEL_Battery_LLN0_Health_stVal (&iedModel_Battery_LLN0_Health_stVal)
-#define IEDMODEL_Battery_LLN0_Health_q (&iedModel_Battery_LLN0_Health_q)
-#define IEDMODEL_Battery_LLN0_Health_t (&iedModel_Battery_LLN0_Health_t)
-#define IEDMODEL_Battery_LLN0_NamPlt (&iedModel_Battery_LLN0_NamPlt)
-#define IEDMODEL_Battery_LLN0_NamPlt_vendor (&iedModel_Battery_LLN0_NamPlt_vendor)
-#define IEDMODEL_Battery_LLN0_NamPlt_swRev (&iedModel_Battery_LLN0_NamPlt_swRev)
-#define IEDMODEL_Battery_LLN0_NamPlt_d (&iedModel_Battery_LLN0_NamPlt_d)
-#define IEDMODEL_Battery_LLN0_NamPlt_configRev (&iedModel_Battery_LLN0_NamPlt_configRev)
-#define IEDMODEL_Battery_LLN0_NamPlt_ldNs (&iedModel_Battery_LLN0_NamPlt_ldNs)
-#define IEDMODEL_Battery_LPHD1 (&iedModel_Battery_LPHD1)
-#define IEDMODEL_Battery_LPHD1_PhyNam (&iedModel_Battery_LPHD1_PhyNam)
-#define IEDMODEL_Battery_LPHD1_PhyNam_vendor (&iedModel_Battery_LPHD1_PhyNam_vendor)
-#define IEDMODEL_Battery_LPHD1_PhyHealth (&iedModel_Battery_LPHD1_PhyHealth)
-#define IEDMODEL_Battery_LPHD1_PhyHealth_stVal (&iedModel_Battery_LPHD1_PhyHealth_stVal)
-#define IEDMODEL_Battery_LPHD1_PhyHealth_q (&iedModel_Battery_LPHD1_PhyHealth_q)
-#define IEDMODEL_Battery_LPHD1_PhyHealth_t (&iedModel_Battery_LPHD1_PhyHealth_t)
-#define IEDMODEL_Battery_LPHD1_Proxy (&iedModel_Battery_LPHD1_Proxy)
-#define IEDMODEL_Battery_LPHD1_Proxy_stVal (&iedModel_Battery_LPHD1_Proxy_stVal)
-#define IEDMODEL_Battery_LPHD1_Proxy_q (&iedModel_Battery_LPHD1_Proxy_q)
-#define IEDMODEL_Battery_LPHD1_Proxy_t (&iedModel_Battery_LPHD1_Proxy_t)
-#define IEDMODEL_Battery_ZBAT1 (&iedModel_Battery_ZBAT1)
-#define IEDMODEL_Battery_ZBAT1_Mod (&iedModel_Battery_ZBAT1_Mod)
-#define IEDMODEL_Battery_ZBAT1_Mod_q (&iedModel_Battery_ZBAT1_Mod_q)
-#define IEDMODEL_Battery_ZBAT1_Mod_t (&iedModel_Battery_ZBAT1_Mod_t)
-#define IEDMODEL_Battery_ZBAT1_Mod_ctlModel (&iedModel_Battery_ZBAT1_Mod_ctlModel)
-#define IEDMODEL_Battery_ZBAT1_Beh (&iedModel_Battery_ZBAT1_Beh)
-#define IEDMODEL_Battery_ZBAT1_Beh_stVal (&iedModel_Battery_ZBAT1_Beh_stVal)
-#define IEDMODEL_Battery_ZBAT1_Beh_q (&iedModel_Battery_ZBAT1_Beh_q)
-#define IEDMODEL_Battery_ZBAT1_Beh_t (&iedModel_Battery_ZBAT1_Beh_t)
-#define IEDMODEL_Battery_ZBAT1_Health (&iedModel_Battery_ZBAT1_Health)
-#define IEDMODEL_Battery_ZBAT1_Health_stVal (&iedModel_Battery_ZBAT1_Health_stVal)
-#define IEDMODEL_Battery_ZBAT1_Health_q (&iedModel_Battery_ZBAT1_Health_q)
-#define IEDMODEL_Battery_ZBAT1_Health_t (&iedModel_Battery_ZBAT1_Health_t)
-#define IEDMODEL_Battery_ZBAT1_NamPlt (&iedModel_Battery_ZBAT1_NamPlt)
-#define IEDMODEL_Battery_ZBAT1_NamPlt_vendor (&iedModel_Battery_ZBAT1_NamPlt_vendor)
-#define IEDMODEL_Battery_ZBAT1_NamPlt_swRev (&iedModel_Battery_ZBAT1_NamPlt_swRev)
-#define IEDMODEL_Battery_ZBAT1_NamPlt_d (&iedModel_Battery_ZBAT1_NamPlt_d)
-#define IEDMODEL_Battery_ZBAT1_Vol (&iedModel_Battery_ZBAT1_Vol)
-#define IEDMODEL_Battery_ZBAT1_Vol_mag (&iedModel_Battery_ZBAT1_Vol_mag)
-#define IEDMODEL_Battery_ZBAT1_Vol_mag_f (&iedModel_Battery_ZBAT1_Vol_mag_f)
-#define IEDMODEL_Battery_ZBAT1_Vol_q (&iedModel_Battery_ZBAT1_Vol_q)
-#define IEDMODEL_Battery_ZBAT1_Vol_t (&iedModel_Battery_ZBAT1_Vol_t)
-#define IEDMODEL_Battery_ZBAT1_Amp (&iedModel_Battery_ZBAT1_Amp)
-#define IEDMODEL_Battery_ZBAT1_Amp_mag (&iedModel_Battery_ZBAT1_Amp_mag)
-#define IEDMODEL_Battery_ZBAT1_Amp_mag_f (&iedModel_Battery_ZBAT1_Amp_mag_f)
-#define IEDMODEL_Battery_ZBAT1_Amp_q (&iedModel_Battery_ZBAT1_Amp_q)
-#define IEDMODEL_Battery_ZBAT1_Amp_t (&iedModel_Battery_ZBAT1_Amp_t)
-#define IEDMODEL_Battery_ZBTC1 (&iedModel_Battery_ZBTC1)
-#define IEDMODEL_Battery_ZBTC1_Mod (&iedModel_Battery_ZBTC1_Mod)
-#define IEDMODEL_Battery_ZBTC1_Mod_q (&iedModel_Battery_ZBTC1_Mod_q)
-#define IEDMODEL_Battery_ZBTC1_Mod_t (&iedModel_Battery_ZBTC1_Mod_t)
-#define IEDMODEL_Battery_ZBTC1_Mod_ctlModel (&iedModel_Battery_ZBTC1_Mod_ctlModel)
-#define IEDMODEL_Battery_ZBTC1_Beh (&iedModel_Battery_ZBTC1_Beh)
-#define IEDMODEL_Battery_ZBTC1_Beh_stVal (&iedModel_Battery_ZBTC1_Beh_stVal)
-#define IEDMODEL_Battery_ZBTC1_Beh_q (&iedModel_Battery_ZBTC1_Beh_q)
-#define IEDMODEL_Battery_ZBTC1_Beh_t (&iedModel_Battery_ZBTC1_Beh_t)
-#define IEDMODEL_Battery_ZBTC1_Health (&iedModel_Battery_ZBTC1_Health)
-#define IEDMODEL_Battery_ZBTC1_Health_stVal (&iedModel_Battery_ZBTC1_Health_stVal)
-#define IEDMODEL_Battery_ZBTC1_Health_q (&iedModel_Battery_ZBTC1_Health_q)
-#define IEDMODEL_Battery_ZBTC1_Health_t (&iedModel_Battery_ZBTC1_Health_t)
-#define IEDMODEL_Battery_ZBTC1_NamPlt (&iedModel_Battery_ZBTC1_NamPlt)
-#define IEDMODEL_Battery_ZBTC1_NamPlt_vendor (&iedModel_Battery_ZBTC1_NamPlt_vendor)
-#define IEDMODEL_Battery_ZBTC1_NamPlt_swRev (&iedModel_Battery_ZBTC1_NamPlt_swRev)
-#define IEDMODEL_Battery_ZBTC1_NamPlt_d (&iedModel_Battery_ZBTC1_NamPlt_d)
-#define IEDMODEL_Battery_ZBTC1_BatChaSt (&iedModel_Battery_ZBTC1_BatChaSt)
-#define IEDMODEL_Battery_ZBTC1_BatChaPwr (&iedModel_Battery_ZBTC1_BatChaPwr)
-#define IEDMODEL_Battery_ZBTC1_BatChaMod (&iedModel_Battery_ZBTC1_BatChaMod)
-#define IEDMODEL_Battery_ZBTC1_ChaV (&iedModel_Battery_ZBTC1_ChaV)
-#define IEDMODEL_Battery_ZBTC1_ChaV_mag (&iedModel_Battery_ZBTC1_ChaV_mag)
-#define IEDMODEL_Battery_ZBTC1_ChaV_mag_f (&iedModel_Battery_ZBTC1_ChaV_mag_f)
-#define IEDMODEL_Battery_ZBTC1_ChaV_q (&iedModel_Battery_ZBTC1_ChaV_q)
-#define IEDMODEL_Battery_ZBTC1_ChaV_t (&iedModel_Battery_ZBTC1_ChaV_t)
-#define IEDMODEL_Battery_ZBTC1_ChaA (&iedModel_Battery_ZBTC1_ChaA)
-#define IEDMODEL_Battery_ZBTC1_ChaA_mag (&iedModel_Battery_ZBTC1_ChaA_mag)
-#define IEDMODEL_Battery_ZBTC1_ChaA_mag_f (&iedModel_Battery_ZBTC1_ChaA_mag_f)
-#define IEDMODEL_Battery_ZBTC1_ChaA_q (&iedModel_Battery_ZBTC1_ChaA_q)
-#define IEDMODEL_Battery_ZBTC1_ChaA_t (&iedModel_Battery_ZBTC1_ChaA_t)
-#define IEDMODEL_Physical_Measurements (&iedModel_Physical_Measurements)
-#define IEDMODEL_Physical_Measurements_LLN0 (&iedModel_Physical_Measurements_LLN0)
-#define IEDMODEL_Physical_Measurements_LLN0_Mod (&iedModel_Physical_Measurements_LLN0_Mod)
-#define IEDMODEL_Physical_Measurements_LLN0_Mod_q (&iedModel_Physical_Measurements_LLN0_Mod_q)
-#define IEDMODEL_Physical_Measurements_LLN0_Mod_t (&iedModel_Physical_Measurements_LLN0_Mod_t)
-#define IEDMODEL_Physical_Measurements_LLN0_Mod_ctlModel (&iedModel_Physical_Measurements_LLN0_Mod_ctlModel)
-#define IEDMODEL_Physical_Measurements_LLN0_Beh (&iedModel_Physical_Measurements_LLN0_Beh)
-#define IEDMODEL_Physical_Measurements_LLN0_Beh_stVal (&iedModel_Physical_Measurements_LLN0_Beh_stVal)
-#define IEDMODEL_Physical_Measurements_LLN0_Beh_q (&iedModel_Physical_Measurements_LLN0_Beh_q)
-#define IEDMODEL_Physical_Measurements_LLN0_Beh_t (&iedModel_Physical_Measurements_LLN0_Beh_t)
-#define IEDMODEL_Physical_Measurements_LLN0_Health (&iedModel_Physical_Measurements_LLN0_Health)
-#define IEDMODEL_Physical_Measurements_LLN0_Health_stVal (&iedModel_Physical_Measurements_LLN0_Health_stVal)
-#define IEDMODEL_Physical_Measurements_LLN0_Health_q (&iedModel_Physical_Measurements_LLN0_Health_q)
-#define IEDMODEL_Physical_Measurements_LLN0_Health_t (&iedModel_Physical_Measurements_LLN0_Health_t)
-#define IEDMODEL_Physical_Measurements_LLN0_NamPlt (&iedModel_Physical_Measurements_LLN0_NamPlt)
-#define IEDMODEL_Physical_Measurements_LLN0_NamPlt_vendor (&iedModel_Physical_Measurements_LLN0_NamPlt_vendor)
-#define IEDMODEL_Physical_Measurements_LLN0_NamPlt_swRev (&iedModel_Physical_Measurements_LLN0_NamPlt_swRev)
-#define IEDMODEL_Physical_Measurements_LLN0_NamPlt_d (&iedModel_Physical_Measurements_LLN0_NamPlt_d)
-#define IEDMODEL_Physical_Measurements_LLN0_NamPlt_configRev (&iedModel_Physical_Measurements_LLN0_NamPlt_configRev)
-#define IEDMODEL_Physical_Measurements_LLN0_NamPlt_ldNs (&iedModel_Physical_Measurements_LLN0_NamPlt_ldNs)
-#define IEDMODEL_Physical_Measurements_LPHD1 (&iedModel_Physical_Measurements_LPHD1)
-#define IEDMODEL_Physical_Measurements_LPHD1_PhyNam (&iedModel_Physical_Measurements_LPHD1_PhyNam)
-#define IEDMODEL_Physical_Measurements_LPHD1_PhyNam_vendor (&iedModel_Physical_Measurements_LPHD1_PhyNam_vendor)
-#define IEDMODEL_Physical_Measurements_LPHD1_PhyHealth (&iedModel_Physical_Measurements_LPHD1_PhyHealth)
-#define IEDMODEL_Physical_Measurements_LPHD1_PhyHealth_stVal (&iedModel_Physical_Measurements_LPHD1_PhyHealth_stVal)
-#define IEDMODEL_Physical_Measurements_LPHD1_PhyHealth_q (&iedModel_Physical_Measurements_LPHD1_PhyHealth_q)
-#define IEDMODEL_Physical_Measurements_LPHD1_PhyHealth_t (&iedModel_Physical_Measurements_LPHD1_PhyHealth_t)
-#define IEDMODEL_Physical_Measurements_LPHD1_Proxy (&iedModel_Physical_Measurements_LPHD1_Proxy)
-#define IEDMODEL_Physical_Measurements_LPHD1_Proxy_stVal (&iedModel_Physical_Measurements_LPHD1_Proxy_stVal)
-#define IEDMODEL_Physical_Measurements_LPHD1_Proxy_q (&iedModel_Physical_Measurements_LPHD1_Proxy_q)
-#define IEDMODEL_Physical_Measurements_LPHD1_Proxy_t (&iedModel_Physical_Measurements_LPHD1_Proxy_t)
-
-#endif /* STATIC_MODEL_H_ */
-
diff --git a/examples/server_example_basic_io/CMakeLists.txt b/examples/server_example_basic_io/CMakeLists.txt
new file mode 100644
index 00000000..6ff774a9
--- /dev/null
+++ b/examples/server_example_basic_io/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(
+ .
+)
+
+set(server_example_SRCS
+ server_example_basic_io.c
+ static_model.c
+)
+
+IF(WIN32)
+set_source_files_properties(${server_example_SRCS}
+ PROPERTIES LANGUAGE CXX)
+ENDIF(WIN32)
+
+add_executable(server_example_basic_io
+ ${server_example_SRCS}
+)
+
+target_link_libraries(server_example_basic_io
+ iec61850
+)
diff --git a/examples/server_example_basic_io/Makefile b/examples/server_example_basic_io/Makefile
new file mode 100644
index 00000000..4e4e5956
--- /dev/null
+++ b/examples/server_example_basic_io/Makefile
@@ -0,0 +1,31 @@
+LIBIEC_HOME=../..
+
+PROJECT_BINARY_NAME = server_example_basic_io
+PROJECT_SOURCES = server_example_basic_io.c
+PROJECT_SOURCES += static_model.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
+
+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)
+ $(CP) $(PROJECT_BINARY_NAME) vmd-filestore/IEDSERVER.BIN
+
+clean:
+ rm -f $(PROJECT_BINARY_NAME)
+ rm -f vmd-filestore/IEDSERVER.BIN
+
+
diff --git a/examples/server_example3/server_example3.c b/examples/server_example_basic_io/server_example_basic_io.c
similarity index 95%
rename from examples/server_example3/server_example3.c
rename to examples/server_example_basic_io/server_example_basic_io.c
index 2352bc67..30faf6e4 100644
--- a/examples/server_example3/server_example3.c
+++ b/examples/server_example_basic_io/server_example_basic_io.c
@@ -1,5 +1,5 @@
/*
- * server_example3.c
+ * server_example_basic_io.c
*
* - How to use simple control models
* - How to serve analog measurement data
@@ -12,7 +12,7 @@
#include
#include
-#include "static_model.h"
+#include "../server_example_basic_io/static_model.h"
/* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel;
@@ -85,6 +85,10 @@ main(int argc, char** argv)
iedServer = IedServer_create(&iedModel);
+ /* Set the base path for the MMS file services */
+ MmsServer mmsServer = IedServer_getMmsServer(iedServer);
+ MmsServer_setFilestoreBasepath(mmsServer, "./vmd-filestore/");
+
/* Install handler for operate command */
IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1,
(ControlHandler) controlHandlerForBinaryOutput,
diff --git a/examples/server_example3/simpleIO_direct_control.icd b/examples/server_example_basic_io/simpleIO_direct_control.icd
similarity index 100%
rename from examples/server_example3/simpleIO_direct_control.icd
rename to examples/server_example_basic_io/simpleIO_direct_control.icd
diff --git a/examples/server_example3/simpleIO_sbo_control.icd b/examples/server_example_basic_io/simpleIO_sbo_control.icd
similarity index 100%
rename from examples/server_example3/simpleIO_sbo_control.icd
rename to examples/server_example_basic_io/simpleIO_sbo_control.icd
diff --git a/examples/server_example_basic_io/static_model.c b/examples/server_example_basic_io/static_model.c
new file mode 100644
index 00000000..ddc8dd64
--- /dev/null
+++ b/examples/server_example_basic_io/static_model.c
@@ -0,0 +1,2003 @@
+/*
+ * static_model.c
+ *
+ * automatically generated from simpleIO_direct_control.icd
+ */
+#include "../server_example_basic_io/static_model.h"
+
+static void initializeValues();
+
+extern DataSet iedModelds_GenericIO_LLN0_Events;
+extern DataSet iedModelds_GenericIO_LLN0_Events2;
+extern DataSet iedModelds_GenericIO_LLN0_Measurements;
+
+
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda0;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda1;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda2;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda3;
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda0 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO1$stVal",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Events_fcda1
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda1 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO2$stVal",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Events_fcda2
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda2 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO3$stVal",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Events_fcda3
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda3 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO4$stVal",
+ -1,
+ NULL,
+ NULL,
+ NULL
+};
+
+DataSet iedModelds_GenericIO_LLN0_Events = {
+ "GenericIO",
+ "LLN0$Events",
+ 4,
+ &iedModelds_GenericIO_LLN0_Events_fcda0,
+ &iedModelds_GenericIO_LLN0_Events2
+};
+
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda0;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda1;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda2;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda3;
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda0 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO1",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Events2_fcda1
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda1 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO2",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Events2_fcda2
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda2 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO3",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Events2_fcda3
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Events2_fcda3 = {
+ "GenericIO",
+ false,
+ "GGIO1$ST$SPCSO4",
+ -1,
+ NULL,
+ NULL,
+ NULL
+};
+
+DataSet iedModelds_GenericIO_LLN0_Events2 = {
+ "GenericIO",
+ "LLN0$Events2",
+ 4,
+ &iedModelds_GenericIO_LLN0_Events2_fcda0,
+ &iedModelds_GenericIO_LLN0_Measurements
+};
+
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda0;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda1;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda2;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda3;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda4;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda5;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda6;
+extern DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda7;
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda0 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn1$mag$f",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda1
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda1 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn1$q",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda2
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda2 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn2$mag$f",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda3
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda3 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn2$q",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda4
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda4 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn3$mag$f",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda5
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda5 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn3$q",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda6
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda6 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn4$mag$f",
+ -1,
+ NULL,
+ NULL,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda7
+};
+
+DataSetEntry iedModelds_GenericIO_LLN0_Measurements_fcda7 = {
+ "GenericIO",
+ false,
+ "GGIO1$MX$AnIn4$q",
+ -1,
+ NULL,
+ NULL,
+ NULL
+};
+
+DataSet iedModelds_GenericIO_LLN0_Measurements = {
+ "GenericIO",
+ "LLN0$Measurements",
+ 8,
+ &iedModelds_GenericIO_LLN0_Measurements_fcda0,
+ NULL
+};
+
+LogicalDevice iedModel_GenericIO = {
+ LogicalDeviceModelType,
+ "GenericIO",
+ (ModelNode*) &iedModel,
+ NULL,
+ (ModelNode*) &iedModel_GenericIO_LLN0
+};
+
+LogicalNode iedModel_GenericIO_LLN0 = {
+ LogicalNodeModelType,
+ "LLN0",
+ (ModelNode*) &iedModel_GenericIO,
+ (ModelNode*) &iedModel_GenericIO_LPHD1,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod,
+};
+
+DataObject iedModel_GenericIO_LLN0_Mod = {
+ DataObjectModelType,
+ "Mod",
+ (ModelNode*) &iedModel_GenericIO_LLN0,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Beh,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_LLN0_Mod_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_INT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_Mod_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_Mod_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod_ctlModel,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_Mod_ctlModel = {
+ DataAttributeModelType,
+ "ctlModel",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Mod,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_LLN0_Beh = {
+ DataObjectModelType,
+ "Beh",
+ (ModelNode*) &iedModel_GenericIO_LLN0,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Health,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Beh_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_LLN0_Beh_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Beh,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Beh_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_INT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_Beh_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Beh,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Beh_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_Beh_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Beh,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_LLN0_Health = {
+ DataObjectModelType,
+ "Health",
+ (ModelNode*) &iedModel_GenericIO_LLN0,
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Health_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_LLN0_Health_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Health,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Health_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_INT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_Health_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Health,
+ (ModelNode*) &iedModel_GenericIO_LLN0_Health_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_Health_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_LLN0_Health,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_LLN0_NamPlt = {
+ DataObjectModelType,
+ "NamPlt",
+ (ModelNode*) &iedModel_GenericIO_LLN0,
+ NULL,
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt_vendor,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_LLN0_NamPlt_vendor = {
+ DataAttributeModelType,
+ "vendor",
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt_swRev,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_NamPlt_swRev = {
+ DataAttributeModelType,
+ "swRev",
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt_d,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_NamPlt_d = {
+ DataAttributeModelType,
+ "d",
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt_configRev,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_NamPlt_configRev = {
+ DataAttributeModelType,
+ "configRev",
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt_ldNs,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LLN0_NamPlt_ldNs = {
+ DataAttributeModelType,
+ "ldNs",
+ (ModelNode*) &iedModel_GenericIO_LLN0_NamPlt,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_EX,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_GenericIO_LPHD1 = {
+ LogicalNodeModelType,
+ "LPHD1",
+ (ModelNode*) &iedModel_GenericIO,
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyNam,
+};
+
+DataObject iedModel_GenericIO_LPHD1_PhyNam = {
+ DataObjectModelType,
+ "PhyNam",
+ (ModelNode*) &iedModel_GenericIO_LPHD1,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyHealth,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyNam_vendor,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_LPHD1_PhyNam_vendor = {
+ DataAttributeModelType,
+ "vendor",
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyNam,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_LPHD1_PhyHealth = {
+ DataObjectModelType,
+ "PhyHealth",
+ (ModelNode*) &iedModel_GenericIO_LPHD1,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_Proxy,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyHealth_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyHealth,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyHealth_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_INT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyHealth,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyHealth_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_LPHD1_PhyHealth,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_LPHD1_Proxy = {
+ DataObjectModelType,
+ "Proxy",
+ (ModelNode*) &iedModel_GenericIO_LPHD1,
+ NULL,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_Proxy_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_LPHD1_Proxy_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_LPHD1_Proxy,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_Proxy_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LPHD1_Proxy_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_LPHD1_Proxy,
+ (ModelNode*) &iedModel_GenericIO_LPHD1_Proxy_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_LPHD1_Proxy_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_LPHD1_Proxy,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+LogicalNode iedModel_GenericIO_GGIO1 = {
+ LogicalNodeModelType,
+ "GGIO1",
+ (ModelNode*) &iedModel_GenericIO,
+ NULL,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Mod,
+};
+
+DataObject iedModel_GenericIO_GGIO1_Mod = {
+ DataObjectModelType,
+ "Mod",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Beh,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_q,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_Mod_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Mod,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Mod_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Mod,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Mod_ctlModel,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel = {
+ DataAttributeModelType,
+ "ctlModel",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Mod,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_Beh = {
+ DataObjectModelType,
+ "Beh",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Health,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_Beh_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Beh,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_INT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Beh_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Beh,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Beh_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Beh_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Beh,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_Health = {
+ DataObjectModelType,
+ "Health",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Health_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_Health_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Health,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Health_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_INT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Health_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Health,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Health_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Health_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Health,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_NamPlt = {
+ DataObjectModelType,
+ "NamPlt",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_NamPlt_vendor,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_NamPlt_vendor = {
+ DataAttributeModelType,
+ "vendor",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_NamPlt_swRev,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_NamPlt_swRev = {
+ DataAttributeModelType,
+ "swRev",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_NamPlt,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_NamPlt_d,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_NamPlt_d = {
+ DataAttributeModelType,
+ "d",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_NamPlt,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_DC,
+ IEC61850_VISIBLE_STRING_255,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_AnIn1 = {
+ DataObjectModelType,
+ "AnIn1",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1_mag,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag = {
+ DataAttributeModelType,
+ "mag",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1_q,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1_mag_f,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag_f = {
+ DataAttributeModelType,
+ "f",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1_mag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_FLOAT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn1_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1_t,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn1_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_AnIn2 = {
+ DataObjectModelType,
+ "AnIn2",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2_mag,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag = {
+ DataAttributeModelType,
+ "mag",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2_q,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2_mag_f,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag_f = {
+ DataAttributeModelType,
+ "f",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2_mag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_FLOAT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn2_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2_t,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn2_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_AnIn3 = {
+ DataObjectModelType,
+ "AnIn3",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3_mag,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag = {
+ DataAttributeModelType,
+ "mag",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3_q,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3_mag_f,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag_f = {
+ DataAttributeModelType,
+ "f",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3_mag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_FLOAT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn3_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3_t,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn3_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_AnIn4 = {
+ DataObjectModelType,
+ "AnIn4",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4_mag,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag = {
+ DataAttributeModelType,
+ "mag",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4_q,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4_mag_f,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_CONSTRUCTED,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag_f = {
+ DataAttributeModelType,
+ "f",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4_mag,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_FLOAT32,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn4_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4_t,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_AnIn4_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_MX,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_SPCSO1 = {
+ DataObjectModelType,
+ "SPCSO1",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper = {
+ DataAttributeModelType,
+ "Oper",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_ctlModel,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal = {
+ DataAttributeModelType,
+ "ctlVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin = {
+ DataAttributeModelType,
+ "origin",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlNum,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat = {
+ DataAttributeModelType,
+ "orCat",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent = {
+ DataAttributeModelType,
+ "orIdent",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_OCTET_STRING_64,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlNum = {
+ DataAttributeModelType,
+ "ctlNum",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_T,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_INT8U,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_T = {
+ DataAttributeModelType,
+ "T",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_Test,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Test = {
+ DataAttributeModelType,
+ "Test",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_Check,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Check = {
+ DataAttributeModelType,
+ "Check",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CHECK,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_ctlModel = {
+ DataAttributeModelType,
+ "ctlModel",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_t,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_SPCSO2 = {
+ DataObjectModelType,
+ "SPCSO2",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper = {
+ DataAttributeModelType,
+ "Oper",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_ctlModel,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal = {
+ DataAttributeModelType,
+ "ctlVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin = {
+ DataAttributeModelType,
+ "origin",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlNum,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat = {
+ DataAttributeModelType,
+ "orCat",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent = {
+ DataAttributeModelType,
+ "orIdent",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_OCTET_STRING_64,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlNum = {
+ DataAttributeModelType,
+ "ctlNum",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_T,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_INT8U,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_T = {
+ DataAttributeModelType,
+ "T",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_Test,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Test = {
+ DataAttributeModelType,
+ "Test",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_Check,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Check = {
+ DataAttributeModelType,
+ "Check",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CHECK,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_ctlModel = {
+ DataAttributeModelType,
+ "ctlModel",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_t,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_SPCSO3 = {
+ DataObjectModelType,
+ "SPCSO3",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper = {
+ DataAttributeModelType,
+ "Oper",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_ctlModel,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal = {
+ DataAttributeModelType,
+ "ctlVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin = {
+ DataAttributeModelType,
+ "origin",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlNum,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat = {
+ DataAttributeModelType,
+ "orCat",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent = {
+ DataAttributeModelType,
+ "orIdent",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_OCTET_STRING_64,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlNum = {
+ DataAttributeModelType,
+ "ctlNum",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_T,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_INT8U,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_T = {
+ DataAttributeModelType,
+ "T",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_Test,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Test = {
+ DataAttributeModelType,
+ "Test",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_Check,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Check = {
+ DataAttributeModelType,
+ "Check",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CHECK,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_ctlModel = {
+ DataAttributeModelType,
+ "ctlModel",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_t,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_SPCSO4 = {
+ DataObjectModelType,
+ "SPCSO4",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper = {
+ DataAttributeModelType,
+ "Oper",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_ctlModel,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal = {
+ DataAttributeModelType,
+ "ctlVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin = {
+ DataAttributeModelType,
+ "origin",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlNum,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CONSTRUCTED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat = {
+ DataAttributeModelType,
+ "orCat",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent = {
+ DataAttributeModelType,
+ "orIdent",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_OCTET_STRING_64,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlNum = {
+ DataAttributeModelType,
+ "ctlNum",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_T,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_INT8U,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_T = {
+ DataAttributeModelType,
+ "T",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_Test,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Test = {
+ DataAttributeModelType,
+ "Test",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_Check,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_BOOLEAN,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Check = {
+ DataAttributeModelType,
+ "Check",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_CO,
+ IEC61850_CHECK,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_ctlModel = {
+ DataAttributeModelType,
+ "ctlModel",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_t,
+ NULL,
+ 0,
+ IEC61850_FC_CF,
+ IEC61850_ENUMERATED,
+ 0,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_Ind1 = {
+ DataObjectModelType,
+ "Ind1",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind1_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind1_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind1_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind1_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind1_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind1_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind1,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_Ind2 = {
+ DataObjectModelType,
+ "Ind2",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind2_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind2_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind2_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind2_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind2,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind2_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind2_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind2,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_Ind3 = {
+ DataObjectModelType,
+ "Ind3",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind3_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind3_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind3_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind3_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind3,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind3_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind3_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind3,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+DataObject iedModel_GenericIO_GGIO1_Ind4 = {
+ DataObjectModelType,
+ "Ind4",
+ (ModelNode*) &iedModel_GenericIO_GGIO1,
+ NULL,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind4_stVal,
+ 0
+};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind4_stVal = {
+ DataAttributeModelType,
+ "stVal",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind4_q,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_BOOLEAN,
+ 0 + TRG_OPT_DATA_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind4_q = {
+ DataAttributeModelType,
+ "q",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind4,
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind4_t,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_QUALITY,
+ 0 + TRG_OPT_QUALITY_CHANGED,
+ NULL,
+ 0};
+
+DataAttribute iedModel_GenericIO_GGIO1_Ind4_t = {
+ DataAttributeModelType,
+ "t",
+ (ModelNode*) &iedModel_GenericIO_GGIO1_Ind4,
+ NULL,
+ NULL,
+ 0,
+ IEC61850_FC_ST,
+ IEC61850_TIMESTAMP,
+ 0,
+ NULL,
+ 0};
+
+extern ReportControlBlock iedModel_GenericIO_LLN0_report0;
+extern ReportControlBlock iedModel_GenericIO_LLN0_report1;
+extern ReportControlBlock iedModel_GenericIO_LLN0_report2;
+extern ReportControlBlock iedModel_GenericIO_LLN0_report3;
+extern ReportControlBlock iedModel_GenericIO_LLN0_report4;
+extern ReportControlBlock iedModel_GenericIO_LLN0_report5;
+extern ReportControlBlock iedModel_GenericIO_LLN0_report6;
+
+ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, "EventsRCB01", "Events1", false, "Events", 4294967295, 24, 239, 50, 1000, &iedModel_GenericIO_LLN0_report1};
+ReportControlBlock iedModel_GenericIO_LLN0_report1 = {&iedModel_GenericIO_LLN0, "EventsIndexed01", "Events2", false, "Events", 1, 24, 239, 50, 1000, &iedModel_GenericIO_LLN0_report2};
+ReportControlBlock iedModel_GenericIO_LLN0_report2 = {&iedModel_GenericIO_LLN0, "EventsIndexed02", "Events2", false, "Events", 1, 24, 239, 50, 1000, &iedModel_GenericIO_LLN0_report3};
+ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0, "EventsIndexed03", "Events2", false, "Events", 1, 24, 239, 50, 1000, &iedModel_GenericIO_LLN0_report4};
+ReportControlBlock iedModel_GenericIO_LLN0_report4 = {&iedModel_GenericIO_LLN0, "Measurements01", "Measurements", true, "Measurements", 1, 16, 239, 50, 1000, &iedModel_GenericIO_LLN0_report5};
+ReportControlBlock iedModel_GenericIO_LLN0_report5 = {&iedModel_GenericIO_LLN0, "Measurements02", "Measurements", true, "Measurements", 1, 16, 239, 50, 1000, &iedModel_GenericIO_LLN0_report6};
+ReportControlBlock iedModel_GenericIO_LLN0_report6 = {&iedModel_GenericIO_LLN0, "Measurements03", "Measurements", true, "Measurements", 1, 16, 239, 50, 1000, NULL};
+
+
+
+
+extern LogControlBlock iedModel_GenericIO_LLN0_lcb0;
+extern LogControlBlock iedModel_GenericIO_LLN0_lcb1;
+LogControlBlock iedModel_GenericIO_LLN0_lcb0 = {&iedModel_GenericIO_LLN0, "EventLog", "Events", "GenericIO/LLN0$EventLog", 3, 0, true, true, &iedModel_GenericIO_LLN0_lcb1};
+LogControlBlock iedModel_GenericIO_LLN0_lcb1 = {&iedModel_GenericIO_LLN0, "GeneralLog", NULL, NULL, 3, 0, true, true, NULL};
+
+extern Log iedModel_GenericIO_LLN0_log0;
+extern Log iedModel_GenericIO_LLN0_log1;
+Log iedModel_GenericIO_LLN0_log0 = {&iedModel_GenericIO_LLN0, "GeneralLog", &iedModel_GenericIO_LLN0_log1};
+Log iedModel_GenericIO_LLN0_log1 = {&iedModel_GenericIO_LLN0, "EventLog", NULL};
+
+
+IedModel iedModel = {
+ "simpleIO",
+ &iedModel_GenericIO,
+ &iedModelds_GenericIO_LLN0_Events,
+ &iedModel_GenericIO_LLN0_report0,
+ NULL,
+ NULL,
+ NULL,
+ &iedModel_GenericIO_LLN0_lcb0,
+ &iedModel_GenericIO_LLN0_log0,
+ initializeValues
+};
+
+static void
+initializeValues()
+{
+
+iedModel_GenericIO_LLN0_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
+
+iedModel_GenericIO_LLN0_NamPlt_vendor.mmsValue = MmsValue_newVisibleString("MZ Automation");
+
+iedModel_GenericIO_LLN0_NamPlt_swRev.mmsValue = MmsValue_newVisibleString("0.7.3");
+
+iedModel_GenericIO_LLN0_NamPlt_d.mmsValue = MmsValue_newVisibleString("libiec61850 server example");
+
+iedModel_GenericIO_GGIO1_Mod_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(0);
+
+iedModel_GenericIO_GGIO1_SPCSO1_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1);
+
+iedModel_GenericIO_GGIO1_SPCSO2_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1);
+
+iedModel_GenericIO_GGIO1_SPCSO3_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1);
+
+iedModel_GenericIO_GGIO1_SPCSO4_ctlModel.mmsValue = MmsValue_newIntegerFromInt32(1);
+}
diff --git a/examples/server_example3/static_model.h b/examples/server_example_basic_io/static_model.h
similarity index 100%
rename from examples/server_example3/static_model.h
rename to examples/server_example_basic_io/static_model.h
diff --git a/examples/server_example_files/CMakeLists.txt b/examples/server_example_files/CMakeLists.txt
new file mode 100644
index 00000000..a0dfc356
--- /dev/null
+++ b/examples/server_example_files/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(
+ .
+)
+
+set(server_example_SRCS
+ server_example_files.c
+ static_model.c
+)
+
+IF(WIN32)
+set_source_files_properties(${server_example_SRCS}
+ PROPERTIES LANGUAGE CXX)
+ENDIF(WIN32)
+
+add_executable(server_example_files
+ ${server_example_SRCS}
+)
+
+target_link_libraries(server_example_files
+ iec61850
+)
diff --git a/examples/server_example3/Makefile b/examples/server_example_files/Makefile
similarity index 89%
rename from examples/server_example3/Makefile
rename to examples/server_example_files/Makefile
index 65e2509d..bcc7b4c5 100644
--- a/examples/server_example3/Makefile
+++ b/examples/server_example_files/Makefile
@@ -1,7 +1,7 @@
LIBIEC_HOME=../..
-PROJECT_BINARY_NAME = server_example3
-PROJECT_SOURCES = server_example3.c
+PROJECT_BINARY_NAME = server_example_files
+PROJECT_SOURCES = server_example_files.c
PROJECT_SOURCES += static_model.c
PROJECT_ICD_FILE = simpleIO_direct_control.icd
diff --git a/examples/server_example_files/server_example_files.c b/examples/server_example_files/server_example_files.c
new file mode 100644
index 00000000..b2a1b07c
--- /dev/null
+++ b/examples/server_example_files/server_example_files.c
@@ -0,0 +1,98 @@
+/*
+ * server_example_files.c
+ *
+ * - How to use some special MMS file service features
+ * - How to control how files file services can be used
+ */
+
+#include "iec61850_server.h"
+#include "hal_thread.h"
+#include
+#include
+#include
+#include
+
+#include "static_model.h"
+
+/* import IEC 61850 device model created from SCL-File */
+extern IedModel iedModel;
+
+static int running = 0;
+static IedServer iedServer = NULL;
+
+void
+sigint_handler(int signalId)
+{
+ running = 0;
+}
+
+static void
+connectionHandler (IedServer self, ClientConnection connection, bool connected, void* parameter)
+{
+ if (connected)
+ printf("Connection opened\n");
+ else
+ printf("Connection closed\n");
+}
+
+static MmsError
+fileAccessHandler (void* parameter, MmsServerConnection connection, MmsFileServiceType service,
+ const char* localFilename, const char* otherFilename)
+{
+ printf("fileAccessHandler: service = %i, local-file: %s other-file: %s\n", service, localFilename, otherFilename);
+
+ /* Don't allow client to rename files */
+ if (service == MMS_FILE_ACCESS_TYPE_RENAME)
+ return MMS_ERROR_FILE_FILE_ACCESS_DENIED;
+
+ /* Don't allow client to delete fike "IEDSERVER.BIN" */
+ if (service == MMS_FILE_ACCESS_TYPE_DELETE) {
+ if (strcmp(localFilename, "IEDSERVER.BIN") == 0)
+ return MMS_ERROR_FILE_FILE_ACCESS_DENIED;
+ }
+
+ /* allow all other accesses */
+ return MMS_ERROR_NONE;
+}
+
+int
+main(int argc, char** argv)
+{
+ printf("Using libIEC61850 version %s\n", LibIEC61850_getVersionString());
+
+ iedServer = IedServer_create(&iedModel);
+
+ /* Set the base path for the MMS file services */
+ MmsServer mmsServer = IedServer_getMmsServer(iedServer);
+ MmsServer_setFilestoreBasepath(mmsServer, "./vmd-filestore/");
+
+ /* Set a callback handler to control file accesses */
+ MmsServer_installFileAccessHandler(mmsServer, fileAccessHandler, NULL);
+
+ IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionHandler, NULL);
+
+ /* 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);
+
+
+ while (running)
+ Thread_sleep(100);
+
+
+ /* stop MMS server - close TCP server socket and all client sockets */
+ IedServer_stop(iedServer);
+
+ /* Cleanup - free all resources */
+ IedServer_destroy(iedServer);
+
+} /* main() */
diff --git a/examples/server_example_files/simpleIO_direct_control.icd b/examples/server_example_files/simpleIO_direct_control.icd
new file mode 100644
index 00000000..0a0c6355
--- /dev/null
+++ b/examples/server_example_files/simpleIO_direct_control.icd
@@ -0,0 +1,281 @@
+
+
+
+
+
+ Station bus
+ 10
+
+
+ 10.0.0.2
+ 255.255.255.0
+ 10.0.0.1
+ 0001
+ 00000001
+ 0001
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status-only
+
+
+
+
+
+ MZ Automation
+
+
+ 0.7.3
+
+
+ libiec61850 server example
+
+
+
+
+
+
+
+ status-only
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status-only
+ direct-with-normal-security
+ sbo-with-normal-security
+ direct-with-enhanced-security
+ sbo-with-enhanced-security
+
+
+ not-supported
+ bay-control
+ station-control
+ remote-control
+ automatic-bay
+ automatic-station
+ automatic-remote
+ maintenance
+ process
+
+
+
diff --git a/examples/server_example3/static_model.c b/examples/server_example_files/static_model.c
similarity index 100%
rename from examples/server_example3/static_model.c
rename to examples/server_example_files/static_model.c
diff --git a/examples/server_example_files/static_model.h b/examples/server_example_files/static_model.h
new file mode 100644
index 00000000..b5670e9f
--- /dev/null
+++ b/examples/server_example_files/static_model.h
@@ -0,0 +1,301 @@
+/*
+ * static_model.h
+ *
+ * automatically generated from simpleIO_direct_control.icd
+ */
+
+#ifndef STATIC_MODEL_H_
+#define STATIC_MODEL_H_
+
+#include
+#include "iec61850_model.h"
+
+extern IedModel iedModel;
+extern LogicalDevice iedModel_GenericIO;
+extern LogicalNode iedModel_GenericIO_LLN0;
+extern DataObject iedModel_GenericIO_LLN0_Mod;
+extern DataAttribute iedModel_GenericIO_LLN0_Mod_stVal;
+extern DataAttribute iedModel_GenericIO_LLN0_Mod_q;
+extern DataAttribute iedModel_GenericIO_LLN0_Mod_t;
+extern DataAttribute iedModel_GenericIO_LLN0_Mod_ctlModel;
+extern DataObject iedModel_GenericIO_LLN0_Beh;
+extern DataAttribute iedModel_GenericIO_LLN0_Beh_stVal;
+extern DataAttribute iedModel_GenericIO_LLN0_Beh_q;
+extern DataAttribute iedModel_GenericIO_LLN0_Beh_t;
+extern DataObject iedModel_GenericIO_LLN0_Health;
+extern DataAttribute iedModel_GenericIO_LLN0_Health_stVal;
+extern DataAttribute iedModel_GenericIO_LLN0_Health_q;
+extern DataAttribute iedModel_GenericIO_LLN0_Health_t;
+extern DataObject iedModel_GenericIO_LLN0_NamPlt;
+extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_vendor;
+extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_swRev;
+extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_d;
+extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_configRev;
+extern DataAttribute iedModel_GenericIO_LLN0_NamPlt_ldNs;
+extern LogicalNode iedModel_GenericIO_LPHD1;
+extern DataObject iedModel_GenericIO_LPHD1_PhyNam;
+extern DataAttribute iedModel_GenericIO_LPHD1_PhyNam_vendor;
+extern DataObject iedModel_GenericIO_LPHD1_PhyHealth;
+extern DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_stVal;
+extern DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_q;
+extern DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_t;
+extern DataObject iedModel_GenericIO_LPHD1_Proxy;
+extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_stVal;
+extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_q;
+extern DataAttribute iedModel_GenericIO_LPHD1_Proxy_t;
+extern LogicalNode iedModel_GenericIO_GGIO1;
+extern DataObject iedModel_GenericIO_GGIO1_Mod;
+extern DataAttribute iedModel_GenericIO_GGIO1_Mod_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_Mod_t;
+extern DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel;
+extern DataObject iedModel_GenericIO_GGIO1_Beh;
+extern DataAttribute iedModel_GenericIO_GGIO1_Beh_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_Beh_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_Beh_t;
+extern DataObject iedModel_GenericIO_GGIO1_Health;
+extern DataAttribute iedModel_GenericIO_GGIO1_Health_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_Health_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_Health_t;
+extern DataObject iedModel_GenericIO_GGIO1_NamPlt;
+extern DataAttribute iedModel_GenericIO_GGIO1_NamPlt_vendor;
+extern DataAttribute iedModel_GenericIO_GGIO1_NamPlt_swRev;
+extern DataAttribute iedModel_GenericIO_GGIO1_NamPlt_d;
+extern DataObject iedModel_GenericIO_GGIO1_AnIn1;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag_f;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn1_t;
+extern DataObject iedModel_GenericIO_GGIO1_AnIn2;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag_f;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn2_t;
+extern DataObject iedModel_GenericIO_GGIO1_AnIn3;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag_f;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn3_t;
+extern DataObject iedModel_GenericIO_GGIO1_AnIn4;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag_f;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_AnIn4_t;
+extern DataObject iedModel_GenericIO_GGIO1_SPCSO1;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlNum;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_T;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Test;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Check;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_ctlModel;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_t;
+extern DataObject iedModel_GenericIO_GGIO1_SPCSO2;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlNum;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_T;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Test;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Check;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_ctlModel;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_t;
+extern DataObject iedModel_GenericIO_GGIO1_SPCSO3;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlNum;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_T;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Test;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Check;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_ctlModel;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_t;
+extern DataObject iedModel_GenericIO_GGIO1_SPCSO4;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlNum;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_T;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Test;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Check;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_ctlModel;
+extern DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_t;
+extern DataObject iedModel_GenericIO_GGIO1_Ind1;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind1_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind1_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind1_t;
+extern DataObject iedModel_GenericIO_GGIO1_Ind2;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind2_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind2_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind2_t;
+extern DataObject iedModel_GenericIO_GGIO1_Ind3;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind3_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind3_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind3_t;
+extern DataObject iedModel_GenericIO_GGIO1_Ind4;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_stVal;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_q;
+extern DataAttribute iedModel_GenericIO_GGIO1_Ind4_t;
+
+
+
+#define IEDMODEL_GenericIO (&iedModel_GenericIO)
+#define IEDMODEL_GenericIO_LLN0 (&iedModel_GenericIO_LLN0)
+#define IEDMODEL_GenericIO_LLN0_Mod (&iedModel_GenericIO_LLN0_Mod)
+#define IEDMODEL_GenericIO_LLN0_Mod_stVal (&iedModel_GenericIO_LLN0_Mod_stVal)
+#define IEDMODEL_GenericIO_LLN0_Mod_q (&iedModel_GenericIO_LLN0_Mod_q)
+#define IEDMODEL_GenericIO_LLN0_Mod_t (&iedModel_GenericIO_LLN0_Mod_t)
+#define IEDMODEL_GenericIO_LLN0_Mod_ctlModel (&iedModel_GenericIO_LLN0_Mod_ctlModel)
+#define IEDMODEL_GenericIO_LLN0_Beh (&iedModel_GenericIO_LLN0_Beh)
+#define IEDMODEL_GenericIO_LLN0_Beh_stVal (&iedModel_GenericIO_LLN0_Beh_stVal)
+#define IEDMODEL_GenericIO_LLN0_Beh_q (&iedModel_GenericIO_LLN0_Beh_q)
+#define IEDMODEL_GenericIO_LLN0_Beh_t (&iedModel_GenericIO_LLN0_Beh_t)
+#define IEDMODEL_GenericIO_LLN0_Health (&iedModel_GenericIO_LLN0_Health)
+#define IEDMODEL_GenericIO_LLN0_Health_stVal (&iedModel_GenericIO_LLN0_Health_stVal)
+#define IEDMODEL_GenericIO_LLN0_Health_q (&iedModel_GenericIO_LLN0_Health_q)
+#define IEDMODEL_GenericIO_LLN0_Health_t (&iedModel_GenericIO_LLN0_Health_t)
+#define IEDMODEL_GenericIO_LLN0_NamPlt (&iedModel_GenericIO_LLN0_NamPlt)
+#define IEDMODEL_GenericIO_LLN0_NamPlt_vendor (&iedModel_GenericIO_LLN0_NamPlt_vendor)
+#define IEDMODEL_GenericIO_LLN0_NamPlt_swRev (&iedModel_GenericIO_LLN0_NamPlt_swRev)
+#define IEDMODEL_GenericIO_LLN0_NamPlt_d (&iedModel_GenericIO_LLN0_NamPlt_d)
+#define IEDMODEL_GenericIO_LLN0_NamPlt_configRev (&iedModel_GenericIO_LLN0_NamPlt_configRev)
+#define IEDMODEL_GenericIO_LLN0_NamPlt_ldNs (&iedModel_GenericIO_LLN0_NamPlt_ldNs)
+#define IEDMODEL_GenericIO_LPHD1 (&iedModel_GenericIO_LPHD1)
+#define IEDMODEL_GenericIO_LPHD1_PhyNam (&iedModel_GenericIO_LPHD1_PhyNam)
+#define IEDMODEL_GenericIO_LPHD1_PhyNam_vendor (&iedModel_GenericIO_LPHD1_PhyNam_vendor)
+#define IEDMODEL_GenericIO_LPHD1_PhyHealth (&iedModel_GenericIO_LPHD1_PhyHealth)
+#define IEDMODEL_GenericIO_LPHD1_PhyHealth_stVal (&iedModel_GenericIO_LPHD1_PhyHealth_stVal)
+#define IEDMODEL_GenericIO_LPHD1_PhyHealth_q (&iedModel_GenericIO_LPHD1_PhyHealth_q)
+#define IEDMODEL_GenericIO_LPHD1_PhyHealth_t (&iedModel_GenericIO_LPHD1_PhyHealth_t)
+#define IEDMODEL_GenericIO_LPHD1_Proxy (&iedModel_GenericIO_LPHD1_Proxy)
+#define IEDMODEL_GenericIO_LPHD1_Proxy_stVal (&iedModel_GenericIO_LPHD1_Proxy_stVal)
+#define IEDMODEL_GenericIO_LPHD1_Proxy_q (&iedModel_GenericIO_LPHD1_Proxy_q)
+#define IEDMODEL_GenericIO_LPHD1_Proxy_t (&iedModel_GenericIO_LPHD1_Proxy_t)
+#define IEDMODEL_GenericIO_GGIO1 (&iedModel_GenericIO_GGIO1)
+#define IEDMODEL_GenericIO_GGIO1_Mod (&iedModel_GenericIO_GGIO1_Mod)
+#define IEDMODEL_GenericIO_GGIO1_Mod_q (&iedModel_GenericIO_GGIO1_Mod_q)
+#define IEDMODEL_GenericIO_GGIO1_Mod_t (&iedModel_GenericIO_GGIO1_Mod_t)
+#define IEDMODEL_GenericIO_GGIO1_Mod_ctlModel (&iedModel_GenericIO_GGIO1_Mod_ctlModel)
+#define IEDMODEL_GenericIO_GGIO1_Beh (&iedModel_GenericIO_GGIO1_Beh)
+#define IEDMODEL_GenericIO_GGIO1_Beh_stVal (&iedModel_GenericIO_GGIO1_Beh_stVal)
+#define IEDMODEL_GenericIO_GGIO1_Beh_q (&iedModel_GenericIO_GGIO1_Beh_q)
+#define IEDMODEL_GenericIO_GGIO1_Beh_t (&iedModel_GenericIO_GGIO1_Beh_t)
+#define IEDMODEL_GenericIO_GGIO1_Health (&iedModel_GenericIO_GGIO1_Health)
+#define IEDMODEL_GenericIO_GGIO1_Health_stVal (&iedModel_GenericIO_GGIO1_Health_stVal)
+#define IEDMODEL_GenericIO_GGIO1_Health_q (&iedModel_GenericIO_GGIO1_Health_q)
+#define IEDMODEL_GenericIO_GGIO1_Health_t (&iedModel_GenericIO_GGIO1_Health_t)
+#define IEDMODEL_GenericIO_GGIO1_NamPlt (&iedModel_GenericIO_GGIO1_NamPlt)
+#define IEDMODEL_GenericIO_GGIO1_NamPlt_vendor (&iedModel_GenericIO_GGIO1_NamPlt_vendor)
+#define IEDMODEL_GenericIO_GGIO1_NamPlt_swRev (&iedModel_GenericIO_GGIO1_NamPlt_swRev)
+#define IEDMODEL_GenericIO_GGIO1_NamPlt_d (&iedModel_GenericIO_GGIO1_NamPlt_d)
+#define IEDMODEL_GenericIO_GGIO1_AnIn1 (&iedModel_GenericIO_GGIO1_AnIn1)
+#define IEDMODEL_GenericIO_GGIO1_AnIn1_mag (&iedModel_GenericIO_GGIO1_AnIn1_mag)
+#define IEDMODEL_GenericIO_GGIO1_AnIn1_mag_f (&iedModel_GenericIO_GGIO1_AnIn1_mag_f)
+#define IEDMODEL_GenericIO_GGIO1_AnIn1_q (&iedModel_GenericIO_GGIO1_AnIn1_q)
+#define IEDMODEL_GenericIO_GGIO1_AnIn1_t (&iedModel_GenericIO_GGIO1_AnIn1_t)
+#define IEDMODEL_GenericIO_GGIO1_AnIn2 (&iedModel_GenericIO_GGIO1_AnIn2)
+#define IEDMODEL_GenericIO_GGIO1_AnIn2_mag (&iedModel_GenericIO_GGIO1_AnIn2_mag)
+#define IEDMODEL_GenericIO_GGIO1_AnIn2_mag_f (&iedModel_GenericIO_GGIO1_AnIn2_mag_f)
+#define IEDMODEL_GenericIO_GGIO1_AnIn2_q (&iedModel_GenericIO_GGIO1_AnIn2_q)
+#define IEDMODEL_GenericIO_GGIO1_AnIn2_t (&iedModel_GenericIO_GGIO1_AnIn2_t)
+#define IEDMODEL_GenericIO_GGIO1_AnIn3 (&iedModel_GenericIO_GGIO1_AnIn3)
+#define IEDMODEL_GenericIO_GGIO1_AnIn3_mag (&iedModel_GenericIO_GGIO1_AnIn3_mag)
+#define IEDMODEL_GenericIO_GGIO1_AnIn3_mag_f (&iedModel_GenericIO_GGIO1_AnIn3_mag_f)
+#define IEDMODEL_GenericIO_GGIO1_AnIn3_q (&iedModel_GenericIO_GGIO1_AnIn3_q)
+#define IEDMODEL_GenericIO_GGIO1_AnIn3_t (&iedModel_GenericIO_GGIO1_AnIn3_t)
+#define IEDMODEL_GenericIO_GGIO1_AnIn4 (&iedModel_GenericIO_GGIO1_AnIn4)
+#define IEDMODEL_GenericIO_GGIO1_AnIn4_mag (&iedModel_GenericIO_GGIO1_AnIn4_mag)
+#define IEDMODEL_GenericIO_GGIO1_AnIn4_mag_f (&iedModel_GenericIO_GGIO1_AnIn4_mag_f)
+#define IEDMODEL_GenericIO_GGIO1_AnIn4_q (&iedModel_GenericIO_GGIO1_AnIn4_q)
+#define IEDMODEL_GenericIO_GGIO1_AnIn4_t (&iedModel_GenericIO_GGIO1_AnIn4_t)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1 (&iedModel_GenericIO_GGIO1_SPCSO1)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_stVal (&iedModel_GenericIO_GGIO1_SPCSO1_stVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_q (&iedModel_GenericIO_GGIO1_SPCSO1_q)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper (&iedModel_GenericIO_GGIO1_SPCSO1_Oper)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlNum)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_T)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_Test)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO1_Oper_Check)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO1_ctlModel)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO1_t (&iedModel_GenericIO_GGIO1_SPCSO1_t)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2 (&iedModel_GenericIO_GGIO1_SPCSO2)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_stVal (&iedModel_GenericIO_GGIO1_SPCSO2_stVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_q (&iedModel_GenericIO_GGIO1_SPCSO2_q)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper (&iedModel_GenericIO_GGIO1_SPCSO2_Oper)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlNum)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_T)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_Test)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO2_Oper_Check)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO2_ctlModel)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO2_t (&iedModel_GenericIO_GGIO1_SPCSO2_t)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3 (&iedModel_GenericIO_GGIO1_SPCSO3)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_stVal (&iedModel_GenericIO_GGIO1_SPCSO3_stVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_q (&iedModel_GenericIO_GGIO1_SPCSO3_q)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper (&iedModel_GenericIO_GGIO1_SPCSO3_Oper)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlNum)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_T)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_Test)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO3_Oper_Check)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO3_ctlModel)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO3_t (&iedModel_GenericIO_GGIO1_SPCSO3_t)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4 (&iedModel_GenericIO_GGIO1_SPCSO4)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_stVal (&iedModel_GenericIO_GGIO1_SPCSO4_stVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_q (&iedModel_GenericIO_GGIO1_SPCSO4_q)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper (&iedModel_GenericIO_GGIO1_SPCSO4_Oper)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_ctlVal (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_origin (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_ctlNum (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlNum)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_T (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_T)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_Test (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_Test)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_Oper_Check (&iedModel_GenericIO_GGIO1_SPCSO4_Oper_Check)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_ctlModel (&iedModel_GenericIO_GGIO1_SPCSO4_ctlModel)
+#define IEDMODEL_GenericIO_GGIO1_SPCSO4_t (&iedModel_GenericIO_GGIO1_SPCSO4_t)
+#define IEDMODEL_GenericIO_GGIO1_Ind1 (&iedModel_GenericIO_GGIO1_Ind1)
+#define IEDMODEL_GenericIO_GGIO1_Ind1_stVal (&iedModel_GenericIO_GGIO1_Ind1_stVal)
+#define IEDMODEL_GenericIO_GGIO1_Ind1_q (&iedModel_GenericIO_GGIO1_Ind1_q)
+#define IEDMODEL_GenericIO_GGIO1_Ind1_t (&iedModel_GenericIO_GGIO1_Ind1_t)
+#define IEDMODEL_GenericIO_GGIO1_Ind2 (&iedModel_GenericIO_GGIO1_Ind2)
+#define IEDMODEL_GenericIO_GGIO1_Ind2_stVal (&iedModel_GenericIO_GGIO1_Ind2_stVal)
+#define IEDMODEL_GenericIO_GGIO1_Ind2_q (&iedModel_GenericIO_GGIO1_Ind2_q)
+#define IEDMODEL_GenericIO_GGIO1_Ind2_t (&iedModel_GenericIO_GGIO1_Ind2_t)
+#define IEDMODEL_GenericIO_GGIO1_Ind3 (&iedModel_GenericIO_GGIO1_Ind3)
+#define IEDMODEL_GenericIO_GGIO1_Ind3_stVal (&iedModel_GenericIO_GGIO1_Ind3_stVal)
+#define IEDMODEL_GenericIO_GGIO1_Ind3_q (&iedModel_GenericIO_GGIO1_Ind3_q)
+#define IEDMODEL_GenericIO_GGIO1_Ind3_t (&iedModel_GenericIO_GGIO1_Ind3_t)
+#define IEDMODEL_GenericIO_GGIO1_Ind4 (&iedModel_GenericIO_GGIO1_Ind4)
+#define IEDMODEL_GenericIO_GGIO1_Ind4_stVal (&iedModel_GenericIO_GGIO1_Ind4_stVal)
+#define IEDMODEL_GenericIO_GGIO1_Ind4_q (&iedModel_GenericIO_GGIO1_Ind4_q)
+#define IEDMODEL_GenericIO_GGIO1_Ind4_t (&iedModel_GenericIO_GGIO1_Ind4_t)
+
+#endif /* STATIC_MODEL_H_ */
+
diff --git a/examples/server_example_files/vmd-filestore/test b/examples/server_example_files/vmd-filestore/test
new file mode 100644
index 00000000..9daeafb9
--- /dev/null
+++ b/examples/server_example_files/vmd-filestore/test
@@ -0,0 +1 @@
+test
diff --git a/examples/server_example_password_auth/CMakeLists.txt b/examples/server_example_password_auth/CMakeLists.txt
new file mode 100644
index 00000000..db7376d2
--- /dev/null
+++ b/examples/server_example_password_auth/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(
+ .
+)
+
+set(server_example_SRCS
+ server_example_password_auth.c
+ static_model.c
+)
+
+IF(WIN32)
+set_source_files_properties(${server_example_SRCS}
+ PROPERTIES LANGUAGE CXX)
+ENDIF(WIN32)
+
+add_executable(server_example_password_auth
+ ${server_example_SRCS}
+)
+
+target_link_libraries(server_example_password_auth
+ iec61850
+)
diff --git a/examples/server_example4/Makefile b/examples/server_example_password_auth/Makefile
similarity index 85%
rename from examples/server_example4/Makefile
rename to examples/server_example_password_auth/Makefile
index 4907673e..62a92580 100644
--- a/examples/server_example4/Makefile
+++ b/examples/server_example_password_auth/Makefile
@@ -1,7 +1,7 @@
LIBIEC_HOME=../..
-PROJECT_BINARY_NAME = server_example4
-PROJECT_SOURCES = server_example4.c
+PROJECT_BINARY_NAME = server_example_password_auth
+PROJECT_SOURCES = server_example_password_auth.c
PROJECT_SOURCES += static_model.c
PROJECT_ICD_FILE = simpleIO_direct_control.icd
diff --git a/examples/server_example4/server_example4.c b/examples/server_example_password_auth/server_example_password_auth.c
similarity index 89%
rename from examples/server_example4/server_example4.c
rename to examples/server_example_password_auth/server_example_password_auth.c
index b3aa07fc..92f7aac5 100644
--- a/examples/server_example4/server_example4.c
+++ b/examples/server_example_password_auth/server_example_password_auth.c
@@ -1,5 +1,5 @@
/*
- * server_example4.c
+ * server_example_password_auth.c
*
* Example server application with password authentication.
*
@@ -15,11 +15,11 @@
*/
#include "iec61850_server.h"
-#include "static_model.h"
#include "hal_thread.h"
#include
#include
#include
+#include "../server_example_password_auth/static_model.h"
/* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel;
@@ -37,13 +37,32 @@ void sigint_handler(int signalId)
static char* password1 = "user1@testpw";
static char* password2 = "user2@testpw";
+static void printAppTitle(ItuObjectIdentifier* oid)
+{
+ int i;
+
+ for (i = 0; i < oid->arcCount; i++) {
+ printf("%i", oid->arc[i]);
+
+ if (i != (oid->arcCount - 1))
+ printf(".");
+ }
+}
+
/**
* This is the AcseAuthenticator callback function that is invoked on each client connection attempt.
* When returning true the server stack accepts the client. Otherwise the connection is rejected.
+ *
+ * The security token can be used to pass an application specific object to other library callbacks
*/
static bool
-clientAuthenticator(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken)
+clientAuthenticator(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken, IsoApplicationReference* appRef)
{
+ printf("ACSE Authenticator:\n");
+ printf(" client ap-title: "); printAppTitle(&(appRef->apTitle)); printf("\n");
+ printf(" client ae-qualifier: %i\n", appRef->aeQualifier);
+
+
if (authParameter->mechanism == ACSE_AUTH_PASSWORD) {
if (authParameter->value.password.passwordLength == strlen(password1)) {
if (memcmp(authParameter->value.password.octetString, password1,
diff --git a/examples/server_example4/simpleIO_direct_control.icd b/examples/server_example_password_auth/simpleIO_direct_control.icd
similarity index 100%
rename from examples/server_example4/simpleIO_direct_control.icd
rename to examples/server_example_password_auth/simpleIO_direct_control.icd
diff --git a/examples/server_example4/static_model.c b/examples/server_example_password_auth/static_model.c
similarity index 99%
rename from examples/server_example4/static_model.c
rename to examples/server_example_password_auth/static_model.c
index bf02f9d5..1db7d778 100644
--- a/examples/server_example4/static_model.c
+++ b/examples/server_example_password_auth/static_model.c
@@ -3,7 +3,7 @@
*
* automatically generated from simpleIO_direct_control.icd
*/
-#include "static_model.h"
+#include "../server_example_password_auth/static_model.h"
static void initializeValues();
diff --git a/examples/server_example4/static_model.h b/examples/server_example_password_auth/static_model.h
similarity index 100%
rename from examples/server_example4/static_model.h
rename to examples/server_example_password_auth/static_model.h
diff --git a/examples/server_example_simple/CMakeLists.txt b/examples/server_example_simple/CMakeLists.txt
new file mode 100644
index 00000000..f7884c94
--- /dev/null
+++ b/examples/server_example_simple/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(
+ .
+)
+
+set(server_example_SRCS
+ server_example_simple.c
+ static_model.c
+)
+
+IF(WIN32)
+set_source_files_properties(${server_example_SRCS}
+ PROPERTIES LANGUAGE CXX)
+ENDIF(WIN32)
+
+add_executable(server_example_simple
+ ${server_example_SRCS}
+)
+
+target_link_libraries(server_example_simple
+ iec61850
+)
diff --git a/examples/server_example1/Makefile b/examples/server_example_simple/Makefile
similarity index 87%
rename from examples/server_example1/Makefile
rename to examples/server_example_simple/Makefile
index 0643046e..4d9c741f 100644
--- a/examples/server_example1/Makefile
+++ b/examples/server_example_simple/Makefile
@@ -1,7 +1,7 @@
LIBIEC_HOME=../..
-PROJECT_BINARY_NAME = server_example1
-PROJECT_SOURCES = server_example1.c
+PROJECT_BINARY_NAME = server_example_simple
+PROJECT_SOURCES = server_example_simple.c
PROJECT_SOURCES += static_model.c
PROJECT_ICD_FILE = sampleModel_with_dataset.icd
diff --git a/examples/server_example1/sampleModel_with_dataset.icd b/examples/server_example_simple/sampleModel_with_dataset.icd
similarity index 100%
rename from examples/server_example1/sampleModel_with_dataset.icd
rename to examples/server_example_simple/sampleModel_with_dataset.icd
diff --git a/examples/server_example1/server_example1.c b/examples/server_example_simple/server_example_simple.c
similarity index 95%
rename from examples/server_example1/server_example1.c
rename to examples/server_example_simple/server_example_simple.c
index f702b1ad..f531e577 100644
--- a/examples/server_example1/server_example1.c
+++ b/examples/server_example_simple/server_example_simple.c
@@ -1,5 +1,5 @@
/*
- * server_example1.c
+ * server_example_simple.c
*
* Copyright 2013 Michael Zillgith
*
@@ -27,7 +27,7 @@
#include
#include
-#include "static_model.h"
+#include "../server_example_simple/static_model.h"
/* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel;
diff --git a/examples/server_example1/static_model.c b/examples/server_example_simple/static_model.c
similarity index 99%
rename from examples/server_example1/static_model.c
rename to examples/server_example_simple/static_model.c
index f4bb1e61..922e1c25 100644
--- a/examples/server_example1/static_model.c
+++ b/examples/server_example_simple/static_model.c
@@ -3,7 +3,7 @@
*
* automatically generated from sampleModel_with_dataset.icd
*/
-#include "static_model.h"
+#include "../server_example_simple/static_model.h"
static void initializeValues();
diff --git a/examples/server_example1/static_model.h b/examples/server_example_simple/static_model.h
similarity index 100%
rename from examples/server_example1/static_model.h
rename to examples/server_example_simple/static_model.h
diff --git a/examples/server_example_write_handler/CMakeLists.txt b/examples/server_example_write_handler/CMakeLists.txt
new file mode 100644
index 00000000..ebcf8d13
--- /dev/null
+++ b/examples/server_example_write_handler/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(
+ .
+)
+
+set(server_example_SRCS
+ server_example_write_handler.c
+ static_model.c
+)
+
+IF(WIN32)
+set_source_files_properties(${server_example_SRCS}
+ PROPERTIES LANGUAGE CXX)
+ENDIF(WIN32)
+
+add_executable(server_example_write_handler
+ ${server_example_SRCS}
+)
+
+target_link_libraries(server_example_write_handler
+ iec61850
+)
diff --git a/examples/server_example5/Makefile b/examples/server_example_write_handler/Makefile
similarity index 85%
rename from examples/server_example5/Makefile
rename to examples/server_example_write_handler/Makefile
index 4a2c4199..639e88ef 100644
--- a/examples/server_example5/Makefile
+++ b/examples/server_example_write_handler/Makefile
@@ -1,7 +1,7 @@
LIBIEC_HOME=../..
-PROJECT_BINARY_NAME = server_example5
-PROJECT_SOURCES = server_example5.c
+PROJECT_BINARY_NAME = server_example_write_handler
+PROJECT_SOURCES = server_example_write_handler.c
PROJECT_SOURCES += static_model.c
PROJECT_ICD_FILE = complexModel.icd
diff --git a/examples/server_example5/complexModel.icd b/examples/server_example_write_handler/complexModel.icd
similarity index 100%
rename from examples/server_example5/complexModel.icd
rename to examples/server_example_write_handler/complexModel.icd
diff --git a/examples/server_example5/server_example5.c b/examples/server_example_write_handler/server_example_write_handler.c
similarity index 95%
rename from examples/server_example5/server_example5.c
rename to examples/server_example_write_handler/server_example_write_handler.c
index 1d6d90ee..0666e817 100644
--- a/examples/server_example5/server_example5.c
+++ b/examples/server_example_write_handler/server_example_write_handler.c
@@ -1,5 +1,5 @@
/*
- * server_example5.c
+ * server_example_write_handler.c
*/
#include "iec61850_server.h"
@@ -8,7 +8,7 @@
#include
#include
-#include "static_model.h"
+#include "../server_example_write_handler/static_model.h"
/* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel;
diff --git a/examples/server_example5/static_model.c b/examples/server_example_write_handler/static_model.c
similarity index 99%
rename from examples/server_example5/static_model.c
rename to examples/server_example_write_handler/static_model.c
index 91d0dcb0..c0dba265 100644
--- a/examples/server_example5/static_model.c
+++ b/examples/server_example_write_handler/static_model.c
@@ -3,7 +3,7 @@
*
* automatically generated from complexModel.icd
*/
-#include "static_model.h"
+#include "../server_example_write_handler/static_model.h"
static void initializeValues();
diff --git a/examples/server_example2/static_model.h b/examples/server_example_write_handler/static_model.h
similarity index 100%
rename from examples/server_example2/static_model.h
rename to examples/server_example_write_handler/static_model.h
diff --git a/examples/sv_publisher/sv_publisher_example.c b/examples/sv_publisher/sv_publisher_example.c
index b048befe..e1128602 100644
--- a/examples/sv_publisher/sv_publisher_example.c
+++ b/examples/sv_publisher/sv_publisher_example.c
@@ -20,7 +20,16 @@ void sigint_handler(int signalId)
int
main(int argc, char** argv)
{
- SampledValuesPublisher svPublisher = SampledValuesPublisher_create("vboxnet0");
+ char* interface;
+
+ if (argc > 1)
+ interface = argv[1];
+ else
+ interface = "eth0";
+
+ printf("Using interface %s\n", interface);
+
+ SampledValuesPublisher svPublisher = SampledValuesPublisher_create(NULL, interface);
SV_ASDU asdu1 = SampledValuesPublisher_addASDU(svPublisher, "svpub1", NULL, 1);
@@ -51,7 +60,7 @@ main(int argc, char** argv)
SampledValuesPublisher_publish(svPublisher);
- //Thread_sleep(50);
+ Thread_sleep(50);
}
SampledValuesPublisher_destroy(svPublisher);
diff --git a/pyiec61850/CMakeLists.txt b/pyiec61850/CMakeLists.txt
index f5f0f922..156f90f2 100644
--- a/pyiec61850/CMakeLists.txt
+++ b/pyiec61850/CMakeLists.txt
@@ -1,23 +1,40 @@
-FIND_PACKAGE(SWIG REQUIRED)
-INCLUDE(${SWIG_USE_FILE})
-FIND_PACKAGE(PythonLibs REQUIRED)
-FIND_PACKAGE ( PythonInterp ${PYTHONLIBS_VERSION_STRING} EXACT REQUIRED )
-INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
-SET(CMAKE_SWIG_FLAGS "")
-SET_PROPERTY(SOURCE iec61850.i PROPERTY CPLUSPLUS ON)
-SWIG_ADD_MODULE(iec61850 python iec61850.i)
-IF(WIN32)
- SWIG_LINK_LIBRARIES(iec61850 ${PYTHON_LIBRARIES} iec61850 ws2_32)
-ELSE()
- SWIG_LINK_LIBRARIES(iec61850 ${PYTHON_LIBRARIES} iec61850-shared)
-ENDIF(WIN32)
-EXECUTE_PROCESS ( #Finding python modules install path
- COMMAND ${PYTHON_EXECUTABLE} -c
- "import site, sys; sys.stdout.write(site.getsitepackages()[-1])"
- OUTPUT_VARIABLE PYTHON_SITE_DIR
- )
-INSTALL ( FILES ${CMAKE_CURRENT_BINARY_DIR}/iec61850.py DESTINATION ${PYTHON_SITE_DIR})
-INSTALL ( TARGETS _iec61850 LIBRARY DESTINATION ${PYTHON_SITE_DIR})
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(PythonLibs REQUIRED)
+find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} EXACT REQUIRED)
+
+include_directories(${PYTHON_INCLUDE_PATH})
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+set(CMAKE_SWIG_FLAGS "")
+set_property(SOURCE iec61850.i PROPERTY CPLUSPLUS ON)
+
+if(WIN32)
+ set(LIBS iec61850 ws2_32)
+else()
+ set(LIBS iec61850-shared)
+endif()
+
+if(${SWIG_VERSION} VERSION_LESS 3.0)
+ swig_add_module(iec61850 python iec61850.i)
+else()
+ swig_add_library(iec61850
+ LANGUAGE python
+ SOURCES iec61850.i
+ )
+endif()
+
+swig_link_libraries(iec61850 ${PYTHON_LIBRARIES} ${LIBS})
+
+# Finding python modules install path
+execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -c
+ "import site, sys; sys.stdout.write(site.getsitepackages()[-1])"
+ OUTPUT_VARIABLE PYTHON_SITE_DIR
+)
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/iec61850.py DESTINATION ${PYTHON_SITE_DIR})
+install(TARGETS _iec61850 LIBRARY DESTINATION ${PYTHON_SITE_DIR})
add_test(test_pyiec61850 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/test_pyiec61850.py)
diff --git a/src/common/inc/libiec61850_platform_includes.h b/src/common/inc/libiec61850_platform_includes.h
index 4dc01c29..68526a4b 100644
--- a/src/common/inc/libiec61850_platform_includes.h
+++ b/src/common/inc/libiec61850_platform_includes.h
@@ -15,7 +15,7 @@
#include "platform_endian.h"
-#define LIBIEC61850_VERSION "1.0.2"
+#define LIBIEC61850_VERSION "1.1.1"
#ifndef CONFIG_DEFAULT_MMS_VENDOR_NAME
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"
diff --git a/src/doxygen.config b/src/doxygen.config
index f188266a..69580e5d 100644
--- a/src/doxygen.config
+++ b/src/doxygen.config
@@ -18,7 +18,7 @@ DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "libIEC61850"
-PROJECT_NUMBER = 1.0.2
+PROJECT_NUMBER = 1.1.1
PROJECT_BRIEF = "Open-source IEC 61850 MMS/GOOSE/SV server and client library"
diff --git a/src/goose/goose_publisher.h b/src/goose/goose_publisher.h
index 29ed6c68..a206e69e 100644
--- a/src/goose/goose_publisher.h
+++ b/src/goose/goose_publisher.h
@@ -31,6 +31,9 @@
extern "C" {
#endif
+#ifndef GOOSE_SV_COMM_PARAMETERS
+#define GOOSE_SV_COMM_PARAMETERS
+
typedef struct sCommParameters {
uint8_t vlanPriority;
uint16_t vlanId;
@@ -38,6 +41,8 @@ typedef struct sCommParameters {
uint8_t dstAddress[6];
} CommParameters;
+#endif
+
typedef struct sGoosePublisher* GoosePublisher;
GoosePublisher
diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c
index 26618ee8..0f1b5355 100644
--- a/src/goose/goose_receiver.c
+++ b/src/goose/goose_receiver.c
@@ -1,7 +1,7 @@
/*
* goose_receiver.c
*
- * Copyright 2014, 2015 Michael Zillgith
+ * Copyright 2014-2017 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -52,6 +52,9 @@ struct sGooseReceiver {
uint8_t* buffer;
EthernetSocket ethSocket;
LinkedList subscriberList;
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Thread thread;
+#endif
};
@@ -66,6 +69,9 @@ GooseReceiver_create()
self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH);
self->ethSocket = NULL;
self->subscriberList = LinkedList_create();
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ self->thread = NULL;
+#endif
}
return self;
@@ -712,33 +718,52 @@ gooseReceiverLoop(void* threadParameter)
void
GooseReceiver_start(GooseReceiver self)
{
- Thread thread = Thread_create((ThreadExecutionFunction) gooseReceiverLoop, (void*) self, true);
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ self->thread = Thread_create((ThreadExecutionFunction) gooseReceiverLoop, (void*) self, false);
- if (thread != NULL) {
+ if (self->thread != NULL) {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: GOOSE receiver started for interface %s\n", self->interfaceId);
- Thread_start(thread);
+ Thread_start(self->thread);
}
else {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: Starting GOOSE receiver failed for interface %s\n", self->interfaceId);
}
+#endif
+}
+bool
+GooseReceiver_isRunning(GooseReceiver self)
+{
+ return self->running;
}
void
GooseReceiver_stop(GooseReceiver self)
{
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
self->running = false;
+ Thread_destroy(self->thread);
+
while (self->stopped == false)
Thread_sleep(1);
+#endif
}
void
GooseReceiver_destroy(GooseReceiver self)
{
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ if ((self->thread != NULL) && (GooseReceiver_isRunning(self)))
+ GooseReceiver_stop(self);
+#endif
+
+ if (self->interfaceId != NULL)
+ GLOBAL_FREEMEM(self->interfaceId);
+
LinkedList_destroyDeep(self->subscriberList,
(LinkedListValueDeleteFunction) GooseSubscriber_destroy);
@@ -757,9 +782,12 @@ GooseReceiver_startThreadless(GooseReceiver self)
else
self->ethSocket = Ethernet_createSocket(self->interfaceId, NULL);
- Ethernet_setProtocolFilter(self->ethSocket, ETH_P_GOOSE);
-
- self->running = true;
+ if (self->ethSocket != NULL) {
+ Ethernet_setProtocolFilter(self->ethSocket, ETH_P_GOOSE);
+ self->running = true;
+ }
+ else
+ self->running = false;
}
void
@@ -770,7 +798,7 @@ GooseReceiver_stopThreadless(GooseReceiver self)
self->running = false;
}
-// call after reception of ethernet frame and periodically to to house keeping tasks
+// call after reception of ethernet frame
bool
GooseReceiver_tick(GooseReceiver self)
{
diff --git a/src/goose/goose_receiver.h b/src/goose/goose_receiver.h
index 51bdebc3..8ba5648c 100644
--- a/src/goose/goose_receiver.h
+++ b/src/goose/goose_receiver.h
@@ -92,7 +92,7 @@ void
GooseReceiver_start(GooseReceiver self);
/**
- * \brief stop the GOOSE receiver running in a speparate thread
+ * \brief stop the GOOSE receiver running in a separate thread
*
* This function is used to stop the receiver thread started with GooseReceiver_start
*
@@ -101,6 +101,14 @@ GooseReceiver_start(GooseReceiver self);
void
GooseReceiver_stop(GooseReceiver self);
+bool
+GooseReceiver_isRunning(GooseReceiver self);
+
+/**
+ * \brief Free all resource of the GooseReceiver and all installed GooseSubscribers
+ *
+ * \param self the GooseReceiver instance
+ */
void
GooseReceiver_destroy(GooseReceiver self);
diff --git a/src/hal/socket/win32/socket_win32.c b/src/hal/socket/win32/socket_win32.c
index 0e944455..777d17c8 100644
--- a/src/hal/socket/win32/socket_win32.c
+++ b/src/hal/socket/win32/socket_win32.c
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#pragma comment (lib, "Ws2_32.lib")
@@ -104,6 +105,9 @@ Handleset_destroy(HandleSet self)
GLOBAL_FREEMEM(self);
}
+static bool wsaStartupCalled = false;
+static int socketCount = 0;
+
static void
activateKeepAlive(SOCKET s)
{
@@ -162,19 +166,47 @@ prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr
return true;
}
+static bool wsaStartUp()
+{
+ if (wsaStartupCalled == false) {
+ int ec;
+ WSADATA wsa;
+
+ if ((ec = WSAStartup(MAKEWORD(2, 0), &wsa)) != 0) {
+ if (DEBUG_SOCKET)
+ printf("WIN32_SOCKET: winsock error: code %i\n", ec);
+ return false;
+ }
+ else {
+ wsaStartupCalled = true;
+ return true;
+ }
+
+ }
+ else
+ return true;
+}
+
+static void wsaShutdown()
+{
+ if (wsaStartupCalled) {
+ if (socketCount == 0) {
+ WSACleanup();
+ wsaStartupCalled = false;
+ }
+
+ }
+}
+
ServerSocket
TcpServerSocket_create(const char* address, int port)
{
ServerSocket serverSocket = NULL;
int ec;
- WSADATA wsa;
SOCKET listen_socket = INVALID_SOCKET;
- if ((ec = WSAStartup(MAKEWORD(2,0), &wsa)) != 0) {
- if (DEBUG_SOCKET)
- printf("WIN32_SOCKET: winsock error: code %i\n", ec);
+ if (wsaStartUp() == false)
return NULL;
- }
struct sockaddr_in server_addr;
@@ -190,7 +222,9 @@ TcpServerSocket_create(const char* address, int port)
if (listen_socket == INVALID_SOCKET) {
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: socket failed with error: %i\n", WSAGetLastError());
- WSACleanup();
+
+ wsaShutdown();
+
return NULL;
}
@@ -203,7 +237,9 @@ TcpServerSocket_create(const char* address, int port)
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: bind failed with error:%i\n", WSAGetLastError());
closesocket(listen_socket);
- WSACleanup();
+
+ wsaShutdown();
+
return NULL;
}
@@ -214,6 +250,8 @@ TcpServerSocket_create(const char* address, int port)
setSocketNonBlocking((Socket) serverSocket);
+ socketCount++;
+
return serverSocket;
}
@@ -252,8 +290,9 @@ void
ServerSocket_destroy(ServerSocket self)
{
closesocket(self->fd);
- WSACleanup();
- free(self);
+ socketCount--;
+ wsaShutdown();
+ GLOBAL_FREEMEM(self);
}
Socket
@@ -264,6 +303,8 @@ TcpSocket_create()
self->fd = INVALID_SOCKET;
self->connectTimeout = 5000;
+ socketCount++;
+
return self;
}
@@ -277,14 +318,10 @@ bool
Socket_connect(Socket self, const char* address, int port)
{
struct sockaddr_in serverAddress;
- WSADATA wsa;
int ec;
- if ((ec = WSAStartup(MAKEWORD(2,0), &wsa)) != 0) {
- if (DEBUG_SOCKET)
- printf("WIN32_SOCKET: winsock error: code %i\n", ec);
+ if (wsaStartUp() == false)
return false;
- }
if (!prepareServerAddress(address, port, &serverAddress))
return false;
@@ -401,5 +438,8 @@ Socket_destroy(Socket self)
closesocket(self->fd);
}
- free(self);
+ socketCount--;
+ wsaShutdown();
+
+ GLOBAL_FREEMEM(self);
}
diff --git a/src/iec61850/client/client_control.c b/src/iec61850/client/client_control.c
index af9dd5d4..6358f614 100644
--- a/src/iec61850/client/client_control.c
+++ b/src/iec61850/client/client_control.c
@@ -149,6 +149,7 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
bool hasOper = false;
bool hasTimeActivatedControl = false;
bool hasCtlNum = false;
+ bool isAPC = false;
MmsVariableSpecification* ctlVal = NULL;
MmsVariableSpecification* t = NULL;
@@ -157,7 +158,12 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
if (oper)
{
- hasOper = true;
+ hasOper = true;
+
+ ctlVal = MmsVariableSpecification_getNamedVariableRecursive(oper, "ctlVal");
+
+ if (MmsVariableSpecification_getType(ctlVal) == MMS_STRUCTURE)
+ isAPC = true;
MmsVariableSpecification* operTm = MmsVariableSpecification_getNamedVariableRecursive(oper, "operTm");
@@ -169,7 +175,6 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
if (ctlNum)
hasCtlNum = true;
- ctlVal = MmsVariableSpecification_getNamedVariableRecursive(oper, "ctlVal");
t = MmsVariableSpecification_getNamedVariableRecursive(oper, "T");
}
}
@@ -200,6 +205,11 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
self->hasCtlNum = hasCtlNum;
self->ctlVal = MmsValue_newDefaultValue(ctlVal);
+ if (isAPC)
+ self->analogValue = MmsValue_createEmptyStructure(1);
+ else
+ self->analogValue = NULL;
+
/* Check for T element type (Binary time -> Ed.1,UTC time -> Ed.2) */
if (MmsVariableSpecification_getType(t) == MMS_BINARY_TIME)
self->edition = 1;
@@ -218,162 +228,6 @@ exit_function:
return self;
}
-
-#if 0
-ControlObjectClient
-ControlObjectClient_create(const char* objectReference, IedConnection connection)
-{
- ControlObjectClient self = NULL;
-
- /* request control model from server */
- char domainId[65];
- char itemId[129];
-
- char* domainName = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainId);
-
- if (domainName == NULL)
- goto exit_function;
-
- convertToMmsAndInsertFC(itemId, objectReference + strlen(domainId) + 1, "CF");
-
- int controlObjectItemIdLen = strlen(itemId);
-
- strncat(itemId, "$ctlModel", 64 - controlObjectItemIdLen);
-
- MmsError mmsError;
-
- MmsValue* ctlModel = MmsConnection_readVariable(IedConnection_getMmsConnection(connection),
- &mmsError, domainId, itemId);
-
- if (ctlModel == NULL) {
- if (DEBUG_IED_CLIENT)
- printf("IED_CLIENT: ControlObjectClient_create: failed to get ctlModel from server\n");
-
- goto exit_function;
- }
-
- int ctlModelVal = MmsValue_toUint32(ctlModel);
-
- MmsValue_delete(ctlModel);
-
- IedClientError error;
-
- LinkedList dataDirectory =
- IedConnection_getDataDirectory(connection, &error, objectReference);
-
- if (dataDirectory == NULL) {
- if (DEBUG_IED_CLIENT)
- printf("IED_CLIENT: ControlObjectClient_create: failed to get data directory of control object\n");
-
- goto exit_function;
- }
-
- /* check what control elements are available */
- bool hasOper = false;
-
- LinkedList element = LinkedList_getNext(dataDirectory);
-
- while (element != NULL) {
- char* objectName = (char*) element->data;
-
- if (strcmp(objectName, "Oper") == 0)
- hasOper = true;
-
- element = LinkedList_getNext(element);
- }
-
- LinkedList_destroy(dataDirectory);
-
- if (hasOper == false) {
- if (DEBUG_IED_CLIENT)
- printf("IED_CLIENT: control is missing required element \"Oper\"\n");
-
- goto exit_function;
- }
-
- /* check for time activated control and ctlNum */
- bool hasTimeActivatedControl = false;
- bool hasCtlNum = false;
-
- strcpy(itemId, objectReference);
- strcat(itemId, ".Oper");
- dataDirectory = IedConnection_getDataDirectory(connection, &error, itemId);
-
- if (dataDirectory == NULL)
- goto exit_function;
-
- element = LinkedList_getNext(dataDirectory);
-
- while (element != NULL) {
- char* objectName = (char*) element->data;
-
- if (strcmp(objectName, "operTm") == 0) {
- hasTimeActivatedControl = true;
- }
- else if (strcmp(objectName, "ctlNum") == 0) {
- hasCtlNum = true;
- }
-
- element = LinkedList_getNext(element);
- }
-
- LinkedList_destroy(dataDirectory);
-
- /* get default parameters for Oper control variable */
-
- MmsValue* oper = IedConnection_readObject(connection, &error, itemId, IEC61850_FC_CO);
-
- if (oper == NULL) {
- if (DEBUG_IED_CLIENT)
- printf("IED_CLIENT: reading \"Oper\" failed!\n");
-
- goto exit_function;
- }
-
- self = (ControlObjectClient) GLOBAL_CALLOC(1, sizeof(struct sControlObjectClient));
-
- if (self == NULL)
- goto exit_function;
-
- self->objectReference = StringUtils_copyString(objectReference);
- self->connection = connection;
- self->ctlModel = (ControlModel) ctlModelVal;
- self->hasTimeActivatedMode = hasTimeActivatedControl;
- self->hasCtlNum = hasCtlNum;
- self->ctlVal = MmsValue_getElement(oper, 0);
-
- if (MmsValue_getType(self->ctlVal) == MMS_STRUCTURE)
- self->analogValue = MmsValue_createEmptyStructure(1);
- else
- self->analogValue = NULL;
-
-
- /* Check for T element type (Binary time -> Ed.1,UTC time -> Ed.2) */
- MmsValue* t;
-
- if (hasTimeActivatedControl)
- t = MmsValue_getElement(oper, 4);
- else
- t = MmsValue_getElement(oper, 3);
-
- if (MmsValue_getType(t) == MMS_BINARY_TIME)
- self->edition = 1;
- else
- self->edition = 2;
-
- if (DEBUG_IED_CLIENT)
- printf("IED_CLIENT: Detected edition %i control\n", self->edition);
-
- MmsValue_setElement(oper, 0, NULL);
- MmsValue_delete(oper);
-
- private_IedConnection_addControlClient(connection, self);
-
-exit_function:
- return self;
-}
-#endif
-
void
ControlObjectClient_destroy(ControlObjectClient self)
{
diff --git a/src/iec61850/client/client_report_control.c b/src/iec61850/client/client_report_control.c
index d9d187ef..bce37e21 100644
--- a/src/iec61850/client/client_report_control.c
+++ b/src/iec61850/client/client_report_control.c
@@ -32,12 +32,19 @@
#include "libiec61850_platform_includes.h"
static bool
-isBufferedRcb(const char* objectReference)
+isBufferedRcb(const char* objectReference, bool* isValid)
{
const char* separator = strchr(objectReference, '.');
if (separator == NULL)
+ separator = strchr(objectReference, '$');
+
+ if (separator == NULL) {
+ *isValid = false;
return false;
+ }
+
+ *isValid = true;
if (*(separator + 1) == 'B')
return true;
@@ -48,12 +55,24 @@ isBufferedRcb(const char* objectReference)
ClientReportControlBlock
ClientReportControlBlock_create(const char* objectReference)
{
- ClientReportControlBlock self = (ClientReportControlBlock) GLOBAL_CALLOC(1, sizeof(struct sClientReportControlBlock));
+ bool isReferenceValid;
+ bool isBuffered;
+
+ isBuffered = isBufferedRcb(objectReference, &isReferenceValid);
+
+ if (isReferenceValid == false) {
+ if (DEBUG_IED_CLIENT)
+ printf("DEBUG_IED_CLIENT: RCB reference invalid\n");
+
+ return NULL;
+ }
- //TODO check validity of object reference?!
+ ClientReportControlBlock self = (ClientReportControlBlock) GLOBAL_CALLOC(1, sizeof(struct sClientReportControlBlock));
- self->objectReference = StringUtils_copyString(objectReference);
- self->isBuffered = isBufferedRcb(objectReference);
+ if (self) {
+ self->objectReference = StringUtils_copyString(objectReference);
+ self->isBuffered = isBuffered;
+ }
return self;
}
diff --git a/src/iec61850/client/ied_connection.c b/src/iec61850/client/ied_connection.c
index 63c60333..fdad55db 100644
--- a/src/iec61850/client/ied_connection.c
+++ b/src/iec61850/client/ied_connection.c
@@ -1131,6 +1131,32 @@ IedConnection_getFileDirectory(IedConnection self, IedClientError* error, const
return fileNames;
}
+LinkedList /**/
+IedConnection_getFileDirectoryEx(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
+ bool* moreFollows)
+{
+ *error = IED_ERROR_OK;
+
+ MmsError mmsError = MMS_ERROR_NONE;
+
+ LinkedList fileNames = LinkedList_create();
+
+ bool moreFollowsInternal = MmsConnection_getFileDirectory(self->connection, &mmsError, directoryName, continueAfter,
+ mmsFileDirectoryHandler, fileNames);
+
+ if (mmsError != MMS_ERROR_NONE) {
+ *error = iedConnection_mapMmsErrorToIedError(mmsError);
+ LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
+
+ return NULL;
+ }
+
+ if (moreFollows != NULL)
+ *moreFollows = moreFollowsInternal;
+
+ return fileNames;
+}
+
struct sClientProvidedFileReadHandler {
IedClientGetFileHandler handler;
@@ -1201,6 +1227,13 @@ IedConnection_getFile(IedConnection self, IedClientError* error, const char* fil
return clientFileReadHandler.byteReceived;
}
+void
+IedConnection_setFilestoreBasepath(IedConnection self, const char* basepath)
+{
+ /* simply pass the call to MMS client API */
+ MmsConnection_setFilestoreBasepath(self->connection, basepath);
+}
+
void
IedConnection_setFile(IedConnection self, IedClientError* error, const char* sourceFilename, const char* destinationFilename)
{
@@ -1948,13 +1981,9 @@ getDataDirectoryByFc(IedConnection self, IedClientError* error,
int elementNameLen = strlen(subElementName);
- char* elementName = (char*) GLOBAL_MALLOC(elementNameLen + 5);
+ char* elementName = (char*) GLOBAL_MALLOC(elementNameLen + 1);
memcpy(elementName, subElementName, elementNameLen);
- elementName[elementNameLen] = '[';
- elementName[elementNameLen + 1] = *(fcPos + 1);
- elementName[elementNameLen + 2] = *(fcPos + 2);
- elementName[elementNameLen + 3] = ']';
- elementName[elementNameLen + 4] = 0;
+ elementName[elementNameLen] = 0;
if (!addToStringSet(dataDirectory, elementName))
GLOBAL_FREEMEM(elementName);
@@ -2297,6 +2326,64 @@ exit_function:
return dataSet;
}
+void
+IedConnection_writeDataSetValues(IedConnection self, IedClientError* error, const char* dataSetReference,
+ LinkedList/**/ values, /* OUTPUT */LinkedList* /* */accessResults)
+{
+ char domainIdBuffer[65];
+ char itemIdBuffer[DATA_SET_MAX_NAME_LENGTH + 1];
+
+ const char* domainId = NULL;
+ const char* itemId = NULL;
+
+ bool isAssociationSpecific = false;
+
+ if (dataSetReference[0] != '@') {
+
+ if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
+ domainId = NULL;
+
+ if (dataSetReference[0] == '/')
+ itemId = dataSetReference + 1;
+ else
+ itemId = dataSetReference;
+ }
+ else {
+ domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
+
+ if (domainId == NULL) {
+ *error = IED_ERROR_OBJECT_REFERENCE_INVALID;
+ goto exit_function;
+ }
+
+ const char* itemIdRefOrig = dataSetReference + strlen(domainId) + 1;
+
+ if (strlen(itemIdRefOrig) > DATA_SET_MAX_NAME_LENGTH) {
+ *error = IED_ERROR_OBJECT_REFERENCE_INVALID;
+ goto exit_function;
+ }
+
+ char* itemIdRef = StringUtils_copyStringToBuffer(itemIdRefOrig, itemIdBuffer);
+
+ StringUtils_replace(itemIdRef, '.', '$');
+ itemId = itemIdRef;
+ }
+ }
+ else {
+ itemId = dataSetReference + 1;
+ isAssociationSpecific = true;
+ }
+
+ MmsError mmsError;
+
+ MmsConnection_writeNamedVariableList(self->connection, &mmsError, isAssociationSpecific, domainId, itemId, values, accessResults);
+
+ *error = iedConnection_mapMmsErrorToIedError(mmsError);
+
+exit_function:
+ return;
+}
+
LinkedList /* */
IedConnection_queryLogByTime(IedConnection self, IedClientError* error, const char* logReference,
uint64_t startTime, uint64_t endTime, bool* moreFollows)
diff --git a/src/iec61850/common/iec61850_common.c b/src/iec61850/common/iec61850_common.c
index 31892033..d2a68988 100644
--- a/src/iec61850/common/iec61850_common.c
+++ b/src/iec61850/common/iec61850_common.c
@@ -405,6 +405,20 @@ Timestamp_setByMmsUtcTime(Timestamp* self, MmsValue* mmsValue)
memcpy(self->val, mmsValue->value.utcTime, 8);
}
+MmsValue*
+Timestamp_toMmsValue(Timestamp* self, MmsValue* mmsValue)
+{
+ MmsValue* convertedValue = mmsValue;
+
+ if (convertedValue == NULL)
+ convertedValue = MmsValue_newUtcTime(0);
+
+ if (convertedValue != NULL)
+ memcpy(convertedValue->value.utcTime, self->val, 8);
+
+ return convertedValue;
+}
+
char*
LibIEC61850_getVersionString()
{
diff --git a/src/iec61850/inc/iec61850_client.h b/src/iec61850/inc/iec61850_client.h
index 8d2b46b7..d319c109 100644
--- a/src/iec61850/inc/iec61850_client.h
+++ b/src/iec61850/inc/iec61850_client.h
@@ -625,7 +625,7 @@ IedConnection_setGoCBValues(IedConnection self, IedClientError* error, ClientGoo
*
* The requested RCB has to be specified by its object reference. E.g.
*
- * "simpleIOGernericIO/LLN0.RP.EventsRCB01"
+ * "simpleIOGenericIO/LLN0.RP.EventsRCB01"
*
* or
*
@@ -810,6 +810,8 @@ IedConnection_uninstallReportHandler(IedConnection self, const char* rcbReferenc
*
* The RCB must have been enabled and GI set as trigger option before this command can be performed.
*
+ * \deprecated Use ClientReportControlBlock_setGI instead
+ *
* \param connection the connection object
* \param error the error code if an error occurs
* \param rcbReference object reference of the report control block
@@ -1216,7 +1218,8 @@ IedConnection_readUnsigned32Value(IedConnection self, IedClientError* error, con
* \brief read a functional constrained data attribute (FCDA) of type Timestamp (UTC Time)
*
* NOTE: If the timestamp parameter is set to NULL the function allocates a new timestamp instance. Otherwise the
- * return value is a pointer to the user provided timestamp instance.
+ * return value is a pointer to the user provided timestamp instance. The new timestamp instance has to be freed by
+ * the caller of the function.
*
* \param self the connection object to operate on
* \param error the error code if an error occurs
@@ -1318,6 +1321,12 @@ IedConnection_writeOctetString(IedConnection self, IedClientError* error, const
/**
* \brief get data set values from a server device
*
+ * The parameter dataSetReference is the name of the data set to read. It is either in the form LDName/LNodeName.dataSetName
+ * for permanent domain or VMD scope data sets or @dataSetName for an association specific data set.
+ * If the LDName part of the reference is missing the resulting data set will be of VMD scope.
+ * The received data set values are stored in a container object of type ClientDataSet that can be reused in a further
+ * read request.
+ *
* \param connection the connection object
* \param error the error code if an error occurs
* \param dataSetReference object reference of the data set
@@ -1383,6 +1392,26 @@ IedConnection_deleteDataSet(IedConnection self, IedClientError* error, const cha
LinkedList /* */
IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, const char* dataSetReference, bool* isDeletable);
+/**
+ * \brief Write the data set values to the server
+ *
+ * The parameter dataSetReference is the name of the data set to write. It is either in the form LDName/LNodeName.dataSetName
+ * for permanent domain or VMD scope data sets or @dataSetName for an association specific data set.
+ * If the LDName part of the reference is missing the resulting data set will be of VMD scope.
+ * The values parameter has to be the same number of elements as are members in the data set. The accessResult return parameter
+ * contains a value for each data set member.
+ *
+ * \param connection the connection object
+ * \param error the error code if an error occurs
+ * \param dataSetReference object reference of the data set
+ * \param values the new data set values
+ * \param accessResults the access results for each data set member
+ */
+void
+IedConnection_writeDataSetValues(IedConnection self, IedClientError* error, const char* dataSetReference,
+ LinkedList/**/ values, /* OUTPUT */LinkedList* /* */accessResults);
+
+
/********************************************************
* Data set object (local representation of a data set)
*******************************************************/
@@ -1637,13 +1666,12 @@ IedConnection_getServerDirectory(IedConnection self, IedClientError* error, bool
/**
* \brief Get the list of logical nodes (LN) of a logical device
*
- * LGetLogicalDeviceDirectory ACSI service implementation. Returns the list of logical nodes present
- * in a logical device. The list is returned as a linked list of type LinkedList where the elements
- * are C style strings.
+ * GetLogicalDeviceDirectory ACSI service implementation. Returns the list of logical nodes names present
+ * in a logical device. The list is returned as a linked list of type LinkedList with c style string elements.
*
* \param self the connection object
* \param error the error code if an error occurs
- * \param getFileNames get list of files instead of logical device names (TO BE IMPLEMENTED)
+ * \param logicalDeviceName the name of the logical device (LD) of interest
*
* \return LinkedList with string elements representing the logical node names
*/
@@ -1738,8 +1766,10 @@ IedConnection_getDataDirectoryFC(IedConnection self, IedClientError* error, cons
* \brief returns the directory of the given data object/data attribute with the given FC
*
* Implementation of the GetDataDirectory ACSI service. This will return the list of
- * C strings with all data attributes or sub data objects as elements. The returned
- * strings will contain the functional constraint appended in square brackets when appropriate.
+ * C strings with all data attributes or sub data objects as elements.
+ *
+ * WARNING: Starting with version 1.0.3 the functional constraint will no longer be appended to
+ * the name string.
*
* \param self the connection object
* \param error the error code if an error occurs
@@ -1869,6 +1899,38 @@ FileDirectoryEntry_getLastModified(FileDirectoryEntry self);
LinkedList /**/
IedConnection_getFileDirectory(IedConnection self, IedClientError* error, const char* directoryName);
+
+/**
+ * \brief returns the directory entries of the specified file directory returned by a single file directory request.
+ *
+ * This function will only create a single request and the result may only be the directory that fits
+ * into a single MMS PDU. If the server contains more directory entries, this will be indicated by setting
+ * the moreFollows variable (if provided by the caller). If the directory entry does not fit into a single MMS
+ * PDU the next part of the directory list can be requested by setting the continueAfter parameter with the value
+ * of the last filename of the received list.
+ *
+ * Requires the server to support file services.
+ *
+ * NOTE: the returned linked list has to be freed by the user. You can user the following statement
+ * to free the list of directory entries:
+ *
+ * LinkedList_destroyDeep(fileNames, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
+ *
+ * where fileNames is the return value of this function.
+ *
+ * \param self the connection object
+ * \param error the error code if an error occurs
+ * \param directoryName the name of the directory or NULL to get the entries of the root directory
+ * \param continueAfter last received filename to continue after, or NULL for the first request
+ * \param moreFollows if provided by the caller (non NULL) the function will indicate if more directory entries
+ * are available.
+ *
+ * \return the list of directory entries. The return type is a LinkedList with FileDirectoryEntry elements
+ */
+LinkedList /**/
+IedConnection_getFileDirectoryEx(IedConnection self, IedClientError* error, const char* directoryName, const char* continueAfter,
+ bool* moreFollows);
+
/**
* \brief user provided handler to receive the data of the GetFile request
*
@@ -1901,6 +1963,19 @@ uint32_t
IedConnection_getFile(IedConnection self, IedClientError* error, const char* fileName, IedClientGetFileHandler handler,
void* handlerParameter);
+/**
+ * \brief Set the virtual filestore basepath for the setFile service
+ *
+ * All external file service accesses will be mapped to paths relative to the base directory.
+ * NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
+ * option in stack_config.h is set.
+ *
+ * \param self the connection object
+ * \param basepath the new virtual filestore basepath
+ */
+void
+IedConnection_setFilestoreBasepath(IedConnection, const char* basepath);
+
/**
* \brief Implementation of the SetFile ACSI service
*
diff --git a/src/iec61850/inc/iec61850_common.h b/src/iec61850/inc/iec61850_common.h
index 47131c43..a48e8eda 100644
--- a/src/iec61850/inc/iec61850_common.h
+++ b/src/iec61850/inc/iec61850_common.h
@@ -406,6 +406,15 @@ Timestamp_setTimeInMilliseconds(Timestamp* self, uint64_t millisSinceEpoch);
void
Timestamp_setByMmsUtcTime(Timestamp* self, MmsValue* mmsValue);
+/**
+ * \brief Set an MmsValue instance of type UTCTime to the timestamp value
+ *
+ * \param self the Timestamp instance
+ * \param mmsValue the mmsValue instance, if NULL a new instance will be created
+ */
+MmsValue*
+Timestamp_toMmsValue(Timestamp* self, MmsValue* mmsValue);
+
/**
* \brief Get the version of the library as string
*
diff --git a/src/iec61850/inc/iec61850_model.h b/src/iec61850/inc/iec61850_model.h
index 9dad53c2..d4fbcb76 100644
--- a/src/iec61850/inc/iec61850_model.h
+++ b/src/iec61850/inc/iec61850_model.h
@@ -151,7 +151,8 @@ typedef enum {
GENERIC_BITSTRING = 26,
CONSTRUCTED = 27,
ENTRY_TIME = 28,
- PHYCOMADDR = 29
+ PHYCOMADDR = 29,
+ CURRENCY = 30
#endif
} DataAttributeType;
@@ -388,7 +389,11 @@ char*
ModelNode_getObjectReference(ModelNode* self, char* objectReference);
/**
+ * \brief Get the type of the ModelNode
*
+ * \param self the ModelNode instance
+ *
+ * \return the type of the ModelNode (one of LD, LN, DO, DA)
*/
ModelNodeType
ModelNode_getType(ModelNode* self);
@@ -412,13 +417,13 @@ IedModel_setIedName(IedModel* self, const char* iedName);
* as it happens to appear on the wire. E.g. if IED name in SCL file would be "IED1"
* and the logical device "WD1" the resulting LD name would be "IED1WD".
*
- * \param model the IedModel instance that holds the model node
+ * \param self the IedModel instance that holds the model node
* \param objectReference the IEC 61850 object reference
*
* \return the model node instance or NULL if model node does not exist.
*/
ModelNode*
-IedModel_getModelNodeByObjectReference(IedModel* model, const char* objectReference);
+IedModel_getModelNodeByObjectReference(IedModel* self, const char* objectReference);
SVControlBlock*
IedModel_getSVControlBlock(IedModel* self, LogicalNode* parentLN, const char* svcbName);
@@ -430,13 +435,13 @@ IedModel_getSVControlBlock(IedModel* self, LogicalNode* parentLN, const char* sv
* IED name as part of the logical device name. This function is useful for
* devices where the IED name can be configured.
*
- * \param model the IedModel instance that holds the model node
+ * \param self the IedModel instance that holds the model node
* \param objectReference the IEC 61850 object reference
*
* \return the model node instance or NULL if model node does not exist.
*/
ModelNode*
-IedModel_getModelNodeByShortObjectReference(IedModel* model, const char* objectReference);
+IedModel_getModelNodeByShortObjectReference(IedModel* self, const char* objectReference);
/**
* \brief Lookup a model node by its short address
@@ -444,13 +449,25 @@ IedModel_getModelNodeByShortObjectReference(IedModel* model, const char* objectR
* Short address is a 32 bit unsigned integer as specified in the "sAddr" attribute of
* the ICD file or in the configuration file.
*
- * \param model the IedModel instance that holds the model node
+ * \param self the IedModel instance that holds the model node
* \param shortAddress
*
* \return the model node instance or NULL if model node does not exist.
*/
ModelNode*
-IedModel_getModelNodeByShortAddress(IedModel* model, uint32_t shortAddress);
+IedModel_getModelNodeByShortAddress(IedModel* self, uint32_t shortAddress);
+
+/**
+ * \brief Lookup logical device (LD) by device instance name (SCL attribute "inst")
+ *
+ * \param self IedModel instance
+ * \param ldInst the logical device instance name (SCL attribute "inst")
+ *
+ * \return The matching LogicalDevice instance
+ */
+LogicalDevice*
+IedModel_getDeviceByInst(IedModel* self, const char* ldInst);
+
/**
* \brief Lookup a logical node by name that is part of the given logical device
@@ -461,7 +478,7 @@ IedModel_getModelNodeByShortAddress(IedModel* model, uint32_t shortAddress);
* \return the logical device instance or NULL if it does not exist
*/
LogicalNode*
-LogicalDevice_getLogicalNode(LogicalDevice* device, const char* lnName);
+LogicalDevice_getLogicalNode(LogicalDevice* self, const char* lnName);
/**
* \brief Get the setting group control block (SGCB) of the logical device
@@ -471,7 +488,7 @@ LogicalDevice_getLogicalNode(LogicalDevice* device, const char* lnName);
* \return the SGCB instance or NULL if no SGCB is available
*/
SettingGroupControlBlock*
-LogicalDevice_getSettingGroupControlBlock(LogicalDevice* device);
+LogicalDevice_getSettingGroupControlBlock(LogicalDevice* self);
/**@}*/
@@ -481,37 +498,69 @@ LogicalDevice_getSettingGroupControlBlock(LogicalDevice* device);
/**
* \brief unset all MmsValue references in the data model
*
- * \param model the IedModel instance that holds the model node
+ * \param self the IedModel instance that holds the model node
*/
void
-IedModel_setAttributeValuesToNull(IedModel* iedModel);
+IedModel_setAttributeValuesToNull(IedModel* self);
+/**
+ * \brief Lookup logical device (LD) by device name
+ *
+ * \param self IedModel instance
+ * \param ldInst the logical device name (as it is seen from the protocol side - MMS domain name)
+ *
+ * \return The matching LogicalDevice instance
+ */
LogicalDevice*
-IedModel_getDevice(IedModel* model, const char* deviceName);
+IedModel_getDevice(IedModel* self, const char* ldName);
-/*
- * \param dataSetReference MMS mapping object reference! e.g. ied1Inverter/LLN0$dataset1
+/**
+ * \brief Lookup a data set in the IED model
+ *
+ * \param self IedModel instance
+ * \param dataSetReference MMS mapping object reference! e.g. ied1Inverter/LLN0$dataset1
+ *
+ * \return The matching DataSet instance
*/
DataSet*
-IedModel_lookupDataSet(IedModel* model, const char* dataSetReference);
+IedModel_lookupDataSet(IedModel* self, const char* dataSetReference);
+
+/**
+ * \brief Lookup a DataAttribute instance with the corresponding MmsValue instance
+ *
+ * \param self IedModel instance
+ * \param value the MmsValue instance (from the MMS value cache)
+ *
+ * \return the matching DataAttribute instance
+ */
+DataAttribute*
+IedModel_lookupDataAttributeByMmsValue(IedModel* self, MmsValue* value);
+
+/**
+ * \brief Get the number of logical devices
+ *
+ * \param self IedModel instance
+ *
+ * \return the number of logical devices
+ */
int
-IedModel_getLogicalDeviceCount(IedModel* iedModel);
+IedModel_getLogicalDeviceCount(IedModel* self);
int
-LogicalDevice_getLogicalNodeCount(LogicalDevice* logicalDevice);
+LogicalDevice_getLogicalNodeCount(LogicalDevice* self);
ModelNode*
-LogicalDevice_getChildByMmsVariableName(LogicalDevice* logicalDevice, const char* mmsVariableName);
+LogicalDevice_getChildByMmsVariableName(LogicalDevice* self, const char* mmsVariableName);
bool
-LogicalNode_hasFCData(LogicalNode* node, FunctionalConstraint fc);
+LogicalNode_hasFCData(LogicalNode* self, FunctionalConstraint fc);
bool
-LogicalNode_hasBufferedReports(LogicalNode* node);
+LogicalNode_hasBufferedReports(LogicalNode* self);
bool
-LogicalNode_hasUnbufferedReports(LogicalNode* node);
+LogicalNode_hasUnbufferedReports(LogicalNode* self);
/**
* \brief get a data set instance
@@ -525,10 +574,8 @@ DataSet*
LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName);
bool
-DataObject_hasFCData(DataObject* dataObject, FunctionalConstraint fc);
+DataObject_hasFCData(DataObject* self, FunctionalConstraint fc);
-DataAttribute*
-IedModel_lookupDataAttributeByMmsValue(IedModel* model, MmsValue* value);
#ifdef __cplusplus
}
diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h
index 338f76bf..8b08e149 100644
--- a/src/iec61850/inc/iec61850_server.h
+++ b/src/iec61850/inc/iec61850_server.h
@@ -76,6 +76,28 @@ IedServer_create(IedModel* iedModel);
void
IedServer_destroy(IedServer self);
+/**
+ * \brief Set the local IP address to listen on
+ *
+ * \param self the IedServer instance
+ * \param localIpAddress the local IP address as C string (an internal copy will be created)
+ */
+void
+IedServer_setLocalIpAddress(IedServer self, const char* localIpAddress);
+
+/**
+ * \brief Set the virtual filestore basepath for the MMS file services
+ *
+ * All external file service accesses will be mapped to paths relative to the base directory.
+ * NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
+ * option in stack_config.h is set.
+ *
+ * \param self the IedServer instance
+ * \param basepath the new virtual filestore basepath
+ */
+void
+IedServer_setFilestoreBasepath(IedServer self, const char* basepath);
+
/**
* \brief Start handling client connections
*
@@ -106,6 +128,19 @@ IedServer_stop(IedServer self);
void
IedServer_startThreadless(IedServer self, int tcpPort);
+/**
+ * \brief Wait until a server connection is ready (with timeout)
+ *
+ * The function will wait until a server connection is ready (data available) or the
+ * timeout elapsed. This function is intended for the non-threaded mode. Its use is optional.
+ * It is equivalent of using select on sockets on Linux. If the return value is != 0 the
+ * IedServer_processIncomingData function should be called.
+ *
+ * \param self the IedServer instance
+ * \param timeoutMs the timeout to wait when no connection is ready
+ *
+ * \return 0 if no connection is ready; otherwise at least one connection is ready
+ */
int
IedServer_waitReady(IedServer self, unsigned int timeoutMs);
@@ -525,6 +560,21 @@ IedServer_updateFloatAttributeValue(IedServer self, DataAttribute* dataAttribute
void
IedServer_updateInt32AttributeValue(IedServer self, DataAttribute* dataAttribute, int32_t value);
+/**
+ * \brief Update the value of an IEC 61850 Dbpos (double point/position) data attribute.
+ *
+ * Update the value of a integer data attribute without handling with MmsValue instances.
+ *
+ * This function will also check if a trigger condition is satisfied in the case when a report or GOOSE
+ * control block is enabled.
+ *
+ * \param self the instance of IedServer to operate on.
+ * \param dataAttribute the data attribute handle
+ * \param value the new Dbpos value of the data attribute.
+ */
+void
+IedServer_udpateDbposValue(IedServer self, DataAttribute* dataAttribute, Dbpos value);
+
/**
* \brief Update the value of an IEC 61850 integer64 data attribute (like BCR actVal)
*
@@ -785,7 +835,8 @@ typedef enum {
CONTROL_HARDWARE_FAULT = 1, /** check failed due to hardware fault */
CONTROL_TEMPORARILY_UNAVAILABLE = 2, /** control is already selected or operated */
CONTROL_OBJECT_ACCESS_DENIED = 3, /** check failed due to access control reason - access denied for this client or state */
- CONTROL_OBJECT_UNDEFINED = 4 /** object not visible in this security context ??? */
+ CONTROL_OBJECT_UNDEFINED = 4, /** object not visible in this security context ??? */
+ CONTROL_VALUE_INVALID = 11 /** ctlVal out of range */
} CheckHandlerResult;
/**
diff --git a/src/iec61850/inc_private/ied_server_private.h b/src/iec61850/inc_private/ied_server_private.h
index df140828..a9e5d9f3 100644
--- a/src/iec61850/inc_private/ied_server_private.h
+++ b/src/iec61850/inc_private/ied_server_private.h
@@ -39,6 +39,7 @@ struct sIedServer
MmsDevice* mmsDevice;
MmsServer mmsServer;
IsoServer isoServer;
+ char* localIpAddress;
MmsMapping* mmsMapping;
LinkedList clientConnections;
uint8_t writeAccessPolicies;
diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c
index eb20a5dd..60778bb2 100644
--- a/src/iec61850/server/impl/ied_server.c
+++ b/src/iec61850/server/impl/ied_server.c
@@ -405,6 +405,7 @@ IedServer_create(IedModel* iedModel)
self->model = iedModel;
// self->running = false; /* not required due to CALLOC */
+ // self->localIpAddress = NULL; /* not required due to CALLOC */
#if (CONFIG_MMS_THREADLESS_STACK != 1)
self->dataModelLock = Semaphore_create(1);
@@ -464,6 +465,9 @@ IedServer_destroy(IedServer self)
MmsServer_destroy(self->mmsServer);
IsoServer_destroy(self->isoServer);
+ if (self->localIpAddress != NULL)
+ GLOBAL_FREEMEM(self->localIpAddress);
+
#if ((CONFIG_MMS_SINGLE_THREADED == 1) && (CONFIG_MMS_THREADLESS_STACK == 0))
/* trigger stopping background task thread */
@@ -600,6 +604,23 @@ IedServer_stop(IedServer self)
}
#endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */
+void
+IedServer_setFilestoreBasepath(IedServer self, const char* basepath)
+{
+ /* simply pass to MMS server API */
+ MmsServer_setFilestoreBasepath(self->mmsServer, basepath);
+}
+
+void
+IedServer_setLocalIpAddress(IedServer self, const char* localIpAddress)
+{
+ if (self->localIpAddress != NULL)
+ GLOBAL_FREEMEM(self->localIpAddress);
+
+ self->localIpAddress = StringUtils_copyString(localIpAddress);
+ IsoServer_setLocalIpAddress(self->isoServer, self->localIpAddress);
+}
+
void
IedServer_startThreadless(IedServer self, int tcpPort)
@@ -964,6 +985,27 @@ IedServer_updateInt32AttributeValue(IedServer self, DataAttribute* dataAttribute
}
}
+void
+IedServer_udpateDbposValue(IedServer self, DataAttribute* dataAttribute, Dbpos value)
+{
+ Dbpos currentValue = Dbpos_fromMmsValue(dataAttribute->mmsValue);
+
+ if (currentValue == value) {
+ checkForUpdateTrigger(self, dataAttribute);
+ }
+ else {
+#if (CONFIG_MMS_THREADLESS_STACK != 1)
+ Semaphore_wait(self->dataModelLock);
+#endif
+ Dbpos_toMmsValue(dataAttribute->mmsValue, value);
+#if (CONFIG_MMS_THREADLESS_STACK != 1)
+ Semaphore_post(self->dataModelLock);
+#endif
+
+ checkForChangedTriggers(self, dataAttribute);
+ }
+}
+
void
IedServer_updateInt64AttributeValue(IedServer self, DataAttribute* dataAttribute, int64_t value)
{
@@ -1253,8 +1295,13 @@ IedServer_setWriteAccessPolicy(IedServer self, FunctionalConstraint fc, AccessPo
void
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)
{
- if (dataAttribute == NULL)
- *((int*) NULL) = 1;
+ if (dataAttribute == NULL) {
+ if (DEBUG_IED_SERVER)
+ printf("IED_SERVER: IedServer_handleWriteAccess - dataAttribute == NULL!\n");
+
+ /* Cause a trap */
+ *((volatile int*) NULL) = 1;
+ }
MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler, parameter);
}
diff --git a/src/iec61850/server/mms_mapping/control.c b/src/iec61850/server/mms_mapping/control.c
index 3759211c..71b3e5ac 100644
--- a/src/iec61850/server/mms_mapping/control.c
+++ b/src/iec61850/server/mms_mapping/control.c
@@ -1211,27 +1211,6 @@ checkValidityOfOriginParameter(MmsValue* origin)
return true;
}
-static MmsDataAccessError
-getDataAccessErrorFromCheckHandlerResult(CheckHandlerResult checkResult)
-{
- MmsDataAccessError indication;
-
- if (checkResult == CONTROL_HARDWARE_FAULT)
- indication = DATA_ACCESS_ERROR_HARDWARE_FAULT;
- else
- if (checkResult == CONTROL_TEMPORARILY_UNAVAILABLE)
- indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
- else
- if (checkResult == CONTROL_OBJECT_UNDEFINED)
- indication = DATA_ACCESS_ERROR_OBJECT_UNDEFINED;
- else if (checkResult == CONTROL_OBJECT_ACCESS_DENIED)
- indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
- else
- indication = DATA_ACCESS_ERROR_SUCCESS;
-
- return indication;
-}
-
MmsDataAccessError
Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
MmsValue* value, MmsServerConnection connection)
@@ -1378,7 +1357,7 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
printf("SBOw: selected successful\n");
}
else {
- indication = getDataAccessErrorFromCheckHandlerResult(checkResult);
+ indication = (MmsDataAccessError) checkResult;
ControlObject_sendLastApplError(controlObject, connection, "SBOw", 0,
ADD_CAUSE_SELECT_FAILED, ctlNum, origin, true);
@@ -1523,7 +1502,7 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
}
else {
- indication = getDataAccessErrorFromCheckHandlerResult(checkResult);
+ indication = (MmsDataAccessError) checkResult;
abortControlOperation(controlObject);
}
diff --git a/src/iec61850/server/mms_mapping/logging.c b/src/iec61850/server/mms_mapping/logging.c
index 4733f14d..2a59c43f 100644
--- a/src/iec61850/server/mms_mapping/logging.c
+++ b/src/iec61850/server/mms_mapping/logging.c
@@ -882,7 +882,7 @@ Logging_processIntegrityLogs(MmsMapping* self, uint64_t currentTimeInMs)
if (currentTimeInMs >= logControl->nextIntegrityScan) {
- //if (DEBUG_IED_SERVER)
+ if (DEBUG_IED_SERVER)
printf("IED_SERVER: INTEGRITY SCAN for log %s\n", logControl->name);
LogControl_logAllDatasetEntries(logControl, self->mmsDevice->deviceName);
diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c
index 7e9e5d9c..b3dab218 100644
--- a/src/iec61850/server/mms_mapping/mms_mapping.c
+++ b/src/iec61850/server/mms_mapping/mms_mapping.c
@@ -1993,12 +1993,16 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
FunctionalConstraint fc = getFunctionalConstraintForWritableNode(self, separator);
#if (CONFIG_IEC61850_SETTING_GROUPS == 1)
- if (fc == IEC61850_FC_SE) {
- SettingGroup* sg = getSettingGroupByMmsDomain(self, domain);
+ if (fc == IEC61850_FC_SE) {
+ SettingGroup* sg = getSettingGroupByMmsDomain(self, domain);
- if (sg->editingClient != (ClientConnection) connection)
- return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
- }
+ if (sg != NULL) {
+ if (sg->editingClient != (ClientConnection) connection)
+ return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
+ }
+ else
+ return DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT;
+ }
#endif /* (CONFIG_IEC61850_SETTING_GROUPS == 1) */
/* writable data model elements - SP, SV, CF, DC */
@@ -2032,7 +2036,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
}
#endif
- /* Call writer access handlers */
+ /* Call write access handlers */
LinkedList writeHandlerListElement = LinkedList_getNext(self->attributeAccessHandlers);
while (writeHandlerListElement != NULL) {
diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c
index 03a00928..6c709b95 100644
--- a/src/iec61850/server/model/model.c
+++ b/src/iec61850/server/model/model.c
@@ -93,9 +93,9 @@ IedModel_getLogicalDeviceCount(IedModel* iedModel)
}
DataSet*
-IedModel_lookupDataSet(IedModel* model, const char* dataSetReference /* e.g. ied1Inverter/LLN0$dataset1 */)
+IedModel_lookupDataSet(IedModel* self, const char* dataSetReference /* e.g. ied1Inverter/LLN0$dataset1 */)
{
- DataSet* dataSet = model->dataSets;
+ DataSet* dataSet = self->dataSets;
const char* separator = strchr(dataSetReference, '/');
@@ -106,9 +106,9 @@ IedModel_lookupDataSet(IedModel* model, const char* dataSetReference /* e.g. ie
char domainName[65];
- int modelNameLen = strlen(model->name);
+ int modelNameLen = strlen(self->name);
- memcpy(domainName, model->name, modelNameLen);
+ memcpy(domainName, self->name, modelNameLen);
while (dataSet != NULL) {
@@ -129,15 +129,15 @@ IedModel_lookupDataSet(IedModel* model, const char* dataSetReference /* e.g. ie
}
LogicalDevice*
-IedModel_getDevice(IedModel* model, const char* deviceName)
+IedModel_getDevice(IedModel* self, const char* deviceName)
{
- LogicalDevice* device = model->firstChild;
+ LogicalDevice* device = self->firstChild;
while (device != NULL) {
char domainName[65];
- strncpy(domainName, model->name, 64);
+ strncpy(domainName, self->name, 64);
strncat(domainName, device->name, 64);
if (strcmp(domainName, deviceName) == 0)
@@ -149,6 +149,22 @@ IedModel_getDevice(IedModel* model, const char* deviceName)
return NULL;
}
+LogicalDevice*
+IedModel_getDeviceByInst(IedModel* self, const char* ldInst)
+{
+ LogicalDevice* device = self->firstChild;
+
+ while (device != NULL) {
+
+ if (strcmp(device->name, ldInst) == 0)
+ return device;
+
+ device = (LogicalDevice*) device->sibling;
+ }
+
+ return NULL;
+}
+
static DataAttribute*
ModelNode_getDataAttributeByMmsValue(ModelNode* self, MmsValue* value)
{
diff --git a/src/mms/asn1/ber_decode.c b/src/mms/asn1/ber_decode.c
index 7eca9308..32be3975 100644
--- a/src/mms/asn1/ber_decode.c
+++ b/src/mms/asn1/ber_decode.c
@@ -56,6 +56,12 @@ BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos)
*length = len1;
}
+ if (*length < 0)
+ return -1;
+
+ if (bufPos + (*length) > maxBufPos)
+ return -1;
+
return bufPos;
}
@@ -70,10 +76,32 @@ BerDecoder_decodeString(uint8_t* buffer, int strlen, int bufPos, int maxBufPos)
}
uint32_t
-BerDecoder_decodeUint32(uint8_t* buffer, int intlen, int bufPos) {
+BerDecoder_decodeUint32(uint8_t* buffer, int intLen, int bufPos)
+{
uint32_t value = 0;
int i;
+ for (i = 0; i < intLen; i++) {
+ value <<= 8;
+ value += buffer[bufPos + i];
+ }
+
+ return value;
+}
+
+int32_t
+BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos)
+{
+ int32_t value;
+ int i;
+
+ bool isNegative = ((buffer[bufPos] & 0x80) == 0x80);
+
+ if (isNegative)
+ value = -1;
+ else
+ value = 0;
+
for (i = 0; i < intlen; i++) {
value <<= 8;
value += buffer[bufPos + i];
@@ -135,3 +163,38 @@ BerDecoder_decodeBoolean(uint8_t* buffer, int bufPos) {
else
return false;
}
+
+void
+BerDecoder_decodeOID(uint8_t* buffer, int bufPos, int length, ItuObjectIdentifier* oid)
+{
+ int startPos = bufPos;
+ int currentArc = 0;
+
+ /* clear all arcs */
+ int i;
+ for (i = 0; i < 10; i++)
+ oid->arc[i] = 0;
+
+ /* parse first two arcs */
+ if (length > 0) {
+ oid->arc[0] = buffer[bufPos] / 40;
+ oid->arc[1] = buffer[bufPos] % 40;
+
+ currentArc = 2;
+ bufPos++;
+ }
+
+ /* parse remaining arcs */
+ while ((bufPos - startPos < length) && (currentArc < 10)) {
+ oid->arc[currentArc] = oid->arc[currentArc]<<7;
+
+ if (buffer[bufPos] < 0x80)
+ oid->arc[currentArc++] += buffer[bufPos];
+ else
+ oid->arc[currentArc] += (buffer[bufPos] & 0x7f);
+
+ bufPos++;
+ }
+
+ oid->arcCount = currentArc;
+}
diff --git a/src/mms/asn1/ber_encoder.c b/src/mms/asn1/ber_encoder.c
index 35953c66..2417c1fa 100644
--- a/src/mms/asn1/ber_encoder.c
+++ b/src/mms/asn1/ber_encoder.c
@@ -34,12 +34,19 @@ BerEncoder_encodeLength(uint32_t length, uint8_t* buffer, int bufPos)
buffer[bufPos++] = 0x81;
buffer[bufPos++] = (uint8_t) length;
}
- else {
+ else if (length < 65535) {
buffer[bufPos++] = 0x82;
buffer[bufPos++] = length / 256;
buffer[bufPos++] = length % 256;
}
+ else {
+ buffer[bufPos++] = 0x83;
+
+ buffer[bufPos++] = length / 0x10000;
+ buffer[bufPos++] = (length & 0xffff) / 0x100;
+ buffer[bufPos++] = length % 256;
+ }
return bufPos;
}
@@ -250,6 +257,33 @@ BerEncoder_encodeUInt32(uint32_t value, uint8_t* buffer, int bufPos)
return bufPos;
}
+int
+BerEncoder_encodeInt32(int32_t value, uint8_t* buffer, int bufPos)
+{
+ uint8_t* valueArray = (uint8_t*) &value;
+ uint8_t valueBuffer[4];
+
+ int i;
+
+#if (ORDER_LITTLE_ENDIAN == 1)
+ for (i = 0; i < 4; i++) {
+ valueBuffer[3 - i] = valueArray[i];
+ }
+#else
+ for (i = 0; i < 4; i++) {
+ valueBuffer[i] = valueArray[i];
+ }
+#endif
+
+ int size = BerEncoder_compressInteger(valueBuffer, 4);
+
+ for (i = 0; i < size; i++) {
+ buffer[bufPos++] = valueBuffer[i];
+ }
+
+ return bufPos;
+}
+
int
BerEncoder_encodeUInt32WithTL(uint8_t tag, uint32_t value, uint8_t* buffer, int bufPos)
{
@@ -335,8 +369,10 @@ BerEncoder_determineLengthSize(uint32_t length)
return 1;
if (length < 256)
return 2;
- else
+ if (length < 65536)
return 3;
+ else
+ return 4;
}
int
diff --git a/src/mms/inc/iso_connection_parameters.h b/src/mms/inc/iso_connection_parameters.h
index b966491c..6ab22704 100644
--- a/src/mms/inc/iso_connection_parameters.h
+++ b/src/mms/inc/iso_connection_parameters.h
@@ -34,22 +34,19 @@ extern "C" {
/**@{*/
+/**
+ * \brief authentication mechanism úsed by AcseAuthenticator
+ */
typedef enum
{
ACSE_AUTH_NONE = 0,
- ACSE_AUTH_PASSWORD = 1
-} AcseAuthenticationMechanism;
+ ACSE_AUTH_PASSWORD = 1,
+ ACSE_AUTH_CERTIFICATE = 2,
+ /** Use TLS certificate for client authentication */
+ ACSE_AUTH_TLS = 3
+} AcseAuthenticationMechanism;
-/* --> for compatibility with older versions (libiec61850 < 0.7.7) */
-#ifndef AUTH_NONE
-#define AUTH_NONE ACSE_AUTH_NONE
-#endif
-
-#ifndef AUTH_PASSWORD
-#define AUTH_PASSWORD ACSE_AUTH_PASSWORD
-#endif
-/* <-- for compatibility with older versions (libiec61850 < 0.7.7) */
typedef struct sAcseAuthenticationParameter* AcseAuthenticationParameter;
@@ -63,6 +60,13 @@ struct sAcseAuthenticationParameter
uint8_t* octetString;
int passwordLength;
} password;
+
+ struct
+ {
+ uint8_t* buf;
+ int length;
+ } certificate;
+
} value;
};
@@ -85,11 +89,12 @@ AcseAuthenticationParameter_setPassword(AcseAuthenticationParameter self, char*
* \param parameter user provided parameter - set when user registers the authenticator
* \param authParameter the authentication parameters provided by the client
* \param securityToken pointer where to store an application specific security token - can be ignored if not used.
+ * \param appReference ISO application reference (ap-title + ae-qualifier)
*
* \return true if client connection is accepted, false otherwise
*/
typedef bool
-(*AcseAuthenticator)(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken);
+(*AcseAuthenticator)(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken, IsoApplicationReference* appReference);
/**
* \brief COTP T selector
diff --git a/src/mms/inc/mms_client_connection.h b/src/mms/inc/mms_client_connection.h
index 972f0fe5..b0a08084 100644
--- a/src/mms/inc/mms_client_connection.h
+++ b/src/mms/inc/mms_client_connection.h
@@ -106,6 +106,19 @@ typedef void (*MmsRawMessageHandler) (void* parameter, uint8_t* message, int mes
void
MmsConnection_setRawMessageHandler(MmsConnection self, MmsRawMessageHandler handler, void* parameter);
+/**
+ * \brief Set the virtual filestore basepath for the MMS obtain file services
+ *
+ * All external file service accesses will be mapped to paths relative to the base directory.
+ * NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
+ * option in stack_config.h is set.
+ *
+ * \param self the MmsServer instance
+ * \param basepath the new virtual filestore basepath
+ */
+void
+MmsConnection_setFilestoreBasepath(MmsConnection self, const char* basepath);
+
/**
* \brief Set the request timeout in ms for this connection
*
@@ -293,13 +306,13 @@ LinkedList /* */
MmsConnection_getDomainVariableNames(MmsConnection self, MmsError* mmsError, const char* domainId);
/**
- * \brief Get the names of all named variable lists present in a MMS domain of the server.
+ * \brief Get the names of all named variable lists present in a MMS domain or VMD scope of the server.
*
* This will result in a domain specific GetNameList request.
*
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
- * \param domainId the domain name for the domain specific request
+ * \param domainId the domain name for the domain specific request or NULL for a VMD scope request
*
* \return the domain specific named variable list names or NULL if the request failed.
*/
@@ -386,20 +399,47 @@ MmsConnection_readMultipleVariables(MmsConnection self, MmsError* mmsError, cons
/**
* \brief Write a single variable to the server.
*
+ * NOTE: added return value in version 1.1
+ *
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
* \param domainId the domain name of the variable to be written
* \param itemId name of the variable to be written
* \param value value of the variable to be written
+ *
+ * \return when successful, the data access error value returned by the server
*/
-void
+MmsDataAccessError
MmsConnection_writeVariable(MmsConnection self, MmsError* mmsError,
const char* domainId, const char* itemId, MmsValue* value);
+/**
+ * \brief Write a single array element or a sub array to an array type variable
+ *
+ * When a single array element is address the MmsValue object value has to be of the type
+ * of the array elements. When multiple array elements have to be written (index range) the
+ * MmsValue object value has to be of type MMS_ARRAY containing "numberOfElements" elements.
+ *
+ * \param self MmsConnection instance to operate on
+ * \param mmsError user provided variable to store error code
+ * \param domainId the domain name of the variable to be written
+ * \param index the index of the array element or the start index of a index range
+ * \param numberOfElements the number of array elements to write starting with index. If 0 only one array element is written.
+ * \param itemId name of the variable to be written
+ * \param value value of the array element(s) to be written. Has to be of the type of
+ * the array elements or of type MMS_ARRAY when it is a sub array (index range)
+ *
+ * \return when successful, the data access error value returned by the server
+ */
+MmsDataAccessError
+MmsConnection_writeArrayElements(MmsConnection self, MmsError* mmsError,
+ const char* domainId, const char* itemId, int index, int numberOfElements,
+ MmsValue* value);
+
/**
* \brief Write multiple variables to the server.
*
- * This function will write multiple variables at the server.
+ * This function will write multiple variables to the server.
*
* The parameter accessResults is a pointer to a LinkedList reference. The methods will create a new LinkedList
* object that contains the AccessResults of the single variable write attempts. It is up to the user to free this
@@ -418,12 +458,33 @@ MmsConnection_writeMultipleVariables(MmsConnection self, MmsError* mmsError, con
LinkedList /**/ items, LinkedList /* */ values,
LinkedList* /* */ accessResults);
+/**
+ * \brief Write named variable list values to the server.
+ *
+ * The parameter accessResults is a pointer to a LinkedList reference. The methods will create a new LinkedList
+ * object that contains the AccessResults of the single variable write attempts. It is in the responsibility of
+ * the user to free this objects properly (e.g. with LinkedList_destroyDeep(accessResults, MmsValue_delete)).
+ * If accessResult is the to NULL the result will not be stored.
+ *
+ * \param self MmsConnection instance to operate on
+ * \param mmsError user provided variable to store error code
+ * \param isAssociationSpecifc true if the named variable list is an association specific named variable list
+ * \param domainId the common domain name of all variables to be written
+ * \param values values of the variables to be written
+ * \param (OUTPUT) the MmsValue objects of type MMS_DATA_ACCESS_ERROR representing the write success of a single variable
+ * write.
+ */
+void
+MmsConnection_writeNamedVariableList(MmsConnection self, MmsError* mmsError, bool isAssociationSpecific,
+ const char* domainId, const char* itemId, LinkedList /* */values,
+ /* OUTPUT */LinkedList* /* */accessResults);
+
/**
* \brief Get the variable access attributes of a MMS named variable of the server
*
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
- * \param domainId the domain name of the variable
+ * \param domainId the domain name of the variable or NULL for a VMD specific request
* \param itemId name of the variable
*
* \return Returns a MmsTypeSpecification object or NULL if the request failed.
diff --git a/src/mms/inc/mms_common.h b/src/mms/inc/mms_common.h
index c1a8169e..0c3832e5 100644
--- a/src/mms/inc/mms_common.h
+++ b/src/mms/inc/mms_common.h
@@ -46,6 +46,7 @@ typedef enum
MMS_ERROR_HARDWARE_FAULT = 5,
MMS_ERROR_CONCLUDE_REJECTED = 6,
MMS_ERROR_INVALID_ARGUMENTS = 7,
+ MMS_ERROR_OUTSTANDING_CALL_LIMIT = 8,
MMS_ERROR_OTHER = 9,
@@ -154,6 +155,17 @@ typedef struct
typedef struct sMmsNamedVariableList* MmsNamedVariableList;
typedef struct sMmsAccessSpecifier* MmsNamedVariableListEntry;
+
+typedef struct {
+ uint16_t arc[10];
+ int arcCount;
+} ItuObjectIdentifier;
+
+typedef struct {
+ ItuObjectIdentifier apTitle;
+ int aeQualifier;
+} IsoApplicationReference;
+
/**@}*/
diff --git a/src/mms/inc/mms_server.h b/src/mms/inc/mms_server.h
index 7aa4d673..23d128d4 100644
--- a/src/mms/inc/mms_server.h
+++ b/src/mms/inc/mms_server.h
@@ -164,13 +164,61 @@ typedef void (*MmsGetFileCompleteHandler)(void* parameter, MmsServerConnection c
* \brief Install callback handler that is invoked when the file upload (obtainFile service) is completed and the
* file has been uploaded.
*
- * \param self the MmsServer instance to operate on
+ * \param self the MmsServer instance
* \param handler the callback handler function
* \param parameter user provided parameter that is passed to the callback handler
*/
void
MmsServer_installGetFileCompleteHandler(MmsServer self, MmsGetFileCompleteHandler handler, void* parameter);
+
+typedef enum {
+ MMS_FILE_ACCESS_TYPE_READ_DIRECTORY,
+ MMS_FILE_ACCESS_TYPE_OPEN,
+ MMS_FILE_ACCESS_TYPE_OBTAIN,
+ MMS_FILE_ACCESS_TYPE_DELETE,
+ MMS_FILE_ACCESS_TYPE_RENAME
+} MmsFileServiceType;
+
+/**
+ * \brief MmsFileAccessHandler callback function. Use to monitor and control file access
+ *
+ * \param parameter user provided parameter that is passed to the callback handler
+ * \param connection the connection that requested the service
+ * \param service the requested file service
+ * \param localFilename the requested file or directory name at the server
+ * \param otherFilename a second file name parameter (e.g. source file of the ObtainFile or new file of rename file)
+ *
+ * \return MMS_ERROR_NONE when the request is accepted, otherwise use the appropriate error code (e.g. MMS_ERROR_FILE_FILE_ACCESS_DENIED)
+ */
+typedef MmsError (*MmsFileAccessHandler) (void* parameter, MmsServerConnection connection, MmsFileServiceType service,
+ const char* localFilename, const char* otherFilename);
+
+
+/**
+ * \brief Install a callback handler this is invoked when the client requests a file server. This function can be
+ * used to monitor and control file access
+ *
+ * \param self the MmsServer instance
+ * \param handler the callback handler function
+ * \param parameter user provided parameter that is passed to the callback handler
+ */
+void
+MmsServer_installFileAccessHandler(MmsServer self, MmsFileAccessHandler handler, void* parameter);
+
+/**
+ * \brief Set the virtual filestore basepath for the MMS file services
+ *
+ * All external file service accesses will be mapped to paths relative to the base directory.
+ * NOTE: This function is only available when the CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME
+ * option in stack_config.h is set.
+ *
+ * \param self the MmsServer instance
+ * \param basepath the new virtual filestore basepath
+ */
+void
+MmsServer_setFilestoreBasepath(MmsServer self, const char* basepath);
+
/**
* \brief lock the cached server data model
*
@@ -198,9 +246,6 @@ void
MmsServer_insertIntoCache(MmsServer self, MmsDomain* domain, char* itemId,
MmsValue* value);
-void
-MmsServer_setDevice(MmsServer self, MmsDevice* device);
-
/***************************************************
* Functions for multi-threaded operation mode
***************************************************/
@@ -391,6 +436,7 @@ MmsServerConnection_getClientAddress(MmsServerConnection self);
IsoConnection
MmsServerConnection_getIsoConnection(MmsServerConnection self);
+
/**@}*/
#ifdef __cplusplus
diff --git a/src/mms/inc/mms_type_spec.h b/src/mms/inc/mms_type_spec.h
index d9db23fb..20693584 100644
--- a/src/mms/inc/mms_type_spec.h
+++ b/src/mms/inc/mms_type_spec.h
@@ -91,6 +91,17 @@ MmsVariableSpecification_getNamedVariableRecursive(MmsVariableSpecification* sel
MmsType
MmsVariableSpecification_getType(MmsVariableSpecification* self);
+/**
+ * \brief Check if the value has exactly the same type as this variable specfication
+ *
+ * \param self the MmsVariableSpecification instance
+ * \param value the value to check
+ *
+ * \return true if type is matching, false otherwise
+ */
+bool
+MmsVariableSpecification_isValueOfType(MmsVariableSpecification* self, MmsValue* value);
+
/**
* \brief get the name of the variable
*
diff --git a/src/mms/inc/mms_value.h b/src/mms/inc/mms_value.h
index 61253fb6..71082009 100644
--- a/src/mms/inc/mms_value.h
+++ b/src/mms/inc/mms_value.h
@@ -953,14 +953,28 @@ MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize);
/**
* \brief create a new MmsValue instance from a BER encoded MMS Data element (deserialize)
*
+ * WARNING: API changed with version 1.0.3 (added endBufPos parameter)
+ *
+ * \param buffer the buffer to read from
+ * \param bufPos the start position of the mms value data in the buffer
+ * \param bufferLength the length of the buffer
+ * \param endBufPos the position in the buffer after the read MMS data element (NULL if not required)
+ *
+ * \return the MmsValue instance created from the buffer
*/
MmsValue*
-MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength);
+MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength, int* endBufPos);
/**
* \brief Serialize the MmsValue instance as BER encoded MMS Data element
*
* \param self the MmsValue instance
+ *
+ * \param buffer the buffer to encode the MMS data element
+ * \param bufPos the position in the buffer where to start encoding
+ * \param encode encode to buffer (true) or calculate length only (false)
+ *
+ * \return the encoded length of the corresponding MMS data element
*/
int
MmsValue_encodeMmsData(MmsValue* self, uint8_t* buffer, int bufPos, bool encode);
diff --git a/src/mms/inc_private/acse.h b/src/mms/inc_private/acse.h
index 42825087..9b36bd3c 100644
--- a/src/mms/inc_private/acse.h
+++ b/src/mms/inc_private/acse.h
@@ -54,6 +54,7 @@ typedef struct sAcseConnection
int userDataBufferSize;
AcseAuthenticationParameter authentication;
AcseAuthenticator authenticator;
+ IsoApplicationReference applicationReference;
void* authenticatorParameter;
void* securityToken;
} AcseConnection;
diff --git a/src/mms/inc_private/ber_decode.h b/src/mms/inc_private/ber_decode.h
index 258f6a21..56f3ed28 100644
--- a/src/mms/inc_private/ber_decode.h
+++ b/src/mms/inc_private/ber_decode.h
@@ -34,6 +34,9 @@ BerDecoder_decodeString(uint8_t* buffer, int strlen, int bufPos, int maxBufPos);
uint32_t
BerDecoder_decodeUint32(uint8_t* buffer, int intlen, int bufPos);
+int32_t
+BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos);
+
float
BerDecoder_decodeFloat(uint8_t* buffer, int bufPos);
@@ -43,4 +46,7 @@ BerDecoder_decodeDouble(uint8_t* buffer, int bufPos);
bool
BerDecoder_decodeBoolean(uint8_t* buffer, int bufPos);
+void
+BerDecoder_decodeOID(uint8_t* buffer, int bufPos, int length, ItuObjectIdentifier* oid);
+
#endif /* BER_DECODER_H_ */
diff --git a/src/mms/inc_private/ber_encoder.h b/src/mms/inc_private/ber_encoder.h
index 343f54f0..ff4b26d6 100644
--- a/src/mms/inc_private/ber_encoder.h
+++ b/src/mms/inc_private/ber_encoder.h
@@ -55,6 +55,9 @@ BerEncoder_encodeAsn1PrimitiveValue(uint8_t tag, Asn1PrimitiveValue* value, uint
int
BerEncoder_encodeUInt32(uint32_t value, uint8_t* buffer, int bufPos);
+int
+BerEncoder_encodeInt32(int32_t value, uint8_t* buffer, int bufPos);
+
int
BerEncoder_encodeUInt32WithTL(uint8_t tag, uint32_t value, uint8_t* buffer, int bufPos);
diff --git a/src/mms/inc_private/mms_client_internal.h b/src/mms/inc_private/mms_client_internal.h
index af992ad1..86253325 100644
--- a/src/mms/inc_private/mms_client_internal.h
+++ b/src/mms/inc_private/mms_client_internal.h
@@ -102,7 +102,12 @@ struct sMmsConnection {
#if (MMS_OBTAIN_FILE_SERVICE == 1)
int32_t nextFrsmId;
MmsFileReadStateMachine frsms[CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION];
+
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char* filestoreBasepath;
#endif
+
+#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
};
@@ -116,6 +121,9 @@ typedef enum {
MMS_OBJECT_CLASS_DOMAIN = 9
} MmsObjectClass;
+char*
+MmsConnection_getFilestoreBasepath(MmsConnection self);
+
MmsValue*
mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSize, bool createArray);
@@ -125,7 +133,7 @@ mmsClient_getInvokeId(ConfirmedResponsePdu_t* confirmedResponse);
int
mmsClient_write_out(void *buffer, size_t size, void *app_key);
-int
+void
mmsClient_createInitiateRequest(MmsConnection self, ByteBuffer* writeBuffer);
MmsPdu_t*
@@ -187,7 +195,7 @@ mmsClient_createGetVariableAccessAttributesRequest(
MmsVariableSpecification*
mmsClient_parseGetVariableAccessAttributesResponse(ByteBuffer* message, uint32_t* invokeId);
-void
+MmsDataAccessError
mmsClient_parseWriteResponse(ByteBuffer* message, int32_t bufPos, MmsError* mmsError);
void
@@ -202,6 +210,15 @@ int
mmsClient_createWriteMultipleItemsRequest(uint32_t invokeId, const char* domainId, LinkedList itemIds, LinkedList values,
ByteBuffer* writeBuffer);
+int
+mmsClient_createWriteRequestNamedVariableList(uint32_t invokeId, bool isAssociationSpecific, const char* domainId, const char* itemId,
+ LinkedList values, ByteBuffer* writeBuffer);
+
+int
+mmsClient_createWriteRequestArray(uint32_t invokeId, const char* domainId, const char* itemId,
+ int startIndex, int elementCount,
+ MmsValue* value, ByteBuffer* writeBuffer);
+
void
mmsClient_createDefineNamedVariableListRequest(uint32_t invokeId, ByteBuffer* writeBuffer,
const char* domainId, const char* listNameId, LinkedList /**/ listOfVariables,
diff --git a/src/mms/inc_private/mms_common_internal.h b/src/mms/inc_private/mms_common_internal.h
index 0c97dde1..6bb28486 100644
--- a/src/mms/inc_private/mms_common_internal.h
+++ b/src/mms/inc_private/mms_common_internal.h
@@ -28,6 +28,7 @@
#include "MmsPdu.h"
#include "conversions.h"
#include "byte_buffer.h"
+#include "mms_server.h"
#if (MMS_FILE_SERVICE == 1)
@@ -60,8 +61,16 @@ void
mmsMsg_createFileCloseResponse(uint32_t invokeId, ByteBuffer* response);
void
-mmsMsg_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm);
+mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm);
+bool
+mmsMsg_parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response);
+
+void
+mmsMsg_createExtendedFilename(const char* basepath, char* extendedFileName, char* fileName);
+
+FileHandle
+mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite);
#endif /* (MMS_FILE_SERVICE == 1) */
@@ -81,6 +90,8 @@ mmsMsg_createMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response);
int
mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, MmsServiceError* serviceError);
+int
+mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, int* rejectType, int* rejectReason);
MmsValue*
mmsMsg_parseDataElement(Data_t* dataElement);
diff --git a/src/mms/inc_private/mms_server_connection.h b/src/mms/inc_private/mms_server_connection.h
index 01901ec7..e65c78ac 100644
--- a/src/mms/inc_private/mms_server_connection.h
+++ b/src/mms/inc_private/mms_server_connection.h
@@ -101,6 +101,9 @@ MmsServerConnection_getLastInvokeId(MmsServerConnection self);
uint32_t
MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self);
+const char*
+MmsServerConnection_getFilesystemBasepath(MmsServerConnection self);
+
#endif /* MMS_SERVER_CONNECTION_H_ */
diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h
index a95579a8..6c8df614 100644
--- a/src/mms/inc_private/mms_server_internal.h
+++ b/src/mms/inc_private/mms_server_internal.h
@@ -156,6 +156,15 @@ struct sMmsServer {
struct sMmsObtainFileTask fileUploadTasks[CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS];
#endif
+#if (MMS_FILE_SERVICE == 1)
+ MmsFileAccessHandler fileAccessHandler;
+ void* fileAccessHandlerParameter;
+#endif
+
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char* filestoreBasepath;
+#endif
+
};
struct sMmsServerConnection {
@@ -271,7 +280,7 @@ mmsServer_handleWriteRequest(
void
mmsServer_handleIdentifyRequest(
MmsServerConnection connection,
- int invokeId,
+ uint32_t invokeId,
ByteBuffer* response);
void
@@ -279,7 +288,7 @@ mmsServer_handleStatusRequest(
MmsServerConnection connection,
uint8_t* requestBuffer,
int bufPos,
- int invokeId,
+ uint32_t invokeId,
ByteBuffer* response);
void
@@ -361,9 +370,9 @@ mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* va
MmsValue*
mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection);
-int
+void
mmsServer_createMmsWriteResponse(MmsServerConnection connection,
- int invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults);
+ uint32_t invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults);
void
mmsMsg_createMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response);
diff --git a/src/mms/iso_acse/acse.c b/src/mms/iso_acse/acse.c
index 67f0ad15..7b872dc4 100644
--- a/src/mms/iso_acse/acse.c
+++ b/src/mms/iso_acse/acse.c
@@ -69,7 +69,10 @@ authenticateClient(AcseConnection* self, AcseAuthenticationMechanism mechanism,
authParameter->value.password.passwordLength = authValueLen;
}
- return self->authenticator(self->authenticatorParameter, authParameter, &(self->securityToken));
+ //TODO Check if we are in a TLS connection: if mechanism == ACSE_AUTH_NONE provide client certificate if present
+ // --> mechanism = ACSE_AUTH_TLS
+
+ return self->authenticator(self->authenticatorParameter, authParameter, &(self->securityToken), &(self->applicationReference));
}
static bool
@@ -88,7 +91,6 @@ checkAuthentication(AcseConnection* self, uint8_t* authMechanism, int authMechLe
}
-
static int
parseUserInformation(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos, bool* userInfoValid)
{
@@ -242,10 +244,28 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
break;
case 0xa6: /* calling AP title */
- bufPos += len;
+ {
+ if (buffer[bufPos] == 0x06) { /* ap-title-form2 */
+
+ int innerLength = buffer[bufPos+1];
+
+ if (innerLength == len - 2)
+ BerDecoder_decodeOID(buffer, bufPos + 2, innerLength, &(self->applicationReference.apTitle));
+ }
+ }
+ bufPos += len;
break;
case 0xa7: /* calling AE qualifier */
+ {
+ if (buffer[bufPos] == 0x02) { /* ae-qualifier-form2 */
+
+ int innerLength = buffer[bufPos+1];
+
+ if (innerLength == len - 2)
+ self->applicationReference.aeQualifier = BerDecoder_decodeInt32(buffer + 2, buffer[bufPos+1], bufPos);
+ }
+ }
bufPos += len;
break;
@@ -316,6 +336,7 @@ AcseConnection_init(AcseConnection* self, AcseAuthenticator authenticator, void*
self->userDataBufferSize = 0;
self->authenticator= authenticator;
self->authenticatorParameter = parameter;
+ memset(&(self->applicationReference), 0, sizeof(self->applicationReference));
}
void
@@ -498,7 +519,7 @@ AcseConnection_createAssociateRequestMessage(AcseConnection* self,
calledAEQualifierLength = BerEncoder_UInt32determineEncodedSize(isoParameters->remoteAEQualifier);
- /* called AP qualifier */
+ /* called AE qualifier */
contentLength += (4 + calledAEQualifierLength);
}
@@ -510,7 +531,7 @@ AcseConnection_createAssociateRequestMessage(AcseConnection* self,
callingAEQualifierLength = BerEncoder_UInt32determineEncodedSize(isoParameters->localAEQualifier);
- /* calling AP qualifier */
+ /* calling AE qualifier */
contentLength += (4 + callingAEQualifierLength);
}
diff --git a/src/mms/iso_client/iso_client_connection.c b/src/mms/iso_client/iso_client_connection.c
index b68631b0..6f6d48f6 100644
--- a/src/mms/iso_client/iso_client_connection.c
+++ b/src/mms/iso_client/iso_client_connection.c
@@ -351,7 +351,6 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
goto returnError;
}
-
ByteBuffer_wrap(self->receivePayloadBuffer, self->acseConnection.userDataBuffer,
self->acseConnection.userDataBufferSize, self->acseConnection.userDataBufferSize);
diff --git a/src/mms/iso_cotp/cotp.c b/src/mms/iso_cotp/cotp.c
index a29c8378..c9165afc 100644
--- a/src/mms/iso_cotp/cotp.c
+++ b/src/mms/iso_cotp/cotp.c
@@ -449,6 +449,8 @@ CotpConnection_init(CotpConnection* self, Socket socket,
self->options.tSelDst = tsel;
self->payload = payloadBuffer;
+ CotpConnection_resetPayload(self);
+
/* default TPDU size is maximum size */
CotpConnection_setTpduSize(self, COTP_MAX_TPDU_SIZE);
diff --git a/src/mms/iso_mms/asn1c/OCTET_STRING.c b/src/mms/iso_mms/asn1c/OCTET_STRING.c
index 0e2ae4fa..9c908d3d 100644
--- a/src/mms/iso_mms/asn1c/OCTET_STRING.c
+++ b/src/mms/iso_mms/asn1c/OCTET_STRING.c
@@ -94,7 +94,6 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
} else { \
RETURN(RC_FAIL); \
} \
- ASN_DEBUG("Reallocating into %ld", (long)_ns); \
} \
memcpy(st->buf + st->size, bufptr, _bs); \
/* Convenient nul-termination */ \
@@ -187,12 +186,6 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
int tlv_constr;
OS_type_e type_variant = (OS_type_e)specs->subvariant;
- ASN_DEBUG("Decoding %s as %s (frame %ld)",
- td->name,
- (type_variant == _TT_GENERIC) ?
- "OCTET STRING" : "OS-SpecialCase",
- (long)size);
-
/*
* Create the string if does not exist.
*/
@@ -254,12 +247,6 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
ssize_t Left = ((!sel||(size_t)sel->left >= size)
?(ssize_t)size:sel->left);
-
- ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel,
- (long)(sel?sel->left:0),
- (long)(sel?sel->want_nulls:0),
- (long)(sel?sel->got:0)
- );
if(sel && sel->left <= 0 && sel->want_nulls == 0) {
if(sel->prev) {
struct _stack_el *prev = sel->prev;
@@ -280,11 +267,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
}
tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
- ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
- (long)size, (long)Left, sel?"":"!",
- (long)(sel?sel->left:0),
- (long)(sel?sel->want_nulls:0),
- (long)tl);
+
switch(tl) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
@@ -294,9 +277,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
ll = ber_fetch_length(tlv_constr,
(const char *)buf_ptr + tl,Left - tl,&tlv_len);
- ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
- ber_tlv_tag_string(tlv_tag), tlv_constr,
- (long)Left, (long)tl, (long)tlv_len, (long)ll);
+
switch(ll) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
@@ -307,8 +288,6 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
&& ((const uint8_t *)buf_ptr)[1] == 0)
{
- ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
-
if(type_variant == _TT_ANY
&& (tag_mode != 1 || sel->cont_level))
APPEND("\0\0", 2);
@@ -359,21 +338,12 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
if(tlv_tag != expected_tag) {
- char buf[2][32];
- ber_tlv_tag_snprint(tlv_tag,
- buf[0], sizeof(buf[0]));
- ber_tlv_tag_snprint(td->tags[td->tags_count-1],
- buf[1], sizeof(buf[1]));
- ASN_DEBUG("Tag does not match expectation: %s != %s",
- buf[0], buf[1]);
RETURN(RC_FAIL);
}
tlvl = tl + ll; /* Combined length of T and L encoding */
if((tlv_len + tlvl) < 0) {
/* tlv_len value is too big */
- ASN_DEBUG("TLV encoding + length (%ld) is too big",
- (long)tlv_len);
RETURN(RC_FAIL);
}
@@ -403,14 +373,9 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
sel->got += tlvl;
ADVANCE(tlvl);
- ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d",
- (long)sel->got, (long)sel->left,
- sel->want_nulls, sel->cont_level);
-
} while(tlv_constr);
if(sel == NULL) {
/* Finished operation, "phase out" */
- ASN_DEBUG("Phase out");
_CH_PHASE(ctx, +3);
break;
}
@@ -420,9 +385,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
case 2:
stck = (struct _stack *)ctx->ptr;
sel = stck->cur_ptr;
- ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
- (long)sel->left, (long)size, (long)sel->got,
- sel->want_nulls);
+
{
ber_tlv_len_t len;
@@ -446,8 +409,6 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
}
if(sel->left) {
- ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
- (long)sel->left, (long)size, sel->want_nulls);
RETURN(RC_WMORE);
}
@@ -491,9 +452,6 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
}
if(sel) {
- ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
- sel->prev, sel->want_nulls,
- (long)sel->left, (long)sel->got, (long)size);
if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
RETURN(RC_WMORE);
}
@@ -507,12 +465,6 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
st->buf[st->size-1] &= 0xff << st->bits_unused;
}
- ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
- (long)consumed_myself, td->name,
- (type_variant == _TT_GENERIC) ? (char *)st->buf : "",
- (long)st->size);
-
-
RETURN(RC_OK);
}
@@ -531,9 +483,6 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
OS_type_e type_variant = (OS_type_e)specs->subvariant;
int fix_last_byte = 0;
- ASN_DEBUG("%s %s as OCTET STRING",
- cb?"Estimating":"Encoding", td->name);
-
/*
* Write tags.
*/
@@ -1274,9 +1223,6 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
if(len_bits < 0) RETURN(RC_WMORE);
len_bits += ct->lower_bound;
- ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
- (long)ct->effective_bits, (long)len_bits,
- repeat ? "repeat" : "once", td->name);
if(unit_bits == 1) {
len_bytes = (len_bits + 7) >> 3;
if(len_bits & 0x7)
@@ -1323,17 +1269,9 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODE_FAILED;
if(unit_bits == 1) {
- ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
- sizeinunits, st->bits_unused);
sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07);
}
- ASN_DEBUG("Encoding %s into %d units of %d bits"
- " (%d..%d, effective %d)%s",
- td->name, sizeinunits, unit_bits,
- ct->lower_bound, ct->upper_bound,
- ct->effective_bits, ct_extensible ? " EXT" : "");
-
/* Figure out wheter size lies within PER visible consrtaint */
if(ct->effective_bits >= 0) {
@@ -1359,9 +1297,6 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(ct->effective_bits >= 0) {
- ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
- st->size, sizeinunits - ct->lower_bound,
- ct->effective_bits);
ret = per_put_few_bits(po, sizeinunits - ct->lower_bound,
ct->effective_bits);
if(ret) _ASN_ENCODE_FAILED;
@@ -1370,8 +1305,6 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(er);
}
- ASN_DEBUG("Encoding %d bytes", st->size);
-
if(sizeinunits == 0) {
if(uper_put_length(po, 0))
_ASN_ENCODE_FAILED;
@@ -1383,8 +1316,6 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
ssize_t maySave = uper_put_length(po, sizeinunits);
if(maySave < 0) _ASN_ENCODE_FAILED;
- ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits);
-
ret = per_put_many_bits(po, buf, maySave * unit_bits);
if(ret) _ASN_ENCODE_FAILED;
@@ -1468,8 +1399,6 @@ OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
if(!td || !st)
return;
- ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
-
if(st->buf) {
FREEMEM(st->buf);
}
diff --git a/src/mms/iso_mms/asn1c/ber_decoder.c b/src/mms/iso_mms/asn1c/ber_decoder.c
index 601f66c0..de0695ae 100644
--- a/src/mms/iso_mms/asn1c/ber_decoder.c
+++ b/src/mms/iso_mms/asn1c/ber_decoder.c
@@ -108,8 +108,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
tagno = step /* Continuing where left previously */
+ (tag_mode==1?-1:0)
;
- ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
- td->name, (long)size, tag_mode, step, tagno);
+
/* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
if(tag_mode == 0 && tagno == td->tags_count) {
@@ -130,8 +129,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
}
- ASN_DEBUG("Advancing %ld in ANY case",
- (long)(tag_len + len_len));
+
ADVANCE(tag_len + len_len);
} else {
assert(tagno < td->tags_count); /* At least one loop */
@@ -142,11 +140,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
* Fetch and process T from TLV.
*/
tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
- ASN_DEBUG("Fetching tag from {%p,%ld}: "
- "len %ld, step %d, tagno %d got %s",
- ptr, (long)size,
- (long)tag_len, step, tagno,
- ber_tlv_tag_string(tlv_tag));
+
switch(tag_len) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
@@ -170,12 +164,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
/*
* Unexpected tag. Too bad.
*/
- ASN_DEBUG("Expected: %s, "
- "expectation failed (tn=%d, tm=%d)",
- ber_tlv_tag_string(td->tags[tagno]),
- tagno, tag_mode
- );
- RETURN(RC_FAIL);
+ RETURN(RC_FAIL);
}
}
@@ -188,15 +177,11 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
*/
if(tagno < (td->tags_count - 1)) {
if(tlv_constr == 0) {
- ASN_DEBUG("tlv_constr = %d, expfail",
- tlv_constr);
RETURN(RC_FAIL);
}
} else {
if(last_tag_form != tlv_constr
&& last_tag_form != -1) {
- ASN_DEBUG("last_tag_form %d != %d",
- last_tag_form, tlv_constr);
RETURN(RC_FAIL);
}
}
@@ -206,7 +191,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
*/
len_len = ber_fetch_length(tlv_constr,
(const char *)ptr + tag_len, size - tag_len, &tlv_len);
- ASN_DEBUG("Fetchinig len = %ld", (long)len_len);
+
switch(len_len) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
@@ -226,16 +211,12 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
if(limit_len == -1) {
expect_00_terminators++;
} else {
- ASN_DEBUG("Unexpected indefinite length "
- "in a chain of definite lengths");
RETURN(RC_FAIL);
}
ADVANCE(tag_len + len_len);
continue;
} else {
if(expect_00_terminators) {
- ASN_DEBUG("Unexpected definite length "
- "in a chain of indefinite lengths");
RETURN(RC_FAIL);
}
}
@@ -255,8 +236,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
* Inner TLV specifies length which is inconsistent
* with the outer TLV's length value.
*/
- ASN_DEBUG("Outer TLV is %ld and inner is %ld",
- (long)limit_len, (long)tlv_len);
+
RETURN(RC_FAIL);
}
diff --git a/src/mms/iso_mms/asn1c/ber_tlv_tag.c b/src/mms/iso_mms/asn1c/ber_tlv_tag.c
index 588d9ee0..24588f90 100644
--- a/src/mms/iso_mms/asn1c/ber_tlv_tag.c
+++ b/src/mms/iso_mms/asn1c/ber_tlv_tag.c
@@ -56,50 +56,6 @@ ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) {
return 0; /* Want more */
}
-
-
-ssize_t
-ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) {
- char buf[sizeof("[APPLICATION ]") + 32];
- ssize_t ret;
-
- ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf));
- if(ret >= (ssize_t)sizeof(buf) || ret < 2) {
- errno = EPERM;
- return -1;
- }
-
- return fwrite(buf, 1, ret, f);
-}
-
-ssize_t
-ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) {
- char *type = 0;
- int ret;
-
- switch(tag & 0x3) {
- case ASN_TAG_CLASS_UNIVERSAL: type = "UNIVERSAL "; break;
- case ASN_TAG_CLASS_APPLICATION: type = "APPLICATION "; break;
- case ASN_TAG_CLASS_CONTEXT: type = ""; break;
- case ASN_TAG_CLASS_PRIVATE: type = "PRIVATE "; break;
- }
-
- ret = snprintf(buf, size, "[%s%u](%02x)", type, ((unsigned)tag) >> 2, tag);
- if(ret <= 0 && size) buf[0] = '\0'; /* against broken libc's */
-
- return ret;
-}
-
-char *
-ber_tlv_tag_string(ber_tlv_tag_t tag) {
- static char buf[sizeof("[APPLICATION ]") + 32];
-
- (void)ber_tlv_tag_snprint(tag, buf, sizeof(buf));
-
- return buf;
-}
-
-
size_t
ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) {
int tclass = BER_TAG_CLASS(tag);
diff --git a/src/mms/iso_mms/asn1c/constr_CHOICE.c b/src/mms/iso_mms/asn1c/constr_CHOICE.c
index b8d6fa9a..de2cc3a4 100644
--- a/src/mms/iso_mms/asn1c/constr_CHOICE.c
+++ b/src/mms/iso_mms/asn1c/constr_CHOICE.c
@@ -117,8 +117,6 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
- ASN_DEBUG("Decoding %s as CHOICE", td->name);
-
/*
* Create the target structure if it is not present already.
*/
@@ -149,8 +147,6 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
tag_mode, -1, &ctx->left, 0);
if(rval.code != RC_OK) {
- ASN_DEBUG("%s tagging check failed: %d",
- td->name, rval.code);
return rval;
}
@@ -165,16 +161,13 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
NEXT_PHASE(ctx);
- ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
- (long)ctx->left, (long)size);
-
/* Fall through */
case 1:
/*
* Fetch the T from TLV.
*/
tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
- ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
+
switch(tag_len) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
@@ -197,17 +190,11 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ctx->step = t2m->el_no;
break;
} else if(specs->ext_start == -1) {
- ASN_DEBUG("Unexpected tag %s "
- "in non-extensible CHOICE %s",
- ber_tlv_tag_string(tlv_tag), td->name);
RETURN(RC_FAIL);
} else {
/* Skip this tag */
ssize_t skip;
- ASN_DEBUG("Skipping unknown tag %s",
- ber_tlv_tag_string(tlv_tag));
-
skip = ber_skip_length(opt_codec_ctx,
BER_TLV_CONSTRUCTED(ptr),
(const char *)ptr + tag_len,
@@ -280,9 +267,6 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* Fall through */
case 3:
- ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
- td->name, (long)ctx->left, (long)size,
- tag_mode, td->tags_count);
if(ctx->left > 0) {
/*
@@ -335,8 +319,6 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
continue;
}
} else {
- ASN_DEBUG("Unexpected continuation in %s",
- td->name);
RETURN(RC_FAIL);
}
@@ -365,9 +347,6 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
if(!sptr) _ASN_ENCODE_FAILED;
- ASN_DEBUG("%s %s as CHOICE",
- cb?"Encoding":"Estimating", td->name);
-
present = _fetch_present_idx(sptr,
specs->pres_offset, specs->pres_size);
@@ -435,9 +414,6 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
if(erval.encoded == -1)
return erval;
- ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)",
- (long)erval.encoded, (long)computed_size);
-
erval.encoded += computed_size;
return erval;
@@ -482,9 +458,6 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int present;
if(!sptr) {
- _ASN_CTFAIL(app_key, td,
- "%s: value not given (%s:%d)",
- td->name, __FILE__, __LINE__);
return -1;
}
@@ -501,9 +474,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
if(!memb_ptr) {
if(elm->optional)
return 0;
- _ASN_CTFAIL(app_key, td,
- "%s: mandatory CHOICE element %s absent (%s:%d)",
- td->name, elm->name, __FILE__, __LINE__);
+
return -1;
}
} else {
@@ -524,9 +495,6 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
return ret;
}
} else {
- _ASN_CTFAIL(app_key, td,
- "%s: no CHOICE element given (%s:%d)",
- td->name, __FILE__, __LINE__);
return -1;
}
}
@@ -616,8 +584,7 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
elm->type, memb_ptr2, elm->name,
buf_ptr, size);
XER_ADVANCE(tmprval.consumed);
- ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d",
- elm->type->name, tmprval.code);
+
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
assert(_fetch_present_idx(st,
@@ -654,17 +621,10 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
- ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d",
- ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
- ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
- ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
- ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
- xml_tag, tcv);
/* Skip the extensions section */
if(ctx->phase == 4) {
- ASN_DEBUG("skip_unknown(%d, %ld)",
- tcv, (long)ctx->left);
+
switch(xer_skip_unknown(tcv, &ctx->left)) {
case -1:
ctx->phase = 5;
@@ -733,7 +693,6 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* It is expected extension */
if(specs->ext_start != -1) {
- ASN_DEBUG("Got anticipated extension");
/*
* Check for (XCT_BOTH or XCT_UNKNOWN_BO)
* By using a mask. Only record a pure
@@ -755,13 +714,6 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
break;
}
- ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]"
- " (ph=%d, tag=%s)",
- ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
- ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
- ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
- ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
- td->name, ctx->phase, xml_tag);
break;
}
@@ -859,8 +811,7 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) _ASN_DECODE_STARVED;
- ASN_DEBUG("CHOICE %s got index %d in range %d",
- td->name, value, ct->range_bits);
+
if(value > ct->upper_bound)
_ASN_DECODE_FAILED;
} else {
@@ -871,7 +822,7 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
value += specs->ext_start;
if(value >= td->elements_count)
_ASN_DECODE_FAILED;
- ASN_DEBUG("NOT IMPLEMENTED YET");
+
_ASN_DECODE_FAILED;
}
@@ -890,13 +841,10 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
- ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
- if(rv.code != RC_OK)
- ASN_DEBUG("Failed to decode %s in %s (CHOICE)",
- elm->name, td->name);
+
return rv;
}
@@ -911,8 +859,6 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
if(!sptr) _ASN_ENCODE_FAILED;
- ASN_DEBUG("Encoding %s as CHOICE", td->name);
-
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
else ct = 0;
@@ -933,8 +879,6 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
if(specs->canonical_order)
present = specs->canonical_order[present];
- ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
-
if(ct && ct->range_bits >= 0) {
if(present < ct->lower_bound
|| present > ct->upper_bound) {
@@ -959,7 +903,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODE_FAILED;
if(uper_put_nsnnwn(po, present - specs->ext_start))
_ASN_ENCODE_FAILED;
- ASN_DEBUG("NOT IMPLEMENTED YET");
+
_ASN_ENCODE_FAILED;
}
@@ -1026,8 +970,6 @@ CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(!td || !ptr)
return;
- ASN_DEBUG("Freeing %s as CHOICE", td->name);
-
/*
* Figure out which CHOICE element is encoded.
*/
diff --git a/src/mms/iso_mms/asn1c/constr_SEQUENCE.c b/src/mms/iso_mms/asn1c/constr_SEQUENCE.c
index b7694343..35aec840 100644
--- a/src/mms/iso_mms/asn1c/constr_SEQUENCE.c
+++ b/src/mms/iso_mms/asn1c/constr_SEQUENCE.c
@@ -33,7 +33,7 @@
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
- ptr = ((const char *)ptr) + num;\
+ ptr = ((const char *)ptr) + num; \
size -= num; \
if(ctx->left >= 0) \
ctx->left -= num; \
@@ -127,8 +127,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
int edx; /* SEQUENCE element's index */
-
- ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
/*
* Create the target structure if it is not present already.
@@ -159,8 +157,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
tag_mode, 1, &ctx->left, 0);
if(rval.code != RC_OK) {
- ASN_DEBUG("%s tagging check failed: %d",
- td->name, rval.code);
return rval;
}
@@ -170,9 +166,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
NEXT_PHASE(ctx);
- ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
- (long)ctx->left, (long)size);
-
/* Fall through */
case 1:
/*
@@ -200,11 +193,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/*
* MICROPHASE 1: Synchronize decoding.
*/
- ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d"
- " opt=%d ec=%d",
- td->name, (int)ctx->left, edx,
- elements[edx].flags, elements[edx].optional,
- td->elements_count);
if(ctx->left == 0 /* No more stuff is expected */
&& (
@@ -217,7 +205,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
&& specs->ext_before > td->elements_count)
)
) {
- ASN_DEBUG("End of SEQUENCE %s", td->name);
/*
* Found the legitimate end of the structure.
*/
@@ -229,10 +216,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
* Fetch the T from TLV.
*/
tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
- ASN_DEBUG("Current tag in %s SEQUENCE for element %d "
- "(%s) is %s encoded in %d bytes, of frame %ld",
- td->name, edx, elements[edx].name,
- ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);
+
switch(tag_len) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
@@ -246,9 +230,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
- ASN_DEBUG("edx = %d, opt = %d, ec=%d",
- edx, elements[edx].optional,
- td->elements_count);
+
if((edx + elements[edx].optional
== td->elements_count)
|| (IN_EXTENSION_GROUP(specs, edx)
@@ -346,25 +328,18 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
* or an extension (...),
* or an end of the indefinite-length structure.
*/
- if(!IN_EXTENSION_GROUP(specs, edx)) {
- ASN_DEBUG("Unexpected tag %s (at %d)",
- ber_tlv_tag_string(tlv_tag), edx);
- ASN_DEBUG("Expected tag %s (%s)%s",
- ber_tlv_tag_string(elements[edx].tag),
- elements[edx].name,
- elements[edx].optional
- ?" or alternatives":"");
+ if(!IN_EXTENSION_GROUP(specs, edx + elements[edx].optional)) {
RETURN(RC_FAIL);
} else {
/* Skip this tag */
ssize_t skip;
+ edx += elements[edx].optional;
skip = ber_skip_length(opt_codec_ctx,
BER_TLV_CONSTRUCTED(ptr),
(const char *)ptr + tag_len,
LEFT - tag_len);
- ASN_DEBUG("Skip length %d in %s",
- (int)skip, td->name);
+
switch(skip) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
@@ -383,7 +358,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
*/
ctx->step |= 1; /* Confirm entering next microphase */
microphase2:
- ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
/*
* Compute the position of the member inside a structure,
@@ -408,10 +382,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
elements[edx].type,
memb_ptr2, ptr, LEFT,
elements[edx].tag_mode);
- ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d "
- "in %d bytes rval.code %d, size=%d",
- td->name, edx, elements[edx].type->name,
- (int)LEFT, (int)rval.consumed, rval.code, (int)size);
+
switch(rval.code) {
case RC_OK:
break;
@@ -420,8 +391,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ADVANCE(rval.consumed);
RETURN(RC_WMORE);
}
- ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
- (long)ctx->left, (long)size);
+
/* Fall through */
case RC_FAIL: /* Fatal error */
RETURN(RC_FAIL);
@@ -435,9 +405,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
case 3: /* 00 and other tags expected */
case 4: /* only 00's expected */
- ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
- td->name, (long)ctx->left, (long)size);
-
/*
* Skip everything until the end of the SEQUENCE.
*/
@@ -474,11 +441,6 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(!IN_EXTENSION_GROUP(specs, td->elements_count)
|| ctx->phase == 4) {
- ASN_DEBUG("Unexpected continuation "
- "of a non-extensible type "
- "%s (SEQUENCE): %s",
- td->name,
- ber_tlv_tag_string(tlv_tag));
RETURN(RC_FAIL);
}
@@ -1174,7 +1136,6 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
er.encoded = 0;
- ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
if(specs->ext_before >= 0)
_ASN_ENCODE_FAILED; /* We don't encode extensions yet */
diff --git a/src/mms/iso_mms/asn1c/constr_SET_OF.c b/src/mms/iso_mms/asn1c/constr_SET_OF.c
index c4928e2e..e183de47 100644
--- a/src/mms/iso_mms/asn1c/constr_SET_OF.c
+++ b/src/mms/iso_mms/asn1c/constr_SET_OF.c
@@ -84,8 +84,6 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_dec_rval_t rval; /* Return code from subparsers */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
-
- ASN_DEBUG("Decoding %s as SET OF", td->name);
/*
* Create the target structure if it is not present already.
@@ -116,8 +114,6 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
tag_mode, 1, &ctx->left, 0);
if(rval.code != RC_OK) {
- ASN_DEBUG("%s tagging check failed: %d",
- td->name, rval.code);
return rval;
}
@@ -125,9 +121,6 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ctx->left += rval.consumed; /* ?Substracted below! */
ADVANCE(rval.consumed);
- ASN_DEBUG("Structure consumes %ld bytes, "
- "buffer %ld", (long)ctx->left, (long)size);
-
NEXT_PHASE(ctx);
/* Fall through */
case 1:
@@ -147,7 +140,6 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
*/
if(ctx->left == 0) {
- ASN_DEBUG("End of SET OF %s", td->name);
/*
* No more things to decode.
* Exit out of here.
@@ -188,10 +180,6 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
* The new list member of expected type has arrived.
*/
} else {
- ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
- ber_tlv_tag_string(tlv_tag), td->name);
- ASN_DEBUG("%s SET OF has tag %s",
- td->name, ber_tlv_tag_string(elm->tag));
RETURN(RC_FAIL);
}
}
@@ -207,9 +195,7 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
*/
rval = elm->type->ber_decoder(opt_codec_ctx,
elm->type, &ctx->ptr, ptr, LEFT, 0);
- ASN_DEBUG("In %s SET OF %s code %d consumed %d",
- td->name, elm->type->name,
- rval.code, (int)rval.consumed);
+
switch(rval.code) {
case RC_OK:
{
@@ -227,6 +213,8 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
/* Fall through */
case RC_FAIL: /* Fatal error */
+ ASN_STRUCT_FREE(*elm->type, ctx->ptr);
+ ctx->ptr = 0;
RETURN(RC_FAIL);
} /* switch(rval) */
@@ -324,8 +312,6 @@ SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
int ret;
int edx;
- ASN_DEBUG("Estimating size for SET OF %s", td->name);
-
/*
* Gather the length of the underlying members sequence.
*/
@@ -374,8 +360,6 @@ SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
return erval;
}
- ASN_DEBUG("Encoding members of %s SET OF", td->name);
-
/*
* Encode all members.
*/
@@ -523,7 +507,6 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_dec_rval_t tmprval;
/* Invoke the inner type decoder, m.b. multiple times */
- ASN_DEBUG("XER/SET OF element [%s]", elm_tag);
tmprval = element->type->xer_decoder(opt_codec_ctx,
element->type, &ctx->ptr, elm_tag,
buf_ptr, size);
@@ -538,7 +521,6 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
RETURN(tmprval.code);
}
ctx->phase = 1; /* Back to body processing */
- ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
/* Fall through */
}
@@ -562,8 +544,7 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
- ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s",
- tcv, ctx->phase, xml_tag);
+
switch(tcv) {
case XCT_CLOSING:
if(ctx->phase == 0) break;
@@ -587,7 +568,6 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
case XCT_UNKNOWN_OP:
case XCT_UNKNOWN_BO:
- ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase);
if(ctx->phase == 1) {
/*
* Process a single possible member.
@@ -600,7 +580,6 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
break;
}
- ASN_DEBUG("Unexpected XML tag in SET OF");
break;
}
@@ -787,8 +766,10 @@ SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
void
SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(td && ptr) {
+ asn_SET_OF_specifics_t *specs;
asn_TYPE_member_t *elm = td->elements;
asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
+ asn_struct_ctx_t *ctx; /* Decoder context */
int i;
/*
@@ -804,6 +785,13 @@ SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
asn_set_empty(list); /* Remove (list->array) */
+ specs = (asn_SET_OF_specifics_t *)td->specifics;
+ ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
+ if(ctx->ptr) {
+ ASN_STRUCT_FREE(*elm->type, ctx->ptr);
+ ctx->ptr = 0;
+ }
+
if(!contents_only) {
FREEMEM(ptr);
}
@@ -819,9 +807,6 @@ SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int i;
if(!sptr) {
- _ASN_CTFAIL(app_key, td,
- "%s: value not given (%s:%d)",
- td->name, __FILE__, __LINE__);
return -1;
}
@@ -890,8 +875,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(ct && ct->effective_bits >= 0) {
/* X.691, #19.5: No length determinant */
nelems = per_get_few_bits(pd, ct->effective_bits);
- ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
- (long)nelems, ct->lower_bound, td->name);
+
if(nelems < 0) _ASN_DECODE_STARVED;
nelems += ct->lower_bound;
} else {
@@ -908,20 +892,11 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
for(i = 0; i < nelems; i++) {
void *ptr = 0;
- ASN_DEBUG("SET OF %s decoding", elm->type->name);
- rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
- elm->per_constraints, &ptr, pd);
- ASN_DEBUG("%s SET OF %s decoded %d, %p",
- td->name, elm->type->name, rv.code, ptr);
+
if(rv.code == RC_OK) {
if(ASN_SET_ADD(list, ptr) == 0)
continue;
- ASN_DEBUG("Failed to add element into %s",
- td->name);
/* Fall through */
- } else {
- ASN_DEBUG("Failed decoding %s of %s (SET OF)",
- elm->type->name, td->name);
}
if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
return rv;
@@ -930,8 +905,6 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
nelems = -1; /* Allow uper_get_length() */
} while(repeat);
- ASN_DEBUG("Decoded %s as SET OF", td->name);
-
rv.code = RC_OK;
rv.consumed = 0;
return rv;
diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c
index 00ad03fd..7111b657 100644
--- a/src/mms/iso_mms/client/mms_client_connection.c
+++ b/src/mms/iso_mms/client/mms_client_connection.c
@@ -281,19 +281,22 @@ removeFromOutstandingCalls(MmsConnection self, uint32_t invokeId)
}
static ByteBuffer*
-sendRequestAndWaitForResponse(MmsConnection self, uint32_t invokeId, ByteBuffer* message)
+sendRequestAndWaitForResponse(MmsConnection self, uint32_t invokeId, ByteBuffer* message, MmsError* mmsError)
{
ByteBuffer* receivedMessage = NULL;
- uint64_t startTime = Hal_getTimeInMs();
-
- uint64_t waitUntilTime = startTime + self->requestTimeout;
+ uint64_t currentTime = Hal_getTimeInMs();
- uint64_t currentTime = startTime;
+ uint64_t waitUntilTime = currentTime + self->requestTimeout;
bool success = false;
- addToOutstandingCalls(self, invokeId);
+ if (addToOutstandingCalls(self, invokeId) == false) {
+ *mmsError = MMS_ERROR_OUTSTANDING_CALL_LIMIT;
+ return NULL;
+ }
+
+ *mmsError = MMS_ERROR_NONE;
#if (CONFIG_MMS_RAW_MESSAGE_LOGGING == 1)
if (self->rawMmsMessageHandler != NULL) {
@@ -307,19 +310,26 @@ sendRequestAndWaitForResponse(MmsConnection self, uint32_t invokeId, ByteBuffer*
while (currentTime < waitUntilTime) {
uint32_t receivedInvokeId;
- if (self->associationState == MMS_STATE_CLOSED)
+ if (self->associationState == MMS_STATE_CLOSED) {
+ *mmsError = MMS_ERROR_CONNECTION_LOST;
goto connection_lost;
+ }
Semaphore_wait(self->lastResponseLock);
+
receivedInvokeId = self->responseInvokeId;
- Semaphore_post(self->lastResponseLock);
if (receivedInvokeId == invokeId) {
+
receivedMessage = self->lastResponse;
+ Semaphore_post(self->lastResponseLock);
+
success = true;
break;
}
+ Semaphore_post(self->lastResponseLock);
+
Thread_sleep(10);
currentTime = Hal_getTimeInMs();
@@ -328,10 +338,17 @@ sendRequestAndWaitForResponse(MmsConnection self, uint32_t invokeId, ByteBuffer*
if (!success) {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: TIMEOUT for request %u: \n", invokeId);
- self->lastResponseError = MMS_ERROR_SERVICE_TIMEOUT;
+
+ *mmsError = MMS_ERROR_SERVICE_TIMEOUT;
+ }
+ else {
+ *mmsError = self->lastResponseError;
+
+ if (*mmsError != MMS_ERROR_NONE)
+ receivedMessage = NULL;
}
- connection_lost:
+connection_lost:
removeFromOutstandingCalls(self, invokeId);
@@ -372,6 +389,21 @@ waitUntilLastResponseHasBeenProcessed(MmsConnection self)
}
}
+static MmsError
+convertRejectCodesToMmsError(int rejectType, int rejectReason)
+{
+ if ((rejectType == 1) && (rejectReason == 1))
+ return MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE;
+ else if ((rejectType == 5) && (rejectReason == 0))
+ return MMS_ERROR_REJECT_UNKNOWN_PDU_TYPE;
+ else if ((rejectType == 1) && (rejectReason == 4))
+ return MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT;
+ else if ((rejectType == 5) && (rejectReason == 1))
+ return MMS_ERROR_REJECT_INVALID_PDU;
+ else
+ return MMS_ERROR_REJECT_OTHER;
+}
+
static MmsError
convertServiceErrorToMmsError(MmsServiceError serviceError)
{
@@ -552,11 +584,8 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32
int endPos = bufPos + length;
- if (endPos > maxBufPos) {
- if (DEBUG_MMS_CLIENT)
- printf("parseConfirmedErrorPDU: message to short!\n");
+ if (endPos > maxBufPos)
goto exit_error;
- }
while (bufPos < endPos) {
tag = buffer[bufPos++];
@@ -588,6 +617,63 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32
return bufPos;
exit_error:
+ if (DEBUG_MMS_CLIENT)
+ printf("MMS_CLIENT: error parsing confirmed error PDU\n");
+
+ return -1;
+}
+
+int
+mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, int* rejectType, int* rejectReason)
+{
+ int length;
+
+ uint8_t tag = buffer[bufPos++];
+
+ if (tag != 0xa4)
+ goto exit_error;
+
+ bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
+ if (bufPos < 0)
+ goto exit_error;
+
+ if (bufPos + length > maxBufPos)
+ goto exit_error;
+
+ int endPos = bufPos + length;
+
+ if (endPos > maxBufPos)
+ goto exit_error;
+
+ while (bufPos < endPos) {
+ tag = buffer[bufPos++];
+ bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
+
+ if (bufPos < 0)
+ goto exit_error;
+
+
+ if (tag == 0x80) { /* invoke id */
+ if (invokeId != NULL)
+ *invokeId = BerDecoder_decodeUint32(buffer, length, bufPos);
+ }
+ else if (tag > 0x80 && tag < 0x8c) {
+ *rejectType = tag - 0x80;
+ *rejectReason = BerDecoder_decodeInt32(buffer, length, bufPos);
+ }
+ else {
+ /* unknown - ignore */
+ }
+
+ bufPos += length;
+ }
+
+ return bufPos;
+
+exit_error:
+ if (DEBUG_MMS_CLIENT)
+ printf("MMS_CLIENT: error parsing reject PDU\n");
+
return -1;
}
@@ -662,7 +748,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
self->concludeState = CONCLUDE_STATE_REQUESTED;
- /* TODO block all new user requests */
+ /* TODO block all new user requests? */
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
}
@@ -693,10 +779,13 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (mmsMsg_parseConfirmedErrorPDU(payload->buffer, 0, payload->size, &invokeId, &serviceError) < 0) {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: Error parsing confirmedErrorPDU!\n");
+
+ goto exit_with_error;
}
else {
if (checkForOutstandingCall(self, invokeId)) {
+ /* wait for application thread to handle last received response */
waitUntilLastResponseHasBeenProcessed(self);
Semaphore_wait(self->lastResponseLock);
@@ -712,6 +801,37 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
}
}
}
+ else if (tag == 0xa4) { /* reject PDU */
+ if (DEBUG_MMS_CLIENT)
+ printf("MMS_CLIENT: reject PDU!\n");
+
+ uint32_t invokeId;
+ int rejectType;
+ int rejectReason;
+
+ if (mmsMsg_parseRejectPDU(payload->buffer, 0, payload->size, &invokeId, &rejectType, &rejectReason) >= 0) {
+
+ if (DEBUG_MMS_CLIENT)
+ printf("MMS_CLIENT: reject PDU invokeID: %i type: %i reason: %i\n", (int) invokeId, rejectType, rejectReason);
+
+ if (checkForOutstandingCall(self, invokeId)) {
+
+ /* wait for application thread to handle last received response */
+ waitUntilLastResponseHasBeenProcessed(self);
+
+ Semaphore_wait(self->lastResponseLock);
+ self->lastResponseError = convertRejectCodesToMmsError(rejectType, rejectReason);
+ self->responseInvokeId = invokeId;
+ Semaphore_post(self->lastResponseLock);
+ }
+ else {
+ IsoClientConnection_releaseReceiveBuffer(self->isoClient);
+ return;
+ }
+ }
+ else
+ goto exit_with_error;
+ }
else if (tag == 0xa1) { /* confirmed response PDU */
int length;
@@ -879,16 +999,16 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
return;
- exit_with_error:
+exit_with_error:
if (DEBUG_MMS_CLIENT)
- printf("received malformed message from server!\n");
+ printf("MMS_CLIENT: received malformed message from server!\n");
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
if (DEBUG_MMS_CLIENT)
- printf("LEAVE mmsIsoCallback - NOT OK!\n");
+ printf("MMS_CLIENT: LEAVE mmsIsoCallback - NOT OK!\n");
return;
}
@@ -947,9 +1067,50 @@ MmsConnection_destroy(MmsConnection self)
GLOBAL_FREEMEM(self->outstandingCalls);
+#if (MMS_OBTAIN_FILE_SERVICE == 1)
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ if (self->filestoreBasepath != NULL)
+ GLOBAL_FREEMEM(self->filestoreBasepath);
+#endif
+#endif
+
GLOBAL_FREEMEM(self);
}
+void
+MmsConnection_setFilestoreBasepath(MmsConnection self, const char* basepath)
+{
+#if (MMS_OBTAIN_FILE_SERVICE == 1)
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ if (self->filestoreBasepath != NULL) {
+ GLOBAL_FREEMEM(self->filestoreBasepath);
+ self->filestoreBasepath = NULL;
+ }
+
+ if (basepath != NULL)
+ self->filestoreBasepath = StringUtils_copyString(basepath);
+#endif
+#endif
+}
+
+char*
+MmsConnection_getFilestoreBasepath(MmsConnection self)
+{
+#if (MMS_OBTAIN_FILE_SERVICE == 1)
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ if (self->filestoreBasepath != NULL)
+ return self->filestoreBasepath;
+ else
+ return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
+#else
+ return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
+#endif
+
+#else
+ return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
+#endif
+}
+
void
MmsConnection_setRawMessageHandler(MmsConnection self, MmsRawMessageHandler handler, void* parameter)
{
@@ -1006,11 +1167,9 @@ MmsConnection_getMmsConnectionParameters(MmsConnection self)
static void
waitForConnectResponse(MmsConnection self)
{
- uint64_t startTime = Hal_getTimeInMs();
+ uint64_t currentTime = Hal_getTimeInMs();
- uint64_t waitUntilTime = startTime + self->requestTimeout;
-
- uint64_t currentTime = startTime;
+ uint64_t waitUntilTime = currentTime + self->requestTimeout;
while (currentTime < waitUntilTime) {
if (self->connectionState != MMS_CON_WAITING)
@@ -1020,7 +1179,6 @@ waitForConnectResponse(MmsConnection self)
currentTime = Hal_getTimeInMs();
}
-
}
bool
@@ -1206,8 +1364,6 @@ mmsClient_getNameListSingleRequest(
goto exit_function;
}
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
@@ -1225,19 +1381,13 @@ mmsClient_getNameListSingleRequest(
payload, objectClass, continueAfter);
}
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
if (responseMessage != NULL)
moreFollows = mmsClient_parseGetNameListResponse(nameList, self->lastResponse, NULL);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
-
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return moreFollows;
}
@@ -1319,24 +1469,17 @@ MmsConnection_readVariable(MmsConnection self, MmsError* mmsError,
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createReadRequest(invokeId, domainId, itemId, payload);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
value = mmsClient_parseReadResponse(self->lastResponse, NULL, false);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return value;
}
@@ -1355,25 +1498,18 @@ MmsConnection_readArrayElements(MmsConnection self, MmsError* mmsError,
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createReadRequestAlternateAccessIndex(invokeId, domainId, itemId, startIndex,
numberOfElements, payload);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
value = mmsClient_parseReadResponse(self->lastResponse, NULL, false);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return value;
}
@@ -1391,24 +1527,17 @@ MmsConnection_readMultipleVariables(MmsConnection self, MmsError* mmsError,
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createReadRequestMultipleValues(invokeId, domainId, items, payload);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
value = mmsClient_parseReadResponse(self->lastResponse, NULL, true);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return value;
}
@@ -1427,27 +1556,18 @@ MmsConnection_readNamedVariableListValues(MmsConnection self, MmsError* mmsError
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createReadNamedVariableListRequest(invokeId, domainId, listName,
payload, specWithResult);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE) {
- *mmsError = self->lastResponseError;
- }
- else if (responseMessage != NULL) {
+ if (responseMessage != NULL)
value = mmsClient_parseReadResponse(self->lastResponse, NULL, true);
- }
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return value;
}
@@ -1467,25 +1587,18 @@ MmsConnection_readNamedVariableListValuesAssociationSpecific(
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createReadAssociationSpecificNamedVariableListRequest(invokeId, listName,
payload, specWithResult);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
value = mmsClient_parseReadResponse(self->lastResponse, NULL, true);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return value;
}
@@ -1503,26 +1616,19 @@ MmsConnection_readNamedVariableListDirectory(MmsConnection self, MmsError* mmsEr
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createGetNamedVariableListAttributesRequest(invokeId, payload, domainId,
listName);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
attributes = mmsClient_parseGetNamedVariableListAttributesResponse(self->lastResponse, NULL,
deletable);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return attributes;
}
@@ -1540,26 +1646,19 @@ MmsConnection_readNamedVariableListDirectoryAssociationSpecific(MmsConnection se
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createGetNamedVariableListAttributesRequestAssociationSpecific(invokeId, payload,
listName);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
attributes = mmsClient_parseGetNamedVariableListAttributesResponse(self->lastResponse, NULL,
deletable);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return attributes;
}
@@ -1575,26 +1674,19 @@ MmsConnection_defineNamedVariableList(MmsConnection self, MmsError* mmsError,
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createDefineNamedVariableListRequest(invokeId, payload, domainId,
listName, variableSpecs, false);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
if (!mmsClient_parseDefineNamedVariableResponse(self->lastResponse, NULL))
- *mmsError = MMS_ERROR_DEFINITION_OTHER;
+ *mmsError = MMS_ERROR_PARSING_RESPONSE;
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return;
}
@@ -1610,25 +1702,19 @@ MmsConnection_defineNamedVariableListAssociationSpecific(MmsConnection self,
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createDefineNamedVariableListRequest(invokeId, payload, NULL,
listName, variableSpecs, true);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
if (!mmsClient_parseDefineNamedVariableResponse(self->lastResponse, NULL))
- *mmsError = MMS_ERROR_DEFINITION_OTHER;
+ *mmsError = MMS_ERROR_PARSING_RESPONSE;
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
exit_function:
return;
@@ -1647,25 +1733,18 @@ MmsConnection_deleteNamedVariableList(MmsConnection self, MmsError* mmsError,
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createDeleteNamedVariableListRequest(invokeId, payload, domainId, listName);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
if (mmsClient_parseDeleteNamedVariableListResponse(self->lastResponse, NULL))
isDeleted = true;
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return isDeleted;
}
@@ -1683,26 +1762,19 @@ MmsConnection_deleteAssociationSpecificNamedVariableList(MmsConnection self,
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createDeleteAssociationSpecificNamedVariableListRequest(
invokeId, payload, listName);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
if (mmsClient_parseDeleteNamedVariableListResponse(self->lastResponse, NULL))
isDeleted = true;
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return isDeleted;
}
@@ -1720,24 +1792,17 @@ MmsConnection_getVariableAccessAttributes(MmsConnection self, MmsError* mmsError
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createGetVariableAccessAttributesRequest(invokeId, domainId, itemId, payload);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
typeSpec = mmsClient_parseGetVariableAccessAttributesResponse(self->lastResponse, NULL);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return typeSpec;
}
@@ -1754,24 +1819,17 @@ MmsConnection_identify(MmsConnection self, MmsError* mmsError)
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createIdentifyRequest(invokeId, payload);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
+ if (responseMessage != NULL)
identity = mmsClient_parseIdentifyResponse(self);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
exit_function:
return identity;
}
@@ -1782,41 +1840,28 @@ MmsConnection_getServerStatus(MmsConnection self, MmsError* mmsError, int* vmdLo
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createStatusRequest(invokeId, payload, extendedDerivation);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL) {
+ if (responseMessage != NULL) {
if (mmsClient_parseStatusResponse(self, vmdLogicalStatus, vmdPhysicalStatus) == false)
*mmsError = MMS_ERROR_PARSING_RESPONSE;
}
releaseResponse(self);
-
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
-
}
static LinkedList
readJournal(MmsConnection self, MmsError* mmsError, uint32_t invokeId, ByteBuffer* payload, bool* moreFollows)
{
- *mmsError = MMS_ERROR_NONE;
-
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
LinkedList response = NULL;
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL) {
+ if (responseMessage != NULL) {
if (mmsClient_parseReadJournalResponse(self, moreFollows, &response) == false)
*mmsError = MMS_ERROR_PARSING_RESPONSE;
@@ -1824,9 +1869,6 @@ readJournal(MmsConnection self, MmsError* mmsError, uint32_t invokeId, ByteBuff
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
return response;
}
@@ -1930,19 +1972,15 @@ MmsConnection_fileOpen(MmsConnection self, MmsError* mmsError, const char* filen
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
int32_t frsmId = -1;
mmsClient_createFileOpenRequest(invokeId, payload, filename, initialPosition);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL) {
+ if (responseMessage != NULL) {
uint8_t* buffer = self->lastResponse->buffer;
int maxBufPos = self->lastResponse->size;
@@ -1954,9 +1992,6 @@ MmsConnection_fileOpen(MmsConnection self, MmsError* mmsError, const char* filen
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
return frsmId;
}
@@ -1965,23 +2000,15 @@ MmsConnection_fileClose(MmsConnection self, MmsError* mmsError, int32_t frsmId)
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
- uint32_t invokeId = getNextInvokeId(self);
-
- mmsClient_createFileCloseRequest(invokeId, payload, frsmId);
-
- sendRequestAndWaitForResponse(self, invokeId, payload);
+ uint32_t invokeId = getNextInvokeId(self);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
+ mmsClient_createFileCloseRequest(invokeId, payload, frsmId);
- /* nothing to do - response contains no data to evaluate */
+ sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- releaseResponse(self);
+ /* nothing to do - response contains no data to evaluate */
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
+ releaseResponse(self);
}
void
@@ -1989,24 +2016,15 @@ MmsConnection_fileDelete(MmsConnection self, MmsError* mmsError, const char* fil
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
- uint32_t invokeId = getNextInvokeId(self);
-
- mmsClient_createFileDeleteRequest(invokeId, payload, fileName);
-
-
- sendRequestAndWaitForResponse(self, invokeId, payload);
+ uint32_t invokeId = getNextInvokeId(self);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
+ mmsClient_createFileDeleteRequest(invokeId, payload, fileName);
- /* nothing to do - response contains no data to evaluate */
+ sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- releaseResponse(self);
+ /* nothing to do - response contains no data to evaluate */
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
+ releaseResponse(self);
}
bool
@@ -2015,18 +2033,14 @@ MmsConnection_fileRead(MmsConnection self, MmsError* mmsError, int32_t frsmId, M
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
bool moreFollows = false;
mmsClient_createFileReadRequest(invokeId, payload, frsmId);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL) {
+ if (responseMessage != NULL) {
uint8_t* buffer = self->lastResponse->buffer;
int maxBufPos = self->lastResponse->size;
int bufPos = self->lastResponseBufPos;
@@ -2037,9 +2051,6 @@ MmsConnection_fileRead(MmsConnection self, MmsError* mmsError, int32_t frsmId, M
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
return moreFollows;
}
@@ -2050,28 +2061,21 @@ MmsConnection_getFileDirectory(MmsConnection self, MmsError* mmsError, const cha
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createFileDirectoryRequest(invokeId, payload, fileSpecification, continueAfter);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
bool moreFollows = false;
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL) {
+ if (responseMessage != NULL) {
if (mmsClient_parseFileDirectoryResponse(self, handler, handlerParameter, &moreFollows) == false)
*mmsError = MMS_ERROR_PARSING_RESPONSE;
}
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
-
return moreFollows;
}
@@ -2080,23 +2084,15 @@ MmsConnection_fileRename(MmsConnection self, MmsError* mmsError, const char* cur
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createFileRenameRequest(invokeId, payload, currentFileName, newFileName);
- sendRequestAndWaitForResponse(self, invokeId, payload);
-
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
+ sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
/* nothing to do - response contains no data to evaluate */
releaseResponse(self);
-
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
}
@@ -2105,49 +2101,38 @@ MmsConnection_obtainFile(MmsConnection self, MmsError* mmsError, const char* sou
{
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createObtainFileRequest(invokeId, payload, sourceFile, destinationFile);
- sendRequestAndWaitForResponse(self, invokeId, payload);
-
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
+ sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
/* nothing to do - response contains no data to evaluate */
releaseResponse(self);
-
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
}
-void
+MmsDataAccessError
MmsConnection_writeVariable(MmsConnection self, MmsError* mmsError,
const char* domainId, const char* itemId,
MmsValue* value)
{
- ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
+ MmsDataAccessError retVal = DATA_ACCESS_ERROR_UNKNOWN;
- *mmsError = MMS_ERROR_NONE;
+ ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
uint32_t invokeId = getNextInvokeId(self);
mmsClient_createWriteRequest(invokeId, domainId, itemId, value, payload);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL)
- mmsClient_parseWriteResponse(self->lastResponse, self->lastResponseBufPos, mmsError);
+ if (responseMessage != NULL)
+ retVal = mmsClient_parseWriteResponse(self->lastResponse, self->lastResponseBufPos, mmsError);
releaseResponse(self);
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
+ return retVal;
}
void
@@ -2156,19 +2141,15 @@ MmsConnection_writeMultipleVariables(MmsConnection self, MmsError* mmsError, con
LinkedList /* */values,
/* OUTPUT */LinkedList* /* */accessResults)
{
- *mmsError = MMS_ERROR_NONE;
-
uint32_t invokeId = getNextInvokeId(self);
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
mmsClient_createWriteMultipleItemsRequest(invokeId, domainId, items, values, payload);
- ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
- if (self->lastResponseError != MMS_ERROR_NONE)
- *mmsError = self->lastResponseError;
- else if (responseMessage != NULL) {
+ if (responseMessage != NULL) {
int numberOfItems = LinkedList_size(items);
@@ -2177,9 +2158,53 @@ MmsConnection_writeMultipleVariables(MmsConnection self, MmsError* mmsError, con
}
releaseResponse(self);
+}
- if (self->associationState == MMS_STATE_CLOSED)
- *mmsError = MMS_ERROR_CONNECTION_LOST;
+MmsDataAccessError
+MmsConnection_writeArrayElements(MmsConnection self, MmsError* mmsError,
+ const char* domainId, const char* itemId, int index, int numberOfElements,
+ MmsValue* value)
+{
+ MmsDataAccessError retVal = DATA_ACCESS_ERROR_UNKNOWN;
+
+ uint32_t invokeId = getNextInvokeId(self);
+
+ ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
+
+ mmsClient_createWriteRequestArray(invokeId, domainId, itemId, index, numberOfElements, value, payload);
+
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
+
+ if (responseMessage != NULL)
+ retVal = mmsClient_parseWriteResponse(self->lastResponse, self->lastResponseBufPos, mmsError);
+
+ releaseResponse(self);
+
+ return retVal;
+}
+
+void
+MmsConnection_writeNamedVariableList(MmsConnection self, MmsError* mmsError, bool isAssociationSpecific,
+ const char* domainId, const char* itemId, LinkedList /* */values,
+ /* OUTPUT */LinkedList* /* */accessResults)
+{
+ uint32_t invokeId = getNextInvokeId(self);
+
+ ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
+
+ mmsClient_createWriteRequestNamedVariableList(invokeId, isAssociationSpecific, domainId, itemId, values, payload);
+
+ ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError);
+
+ if (responseMessage != NULL) {
+
+ int numberOfItems = LinkedList_size(values);
+
+ mmsClient_parseWriteMultipleItemsResponse(self->lastResponse, self->lastResponseBufPos, mmsError,
+ numberOfItems, accessResults);
+ }
+
+ releaseResponse(self);
}
void
diff --git a/src/mms/iso_mms/client/mms_client_files.c b/src/mms/iso_mms/client/mms_client_files.c
index a6603ebc..1eb79890 100644
--- a/src/mms/iso_mms/client/mms_client_files.c
+++ b/src/mms/iso_mms/client/mms_client_files.c
@@ -80,57 +80,6 @@ getNextFrsmId(MmsConnection connection)
return nextFrsmId;
}
-//TODO remove redundancy (with server implementation)
-static void
-createExtendedFilename(char* extendedFileName, char* fileName)
-{
- strcpy(extendedFileName, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
- strncat(extendedFileName, fileName, sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256);
-}
-
-//TODO remove redundancy (with server implementation)
-static FileHandle
-openFile(char* fileName, bool readWrite)
-{
- char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
-
- createExtendedFilename(extendedFileName, fileName);
-
- return FileSystem_openFile(extendedFileName, readWrite);
-}
-
-//TODO remove redundancy (with server implementation)
-static bool
-parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response)
-{
- uint8_t tag = buffer[(*bufPos)++];
- int length;
-
- if (tag != 0x19) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- return false;
- }
-
- *bufPos = BerDecoder_decodeLength(buffer, &length, *bufPos, maxBufPos);
-
- if (*bufPos < 0) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- return false;
- }
-
- if (length > 255) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
- return false;
- }
-
- memcpy(filename, buffer + *bufPos, length);
- filename[length] = 0;
- *bufPos += length;
-
- return true;
-}
-
-
void
mmsClient_handleFileOpenRequest(
MmsConnection connection,
@@ -149,10 +98,12 @@ mmsClient_handleFileOpenRequest(
if (bufPos < 0) goto exit_reject_invalid_pdu;
+ if (bufPos + length > maxBufPos) goto exit_reject_invalid_pdu;
+
switch(tag) {
case 0xa0: /* filename */
- if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasFileName = true;
@@ -175,14 +126,15 @@ mmsClient_handleFileOpenRequest(
MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
if (frsm != NULL) {
- FileHandle fileHandle = openFile(filename, false);
+ FileHandle fileHandle = mmsMsg_openFile(MmsConnection_getFilestoreBasepath(connection), filename, false);
if (fileHandle != NULL) {
frsm->fileHandle = fileHandle;
frsm->readPosition = filePosition;
frsm->frsmId = getNextFrsmId(connection);
- mmsMsg_createFileOpenResponse(invokeId, response, filename, frsm);
+ mmsMsg_createFileOpenResponse(MmsConnection_getFilestoreBasepath(connection),
+ invokeId, response, filename, frsm);
}
else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
@@ -212,7 +164,7 @@ mmsClient_handleFileReadRequest(
uint32_t invokeId,
ByteBuffer* response)
{
- int32_t frsmId = (int32_t) BerDecoder_decodeUint32(buffer, maxBufPos - bufPos, bufPos);
+ int32_t frsmId = BerDecoder_decodeInt32(buffer, maxBufPos - bufPos, bufPos);
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: mmsClient_handleFileReadRequest read request for frsmId: %i\n", frsmId);
@@ -232,7 +184,7 @@ mmsClient_handleFileCloseRequest(
uint32_t invokeId,
ByteBuffer* response)
{
- int32_t frsmId = (int32_t) BerDecoder_decodeUint32(buffer, maxBufPos - bufPos, bufPos);
+ int32_t frsmId = BerDecoder_decodeInt32(buffer, maxBufPos - bufPos, bufPos);
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
@@ -252,13 +204,13 @@ mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const ch
uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId);
uint32_t fileNameStringSize = strlen(fileName);
- uint32_t fileNameSize = 1+ BerEncoder_determineLengthSize(fileNameStringSize) + fileNameStringSize;
+ uint32_t fileNameSize = 1 + BerEncoder_determineLengthSize(fileNameStringSize) + fileNameStringSize;
uint32_t fileNameSeqSize = fileNameSize;
- uint32_t fileOpenRequestSize = fileNameSeqSize + 2 + BerEncoder_UInt32determineEncodedSize(initialPosition) + 2;
+ uint32_t fileOpenRequestSize = 1 + BerEncoder_determineLengthSize(fileNameSeqSize) + fileNameSeqSize + 2 + BerEncoder_UInt32determineEncodedSize(initialPosition);
- uint32_t confirmedRequestPduSize = 1 + 2 + 2 + invokeIdSize + fileOpenRequestSize;
+ uint32_t confirmedRequestPduSize = 2 + invokeIdSize + 2 + BerEncoder_determineLengthSize(fileOpenRequestSize) + fileOpenRequestSize;
int bufPos = 0;
uint8_t* buffer = request->buffer;
@@ -271,9 +223,10 @@ mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const ch
buffer[bufPos++] = 0xbf;
buffer[bufPos++] = 0x48;
bufPos = BerEncoder_encodeLength(fileOpenRequestSize, buffer, bufPos);
- bufPos = BerEncoder_encodeTL(0xa0, fileNameSeqSize, buffer, bufPos);
+ bufPos = BerEncoder_encodeTL(0xa0, fileNameSeqSize, buffer, bufPos);
bufPos = BerEncoder_encodeOctetString(0x19, (uint8_t*) fileName, fileNameStringSize, buffer, bufPos);
+
bufPos = BerEncoder_encodeUInt32WithTL(0x81, initialPosition, buffer, bufPos);
request->size = bufPos;
@@ -287,11 +240,9 @@ mmsClient_createFileDeleteRequest(uint32_t invokeId, ByteBuffer* request, const
uint32_t fileNameStringSize = strlen(fileName);
uint32_t fileNameSize = 1 + BerEncoder_determineLengthSize(fileNameStringSize) + fileNameStringSize;
- uint32_t fileNameSeqSize = fileNameSize;
-
- uint32_t fileDeleteRequestSize = fileNameSeqSize; // + 2;
+ uint32_t fileDeleteRequestSize = fileNameSize;
- uint32_t confirmedRequestPduSize = 1 + 2 + 2 + invokeIdSize + fileDeleteRequestSize;
+ uint32_t confirmedRequestPduSize = 1 + 2 + invokeIdSize + 1 + BerEncoder_determineLengthSize(fileDeleteRequestSize) + fileDeleteRequestSize;
int bufPos = 0;
uint8_t* buffer = request->buffer;
@@ -364,7 +315,7 @@ mmsClient_createFileDirectoryRequest(uint32_t invokeId, ByteBuffer* request, con
{
uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId);
- uint32_t confirmedRequestPduSize = 1 + 2 + 2 + invokeIdSize + 0;
+ uint32_t confirmedRequestPduSize = 1 + 2 + 1 + invokeIdSize;
uint32_t parameterSize = 0;
@@ -374,7 +325,7 @@ mmsClient_createFileDirectoryRequest(uint32_t invokeId, ByteBuffer* request, con
if (continueAfter)
parameterSize += encodeFileSpecification(0xa1, continueAfter, NULL, 0);
- confirmedRequestPduSize += parameterSize;
+ confirmedRequestPduSize += BerEncoder_determineLengthSize(parameterSize) + parameterSize;
int bufPos = 0;
uint8_t* buffer = request->buffer;
@@ -403,15 +354,13 @@ mmsClient_createFileRenameRequest(uint32_t invokeId, ByteBuffer* request, const
{
uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId);
- uint32_t confirmedRequestPduSize = 1 + 2 + 2 + invokeIdSize;
-
uint32_t parameterSize = 0;
parameterSize += encodeFileSpecification(0xa0, currentFileName, NULL, 0);
parameterSize += encodeFileSpecification(0xa1, newFileName, NULL, 0);
- confirmedRequestPduSize += parameterSize;
+ uint32_t confirmedRequestPduSize = 2 + invokeIdSize + 2 + BerEncoder_determineLengthSize(parameterSize) + parameterSize;
int bufPos = 0;
uint8_t* buffer = request->buffer;
@@ -437,15 +386,13 @@ mmsClient_createObtainFileRequest(uint32_t invokeId, ByteBuffer* request, const
{
uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId);
- uint32_t confirmedRequestPduSize = 1 + 2 + 2 + invokeIdSize;
-
uint32_t parameterSize = 0;
parameterSize += encodeFileSpecification(0xa0, sourceFile, NULL, 0);
parameterSize += encodeFileSpecification(0xa1, destinationFile, NULL, 0);
- confirmedRequestPduSize += parameterSize;
+ uint32_t confirmedRequestPduSize = 2 + invokeIdSize + 2 + BerEncoder_determineLengthSize(parameterSize) + parameterSize;
int bufPos = 0;
uint8_t* buffer = request->buffer;
@@ -698,7 +645,7 @@ mmsMsg_parseFileOpenResponse(uint8_t* buffer, int bufPos, int maxBufPos, int32_t
switch (tag) {
case 0x80: /* frsmId */
- *frsmId = (int32_t) BerDecoder_decodeUint32(buffer, length, bufPos);
+ *frsmId = BerDecoder_decodeInt32(buffer, length, bufPos);
bufPos += length;
break;
diff --git a/src/mms/iso_mms/client/mms_client_get_var_access.c b/src/mms/iso_mms/client/mms_client_get_var_access.c
index d4104af4..af926022 100644
--- a/src/mms/iso_mms/client/mms_client_get_var_access.c
+++ b/src/mms/iso_mms/client/mms_client_get_var_access.c
@@ -179,22 +179,35 @@ mmsClient_createGetVariableAccessAttributesRequest(
request->present = GetVariableAccessAttributesRequest_PR_name;
- request->choice.name.present = ObjectName_PR_domainspecific;
+ if (domainId != NULL) {
+ request->choice.name.present = ObjectName_PR_domainspecific;
- request->choice.name.choice.domainspecific.domainId.buf = (uint8_t*) domainId;
- request->choice.name.choice.domainspecific.domainId.size = strlen(domainId);
- request->choice.name.choice.domainspecific.itemId.buf = (uint8_t*) itemId;
- request->choice.name.choice.domainspecific.itemId.size = strlen(itemId);
+ request->choice.name.choice.domainspecific.domainId.buf = (uint8_t*) domainId;
+ request->choice.name.choice.domainspecific.domainId.size = strlen(domainId);
+ request->choice.name.choice.domainspecific.itemId.buf = (uint8_t*) itemId;
+ request->choice.name.choice.domainspecific.itemId.size = strlen(itemId);
+ }
+ else {
+ request->choice.name.present = ObjectName_PR_vmdspecific;
+ request->choice.name.choice.vmdspecific.buf = (uint8_t*) itemId;
+ request->choice.name.choice.vmdspecific.size = strlen(itemId);
+ }
asn_enc_rval_t rval;
rval = der_encode(&asn_DEF_MmsPdu, mmsPdu,
(asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer);
- request->choice.name.choice.domainspecific.domainId.buf = 0;
- request->choice.name.choice.domainspecific.domainId.size = 0;
- request->choice.name.choice.domainspecific.itemId.buf = 0;
- request->choice.name.choice.domainspecific.itemId.size = 0;
+ if (domainId != NULL) {
+ request->choice.name.choice.domainspecific.domainId.buf = 0;
+ request->choice.name.choice.domainspecific.domainId.size = 0;
+ request->choice.name.choice.domainspecific.itemId.buf = 0;
+ request->choice.name.choice.domainspecific.itemId.size = 0;
+ }
+ else {
+ request->choice.name.choice.vmdspecific.buf = 0;
+ request->choice.name.choice.vmdspecific.size = 0;
+ }
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
diff --git a/src/mms/iso_mms/client/mms_client_initiate.c b/src/mms/iso_mms/client/mms_client_initiate.c
index e8c7d7d4..5cf93b43 100644
--- a/src/mms/iso_mms/client/mms_client_initiate.c
+++ b/src/mms/iso_mms/client/mms_client_initiate.c
@@ -1,28 +1,27 @@
/*
* mms_client_initiate.c
*
- * Copyright 2013, 2014 Michael Zillgith
+ * Copyright 2013-2017 Michael Zillgith
*
- * This file is part of libIEC61850.
+ * 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 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.
+ * 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 .
+ * 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.
+ * See COPYING file for the complete license text.
*/
#include "libiec61850_platform_includes.h"
-#include
#include "mms_common.h"
#include "mms_common_internal.h"
#include "mms_indication.h"
@@ -33,63 +32,80 @@
#include "mms_client_internal.h"
+#include "ber_encoder.h"
+
/* servicesSupported = {GetNameList} - required by initiate request, other services are required by some servers to work properly */
static uint8_t servicesSupported[] = { 0xee, 0x1c, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x79, 0xef, 0x18 };
-static InitiateRequestPdu_t
-createInitiateRequestPdu(MmsConnection self)
+void
+mmsClient_createInitiateRequest(MmsConnection self, ByteBuffer* message)
{
- InitiateRequestPdu_t request;
+ int maxServerOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+ int maxServerOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ int dataStructureNestingLevel = DEFAULT_DATA_STRUCTURE_NESTING_LEVEL;
- request.localDetailCalling = (Integer32_t*) GLOBAL_CALLOC(1, sizeof(Integer32_t));
- *(request.localDetailCalling) = self->parameters.maxPduSize;
+ uint32_t localDetailSize =
+ BerEncoder_UInt32determineEncodedSize(self->parameters.maxPduSize);
- request.proposedMaxServOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
- request.proposedMaxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+ uint32_t proposedMaxServerOutstandingCallingSize =
+ BerEncoder_UInt32determineEncodedSize(maxServerOutstandingCalling);
- request.proposedDataStructureNestingLevel = (Integer8_t*) GLOBAL_CALLOC(1, sizeof(Integer8_t));
- *(request.proposedDataStructureNestingLevel) = DEFAULT_DATA_STRUCTURE_NESTING_LEVEL;
+ uint32_t proposedMaxServerOutstandingCalledSize =
+ BerEncoder_UInt32determineEncodedSize(maxServerOutstandingCalled);
- request.mmsInitRequestDetail.proposedParameterCBB.size = 2;
- request.mmsInitRequestDetail.proposedParameterCBB.bits_unused = 5;
- request.mmsInitRequestDetail.proposedParameterCBB.buf = (uint8_t*) GLOBAL_CALLOC(2, sizeof(uint8_t));
- request.mmsInitRequestDetail.proposedParameterCBB.buf[0] = 0xf1;
- request.mmsInitRequestDetail.proposedParameterCBB.buf[1] = 0x00;
+ uint32_t dataStructureNestingLevelSize =
+ BerEncoder_UInt32determineEncodedSize(dataStructureNestingLevel);
- request.mmsInitRequestDetail.proposedVersionNumber = 1;
+ uint32_t initRequestDetailSize = 3 + 5 + 14;
- request.mmsInitRequestDetail.servicesSupportedCalling.size = 11;
- request.mmsInitRequestDetail.servicesSupportedCalling.bits_unused = 3;
+ uint32_t initiateRequestPduSize = 2 + localDetailSize +
+ 2 + proposedMaxServerOutstandingCallingSize +
+ 2 + proposedMaxServerOutstandingCalledSize +
+ 2 + dataStructureNestingLevelSize +
+ 2 + initRequestDetailSize;
- request.mmsInitRequestDetail.servicesSupportedCalling.buf = servicesSupported;
+ /* encode message (InitiateRequestPdu) */
- return request;
-}
+ int bufPos = 0;
+ uint8_t* buffer = message->buffer;
-static void
-freeInitiateRequestPdu(InitiateRequestPdu_t request)
-{
- GLOBAL_FREEMEM(request.localDetailCalling);
- GLOBAL_FREEMEM(request.proposedDataStructureNestingLevel);
- GLOBAL_FREEMEM(request.mmsInitRequestDetail.proposedParameterCBB.buf);
-}
+ bufPos = BerEncoder_encodeTL(0xa8, initiateRequestPduSize, buffer, bufPos);
-int
-mmsClient_createInitiateRequest(MmsConnection self, ByteBuffer* message)
-{
- MmsPdu_t* mmsPdu = (MmsPdu_t*) GLOBAL_CALLOC(1, sizeof(MmsPdu_t));
+ /* localDetail */
+ bufPos = BerEncoder_encodeTL(0x80, localDetailSize, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(self->parameters.maxPduSize, buffer, bufPos);
+
+ /* proposedMaxServerOutstandingCalling */
+ bufPos = BerEncoder_encodeTL(0x81, proposedMaxServerOutstandingCallingSize, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(maxServerOutstandingCalling, buffer, bufPos);
- mmsPdu->present = MmsPdu_PR_initiateRequestPdu;
+ /* proposedMaxServerOutstandingCalled */
+ bufPos = BerEncoder_encodeTL(0x82, proposedMaxServerOutstandingCalledSize, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(maxServerOutstandingCalled, buffer, bufPos);
- mmsPdu->choice.initiateRequestPdu = createInitiateRequestPdu(self);
+ /* proposedDataStructureNestingLevel */
+ bufPos = BerEncoder_encodeTL(0x83, dataStructureNestingLevelSize, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(dataStructureNestingLevel, buffer, bufPos);
- asn_enc_rval_t rval = der_encode(&asn_DEF_MmsPdu, mmsPdu,
- (asn_app_consume_bytes_f*) mmsClient_write_out, (void*) message);
+ /* initRequestDetail */
+ bufPos = BerEncoder_encodeTL(0xa4, initRequestDetailSize, buffer, bufPos);
- freeInitiateRequestPdu(mmsPdu->choice.initiateRequestPdu);
- GLOBAL_FREEMEM(mmsPdu);
+ /* proposedVersionNumber = 1 */
+ buffer[bufPos++] = 0x80;
+ buffer[bufPos++] = 0x01;
+ buffer[bufPos++] = 0x01;
- return rval.encoded;
+ /* proposedParameterCBC */
+ buffer[bufPos++] = 0x81;
+ buffer[bufPos++] = 0x03;
+ buffer[bufPos++] = 0x05; /* padding */
+ buffer[bufPos++] = 0xf1;
+ buffer[bufPos++] = 0x00;
+
+ /* servicesSupportedCalling */
+ bufPos = BerEncoder_encodeBitString(0x82, 85, servicesSupported, buffer, bufPos);
+
+ message->size = bufPos;
}
int
@@ -105,43 +121,112 @@ mmsClient_createConcludeRequest(MmsConnection self, ByteBuffer* message)
return -1;
}
+static bool
+parseInitResponseDetail(MmsConnection self, uint8_t* buffer, int bufPos, int maxBufPos)
+{
+ while (bufPos < maxBufPos) {
+ uint8_t tag = buffer[bufPos++];
+ int length;
+
+ bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
+
+ if (bufPos < 0)
+ return false;
+
+ switch (tag) {
+
+ case 0x80: /* negotiated protocol version */
+ break;
+
+ case 0x81: /* parameter CBB */
+ break;
+
+ case 0x82: /* services supported called */
+ {
+ int i;
+
+ for (i = 0; i < 11; i++)
+ self->parameters.servicesSupported[i] = buffer[bufPos + i];
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ bufPos += length;
+ }
+
+ return true;
+}
+
bool
mmsClient_parseInitiateResponse(MmsConnection self)
{
bool result = false;
- MmsPdu_t* mmsPdu = 0;
- asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu,
- (void**) &mmsPdu, ByteBuffer_getBuffer(self->lastResponse),
- ByteBuffer_getSize(self->lastResponse));
+ self->parameters.maxPduSize = CONFIG_MMS_MAXIMUM_PDU_SIZE;
+ self->parameters.dataStructureNestingLevel = DEFAULT_DATA_STRUCTURE_NESTING_LEVEL;
+ self->parameters.maxServOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+ self->parameters.maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
- if (rval.code != RC_OK) goto exit_function;
+ int bufPos = 0;
+ int maxBufPos = ByteBuffer_getSize(self->lastResponse);
+ uint8_t* buffer = ByteBuffer_getBuffer(self->lastResponse);
- if (mmsPdu->present == MmsPdu_PR_initiateResponsePdu) {
- InitiateResponsePdu_t* initiateResponse = &(mmsPdu->choice.initiateResponsePdu);
+ while (bufPos < maxBufPos) {
+ uint8_t tag = buffer[bufPos++];
+ int length;
- if (initiateResponse->localDetailCalled != NULL)
- self->parameters.maxPduSize = *(initiateResponse->localDetailCalled);
+ bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
- if (initiateResponse->negotiatedDataStructureNestingLevel != NULL)
- self->parameters.dataStructureNestingLevel = *(initiateResponse->negotiatedDataStructureNestingLevel);;
+ if (bufPos < 0) {
+ // TODO write initiate error PDU!
+ return false;
+ }
- self->parameters.maxServOutstandingCalled = initiateResponse->negotiatedMaxServOutstandingCalled;
+ switch (tag) {
+ case 0x80: /* local-detail-calling */
+ self->parameters.maxPduSize = BerDecoder_decodeUint32(buffer, length, bufPos);
- self->parameters.maxServOutstandingCalling = initiateResponse->negotiatedMaxServOutstandingCalling;
+ if (self->parameters.maxPduSize > CONFIG_MMS_MAXIMUM_PDU_SIZE)
+ self->parameters.maxPduSize = CONFIG_MMS_MAXIMUM_PDU_SIZE;
- int i;
+ break;
- for (i = 0; i < 11; i++)
- self->parameters.servicesSupported[i] = initiateResponse->mmsInitResponseDetail.servicesSupportedCalled.buf[i];
+ case 0x81: /* proposed-max-serv-outstanding-calling */
+ self->parameters.maxServOutstandingCalling = BerDecoder_decodeUint32(buffer, length, bufPos);
- result = true;
+ if (self->parameters.maxServOutstandingCalling > DEFAULT_MAX_SERV_OUTSTANDING_CALLING)
+ self->parameters.maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
+
+ break;
+
+ case 0x82: /* proposed-max-serv-outstanding-called */
+ self->parameters.maxServOutstandingCalled = BerDecoder_decodeUint32(buffer, length, bufPos);
+
+ if (self->parameters.maxServOutstandingCalled > DEFAULT_MAX_SERV_OUTSTANDING_CALLED)
+ self->parameters.maxServOutstandingCalled = DEFAULT_MAX_SERV_OUTSTANDING_CALLED;
+
+ break;
+ case 0x83: /* proposed-data-structure-nesting-level */
+ self->parameters.dataStructureNestingLevel = BerDecoder_decodeUint32(buffer, length, bufPos);
+ break;
+
+ case 0xa4: /* mms-init-request-detail */
+ {
+ if (parseInitResponseDetail(self, buffer, bufPos, bufPos + length) == false)
+ return false;
+ }
+ break;
+
+ default:
+ break; /* Ignore unknown tags */
+ }
+
+ bufPos += length;
}
- else
- result = false;
- asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
-exit_function:
return result;
}
diff --git a/src/mms/iso_mms/client/mms_client_journals.c b/src/mms/iso_mms/client/mms_client_journals.c
index 919e2c57..cf59685e 100644
--- a/src/mms/iso_mms/client/mms_client_journals.c
+++ b/src/mms/iso_mms/client/mms_client_journals.c
@@ -67,7 +67,7 @@ parseJournalVariable(uint8_t* buffer, int bufPos, int maxLength, MmsJournalVaria
case 0xa1: /* valueSpec */
if (journalVariable->value == NULL) {
- journalVariable->value = MmsValue_decodeMmsData(buffer, bufPos, length);
+ journalVariable->value = MmsValue_decodeMmsData(buffer, bufPos, length, NULL);
}
break;
diff --git a/src/mms/iso_mms/client/mms_client_named_variable_list.c b/src/mms/iso_mms/client/mms_client_named_variable_list.c
index e678388f..9714fd7e 100644
--- a/src/mms/iso_mms/client/mms_client_named_variable_list.c
+++ b/src/mms/iso_mms/client/mms_client_named_variable_list.c
@@ -35,45 +35,48 @@
void
mmsClient_createDeleteNamedVariableListRequest(long invokeId, ByteBuffer* writeBuffer,
- const char* domainId, const char* listNameId)
+ const char* domainId, const char* listNameId)
{
- MmsPdu_t* mmsPdu = mmsClient_createConfirmedRequestPdu(invokeId);
+ MmsPdu_t* mmsPdu = mmsClient_createConfirmedRequestPdu(invokeId);
- mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.present =
- ConfirmedServiceRequest_PR_deleteNamedVariableList;
+ mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.present =
+ ConfirmedServiceRequest_PR_deleteNamedVariableList;
- DeleteNamedVariableListRequest_t* request =
- &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.deleteNamedVariableList);
+ DeleteNamedVariableListRequest_t* request =
+ &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.deleteNamedVariableList);
- request->listOfVariableListName = (struct DeleteNamedVariableListRequest__listOfVariableListName*) GLOBAL_CALLOC(1,
- sizeof(struct DeleteNamedVariableListRequest__listOfVariableListName));
+ request->listOfVariableListName = (struct DeleteNamedVariableListRequest__listOfVariableListName*) GLOBAL_CALLOC(1,
+ sizeof(struct DeleteNamedVariableListRequest__listOfVariableListName));
- request->listOfVariableListName->list.count = 1;
- request->listOfVariableListName->list.size = 1;
+ request->listOfVariableListName->list.count = 1;
+ request->listOfVariableListName->list.size = 1;
- request->listOfVariableListName->list.array = (ObjectName_t**) GLOBAL_CALLOC(1, sizeof(ObjectName_t*));
- request->listOfVariableListName->list.array[0] = (ObjectName_t*) GLOBAL_CALLOC(1, sizeof(ObjectName_t));
+ request->listOfVariableListName->list.array = (ObjectName_t**) GLOBAL_CALLOC(1, sizeof(ObjectName_t*));
+ request->listOfVariableListName->list.array[0] = (ObjectName_t*) GLOBAL_CALLOC(1, sizeof(ObjectName_t));
- if (domainId != NULL) {
+ if (domainId != NULL) {
request->listOfVariableListName->list.array[0]->present = ObjectName_PR_domainspecific;
request->listOfVariableListName->list.array[0]->choice.domainspecific.domainId.size = strlen(domainId);
- request->listOfVariableListName->list.array[0]->choice.domainspecific.domainId.buf = (uint8_t*) StringUtils_copyString(domainId);
+ request->listOfVariableListName->list.array[0]->choice.domainspecific.domainId.buf =
+ (uint8_t*) StringUtils_copyString(domainId);
request->listOfVariableListName->list.array[0]->choice.domainspecific.itemId.size = strlen(listNameId);
- request->listOfVariableListName->list.array[0]->choice.domainspecific.itemId.buf = (uint8_t*) StringUtils_copyString(listNameId);
- }
- else {
- request->listOfVariableListName->list.array[0]->present = ObjectName_PR_vmdspecific;
- request->listOfVariableListName->list.array[0]->choice.vmdspecific.size = strlen(listNameId);
- request->listOfVariableListName->list.array[0]->choice.vmdspecific.buf = (uint8_t*) StringUtils_copyString(listNameId);
- }
-
- request->scopeOfDelete = (INTEGER_t*) GLOBAL_CALLOC(1, sizeof(INTEGER_t));
- asn_long2INTEGER(request->scopeOfDelete, DeleteNamedVariableListRequest__scopeOfDelete_specific);
+ request->listOfVariableListName->list.array[0]->choice.domainspecific.itemId.buf =
+ (uint8_t*) StringUtils_copyString(listNameId);
+ }
+ else {
+ request->listOfVariableListName->list.array[0]->present = ObjectName_PR_vmdspecific;
+ request->listOfVariableListName->list.array[0]->choice.vmdspecific.size = strlen(listNameId);
+ request->listOfVariableListName->list.array[0]->choice.vmdspecific.buf =
+ (uint8_t*) StringUtils_copyString(listNameId);
+ }
+
+ request->scopeOfDelete = (INTEGER_t*) GLOBAL_CALLOC(1, sizeof(INTEGER_t));
+ asn_long2INTEGER(request->scopeOfDelete, DeleteNamedVariableListRequest__scopeOfDelete_specific);
der_encode(&asn_DEF_MmsPdu, mmsPdu,
- (asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer);
+ (asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer);
- asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
+ asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
}
void
@@ -220,11 +223,25 @@ parseNamedVariableAttributes(GetNamedVariableListAttributesResponse_t* response,
LinkedList attributes = LinkedList_create();
for (i = 0; i < attributesCount; i++) {
- char* domainId = mmsMsg_createStringFromAsnIdentifier(response->listOfVariable.list.array[i]->
+
+ char* domainId;
+ char* itemId;
+
+
+ if (response->listOfVariable.list.array[i]->variableSpecification.choice.name.present == ObjectName_PR_vmdspecific) {
+
+ domainId = NULL;
+
+ itemId = mmsMsg_createStringFromAsnIdentifier(response->listOfVariable.list.array[i]->
+ variableSpecification.choice.name.choice.vmdspecific);
+ }
+ else {
+ domainId = mmsMsg_createStringFromAsnIdentifier(response->listOfVariable.list.array[i]->
variableSpecification.choice.name.choice.domainspecific.domainId);
- char* itemId = mmsMsg_createStringFromAsnIdentifier(response->listOfVariable.list.array[i]->
+ itemId = mmsMsg_createStringFromAsnIdentifier(response->listOfVariable.list.array[i]->
variableSpecification.choice.name.choice.domainspecific.itemId);
+ }
MmsVariableAccessSpecification* listEntry = MmsVariableAccessSpecification_create(domainId, itemId);
diff --git a/src/mms/iso_mms/client/mms_client_write.c b/src/mms/iso_mms/client/mms_client_write.c
index 8163cdd8..ed0c6665 100644
--- a/src/mms/iso_mms/client/mms_client_write.c
+++ b/src/mms/iso_mms/client/mms_client_write.c
@@ -87,7 +87,8 @@ mmsClient_parseWriteMultipleItemsResponse(ByteBuffer* message, int32_t bufPos, M
return;
}
- *accessResults = LinkedList_create();
+ if (accessResults != NULL)
+ *accessResults = LinkedList_create();
int endPos = bufPos + length;
@@ -101,17 +102,16 @@ mmsClient_parseWriteMultipleItemsResponse(ByteBuffer* message, int32_t bufPos, M
if (bufPos == -1) goto exit_with_error;
if (tag == 0x81) {
- MmsValue* value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_SUCCESS);
- LinkedList_add(*accessResults, (void*) value);
+ if (accessResults != NULL)
+ LinkedList_add(*accessResults, (void*) MmsValue_newDataAccessError(DATA_ACCESS_ERROR_SUCCESS));
}
if (tag == 0x80) {
uint32_t dataAccessErrorCode =
BerDecoder_decodeUint32(buf, length, bufPos);
- MmsValue* value = MmsValue_newDataAccessError((MmsDataAccessError) dataAccessErrorCode);
-
- LinkedList_add(*accessResults, (void*) value);
+ if (accessResults != NULL)
+ LinkedList_add(*accessResults, (void*) MmsValue_newDataAccessError((MmsDataAccessError) dataAccessErrorCode));
}
bufPos += length;
@@ -129,13 +129,17 @@ mmsClient_parseWriteMultipleItemsResponse(ByteBuffer* message, int32_t bufPos, M
exit_with_error:
*mmsError = MMS_ERROR_PARSING_RESPONSE;
- LinkedList_destroyDeep(*accessResults, (LinkedListValueDeleteFunction) MmsValue_delete);
+
+ if (accessResults != NULL)
+ LinkedList_destroyDeep(*accessResults, (LinkedListValueDeleteFunction) MmsValue_delete);
}
-void
+MmsDataAccessError
mmsClient_parseWriteResponse(ByteBuffer* message, int32_t bufPos, MmsError* mmsError)
{
+ MmsDataAccessError retVal = DATA_ACCESS_ERROR_UNKNOWN;
+
uint8_t* buf = message->buffer;
int size = message->size;
@@ -151,13 +155,16 @@ mmsClient_parseWriteResponse(ByteBuffer* message, int32_t bufPos, MmsError* mmsE
if (bufPos == -1) {
*mmsError = MMS_ERROR_PARSING_RESPONSE;
- return;
+ retVal = DATA_ACCESS_ERROR_UNKNOWN;
+ goto exit_function;
}
tag = buf[bufPos++];
- if (tag == 0x81)
- return;
+ if (tag == 0x81) {
+ retVal = DATA_ACCESS_ERROR_SUCCESS;
+ goto exit_function;
+ }
if (tag == 0x80) {
bufPos = BerDecoder_decodeLength(buf, &length, bufPos, size);
@@ -165,26 +172,104 @@ mmsClient_parseWriteResponse(ByteBuffer* message, int32_t bufPos, MmsError* mmsE
uint32_t dataAccessErrorCode =
BerDecoder_decodeUint32(buf, length, bufPos);
- *mmsError = mapDataAccessErrorToMmsError(dataAccessErrorCode);
+ if (dataAccessErrorCode < 13) {
+ *mmsError = mapDataAccessErrorToMmsError(dataAccessErrorCode);
+ retVal = (MmsDataAccessError) dataAccessErrorCode;
+ }
+ else {
+ *mmsError = MMS_ERROR_PARSING_RESPONSE;
+ retVal = DATA_ACCESS_ERROR_UNKNOWN;
+ }
}
}
else
*mmsError = MMS_ERROR_PARSING_RESPONSE;
+
+exit_function:
+ return retVal;
+}
+
+//TODO remove redundant code (see mms_client_read.c)
+
+static AlternateAccess_t*
+createAlternateAccess(uint32_t index, uint32_t elementCount)
+{
+ AlternateAccess_t* alternateAccess = (AlternateAccess_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccess_t));
+ alternateAccess->list.count = 1;
+ alternateAccess->list.array = (struct AlternateAccess__Member**) GLOBAL_CALLOC(1, sizeof(struct AlternateAccess__Member*));
+ alternateAccess->list.array[0] = (struct AlternateAccess__Member*) GLOBAL_CALLOC(1, sizeof(struct AlternateAccess__Member));
+ alternateAccess->list.array[0]->present = AlternateAccess__Member_PR_unnamed;
+
+ alternateAccess->list.array[0]->choice.unnamed = (AlternateAccessSelection_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccessSelection_t));
+
+ alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAccess;
+
+ if (elementCount > 0) {
+ alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present =
+ AlternateAccessSelection__selectAccess_PR_indexRange;
+
+ INTEGER_t* asnIndex =
+ &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.lowIndex);
+
+ asn_long2INTEGER(asnIndex, index);
+
+ asnIndex =
+ &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.numberOfElements);
+
+ asn_long2INTEGER(asnIndex, elementCount);
+ }
+ else {
+ alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present =
+ AlternateAccessSelection__selectAccess_PR_index;
+
+ INTEGER_t* asnIndex =
+ &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index);
+
+ asn_long2INTEGER(asnIndex, index);
+ }
+
+ return alternateAccess;
}
-static VariableSpecification_t*
+static void
+deleteAlternateAccess(AlternateAccess_t* alternateAccess)
+{
+ if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.lowIndex.buf != NULL) {
+ GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.lowIndex.buf);
+ alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.lowIndex.buf = NULL;
+ }
+
+ if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.numberOfElements.buf != NULL) {
+ GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.numberOfElements.buf);
+ alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.indexRange.numberOfElements.buf = NULL;
+ }
+
+ if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index.buf != NULL) {
+ GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index.buf);
+ alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index.buf = NULL;
+ }
+
+ GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed);
+ GLOBAL_FREEMEM(alternateAccess->list.array[0]);
+ GLOBAL_FREEMEM(alternateAccess->list.array);
+ GLOBAL_FREEMEM(alternateAccess);
+
+}
+
+
+static ListOfVariableSeq_t*
createNewDomainVariableSpecification(const char* domainId, const char* itemId)
{
- VariableSpecification_t* varSpec = (VariableSpecification_t*) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t));
+ ListOfVariableSeq_t* varSpec = (ListOfVariableSeq_t*) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t));
- varSpec->present = VariableSpecification_PR_name;
- varSpec->choice.name.present = ObjectName_PR_domainspecific;
- varSpec->choice.name.choice.domainspecific.domainId.buf = (uint8_t*) domainId;
- varSpec->choice.name.choice.domainspecific.domainId.size = strlen(domainId);
- varSpec->choice.name.choice.domainspecific.itemId.buf = (uint8_t*) itemId;
- varSpec->choice.name.choice.domainspecific.itemId.size = strlen(itemId);
+ varSpec->variableSpecification.present = VariableSpecification_PR_name;
+ varSpec->variableSpecification.choice.name.present = ObjectName_PR_domainspecific;
+ varSpec->variableSpecification.choice.name.choice.domainspecific.domainId.buf = (uint8_t*) domainId;
+ varSpec->variableSpecification.choice.name.choice.domainspecific.domainId.size = strlen(domainId);
+ varSpec->variableSpecification.choice.name.choice.domainspecific.itemId.buf = (uint8_t*) itemId;
+ varSpec->variableSpecification.choice.name.choice.domainspecific.itemId.size = strlen(itemId);
- return varSpec;
+ return varSpec;
}
static void
@@ -262,7 +347,7 @@ mmsClient_createWriteMultipleItemsRequest(uint32_t invokeId, const char* domainI
char* itemId = (char*) item->data;
MmsValue* value = (MmsValue*) valueElement->data;
- request->variableAccessSpecification.choice.listOfVariable.list.array[i] = (ListOfVariableSeq_t*)
+ request->variableAccessSpecification.choice.listOfVariable.list.array[i] =
createNewDomainVariableSpecification(domainId, itemId);
request->listOfData.list.array[i] = mmsMsg_createBasicDataElement(value);
@@ -314,7 +399,7 @@ mmsClient_createWriteRequest(uint32_t invokeId, const char* domainId, const char
request->variableAccessSpecification.choice.listOfVariable.list.size = 1;
request->variableAccessSpecification.choice.listOfVariable.list.array =
(ListOfVariableSeq_t**) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t*));
- request->variableAccessSpecification.choice.listOfVariable.list.array[0] = (ListOfVariableSeq_t*)
+ request->variableAccessSpecification.choice.listOfVariable.list.array[0] =
createNewDomainVariableSpecification(domainId, itemId);
/* Create list of typed data values */
@@ -346,3 +431,157 @@ mmsClient_createWriteRequest(uint32_t invokeId, const char* domainId, const char
return rval.encoded;
}
+
+/**
+ * \brief Encode request to write a named variable list (SetDataSet)
+ *
+ * The named variable list can be
+ * - VMD specific (domainId = NULL and isAssociationSpecific = false)
+ * - Domain specific (domainID != NULL and isAssociationSpecific = false)
+ * - association specific (isAssociationSpecific = true, domainId will be ignored)
+ *
+ * \param invokeId invoke ID of the new request
+ * \param isAssociationSpecific true = create an association specific request, false = create domain of VMD specific request
+ * \param domainId name of the MMS domain or NULL for association of VMD specific request
+ * \param itemId named variable list name
+ * \param values the list of the named variable list element values
+ * \param writeBuffer the buffer to write the request
+ *
+ * \return number of bytes encoded
+ */
+int
+mmsClient_createWriteRequestNamedVariableList(uint32_t invokeId, bool isAssociationSpecific, const char* domainId, const char* itemId,
+ LinkedList values, ByteBuffer* writeBuffer)
+{
+ MmsPdu_t* mmsPdu = mmsClient_createConfirmedRequestPdu(invokeId);
+
+ mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.present =
+ ConfirmedServiceRequest_PR_write;
+ WriteRequest_t* request =
+ &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.write);
+
+ /* Create list of variable specifications */
+ request->variableAccessSpecification.present = VariableAccessSpecification_PR_variableListName;
+
+ if (isAssociationSpecific) {
+ request->variableAccessSpecification.choice.variableListName.present = ObjectName_PR_aaspecific;
+ request->variableAccessSpecification.choice.variableListName.choice.aaspecific.buf = (uint8_t*) StringUtils_copyString(itemId);
+ request->variableAccessSpecification.choice.variableListName.choice.aaspecific.size = strlen(itemId);
+ }
+ else {
+ if (domainId != NULL) {
+ request->variableAccessSpecification.choice.variableListName.present = ObjectName_PR_domainspecific;
+ request->variableAccessSpecification.choice.variableListName.choice.domainspecific.domainId.buf = (uint8_t*) StringUtils_copyString(domainId);
+ request->variableAccessSpecification.choice.variableListName.choice.domainspecific.domainId.size = strlen(domainId);
+ request->variableAccessSpecification.choice.variableListName.choice.domainspecific.itemId.buf = (uint8_t*) StringUtils_copyString(itemId);
+ request->variableAccessSpecification.choice.variableListName.choice.domainspecific.itemId.size = strlen(itemId);
+ }
+ else {
+ request->variableAccessSpecification.choice.variableListName.present = ObjectName_PR_vmdspecific;
+ request->variableAccessSpecification.choice.variableListName.choice.vmdspecific.buf = (uint8_t*) StringUtils_copyString(itemId);
+ request->variableAccessSpecification.choice.variableListName.choice.vmdspecific.size = strlen(itemId);
+ }
+ }
+
+ /* Create list of typed data values */
+
+ int numberOfItems = LinkedList_size(values);
+
+ request->listOfData.list.count = numberOfItems;
+ request->listOfData.list.size = numberOfItems;
+ request->listOfData.list.array = (Data_t**) GLOBAL_CALLOC(numberOfItems, sizeof(struct Data*));
+
+ int i;
+
+ LinkedList valueElement = LinkedList_getNext(values);
+
+ for (i = 0; i < numberOfItems; i++) {
+
+ if (valueElement == NULL) return -1;
+
+ MmsValue* value = (MmsValue*) valueElement->data;
+
+ request->listOfData.list.array[i] = mmsMsg_createBasicDataElement(value);
+
+ valueElement = LinkedList_getNext(valueElement);
+ }
+
+ /* Encode complete ASN1 structure */
+
+ asn_enc_rval_t rval;
+
+ rval = der_encode(&asn_DEF_MmsPdu, mmsPdu,
+ (asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer);
+
+ /* Free ASN structure */
+
+ for (i = 0; i < numberOfItems; i++)
+ deleteDataElement(request->listOfData.list.array[i]);
+
+ request->listOfData.list.count = 0;
+ GLOBAL_FREEMEM(request->listOfData.list.array);
+ request->listOfData.list.array = 0;
+
+ asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
+
+ return rval.encoded;
+}
+
+int
+mmsClient_createWriteRequestArray(uint32_t invokeId, const char* domainId, const char* itemId,
+ int startIndex, int elementCount,
+ MmsValue* value,
+ ByteBuffer* writeBuffer)
+{
+ MmsPdu_t* mmsPdu = mmsClient_createConfirmedRequestPdu(invokeId);
+
+ mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.present =
+ ConfirmedServiceRequest_PR_write;
+ WriteRequest_t* request =
+ &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.write);
+
+ /* Create list of variable specifications */
+ request->variableAccessSpecification.present = VariableAccessSpecification_PR_listOfVariable;
+ request->variableAccessSpecification.choice.listOfVariable.list.count = 1;
+ request->variableAccessSpecification.choice.listOfVariable.list.size = 1;
+ request->variableAccessSpecification.choice.listOfVariable.list.array =
+ (ListOfVariableSeq_t**) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t*));
+
+ ListOfVariableSeq_t* variableIdentifier = createNewDomainVariableSpecification(domainId, itemId);
+ variableIdentifier->alternateAccess = createAlternateAccess(startIndex, elementCount);
+ request->variableAccessSpecification.choice.listOfVariable.list.array[0] = variableIdentifier;
+
+ /* Create list of typed data values */
+ request->listOfData.list.count = 1;
+ request->listOfData.list.size = 1;
+ request->listOfData.list.array = (Data_t**) GLOBAL_CALLOC(1, sizeof(struct Data*));
+ request->listOfData.list.array[0] = mmsMsg_createBasicDataElement(value);
+
+ /* Encode complete ASN1 structure */
+
+ asn_enc_rval_t rval;
+
+ rval = der_encode(&asn_DEF_MmsPdu, mmsPdu,
+ (asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer);
+
+ /* Free ASN structure */
+ deleteAlternateAccess(variableIdentifier->alternateAccess);
+
+ request->variableAccessSpecification.choice.listOfVariable.list.count = 0;
+
+ GLOBAL_FREEMEM(request->variableAccessSpecification.choice.listOfVariable.list.array[0]);
+ GLOBAL_FREEMEM(request->variableAccessSpecification.choice.listOfVariable.list.array);
+ request->variableAccessSpecification.choice.listOfVariable.list.array = 0;
+
+
+ request->listOfData.list.count = 0;
+
+ deleteDataElement(request->listOfData.list.array[0]);
+
+ GLOBAL_FREEMEM(request->listOfData.list.array);
+ request->listOfData.list.array = 0;
+
+ asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
+
+ return rval.encoded;
+}
diff --git a/src/mms/iso_mms/common/mms_common_msg.c b/src/mms/iso_mms/common/mms_common_msg.c
index 36bdd7ef..75443e72 100644
--- a/src/mms/iso_mms/common/mms_common_msg.c
+++ b/src/mms/iso_mms/common/mms_common_msg.c
@@ -1,7 +1,7 @@
/*
* mms_common_msg.c
*
- * Copyright 2013 Michael Zillgith
+ * Copyright 2013 - 2017 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -25,6 +25,7 @@
#include "mms_common_internal.h"
#include "stack_config.h"
#include "mms_value_internal.h"
+#include "ber_decode.h"
static void
mmsMsg_createFloatData(MmsValue* value, int* size, uint8_t** buf)
@@ -342,3 +343,76 @@ mmsMsg_copyAsn1IdentifierToStringBuffer(Identifier_t identifier, char* buffer, i
buffer[0] = 0;
}
}
+
+void
+mmsMsg_createExtendedFilename(const char* basepath, char* extendedFileName, char* fileName)
+{
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ // strncpy(extendedFileName, MmsServerConnection_getFilesystemBasepath(self), 512);
+ strncpy(extendedFileName, basepath, 512);
+ strncat(extendedFileName, fileName, 512);
+#else
+ strcpy(extendedFileName, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
+ strncat(extendedFileName, fileName, sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256);
+#endif
+}
+
+
+
+FileHandle
+mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite)
+{
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char extendedFileName[512];
+#else
+ char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
+#endif
+
+ mmsMsg_createExtendedFilename(basepath, extendedFileName, fileName);
+
+ return FileSystem_openFile(extendedFileName, readWrite);
+}
+
+
+bool
+mmsMsg_parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response)
+{
+ if (*bufPos == maxBufPos)
+ return false;
+
+ uint8_t tag = buffer[(*bufPos)++];
+
+ if (tag != 0x19) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ return false;
+ }
+
+ int length;
+
+ *bufPos = BerDecoder_decodeLength(buffer, &length, *bufPos, maxBufPos);
+
+ if (*bufPos < 0) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ return false;
+ }
+
+ if (length > 255) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
+ return false;
+ }
+
+ memcpy(filename, buffer + *bufPos, length);
+ filename[length] = 0;
+ *bufPos += length;
+
+ /* Check if path contains invalid characters (prevent escaping the virtual filestore by using "..")
+ * TODO this may be platform dependent. Also depending of the platform there might be other evil
+ * characters.
+ */
+ if (strstr(filename, "..") != NULL) {
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILENAME_SYNTAX_ERROR);
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/mms/iso_mms/common/mms_type_spec.c b/src/mms/iso_mms/common/mms_type_spec.c
index 3d3ea1f4..95f17ba9 100644
--- a/src/mms/iso_mms/common/mms_type_spec.c
+++ b/src/mms/iso_mms/common/mms_type_spec.c
@@ -95,6 +95,64 @@ MmsVariableSpecification_getType(MmsVariableSpecification* self)
return self->type;
}
+bool
+MmsVariableSpecification_isValueOfType(MmsVariableSpecification* self, MmsValue* value)
+{
+ if ((self->type) == (value->type)) {
+
+ if ((self->type == MMS_STRUCTURE) || (self->type == MMS_ARRAY)) {
+
+ int componentCount = self->typeSpec.structure.elementCount;
+
+ if (componentCount != (int) MmsValue_getArraySize(value))
+ return false;
+
+ if (self->type == MMS_STRUCTURE) {
+
+ int i;
+ for (i = 0; i < componentCount; i++) {
+
+ if (MmsVariableSpecification_isValueOfType(self->typeSpec.structure.elements[i], MmsValue_getElement(value, i)) == false)
+ return false;
+ }
+
+ return true;
+ }
+ else {
+ int i;
+ for (i = 0; i < componentCount; i++) {
+
+ if (MmsVariableSpecification_isValueOfType(self->typeSpec.array.elementTypeSpec, MmsValue_getElement(value, i)) == false)
+ return false;
+ }
+ }
+ }
+ else if (self->type == MMS_BIT_STRING) {
+ if (self->typeSpec.bitString == value->value.bitString.size)
+ return true;
+
+ if (self->typeSpec.bitString < 0) {
+ if (value->value.bitString.size <= (-self->typeSpec.bitString))
+ return true;
+ }
+ }
+ else if (self->type == MMS_FLOAT) {
+ if ((self->typeSpec.floatingpoint.exponentWidth == value->value.floatingPoint.exponentWidth) &&
+ (self->typeSpec.floatingpoint.formatWidth == value->value.floatingPoint.formatWidth))
+ return true;
+ }
+ else if (self->type == MMS_BINARY_TIME) {
+ if (self->typeSpec.binaryTime == value->value.binaryTime.size)
+ return true;
+ }
+ else
+ return true;
+
+ }
+
+ return false;
+}
+
const char*
MmsVariableSpecification_getName(MmsVariableSpecification* self)
{
diff --git a/src/mms/iso_mms/common/mms_value.c b/src/mms/iso_mms/common/mms_value.c
index 199e3ec4..e0a27ee6 100644
--- a/src/mms/iso_mms/common/mms_value.c
+++ b/src/mms/iso_mms/common/mms_value.c
@@ -47,21 +47,25 @@ MmsValue_getBitStringByteSize(const MmsValue* self)
return bitStringByteSize(self);
}
-static void
+static bool
updateStructuredComponent(MmsValue* self, const MmsValue* update)
{
- int componentCount;
MmsValue** selfValues;
MmsValue** updateValues;
- componentCount = self->value.structure.size;
+ if (self->value.structure.size != update->value.structure.size)
+ return false;
+
selfValues = self->value.structure.components;
updateValues = update->value.structure.components;
int i;
- for (i = 0; i < componentCount; i++) {
- MmsValue_update(selfValues[i], updateValues[i]);
+ for (i = 0; i < self->value.structure.size; i++) {
+ if (MmsValue_update(selfValues[i], updateValues[i]) == false)
+ return false;
}
+
+ return true;
}
MmsValue*
@@ -223,7 +227,8 @@ MmsValue_update(MmsValue* self, const MmsValue* update)
switch (self->type) {
case MMS_STRUCTURE:
case MMS_ARRAY:
- updateStructuredComponent(self, update);
+ if (updateStructuredComponent(self, update) == false)
+ return false;
break;
case MMS_BOOLEAN:
self->value.boolean = update->value.boolean;
@@ -1010,9 +1015,7 @@ MmsValue_cloneToBuffer(const MmsValue* self, uint8_t* destinationAddress)
int i;
for (i = 0; i < self->value.structure.size; i++) {
- newValue->value.structure.components[i] = (MmsValue*) destinationAddress;
- //memcpy(&(newValue->value.structure.components[i]), &(destinationAddress), sizeof (MmsValue*));
-
+ memcpy(&(newValue->value.structure.components[i]), &(destinationAddress), sizeof (MmsValue*));
destinationAddress = MmsValue_cloneToBuffer(self->value.structure.components[i], destinationAddress);
}
}
diff --git a/src/mms/iso_mms/server/mms_access_result.c b/src/mms/iso_mms/server/mms_access_result.c
index 03485f90..0dafbf7d 100644
--- a/src/mms/iso_mms/server/mms_access_result.c
+++ b/src/mms/iso_mms/server/mms_access_result.c
@@ -152,8 +152,10 @@ exit_with_error:
}
MmsValue*
-MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
+MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength, int* endBufPos)
{
+ MmsValue* value = NULL;
+
int dataEndBufPos = bufPos + bufferLength;
uint8_t tag = buffer[bufPos++];
@@ -165,8 +167,6 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
if (bufPos + dataLength > dataEndBufPos)
goto exit_with_error;
- MmsValue* value = NULL;
-
switch (tag) {
case 0xa1: /* MMS_ARRAY */
@@ -191,7 +191,7 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
if (newBufPos == -1)
goto exit_with_error;
- MmsValue* elementValue = MmsValue_decodeMmsData(buffer, bufPos, dataLength);
+ MmsValue* elementValue = MmsValue_decodeMmsData(buffer, bufPos, dataLength, NULL);
if (elementValue == NULL)
goto exit_with_error;
@@ -209,12 +209,12 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
case 0x80: /* MMS_DATA_ACCESS_ERROR */
value = MmsValue_newDataAccessError((MmsDataAccessError) BerDecoder_decodeUint32(buffer, dataLength, bufPos));
-
+ bufPos += dataLength;
break;
case 0x83: /* MMS_BOOLEAN */
value = MmsValue_newBoolean(BerDecoder_decodeBoolean(buffer, bufPos));
-
+ bufPos += dataLength;
break;
case 0x84: /* MMS_BIT_STRING */
@@ -223,6 +223,7 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
int bitStringLength = (8 * (dataLength - 1)) - padding;
value = MmsValue_newBitString(bitStringLength);
memcpy(value->value.bitString.buf, buffer + bufPos + 1, dataLength - 1);
+ bufPos += dataLength;
}
break;
@@ -230,12 +231,14 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
value = MmsValue_newInteger(dataLength * 8);
memcpy(value->value.integer->octets, buffer + bufPos, dataLength);
value->value.integer->size = dataLength;
+ bufPos += dataLength;
break;
case 0x86: /* MMS_UNSIGNED */
value = MmsValue_newUnsigned(dataLength * 8);
memcpy(value->value.integer->octets, buffer + bufPos, dataLength);
value->value.integer->size = dataLength;
+ bufPos += dataLength;
break;
case 0x87: /* MMS_FLOAT */
@@ -243,15 +246,18 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
value = MmsValue_newDouble(BerDecoder_decodeDouble(buffer, bufPos));
else if (dataLength == 5)
value = MmsValue_newFloat(BerDecoder_decodeFloat(buffer, bufPos));
+ bufPos += dataLength;
break;
case 0x89: /* MMS_OCTET_STRING */
value = MmsValue_newOctetString(dataLength, dataLength);
memcpy(value->value.octetString.buf, buffer + bufPos, dataLength);
+ bufPos += dataLength;
break;
case 0x8a: /* MMS_VISIBLE_STRING */
value = MmsValue_newVisibleStringFromByteArray(buffer + bufPos, dataLength);
+ bufPos += dataLength;
break;
case 0x8c: /* MMS_BINARY_TIME */
@@ -263,11 +269,14 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
if ((dataLength == 4) || (dataLength == 6))
memcpy(value->value.binaryTime.buf, buffer + bufPos, dataLength);
+ bufPos += dataLength;
+
break;
case 0x90: /* MMS_STRING */
value = MmsValue_newVisibleStringFromByteArray(buffer + bufPos, dataLength);
value->type = MMS_STRING;
+ bufPos += dataLength;
break;
@@ -275,6 +284,7 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
if (dataLength == 8) {
value = MmsValue_newUtcTime(0);
MmsValue_setUtcTimeByBuffer(value, buffer + bufPos);
+ bufPos += dataLength;
}
else
goto exit_with_error;
@@ -285,6 +295,9 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
goto exit_with_error;
}
+ if (endBufPos != NULL)
+ *endBufPos = bufPos;
+
return value;
exit_with_error:
diff --git a/src/mms/iso_mms/server/mms_file_service.c b/src/mms/iso_mms/server/mms_file_service.c
index 9894e9a6..a9f9b7c5 100644
--- a/src/mms/iso_mms/server/mms_file_service.c
+++ b/src/mms/iso_mms/server/mms_file_service.c
@@ -122,69 +122,85 @@ encodeFileAttributes(uint8_t tag, uint32_t fileSize, char* gtString, uint8_t* bu
}
}
-static void
-createExtendedFilename(char* extendedFileName, char* fileName)
-{
- strcpy(extendedFileName, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
- strncat(extendedFileName, fileName, sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256);
-}
-
static bool
-getFileInfo(char* filename, uint32_t* fileSize, uint64_t* lastModificationTimestamp)
+getFileInfo(const char* basepath, char* filename, uint32_t* fileSize, uint64_t* lastModificationTimestamp)
{
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char extendedFileName[512];
+#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
+#endif
- createExtendedFilename(extendedFileName, filename);
+ mmsMsg_createExtendedFilename(basepath, extendedFileName, filename);
return FileSystem_getFileInfo(extendedFileName, fileSize, lastModificationTimestamp);
}
static FileHandle
-openFile(char* fileName, bool readWrite)
+openFile(const char* basepath, char* fileName, bool readWrite)
{
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char extendedFileName[512];
+#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
+#endif
- createExtendedFilename(extendedFileName, fileName);
+ mmsMsg_createExtendedFilename(basepath, extendedFileName, fileName);
return FileSystem_openFile(extendedFileName, readWrite);
}
static DirectoryHandle
-openDirectory(char* directoryName)
+openDirectory(const char* basepath, char* directoryName)
{
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char extendedFileName[512];
+#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
+#endif
- createExtendedFilename(extendedFileName, directoryName);
+ mmsMsg_createExtendedFilename(basepath, extendedFileName, directoryName);
return FileSystem_openDirectory(extendedFileName);
}
static bool
-renameFile(char* oldFilename, char* newFilename) {
+renameFile(const char* basepath, char* oldFilename, char* newFilename) {
+
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char extendedOldFileName[512];
+ char extendedNewFileName[512];
+#else
char extendedOldFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
char extendedNewFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
+#endif
- createExtendedFilename(extendedOldFileName, oldFilename);
- createExtendedFilename(extendedNewFileName, newFilename);
+ mmsMsg_createExtendedFilename(basepath, extendedOldFileName, oldFilename);
+ mmsMsg_createExtendedFilename(basepath, extendedNewFileName, newFilename);
return FileSystem_renameFile(extendedOldFileName, extendedNewFileName);
}
static bool
-deleteFile(char* fileName) {
+deleteFile(const char* basepath, char* fileName) {
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char extendedFileName[512];
+#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
+#endif
- createExtendedFilename(extendedFileName, fileName);
+ mmsMsg_createExtendedFilename(basepath, extendedFileName, fileName);
return FileSystem_deleteFile(extendedFileName);
}
void
-mmsMsg_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm)
+mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffer* response,
+ char* filename, MmsFileReadStateMachine* frsm)
{
uint64_t msTime;
- getFileInfo(fullPath, &(frsm->fileSize), &msTime);
+ getFileInfo(basepath, filename, &(frsm->fileSize), &msTime);
char gtString[30];
@@ -213,41 +229,13 @@ mmsMsg_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* ful
buffer[bufPos++] = 0xbf;
bufPos = BerEncoder_encodeTL(0x48, openFileResponseSize, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0x80, frsmIdSize - 2, buffer, bufPos);
- bufPos = BerEncoder_encodeUInt32(frsm->frsmId, buffer, bufPos);
+ bufPos = BerEncoder_encodeInt32(frsm->frsmId, buffer, bufPos);
bufPos = encodeFileAttributes(0xa1, frsm->fileSize, gtString, buffer, bufPos);
response->size = bufPos;
}
-static bool
-parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response)
-{
- uint8_t tag = buffer[(*bufPos)++];
- int length;
-
- if (tag != 0x19) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- return false;
- }
-
- *bufPos = BerDecoder_decodeLength(buffer, &length, *bufPos, maxBufPos);
-
- if (*bufPos < 0) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- return false;
- }
-
- if (length > 255) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
- return false;
- }
- memcpy(filename, buffer + *bufPos, length);
- filename[length] = 0;
- *bufPos += length;
-
- return true;
-}
void
mmsServer_handleFileDeleteRequest(
@@ -263,6 +251,11 @@ mmsServer_handleFileDeleteRequest(
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
+ if (length > 255) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
+ return;
+ }
+
char filename[256];
memcpy(filename, buffer + bufPos, length);
@@ -271,7 +264,17 @@ mmsServer_handleFileDeleteRequest(
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s)\n", filename);
- if (!getFileInfo(filename, NULL, NULL)) {
+ if (connection->server->fileAccessHandler != NULL) {
+ MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
+ connection, MMS_FILE_ACCESS_TYPE_DELETE, filename, NULL);
+
+ if (access != MMS_ERROR_NONE) {
+ mmsMsg_createServiceErrorPdu(invokeId, response, access);
+ return;
+ }
+ }
+
+ if (!getFileInfo(MmsServerConnection_getFilesystemBasepath(connection), filename, NULL, NULL)) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: File (%s) not found\n", filename);
@@ -279,7 +282,7 @@ mmsServer_handleFileDeleteRequest(
return;
}
- if (!deleteFile(filename)) {
+ if (!deleteFile(MmsServerConnection_getFilesystemBasepath(connection), filename)) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mms_file_service.c: Delete file (%s) failed\n", filename);
@@ -313,10 +316,12 @@ mmsServer_handleFileOpenRequest(
if (bufPos < 0) goto exit_reject_invalid_pdu;
+ if (bufPos + length > maxBufPos) goto exit_reject_invalid_pdu;
+
switch(tag) {
case 0xa0: /* filename */
- if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasFileName = true;
@@ -336,17 +341,28 @@ mmsServer_handleFileOpenRequest(
if (hasFileName) {
+ if (connection->server->fileAccessHandler != NULL) {
+ MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
+ connection, MMS_FILE_ACCESS_TYPE_OPEN, filename, NULL);
+
+ if (access != MMS_ERROR_NONE) {
+ mmsMsg_createServiceErrorPdu(invokeId, response, access);
+ return;
+ }
+ }
+
MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
if (frsm != NULL) {
- FileHandle fileHandle = openFile(filename, false);
+ FileHandle fileHandle = openFile(MmsServerConnection_getFilesystemBasepath(connection), filename, false);
if (fileHandle != NULL) {
frsm->fileHandle = fileHandle;
frsm->readPosition = filePosition;
frsm->frsmId = getNextFrsmId(connection);
- mmsMsg_createFileOpenResponse(invokeId, response, filename, frsm);
+ mmsMsg_createFileOpenResponse(MmsServerConnection_getFilesystemBasepath(connection),
+ invokeId, response, filename, frsm);
}
else
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
@@ -394,9 +410,6 @@ createObtainFileResponse(uint32_t invokeId, ByteBuffer* response)
void
mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
{
-
- //printf("mmsServer_fileUploadTask: state: %i\n", task->state);
-
switch (task->state) {
case MMS_FILE_UPLOAD_STATE_NOT_USED:
@@ -412,7 +425,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
FileSystem_closeFile(task->fileHandle);
- deleteFile(task->destinationFilename);
+ deleteFile(MmsServerConnection_getFilesystemBasepath(task->connection), task->destinationFilename);
}
}
break;
@@ -446,7 +459,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
FileSystem_closeFile(task->fileHandle);
- deleteFile(task->destinationFilename);
+ deleteFile(MmsServerConnection_getFilesystemBasepath(task->connection), task->destinationFilename);
}
break;
@@ -479,7 +492,7 @@ mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
FileSystem_closeFile(task->fileHandle);
- deleteFile(task->destinationFilename);
+ deleteFile(MmsServerConnection_getFilesystemBasepath(task->connection), task->destinationFilename);
}
break;
@@ -564,11 +577,13 @@ mmsServer_handleObtainFileRequest(
if (bufPos < 0) goto exit_reject_invalid_pdu;
+ if (bufPos + length > maxBufPos) goto exit_reject_invalid_pdu;
+
switch(tag) {
case 0xa1: /* source filename */
- if (!parseFileName(sourceFilename, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(sourceFilename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasSourceFileName = true;
@@ -577,7 +592,7 @@ mmsServer_handleObtainFileRequest(
case 0xa2: /* destination filename */
- if (!parseFileName(destinationFilename, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(destinationFilename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
hasDestinationFilename = true;
@@ -592,14 +607,31 @@ mmsServer_handleObtainFileRequest(
if (hasSourceFileName && hasDestinationFilename) {
- /* call callback to check if access is allowed */
+ /* Call user to check if access is allowed */
+ if (connection->server->fileAccessHandler != NULL) {
+ MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
+ connection, MMS_FILE_ACCESS_TYPE_OBTAIN, destinationFilename, sourceFilename);
+
+ if (access != MMS_ERROR_NONE) {
+ mmsMsg_createServiceErrorPdu(invokeId, response, access);
+ return;
+ }
+ }
+
+ /* call callback to check if access is allowed -- DEPRECATED */
if (connection->server->obtainFileHandler)
if (connection->server->obtainFileHandler(connection->server->obtainFileHandlerParameter, connection, sourceFilename, destinationFilename) == false)
goto exit_access_denied;
/* check if destination file already exists. If exists return error message */
+
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ char extendedFileName[512];
+#else
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
- createExtendedFilename(extendedFileName, destinationFilename);
+#endif
+ mmsMsg_createExtendedFilename(MmsServerConnection_getFilesystemBasepath(connection),
+ extendedFileName, destinationFilename);
if (FileSystem_getFileInfo(extendedFileName, NULL, NULL)) {
if (DEBUG_MMS_SERVER)
@@ -614,7 +646,8 @@ mmsServer_handleObtainFileRequest(
if (task != NULL) {
- FileHandle fileHandle = openFile(destinationFilename, true);
+ FileHandle fileHandle = openFile(MmsServerConnection_getFilesystemBasepath(connection),
+ destinationFilename, true);
if (fileHandle == NULL) {
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_DESTINATION;
@@ -734,7 +767,7 @@ mmsServer_handleFileReadRequest(
uint32_t invokeId,
ByteBuffer* response)
{
- int32_t frsmId = (int32_t) BerDecoder_decodeUint32(buffer, maxBufPos - bufPos, bufPos);
+ int32_t frsmId = BerDecoder_decodeInt32(buffer, maxBufPos - bufPos, bufPos);
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: mmsServer_handleFileReadRequest read request for frsmId: %i\n", frsmId);
@@ -760,7 +793,7 @@ mmsServer_handleFileCloseRequest(
uint32_t invokeId,
ByteBuffer* response)
{
- int32_t frsmId = (int32_t) BerDecoder_decodeUint32(buffer, maxBufPos - bufPos, bufPos);
+ int32_t frsmId = BerDecoder_decodeInt32(buffer, maxBufPos - bufPos, bufPos);
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
@@ -792,11 +825,11 @@ encodeFileSpecification(uint8_t tag, char* fileSpecification, uint8_t* buffer, i
}
static int
-addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* directoryName, char** continueAfterFileName, bool* moreFollows)
+addFileEntriesToResponse(const char* basepath, uint8_t* buffer, int bufPos, int maxBufSize, char* directoryName, char** continueAfterFileName, bool* moreFollows)
{
int directoryNameLength = strlen(directoryName);
- DirectoryHandle directory = openDirectory(directoryName);
+ DirectoryHandle directory = openDirectory(basepath, directoryName);
if (directory != NULL) {
@@ -813,7 +846,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
strcat(directoryName, fileName);
- bufPos = addFileEntriesToResponse(buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows);
+ bufPos = addFileEntriesToResponse(basepath, buffer, bufPos, maxBufSize, directoryName, continueAfterFileName, moreFollows);
if (*moreFollows == true)
break;
@@ -835,7 +868,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
uint32_t fileSize;
- if (getFileInfo(directoryName, &fileSize, &msTime)) {
+ if (getFileInfo(basepath, directoryName, &fileSize, &msTime)) {
char gtString[30];
Conversions_msTimeToGeneralizedTime(msTime, (uint8_t*) gtString);
@@ -873,7 +906,7 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
}
static void
-createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, int maxPduSize, char* directoryName, char* continueAfterFileName)
+createFileDirectoryResponse(const char* basepath, uint32_t invokeId, ByteBuffer* response, int maxPduSize, char* directoryName, char* continueAfterFileName)
{
int maxSize = maxPduSize - 3; /* reserve space for moreFollows */
uint8_t* buffer = response->buffer;
@@ -889,7 +922,7 @@ createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, int maxPduS
continueAfterFileName = NULL;
}
- tempCurPos = addFileEntriesToResponse(buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows);
+ tempCurPos = addFileEntriesToResponse(basepath, buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows);
if (tempCurPos < 0) {
@@ -923,7 +956,7 @@ createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, int maxPduS
bufPos = BerEncoder_encodeTL(0xa1, confirmedResponsePDUSize, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0x02, invokeIdSize - 2, buffer, bufPos);
- bufPos = BerEncoder_encodeUInt32((uint32_t) invokeId, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos);
buffer[bufPos++] = 0xbf;
bufPos = BerEncoder_encodeTL(0x4d, fileDirectoryResponseSize, buffer, bufPos);
@@ -958,14 +991,14 @@ mmsServer_handleFileRenameRequest(
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
- if (bufPos < 0) {
+ if ((bufPos < 0) || (bufPos + length > maxBufPos)) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
}
switch(tag) {
case 0xa0: /* currentFilename */
- if (!parseFileName(currentFileName, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(currentFileName, buffer, &bufPos, bufPos + length, invokeId, response))
return;
if (DEBUG_MMS_SERVER)
@@ -974,7 +1007,7 @@ mmsServer_handleFileRenameRequest(
break;
case 0xa1: /* newFilename */
- if (!parseFileName(newFileName, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(newFileName, buffer, &bufPos, bufPos + length, invokeId, response))
return;
if (DEBUG_MMS_SERVER)
@@ -991,7 +1024,19 @@ mmsServer_handleFileRenameRequest(
}
if ((strlen(currentFileName) != 0) && (strlen(newFileName) != 0)) {
- if (renameFile(currentFileName, newFileName)){
+
+ /* Call user to check if access is allowed */
+ if (connection->server->fileAccessHandler != NULL) {
+ MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
+ connection, MMS_FILE_ACCESS_TYPE_RENAME, currentFileName, newFileName);
+
+ if (access != MMS_ERROR_NONE) {
+ mmsMsg_createServiceErrorPdu(invokeId, response, access);
+ return;
+ }
+ }
+
+ if (renameFile(MmsServerConnection_getFilesystemBasepath(connection), currentFileName, newFileName)){
/* send positive response */
createNullResponseExtendedTag(invokeId, response, 0x4b);
}
@@ -1030,14 +1075,14 @@ mmsServer_handleFileDirectoryRequest(
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
- if (bufPos < 0) {
+ if ((bufPos < 0) || (bufPos + length > maxBufPos)) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
}
switch(tag) {
case 0xa0: /* filename */
- if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
return;
/* check for wildcard character(*) */
@@ -1047,7 +1092,7 @@ mmsServer_handleFileDirectoryRequest(
break;
case 0xa1: /* continue-after */
- if (!parseFileName(continueAfterFileName, buffer, &bufPos, bufPos + length, invokeId, response))
+ if (!mmsMsg_parseFileName(continueAfterFileName, buffer, &bufPos, bufPos + length, invokeId, response))
return;
continueAfter = continueAfterFileName;
@@ -1066,7 +1111,19 @@ mmsServer_handleFileDirectoryRequest(
int maxPduSize = connection->maxPduSize;
- createFileDirectoryResponse(invokeId, response, maxPduSize, filename, continueAfter);
+ /* Call user to check if access is allowed */
+ if (connection->server->fileAccessHandler != NULL) {
+ MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,
+ connection, MMS_FILE_ACCESS_TYPE_READ_DIRECTORY, filename, continueAfter);
+
+ if (access != MMS_ERROR_NONE) {
+ mmsMsg_createServiceErrorPdu(invokeId, response, access);
+ return;
+ }
+ }
+
+ createFileDirectoryResponse(MmsServerConnection_getFilesystemBasepath(connection),
+ invokeId, response, maxPduSize, filename, continueAfter);
}
#endif /* MMS_FILE_SERVICE == 1 */
diff --git a/src/mms/iso_mms/server/mms_get_namelist_service.c b/src/mms/iso_mms/server/mms_get_namelist_service.c
index 4b41f21b..676a1964 100644
--- a/src/mms/iso_mms/server/mms_get_namelist_service.c
+++ b/src/mms/iso_mms/server/mms_get_namelist_service.c
@@ -330,7 +330,7 @@ getNamedVariableListAssociationSpecific(MmsServerConnection connection)
static void
createNameListResponse(
MmsServerConnection connection,
- int invokeId,
+ uint32_t invokeId,
LinkedList nameList,
ByteBuffer* response,
char* continueAfter)
@@ -406,7 +406,7 @@ createNameListResponse(
bufPos = BerEncoder_encodeTL(0xa1, confirmedResponsePDUSize, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0x02, invokeIdSize - 2, buffer, bufPos);
- bufPos = BerEncoder_encodeUInt32((uint32_t) invokeId, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0xa1, getNameListSize, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0xa0, identifierListSize, buffer, bufPos);
diff --git a/src/mms/iso_mms/server/mms_identify_service.c b/src/mms/iso_mms/server/mms_identify_service.c
index b8ff70b4..0c88007e 100644
--- a/src/mms/iso_mms/server/mms_identify_service.c
+++ b/src/mms/iso_mms/server/mms_identify_service.c
@@ -29,7 +29,7 @@
void
mmsServer_handleIdentifyRequest(
MmsServerConnection connection,
- int invokeId,
+ uint32_t invokeId,
ByteBuffer* response)
{
int bufPos = 0;
diff --git a/src/mms/iso_mms/server/mms_named_variable_list_service.c b/src/mms/iso_mms/server/mms_named_variable_list_service.c
index f82dd629..9192f68b 100644
--- a/src/mms/iso_mms/server/mms_named_variable_list_service.c
+++ b/src/mms/iso_mms/server/mms_named_variable_list_service.c
@@ -233,9 +233,10 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection,
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
}
+exit_function:
+
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
-exit_function:
return;
}
@@ -252,7 +253,7 @@ createDefineNamedVariableListResponse(uint32_t invokeId, ByteBuffer* response)
bufPos = BerEncoder_encodeTL(0xa1, confirmedResponsePDUSize, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0x02, invokeIdSize - 2, buffer, bufPos);
- bufPos = BerEncoder_encodeUInt32((uint32_t) invokeId, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0x8b, 0, buffer, bufPos);
@@ -420,7 +421,7 @@ mmsServer_handleDefineNamedVariableListRequest(
if (rval.code != RC_OK) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- goto exit_function;
+ goto exit_free_struct;
}
request = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.defineNamedVariableList);
@@ -497,8 +498,7 @@ mmsServer_handleDefineNamedVariableListRequest(
char variableListName[65];
if (request->variableListName.choice.aaspecific.size > 64) {
- //TODO send reject PDU instead?
- mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
goto exit_free_struct;
}
@@ -542,8 +542,7 @@ mmsServer_handleDefineNamedVariableListRequest(
char variableListName[65];
if (request->variableListName.choice.vmdspecific.size > 64) {
- //TODO send reject PDU instead?
- mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
goto exit_free_struct;
}
@@ -582,7 +581,6 @@ mmsServer_handleDefineNamedVariableListRequest(
exit_free_struct:
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
-exit_function:
return;
}
@@ -666,7 +664,7 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
if (rval.code != RC_OK) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- return;
+ goto exit_function;
}
if (request->present == ObjectName_PR_domainspecific) {
diff --git a/src/mms/iso_mms/server/mms_read_service.c b/src/mms/iso_mms/server/mms_read_service.c
index 2840ff5b..7d69193c 100644
--- a/src/mms/iso_mms/server/mms_read_service.c
+++ b/src/mms/iso_mms/server/mms_read_service.c
@@ -115,8 +115,8 @@ appendValueToResultList(MmsValue* value, LinkedList values)
}
static void
-appendErrorToResultList(LinkedList values, uint32_t errorCode) {
- MmsValue* value = MmsValue_newDataAccessError((MmsDataAccessError) errorCode);
+appendErrorToResultList(LinkedList values, MmsDataAccessError errorType) {
+ MmsValue* value = MmsValue_newDataAccessError(errorType);
MmsValue_setDeletable(value);
appendValueToResultList(value, values);
}
@@ -246,13 +246,13 @@ alternateArrayAccess(MmsServerConnection connection,
}
else /* access error */
- appendErrorToResultList(values, 10 /* object-non-existant*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
}
else { // invalid access
if (DEBUG_MMS_SERVER) printf("Invalid alternate access\n");
- appendErrorToResultList(values, 10 /* object-non-existant*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
}
}
@@ -295,7 +295,7 @@ addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain*
if (DEBUG_MMS_SERVER)
printf("MMS read: value of known variable is not found. Maybe illegal access to array element!\n");
- appendErrorToResultList(values, 10 /* object-non-existant*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
}
else
appendValueToResultList(value, values);
@@ -303,7 +303,7 @@ addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain*
}
else
- appendErrorToResultList(values, 10 /* object-non-existant*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
}
@@ -479,6 +479,14 @@ exit_function:
return;
}
+/**
+ * \brief implements access to list of variables (multiple MMS variables)
+ *
+ * \param connection the client connection that received the request
+ * \param read read request information
+ * \param invokeId the invoke ID of the confirmed request PDU
+ * \param response byte buffer to encode the response
+ */
static void
handleReadListOfVariablesRequest(
MmsServerConnection connection,
@@ -524,13 +532,13 @@ handleReadListOfVariablesRequest(
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: READ domain %s not found!\n", domainIdStr);
- appendErrorToResultList(values, (uint32_t) DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT /* object-non-existent*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
}
else {
MmsVariableSpecification* namedVariable = MmsDomain_getNamedVariable(domain, nameIdStr);
if (namedVariable == NULL)
- appendErrorToResultList(values, (uint32_t) DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT /* object-non-existent*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
else
addNamedVariableToResultList(namedVariable, domain, nameIdStr,
values, connection, alternateAccess);
@@ -549,7 +557,7 @@ handleReadListOfVariablesRequest(
MmsVariableSpecification* namedVariable = MmsDevice_getNamedVariable(MmsServer_getDevice(connection->server), nameIdStr);
if (namedVariable == NULL)
- appendErrorToResultList(values, 10 /* object-non-existent*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
else
addNamedVariableToResultList(namedVariable, (MmsDomain*) MmsServer_getDevice(connection->server), nameIdStr,
values, connection, alternateAccess);
@@ -558,7 +566,7 @@ handleReadListOfVariablesRequest(
#endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */
else {
- appendErrorToResultList(values, (uint32_t) DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT /* object-non-existent*/);
+ appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT);
if (DEBUG_MMS_SERVER) printf("MMS_SERVER: READ object name type not supported!\n");
}
@@ -617,6 +625,14 @@ createNamedVariableListResponse(MmsServerConnection connection, MmsNamedVariable
deleteValueList(values);
}
+/**
+ * \brief implements access to named variable lists (data sets)
+ *
+ * \param connection the client connection that received the request
+ * \param read read request information
+ * \param invokeId the invoke ID of the confirmed request PDU
+ * \param response byte buffer to encode the response
+ */
static void
handleReadNamedVariableListRequest(
MmsServerConnection connection,
@@ -731,7 +747,7 @@ mmsServer_handleReadRequest(
if (rval.code != RC_OK) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- return;
+ goto exit_function;
}
request = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.read);
@@ -748,6 +764,7 @@ mmsServer_handleReadRequest(
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
}
+exit_function:
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
}
diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c
index efb7dbbf..f3c2cf89 100644
--- a/src/mms/iso_mms/server/mms_server.c
+++ b/src/mms/iso_mms/server/mms_server.c
@@ -50,9 +50,7 @@ createValueCaches(MmsDevice* device)
MmsServer
MmsServer_create(IsoServer isoServer, MmsDevice* device)
{
- MmsServer self = (MmsServer) GLOBAL_MALLOC(sizeof(struct sMmsServer));
-
- memset(self, 0, sizeof(struct sMmsServer));
+ MmsServer self = (MmsServer) GLOBAL_CALLOC(1, sizeof(struct sMmsServer));
self->isoServer = isoServer;
self->device = device;
@@ -72,6 +70,22 @@ MmsServer_create(IsoServer isoServer, MmsDevice* device)
return self;
}
+
+void
+MmsServer_setFilestoreBasepath(MmsServer self, const char* basepath)
+{
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ if (self->filestoreBasepath != NULL) {
+ GLOBAL_FREEMEM(self->filestoreBasepath);
+ self->filestoreBasepath = NULL;
+ }
+
+ if (basepath != NULL)
+ self->filestoreBasepath = StringUtils_copyString(basepath);
+#endif /* (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1) */
+}
+
+
void
MmsServer_lockModel(MmsServer self)
{
@@ -169,6 +183,15 @@ MmsServer_setClientAuthenticator(MmsServer self, AcseAuthenticator authenticator
IsoServer_setAuthenticator(self->isoServer, authenticator, authenticatorParameter);
}
+#if (MMS_FILE_SERVICE == 1)
+void
+MmsServer_installFileAccessHandler(MmsServer self, MmsFileAccessHandler handler, void* parameter)
+{
+ self->fileAccessHandler = handler;
+ self->fileAccessHandlerParameter = parameter;
+}
+#endif /* (MMS_FILE_SERVICE == 1) */
+
#if (MMS_OBTAIN_FILE_SERVICE == 1)
void
MmsServer_installObtainFileHandler(MmsServer self, MmsObtainFileHandler handler, void* parameter)
@@ -212,6 +235,11 @@ MmsServer_destroy(MmsServer self)
ByteBuffer_destroy(self->transmitBuffer);
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ if (self->filestoreBasepath != NULL)
+ GLOBAL_FREEMEM(self->filestoreBasepath);
+#endif
+
GLOBAL_FREEMEM(self);
}
@@ -271,7 +299,8 @@ mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerCon
if (self->readAccessHandler != NULL) {
MmsDataAccessError accessError =
- self->readAccessHandler(self->readAccessHandlerParameter, domain, itemId, connection);
+ self->readAccessHandler(self->readAccessHandlerParameter, (domain == (MmsDomain*) self->device) ? NULL : domain,
+ itemId, connection);
if (accessError != DATA_ACCESS_ERROR_SUCCESS) {
value = MmsValue_newDataAccessError(accessError);
@@ -284,7 +313,7 @@ mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerCon
if (value == NULL)
if (self->readHandler != NULL)
- value = self->readHandler(self->readHandlerParameter, domain,
+ value = self->readHandler(self->readHandlerParameter, (domain == (MmsDomain*) self->device) ? NULL : domain,
itemId, connection);
exit_function:
@@ -298,12 +327,6 @@ MmsServer_getDevice(MmsServer self)
return self->device;
}
-inline void
-MmsServer_setDevice(MmsServer server, MmsDevice* device)
-{
- server->device = device;
-}
-
static void /* will be called by ISO server stack */
isoConnectionIndicationHandler(IsoConnectionIndication indication,
void* parameter, IsoConnection connection)
diff --git a/src/mms/iso_mms/server/mms_server_common.c b/src/mms/iso_mms/server/mms_server_common.c
index bfdbedf8..e6522bf4 100644
--- a/src/mms/iso_mms/server/mms_server_common.c
+++ b/src/mms/iso_mms/server/mms_server_common.c
@@ -181,7 +181,7 @@ mmsServer_createServiceErrorPduWithServiceSpecificInfo(uint32_t invokeId, ByteBu
bufPos = BerEncoder_encodeTL(0xa2, confirmedErrorContentSize, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0x80, invokeIdSize - 2, buffer, bufPos); /* invokeID */
- bufPos = BerEncoder_encodeUInt32((uint32_t) invokeId, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos);
bufPos = BerEncoder_encodeTL(0xa2, serviceErrorContentSize, buffer, bufPos); /* serviceError */
bufPos = BerEncoder_encodeTL(0xa0, 3, buffer, bufPos); /* serviceError */
diff --git a/src/mms/iso_mms/server/mms_server_connection.c b/src/mms/iso_mms/server/mms_server_connection.c
index 87249e72..c80b0680 100644
--- a/src/mms/iso_mms/server/mms_server_connection.c
+++ b/src/mms/iso_mms/server/mms_server_connection.c
@@ -36,47 +36,98 @@
* MMS Common support functions
*********************************************************************************************/
-void
-mmsMsg_createMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response)
+#define MMS_REJECT_CONFIRMED_REQUEST 1
+#define MMS_REJECT_CONFIRMED_RESPONSE 2
+#define MMS_REJECT_CONFIRMED_ERROR 3
+#define MMS_REJECT_UNCONFIRMED 4
+#define MMS_REJECT_PDU_ERROR 5
+#define MMS_REJECT_CANCEL_REQUEST 6
+#define MMS_REJECT_CANCEL_RESPONSE 7
+#define MMS_REJECT_CANCEL_ERROR 8
+#define MMS_REJECT_CONCLUDE_REQUEST 9
+#define MMS_REJECT_CONCLUDE_RESPONSE 10
+#define MMS_REJECT_CONCLUDE_ERROR 11
+
+#define MMS_REJECT_CONFIRMED_REQUEST_OTHER 0
+#define MMS_REJECT_CONFIRMED_REQUEST_UNRECOGNIZED_SERVICE 1
+#define MMS_REJECT_CONFIRMED_REQUEST_UNRECOGNIZED_MODIFIER 2
+#define MMS_REJECT_CONFIRMED_REQUEST_INVALID_INVOKE_ID 3
+#define MMS_REJECT_CONFIRMED_REQUEST_INVALID_ARGUMENT 4
+#define MMS_REJECT_CONFIRMED_REQUEST_INVALID_MODIFIER 5
+#define MMS_REJECT_CONFIRMED_REQUEST_MAX_SERV_OUTSTANDING_EXCEEDED 6
+#define MMS_REJECT_CONFIRMED_REQUEST_MAX_RECURSION_EXCEEDED 8
+#define MMS_REJECT_CONFIRMED_REQUEST_VALUE_OUT_OF_RANGE 9
+
+#define MMS_REJECT_PDU_ERROR_UNKNOWN_PDU_TYPE 0
+#define MMS_REJECT_PDU_ERROR_INVALID_PDU 1
+#define MMS_REJECT_PDU_ERROR_ILLEGAL_ACSI_MAPPING 2
+
+
+static void
+mmsMsg_encodeMmsRejectPdu(uint32_t* invokeId, int rejectType, int rejectReason, ByteBuffer* response)
{
- MmsPdu_t* mmsPdu = (MmsPdu_t*) GLOBAL_CALLOC(1, sizeof(MmsPdu_t));
+ int bufPos = 0;
+ uint8_t* buffer = response->buffer;
- mmsPdu->present = MmsPdu_PR_rejectPDU;
+ uint32_t invokeIdLength = 0;
- if (invokeId != NULL) {
- mmsPdu->choice.rejectPDU.originalInvokeID = (Unsigned32_t*) GLOBAL_CALLOC(1, sizeof(Unsigned32_t));
- asn_long2INTEGER(mmsPdu->choice.rejectPDU.originalInvokeID, *invokeId);
- }
+ uint32_t rejectPduLength = 3;
- if (reason == MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE) {
- mmsPdu->choice.rejectPDU.rejectReason.present = RejectPDU__rejectReason_PR_confirmedRequestPDU;
- mmsPdu->choice.rejectPDU.rejectReason.choice.confirmedResponsePDU =
- RejectPDU__rejectReason__confirmedRequestPDU_unrecognizedService;
- }
- else if(reason == MMS_ERROR_REJECT_UNKNOWN_PDU_TYPE) {
- mmsPdu->choice.rejectPDU.rejectReason.present = RejectPDU__rejectReason_PR_pduError;
- asn_long2INTEGER(&mmsPdu->choice.rejectPDU.rejectReason.choice.pduError,
- RejectPDU__rejectReason__pduError_unknownPduType);
- }
- else if (reason == MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT) {
- mmsPdu->choice.rejectPDU.rejectReason.present = RejectPDU__rejectReason_PR_confirmedRequestPDU;
- mmsPdu->choice.rejectPDU.rejectReason.choice.confirmedResponsePDU =
- RejectPDU__rejectReason__confirmedRequestPDU_invalidArgument;
- }
- else if (reason == MMS_ERROR_REJECT_INVALID_PDU) {
- mmsPdu->choice.rejectPDU.rejectReason.present = RejectPDU__rejectReason_PR_pduError;
- asn_long2INTEGER(&mmsPdu->choice.rejectPDU.rejectReason.choice.pduError,
- RejectPDU__rejectReason__pduError_invalidPdu);
- }
- else {
- mmsPdu->choice.rejectPDU.rejectReason.present = RejectPDU__rejectReason_PR_confirmedRequestPDU;
- mmsPdu->choice.rejectPDU.rejectReason.choice.confirmedResponsePDU =
- RejectPDU__rejectReason__confirmedRequestPDU_other;
- }
+ if (invokeId != NULL) {
+ invokeIdLength = BerEncoder_UInt32determineEncodedSize(*invokeId);
+ rejectPduLength += 2 + invokeIdLength;
+ }
+
+ /* Encode reject PDU */
+ bufPos = BerEncoder_encodeTL(0xa4, rejectPduLength, buffer, bufPos);
+
+ if (invokeId != NULL) {
+ /* original invokeId */
+ bufPos = BerEncoder_encodeTL(0x80, invokeIdLength, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(*invokeId, buffer, bufPos);
+ }
+
+ buffer[bufPos++] = (uint8_t) (0x80 + rejectType);
+ buffer[bufPos++] = 0x01;
+ buffer[bufPos++] = (uint8_t) rejectReason;
+
+ response->size = bufPos;
+}
- der_encode(&asn_DEF_MmsPdu, mmsPdu, mmsServer_write_out, (void*) response);
+void
+mmsMsg_createMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response)
+{
+ int rejectType = 0;
+ int rejectReason = 0;
+
+ switch (reason) {
+
+ case MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE:
+ rejectType = MMS_REJECT_CONFIRMED_REQUEST;
+ rejectReason = MMS_REJECT_CONFIRMED_REQUEST_UNRECOGNIZED_SERVICE;
+ break;
+
+ case MMS_ERROR_REJECT_UNKNOWN_PDU_TYPE:
+ rejectType = MMS_REJECT_PDU_ERROR;
+ rejectReason = MMS_REJECT_PDU_ERROR_UNKNOWN_PDU_TYPE;
+ break;
+
+ case MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT:
+ rejectType = MMS_REJECT_CONFIRMED_REQUEST;
+ rejectReason = MMS_REJECT_CONFIRMED_REQUEST_INVALID_ARGUMENT;
+ break;
+
+ case MMS_ERROR_REJECT_INVALID_PDU:
+ rejectType = MMS_REJECT_PDU_ERROR;
+ rejectReason = MMS_REJECT_PDU_ERROR_INVALID_PDU;
+ break;
+
+ default:
+ rejectType = MMS_REJECT_CONFIRMED_REQUEST;
+ rejectReason = MMS_REJECT_CONFIRMED_REQUEST_OTHER;
+ }
- asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
+ mmsMsg_encodeMmsRejectPdu(invokeId, rejectType, rejectReason, response);
}
/**********************************************************************************************
@@ -105,9 +156,14 @@ handleConfirmedRequestPdu(
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response);
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
- }
+ }
+
+ if (bufPos + length > maxBufPos) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ return;
+ }
if (extendedTag) {
switch(tag) {
@@ -252,8 +308,6 @@ handleConfirmedErrorPdu(
uint32_t invokeId;
MmsServiceError serviceError;
-
-
if (mmsMsg_parseConfirmedErrorPDU(buffer, bufPos, maxBufPos, &invokeId, &serviceError)) {
if (DEBUG_MMS_SERVER)
@@ -634,3 +688,20 @@ MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self)
return self->lastRequestInvokeId;
}
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
+
+
+const char*
+MmsServerConnection_getFilesystemBasepath(MmsServerConnection self)
+{
+#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1)
+ if (self->server->filestoreBasepath != NULL)
+ return self->server->filestoreBasepath;
+ else
+ return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
+#else
+ return CONFIG_VIRTUAL_FILESTORE_BASEPATH;
+#endif
+}
+
+
+
diff --git a/src/mms/iso_mms/server/mms_status_service.c b/src/mms/iso_mms/server/mms_status_service.c
index a547b9f0..bccbd34b 100644
--- a/src/mms/iso_mms/server/mms_status_service.c
+++ b/src/mms/iso_mms/server/mms_status_service.c
@@ -31,7 +31,7 @@ mmsServer_handleStatusRequest(
MmsServerConnection connection,
uint8_t* requestBuffer,
int bufPos,
- int invokeId,
+ uint32_t invokeId,
ByteBuffer* response)
{
/* check for extended derivation */
diff --git a/src/mms/iso_mms/server/mms_write_service.c b/src/mms/iso_mms/server/mms_write_service.c
index 7014e217..13eaec62 100644
--- a/src/mms/iso_mms/server/mms_write_service.c
+++ b/src/mms/iso_mms/server/mms_write_service.c
@@ -1,7 +1,7 @@
/*
* mms_write_service.c
*
- * Copyright 2013 Michael Zillgith
+ * Copyright 2013-2017 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -30,46 +30,54 @@
#define CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS 100
-/**********************************************************************************************
- * MMS Write Service
- *********************************************************************************************/
-
-int
+void
mmsServer_createMmsWriteResponse(MmsServerConnection connection,
- int invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults)
+ uint32_t invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults)
{
- //TODO remove asn1c code
- MmsPdu_t* mmsPdu = mmsServer_createConfirmedResponse(invokeId);
+ int bufPos = 0;
+ uint8_t* buffer = response->buffer;
- mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present =
- ConfirmedServiceResponse_PR_write;
+ /* Determine length fields */
- WriteResponse_t* writeResponse =
- &(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.write);
+ uint32_t invokeIdLength = BerEncoder_UInt32determineEncodedSize(invokeId);
- writeResponse->list.count = numberOfItems;
- writeResponse->list.size = numberOfItems;
- writeResponse->list.array = (struct WriteResponse__Member**) GLOBAL_CALLOC(numberOfItems,
- sizeof(struct WriteResponse__Member*));
+ uint32_t accessResultsLength = 0;
- int i;
+ int i;
+ for (i = 0; i < numberOfItems; i++) {
+ if (accessResults[i] < 0)
+ accessResultsLength += 2;
+ else
+ accessResultsLength += 3;
+ }
- for (i = 0; i < numberOfItems; i++) {
- writeResponse->list.array[i] = (struct WriteResponse__Member*) GLOBAL_CALLOC(1, sizeof(struct WriteResponse__Member));
+ uint32_t writeResponseLength = 2 + invokeIdLength
+ + 1 + BerEncoder_determineLengthSize(accessResultsLength)
+ + accessResultsLength;
- if (accessResults[i] == DATA_ACCESS_ERROR_SUCCESS)
- writeResponse->list.array[i]->present = WriteResponse__Member_PR_success;
- else {
- writeResponse->list.array[i]->present = WriteResponse__Member_PR_failure;
- asn_long2INTEGER(&writeResponse->list.array[i]->choice.failure, (long) accessResults[i]);
- }
- }
+ /* Encode write response */
- der_encode(&asn_DEF_MmsPdu, mmsPdu, mmsServer_write_out, (void*) response);
+ bufPos = BerEncoder_encodeTL(0xa1, writeResponseLength, buffer, bufPos);
- asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
+ /* invokeId */
+ bufPos = BerEncoder_encodeTL(0x02, invokeIdLength, buffer, bufPos);
+ bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos);
+
+ bufPos = BerEncoder_encodeTL(0xa5, accessResultsLength, buffer, bufPos);
+
+ for (i = 0; i < numberOfItems; i++) {
+ if (accessResults[i] < 0) {
+ buffer[bufPos++] = 0x81;
+ buffer[bufPos++] = 0x00;
+ }
+ else {
+ buffer[bufPos++] = 0x80;
+ buffer[bufPos++] = 0x01;
+ buffer[bufPos++] = (uint8_t) accessResults[i];
+ }
+ }
- return 0;
+ response->size = bufPos;
}
@@ -87,198 +95,595 @@ MmsServerConnection_sendWriteResponse(MmsServerConnection self, uint32_t invokeI
MmsServer_releaseTransmitBuffer(self->server);
}
+#if 0
+typedef struct {
+ uint8_t type; /* 0 = vmd-specific, 1 = domain-specific, 2 = association-specific */
+ uint8_t* name;
+ uint8_t nameLength;
+ uint8_t* domain;
+ uint8_t domainLength;
+} _MmsObjectName;
+
+/**
+ * \brief Decode MMS ObjectName
+ *
+ * \return true = valid data, false = decoding error
+ */
+static bool
+decodeObjectName(uint8_t* buffer, int bufPos, int length, int* endPos, _MmsObjectName* objName)
+{
+ int dataEndBufPos = bufPos + length;
+
+ uint8_t tag = buffer[bufPos++];
+
+ int dataLength;
+
+ bufPos = BerDecoder_decodeLength(buffer, &dataLength, bufPos, dataEndBufPos);
+
+ printf(" decodeObjectName - bufPos: %i endPos: %i tag: %02x\n", bufPos, bufPos + dataLength, tag);
+
+ if (bufPos == -1)
+ return false;
+
+ switch (tag) {
+ case 0x80: /* VMD specific */
+ objName->type = 0;
+ objName->name = buffer + bufPos;
+ objName->nameLength = dataLength;
+ objName->domain = NULL;
+ if (bufPos + dataLength > dataEndBufPos)
+ return false;
+
+ bufPos += dataLength;
+ break;
+
+ case 0xa1: /* domain specific */
+ objName->type = 1;
+ {
+ if (buffer[bufPos++] != 0x1a)
+ return false;
+
+ int nameLength;
+
+ bufPos = BerDecoder_decodeLength(buffer, &nameLength, bufPos, dataEndBufPos);
+
+ if (bufPos == -1)
+ return false;
+
+ objName->domainLength = nameLength;
+ objName->domain = buffer + bufPos;
+
+ if (bufPos + nameLength >= dataEndBufPos)
+ return false;
+
+ bufPos += nameLength;
+
+ if (buffer[bufPos++] != 0x1a)
+ return false;
+
+ bufPos = BerDecoder_decodeLength(buffer, &nameLength, bufPos, dataEndBufPos);
+
+ objName->nameLength = nameLength;
+ objName->name = buffer + bufPos;
+
+ if (bufPos + nameLength > dataEndBufPos)
+ return false;
+
+ bufPos += nameLength;
+ }
+ break;
+
+ case 0x82: /* association specific */
+ objName->type = 2;
+ objName->name = buffer + bufPos;
+ objName->nameLength = dataLength;
+ objName->domain = NULL;
+ if (bufPos + dataLength > dataEndBufPos)
+ return false;
+
+ bufPos += dataLength;
+ break;
+ }
+
+ if (endPos != NULL)
+ *endPos = bufPos;
+
+ return true;
+}
+
+static bool
+decodeVarSpec(uint8_t* buffer, int bufPos, int length, int* endPos)
+{
+ int dataEndBufPos = bufPos + length;
+
+ uint8_t tag = buffer[bufPos++];
+
+ printf(" varSpec - bufPos: %i endPos: %i tag: %02x\n", bufPos - 1, bufPos + length, tag);
+
+ if (tag != 0x30)
+ return false;
+
+ int dataLength;
+
+ bufPos = BerDecoder_decodeLength(buffer, &dataLength, bufPos, dataEndBufPos);
+
+ printf("dataLength = %i - bufPos: %i\n", dataLength, bufPos);
+
+ if (bufPos < 0)
+ return false;
+
+ tag = buffer[bufPos++];
+
+ printf(" varSpec - bufPos: %i endPos: %i tag: %02x\n", bufPos - 1, bufPos + length, tag);
+
+ if (tag != 0xa0)
+ return false;
+
+ bufPos = BerDecoder_decodeLength(buffer, &dataLength, bufPos, dataEndBufPos);
+
+ if (bufPos < 0)
+ return false;
+
+ printf("dataLength = %i - bufPos: %i\n", dataLength, bufPos);
+
+ _MmsObjectName objName;
+
+ if (decodeObjectName(buffer, bufPos, bufPos + dataLength, &bufPos, &objName) == false)
+ return false;
+
+ if (objName.domain != NULL)
+ printf("domain name: %.*s\n", objName.domainLength, objName.domain);
+ if (objName.name != NULL)
+ printf("item name: %.*s\n", objName.nameLength, objName.name);
+
+ if (endPos != NULL)
+ *endPos = bufPos;
+
+ return true;
+}
+
void
-mmsServer_handleWriteRequest(
- MmsServerConnection connection,
- uint8_t* buffer, int bufPos, int maxBufPos,
- uint32_t invokeId,
- ByteBuffer* response)
+mmsServer_handleWriteRequest2(
+ MmsServerConnection connection,
+ uint8_t* buffer, int bufPos, int maxBufPos,
+ uint32_t invokeId,
+ ByteBuffer* response)
{
- WriteRequest_t* writeRequest = 0;
- MmsPdu_t* mmsPdu = 0;
+ bool isAccessSpecification = true;
- asn_dec_rval_t rval; /* Decoder return value */
+ while (bufPos < maxBufPos) {
+ uint8_t tag = buffer[bufPos++];
+ int length;
- rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, buffer, CONFIG_MMS_MAXIMUM_PDU_SIZE);
+ bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
- if (rval.code != RC_OK) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
- return;
- }
+ if (bufPos < 0) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ return;
+ }
- writeRequest = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.write);
+ if (tag == 0xa1) { /* variable access specification - variable list name (data set) */
+ isAccessSpecification = false;
- int numberOfWriteItems = writeRequest->variableAccessSpecification.choice.listOfVariable.list.count;
- if (numberOfWriteItems < 1) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
- return;
- }
+ }
+ if (tag == 0xa0) {
+ if (isAccessSpecification) { /* variable access specification - list of variable names */
+ printf("VAR ACCESS SPEC\n");
- if (numberOfWriteItems > CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_OTHER, response);
- return;
- }
+ isAccessSpecification = false;
- if (writeRequest->listOfData.list.count != numberOfWriteItems) {
- mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
+ int dataBufPos = bufPos;
+
+ while (dataBufPos < (bufPos + length)) {
+
+
+ if (decodeVarSpec(buffer, dataBufPos, length, &dataBufPos) == false) {
+ printf("Failed to decode MMS var access spec\n");
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ return;
+ }
+ }
+ }
+ else {
+ printf("LIST OF DATA\n");
+
+
+ int dataBufPos = bufPos;
+
+ while (dataBufPos < (bufPos + length)) {
+ printf("lod - dataBufPos: %i endPos: %i\n", dataBufPos, bufPos + length);
+
+ MmsValue* newValue = MmsValue_decodeMmsData(buffer, dataBufPos, length, &dataBufPos);
+
+ if (newValue != NULL) {
+ printf(" Decoded MMS data value:\n");
+
+ uint8_t printBuf[1024];
+
+ MmsValue_printToBuffer(newValue, printBuf, 1024);
+
+ printf(" %s\n", printBuf);
+ }
+ else {
+ //TODO cleanup already decoded MmsValue instances
+ printf(" Failed to decode MMS data value\n");
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ return;
+ }
+ }
+ }
+ }
+
+ bufPos += length;
+ }
+}
+#endif
+
+static void
+createWriteNamedVariableListResponse(
+ MmsServerConnection connection,
+ WriteRequest_t* writeRequest,
+ uint32_t invokeId,
+ MmsNamedVariableList namedList,
+ ByteBuffer* response)
+{
+ bool sendResponse = true;
+
+ LinkedList variables = MmsNamedVariableList_getVariableList(namedList);
+
+ int numberOfWriteItems = LinkedList_size(variables);
+
+ if (numberOfWriteItems > CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_OTHER, response);
return;
}
+ /* write variables and send response */
+
MmsDataAccessError accessResults[CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS * sizeof(MmsDataAccessError)];
- bool sendResponse = true;
+ LinkedList element;
+
+ int i = 0;
+
+ for (element = LinkedList_getNext(variables); element != NULL; element = LinkedList_getNext(element)) {
+ MmsNamedVariableListEntry variableListEntry = (MmsNamedVariableListEntry) LinkedList_getData(element);
+
+ MmsDomain* variableDomain = MmsNamedVariableListEntry_getDomain(variableListEntry);
+ char* variableName = MmsNamedVariableListEntry_getVariableName(variableListEntry);
+
+ MmsValue* oldValue = mmsServer_getValue(connection->server, variableDomain, variableName, connection);
+
+ Data_t* dataElement = writeRequest->listOfData.list.array[i];
+
+ MmsValue* newValue = mmsMsg_parseDataElement(dataElement);
+
+ if (newValue == NULL) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
+ }
+ else if (MmsValue_equalTypes(oldValue, newValue) == false) {
+ MmsValue_delete(newValue);
+ accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ }
+ else {
+ MmsDataAccessError valueIndication =
+ mmsServer_setValue(connection->server, variableDomain, variableName, newValue, connection);
- int i;
+ accessResults[i] = valueIndication;
- for (i = 0; i < numberOfWriteItems; i++) {
- ListOfVariableSeq_t* varSpec =
- writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[i];
+ if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE)
+ sendResponse = false;
- if (varSpec->variableSpecification.present != VariableSpecification_PR_name) {
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
- continue;
+ MmsValue_delete(newValue);
}
- MmsVariableSpecification* variable;
+ i++;
+ }
- MmsDevice* device = MmsServer_getDevice(connection->server);
+ if (sendResponse)
+ mmsServer_createMmsWriteResponse(connection, invokeId, response, numberOfWriteItems, accessResults);
+}
- MmsDomain* domain = NULL;
+static void
+handleWriteNamedVariableListRequest(
+ MmsServerConnection connection,
+ WriteRequest_t* writeRequest,
+ uint32_t invokeId,
+ ByteBuffer* response)
+{
+ if (writeRequest->variableAccessSpecification.choice.variableListName.present == ObjectName_PR_domainspecific)
+ {
+ char domainIdStr[65];
+ char nameIdStr[65];
- char* nameIdStr;
+ mmsMsg_copyAsn1IdentifierToStringBuffer(writeRequest->variableAccessSpecification.choice.variableListName.choice.domainspecific.domainId,
+ domainIdStr, 65);
- if (varSpec->variableSpecification.choice.name.present == ObjectName_PR_domainspecific) {
- Identifier_t domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId;
- char* domainIdStr = StringUtils_createStringFromBuffer(domainId.buf, domainId.size);
+ mmsMsg_copyAsn1IdentifierToStringBuffer(writeRequest->variableAccessSpecification.choice.variableListName.choice.domainspecific.itemId,
+ nameIdStr, 65);
- domain = MmsDevice_getDomain(device, domainIdStr);
+ MmsDomain* domain = MmsDevice_getDomain(MmsServer_getDevice(connection->server), domainIdStr);
- GLOBAL_FREEMEM(domainIdStr);
+ if (domain == NULL) {
+ if (DEBUG_MMS_SERVER)
+ printf("MMS write: domain %s not found!\n", domainIdStr);
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
- if (domain == NULL) {
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT;
- continue;
+ return;
+ }
+ else {
+ MmsNamedVariableList namedList = MmsDomain_getNamedVariableList(domain, nameIdStr);
+
+ if (namedList != NULL) {
+ createWriteNamedVariableListResponse(connection, writeRequest, invokeId, namedList, response);
}
+ else {
+ if (DEBUG_MMS_SERVER) printf("MMS write: named variable list %s not found!\n", nameIdStr);
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
+ }
+ }
+
+ }
+ else if (writeRequest->variableAccessSpecification.choice.variableListName.present == ObjectName_PR_vmdspecific) {
+ char listName[65];
+
+ mmsMsg_copyAsn1IdentifierToStringBuffer(writeRequest->variableAccessSpecification.choice.variableListName.choice.vmdspecific,
+ listName, 65);
- Identifier_t nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId;
- nameIdStr = StringUtils_createStringFromBuffer(nameId.buf, nameId.size);
+ MmsNamedVariableList namedList = mmsServer_getNamedVariableListWithName(connection->server->device->namedVariableLists, listName);
- variable = MmsDomain_getNamedVariable(domain, nameIdStr);
+ if (namedList != NULL) {
+ createWriteNamedVariableListResponse(connection, writeRequest, invokeId, namedList, response);
}
+ else {
+ if (DEBUG_MMS_SERVER) printf("MMS write: vmd specific named variable list %s not found!\n", listName);
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
+ }
+ }
+#if (MMS_DYNAMIC_DATA_SETS == 1)
+ else if (writeRequest->variableAccessSpecification.choice.variableListName.present == ObjectName_PR_aaspecific) {
+ char listName[65];
-#if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)
- else if (varSpec->variableSpecification.choice.name.present == ObjectName_PR_vmdspecific) {
+ mmsMsg_copyAsn1IdentifierToStringBuffer(writeRequest->variableAccessSpecification.choice.variableListName.choice.aaspecific,
+ listName, 65);
- Identifier_t nameId = varSpec->variableSpecification.choice.name.choice.vmdspecific;
- nameIdStr = StringUtils_createStringFromBuffer(nameId.buf, nameId.size);
+ MmsNamedVariableList namedList = MmsServerConnection_getNamedVariableList(connection, listName);
- variable = MmsDevice_getNamedVariable(device, nameIdStr);
+ if (namedList != NULL) {
+ createWriteNamedVariableListResponse(connection, writeRequest, invokeId, namedList, response);
}
-#endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */
-
else {
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
- continue;
+ if (DEBUG_MMS_SERVER) printf("MMS write: association specific named variable list %s not found!\n", listName);
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
+ }
+ }
+#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */
+ else
+ mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
+
+}
+
+
+void
+mmsServer_handleWriteRequest(
+ MmsServerConnection connection,
+ uint8_t* buffer, int bufPos, int maxBufPos,
+ uint32_t invokeId,
+ ByteBuffer* response)
+{
+ MmsPdu_t* mmsPdu = 0;
+
+ asn_dec_rval_t rval; /* Decoder return value */
+
+ rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, buffer, CONFIG_MMS_MAXIMUM_PDU_SIZE);
+
+ if (rval.code != RC_OK) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
+ goto exit_function;
+ }
+
+ WriteRequest_t* writeRequest = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.write);
+
+ if (writeRequest->variableAccessSpecification.present == VariableAccessSpecification_PR_variableListName) {
+ handleWriteNamedVariableListRequest(connection, writeRequest, invokeId, response);
+ goto exit_function;
+ }
+ else if (writeRequest->variableAccessSpecification.present == VariableAccessSpecification_PR_listOfVariable) {
+
+ int numberOfWriteItems = writeRequest->variableAccessSpecification.choice.listOfVariable.list.count;
+
+ if (numberOfWriteItems < 1) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
+ goto exit_function;
}
- if (variable == NULL) {
- GLOBAL_FREEMEM(nameIdStr);
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT;
- continue;
+ if (numberOfWriteItems > CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_OTHER, response);
+ goto exit_function;
}
- AlternateAccess_t* alternateAccess = varSpec->alternateAccess;
+ if (writeRequest->listOfData.list.count != numberOfWriteItems) {
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
+ goto exit_function;
+ }
- if (alternateAccess != NULL) {
- if (variable->type != MMS_ARRAY) {
- GLOBAL_FREEMEM(nameIdStr);
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
- continue;
- }
+ MmsDataAccessError accessResults[CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS * sizeof(MmsDataAccessError)];
+
+ bool sendResponse = true;
+
+ int i;
- if (!mmsServer_isIndexAccess(alternateAccess)) {
- GLOBAL_FREEMEM(nameIdStr);
+ for (i = 0; i < numberOfWriteItems; i++) {
+ ListOfVariableSeq_t* varSpec =
+ writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[i];
+
+ if (varSpec->variableSpecification.present != VariableSpecification_PR_name) {
accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
continue;
}
- }
- Data_t* dataElement = writeRequest->listOfData.list.array[i];
+ MmsVariableSpecification* variable;
- MmsValue* value = mmsMsg_parseDataElement(dataElement);
+ MmsDevice* device = MmsServer_getDevice(connection->server);
- if (value == NULL) {
- GLOBAL_FREEMEM(nameIdStr);
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
- continue;
- }
+ MmsDomain* domain = NULL;
- /* Check for correct type */
- if (MmsValue_getType(value) != MmsVariableSpecification_getType(variable)) {
- GLOBAL_FREEMEM(nameIdStr);
- MmsValue_delete(value);
- accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
- continue;
- }
+ char nameIdStr[65];
- if (alternateAccess != NULL) {
+ if (varSpec->variableSpecification.choice.name.present == ObjectName_PR_domainspecific) {
+ Identifier_t domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId;
- if (domain != NULL)
- domain = (MmsDomain*) device;
+ char domainIdStr[65];
- MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr);
+ mmsMsg_copyAsn1IdentifierToStringBuffer(domainId, domainIdStr, 65);
- if (cachedArray == NULL) {
- GLOBAL_FREEMEM(nameIdStr);
- MmsValue_delete(value);
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
- continue;
+ domain = MmsDevice_getDomain(device, domainIdStr);
+
+ if (domain == NULL) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT;
+ continue;
+ }
+
+ Identifier_t nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId;
+
+ mmsMsg_copyAsn1IdentifierToStringBuffer(nameId, nameIdStr, 65);
+
+ variable = MmsDomain_getNamedVariable(domain, nameIdStr);
}
- int index = mmsServer_getLowIndex(alternateAccess);
+ #if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)
+ else if (varSpec->variableSpecification.choice.name.present == ObjectName_PR_vmdspecific) {
+ Identifier_t nameId = varSpec->variableSpecification.choice.name.choice.vmdspecific;
- MmsValue* elementValue = MmsValue_getElement(cachedArray, index);
+ mmsMsg_copyAsn1IdentifierToStringBuffer(nameId, nameIdStr, 65);
- if (elementValue == NULL) {
- GLOBAL_FREEMEM(nameIdStr);
- MmsValue_delete(value);
- accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
+ variable = MmsDevice_getNamedVariable(device, nameIdStr);
+ }
+ #endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */
+
+ else {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
continue;
}
- if (MmsValue_update(elementValue, value) == false) {
- GLOBAL_FREEMEM(nameIdStr);
- MmsValue_delete(value);
- accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ if (variable == NULL) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT;
continue;
}
- GLOBAL_FREEMEM(nameIdStr);
- MmsValue_delete(value);
- accessResults[i] = DATA_ACCESS_ERROR_SUCCESS;
- continue;
+ AlternateAccess_t* alternateAccess = varSpec->alternateAccess;
- }
+ if (alternateAccess != NULL) {
+ if (variable->type != MMS_ARRAY) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
+ continue;
+ }
- MmsDataAccessError valueIndication =
- mmsServer_setValue(connection->server, domain, nameIdStr, value, connection);
+ if (!mmsServer_isIndexAccess(alternateAccess)) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED;
+ continue;
+ }
+ }
- if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE)
- sendResponse = false;
+ Data_t* dataElement = writeRequest->listOfData.list.array[i];
- accessResults[i] = valueIndication;
+ MmsValue* value = mmsMsg_parseDataElement(dataElement);
- MmsValue_delete(value);
+ if (value == NULL) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
+ continue;
+ }
- GLOBAL_FREEMEM(nameIdStr);
- }
+ if (alternateAccess != NULL) {
+
+ if (domain == NULL)
+ domain = (MmsDomain*) device;
+
+ MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr);
+
+ if (cachedArray == NULL) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
- if (sendResponse) {
- mmsServer_createMmsWriteResponse(connection, invokeId, response, numberOfWriteItems, accessResults);
+ int index = mmsServer_getLowIndex(alternateAccess);
+ int numberOfElements = mmsServer_getNumberOfElements(alternateAccess);
+
+ if (numberOfElements == 0) { /* select single array element with index */
+
+ MmsValue* elementValue = MmsValue_getElement(cachedArray, index);
+
+ if (elementValue == NULL) {
+ accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
+
+ if (MmsValue_update(elementValue, value) == false) {
+ accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
+ }
+ else { /* select sub-array with start-index and number-of-elements */
+
+ if (MmsValue_getType(value) != MMS_ARRAY) {
+ accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
+
+ int elementNo;
+
+ for (elementNo = 0; elementNo < numberOfElements; elementNo++) {
+ MmsValue* newElement = MmsValue_getElement(value, elementNo);
+ MmsValue* elementValue = MmsValue_getElement(cachedArray, index++);
+
+ if ((elementValue == NULL) || (newElement == NULL) ) {
+ accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
+
+ if (MmsValue_update(elementValue, newElement) == false) {
+ accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
+
+ }
+ }
+
+ accessResults[i] = DATA_ACCESS_ERROR_SUCCESS;
+ goto end_of_main_loop;
+
+ }
+
+ /* Check for correct type */
+ if (MmsVariableSpecification_isValueOfType(variable, value) == false) {
+ accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
+ goto end_of_main_loop;
+ }
+
+ MmsDataAccessError valueIndication =
+ mmsServer_setValue(connection->server, domain, nameIdStr, value, connection);
+
+ if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE)
+ sendResponse = false;
+
+ accessResults[i] = valueIndication;
+
+end_of_main_loop:
+
+ MmsValue_delete(value);
+ }
+
+ if (sendResponse)
+ mmsServer_createMmsWriteResponse(connection, invokeId, response, numberOfWriteItems, accessResults);
+ }
+ else { /* unknown request type */
+ mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
+ goto exit_function;
}
+exit_function:
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
}
diff --git a/src/sampled_values/sv_publisher.c b/src/sampled_values/sv_publisher.c
index d550b57e..969992a4 100644
--- a/src/sampled_values/sv_publisher.c
+++ b/src/sampled_values/sv_publisher.c
@@ -42,15 +42,6 @@
#define SV_MAX_MESSAGE_SIZE 1518
-typedef struct sCommParameters {
- uint8_t vlanPriority;
- uint16_t vlanId;
- uint16_t appId;
- uint8_t dstAddress[6];
-} CommParameters;
-
-
-
struct sSV_ASDU {
char* svID;
char* datset;
@@ -68,6 +59,7 @@ struct sSV_ASDU {
uint64_t refrTm;
uint8_t smpMod;
+ uint16_t smpRate;
uint8_t* smpCntBuf;
@@ -229,6 +221,34 @@ encodeInt32FixedSize(int32_t value, uint8_t* buffer, int bufPos)
return bufPos;
}
+static int
+encodeInt64FixedSize(int64_t value, uint8_t* buffer, int bufPos)
+{
+ uint8_t* valueArray = (uint8_t*) &value;
+
+#if (ORDER_LITTLE_ENDIAN == 1)
+ buffer[bufPos++] = valueArray[7];
+ buffer[bufPos++] = valueArray[6];
+ buffer[bufPos++] = valueArray[5];
+ buffer[bufPos++] = valueArray[4];
+ buffer[bufPos++] = valueArray[3];
+ buffer[bufPos++] = valueArray[2];
+ buffer[bufPos++] = valueArray[1];
+ buffer[bufPos++] = valueArray[0];
+#else
+ buffer[bufPos++] = valueArray[0];
+ buffer[bufPos++] = valueArray[1];
+ buffer[bufPos++] = valueArray[2];
+ buffer[bufPos++] = valueArray[3];
+ buffer[bufPos++] = valueArray[4];
+ buffer[bufPos++] = valueArray[5];
+ buffer[bufPos++] = valueArray[6];
+ buffer[bufPos++] = valueArray[7];
+#endif
+
+ return bufPos;
+}
+
static int
encodeUtcTime(uint64_t timeval, uint8_t* buffer, int bufPos)
{
@@ -264,15 +284,15 @@ encodeUtcTime(uint64_t timeval, uint8_t* buffer, int bufPos)
}
SampledValuesPublisher
-SampledValuesPublisher_create(const char* interfaceId)
+SampledValuesPublisher_create(CommParameters* parameters, const char* interfaceId)
{
- SampledValuesPublisher self = (SampledValuesPublisher) GLOBAL_CALLOC(1, sizeof(struct sSampledValuesPublisher));
+ SampledValuesPublisher self = (SampledValuesPublisher) GLOBAL_CALLOC(1, sizeof(struct sSampledValuesPublisher));
- self->asduLIst = NULL;
+ self->asduLIst = NULL;
- preparePacketBuffer(self, NULL, interfaceId);
+ preparePacketBuffer(self, parameters, interfaceId);
- return self;
+ return self;
}
SV_ASDU
@@ -378,7 +398,8 @@ SV_ASDU_encodeToBuffer(SV_ASDU self, uint8_t* buffer, int bufPos)
buffer[bufPos++] = self->smpSynch;
/* SmpRate */
- //TODO implement me
+ bufPos = BerEncoder_encodeTL(0x86, 2, buffer, bufPos);
+ bufPos = encodeUInt16FixedSize(self->smpRate, buffer, bufPos);
/* Sample */
bufPos = BerEncoder_encodeTL(0x87, self->dataSize, buffer, bufPos);
@@ -386,15 +407,11 @@ SV_ASDU_encodeToBuffer(SV_ASDU self, uint8_t* buffer, int bufPos)
self->_dataBuffer = buffer + bufPos;
bufPos += self->dataSize; /* data has to inserted by user before sending message */
-
+
/* SmpMod */
if (self->hasSmpMod) {
- bufPos = BerEncoder_encodeTL(0x84, 4, buffer, bufPos);
- buffer[bufPos++] = 0;
- buffer[bufPos++] = 0;
- buffer[bufPos++] = 0;
- buffer[bufPos++] = self->smpMod;
-
+ bufPos = BerEncoder_encodeTL(0x88, 4, buffer, bufPos);
+ bufPos = encodeUInt16FixedSize(self->smpMod, buffer, bufPos);
}
return bufPos;
@@ -474,7 +491,7 @@ SampledValuesPublisher_publish(SampledValuesPublisher self)
void
SampledValuesPublisher_destroy(SampledValuesPublisher self)
{
- GLOBAL_FREEMEM(self->buffer);
+ GLOBAL_FREEMEM(self->buffer);
}
@@ -517,6 +534,22 @@ SV_ASDU_setINT32(SV_ASDU self, int index, int32_t value)
encodeInt32FixedSize(value, self->_dataBuffer, index);
}
+int
+SV_ASDU_addINT64(SV_ASDU self)
+{
+ int index = self->dataSize;
+
+ self->dataSize += 8;
+
+ return index;
+}
+
+void
+SV_ASDU_setINT64(SV_ASDU self, int index, int64_t value)
+{
+ encodeInt64FixedSize(value, self->_dataBuffer, index);
+}
+
int
SV_ASDU_addFLOAT(SV_ASDU self)
{
@@ -532,7 +565,6 @@ SV_ASDU_setFLOAT(SV_ASDU self, int index, float value)
{
uint8_t* buf = (uint8_t*) &value;
-
#if (ORDER_LITTLE_ENDIAN == 1)
BerEncoder_revertByteOrder(buf, 4);
#endif
@@ -559,11 +591,15 @@ void
SV_ASDU_setFLOAT64(SV_ASDU self, int index, double value)
{
uint8_t* buf = (uint8_t*) &value;
+
#if (ORDER_LITTLE_ENDIAN == 1)
BerEncoder_revertByteOrder(buf, 8);
#endif
+
int i;
+
uint8_t* buffer = self->_dataBuffer + index;
+
for (i = 0; i < 8; i++) {
buffer[i] = buf[i];
}
@@ -605,3 +641,9 @@ SV_ASDU_setSmpMod(SV_ASDU self, uint8_t smpMod)
self->smpMod = smpMod;
}
+void
+SV_ASDU_setSmpRate(SV_ASDU self, uint16_t smpRate)
+{
+ self->hasSmpRate = true;
+ self->smpRate = smpRate;
+}
diff --git a/src/sampled_values/sv_publisher.h b/src/sampled_values/sv_publisher.h
index eeaf70e3..e86a5790 100644
--- a/src/sampled_values/sv_publisher.h
+++ b/src/sampled_values/sv_publisher.h
@@ -31,6 +31,17 @@
extern "C" {
#endif
+#ifndef GOOSE_SV_COMM_PARAMETERS
+#define GOOSE_SV_COMM_PARAMETERS
+
+typedef struct sCommParameters {
+ uint8_t vlanPriority;
+ uint16_t vlanId;
+ uint16_t appId;
+ uint8_t dstAddress[6];
+} CommParameters;
+
+#endif
#define IEC61850_SV_SMPSYNC_NOT_SYNCHRONIZED 0
#define IEC61850_SV_SMPSYNC_SYNCED_UNSPEC_LOCAL_CLOCK 1
@@ -45,7 +56,7 @@ typedef struct sSampledValuesPublisher* SampledValuesPublisher;
typedef struct sSV_ASDU* SV_ASDU;
SampledValuesPublisher
-SampledValuesPublisher_create(const char* interfaceId);
+SampledValuesPublisher_create(CommParameters* parameters, const char* interfaceId);
SV_ASDU
SampledValuesPublisher_addASDU(SampledValuesPublisher self, char* svID, char* datset, uint32_t confRev);
@@ -74,6 +85,12 @@ SV_ASDU_addINT32(SV_ASDU self);
void
SV_ASDU_setINT32(SV_ASDU self, int index, int32_t value);
+int
+SV_ASDU_addINT64(SV_ASDU self);
+
+void
+SV_ASDU_setINT64(SV_ASDU self, int index, int64_t value);
+
int
SV_ASDU_addFLOAT(SV_ASDU self);
@@ -110,6 +127,18 @@ SV_ASDU_setRefrTm(SV_ASDU self, uint64_t refrTm);
void
SV_ASDU_setSmpMod(SV_ASDU self, uint8_t smpMod);
+/**
+ * \brief Set the sample rate of the ASDU.
+ *
+ * If not set the transmitted ASDU will not contain an smpRate value.
+ *
+ * \param self the SV_ASDU
+ *
+ * \param smpRate Amount of samples (default per nominal period, see SmpMod).
+ */
+void
+SV_ASDU_setSmpRate(SV_ASDU self, uint16_t smpRate);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/sampled_values/sv_subscriber.c b/src/sampled_values/sv_subscriber.c
index 3f5333e3..1a0e2583 100644
--- a/src/sampled_values/sv_subscriber.c
+++ b/src/sampled_values/sv_subscriber.c
@@ -50,7 +50,13 @@ struct sSVReceiver {
uint8_t* buffer;
EthernetSocket ethSocket;
+
LinkedList subscriberList;
+
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore subscriberListLock;
+#endif
+
};
struct sSVSubscriber {
@@ -67,6 +73,7 @@ struct sSVClientASDU {
uint8_t* smpCnt;
uint8_t* confRev;
+ uint8_t* refrTm;
uint8_t* smpSynch;
@@ -87,6 +94,10 @@ SVReceiver_create(void)
self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH);
self->checkDestAddr = false;
+
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ self->subscriberListLock = Semaphore_create(1);
+#endif
}
return self;
@@ -110,13 +121,29 @@ SVReceiver_disableDestAddrCheck(SVReceiver self)
void
SVReceiver_addSubscriber(SVReceiver self, SVSubscriber subscriber)
{
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore_wait(self->subscriberListLock);
+#endif
+
LinkedList_add(self->subscriberList, (void*) subscriber);
+
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore_post(self->subscriberListLock);
+#endif
}
void
SVReceiver_removeSubscriber(SVReceiver self, SVSubscriber subscriber)
{
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore_wait(self->subscriberListLock);
+#endif
+
LinkedList_remove(self->subscriberList, (void*) subscriber);
+
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore_post(self->subscriberListLock);
+#endif
}
static void
@@ -173,6 +200,10 @@ SVReceiver_destroy(SVReceiver self)
LinkedList_destroyDeep(self->subscriberList,
(LinkedListValueDeleteFunction) SVSubscriber_destroy);
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore_destroy(self->subscriberListLock);
+#endif
+
GLOBAL_FREEMEM(self->buffer);
GLOBAL_FREEMEM(self);
}
@@ -232,6 +263,10 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
asdu.confRev = buffer + bufPos;
break;
+ case 0x84:
+ asdu.refrTm = buffer + bufPos;
+ break;
+
case 0x85:
asdu.smpSynch = buffer + bufPos;
break;
@@ -393,6 +428,11 @@ parseSVMessage(SVReceiver self, int numbytes)
/* check if there is a matching subscriber */
+
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore_wait(self->subscriberListLock);
+#endif
+
LinkedList element = LinkedList_getNext(self->subscriberList);
SVSubscriber subscriber;
@@ -422,6 +462,10 @@ parseSVMessage(SVReceiver self, int numbytes)
element = LinkedList_getNext(element);
}
+#if (CONFIG_MMS_THREADLESS_STACK == 0)
+ Semaphore_post(self->subscriberListLock);
+#endif
+
if (subscriberFound)
parseSVPayload(self, subscriber, buffer + bufPos, apduLength);
@@ -491,6 +535,52 @@ SVClientASDU_getSmpCnt(SVClientASDU self)
return retVal;
}
+static uint64_t
+decodeUtcTime(uint8_t* buffer, uint8_t* timeQuality)
+{
+ uint32_t timeval32;
+
+ timeval32 = buffer[3];
+ timeval32 += buffer[2] * 0x100;
+ timeval32 += buffer[1] * 0x10000;
+ timeval32 += buffer[0] * 0x1000000;
+
+ uint32_t msVal;
+
+ uint32_t fractionOfSecond;
+
+ fractionOfSecond = buffer[6];
+ fractionOfSecond += buffer[5] * 0x100;
+ fractionOfSecond += buffer[4] * 0x10000;
+
+ msVal = (uint32_t) (((uint64_t) fractionOfSecond * 1000) / 16777215);
+
+ if (timeQuality != NULL)
+ *timeQuality = buffer[7];
+
+ uint64_t timeval64 = (uint64_t) timeval32 * 1000 + (uint64_t) msVal;
+
+ return timeval64;
+}
+
+uint64_t
+SVClientASDU_getRefrTmAsMs(SVClientASDU self)
+{
+ uint64_t msTime = 0;
+
+ if (self->refrTm != NULL)
+ msTime = decodeUtcTime(self->refrTm, NULL);
+
+ return msTime;
+}
+
+bool
+SVClientASDU_hasRefrTm(SVClientASDU self)
+{
+ return (self->refrTm != NULL);
+}
+
+
const char*
SVClientASDU_getSvId(SVClientASDU self)
{
@@ -547,6 +637,20 @@ SVClientASDU_getINT32(SVClientASDU self, int index)
return retVal;
}
+int64_t
+SVClientASDU_getINT64(SVClientASDU self, int index)
+{
+ int64_t retVal = *((int64_t*) (self->dataBuffer + index));
+
+#if (ORDER_LITTLE_ENDIAN == 1)
+ uint8_t* buf = (uint8_t*) (&retVal);
+
+ BerEncoder_revertByteOrder(buf, 8);
+#endif
+
+ return retVal;
+}
+
uint8_t
SVClientASDU_getINT8U(SVClientASDU self, int index)
{
@@ -583,6 +687,19 @@ SVClientASDU_getINT32U(SVClientASDU self, int index)
return retVal;
}
+uint64_t
+SVClientASDU_getINT64U(SVClientASDU self, int index)
+{
+ uint64_t retVal = *((uint64_t*) (self->dataBuffer + index));
+
+#if (ORDER_LITTLE_ENDIAN == 1)
+ uint8_t* buf = (uint8_t*) (&retVal);
+
+ BerEncoder_revertByteOrder(buf, 8);
+#endif
+
+ return retVal;
+}
float
SVClientASDU_getFLOAT32(SVClientASDU self, int index)
diff --git a/src/sampled_values/sv_subscriber.h b/src/sampled_values/sv_subscriber.h
index c463e5bd..16ae7443 100644
--- a/src/sampled_values/sv_subscriber.h
+++ b/src/sampled_values/sv_subscriber.h
@@ -52,24 +52,25 @@ extern "C" {
*
* | IEC 61850 type | required bytes |
* | -------------- | -------------- |
- * | BOOLEAN | 1 byte |
- * | INT8 | 1 byte |
- * | INT16 | 2 byte |
- * | INT32 | 4 byte |
- * | INT64 | 8 byte |
- * | INT8U | 1 byte |
- * | INT16U | 2 byte |
- * | INT24U | 3 byte |
- * | INT32U | 4 byte |
- * | FLOAT32 | 4 byte |
- * | FLOAT64 | 8 byte |
- * | ENUMERATED | 4 byte |
- * | CODED ENUM | 4 byte |
- * | OCTET STRING | 20 byte |
- * | VISIBLE STRING | 35 byte |
- * | TimeStamp | 8 byte |
- * | EntryTime | 6 byte |
- * | BITSTRING | 4 byte |
+ * | BOOLEAN | 1 byte |
+ * | INT8 | 1 byte |
+ * | INT16 | 2 byte |
+ * | INT32 | 4 byte |
+ * | INT64 | 8 byte |
+ * | INT8U | 1 byte |
+ * | INT16U | 2 byte |
+ * | INT24U | 3 byte |
+ * | INT32U | 4 byte |
+ * | INT64U | 8 byte |
+ * | FLOAT32 | 4 byte |
+ * | FLOAT64 | 8 byte |
+ * | ENUMERATED | 4 byte |
+ * | CODED ENUM | 4 byte |
+ * | OCTET STRING | 20 byte |
+ * | VISIBLE STRING | 35 byte |
+ * | TimeStamp | 8 byte |
+ * | EntryTime | 6 byte |
+ * | BITSTRING | 4 byte |
*
* The SV subscriber API can be used independent of the IEC 61850 client API. In order to access the SVCB via MMS you
* have to use the IEC 61850 client API. Please see \ref ClientSVControlBlock object in section \ref IEC61850_CLIENT_SV.
@@ -268,6 +269,26 @@ SVClientASDU_getSvId(SVClientASDU self);
uint32_t
SVClientASDU_getConfRev(SVClientASDU self);
+/**
+ * \brief Check if RefrTm value is included in the SV ASDU
+ *
+ * \param self ASDU object instance
+ *
+ * \return true if RefrTm value is present, false otherwise
+ */
+bool
+SVClientASDU_hasRefrTm(SVClientASDU self);
+
+/**
+ * \brief Get the RefrTim value included in SV ASDU as ms timestamp
+ *
+ * \param self ASDU object instance
+ *
+ * \return the time value as ms timestamp or 0 if RefrTm is not present in the SV ASDU
+ */
+uint64_t
+SVClientASDU_getRefrTmAsMs(SVClientASDU self);
+
/**
* \brief Get an INT8 data value in the data part of the ASDU
*
@@ -301,6 +322,17 @@ SVClientASDU_getINT16(SVClientASDU self, int index);
int32_t
SVClientASDU_getINT32(SVClientASDU self, int index);
+/**
+ * \brief Get an INT64 data value in the data part of the ASDU
+ *
+ * \param self ASDU object instance
+ * \param index the index (byte position of the start) of the data in the data part
+ *
+ * \return SV data
+ */
+int64_t
+SVClientASDU_getINT64(SVClientASDU self, int index);
+
/**
* \brief Get an INT8U data value in the data part of the ASDU
*
@@ -334,6 +366,17 @@ SVClientASDU_getINT16U(SVClientASDU self, int index);
uint32_t
SVClientASDU_getINT32U(SVClientASDU self, int index);
+/**
+ * \brief Get an INT64U data value in the data part of the ASDU
+ *
+ * \param self ASDU object instance
+ * \param index the index (byte position of the start) of the data in the data part
+ *
+ * \return SV data
+ */
+uint64_t
+SVClientASDU_getINT64U(SVClientASDU self, int index);
+
/**
* \brief Get an FLOAT32 data value in the data part of the ASDU
*
diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def
index 065650a9..e3dcaccb 100644
--- a/src/vs/libiec61850-wo-goose.def
+++ b/src/vs/libiec61850-wo-goose.def
@@ -560,4 +560,16 @@ EXPORTS
IedConnection_readInt64Value
Timestamp_create
Timestamp_destroy
- Timestamp_setByMmsUtcTime
\ No newline at end of file
+ Timestamp_setByMmsUtcTime
+ IedServer_setLocalIpAddress
+ Timestamp_toMmsValue
+ MmsServer_installFileAccessHandler
+ MmsServer_setFilestoreBasepath
+ MmsConnection_setFilestoreBasepath
+ IedConnection_setFilestoreBasepath
+ IedServer_setFilestoreBasepath
+ IedModel_getDeviceByInst
+ MmsConnection_writeNamedVariableList
+ IedConnection_writeDataSetValues
+ MmsVariableSpecification_isValueOfType
+ IedServer_udpateDbposValue
diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def
index 3a2ca387..a69d7634 100644
--- a/src/vs/libiec61850.def
+++ b/src/vs/libiec61850.def
@@ -638,4 +638,19 @@ EXPORTS
IedConnection_readInt64Value
Timestamp_create
Timestamp_destroy
- Timestamp_setByMmsUtcTime
\ No newline at end of file
+ Timestamp_setByMmsUtcTime
+ IedServer_setLocalIpAddress
+ Timestamp_toMmsValue
+ MmsServer_installFileAccessHandler
+ MmsServer_setFilestoreBasepath
+ MmsConnection_setFilestoreBasepath
+ IedConnection_setFilestoreBasepath
+ IedServer_setFilestoreBasepath
+ GooseReceiver_isRunning
+ IedModel_getDeviceByInst
+ MmsConnection_writeNamedVariableList
+ SVClientASDU_hasRefrTm
+ SVClientASDU_getRefrTmAsMs
+ IedConnection_writeDataSetValues
+ MmsVariableSpecification_isValueOfType
+ IedServer_udpateDbposValue
diff --git a/third_party/sqlite/README b/third_party/sqlite/README
index 2e1781bf..02bb67e0 100644
--- a/third_party/sqlite/README
+++ b/third_party/sqlite/README
@@ -1 +1,2 @@
-Copy the sqlite amalagamation source code files (sqlite3.c sqlite3ext.h sqlite3.h) in this directory. You can download an archive withan archive with the files here: https://www.sqlite.org/download.html
+Copy the sqlite amalagamation source code files (sqlite3.c sqlite3ext.h sqlite3.h) in this directory. You can download an archive with the files here: https://www.sqlite.org/download.html
+
diff --git a/third_party/winpcap/README b/third_party/winpcap/README
deleted file mode 100644
index 9050673d..00000000
--- a/third_party/winpcap/README
+++ /dev/null
@@ -1,2 +0,0 @@
-For GOOSE support add winpcap source and headers here. Rerun cmake to configure the build system for GOOSE support.
-
diff --git a/tools/model_generator/gendyncode.jar b/tools/model_generator/gendyncode.jar
index 0721d44f..ba2bd0fa 100644
Binary files a/tools/model_generator/gendyncode.jar and b/tools/model_generator/gendyncode.jar differ
diff --git a/tools/model_generator/genmodel.jar b/tools/model_generator/genmodel.jar
index aa36640b..6c45543a 100644
Binary files a/tools/model_generator/genmodel.jar and b/tools/model_generator/genmodel.jar differ
diff --git a/tools/model_generator/modelviewer.jar b/tools/model_generator/modelviewer.jar
index 9beb17fe..4c6360d5 100644
Binary files a/tools/model_generator/modelviewer.jar and b/tools/model_generator/modelviewer.jar differ
diff --git a/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java b/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java
index 5eeb67e3..07980464 100644
--- a/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java
+++ b/tools/model_generator/src/com/libiec61850/scl/model/DataModelValue.java
@@ -23,6 +23,8 @@ package com.libiec61850.scl.model;
* See COPYING file for the complete license text.
*/
+import java.util.Base64;
+
import com.libiec61850.scl.types.EnumerationType;
import com.libiec61850.scl.types.IllegalValueException;
import com.libiec61850.scl.types.SclType;
@@ -128,6 +130,15 @@ public class DataModelValue {
case UNICODE_STRING_255:
this.value = value;
break;
+
+ case OCTET_STRING_64:
+ try {
+ this.value = Base64.getDecoder().decode(value);
+ }
+ catch (IllegalArgumentException e) {
+ throw new IllegalValueException("Val element for Octet64 type does not contain a valid base64 encoded string");
+ }
+ break;
case VISIBLE_STRING_32:
case VISIBLE_STRING_64:
diff --git a/tools/model_generator/src/com/libiec61850/tools/DynamicCodeGenerator.java b/tools/model_generator/src/com/libiec61850/tools/DynamicCodeGenerator.java
index 9a589860..2cc6ff00 100644
--- a/tools/model_generator/src/com/libiec61850/tools/DynamicCodeGenerator.java
+++ b/tools/model_generator/src/com/libiec61850/tools/DynamicCodeGenerator.java
@@ -189,8 +189,8 @@ public class DynamicCodeGenerator {
for (DataObjectDefinition dod : doType.getSubDataObjects()) {
- out.print(" DO_" + dod.getType() + "_createInstance(\"" + dod.getName() + "\")");
- out.println("(ModelNode*) newDo);");
+ out.print(" DO_" + dod.getType() + "_createInstance(\"" + dod.getName() + "\", ");
+ out.println("(ModelNode*) newDo, " + dod.getCount() + ");");
}
out.println("\n return newDo;");
diff --git a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
index d7b8b9e3..2db231b4 100644
--- a/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
+++ b/tools/model_generator/src/com/libiec61850/tools/StaticModelGenerator.java
@@ -727,6 +727,20 @@ public class StaticModelGenerator {
}
}
+
+ private void appendHexArrayString(StringBuffer buffer, byte[] byteArray) {
+
+ buffer.append("{");
+ for (int i = 0; i < byteArray.length; i++) {
+
+ if (i == 0)
+ buffer.append(String.format("0x%02X", byteArray[i]));
+ else
+ buffer.append(String.format(", 0x%02X", byteArray[i]));
+ }
+ buffer.append("}");
+
+ }
private void printValue(String daName, DataAttribute dataAttribute, DataModelValue value) {
@@ -759,6 +773,21 @@ public class StaticModelGenerator {
case BOOLEAN:
buffer.append("MmsValue_newBoolean(" + value.getValue() + ");");
break;
+
+ case OCTET_STRING_64:
+ {
+ String daValName = daName + "__val";
+
+ buffer.append("MmsValue_newOctetString(0, 64);\n");
+ buffer.append("uint8_t " + daValName + "[] = ");
+ appendHexArrayString(buffer, (byte[]) value.getValue());
+ buffer.append(";\n");
+ buffer.append("MmsValue_setOctetString(");
+ buffer.append(daName);
+ buffer.append(".mmsValue, " + daValName + ", " + ((byte[])value.getValue()).length + ");\n");
+ }
+ break;
+
case UNICODE_STRING_255:
buffer.append("MmsValue_newMmsString(\"" + value.getValue() + "\");");
break;