diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 793490e..18e9d3e 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -4,7 +4,7 @@ ENV TZ=America/Denver
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update && apt install -y \
- bash-completion build-essential cmake curl git git-lfs mbpoll sudo tmux tree vim wget xz-utils \
+ 7zip bash-completion build-essential cmake curl git git-lfs mbpoll sudo tmux tree vim wget xz-utils \
cmake libboost-dev libczmq-dev libxml2-dev libzmq3-dev pkg-config python3-dev python3-pip
ARG USERNAME=vscode
@@ -68,4 +68,8 @@ RUN /root/install-node-red.sh \
ADD ./src/js/node-red /root/.node-red/nodes/ot-sim
RUN cd /root/.node-red/nodes/ot-sim && npm install
+RUN wget -O snap7.7z https://versaweb.dl.sourceforge.net/project/snap7/1.4.2/snap7-full-1.4.2.7z \
+ && 7zz -o/tmp x snap7.7z && rm snap7.7z \
+ && make -C /tmp/snap7-full-1.4.2/build/unix -f x86_64_linux.mk install LibInstall=/usr/local/lib
+
RUN python3 -m pip install --break-system-packages opendssdirect.py~=0.8.4
diff --git a/.gitignore b/.gitignore
index 831b205..7bb0e8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
bin
build
+*.cmake
+CMakeFiles
+
__pycache__
diff --git a/CMakeCache.txt b/CMakeCache.txt
new file mode 100644
index 0000000..e3247e6
--- /dev/null
+++ b/CMakeCache.txt
@@ -0,0 +1,878 @@
+# This is the CMakeCache file.
+# For build in directory: /home/htoohey/repos/ot-sim
+# It was generated by CMake: /usr/bin/cmake
+# You can edit this file to change values found and used by cmake.
+# If you do not want to change any of the values, simply exit the editor.
+# If you do want to change a value, simply edit, save, and exit the editor.
+# The syntax for the file is as follows:
+# KEY:TYPE=VALUE
+# KEY is the name of a variable in the cache.
+# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
+# VALUE is the current value for the KEY.
+
+########################
+# EXTERNAL cache entries
+########################
+
+//Build E2E test executables
+BUILD_E2E:BOOL=OFF
+
+//The directory containing a CMake configuration file for Boost.
+Boost_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/Boost-1.74.0
+
+//Path to a file.
+Boost_INCLUDE_DIR:PATH=/usr/include
+
+//Path to a program.
+CLANG_FORMAT_EXE:FILEPATH=CLANG_FORMAT_EXE-NOTFOUND
+
+//Path to a program.
+CLANG_TIDY_EXE:FILEPATH=CLANG_TIDY_EXE-NOTFOUND
+
+//Path to a program.
+CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
+
+//Path to a program.
+CMAKE_AR:FILEPATH=/usr/bin/ar
+
+//Choose the type of build, options are: None Debug Release RelWithDebInfo
+// MinSizeRel ...
+CMAKE_BUILD_TYPE:STRING=
+
+//Enable/Disable color output during build.
+CMAKE_COLOR_MAKEFILE:BOOL=ON
+
+//CXX compiler
+CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-11
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-11
+
+//Flags used by the CXX compiler during all build types.
+CMAKE_CXX_FLAGS:STRING=
+
+//Flags used by the CXX compiler during DEBUG builds.
+CMAKE_CXX_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the CXX compiler during MINSIZEREL builds.
+CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//Flags used by the CXX compiler during RELEASE builds.
+CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the CXX compiler during RELWITHDEBINFO builds.
+CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//C compiler
+CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
+
+//A wrapper around 'ar' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-11
+
+//A wrapper around 'ranlib' adding the appropriate '--plugin' option
+// for the GCC compiler
+CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-11
+
+//Flags used by the C compiler during all build types.
+CMAKE_C_FLAGS:STRING=
+
+//Flags used by the C compiler during DEBUG builds.
+CMAKE_C_FLAGS_DEBUG:STRING=-g
+
+//Flags used by the C compiler during MINSIZEREL builds.
+CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
+
+//Flags used by the C compiler during RELEASE builds.
+CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
+
+//Flags used by the C compiler during RELWITHDEBINFO builds.
+CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
+
+//Path to a program.
+CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
+
+//Flags used by the linker during all build types.
+CMAKE_EXE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during DEBUG builds.
+CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during MINSIZEREL builds.
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during RELEASE builds.
+CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during RELWITHDEBINFO builds.
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Enable/Disable output of compile commands during generation.
+CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
+
+//User executables (bin)
+CMAKE_INSTALL_BINDIR:PATH=bin
+
+//Read-only architecture-independent data (DATAROOTDIR)
+CMAKE_INSTALL_DATADIR:PATH=
+
+//Read-only architecture-independent data root (share)
+CMAKE_INSTALL_DATAROOTDIR:PATH=share
+
+//Documentation root (DATAROOTDIR/doc/PROJECT_NAME)
+CMAKE_INSTALL_DOCDIR:PATH=
+
+//C header files (include)
+CMAKE_INSTALL_INCLUDEDIR:PATH=include
+
+//Info documentation (DATAROOTDIR/info)
+CMAKE_INSTALL_INFODIR:PATH=
+
+//Object code libraries (lib)
+CMAKE_INSTALL_LIBDIR:PATH=lib
+
+//Program executables (libexec)
+CMAKE_INSTALL_LIBEXECDIR:PATH=libexec
+
+//Locale-dependent data (DATAROOTDIR/locale)
+CMAKE_INSTALL_LOCALEDIR:PATH=
+
+//Modifiable single-machine data (var)
+CMAKE_INSTALL_LOCALSTATEDIR:PATH=var
+
+//Man documentation (DATAROOTDIR/man)
+CMAKE_INSTALL_MANDIR:PATH=
+
+//C header files for non-gcc (/usr/include)
+CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include
+
+//Install path prefix, prepended onto install directories.
+CMAKE_INSTALL_PREFIX:PATH=/usr/local
+
+//Run-time variable data (LOCALSTATEDIR/run)
+CMAKE_INSTALL_RUNSTATEDIR:PATH=
+
+//System admin executables (sbin)
+CMAKE_INSTALL_SBINDIR:PATH=sbin
+
+//Modifiable architecture-independent data (com)
+CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com
+
+//Read-only single-machine data (etc)
+CMAKE_INSTALL_SYSCONFDIR:PATH=etc
+
+//Path to a program.
+CMAKE_LINKER:FILEPATH=/usr/bin/ld
+
+//Path to a program.
+CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake
+
+//Flags used by the linker during the creation of modules during
+// all build types.
+CMAKE_MODULE_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of modules during
+// DEBUG builds.
+CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of modules during
+// MINSIZEREL builds.
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELEASE builds.
+CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of modules during
+// RELWITHDEBINFO builds.
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_NM:FILEPATH=/usr/bin/nm
+
+//Path to a program.
+CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
+
+//Path to a program.
+CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
+
+//Value Computed by CMake
+CMAKE_PROJECT_DESCRIPTION:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_NAME:STATIC=ot-sim
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION:STATIC=4.8.1
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_MAJOR:STATIC=4
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_MINOR:STATIC=8
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_PATCH:STATIC=1
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_TWEAK:STATIC=
+
+//Path to a program.
+CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
+
+//Path to a program.
+CMAKE_READELF:FILEPATH=/usr/bin/readelf
+
+//Flags used by the linker during the creation of shared libraries
+// during all build types.
+CMAKE_SHARED_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during DEBUG builds.
+CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during MINSIZEREL builds.
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during RELEASE builds.
+CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during RELWITHDEBINFO builds.
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//If set, runtime paths are not added when installing shared libraries,
+// but are added when building.
+CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
+
+//If set, runtime paths are not added when using shared libraries.
+CMAKE_SKIP_RPATH:BOOL=NO
+
+//Flags used by the linker during the creation of static libraries
+// during all build types.
+CMAKE_STATIC_LINKER_FLAGS:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during DEBUG builds.
+CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during MINSIZEREL builds.
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELEASE builds.
+CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELWITHDEBINFO builds.
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//Path to a program.
+CMAKE_STRIP:FILEPATH=/usr/bin/strip
+
+//If this value is on, makefiles will be generated without the
+// .SILENT directive, and all commands will be echoed to the console
+// during the make. This is useful for debugging only. With Visual
+// Studio IDE projects all commands are done without /nologo.
+CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
+
+//Enable to build Debian packages
+CPACK_BINARY_DEB:BOOL=OFF
+
+//Enable to build FreeBSD packages
+CPACK_BINARY_FREEBSD:BOOL=OFF
+
+//Enable to build IFW packages
+CPACK_BINARY_IFW:BOOL=OFF
+
+//Enable to build NSIS packages
+CPACK_BINARY_NSIS:BOOL=OFF
+
+//Enable to build RPM packages
+CPACK_BINARY_RPM:BOOL=OFF
+
+//Enable to build STGZ packages
+CPACK_BINARY_STGZ:BOOL=ON
+
+//Enable to build TBZ2 packages
+CPACK_BINARY_TBZ2:BOOL=OFF
+
+//Enable to build TGZ packages
+CPACK_BINARY_TGZ:BOOL=ON
+
+//Enable to build TXZ packages
+CPACK_BINARY_TXZ:BOOL=OFF
+
+//Enable to build TZ packages
+CPACK_BINARY_TZ:BOOL=ON
+
+//Enable to build RPM source packages
+CPACK_SOURCE_RPM:BOOL=OFF
+
+//Enable to build TBZ2 source packages
+CPACK_SOURCE_TBZ2:BOOL=ON
+
+//Enable to build TGZ source packages
+CPACK_SOURCE_TGZ:BOOL=ON
+
+//Enable to build TXZ source packages
+CPACK_SOURCE_TXZ:BOOL=ON
+
+//Enable to build TZ source packages
+CPACK_SOURCE_TZ:BOOL=ON
+
+//Enable to build ZIP source packages
+CPACK_SOURCE_ZIP:BOOL=OFF
+
+//install path for cppzmqConfig.cmake
+CPPZMQ_CMAKECONFIG_INSTALL_DIR:STRING=share/cmake/cppzmq
+
+//Enable code coverage target
+DNP3_COVERAGE:BOOL=OFF
+
+//Build all optional targets
+DNP3_EVERYTHING:BOOL=OFF
+
+//Build example applications
+DNP3_EXAMPLES:BOOL=OFF
+
+//Build Google OSS-Fuzz targets
+DNP3_FUZZING:BOOL=OFF
+
+//Building the native Java bindings
+DNP3_JAVA:BOOL=OFF
+
+//Build static libraries instead of shared libraries
+DNP3_STATIC_LIBS:BOOL=OFF
+
+//Build unit and integration tests
+DNP3_TESTS:BOOL=OFF
+
+//Build TLS client/server support (requires OpenSSL)
+DNP3_TLS:BOOL=OFF
+
+//Build and install draft classes and methods
+ENABLE_DRAFTS:BOOL=ON
+
+//Directory under which to collect all populated content
+FETCHCONTENT_BASE_DIR:PATH=/home/htoohey/repos/ot-sim/_deps
+
+//Disables all attempts to download or update content and assumes
+// source dirs already exist
+FETCHCONTENT_FULLY_DISCONNECTED:BOOL=OFF
+
+//Enables QUIET option for all content population
+FETCHCONTENT_QUIET:BOOL=ON
+
+//When not empty, overrides where to find pre-populated content
+// for asio
+FETCHCONTENT_SOURCE_DIR_ASIO:PATH=
+
+//When not empty, overrides where to find pre-populated content
+// for exe4cpp
+FETCHCONTENT_SOURCE_DIR_EXE4CPP:PATH=
+
+//When not empty, overrides where to find pre-populated content
+// for ser4cpp
+FETCHCONTENT_SOURCE_DIR_SER4CPP:PATH=
+
+//Enables UPDATE_DISCONNECTED behavior for all content population
+FETCHCONTENT_UPDATES_DISCONNECTED:BOOL=OFF
+
+//Enables UPDATE_DISCONNECTED behavior just for population of asio
+FETCHCONTENT_UPDATES_DISCONNECTED_ASIO:BOOL=OFF
+
+//Enables UPDATE_DISCONNECTED behavior just for population of exe4cpp
+FETCHCONTENT_UPDATES_DISCONNECTED_EXE4CPP:BOOL=OFF
+
+//Enables UPDATE_DISCONNECTED behavior just for population of ser4cpp
+FETCHCONTENT_UPDATES_DISCONNECTED_SER4CPP:BOOL=OFF
+
+//Value Computed by CMake
+FMT_BINARY_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/fmt
+
+//Generate the cuda-test target.
+FMT_CUDA_TEST:BOOL=OFF
+
+//Debug library postfix.
+FMT_DEBUG_POSTFIX:STRING=d
+
+//Generate the doc target.
+FMT_DOC:BOOL=OFF
+
+//Generate the fuzz target.
+FMT_FUZZ:BOOL=OFF
+
+//Installation directory for include files, a relative path that
+// will be joined with /usr/local or an absolute path.
+FMT_INC_DIR:STRING=include
+
+//Generate the install target.
+FMT_INSTALL:BOOL=OFF
+
+//Value Computed by CMake
+FMT_IS_TOP_LEVEL:STATIC=OFF
+
+//Build a module instead of a traditional library.
+FMT_MODULE:BOOL=OFF
+
+//Include core requiring OS (Windows/Posix)
+FMT_OS:BOOL=ON
+
+//Enable extra warnings and expensive tests.
+FMT_PEDANTIC:BOOL=OFF
+
+//Value Computed by CMake
+FMT_SOURCE_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/fmt
+
+//Expose headers with marking them as system.
+FMT_SYSTEM_HEADERS:BOOL=OFF
+
+//Generate the test target.
+FMT_TEST:BOOL=OFF
+
+//Halt the compilation with an error on compiler warnings.
+FMT_WERROR:BOOL=OFF
+
+//Git command line client
+GIT_EXECUTABLE:FILEPATH=/usr/bin/git
+
+//Enable CI build targets.
+JSON_CI:BOOL=OFF
+
+//Use extended diagnostic messages.
+JSON_Diagnostics:BOOL=OFF
+
+//Enable implicit conversions.
+JSON_ImplicitConversions:BOOL=ON
+
+//Install CMake targets during install step.
+JSON_Install:BOOL=OFF
+
+//Use non-amalgamated version of the library.
+JSON_MultipleHeaders:BOOL=OFF
+
+//Include as system headers (skip for clang-tidy).
+JSON_SystemInclude:BOOL=OFF
+
+//Path to a file.
+LIBXML2_INCLUDE_DIR:PATH=/usr/include/libxml2
+
+//Path to a library.
+LIBXML2_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libxml2.so
+
+//Path to a program.
+LIBXML2_XMLLINT_EXECUTABLE:FILEPATH=LIBXML2_XMLLINT_EXECUTABLE-NOTFOUND
+
+//Arguments to supply to pkg-config
+PKG_CONFIG_ARGN:STRING=
+
+//pkg-config executable
+PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config
+
+//The directory containing a CMake configuration file for ZeroMQ.
+ZeroMQ_DIR:PATH=ZeroMQ_DIR-NOTFOUND
+
+//Path to a file.
+ZeroMQ_INCLUDE_DIR:PATH=/usr/include
+
+//Path to a library.
+ZeroMQ_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libzmq.so
+
+//The directory containing a CMake configuration file for boost_headers.
+boost_headers_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/boost_headers-1.74.0
+
+//Value Computed by CMake
+cppzmq_BINARY_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/cppzmq
+
+//Value Computed by CMake
+cppzmq_IS_TOP_LEVEL:STATIC=OFF
+
+//Value Computed by CMake
+cppzmq_SOURCE_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/cppzmq
+
+//Value Computed by CMake
+nlohmann_json_BINARY_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/json
+
+//Value Computed by CMake
+nlohmann_json_IS_TOP_LEVEL:STATIC=OFF
+
+//Value Computed by CMake
+nlohmann_json_SOURCE_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/json
+
+//Value Computed by CMake
+opendnp3_BINARY_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/opendnp3
+
+//Value Computed by CMake
+opendnp3_IS_TOP_LEVEL:STATIC=OFF
+
+//Value Computed by CMake
+opendnp3_SOURCE_DIR:STATIC=/home/htoohey/repos/ot-sim/src/c++/deps/opendnp3
+
+//Dependencies for the target
+ot-sim-dnp3_LIB_DEPENDS:STATIC=general;fmt::fmt;general;opendnp3;general;ot-sim-msgbus;
+
+//Dependencies for the target
+ot-sim-snap7_LIB_DEPENDS:STATIC=general;fmt::fmt;general;ot-sim-msgbus;
+
+//Value Computed by CMake
+ot-sim_BINARY_DIR:STATIC=/home/htoohey/repos/ot-sim
+
+//Value Computed by CMake
+ot-sim_IS_TOP_LEVEL:STATIC=ON
+
+//Value Computed by CMake
+ot-sim_SOURCE_DIR:STATIC=/home/htoohey/repos/ot-sim
+
+//Path to a library.
+pkgcfg_lib_PC_LIBXML_xml2:FILEPATH=/usr/lib/x86_64-linux-gnu/libxml2.so
+
+//Path to a library.
+pkgcfg_lib_PC_LIBZMQ_zmq:FILEPATH=/usr/lib/x86_64-linux-gnu/libzmq.so
+
+
+########################
+# INTERNAL cache entries
+########################
+
+//ADVANCED property for variable: Boost_DIR
+Boost_DIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_ADDR2LINE
+CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_AR
+CMAKE_AR-ADVANCED:INTERNAL=1
+//This is the directory where this CMakeCache.txt was created
+CMAKE_CACHEFILE_DIR:INTERNAL=/home/htoohey/repos/ot-sim
+//Major version of cmake used to create the current loaded cache
+CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
+//Minor version of cmake used to create the current loaded cache
+CMAKE_CACHE_MINOR_VERSION:INTERNAL=22
+//Patch version of cmake used to create the current loaded cache
+CMAKE_CACHE_PATCH_VERSION:INTERNAL=1
+//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE
+CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1
+//Path to CMake executable.
+CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
+//Path to cpack program executable.
+CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
+//Path to ctest program executable.
+CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
+//ADVANCED property for variable: CMAKE_CXX_COMPILER
+CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
+CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB
+CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS
+CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
+CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
+CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
+CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
+CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER
+CMAKE_C_COMPILER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_AR
+CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB
+CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS
+CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
+CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
+CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
+CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
+CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_DLLTOOL
+CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
+//Executable file format
+CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
+CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
+CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
+CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS
+CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1
+//Name of external makefile project generator.
+CMAKE_EXTRA_GENERATOR:INTERNAL=
+//Name of generator.
+CMAKE_GENERATOR:INTERNAL=Unix Makefiles
+//Generator instance identifier.
+CMAKE_GENERATOR_INSTANCE:INTERNAL=
+//Name of generator platform.
+CMAKE_GENERATOR_PLATFORM:INTERNAL=
+//Name of generator toolset.
+CMAKE_GENERATOR_TOOLSET:INTERNAL=
+//Test CMAKE_HAVE_LIBC_PTHREAD
+CMAKE_HAVE_LIBC_PTHREAD:INTERNAL=1
+//Have include pthread.h
+CMAKE_HAVE_PTHREAD_H:INTERNAL=1
+//Source directory with the top level CMakeLists.txt file for this
+// project
+CMAKE_HOME_DIRECTORY:INTERNAL=/home/htoohey/repos/ot-sim
+//ADVANCED property for variable: CMAKE_INSTALL_BINDIR
+CMAKE_INSTALL_BINDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DATADIR
+CMAKE_INSTALL_DATADIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DATAROOTDIR
+CMAKE_INSTALL_DATAROOTDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DOCDIR
+CMAKE_INSTALL_DOCDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_INCLUDEDIR
+CMAKE_INSTALL_INCLUDEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_INFODIR
+CMAKE_INSTALL_INFODIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LIBDIR
+CMAKE_INSTALL_LIBDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LIBEXECDIR
+CMAKE_INSTALL_LIBEXECDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR
+CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LOCALSTATEDIR
+CMAKE_INSTALL_LOCALSTATEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_MANDIR
+CMAKE_INSTALL_MANDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_OLDINCLUDEDIR
+CMAKE_INSTALL_OLDINCLUDEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_RUNSTATEDIR
+CMAKE_INSTALL_RUNSTATEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SBINDIR
+CMAKE_INSTALL_SBINDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SHAREDSTATEDIR
+CMAKE_INSTALL_SHAREDSTATEDIR-ADVANCED:INTERNAL=1
+//Install .so files without execute permission.
+CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SYSCONFDIR
+CMAKE_INSTALL_SYSCONFDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_LINKER
+CMAKE_LINKER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MAKE_PROGRAM
+CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
+CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
+CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
+CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_NM
+CMAKE_NM-ADVANCED:INTERNAL=1
+//number of local generators
+CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=14
+//ADVANCED property for variable: CMAKE_OBJCOPY
+CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_OBJDUMP
+CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
+//Platform information initialized
+CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RANLIB
+CMAKE_RANLIB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_READELF
+CMAKE_READELF-ADVANCED:INTERNAL=1
+//Path to CMake installation.
+CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.22
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
+CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
+CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
+CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
+CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_RPATH
+CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
+CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
+CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
+CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STRIP
+CMAKE_STRIP-ADVANCED:INTERNAL=1
+//uname command
+CMAKE_UNAME:INTERNAL=/usr/bin/uname
+//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
+CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_DEB
+CPACK_BINARY_DEB-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_FREEBSD
+CPACK_BINARY_FREEBSD-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_IFW
+CPACK_BINARY_IFW-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_NSIS
+CPACK_BINARY_NSIS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_RPM
+CPACK_BINARY_RPM-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_STGZ
+CPACK_BINARY_STGZ-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_TBZ2
+CPACK_BINARY_TBZ2-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_TGZ
+CPACK_BINARY_TGZ-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_TXZ
+CPACK_BINARY_TXZ-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_BINARY_TZ
+CPACK_BINARY_TZ-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_SOURCE_RPM
+CPACK_SOURCE_RPM-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_SOURCE_TBZ2
+CPACK_SOURCE_TBZ2-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_SOURCE_TGZ
+CPACK_SOURCE_TGZ-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_SOURCE_TXZ
+CPACK_SOURCE_TXZ-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_SOURCE_TZ
+CPACK_SOURCE_TZ-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CPACK_SOURCE_ZIP
+CPACK_SOURCE_ZIP-ADVANCED:INTERNAL=1
+//Details about finding Boost
+FIND_PACKAGE_MESSAGE_DETAILS_Boost:INTERNAL=[/usr/lib/x86_64-linux-gnu/cmake/Boost-1.74.0/BoostConfig.cmake][c ][v1.74.0()]
+//Details about finding LibXml2
+FIND_PACKAGE_MESSAGE_DETAILS_LibXml2:INTERNAL=[/usr/lib/x86_64-linux-gnu/libxml2.so][/usr/include/libxml2][v2.9.13()]
+//Details about finding PkgConfig
+FIND_PACKAGE_MESSAGE_DETAILS_PkgConfig:INTERNAL=[/usr/bin/pkg-config][v0.29.2()]
+//Details about finding Threads
+FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()]
+//Details about finding ZeroMQ
+FIND_PACKAGE_MESSAGE_DETAILS_ZeroMQ:INTERNAL=[/usr/lib/x86_64-linux-gnu/libzmq.so][/usr/include][v()]
+//Test FMT_HAS_VARIANT
+FMT_HAS_VARIANT:INTERNAL=1
+//ADVANCED property for variable: GIT_EXECUTABLE
+GIT_EXECUTABLE-ADVANCED:INTERNAL=1
+//Have symbol strtod_l
+HAVE_STRTOD_L:INTERNAL=
+//ADVANCED property for variable: LIBXML2_INCLUDE_DIR
+LIBXML2_INCLUDE_DIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: LIBXML2_LIBRARY
+LIBXML2_LIBRARY-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: LIBXML2_XMLLINT_EXECUTABLE
+LIBXML2_XMLLINT_EXECUTABLE-ADVANCED:INTERNAL=1
+NLOHMANN_JSON_CONFIG_INSTALL_DIR:INTERNAL=lib/cmake/nlohmann_json
+PC_LIBXML_CFLAGS:INTERNAL=-I/usr/include/libxml2
+PC_LIBXML_CFLAGS_I:INTERNAL=
+PC_LIBXML_CFLAGS_OTHER:INTERNAL=
+PC_LIBXML_FOUND:INTERNAL=1
+PC_LIBXML_INCLUDEDIR:INTERNAL=/usr/include
+PC_LIBXML_INCLUDE_DIRS:INTERNAL=/usr/include/libxml2
+PC_LIBXML_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lxml2
+PC_LIBXML_LDFLAGS_OTHER:INTERNAL=
+PC_LIBXML_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu
+PC_LIBXML_LIBRARIES:INTERNAL=xml2
+PC_LIBXML_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu
+PC_LIBXML_LIBS:INTERNAL=
+PC_LIBXML_LIBS_L:INTERNAL=
+PC_LIBXML_LIBS_OTHER:INTERNAL=
+PC_LIBXML_LIBS_PATHS:INTERNAL=
+PC_LIBXML_MODULE_NAME:INTERNAL=libxml-2.0
+PC_LIBXML_PREFIX:INTERNAL=/usr
+PC_LIBXML_STATIC_CFLAGS:INTERNAL=-I/usr/include/libxml2
+PC_LIBXML_STATIC_CFLAGS_I:INTERNAL=
+PC_LIBXML_STATIC_CFLAGS_OTHER:INTERNAL=
+PC_LIBXML_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include/libxml2
+PC_LIBXML_STATIC_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lxml2;-licui18n;-licuuc;-licudata;-lz;-llzma;-lm
+PC_LIBXML_STATIC_LDFLAGS_OTHER:INTERNAL=
+PC_LIBXML_STATIC_LIBDIR:INTERNAL=
+PC_LIBXML_STATIC_LIBRARIES:INTERNAL=xml2;icui18n;icuuc;icudata;z;lzma;m
+PC_LIBXML_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu
+PC_LIBXML_STATIC_LIBS:INTERNAL=
+PC_LIBXML_STATIC_LIBS_L:INTERNAL=
+PC_LIBXML_STATIC_LIBS_OTHER:INTERNAL=
+PC_LIBXML_STATIC_LIBS_PATHS:INTERNAL=
+PC_LIBXML_VERSION:INTERNAL=2.9.13
+PC_LIBXML_libxml-2.0_INCLUDEDIR:INTERNAL=
+PC_LIBXML_libxml-2.0_LIBDIR:INTERNAL=
+PC_LIBXML_libxml-2.0_PREFIX:INTERNAL=
+PC_LIBXML_libxml-2.0_VERSION:INTERNAL=
+PC_LIBZMQ_CFLAGS:INTERNAL=-isystem;/usr/include/mit-krb5;-I/usr/include/pgm-5.3;-I/usr/include/libxml2
+PC_LIBZMQ_CFLAGS_I:INTERNAL=
+PC_LIBZMQ_CFLAGS_OTHER:INTERNAL=
+PC_LIBZMQ_FOUND:INTERNAL=1
+PC_LIBZMQ_INCLUDEDIR:INTERNAL=/usr/include
+PC_LIBZMQ_INCLUDE_DIRS:INTERNAL=/usr/include/mit-krb5;/usr/include/pgm-5.3;/usr/include/libxml2
+PC_LIBZMQ_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lzmq
+PC_LIBZMQ_LDFLAGS_OTHER:INTERNAL=
+PC_LIBZMQ_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu
+PC_LIBZMQ_LIBRARIES:INTERNAL=zmq
+PC_LIBZMQ_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu
+PC_LIBZMQ_LIBS:INTERNAL=
+PC_LIBZMQ_LIBS_L:INTERNAL=
+PC_LIBZMQ_LIBS_OTHER:INTERNAL=
+PC_LIBZMQ_LIBS_PATHS:INTERNAL=
+PC_LIBZMQ_MODULE_NAME:INTERNAL=libzmq
+PC_LIBZMQ_PREFIX:INTERNAL=/usr
+PC_LIBZMQ_STATIC_CFLAGS:INTERNAL=-isystem;/usr/include/mit-krb5;-I/usr/include/pgm-5.3;-I/usr/include/libxml2
+PC_LIBZMQ_STATIC_CFLAGS_I:INTERNAL=
+PC_LIBZMQ_STATIC_CFLAGS_OTHER:INTERNAL=
+PC_LIBZMQ_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include/mit-krb5;/usr/include/pgm-5.3;/usr/include/libxml2
+PC_LIBZMQ_STATIC_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-L/usr/lib/x86_64-linux-gnu/mit-krb5;-L/usr/lib/x86_64-linux-gnu;-lzmq;-lstdc++;-lpthread;-lrt;-lgssapi_krb5;-lkrb5;-lk5crypto;-lcom_err;-lkrb5support;-lsodium;-pthread;-lpgm;-lpthread;-lm;-lnorm;libprotokit.a;-lxml2;-licui18n;-licuuc;-licudata;-lz;-llzma;-lm;-lbsd;-lmd
+PC_LIBZMQ_STATIC_LDFLAGS_OTHER:INTERNAL=-pthread;libprotokit.a
+PC_LIBZMQ_STATIC_LIBDIR:INTERNAL=
+PC_LIBZMQ_STATIC_LIBRARIES:INTERNAL=zmq;stdc++;pthread;rt;gssapi_krb5;krb5;k5crypto;com_err;krb5support;sodium;pgm;pthread;m;norm;xml2;icui18n;icuuc;icudata;z;lzma;m;bsd;md
+PC_LIBZMQ_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu;/usr/lib/x86_64-linux-gnu/mit-krb5;/usr/lib/x86_64-linux-gnu
+PC_LIBZMQ_STATIC_LIBS:INTERNAL=
+PC_LIBZMQ_STATIC_LIBS_L:INTERNAL=
+PC_LIBZMQ_STATIC_LIBS_OTHER:INTERNAL=
+PC_LIBZMQ_STATIC_LIBS_PATHS:INTERNAL=
+PC_LIBZMQ_VERSION:INTERNAL=4.3.4
+PC_LIBZMQ_libzmq_INCLUDEDIR:INTERNAL=
+PC_LIBZMQ_libzmq_LIBDIR:INTERNAL=
+PC_LIBZMQ_libzmq_PREFIX:INTERNAL=
+PC_LIBZMQ_libzmq_VERSION:INTERNAL=
+//ADVANCED property for variable: PKG_CONFIG_ARGN
+PKG_CONFIG_ARGN-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: PKG_CONFIG_EXECUTABLE
+PKG_CONFIG_EXECUTABLE-ADVANCED:INTERNAL=1
+//Test SUPPORTS_USER_DEFINED_LITERALS
+SUPPORTS_USER_DEFINED_LITERALS:INTERNAL=1
+//CMAKE_INSTALL_PREFIX during last run
+_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=/usr/local
+__pkg_config_arguments_PC_LIBXML:INTERNAL=QUIET;libxml-2.0
+__pkg_config_arguments_PC_LIBZMQ:INTERNAL=QUIET;libzmq
+__pkg_config_checked_PC_LIBXML:INTERNAL=1
+__pkg_config_checked_PC_LIBZMQ:INTERNAL=1
+//ADVANCED property for variable: boost_headers_DIR
+boost_headers_DIR-ADVANCED:INTERNAL=1
+//Test has_std_17_flag
+has_std_17_flag:INTERNAL=1
+//Test has_std_1z_flag
+has_std_1z_flag:INTERNAL=1
+//ADVANCED property for variable: pkgcfg_lib_PC_LIBXML_xml2
+pkgcfg_lib_PC_LIBXML_xml2-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: pkgcfg_lib_PC_LIBZMQ_zmq
+pkgcfg_lib_PC_LIBZMQ_zmq-ADVANCED:INTERNAL=1
+prefix_result:INTERNAL=/usr/lib/x86_64-linux-gnu
+
diff --git a/Dockerfile b/Dockerfile
index 09073aa..47eb963 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -13,7 +13,7 @@ ADD .git /usr/local/src/ot-sim/.git
ADD src/go /usr/local/src/ot-sim/src/go
RUN make -C /usr/local/src/ot-sim/src/go install
-FROM python:3.11-bookworm as pybuild
+FROM python:3.11-bookworm AS pybuild
ADD .git /usr/local/src/ot-sim/.git
@@ -26,6 +26,7 @@ ENV TZ=Etc/UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update && apt install -y \
+ 7zip \
build-essential \
cmake \
git \
@@ -38,6 +39,11 @@ RUN apt update && apt install -y \
python3-pip \
wget
+# TODO: add TARGETARCH support for Snap7.
+RUN wget -O snap7.7z https://versaweb.dl.sourceforge.net/project/snap7/1.4.2/snap7-full-1.4.2.7z \
+ && 7zz -o/tmp x snap7.7z && rm snap7.7z \
+ && make -C /tmp/snap7-full-1.4.2/build/unix -f x86_64_linux.mk install LibInstall=/usr/local/lib
+
ADD .git /usr/local/src/ot-sim/.git
ADD CMakeLists.txt /usr/local/src/ot-sim/CMakeLists.txt
@@ -63,15 +69,15 @@ RUN curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.noarmor.gpg \
WORKDIR /root
-ADD install-node-red.sh .
+#ADD install-node-red.sh .
# needed by nod-red install script
ARG TARGETARCH
-RUN /root/install-node-red.sh \
- && rm /root/install-node-red.sh
+#RUN /root/install-node-red.sh \
+# && rm /root/install-node-red.sh
-ADD ./src/js/node-red /root/.node-red/nodes/ot-sim
-RUN cd /root/.node-red/nodes/ot-sim && npm install && cd /root
+#ADD ./src/js/node-red /root/.node-red/nodes/ot-sim
+#RUN cd /root/.node-red/nodes/ot-sim && npm install && cd /root
COPY --from=gobuild /usr/local /usr/local
COPY --from=pybuild /usr/local /usr/local
@@ -110,15 +116,15 @@ RUN wget -O overmind.gz https://github.com/DarthSim/overmind/releases/download/v
WORKDIR /root
-ADD install-node-red.sh .
+#ADD install-node-red.sh .
# needed by nod-red install script
-ARG TARGETARCH
-RUN /root/install-node-red.sh \
- && rm /root/install-node-red.sh
+#ARG TARGETARCH
+#RUN /root/install-node-red.sh \
+ #&& rm /root/install-node-red.sh
-ADD ./src/js/node-red /root/.node-red/nodes/ot-sim
-RUN cd /root/.node-red/nodes/ot-sim && npm install && cd /root
+#ADD ./src/js/node-red /root/.node-red/nodes/ot-sim
+#RUN cd /root/.node-red/nodes/ot-sim && npm install && cd /root
COPY --from=gobuild /usr/local /usr/local
COPY --from=pybuild /usr/local /usr/local
diff --git a/Procfile.single b/Procfile.single
index d604a08..6ea4a8d 100644
--- a/Procfile.single
+++ b/Procfile.single
@@ -1,3 +1,3 @@
broker: python3 testing/e2e/helics/broker.py
dss: python3 testing/e2e/helics/opendss-federate.py
-cpu: ot-sim-cpu-module config/single-device/device.xml
+cpu: ot-sim-cpu-module config/single-device/device2.xml
diff --git a/config/single-device/device.xml b/config/single-device/device.xml
index 2d8cf6c..7403135 100644
--- a/config/single-device/device.xml
+++ b/config/single-device/device.xml
@@ -9,6 +9,7 @@
ot-sim-io-module {{config_file}}
ot-sim-modbus-module {{config_file}}
ot-sim-dnp3-module {{config_file}}
+ ot-sim-s7comm-module {{config_file}}
ot-sim-telnet-module {{config_file}}
ot-sim-node-red-module {{config_file}}
diff --git a/config/single-device/device2.xml b/config/single-device/device2.xml
new file mode 100644
index 0000000..9cd603e
--- /dev/null
+++ b/config/single-device/device2.xml
@@ -0,0 +1,87 @@
+
+
+
+ tcp://127.0.0.1:1234
+ tcp://127.0.0.1:5678
+
+
+ ot-sim-message-bus {{config_file}}
+ ot-sim-io-module {{config_file}}
+ ot-sim-modbus-module {{config_file}}
+ ot-sim-s7comm-module {{config_file}}
+ ot-sim-telnet-module {{config_file}}
+ ot-sim-node-red-module {{config_file}}
+
+
+ node-red
+ /etc/node-red.js
+ dark
+ config/single-device/node-red-hmi.json
+
+
+
+
+ :23
+ default
+
+
+ 127.0.0.1:5502
+
+ 0
+ line-650632.closed
+
+
+ 30000
+ line-650632.kW
+ -2
+
+
+
+ 0.0.0.0:20000
+
+ line-650632.closed
+ 0
+
+
+
+ line-650632.kW
+ 0
+
+
+
+ localhost
+ ot-sim-io
+
+ OpenDSS/line-650632.kW
+ double
+ line-650632.kW
+
+
+ OpenDSS/line-650632.kVAR
+ double
+ line-650632.kVAR
+
+
+ OpenDSS/line-650632.closed
+ boolean
+ line-650632.closed
+
+
+ OpenDSS/switch-671692.closed
+ boolean
+ switch-671692.closed
+
+
+ line-650632.closed
+
+
+
diff --git a/config/single-device/device3.xml b/config/single-device/device3.xml
new file mode 100644
index 0000000..b651810
--- /dev/null
+++ b/config/single-device/device3.xml
@@ -0,0 +1,86 @@
+
+
+
+ tcp://127.0.0.1:1234
+ tcp://127.0.0.1:5678
+
+
+ ot-sim-message-bus {{config_file}}
+ ot-sim-io-module {{config_file}}
+ ot-sim-modbus-module {{config_file}}
+ ot-sim-s7comm-module {{config_file}}
+ ot-sim-telnet-module {{config_file}}
+ ot-sim-node-red-module {{config_file}}
+
+
+ node-red
+ /etc/node-red.js
+ dark
+ config/single-device/node-red-hmi.json
+
+
+
+
+ :23
+ default
+
+
+ 127.0.0.1:5502
+
+ 0
+ line-650632.closed
+
+
+ 30000
+ line-650632.kW
+ -2
+
+
+
+
+ line-650632.closed
+ 0
+
+
+
+ line-650632.kW
+ 0
+
+
+
+ localhost
+ ot-sim-io
+
+ OpenDSS/line-650632.kW
+ double
+ line-650632.kW
+
+
+ OpenDSS/line-650632.kVAR
+ double
+ line-650632.kVAR
+
+
+ OpenDSS/line-650632.closed
+ boolean
+ line-650632.closed
+
+
+ OpenDSS/switch-671692.closed
+ boolean
+ switch-671692.closed
+
+
+ line-650632.closed
+
+
+
diff --git a/config/single-device/device4.xml b/config/single-device/device4.xml
new file mode 100644
index 0000000..b079a1b
--- /dev/null
+++ b/config/single-device/device4.xml
@@ -0,0 +1,101 @@
+
+
+
+ tcp://127.0.0.1:1234
+ tcp://127.0.0.1:5678
+
+
+ ot-sim-message-bus {{config_file}}
+ ot-sim-io-module {{config_file}}
+ ot-sim-modbus-module {{config_file}}
+ ot-sim-dnp3-module {{config_file}}
+ ot-sim-s7comm-module {{config_file}}
+ ot-sim-telnet-module {{config_file}}
+ ot-sim-node-red-module {{config_file}}
+
+
+ node-red
+ /etc/node-red.js
+ dark
+ config/single-device/node-red-hmi.json
+
+
+
+
+ :23
+ default
+
+
+ 127.0.0.1:5502
+
+ 0
+ line-650632.closed
+
+
+ 30000
+ line-650632.kW
+ -2
+
+
+
+ 127.0.0.1:20001
+
+ 1
+ 1024
+
+ 0
+ line-650632.closed
+ Group1Var1
+ Group2Var1
+ Class1
+
+
+
+ 0
+ line-650632.kW
+ Group30Var6
+ Group32Var6
+ Class1
+
+
+
+
+ localhost
+ ot-sim-io
+
+ OpenDSS/line-650632.kW
+ double
+ line-650632.kW
+
+
+ OpenDSS/line-650632.kVAR
+ double
+ line-650632.kVAR
+
+
+ OpenDSS/line-650632.closed
+ boolean
+ line-650632.closed
+
+
+ OpenDSS/switch-671692.closed
+ boolean
+ switch-671692.closed
+
+
+ line-650632.closed
+
+
+
diff --git a/src/c++/.vscode/c_cpp_properties.json b/src/c++/.vscode/c_cpp_properties.json
index 106ad1f..52d90a7 100644
--- a/src/c++/.vscode/c_cpp_properties.json
+++ b/src/c++/.vscode/c_cpp_properties.json
@@ -8,6 +8,7 @@
"${workspaceFolder}/deps/fmt/include",
"${workspaceFolder}/deps/json/single_include",
"${workspaceFolder}/deps/opendnp3/cpp/lib/include",
+ "${workspaceFolder}/deps/snap7",
"/usr/include/**",
"/usr/local/include/**"
],
diff --git a/src/c++/CMakeLists.txt b/src/c++/CMakeLists.txt
index 9f3727d..6a0ac54 100644
--- a/src/c++/CMakeLists.txt
+++ b/src/c++/CMakeLists.txt
@@ -17,6 +17,10 @@ set(OPENDNP3_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/deps/opendnp3/cpp/lib/include
)
+set(SNAP7_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/deps/snap7
+)
+
set(OTSIM_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
)
@@ -33,9 +37,11 @@ add_subdirectory(deps/json)
add_subdirectory(deps/opendnp3)
add_subdirectory(dnp3)
+add_subdirectory(s7)
add_subdirectory(msgbus)
add_subdirectory(cmd/ot-sim-dnp3-module)
+add_subdirectory(cmd/ot-sim-s7comm-module)
if(BUILD_E2E)
add_subdirectory(cmd/ot-sim-e2e-dnp3-master)
diff --git a/src/c++/cmd/ot-sim-dnp3-module/main.cpp b/src/c++/cmd/ot-sim-dnp3-module/main.cpp
index 825560d..c94b796 100644
--- a/src/c++/cmd/ot-sim-dnp3-module/main.cpp
+++ b/src/c++/cmd/ot-sim-dnp3-module/main.cpp
@@ -211,7 +211,7 @@ int main(int argc, char** argv) {
auto outstation = server->AddOutstation(config, restart, pusher);
sub->AddHandler(std::bind(&otsim::dnp3::Outstation::HandleMsgBusStatus, outstation, std::placeholders::_1));
-
+
auto inputs = outstn.equal_range("input");
for (auto iter = inputs.first; iter != inputs.second; ++iter) {
auto point = iter->second;
@@ -444,7 +444,7 @@ int main(int argc, char** argv) {
auto master = client->AddMaster(id, local, remote, timeout, pusher);
sub->AddHandler(std::bind(&otsim::dnp3::Master::HandleMsgBusUpdate, master, std::placeholders::_1));
-
+
auto inputs = mstr.equal_range("input");
for (auto iter = inputs.first; iter != inputs.second; ++iter) {
auto point = iter->second;
diff --git a/src/c++/cmd/ot-sim-dnp3-module/ot-sim-dnp3-module b/src/c++/cmd/ot-sim-dnp3-module/ot-sim-dnp3-module
new file mode 100755
index 0000000..f6a7862
Binary files /dev/null and b/src/c++/cmd/ot-sim-dnp3-module/ot-sim-dnp3-module differ
diff --git a/src/c++/cmd/ot-sim-s7comm-module/CMakeLists.txt b/src/c++/cmd/ot-sim-s7comm-module/CMakeLists.txt
new file mode 100644
index 0000000..0ecf42e
--- /dev/null
+++ b/src/c++/cmd/ot-sim-s7comm-module/CMakeLists.txt
@@ -0,0 +1,31 @@
+find_package(Boost REQUIRED)
+
+include_directories(
+ ${Boost_INCLUDE_DIRS}
+ ${CPPZMQ_INCLUDE_DIRS}
+ ${FMT_INCLUDE_DIRS}
+ ${OTSIM_INCLUDE_DIRS}
+ ${SNAP7_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${Boost_LIBRARY_DIRS}
+)
+
+add_definitions(-DBOOST_ALL_NO_LIB -DBOOST_ALL_DYN_LINK)
+
+add_executable(ot-sim-s7comm-module
+ main.cpp
+ ${SNAP7_INCLUDE_DIRS}/snap7.cpp
+)
+
+target_link_libraries(ot-sim-s7comm-module
+ ${Boost_LIBRARIES}
+ fmt::fmt
+ ot-sim-msgbus
+ ot-sim-s7
+)
+
+install(TARGETS ot-sim-s7comm-module
+ RUNTIME DESTINATION bin
+)
\ No newline at end of file
diff --git a/src/c++/cmd/ot-sim-s7comm-module/main.cpp b/src/c++/cmd/ot-sim-s7comm-module/main.cpp
new file mode 100644
index 0000000..a96c32f
--- /dev/null
+++ b/src/c++/cmd/ot-sim-s7comm-module/main.cpp
@@ -0,0 +1,470 @@
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "fmt/format.h"
+
+#include "msgbus/pusher.hpp"
+#include "msgbus/subscriber.hpp"
+
+#include "s7/server.hpp"
+#include "s7/client.hpp"
+
+#include "snap7.h"
+
+//for multithreading, mutex
+std::condition_variable cv;
+std::mutex m;
+namespace pt = boost::property_tree;
+
+typedef std::shared_ptr Pusher;
+
+void signalHandler(int) {
+ //if threads waiting for *this, notify_one unblocks one of the waiting threads
+ cv.notify_one();
+}
+
+/*
+LISTENER CLASS TO CONTINUALLY PUBLISH MESSAGES TO THE MSGBUS <------------- similar to DNP3 module
+The main difference between this listener and the dnp3 channel listener is that this one does not deal with threading
+because snap7 does not implement channels or channel states, which dnp3 bases its threading on.
+There is still a thread that is used to run the channel listener, but it does not have any mutex implementation, so it should just work
+normally.
+This class should accomplish all pushing and interface through zeromq via the msgbus pusher class
+*/
+class Listener {
+public:
+ static std::shared_ptr Create(std::string name, Pusher pusher) {
+ return std::make_shared(name, pusher);
+ }
+
+ //declaration sets the incoming name and pusher
+ Listener(std::string name, Pusher pusher) : name(name), pusher(pusher) {
+ thread = std::thread(std::bind(&Listener::Run, this));
+ }
+
+ ~Listener() {};
+
+ void runThread(){
+ thread = std::thread(std::bind(&Listener::Run, this));
+ }
+
+ //primary loop, which continually publishes on 5 second intervals
+ void Run() {
+ while (true) {
+ {
+ publish();
+ }
+
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ }
+ }
+
+private:
+ /*
+ Every module in ot-sim should push EVERYTHING, but should only subscribe to certain tags.
+ For that reason, this publish function does not implement any tag-checking/ descrimination; instead,
+ it pushes all envelopes to the msgbus, where other modules can determine whether or not they are relevant
+ */
+ void publish() {
+ std::string tag = fmt::format("{}.connected", name);
+ std::cout << fmt::format("[{}] setting connected", name) << std::endl;
+
+ otsim::msgbus::Points points;
+ points.push_back(otsim::msgbus::Point{tag});
+ otsim::msgbus::Status contents = {.measurements = points};
+
+ //create an envelope with all of the data
+ auto env = otsim::msgbus::NewEnvelope(name, contents);
+
+ //push all data to msgbus
+ pusher->Push("RUNTIME", env);
+ }
+
+ std::string name;
+ Pusher pusher;
+ std::thread thread;
+};
+
+int main(int argc, char** argv){
+ //argv will contain the path to the XML config file, if argc is less than 2, it means no path was included and the module cannot run
+ if (argc < 2) {
+ std::cerr << "ERROR: missing path to XML config file" << std::endl;
+ return 1;
+ }
+
+ //keep servers in scope so their threads don't terminate immediately.
+ std::vector> servers;
+
+ //keep clients in scope so their threads don't terminate immediately.
+ std::vector> clients;
+
+ // Keep client channel listeners in scope so their threads don't terminate immediately.
+ std::vector> listeners;
+
+ //keep subscribers in scope so their threads don't terminate immediately.
+ std::vector> subscribers;
+
+ //the xml file will be read and parsed into a ptree
+ pt::ptree tree;
+ pt::read_xml(argv[1], tree);
+
+ //main loop for the module. loops through XML data
+ BOOST_FOREACH(pt::ptree::value_type &v, tree) {
+
+ //ensure this is the ot-sim XML
+ if (v.first.compare("ot-sim") != 0) {
+ std::cerr << "ERROR: missing root 'ot-sim' element in XML config" << std::endl;
+ return 1;
+ }
+
+ std::string pubEndpoint;
+ std::string pullEndpoint;
+
+ //v.second will contain the message-bus branch of the v ptree. By default, pub and pull endpoints are set to non-meaningful values
+ try {
+ auto msgbus = v.second.get_child("message-bus");
+ pubEndpoint = msgbus.get("pub-endpoint", "tcp://127.0.0.1:5678");
+ pullEndpoint = msgbus.get("pull-endpoint", "tcp://127.0.0.1:1234");
+ } catch (pt::ptree_bad_path&) {std::cout<<"\nmessage bus pub/pull endpoint failure\n";}
+
+ //loop through each branch of the s7comm tree
+ auto devices = v.second.equal_range("s7comm");
+ for (auto iter = devices.first; iter != devices.second; ++iter) {
+ auto device = iter->second;
+
+ //required for pub sub
+ std::shared_ptr pusher;
+ std::shared_ptr sub;
+
+ //each s7comm device will have a name and mode
+ std::string name; //arbitrary device name
+ std::string mode; //server or client
+ //get name
+ try {
+ name = device.get(".name");
+ } catch (pt::ptree_bad_path&) {
+ std::cerr << "ERROR: missing name for S7COMM device" << std::endl;
+ }
+
+ //get mode (either client or server)
+ try {
+ mode = device.get(".mode");
+ } catch (pt::ptree_bad_path&) {
+ std::cerr << "ERROR: missing mode for S7COMM device" << std::endl;
+ }
+
+ //if the device specifies a pub endpoint create a msgbus subscriber with that endpoint, otherwise, use the default
+ if (device.get_child_optional("pub-endpoint")) {
+ auto endpoint = device.get("pub-endpoint");
+ sub = otsim::msgbus::Subscriber::Create(endpoint);
+ } else {
+ sub = otsim::msgbus::Subscriber::Create(pubEndpoint);
+ }
+
+ //if the device specifies a pull endpoint create a msgbus pusher with that endpoint, otherwise, use the default
+ if (device.get_child_optional("pull-endpoint")) {
+ auto endpoint = device.get("pull-endpoint");
+ pusher = otsim::msgbus::Pusher::Create(endpoint);
+ } else {
+ pusher = otsim::msgbus::Pusher::Create(pullEndpoint);
+ }
+
+ //if the s7comm device is a server
+ if (mode.compare("server") == 0){
+ std::cout << fmt::format("configuring S7COMM server {}", name) << std::endl;
+
+ //auto listener = Listener::Create(name, pusher);
+
+ //create the server object
+ auto server = std::make_shared();
+ std::string address = "0.0.0.0";
+ std::string ip;
+
+ //get the endpoint and set it
+ if (device.get_child_optional("endpoint")) {
+ auto endpoint = device.get("endpoint");
+
+ ip = endpoint.substr(0, endpoint.find(":"));
+ address = ip;
+
+ std::cout<<"S7 server IP: " << ip << std::endl;
+ }else{
+ std::cout<<"S7 server IP: 0.0.0.0\n";
+ ip = address;
+ }
+
+ otsim::s7::ServerConfig config = {
+ .id = name,
+ .address = device.get("local-address", 1024),
+ };
+
+ // TODO: FINISH XML for loop to get DB information for the server
+ /*
+ auto DBinputs = device.equal_range("DB");
+
+ //loop through each database listed in the XML
+ for(auto iter=DBinputs.first; iter !=DBinputs.second; iter++){
+ auto DBinput = iter->second;
+ std::string dbName;
+ uint16_t dbSize;
+
+ //get DB name (arbitrary)
+ dbName = DBinput.get("name");
+
+ //get DB size
+ dbSize = DBinput.get("size");
+ }*/
+
+ //create a handler using the server class from the s7 folder, which links snap7 and msgbus
+ auto s7server = otsim::s7::Server::Create(config, pusher);
+ sub->AddHandler(std::bind(&otsim::s7::Server::HandleMsgBusStatus, s7server, std::placeholders::_1));
+
+ //loop through the inputs, getting the tag for each
+ auto inputs = device.equal_range("input");
+ for(auto iter=inputs.first; iter !=inputs.second; iter++){
+ auto point = iter->second;
+
+ std::string typ;
+
+ //get the type of the input/output (binary or analog)
+ try {
+ typ = point.get(".type");
+ } catch (pt::ptree_bad_path&) {
+ std::cerr << "ERROR: missing type for S7COMM input" << std::endl;
+ continue;
+ }
+
+ if(typ.compare("binary")== 0){
+ otsim::s7::BinaryInputPoint p;
+
+ //get input information
+ p.tag = point.get("tag");
+ p.address = point.get("address");
+
+ //set input information
+ s7server->AddBinaryInput(p);
+ } else if(typ.compare("analog")== 0){
+ otsim::s7::AnalogInputPoint p;
+
+ //get input information
+ p.tag = point.get("tag");
+ p.address = point.get("address");
+
+ //set input information
+ s7server->AddAnalogInput(p);
+ } else {
+ std::cerr << "ERROR: invalid type " << typ << " provided for S7COMM input" << std::endl;
+ continue;
+ }
+ }
+
+ //loop through the outputs, getting the tag for each. if it is an output, the sbo value will be set to 'true'
+ auto outputs = device.equal_range("output");
+ for(auto iter=outputs.first; iter !=outputs.second; iter++){
+ auto point = iter->second;
+
+ std::string typ;
+
+ //get the type of the input/output (binary or analog)
+ try {
+ typ = point.get(".type");
+ } catch (pt::ptree_bad_path&) {
+ std::cerr << "ERROR: missing type for S7COMM output" << std::endl;
+ continue;
+ }
+
+ if(typ.compare("binary")== 0){
+ otsim::s7::BinaryOutputPoint p;
+
+ //get output information
+ p.tag = point.get("tag");
+ p.address = point.get("address");
+ p.sbo = point.get("sbo", 0) == 1;
+
+ //set output information
+ s7server->AddBinaryOutput(p);
+ } else if(typ.compare("analog")== 0){
+ otsim::s7::AnalogOutputPoint p;
+
+ //get output information
+ p.tag = point.get("tag");
+ p.address = point.get("address");
+ p.sbo = point.get("sbo", 0) == 1;
+
+ //set output information
+ s7server->AddAnalogOutput(p);
+ } else {
+ std::cerr << "ERROR: invalid type " << typ << " provided for S7COMM output" << std::endl;
+ continue;
+ }
+ }
+ std::cout << fmt::format("starting S7comm server {}", name) << std::endl;
+ //start the server and add it to the vector of servers
+ server->StartTo(ip.c_str());
+ sub->Start("RUNTIME");
+ subscribers.push_back(sub);
+ s7server->Run(server);
+ servers.push_back(server);
+ //listeners.push_back(listener);
+ } else if (mode.compare("client") == 0){ //if the s7comm device is a client
+
+ //create the client object
+ auto client = std::make_shared();
+
+ //create a listener for publishing purposes
+ auto listener = Listener::Create(name, pusher);
+
+ std::cout << fmt::format("configuring S7COMM client {}", name) << std::endl;
+ //listener->Run();
+
+ /*
+ set the connection type for the device based on what is provided in the xml.
+ if nothing is provided in the xml, set the connection type of the client to be
+ equal to 3. values 3-10 represent s7 basic. 2 represents OP. 1 represenets PG.
+ s7 basic is likely the main/only connection type for more clients.
+ */
+ try {
+ auto connectionType = device.get("connection-type", 3);
+ client->SetConnectionType(connectionType);
+ } catch (pt::ptree_bad_path&) {
+ std::cerr << "ERROR: missing mode for CONNECTION TYPE for client s7comm device" << std::endl;
+ }
+
+ /*
+ set the connection parameters. this includes the address, local TSAP and remote TSAP.
+ local TSAP and remote TSAP are stored as 16 bit unsigned integers. address is stored as a pointer
+ to an ANSI string; "192.168.1.12" for example.
+ */
+ auto ip_address = device.get("ip-address", "192.168.0.0"); //get IP, defaults to 192.168.0.0 arbitrarily
+
+ auto local_tsap = device.get("local-tsap", 10.00); //get local TSAP, defaults to 10.00
+
+ auto remote_tsap = device.get("remote-tsap", 13.00); //get remote TSAP, defaults to 13.00
+
+ client->SetConnectionParams(ip_address.c_str(), local_tsap, remote_tsap);
+
+ /*
+ declare where the client will connect. for S7 CPUs the default is rack 0 slot 2
+ */
+ auto rack = device.get("rack", 0);
+ auto slot = device.get("slot", 2);
+
+ std::string cliId = device.get(".name", "s7-client");
+ std::uint16_t cliAddr = device.get("address", 0);
+
+ auto s7client = otsim::s7::Client::Create(cliId, pusher);
+
+ //create an object of the client class from the s7 folder, which links snap to msgbus
+ s7client->BuildConfig(cliId, cliAddr);
+
+ //add the s7client to subscriber as a handler. the s7client will call handlemsgbusupdate with one input (an envelope)
+ sub->AddHandler(std::bind(&otsim::s7::Client::HandleMsgBusUpdate, s7client, std::placeholders::_1));
+
+ //loop through the inputs, getting the tag for each
+ auto inputs = device.equal_range("input");
+ for(auto iter=inputs.first; iter !=inputs.second; iter++){
+ auto point = iter->second;
+
+ std::string typ;
+
+ //get the type of input (binary or analog)
+ try {
+ typ = point.get(".type");
+ } catch (pt::ptree_bad_path&) {
+ std::cerr << "ERROR: missing type for S7COMM input" << std::endl;
+ continue;
+ }
+
+ if(typ.compare("binary")== 0){
+ //based on the xml, add tags that the s7client will communicate to the msgbus
+ std::string tag_read = point.get("tag");
+ std::uint16_t address_read = point.get("address");
+
+ s7client->AddBinaryTag(address_read, tag_read);
+ } else if(typ.compare("analog")== 0){
+ //based on the xml, add tags that the s7client will communicate to the msgbus
+ std::string tag_read = point.get("tag");
+ std::uint16_t address_read = point.get("address");
+
+ s7client->AddAnalogTag(address_read, tag_read);
+ } else{
+ std::cerr << "ERROR: invalid type " << typ << " provided for S7COMM input" << std::endl;
+ continue;
+ }
+ }
+
+ //loop through the outputs, getting the tag for each
+ auto outputs = device.equal_range("output");
+ for(auto iter=outputs.first; iter !=outputs.second; iter++){
+ auto point = iter->second;
+
+ std::string typ;
+
+ //get the type of output (binary or analog)
+ try {
+ typ = point.get(".type");
+ } catch (pt::ptree_bad_path&) {
+ std::cerr << "ERROR: missing type for S7COMM output" << std::endl;
+ continue;
+ }
+
+ if(typ.compare("binary")== 0){
+ //based on the xml, add tags that the s7client will communicate to the msgbus
+ std::string tag_read = point.get("tag");
+ std::uint16_t address_read = point.get("address");
+ auto sbo = point.get("sbo", 0) == 1;
+
+ s7client->AddBinaryTag(address_read, tag_read, sbo);
+ } else if(typ.compare("analog")== 0){
+ //based on the xml, add tags that the s7client will communicate to the msgbus
+ std::string tag_read = point.get("tag");
+ std::uint16_t address_read = point.get("address");
+ auto sbo = point.get("sbo", 0) == 1;
+
+ s7client->AddAnalogTag(address_read, tag_read, sbo);
+ } else{
+ std::cerr << "ERROR: invalid type " << typ << " provided for S7COMM output" << std::endl;
+ continue;
+ }
+ }
+
+ std::cout << fmt::format("starting S7comm client {}", cliId) << std::endl;
+ sub->Start("RUNTIME");
+ subscribers.push_back(sub);
+ //connect
+ client->ConnectTo(ip_address.c_str(), rack, slot);
+ clients.push_back(client); //<------ THIS LINE IS NEVER REACHED
+ //listener->Run();
+ listeners.push_back(listener);
+ } else {
+ std::cerr << "ERROR: invalid mode provided for S7COMM config" << std::endl;
+ return 1;
+ }
+
+ //push back the subscriber created for this s7comm device
+ sub->Start("RUNTIME");
+ subscribers.push_back(sub);
+ } //end of S7COMM loop
+ } //end of BOOST_FOREACH loop
+
+ //signal handling/threading
+ std::signal(SIGINT, signalHandler);
+
+ std::unique_lock lk(m);
+ cv.wait(lk);
+
+ //this *should* cause any blocking subscribers to immediately return so
+ //threads can exit.
+ for (auto &sub : subscribers) {
+ sub->Stop();
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/src/c++/deps/snap7/README.md b/src/c++/deps/snap7/README.md
new file mode 100644
index 0000000..f2c0501
--- /dev/null
+++ b/src/c++/deps/snap7/README.md
@@ -0,0 +1,7 @@
+# Snap7 v1.4.2
+
+These dependency files are from v1.4.2 of the Snap7 library available
+[here](https://snap7.sourceforge.net/). More specifically, they are the C++
+wrappers from the `examples/cpp` directory within the Snap7 archive.
+
+The Snap7 library is licensed under the LGPL v3.
\ No newline at end of file
diff --git a/src/c++/deps/snap7/snap7.cpp b/src/c++/deps/snap7/snap7.cpp
new file mode 100644
index 0000000..1fc1c1d
--- /dev/null
+++ b/src/c++/deps/snap7/snap7.cpp
@@ -0,0 +1,775 @@
+/*=============================================================================|
+| PROJECT SNAP7 1.4.0 |
+|==============================================================================|
+| Copyright (C) 2013, 2014 Davide Nardella |
+| All rights reserved. |
+|==============================================================================|
+| SNAP7 is free software: you can redistribute it and/or modify |
+| it under the terms of the Lesser GNU General Public License as published by |
+| the Free Software Foundation, either version 3 of the License, or |
+| (at your option) any later version. |
+| |
+| It means that you can distribute your commercial software linked with |
+| SNAP7 without the requirement to distribute the source code of your |
+| application and without the requirement that your application be itself |
+| distributed under LGPL. |
+| |
+| SNAP7 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 |
+| Lesser GNU General Public License for more details. |
+| |
+| You should have received a copy of the GNU General Public License and a |
+| copy of Lesser GNU General Public License along with Snap7. |
+| If not, see http://www.gnu.org/licenses/ |
+|==============================================================================|
+| |
+| C++ Snap 7 classes Implementation |
+| |
+|=============================================================================*/
+
+#include "snap7.h"
+
+//==============================================================================
+// CLIENT
+//==============================================================================
+TS7Client::TS7Client()
+{
+ Client=Cli_Create();
+}
+//---------------------------------------------------------------------------
+TS7Client::~TS7Client()
+{
+ Cli_Destroy(&Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::Connect()
+{
+ return Cli_Connect(Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ConnectTo(const char *RemAddress, int Rack, int Slot)
+{
+ return Cli_ConnectTo(Client, RemAddress, Rack, Slot);
+}
+//---------------------------------------------------------------------------
+int TS7Client::SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTSAP)
+{
+ return Cli_SetConnectionParams(Client, RemAddress, LocalTSAP, RemoteTSAP);
+}
+//---------------------------------------------------------------------------
+int TS7Client::SetConnectionType(word ConnectionType)
+{
+ return Cli_SetConnectionType(Client, ConnectionType);
+}
+//---------------------------------------------------------------------------
+int TS7Client::Disconnect()
+{
+ return Cli_Disconnect(Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetParam(int ParamNumber, void *pValue)
+{
+ return Cli_GetParam(Client, ParamNumber, pValue);
+}
+//---------------------------------------------------------------------------
+int TS7Client::SetParam(int ParamNumber, void *pValue)
+{
+ return Cli_SetParam(Client, ParamNumber, pValue);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
+{
+ return Cli_ReadArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
+{
+ return Cli_WriteArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ReadMultiVars(PS7DataItem Item, int ItemsCount)
+{
+ return Cli_ReadMultiVars(Client, Item, ItemsCount);
+}
+//---------------------------------------------------------------------------
+int TS7Client::WriteMultiVars(PS7DataItem Item, int ItemsCount)
+{
+ return Cli_WriteMultiVars(Client, Item, ItemsCount);
+}
+//---------------------------------------------------------------------------
+int TS7Client::DBRead(int DBNumber, int Start, int Size, void *pUsrData)
+{
+ return Cli_DBRead(Client, DBNumber, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::DBWrite(int DBNumber, int Start, int Size, void *pUsrData)
+{
+ return Cli_DBWrite(Client, DBNumber, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::MBRead(int Start, int Size, void *pUsrData)
+{
+ return Cli_MBRead(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::MBWrite(int Start, int Size, void *pUsrData)
+{
+ return Cli_MBWrite(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::EBRead(int Start, int Size, void *pUsrData)
+{
+ return Cli_EBRead(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::EBWrite(int Start, int Size, void *pUsrData)
+{
+ return Cli_EBWrite(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ABRead(int Start, int Size, void *pUsrData)
+{
+ return Cli_ABRead(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ABWrite(int Start, int Size, void *pUsrData)
+{
+ return Cli_ABWrite(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::TMRead(int Start, int Amount, void *pUsrData)
+{
+ return Cli_TMRead(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::TMWrite(int Start, int Amount, void *pUsrData)
+{
+ return Cli_TMWrite(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::CTRead(int Start, int Amount, void *pUsrData)
+{
+ return Cli_CTRead(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::CTWrite(int Start, int Amount, void *pUsrData)
+{
+ return Cli_CTWrite(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ListBlocks(PS7BlocksList pUsrData)
+{
+ return Cli_ListBlocks(Client, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData)
+{
+ return Cli_GetAgBlockInfo(Client, BlockType, BlockNum, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetPgBlockInfo(void *pBlock, PS7BlockInfo pUsrData, int Size)
+{
+ return Cli_GetPgBlockInfo(Client, pBlock, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount)
+{
+ return Cli_ListBlocksOfType(Client, BlockType, pUsrData, ItemsCount);
+}
+//---------------------------------------------------------------------------
+int TS7Client::Upload(int BlockType, int BlockNum, void *pUsrData, int *Size)
+{
+ return Cli_Upload(Client, BlockType, BlockNum, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::FullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)
+{
+ return Cli_FullUpload(Client, BlockType, BlockNum, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::Download(int BlockNum, void *pUsrData, int Size)
+{
+ return Cli_Download(Client, BlockNum, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::Delete(int BlockType, int BlockNum)
+{
+ return Cli_Delete(Client, BlockType, BlockNum);
+}
+//---------------------------------------------------------------------------
+int TS7Client::DBGet(int DBNumber, void *pUsrData, int *Size)
+{
+ return Cli_DBGet(Client, DBNumber, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::DBFill(int DBNumber, int FillChar)
+{
+ return Cli_DBFill(Client, DBNumber, FillChar);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetPlcDateTime(tm *DateTime)
+{
+ return Cli_GetPlcDateTime(Client, DateTime);
+}
+//---------------------------------------------------------------------------
+int TS7Client::SetPlcDateTime(tm *DateTime)
+{
+ return Cli_SetPlcDateTime(Client, DateTime);
+}
+//---------------------------------------------------------------------------
+int TS7Client::SetPlcSystemDateTime()
+{
+ return Cli_SetPlcSystemDateTime(Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetOrderCode(PS7OrderCode pUsrData)
+{
+ return Cli_GetOrderCode(Client, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetCpuInfo(PS7CpuInfo pUsrData)
+{
+ return Cli_GetCpuInfo(Client, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetCpInfo(PS7CpInfo pUsrData)
+{
+ return Cli_GetCpInfo(Client, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size)
+{
+ return Cli_ReadSZL(Client, ID, Index, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ReadSZLList(PS7SZLList pUsrData, int *ItemsCount)
+{
+ return Cli_ReadSZLList(Client, pUsrData, ItemsCount);
+}
+//---------------------------------------------------------------------------
+int TS7Client::PlcHotStart()
+{
+ return Cli_PlcHotStart(Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::PlcColdStart()
+{
+ return Cli_PlcColdStart(Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::PlcStop()
+{
+ return Cli_PlcStop(Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::CopyRamToRom(int Timeout)
+{
+ return Cli_CopyRamToRom(Client, Timeout);
+}
+//---------------------------------------------------------------------------
+int TS7Client::Compress(int Timeout)
+{
+ return Cli_Compress(Client, Timeout);
+}
+//---------------------------------------------------------------------------
+int TS7Client::GetProtection(PS7Protection pUsrData)
+{
+ return Cli_GetProtection(Client, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::SetSessionPassword(char *Password)
+{
+ return Cli_SetSessionPassword(Client, Password);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ClearSessionPassword()
+{
+ return Cli_ClearSessionPassword(Client);
+}
+//---------------------------------------------------------------------------
+int TS7Client::ExecTime()
+{
+ int Time;
+ int Result = Cli_GetExecTime(Client, &Time);
+ if (Result==0)
+ return Time;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+int TS7Client::LastError()
+{
+ int LastError;
+ int Result =Cli_GetLastError(Client, &LastError);
+ if (Result==0)
+ return LastError;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+int TS7Client::PDULength()
+{
+ int Requested, Negotiated;
+ if (Cli_GetPduLength(Client, &Requested, &Negotiated)==0)
+ return Negotiated;
+ else
+ return 0;
+}
+//---------------------------------------------------------------------------
+int TS7Client::PDURequested()
+{
+ int Requested, Negotiated;
+ if (Cli_GetPduLength(Client, &Requested, &Negotiated)==0)
+ return Requested;
+ else
+ return 0;
+}
+//---------------------------------------------------------------------------
+int TS7Client::PlcStatus()
+{
+ int Status;
+ int Result = Cli_GetPlcStatus(Client, &Status);
+ if (Result==0)
+ return Status;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+bool TS7Client::Connected()
+{
+ int ClientStatus;
+ if (Cli_GetConnected(Client ,&ClientStatus)==0)
+ return ClientStatus!=0;
+ else
+ return false;
+}
+//---------------------------------------------------------------------------
+int TS7Client::SetAsCallback(pfn_CliCompletion pCompletion, void *usrPtr)
+{
+ return Cli_SetAsCallback(Client, pCompletion, usrPtr);
+}
+//---------------------------------------------------------------------------
+bool TS7Client::CheckAsCompletion(int *opResult)
+{
+ return Cli_CheckAsCompletion(Client ,opResult)==JobComplete;
+}
+//---------------------------------------------------------------------------
+int TS7Client::WaitAsCompletion(longword Timeout)
+{
+ return Cli_WaitAsCompletion(Client, Timeout);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
+{
+ return Cli_AsReadArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
+{
+ return Cli_AsWriteArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsListBlocksOfType(int BlockType, PS7BlocksOfType pUsrData, int *ItemsCount)
+{
+ return Cli_AsListBlocksOfType(Client, BlockType, pUsrData, ItemsCount);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size)
+{
+ return Cli_AsReadSZL(Client, ID, Index, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsReadSZLList(PS7SZLList pUsrData, int *ItemsCount)
+{
+ return Cli_AsReadSZLList(Client, pUsrData, ItemsCount);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)
+{
+ return Cli_AsUpload(Client, BlockType, BlockNum, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsFullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)
+{
+ return Cli_AsFullUpload(Client, BlockType, BlockNum, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsDownload(int BlockNum, void *pUsrData, int Size)
+{
+ return Cli_AsDownload(Client, BlockNum, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsCopyRamToRom(int Timeout)
+{
+ return Cli_AsCopyRamToRom(Client, Timeout);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsCompress(int Timeout)
+{
+ return Cli_AsCompress(Client, Timeout);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsDBRead(int DBNumber, int Start, int Size, void *pUsrData)
+{
+ return Cli_AsDBRead(Client, DBNumber, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsDBWrite(int DBNumber, int Start, int Size, void *pUsrData)
+{
+ return Cli_AsDBWrite(Client, DBNumber, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsMBRead(int Start, int Size, void *pUsrData)
+{
+ return Cli_AsMBRead(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsMBWrite(int Start, int Size, void *pUsrData)
+{
+ return Cli_AsMBWrite(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsEBRead(int Start, int Size, void *pUsrData)
+{
+ return Cli_AsEBRead(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsEBWrite(int Start, int Size, void *pUsrData)
+{
+ return Cli_AsEBWrite(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsABRead(int Start, int Size, void *pUsrData)
+{
+ return Cli_AsABRead(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsABWrite(int Start, int Size, void *pUsrData)
+{
+ return Cli_AsABWrite(Client, Start, Size, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsTMRead(int Start, int Amount, void *pUsrData)
+{
+ return Cli_AsTMRead(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsTMWrite(int Start, int Amount, void *pUsrData)
+{
+ return Cli_AsTMWrite(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsCTRead(int Start, int Amount, void *pUsrData)
+{
+ return Cli_AsCTRead(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsCTWrite(int Start, int Amount, void *pUsrData)
+{
+ return Cli_AsCTWrite(Client, Start, Amount, pUsrData);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsDBGet(int DBNumber, void *pUsrData, int *Size)
+{
+ return Cli_AsDBGet(Client, DBNumber, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Client::AsDBFill(int DBNumber, int FillChar)
+{
+ return Cli_AsDBFill(Client, DBNumber, FillChar);
+}
+//==============================================================================
+// SERVER
+//==============================================================================
+TS7Server::TS7Server()
+{
+ Server=Srv_Create();
+}
+//---------------------------------------------------------------------------
+TS7Server::~TS7Server()
+{
+ Srv_Destroy(&Server);
+}
+//---------------------------------------------------------------------------
+int TS7Server::Start()
+{
+ return Srv_Start(Server);
+}
+//---------------------------------------------------------------------------
+int TS7Server::StartTo(const char *Address)
+{
+ return Srv_StartTo(Server, Address);
+}
+//---------------------------------------------------------------------------
+int TS7Server::Stop()
+{
+ return Srv_Stop(Server);
+}
+//---------------------------------------------------------------------------
+int TS7Server::GetParam(int ParamNumber, void *pValue)
+{
+ return Srv_GetParam(Server, ParamNumber, pValue);
+}
+//---------------------------------------------------------------------------
+int TS7Server::SetParam(int ParamNumber, void *pValue)
+{
+ return Srv_SetParam(Server, ParamNumber, pValue);
+}
+//---------------------------------------------------------------------------
+int TS7Server::SetEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr)
+{
+ return Srv_SetEventsCallback(Server, PCallBack, UsrPtr);
+}
+//---------------------------------------------------------------------------
+int TS7Server::SetReadEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr)
+{
+ return Srv_SetReadEventsCallback(Server, PCallBack, UsrPtr);
+}
+//---------------------------------------------------------------------------
+int TS7Server::SetRWAreaCallback(pfn_RWAreaCallBack PCallBack, void *UsrPtr)
+{
+ return Srv_SetRWAreaCallback(Server, PCallBack, UsrPtr);
+}
+//---------------------------------------------------------------------------
+bool TS7Server::PickEvent(TSrvEvent *pEvent)
+{
+ int EvtReady;
+ if (Srv_PickEvent(Server, pEvent, &EvtReady)==0)
+ return EvtReady!=0;
+ else
+ return false;
+}
+//---------------------------------------------------------------------------
+void TS7Server::ClearEvents()
+{
+ Srv_ClearEvents(Server);
+}
+//---------------------------------------------------------------------------
+longword TS7Server::GetEventsMask()
+{
+ longword Mask;
+ int Result = Srv_GetMask(Server, mkEvent, &Mask);
+ if (Result==0)
+ return Mask;
+ else
+ return 0;
+}
+//---------------------------------------------------------------------------
+longword TS7Server::GetLogMask()
+{
+ longword Mask;
+ int Result = Srv_GetMask(Server, mkLog, &Mask);
+ if (Result==0)
+ return Mask;
+ else
+ return 0;
+}
+//---------------------------------------------------------------------------
+void TS7Server::SetEventsMask(longword Mask)
+{
+ Srv_SetMask(Server, mkEvent, Mask);
+}
+//---------------------------------------------------------------------------
+void TS7Server::SetLogMask(longword Mask)
+{
+ Srv_SetMask(Server, mkLog, Mask);
+}
+//---------------------------------------------------------------------------
+int TS7Server::RegisterArea(int AreaCode, word Index, void *pUsrData, word Size)
+{
+ return Srv_RegisterArea(Server, AreaCode, Index, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Server::UnregisterArea(int AreaCode, word Index)
+{
+ return Srv_UnregisterArea(Server, AreaCode, Index);
+}
+//---------------------------------------------------------------------------
+int TS7Server::LockArea(int AreaCode, word Index)
+{
+ return Srv_LockArea(Server, AreaCode, Index);
+}
+//---------------------------------------------------------------------------
+int TS7Server::UnlockArea(int AreaCode, word Index)
+{
+ return Srv_UnlockArea(Server, AreaCode, Index);
+}
+//---------------------------------------------------------------------------
+int TS7Server::ServerStatus()
+{
+ int ServerStatus, CpuStatus, ClientsCount;
+ int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);
+ if (Result==0)
+ return ServerStatus;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+int TS7Server::GetCpuStatus()
+{
+ int ServerStatus, CpuStatus, ClientsCount;
+ int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);
+ if (Result==0)
+ return CpuStatus;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+int TS7Server::ClientsCount()
+{
+ int ServerStatus, CpuStatus, ClientsCount;
+ int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);
+ if (Result==0)
+ return ClientsCount;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+int TS7Server::SetCpuStatus(int Status)
+{
+ return Srv_SetCpuStatus(Server, Status);
+}
+//==============================================================================
+// PARTNER
+//==============================================================================
+TS7Partner::TS7Partner(bool Active)
+{
+ Partner=Par_Create(int(Active));
+}
+//---------------------------------------------------------------------------
+TS7Partner::~TS7Partner()
+{
+ Par_Destroy(&Partner);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::GetParam(int ParamNumber, void *pValue)
+{
+ return Par_GetParam(Partner, ParamNumber, pValue);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::SetParam(int ParamNumber, void *pValue)
+{
+ return Par_SetParam(Partner, ParamNumber, pValue);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::Start()
+{
+ return Par_Start(Partner);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::StartTo(const char *LocalAddress, const char *RemoteAddress, int LocalTSAP, int RemoteTSAP)
+{
+ return Par_StartTo(Partner, LocalAddress, RemoteAddress, LocalTSAP, RemoteTSAP);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::Stop()
+{
+ return Par_Stop(Partner);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::BSend(longword R_ID, void *pUsrData, int Size)
+{
+ return Par_BSend(Partner, R_ID, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::AsBSend(longword R_ID, void *pUsrData, int Size)
+{
+ return Par_AsBSend(Partner, R_ID, pUsrData, Size);
+}
+//---------------------------------------------------------------------------
+bool TS7Partner::CheckAsBSendCompletion(int *opResult)
+{
+ return Par_CheckAsBSendCompletion(Partner ,opResult)==JobComplete;
+}
+//---------------------------------------------------------------------------
+int TS7Partner::WaitAsBSendCompletion(longword Timeout)
+{
+ return Par_WaitAsBSendCompletion(Partner, Timeout);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::SetSendCallback(pfn_ParSendCompletion pCompletion, void *usrPtr)
+{
+ return Par_SetSendCallback(Partner, pCompletion, usrPtr);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::BRecv(longword *R_ID, void *pUsrData, int *Size, longword Timeout)
+{
+ return Par_BRecv(Partner, R_ID, pUsrData, Size, Timeout);
+}
+//---------------------------------------------------------------------------
+bool TS7Partner::CheckAsBRecvCompletion(int *opResult, longword *R_ID, void *pUsrData, int *Size)
+{
+ return Par_CheckAsBRecvCompletion(Partner, opResult, R_ID, pUsrData, Size) == JobComplete;
+}
+//---------------------------------------------------------------------------
+int TS7Partner::SetRecvCallback(pfn_ParRecvCallBack pCallback, void *usrPtr)
+{
+ return Par_SetRecvCallback(Partner, pCallback, usrPtr);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::Status()
+{
+ int ParStatus;
+ int Result = Par_GetStatus(Partner, &ParStatus);
+ if (Result==0)
+ return ParStatus;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+int TS7Partner::LastError()
+{
+ int Error;
+ int Result = Par_GetLastError(Partner, &Error);
+ if (Result==0)
+ return Error;
+ else
+ return Result;
+}
+//---------------------------------------------------------------------------
+int TS7Partner::GetTimes(longword *SendTime, longword *RecvTime)
+{
+ return Par_GetTimes(Partner, SendTime, RecvTime);
+}
+//---------------------------------------------------------------------------
+int TS7Partner::GetStats(longword *BytesSent, longword *BytesRecv, longword *ErrSend, longword *ErrRecv)
+{
+ return Par_GetStats(Partner, BytesSent, BytesRecv, ErrSend, ErrRecv);
+}
+//---------------------------------------------------------------------------
+bool TS7Partner::Linked()
+{
+ return Status()==par_linked;
+}
+//==============================================================================
+// Text routines
+//==============================================================================
+TextString CliErrorText(int Error)
+{
+ char text[TextLen];
+ Cli_ErrorText(Error, text, TextLen);
+ return TextString(text);
+}
+//---------------------------------------------------------------------------
+TextString SrvErrorText(int Error)
+{
+ char text[TextLen];
+ Srv_ErrorText(Error, text, TextLen);
+ return TextString(text);
+}
+//---------------------------------------------------------------------------
+TextString ParErrorText(int Error)
+{
+ char text[TextLen];
+ Par_ErrorText(Error, text, TextLen);
+ return TextString(text);
+}
+//---------------------------------------------------------------------------
+TextString SrvEventText(TSrvEvent *Event)
+{
+ char text[TextLen];
+ Srv_EventText(Event, text, TextLen);
+ return TextString(text);
+}
+
diff --git a/src/c++/deps/snap7/snap7.h b/src/c++/deps/snap7/snap7.h
new file mode 100644
index 0000000..129b861
--- /dev/null
+++ b/src/c++/deps/snap7/snap7.h
@@ -0,0 +1,957 @@
+/*=============================================================================|
+| PROJECT SNAP7 1.4.0 |
+|==============================================================================|
+| Copyright (C) 2013, 2014 Davide Nardella |
+| All rights reserved. |
+|==============================================================================|
+| SNAP7 is free software: you can redistribute it and/or modify |
+| it under the terms of the Lesser GNU General Public License as published by |
+| the Free Software Foundation, either version 3 of the License, or |
+| (at your option) any later version. |
+| |
+| It means that you can distribute your commercial software linked with |
+| SNAP7 without the requirement to distribute the source code of your |
+| application and without the requirement that your application be itself |
+| distributed under LGPL. |
+| |
+| SNAP7 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 |
+| Lesser GNU General Public License for more details. |
+| |
+| You should have received a copy of the GNU General Public License and a |
+| copy of Lesser GNU General Public License along with Snap7. |
+| If not, see http://www.gnu.org/licenses/ |
+|==============================================================================|
+| |
+| C/C++ Snap 7 classes/Imports definitions |
+| |
+|=============================================================================*/
+#ifndef snap7_h
+#define snap7_h
+//---------------------------------------------------------------------------
+// Platform detection
+//---------------------------------------------------------------------------
+#if defined (_WIN32)||defined(_WIN64)||defined(__WIN32__)||defined(__WINDOWS__)
+# define OS_WINDOWS
+#endif
+
+// Visual Studio needs this to use the correct time_t size
+#if defined (_WIN32) && !defined(_WIN64)
+# define _USE_32BIT_TIME_T
+#endif
+
+#if defined(unix) || defined(__unix__) || defined(__unix)
+# define PLATFORM_UNIX
+#endif
+
+#if defined(__SVR4) || defined(__svr4__)
+# define OS_SOLARIS
+#endif
+
+#if BSD>=0
+# define OS_BSD
+#endif
+
+#if defined(__APPLE__)
+# define OS_OSX
+#endif
+
+#if defined(PLATFORM_UNIX) || defined(OS_OSX)
+# include
+# if defined(_POSIX_VERSION)
+# define POSIX
+# endif
+#endif
+
+//---------------------------------------------------------------------------
+// C++ Library
+//---------------------------------------------------------------------------
+#ifdef __cplusplus
+#include
+#include
+
+// Visual C++ not C99 compliant (VS2008--)
+#ifdef _MSC_VER
+# if _MSC_VER >= 1600
+# include // VS2010++ have it
+# else
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef signed __int64 int64_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int64 uint64_t;
+ #ifdef _WIN64
+ typedef unsigned __int64 uintptr_t;
+ #else
+ typedef unsigned __int32 uintptr_t;
+ #endif
+# endif
+#else
+# include
+#endif
+
+extern "C" {
+#endif
+//---------------------------------------------------------------------------
+// C exact length types
+//---------------------------------------------------------------------------
+#ifndef __cplusplus
+
+#ifdef OS_BSD
+# include
+# include
+#endif
+
+#ifdef OS_OSX
+# include
+# include
+#endif
+
+#ifdef OS_SOLARIS
+# include
+# include
+#endif
+
+#if defined(_UINTPTR_T_DEFINED)
+# include
+# include
+#endif
+
+#if !defined(_UINTPTR_T_DEFINED) && !defined(OS_SOLARIS) && !defined(OS_BSD) && !defined(OS_OSX)
+ typedef unsigned char uint8_t; // 8 bit unsigned integer
+ typedef unsigned short uint16_t; // 16 bit unsigned integer
+ typedef unsigned int uint32_t; // 32 bit unsigned integer
+ typedef unsigned long uintptr_t;// 64 bit unsigned integer
+#endif
+
+#endif
+
+#ifdef OS_WINDOWS
+# define S7API __stdcall
+#else
+# define S7API
+#endif
+
+#pragma pack(1)
+//******************************************************************************
+// COMMON
+//******************************************************************************
+// Exact length types regardless of platform/processor
+typedef uint8_t byte;
+typedef uint16_t word;
+typedef uint32_t longword;
+typedef byte *pbyte;
+typedef word *pword;
+typedef uintptr_t S7Object; // multi platform/processor object reference
+ // DON'T CONFUSE IT WITH AN OLE OBJECT, IT'S SIMPLY
+ // AN INTEGER VALUE (32 OR 64 BIT) USED AS HANDLE.
+
+#ifndef __cplusplus
+typedef struct
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+}tm;
+
+typedef int bool;
+#define false 0;
+#define true 1;
+#endif
+
+const int errLibInvalidParam = -1;
+const int errLibInvalidObject = -2;
+
+// CPU status
+#define S7CpuStatusUnknown 0x00
+#define S7CpuStatusRun 0x08
+#define S7CpuStatusStop 0x04
+
+// ISO Errors
+const longword errIsoConnect = 0x00010000; // Connection error
+const longword errIsoDisconnect = 0x00020000; // Disconnect error
+const longword errIsoInvalidPDU = 0x00030000; // Bad format
+const longword errIsoInvalidDataSize = 0x00040000; // Bad Datasize passed to send/recv buffer is invalid
+const longword errIsoNullPointer = 0x00050000; // Null passed as pointer
+const longword errIsoShortPacket = 0x00060000; // A short packet received
+const longword errIsoTooManyFragments = 0x00070000; // Too many packets without EoT flag
+const longword errIsoPduOverflow = 0x00080000; // The sum of fragments data exceded maximum packet size
+const longword errIsoSendPacket = 0x00090000; // An error occurred during send
+const longword errIsoRecvPacket = 0x000A0000; // An error occurred during recv
+const longword errIsoInvalidParams = 0x000B0000; // Invalid TSAP params
+const longword errIsoResvd_1 = 0x000C0000; // Unassigned
+const longword errIsoResvd_2 = 0x000D0000; // Unassigned
+const longword errIsoResvd_3 = 0x000E0000; // Unassigned
+const longword errIsoResvd_4 = 0x000F0000; // Unassigned
+
+// Tag Struct
+typedef struct{
+ int Area;
+ int DBNumber;
+ int Start;
+ int Size;
+ int WordLen;
+}TS7Tag, *PS7Tag;
+
+//------------------------------------------------------------------------------
+// PARAMS LIST
+//------------------------------------------------------------------------------
+const int p_u16_LocalPort = 1;
+const int p_u16_RemotePort = 2;
+const int p_i32_PingTimeout = 3;
+const int p_i32_SendTimeout = 4;
+const int p_i32_RecvTimeout = 5;
+const int p_i32_WorkInterval = 6;
+const int p_u16_SrcRef = 7;
+const int p_u16_DstRef = 8;
+const int p_u16_SrcTSap = 9;
+const int p_i32_PDURequest = 10;
+const int p_i32_MaxClients = 11;
+const int p_i32_BSendTimeout = 12;
+const int p_i32_BRecvTimeout = 13;
+const int p_u32_RecoveryTime = 14;
+const int p_u32_KeepAliveTime = 15;
+
+// Client/Partner Job status
+const int JobComplete = 0;
+const int JobPending = 1;
+
+//******************************************************************************
+// CLIENT
+//******************************************************************************
+
+// Error codes
+const longword errNegotiatingPDU = 0x00100000;
+const longword errCliInvalidParams = 0x00200000;
+const longword errCliJobPending = 0x00300000;
+const longword errCliTooManyItems = 0x00400000;
+const longword errCliInvalidWordLen = 0x00500000;
+const longword errCliPartialDataWritten = 0x00600000;
+const longword errCliSizeOverPDU = 0x00700000;
+const longword errCliInvalidPlcAnswer = 0x00800000;
+const longword errCliAddressOutOfRange = 0x00900000;
+const longword errCliInvalidTransportSize = 0x00A00000;
+const longword errCliWriteDataSizeMismatch = 0x00B00000;
+const longword errCliItemNotAvailable = 0x00C00000;
+const longword errCliInvalidValue = 0x00D00000;
+const longword errCliCannotStartPLC = 0x00E00000;
+const longword errCliAlreadyRun = 0x00F00000;
+const longword errCliCannotStopPLC = 0x01000000;
+const longword errCliCannotCopyRamToRom = 0x01100000;
+const longword errCliCannotCompress = 0x01200000;
+const longword errCliAlreadyStop = 0x01300000;
+const longword errCliFunNotAvailable = 0x01400000;
+const longword errCliUploadSequenceFailed = 0x01500000;
+const longword errCliInvalidDataSizeRecvd = 0x01600000;
+const longword errCliInvalidBlockType = 0x01700000;
+const longword errCliInvalidBlockNumber = 0x01800000;
+const longword errCliInvalidBlockSize = 0x01900000;
+const longword errCliDownloadSequenceFailed = 0x01A00000;
+const longword errCliInsertRefused = 0x01B00000;
+const longword errCliDeleteRefused = 0x01C00000;
+const longword errCliNeedPassword = 0x01D00000;
+const longword errCliInvalidPassword = 0x01E00000;
+const longword errCliNoPasswordToSetOrClear = 0x01F00000;
+const longword errCliJobTimeout = 0x02000000;
+const longword errCliPartialDataRead = 0x02100000;
+const longword errCliBufferTooSmall = 0x02200000;
+const longword errCliFunctionRefused = 0x02300000;
+const longword errCliDestroying = 0x02400000;
+const longword errCliInvalidParamNumber = 0x02500000;
+const longword errCliCannotChangeParam = 0x02600000;
+
+const int MaxVars = 20; // Max vars that can be transferred with MultiRead/MultiWrite
+
+// Client Connection Type
+const word CONNTYPE_PG = 0x0001; // Connect to the PLC as a PG
+const word CONNTYPE_OP = 0x0002; // Connect to the PLC as an OP
+const word CONNTYPE_BASIC = 0x0003; // Basic connection
+
+// Area ID
+const byte S7AreaPE = 0x81;
+const byte S7AreaPA = 0x82;
+const byte S7AreaMK = 0x83;
+const byte S7AreaDB = 0x84;
+const byte S7AreaCT = 0x1C;
+const byte S7AreaTM = 0x1D;
+
+// Word Length
+const int S7WLBit = 0x01;
+const int S7WLByte = 0x02;
+const int S7WLWord = 0x04;
+const int S7WLDWord = 0x06;
+const int S7WLReal = 0x08;
+const int S7WLCounter = 0x1C;
+const int S7WLTimer = 0x1D;
+
+// Block type
+const byte Block_OB = 0x38;
+const byte Block_DB = 0x41;
+const byte Block_SDB = 0x42;
+const byte Block_FC = 0x43;
+const byte Block_SFC = 0x44;
+const byte Block_FB = 0x45;
+const byte Block_SFB = 0x46;
+
+// Sub Block Type
+const byte SubBlk_OB = 0x08;
+const byte SubBlk_DB = 0x0A;
+const byte SubBlk_SDB = 0x0B;
+const byte SubBlk_FC = 0x0C;
+const byte SubBlk_SFC = 0x0D;
+const byte SubBlk_FB = 0x0E;
+const byte SubBlk_SFB = 0x0F;
+
+// Block languages
+const byte BlockLangAWL = 0x01;
+const byte BlockLangKOP = 0x02;
+const byte BlockLangFUP = 0x03;
+const byte BlockLangSCL = 0x04;
+const byte BlockLangDB = 0x05;
+const byte BlockLangGRAPH = 0x06;
+
+// Read/Write Multivars
+typedef struct{
+ int Area;
+ int WordLen;
+ int Result;
+ int DBNumber;
+ int Start;
+ int Amount;
+ void *pdata;
+} TS7DataItem, *PS7DataItem;
+
+//typedef int TS7ResultItems[MaxVars];
+//typedef TS7ResultItems *PS7ResultItems;
+
+// List Blocks
+typedef struct {
+ int OBCount;
+ int FBCount;
+ int FCCount;
+ int SFBCount;
+ int SFCCount;
+ int DBCount;
+ int SDBCount;
+} TS7BlocksList, *PS7BlocksList;
+
+// Blocks info
+typedef struct {
+ int BlkType; // Block Type (OB, DB)
+ int BlkNumber; // Block number
+ int BlkLang; // Block Language
+ int BlkFlags; // Block flags
+ int MC7Size; // The real size in bytes
+ int LoadSize; // Load memory size
+ int LocalData; // Local data
+ int SBBLength; // SBB Length
+ int CheckSum; // Checksum
+ int Version; // Block version
+ // Chars info
+ char CodeDate[11]; // Code date
+ char IntfDate[11]; // Interface date
+ char Author[9]; // Author
+ char Family[9]; // Family
+ char Header[9]; // Header
+} TS7BlockInfo, *PS7BlockInfo ;
+
+typedef word TS7BlocksOfType[0x2000];
+typedef TS7BlocksOfType *PS7BlocksOfType;
+
+// Order code
+typedef struct {
+ char Code[21];
+ byte V1;
+ byte V2;
+ byte V3;
+} TS7OrderCode, *PS7OrderCode;
+
+// CPU Info
+typedef struct {
+ char ModuleTypeName[33];
+ char SerialNumber[25];
+ char ASName[25];
+ char Copyright[27];
+ char ModuleName[25];
+} TS7CpuInfo, *PS7CpuInfo;
+
+// CP Info
+typedef struct {
+ int MaxPduLengt;
+ int MaxConnections;
+ int MaxMpiRate;
+ int MaxBusRate;
+} TS7CpInfo, *PS7CpInfo;
+
+// See §33.1 of "System Software for S7-300/400 System and Standard Functions"
+// and see SFC51 description too
+typedef struct {
+ word LENTHDR;
+ word N_DR;
+} SZL_HEADER, *PSZL_HEADER;
+
+typedef struct {
+ SZL_HEADER Header;
+ byte Data[0x4000-4];
+} TS7SZL, *PS7SZL;
+
+// SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted
+typedef struct {
+ SZL_HEADER Header;
+ word List[0x2000-2];
+} TS7SZLList, *PS7SZLList;
+
+// See §33.19 of "System Software for S7-300/400 System and Standard Functions"
+typedef struct {
+ word sch_schal;
+ word sch_par;
+ word sch_rel;
+ word bart_sch;
+ word anl_sch;
+} TS7Protection, *PS7Protection;
+
+// Client completion callback
+typedef void (S7API *pfn_CliCompletion) (void *usrPtr, int opCode, int opResult);
+//------------------------------------------------------------------------------
+// Import prototypes
+//------------------------------------------------------------------------------
+S7Object S7API Cli_Create();
+void S7API Cli_Destroy(S7Object *Client);
+int S7API Cli_ConnectTo(S7Object Client, const char *Address, int Rack, int Slot);
+int S7API Cli_SetConnectionParams(S7Object Client, const char *Address, word LocalTSAP, word RemoteTSAP);
+int S7API Cli_SetConnectionType(S7Object Client, word ConnectionType);
+int S7API Cli_Connect(S7Object Client);
+int S7API Cli_Disconnect(S7Object Client);
+int S7API Cli_GetParam(S7Object Client, int ParamNumber, void *pValue);
+int S7API Cli_SetParam(S7Object Client, int ParamNumber, void *pValue);
+int S7API Cli_SetAsCallback(S7Object Client, pfn_CliCompletion pCompletion, void *usrPtr);
+// Data I/O main functions
+int S7API Cli_ReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+int S7API Cli_WriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+int S7API Cli_ReadMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);
+int S7API Cli_WriteMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);
+// Data I/O Lean functions
+int S7API Cli_DBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
+int S7API Cli_DBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
+int S7API Cli_MBRead(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_MBWrite(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_EBRead(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_EBWrite(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_ABRead(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_ABWrite(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_TMRead(S7Object Client, int Start, int Amount, void *pUsrData);
+int S7API Cli_TMWrite(S7Object Client, int Start, int Amount, void *pUsrData);
+int S7API Cli_CTRead(S7Object Client, int Start, int Amount, void *pUsrData);
+int S7API Cli_CTWrite(S7Object Client, int Start, int Amount, void *pUsrData);
+// Directory functions
+int S7API Cli_ListBlocks(S7Object Client, TS7BlocksList *pUsrData);
+int S7API Cli_GetAgBlockInfo(S7Object Client, int BlockType, int BlockNum, TS7BlockInfo *pUsrData);
+int S7API Cli_GetPgBlockInfo(S7Object Client, void *pBlock, TS7BlockInfo *pUsrData, int Size);
+int S7API Cli_ListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);
+// Blocks functions
+int S7API Cli_Upload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
+int S7API Cli_FullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
+int S7API Cli_Download(S7Object Client, int BlockNum, void *pUsrData, int Size);
+int S7API Cli_Delete(S7Object Client, int BlockType, int BlockNum);
+int S7API Cli_DBGet(S7Object Client, int DBNumber, void *pUsrData, int *Size);
+int S7API Cli_DBFill(S7Object Client, int DBNumber, int FillChar);
+// Date/Time functions
+int S7API Cli_GetPlcDateTime(S7Object Client, tm *DateTime);
+int S7API Cli_SetPlcDateTime(S7Object Client, tm *DateTime);
+int S7API Cli_SetPlcSystemDateTime(S7Object Client);
+// System Info functions
+int S7API Cli_GetOrderCode(S7Object Client, TS7OrderCode *pUsrData);
+int S7API Cli_GetCpuInfo(S7Object Client, TS7CpuInfo *pUsrData);
+int S7API Cli_GetCpInfo(S7Object Client, TS7CpInfo *pUsrData);
+int S7API Cli_ReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int *Size);
+int S7API Cli_ReadSZLList(S7Object Client, TS7SZLList *pUsrData, int *ItemsCount);
+// Control functions
+int S7API Cli_PlcHotStart(S7Object Client);
+int S7API Cli_PlcColdStart(S7Object Client);
+int S7API Cli_PlcStop(S7Object Client);
+int S7API Cli_CopyRamToRom(S7Object Client, int Timeout);
+int S7API Cli_Compress(S7Object Client, int Timeout);
+int S7API Cli_GetPlcStatus(S7Object Client, int *Status);
+// Security functions
+int S7API Cli_GetProtection(S7Object Client, TS7Protection *pUsrData);
+int S7API Cli_SetSessionPassword(S7Object Client, char *Password);
+int S7API Cli_ClearSessionPassword(S7Object Client);
+// Low level
+int S7API Cli_IsoExchangeBuffer(S7Object Client, void *pUsrData, int *Size);
+// Misc
+int S7API Cli_GetExecTime(S7Object Client, int *Time);
+int S7API Cli_GetLastError(S7Object Client, int *LastError);
+int S7API Cli_GetPduLength(S7Object Client, int *Requested, int *Negotiated);
+int S7API Cli_ErrorText(int Error, char *Text, int TextLen);
+// 1.1.0
+int S7API Cli_GetConnected(S7Object Client, int *Connected);
+//------------------------------------------------------------------------------
+// Async functions
+//------------------------------------------------------------------------------
+int S7API Cli_AsReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+int S7API Cli_AsWriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+int S7API Cli_AsDBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
+int S7API Cli_AsDBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
+int S7API Cli_AsMBRead(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_AsMBWrite(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_AsEBRead(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_AsEBWrite(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_AsABRead(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_AsABWrite(S7Object Client, int Start, int Size, void *pUsrData);
+int S7API Cli_AsTMRead(S7Object Client, int Start, int Amount, void *pUsrData);
+int S7API Cli_AsTMWrite(S7Object Client, int Start, int Amount, void *pUsrData);
+int S7API Cli_AsCTRead(S7Object Client, int Start, int Amount, void *pUsrData);
+int S7API Cli_AsCTWrite(S7Object Client, int Start, int Amount, void *pUsrData);
+int S7API Cli_AsListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);
+int S7API Cli_AsReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int *Size);
+int S7API Cli_AsReadSZLList(S7Object Client, TS7SZLList *pUsrData, int *ItemsCount);
+int S7API Cli_AsUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
+int S7API Cli_AsFullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);
+int S7API Cli_AsDownload(S7Object Client, int BlockNum, void *pUsrData, int Size);
+int S7API Cli_AsCopyRamToRom(S7Object Client, int Timeout);
+int S7API Cli_AsCompress(S7Object Client, int Timeout);
+int S7API Cli_AsDBGet(S7Object Client, int DBNumber, void *pUsrData, int *Size);
+int S7API Cli_AsDBFill(S7Object Client, int DBNumber, int FillChar);
+int S7API Cli_CheckAsCompletion(S7Object Client, int *opResult);
+int S7API Cli_WaitAsCompletion(S7Object Client, int Timeout);
+
+//******************************************************************************
+// SERVER
+//******************************************************************************
+const int OperationRead = 0;
+const int OperationWrite = 1;
+
+const int mkEvent = 0;
+const int mkLog = 1;
+
+// Server Area ID (use with Register/unregister - Lock/unlock Area)
+const int srvAreaPE = 0;
+const int srvAreaPA = 1;
+const int srvAreaMK = 2;
+const int srvAreaCT = 3;
+const int srvAreaTM = 4;
+const int srvAreaDB = 5;
+
+// Errors
+const longword errSrvCannotStart = 0x00100000; // Server cannot start
+const longword errSrvDBNullPointer = 0x00200000; // Passed null as PData
+const longword errSrvAreaAlreadyExists = 0x00300000; // Area Re-registration
+const longword errSrvUnknownArea = 0x00400000; // Unknown area
+const longword errSrvInvalidParams = 0x00500000; // Invalid param(s) supplied
+const longword errSrvTooManyDB = 0x00600000; // Cannot register DB
+const longword errSrvInvalidParamNumber = 0x00700000; // Invalid param (srv_get/set_param)
+const longword errSrvCannotChangeParam = 0x00800000; // Cannot change because running
+
+// TCP Server Event codes
+const longword evcServerStarted = 0x00000001;
+const longword evcServerStopped = 0x00000002;
+const longword evcListenerCannotStart = 0x00000004;
+const longword evcClientAdded = 0x00000008;
+const longword evcClientRejected = 0x00000010;
+const longword evcClientNoRoom = 0x00000020;
+const longword evcClientException = 0x00000040;
+const longword evcClientDisconnected = 0x00000080;
+const longword evcClientTerminated = 0x00000100;
+const longword evcClientsDropped = 0x00000200;
+const longword evcReserved_00000400 = 0x00000400; // actually unused
+const longword evcReserved_00000800 = 0x00000800; // actually unused
+const longword evcReserved_00001000 = 0x00001000; // actually unused
+const longword evcReserved_00002000 = 0x00002000; // actually unused
+const longword evcReserved_00004000 = 0x00004000; // actually unused
+const longword evcReserved_00008000 = 0x00008000; // actually unused
+// S7 Server Event Code
+const longword evcPDUincoming = 0x00010000;
+const longword evcDataRead = 0x00020000;
+const longword evcDataWrite = 0x00040000;
+const longword evcNegotiatePDU = 0x00080000;
+const longword evcReadSZL = 0x00100000;
+const longword evcClock = 0x00200000;
+const longword evcUpload = 0x00400000;
+const longword evcDownload = 0x00800000;
+const longword evcDirectory = 0x01000000;
+const longword evcSecurity = 0x02000000;
+const longword evcControl = 0x04000000;
+const longword evcReserved_08000000 = 0x08000000; // actually unused
+const longword evcReserved_10000000 = 0x10000000; // actually unused
+const longword evcReserved_20000000 = 0x20000000; // actually unused
+const longword evcReserved_40000000 = 0x40000000; // actually unused
+const longword evcReserved_80000000 = 0x80000000; // actually unused
+// Masks to enable/disable all events
+const longword evcAll = 0xFFFFFFFF;
+const longword evcNone = 0x00000000;
+// Event SubCodes
+const word evsUnknown = 0x0000;
+const word evsStartUpload = 0x0001;
+const word evsStartDownload = 0x0001;
+const word evsGetBlockList = 0x0001;
+const word evsStartListBoT = 0x0002;
+const word evsListBoT = 0x0003;
+const word evsGetBlockInfo = 0x0004;
+const word evsGetClock = 0x0001;
+const word evsSetClock = 0x0002;
+const word evsSetPassword = 0x0001;
+const word evsClrPassword = 0x0002;
+// Event Params : functions group
+const word grProgrammer = 0x0041;
+const word grCyclicData = 0x0042;
+const word grBlocksInfo = 0x0043;
+const word grSZL = 0x0044;
+const word grPassword = 0x0045;
+const word grBSend = 0x0046;
+const word grClock = 0x0047;
+const word grSecurity = 0x0045;
+// Event Params : control codes
+const word CodeControlUnknown = 0x0000;
+const word CodeControlColdStart = 0x0001;
+const word CodeControlWarmStart = 0x0002;
+const word CodeControlStop = 0x0003;
+const word CodeControlCompress = 0x0004;
+const word CodeControlCpyRamRom = 0x0005;
+const word CodeControlInsDel = 0x0006;
+// Event Result
+const word evrNoError = 0x0000;
+const word evrFragmentRejected = 0x0001;
+const word evrMalformedPDU = 0x0002;
+const word evrSparseBytes = 0x0003;
+const word evrCannotHandlePDU = 0x0004;
+const word evrNotImplemented = 0x0005;
+const word evrErrException = 0x0006;
+const word evrErrAreaNotFound = 0x0007;
+const word evrErrOutOfRange = 0x0008;
+const word evrErrOverPDU = 0x0009;
+const word evrErrTransportSize = 0x000A;
+const word evrInvalidGroupUData = 0x000B;
+const word evrInvalidSZL = 0x000C;
+const word evrDataSizeMismatch = 0x000D;
+const word evrCannotUpload = 0x000E;
+const word evrCannotDownload = 0x000F;
+const word evrUploadInvalidID = 0x0010;
+const word evrResNotFound = 0x0011;
+
+typedef struct{
+ time_t EvtTime; // Timestamp
+ int EvtSender; // Sender
+ longword EvtCode; // Event code
+ word EvtRetCode; // Event result
+ word EvtParam1; // Param 1 (if available)
+ word EvtParam2; // Param 2 (if available)
+ word EvtParam3; // Param 3 (if available)
+ word EvtParam4; // Param 4 (if available)
+}TSrvEvent, *PSrvEvent;
+
+// Server Events callback
+typedef void (S7API *pfn_SrvCallBack)(void *usrPtr, PSrvEvent PEvent, int Size);
+// Server Read/Write callback
+typedef int(S7API *pfn_RWAreaCallBack)(void *usrPtr, int Sender, int Operation, PS7Tag PTag, void *pUsrData);
+
+S7Object S7API Srv_Create();
+void S7API Srv_Destroy(S7Object *Server);
+int S7API Srv_GetParam(S7Object Server, int ParamNumber, void *pValue);
+int S7API Srv_SetParam(S7Object Server, int ParamNumber, void *pValue);
+int S7API Srv_StartTo(S7Object Server, const char *Address);
+int S7API Srv_Start(S7Object Server);
+int S7API Srv_Stop(S7Object Server);
+int S7API Srv_RegisterArea(S7Object Server, int AreaCode, word Index, void *pUsrData, int Size);
+int S7API Srv_UnregisterArea(S7Object Server, int AreaCode, word Index);
+int S7API Srv_LockArea(S7Object Server, int AreaCode, word Index);
+int S7API Srv_UnlockArea(S7Object Server, int AreaCode, word Index);
+int S7API Srv_GetStatus(S7Object Server, int *ServerStatus, int *CpuStatus, int *ClientsCount);
+int S7API Srv_SetCpuStatus(S7Object Server, int CpuStatus);
+int S7API Srv_ClearEvents(S7Object Server);
+int S7API Srv_PickEvent(S7Object Server, TSrvEvent *pEvent, int *EvtReady);
+int S7API Srv_GetMask(S7Object Server, int MaskKind, longword *Mask);
+int S7API Srv_SetMask(S7Object Server, int MaskKind, longword Mask);
+int S7API Srv_SetEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);
+int S7API Srv_SetReadEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);
+int S7API Srv_SetRWAreaCallback(S7Object Server, pfn_RWAreaCallBack pCallback, void *usrPtr);
+int S7API Srv_EventText(TSrvEvent *Event, char *Text, int TextLen);
+int S7API Srv_ErrorText(int Error, char *Text, int TextLen);
+
+//******************************************************************************
+// PARTNER
+//******************************************************************************
+
+// Status
+const int par_stopped = 0; // stopped
+const int par_connecting = 1; // running and active connecting
+const int par_waiting = 2; // running and waiting for a connection
+const int par_linked = 3; // running and connected : linked
+const int par_sending = 4; // sending data
+const int par_receiving = 5; // receiving data
+const int par_binderror = 6; // error starting passive server
+
+// Errors
+const longword errParAddressInUse = 0x00200000;
+const longword errParNoRoom = 0x00300000;
+const longword errServerNoRoom = 0x00400000;
+const longword errParInvalidParams = 0x00500000;
+const longword errParNotLinked = 0x00600000;
+const longword errParBusy = 0x00700000;
+const longword errParFrameTimeout = 0x00800000;
+const longword errParInvalidPDU = 0x00900000;
+const longword errParSendTimeout = 0x00A00000;
+const longword errParRecvTimeout = 0x00B00000;
+const longword errParSendRefused = 0x00C00000;
+const longword errParNegotiatingPDU = 0x00D00000;
+const longword errParSendingBlock = 0x00E00000;
+const longword errParRecvingBlock = 0x00F00000;
+const longword errParBindError = 0x01000000;
+const longword errParDestroying = 0x01100000;
+const longword errParInvalidParamNumber = 0x01200000; // Invalid param (par_get/set_param)
+const longword errParCannotChangeParam = 0x01300000; // Cannot change because running
+const longword errParBufferTooSmall = 0x01400000; // Raised by LabVIEW wrapper
+
+// Brecv Data incoming Callback
+typedef void (S7API *pfn_ParRecvCallBack)(void * usrPtr, int opResult, longword R_ID, void *pData, int Size);
+// BSend Completion Callback
+typedef void (S7API *pfn_ParSendCompletion)(void * usrPtr, int opResult);
+
+S7Object S7API Par_Create(int Active);
+void S7API Par_Destroy(S7Object *Partner);
+int S7API Par_GetParam(S7Object Partner, int ParamNumber, void *pValue);
+int S7API Par_SetParam(S7Object Partner, int ParamNumber, void *pValue);
+int S7API Par_StartTo(S7Object Partner, const char *LocalAddress, const char *RemoteAddress,
+ word LocTsap, word RemTsap);
+int S7API Par_Start(S7Object Partner);
+int S7API Par_Stop(S7Object Partner);
+// BSend
+int S7API Par_BSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);
+int S7API Par_AsBSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);
+int S7API Par_CheckAsBSendCompletion(S7Object Partner, int *opResult);
+int S7API Par_WaitAsBSendCompletion(S7Object Partner, longword Timeout);
+int S7API Par_SetSendCallback(S7Object Partner, pfn_ParSendCompletion pCompletion, void *usrPtr);
+// BRecv
+int S7API Par_BRecv(S7Object Partner, longword *R_ID, void *pData, int *Size, longword Timeout);
+int S7API Par_CheckAsBRecvCompletion(S7Object Partner, int *opResult, longword *R_ID,
+ void *pData, int *Size);
+int S7API Par_SetRecvCallback(S7Object Partner, pfn_ParRecvCallBack pCompletion, void *usrPtr);
+// Stat
+int S7API Par_GetTimes(S7Object Partner, longword *SendTime, longword *RecvTime);
+int S7API Par_GetStats(S7Object Partner, longword *BytesSent, longword *BytesRecv,
+ longword *SendErrors, longword *RecvErrors);
+int S7API Par_GetLastError(S7Object Partner, int *LastError);
+int S7API Par_GetStatus(S7Object Partner, int *Status);
+int S7API Par_ErrorText(int Error, char *Text, int TextLen);
+
+
+#pragma pack()
+#ifdef __cplusplus
+ }
+#endif // __cplusplus
+
+#ifdef __cplusplus
+
+//******************************************************************************
+// CLIENT CLASS DEFINITION
+//******************************************************************************
+class TS7Client
+{
+private:
+ S7Object Client;
+public:
+ TS7Client();
+ ~TS7Client();
+ // Control functions
+ int Connect();
+ int ConnectTo(const char *RemAddress, int Rack, int Slot);
+ int SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTSAP);
+ int SetConnectionType(word ConnectionType);
+ int Disconnect();
+ int GetParam(int ParamNumber, void *pValue);
+ int SetParam(int ParamNumber, void *pValue);
+ // Data I/O Main functions
+ int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+ int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+ int ReadMultiVars(PS7DataItem Item, int ItemsCount);
+ int WriteMultiVars(PS7DataItem Item, int ItemsCount);
+ // Data I/O Lean functions
+ int DBRead(int DBNumber, int Start, int Size, void *pUsrData);
+ int DBWrite(int DBNumber, int Start, int Size, void *pUsrData);
+ int MBRead(int Start, int Size, void *pUsrData);
+ int MBWrite(int Start, int Size, void *pUsrData);
+ int EBRead(int Start, int Size, void *pUsrData);
+ int EBWrite(int Start, int Size, void *pUsrData);
+ int ABRead(int Start, int Size, void *pUsrData);
+ int ABWrite(int Start, int Size, void *pUsrData);
+ int TMRead(int Start, int Amount, void *pUsrData);
+ int TMWrite(int Start, int Amount, void *pUsrData);
+ int CTRead(int Start, int Amount, void *pUsrData);
+ int CTWrite(int Start, int Amount, void *pUsrData);
+ // Directory functions
+ int ListBlocks(PS7BlocksList pUsrData);
+ int GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData);
+ int GetPgBlockInfo(void *pBlock, PS7BlockInfo pUsrData, int Size);
+ int ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);
+ // Blocks functions
+ int Upload(int BlockType, int BlockNum, void *pUsrData, int *Size);
+ int FullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size);
+ int Download(int BlockNum, void *pUsrData, int Size);
+ int Delete(int BlockType, int BlockNum);
+ int DBGet(int DBNumber, void *pUsrData, int *Size);
+ int DBFill(int DBNumber, int FillChar);
+ // Date/Time functions
+ int GetPlcDateTime(tm *DateTime);
+ int SetPlcDateTime(tm *DateTime);
+ int SetPlcSystemDateTime();
+ // System Info functions
+ int GetOrderCode(PS7OrderCode pUsrData);
+ int GetCpuInfo(PS7CpuInfo pUsrData);
+ int GetCpInfo(PS7CpInfo pUsrData);
+ int ReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size);
+ int ReadSZLList(PS7SZLList pUsrData, int *ItemsCount);
+ // Control functions
+ int PlcHotStart();
+ int PlcColdStart();
+ int PlcStop();
+ int CopyRamToRom(int Timeout);
+ int Compress(int Timeout);
+ // Security functions
+ int GetProtection(PS7Protection pUsrData);
+ int SetSessionPassword(char *Password);
+ int ClearSessionPassword();
+ // Properties
+ int ExecTime();
+ int LastError();
+ int PDURequested();
+ int PDULength();
+ int PlcStatus();
+ bool Connected();
+ // Async functions
+ int SetAsCallback(pfn_CliCompletion pCompletion, void *usrPtr);
+ bool CheckAsCompletion(int *opResult);
+ int WaitAsCompletion(longword Timeout);
+ int AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+ int AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
+ int AsListBlocksOfType(int BlockType, PS7BlocksOfType pUsrData, int *ItemsCount);
+ int AsReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size);
+ int AsReadSZLList(PS7SZLList pUsrData, int *ItemsCount);
+ int AsUpload(int BlockType, int BlockNum, void *pUsrData, int *Size);
+ int AsFullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size);
+ int AsDownload(int BlockNum, void *pUsrData, int Size);
+ int AsCopyRamToRom(int Timeout);
+ int AsCompress(int Timeout);
+ int AsDBRead(int DBNumber, int Start, int Size, void *pUsrData);
+ int AsDBWrite(int DBNumber, int Start, int Size, void *pUsrData);
+ int AsMBRead(int Start, int Size, void *pUsrData);
+ int AsMBWrite(int Start, int Size, void *pUsrData);
+ int AsEBRead(int Start, int Size, void *pUsrData);
+ int AsEBWrite(int Start, int Size, void *pUsrData);
+ int AsABRead(int Start, int Size, void *pUsrData);
+ int AsABWrite(int Start, int Size, void *pUsrData);
+ int AsTMRead(int Start, int Amount, void *pUsrData);
+ int AsTMWrite(int Start, int Amount, void *pUsrData);
+ int AsCTRead(int Start, int Amount, void *pUsrData);
+ int AsCTWrite(int Start, int Amount, void *pUsrData);
+ int AsDBGet(int DBNumber, void *pUsrData, int *Size);
+ int AsDBFill(int DBNumber, int FillChar);
+};
+typedef TS7Client *PS7Client;
+//******************************************************************************
+// SERVER CLASS DEFINITION
+//******************************************************************************
+class TS7Server
+{
+private:
+ S7Object Server;
+public:
+ TS7Server();
+ ~TS7Server();
+ // Control
+ int Start();
+ int StartTo(const char *Address);
+ int Stop();
+ int GetParam(int ParamNumber, void *pValue);
+ int SetParam(int ParamNumber, void *pValue);
+ // Events
+ int SetEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr);
+ int SetReadEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr);
+ int SetRWAreaCallback(pfn_RWAreaCallBack PCallBack, void *UsrPtr);
+ bool PickEvent(TSrvEvent *pEvent);
+ void ClearEvents();
+ longword GetEventsMask();
+ longword GetLogMask();
+ void SetEventsMask(longword Mask);
+ void SetLogMask(longword Mask);
+ // Resources
+ int RegisterArea(int AreaCode, word Index, void *pUsrData, word Size);
+ int UnregisterArea(int AreaCode, word Index);
+ int LockArea(int AreaCode, word Index);
+ int UnlockArea(int AreaCode, word Index);
+ // Properties
+ int ServerStatus();
+ int GetCpuStatus();
+ int SetCpuStatus(int Status);
+ int ClientsCount();
+};
+typedef TS7Server *PS7Server;
+
+//******************************************************************************
+// PARTNER CLASS DEFINITION
+//******************************************************************************
+class TS7Partner
+{
+private:
+ S7Object Partner; // Partner Handle
+public:
+ TS7Partner(bool Active);
+ ~TS7Partner();
+ // Control
+ int GetParam(int ParamNumber, void *pValue);
+ int SetParam(int ParamNumber, void *pValue);
+ int Start();
+ int StartTo(const char *LocalAddress,
+ const char *RemoteAddress,
+ int LocalTSAP,
+ int RemoteTSAP);
+ int Stop();
+ // Data I/O functions : BSend
+ int BSend(longword R_ID, void *pUsrData, int Size);
+ int AsBSend(longword R_ID, void *pUsrData, int Size);
+ bool CheckAsBSendCompletion(int *opResult);
+ int WaitAsBSendCompletion(longword Timeout);
+ int SetSendCallback(pfn_ParSendCompletion pCompletion, void *usrPtr);
+ // Data I/O functions : BRecv
+ int BRecv(longword *R_ID, void *pUsrData, int *Size, longword Timeout);
+ bool CheckAsBRecvCompletion(int *opResult, longword *R_ID, void *pUsrData, int *Size);
+ int SetRecvCallback(pfn_ParRecvCallBack pCallback, void *usrPtr);
+ // Properties
+ int Status();
+ int LastError();
+ int GetTimes(longword *SendTime, longword *RecvTime);
+ int GetStats(longword *BytesSent,
+ longword *BytesRecv,
+ longword *ErrSend,
+ longword *ErrRecv);
+ bool Linked();
+};
+typedef TS7Partner *PS7Partner;
+//******************************************************************************
+// TEXT ROUTINES
+// Only for C++, for pure C use xxx_ErrorText() which uses *char
+//******************************************************************************
+#define TextLen 1024
+
+// String type
+// Here we define generic TextString (by default mapped onto std::string).
+// So you can change it if needed (Unicodestring, Ansistring etc...)
+
+typedef std::string TextString;
+
+TextString CliErrorText(int Error);
+TextString SrvErrorText(int Error);
+TextString ParErrorText(int Error);
+TextString SrvEventText(TSrvEvent *Event);
+
+
+#endif // __cplusplus
+#endif // snap7_h
diff --git a/src/c++/dnp3/libot-sim-dnp3.so b/src/c++/dnp3/libot-sim-dnp3.so
new file mode 100755
index 0000000..ee95c90
Binary files /dev/null and b/src/c++/dnp3/libot-sim-dnp3.so differ
diff --git a/src/c++/msgbus/libot-sim-msgbus.so b/src/c++/msgbus/libot-sim-msgbus.so
new file mode 100755
index 0000000..adea28e
Binary files /dev/null and b/src/c++/msgbus/libot-sim-msgbus.so differ
diff --git a/src/c++/s7/CMakeLists.txt b/src/c++/s7/CMakeLists.txt
new file mode 100644
index 0000000..3ba16b7
--- /dev/null
+++ b/src/c++/s7/CMakeLists.txt
@@ -0,0 +1,25 @@
+include_directories(
+ ${CPPZMQ_INCLUDE_DIRS}
+ ${FMT_INCLUDE_DIRS}
+ ${SNAP7_INCLUDE_DIRS}
+ ${OTSIM_INCLUDE_DIRS}
+)
+
+file(GLOB_RECURSE ot-sim-s7_SRC *.cpp *.hpp)
+
+add_library(ot-sim-s7 SHARED
+ ${ot-sim-s7_SRC}
+)
+
+target_link_libraries(ot-sim-s7
+ cppzmq
+ fmt::fmt
+ snap7
+ ot-sim-msgbus
+)
+
+install(TARGETS ot-sim-s7
+ ARCHIVE DESTINATION lib
+ LIBRARY DESTINATION lib
+ RUNTIME DESTINATION bin
+)
diff --git a/src/c++/s7/client.cpp b/src/c++/s7/client.cpp
new file mode 100644
index 0000000..1bd1c9d
--- /dev/null
+++ b/src/c++/s7/client.cpp
@@ -0,0 +1,37 @@
+#include
+
+#include "client.hpp"
+
+#include "fmt/format.h"
+
+
+namespace otsim {
+namespace s7 {
+
+Client::Client(std::string id, Pusher pusher) : id(id), pusher(pusher) {}
+
+/*
+void Server::Run(std::shared_ptr ts7client, ){
+ ts7client->
+}*/
+
+void Client::HandleMsgBusUpdate(const otsim::msgbus::Envelope& env) {
+ auto sender = otsim::msgbus::GetEnvelopeSender(env);
+
+ //if the update sender is the same as the client, disregard the update and exit
+ if (sender == id) {
+ return;
+ }
+
+ //sort through each point in the envelope and handle them with appropriate functions for binary and analog
+ for (auto &p : env.contents.updates) {
+ if (WriteBinary(p.tag,p.value)) {
+ continue;
+ }
+
+ WriteAnalog(p.tag, p.value);
+ }
+}
+
+}
+}
\ No newline at end of file
diff --git a/src/c++/s7/client.hpp b/src/c++/s7/client.hpp
new file mode 100644
index 0000000..9a3c8aa
--- /dev/null
+++ b/src/c++/s7/client.hpp
@@ -0,0 +1,168 @@
+#ifndef OTSIM_S7_CLIENT_HPP
+#define OTSIM_S7_CLIENT_HPP
+
+#include
+#include
+#include