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.closed +
10
+ false +
+ + 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.closed +
10
+ false +
+ + 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 + + +
10
+ line-650632.closed + Group10Var2 + Group11Var2 + Class1 + false +
+ +
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 + +#include "common.hpp" + +#include "msgbus/envelope.hpp" + +#include "snap7.h" + +namespace otsim { +namespace s7 { + +struct ClientConfig { + std::string id; + std::uint16_t address; + std::string logLevel = "info"; +}; + +class Client : public std::enable_shared_from_this{ +public: + //used for dynamically creating Clients + static std::shared_ptr Create(std::string id, Pusher pusher) { + return std::make_shared(id, pusher); + } + + Client(std::string id, Pusher pusher); + ~Client() {}; + + //void Run(std::shared_ptr ts7client); + + std::string ID() { return id; } + std::uint16_t Address() { return address; } + + //setter function for id and address (config) + ClientConfig BuildConfig(std::string idVal, std::uint16_t local) { + address = local; + id = idVal; + + ClientConfig config; + + config.address = local; + config.id = idVal; + + std::cout << "initializing client " << config.address << std::endl; + + return config; + } + + void AddBinaryTag(std::uint16_t address, std::string tag) { + binaryInputTags[address] = tag; + } + + void AddBinaryTag(std::uint16_t address, std::string tag, bool sbo) { + binaryOutputTags[address] = tag; + + BinaryOutputPoint point = {.address = address, .tag = tag, .output = true, .sbo = sbo}; + binaryOutputs[tag] = point; + } + + void AddAnalogTag(std::uint16_t address, std::string tag) { + analogInputTags[address] = tag; + } + + void AddAnalogTag(std::uint16_t address, std::string tag, bool sbo) { + analogOutputTags[address] = tag; + + AnalogOutputPoint point = {.address = address, .tag = tag, .output = true, .sbo = sbo}; + analogOutputs[tag] = point; + } + + std::string GetBinaryTag(std::uint16_t address, bool output = false) { + if (output) { + auto iter = binaryOutputTags.find(address); + if (iter != binaryOutputTags.end()) { + return iter->second; + } + + return {}; + } + + auto iter = binaryInputTags.find(address); + if (iter != binaryInputTags.end()) { + return iter->second; + } + + return {}; + } + + std::string GetAnalogTag(std::uint16_t address, bool output = false) { + if (output) { + auto iter = analogOutputTags.find(address); + if (iter != analogOutputTags.end()) { + return iter->second; + } + + return {}; + } + + auto iter = analogInputTags.find(address); + if (iter != analogInputTags.end()) { + return iter->second; + } + + return {}; + } + + bool WriteBinary(std::string tag, bool status) { + auto iter = binaryOutputs.find(tag); + if (iter == binaryOutputs.end()) { + return false; + } + + auto point = iter->second; + + if (!point.output) { + return false; + } + + // TODO: + + + return true; + } + + bool WriteAnalog(std::string tag, double value) { + auto iter = analogOutputs.find(tag); + if (iter == analogOutputs.end()) { + return false; + } + + auto point = iter->second; + + if (!point.output) { + return false; + } + + // TODO: + + + return true; + } + + void HandleMsgBusUpdate(const otsim::msgbus::Envelope& env); + +private: + std::string id; + std::uint16_t address; + + Pusher pusher; + + std::shared_ptr client; + + std::map binaryInputTags; + std::map binaryOutputTags; + std::map analogInputTags; + std::map analogOutputTags; + std::map binaryOutputs; + std::map analogOutputs; +}; + +} // namespace s7 +} // namespace otsim + +#endif // OTSIM_S7_CLIENT_HPP \ No newline at end of file diff --git a/src/c++/s7/common.hpp b/src/c++/s7/common.hpp new file mode 100644 index 0000000..ee73025 --- /dev/null +++ b/src/c++/s7/common.hpp @@ -0,0 +1,35 @@ +#ifndef OTSIM_S7_COMMON_HPP +#define OTSIM_S7_COMMON_HPP + +#include "msgbus/metrics.hpp" +#include "msgbus/pusher.hpp" + +namespace otsim { +namespace s7 { + +template +struct Point { + std::uint16_t address {}; + std::string tag {}; + + T value {}; + + bool output {}; + bool sbo {}; + + double deadband; +}; + +typedef Point BinaryInputPoint; +typedef Point AnalogInputPoint; + +typedef Point BinaryOutputPoint; +typedef Point AnalogOutputPoint; + +typedef std::shared_ptr Pusher; +typedef std::shared_ptr MetricsPusher; + +} // namespace s7 +} // namespace otsim + +#endif // OTSIM_S7_COMMON_HPP \ No newline at end of file diff --git a/src/c++/s7/server.cpp b/src/c++/s7/server.cpp new file mode 100644 index 0000000..e4bfa8d --- /dev/null +++ b/src/c++/s7/server.cpp @@ -0,0 +1,241 @@ +#include + +#include "server.hpp" +#include "fmt/format.h" + +#include "msgbus/metrics.hpp" + +#include "snap7.h" + +namespace otsim { +namespace s7 { + + //Constructor + Server::Server(ServerConfig config, Pusher pusher): config(config), pusher(pusher) { + + //create a Metrics Pusher and add counters for status', updates, and binary/analog writes + metrics = otsim::msgbus::MetricsPusher::Create(); + + metrics->NewMetric("Counter", "status_count", "number of OT-sim status messages processed"); + metrics->NewMetric("Counter", "update_count", "number of OT-sim update messages generated"); + metrics->NewMetric("Counter", "s7_binary_write_count", "number of S7 binary writes processed"); + metrics->NewMetric("Counter", "s7_analog_write_count", "number of S7 analog writes processed"); + } + + //start the snap7 server created in otstim-s7comm-module main.cpp + void Server::Run(std::shared_ptr ts7server){ + metrics->Start(pusher, config.id); + //ts7server->Start(); + running = true; + while(running){ + for (const auto& kv : binaryInputs) { + const std::uint16_t addr = kv.first; + const float val = kv.second.value; + const std::string tag = kv.second.tag; + + try { + auto lock = std::unique_lock(pointsMu); + auto point = points.at(tag); + std::cout << fmt::format("[{}] updated binary input {} to {}", config.id, addr, point.value) << std::endl; + + WriteAnalog(addr, point.value); + metrics->IncrMetric("s7_analog_write_count"); + } catch (const std::out_of_range&) {} + } + + //loop through all analog outputs, get their address and value, send that information to WriteAnalog where they will be pushed to the msgbus + for (const auto& kv : analogInputs) { + const std::uint16_t addr = kv.first; + const float val = kv.second.value; + const std::string tag = kv.second.tag; + + try { + auto lock = std::unique_lock(pointsMu); + auto point = points.at(tag); + std::cout << fmt::format("[{}] updated analog input {} to {}", config.id, addr, point.value) << std::endl; + WriteAnalog(addr, point.value); + metrics->IncrMetric("s7_analog_write_count"); + } catch (const std::out_of_range&) {} + } + + //loop through all analog outputs, get their address and value, send that information to WriteAnalog where they will be pushed to the msgbus + for (const auto& kv : analogOutputs) { + const std::uint16_t addr = kv.first; + const float val = kv.second.value; + const std::string tag = kv.second.tag; + + try { + auto lock = std::unique_lock(pointsMu); + auto point = points.at(tag); + std::cout << fmt::format("[{}] updated analog output {} to {}", config.id, addr, point.value) << std::endl; + WriteAnalog(addr, point.value); + metrics->IncrMetric("s7_analog_write_count"); + } catch (const std::out_of_range&) {} + } + + //loop through all binary outputs, get their address and value, send that information to WriteBinary where they will be pushed to the msgbus + for (const auto& kv : binaryOutputs) { + const std::uint16_t addr = kv.first; + const bool val = kv.second.value; + const std::string tag = kv.second.tag; + + try { + auto lock = std::unique_lock(pointsMu); + auto point = points.at(tag); + std::cout << fmt::format("[{}] updated binary output {} to {}", config.id, addr, point.value) << std::endl; + WriteAnalog(addr, point.value); + metrics->IncrMetric("s7_binary_write_count"); + } catch (const std::out_of_range&) {} + } + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + + bool Server::AddBinaryInput(BinaryInputPoint point) { + /* + * in our binary inputs array, at the position equal to the address of the + * point being passed in, set the value equal to the incoming point. Then + * create a msgbus Point structure and store it in the list of points + */ + binaryInputs[point.address] = point; + points[point.tag] = otsim::msgbus::Point{point.tag, 0.0, 0}; + + return true; //assuming this doesn't fail, return true + } + + bool Server::AddBinaryOutput(BinaryOutputPoint point) { + point.output = true; + + //store the point and point tag into the binaryOutputs and points arrays respectively + binaryOutputs[point.address] = point; + points[point.tag] = otsim::msgbus::Point{point.tag, 0.0, 0}; + + return true; + } + + bool Server::AddAnalogInput(AnalogInputPoint point) { + + //store the point and point tag into the analogInputs and points arrays respectively + analogInputs[point.address] = point; + points[point.tag] = otsim::msgbus::Point{point.tag, 0.0, 0}; + + return true; + } + + bool Server::AddAnalogOutput(AnalogOutputPoint point) { + point.output = true; + + //store the point and point tag into the analogOutputs and points arrays respectively + analogOutputs[point.address] = point; + points[point.tag] = otsim::msgbus::Point{point.tag, 0.0, 0}; + + return true; + } + + //this function interacts with the message bus to store status information for tags so other modules can access it (binary) + void Server::WriteBinary(std::uint16_t address, bool status) { + auto iter = binaryOutputs.find(address); + if (iter == binaryOutputs.end()) { + return; + } + + std::cout << fmt::format("[{}] setting tag {} to {}", config.id, iter->second.tag, status) << std::endl; + + otsim::msgbus::Points points; + points.push_back(otsim::msgbus::Point{iter->second.tag, status ? 1.0 : 0.0}); + + otsim::msgbus::Update contents = {.updates = points}; + auto env = otsim::msgbus::NewEnvelope(config.id, contents); + + pusher->Push("RUNTIME", env); + metrics->IncrMetric("update_count"); + } + + //this function interacts with the message bus to store status information for tags so other modules can access it (analog) + void Server::WriteAnalog(std::uint16_t address, double value) { + auto iter = analogOutputs.find(address); + if (iter == analogOutputs.end()) { + return; + } + + std::cout << fmt::format("[{}] setting tag {} to {}", config.id, iter->second.tag, value) << std::endl; + + otsim::msgbus::Points points; + points.push_back(otsim::msgbus::Point{iter->second.tag, value}); + + otsim::msgbus::Update contents = {.updates = points}; + auto env = otsim::msgbus::NewEnvelope(config.id, contents); + + pusher->Push("RUNTIME", env); + metrics->IncrMetric("update_count"); + } + + const BinaryOutputPoint* Server::GetBinaryOutput(const uint16_t address) { + auto iter = binaryOutputs.find(address); + if (iter == binaryOutputs.end()) { + return NULL; + } + + //if the function hasn't returned, it must've found the output, so it returns the value + return &iter->second; + } + + const AnalogOutputPoint* Server::GetAnalogOutput(const uint16_t address) { + auto iter = analogOutputs.find(address); + if (iter == analogOutputs.end()) { + return NULL; + } + + //if the function hasn't returned, it must've found the output, so it returns the value + return &iter->second; + } + + /* + * set all outputs to new points with zero values, create a new envelope with those points + * and then push that envelope with the pusher + */ + void Server::ResetOutputs() { + otsim::msgbus::Points points; + + for (const auto& kv : binaryOutputs) { + points.push_back(otsim::msgbus::Point{kv.second.tag, 0.0}); + } + + for (const auto& kv : analogOutputs) { + points.push_back(otsim::msgbus::Point{kv.second.tag, 0.0}); + } + + if (points.size()) { + std::cout << fmt::format("[{}] setting outputs to zero values", config.id) << std::endl; + + otsim::msgbus::Update contents = {.updates = points}; + auto env = otsim::msgbus::NewEnvelope(config.id, contents); + + pusher->Push("RUNTIME", env); + } + } + + void Server::HandleMsgBusStatus(const otsim::msgbus::Envelope& env) { + auto sender = otsim::msgbus::GetEnvelopeSender(env); + + //if the status sender is the current s7 device, return because the status does not need to be handled + if (sender == config.id) { + return; + } + + //increment status count + metrics->IncrMetric("status_count"); + + //add each point in measurements to the points array based on tag + for (auto &p : env.contents.measurements) { + if (points.count(p.tag)) { + std::cout << fmt::format("[{}] status received for tag {}", config.id, p.tag) << std::endl; + + auto lock = std::unique_lock(pointsMu); + points[p.tag] = p; + } + } + } + +} // namespace s7 +} // namespace otsim diff --git a/src/c++/s7/server.hpp b/src/c++/s7/server.hpp new file mode 100644 index 0000000..cd5e1dc --- /dev/null +++ b/src/c++/s7/server.hpp @@ -0,0 +1,73 @@ +#ifndef OTSIM_S7_SERVER_HPP +#define OTSIM_S7_SERVER_HPP + +#include +#include +#include + +#include "common.hpp" + +#include "msgbus/envelope.hpp" +#include "msgbus/metrics.hpp" +#include "msgbus/pusher.hpp" + +#include "snap7.h" + +namespace otsim { +namespace s7 { + +struct ServerConfig { + std::string id; + std::uint16_t address; + std::string logLevel = "info"; +}; + +class Server : public std::enable_shared_from_this{ +public: + static std::shared_ptr Create(ServerConfig config, Pusher pusher) { + return std::make_shared(config, pusher); + } + + Server(ServerConfig config, Pusher pusher); + ~Server() {}; + + std::string ID() { return config.id; } + + void Run(std::shared_ptr ts7server); + + bool AddBinaryInput(BinaryInputPoint point); + bool AddBinaryOutput(BinaryOutputPoint point); + bool AddAnalogInput(AnalogInputPoint point); + bool AddAnalogOutput(AnalogOutputPoint point); + + void WriteBinary(uint16_t address, bool value); + void WriteAnalog(uint16_t address, double value); + + const BinaryOutputPoint* GetBinaryOutput(const uint16_t address); + const AnalogOutputPoint* GetAnalogOutput(const uint16_t address); + + void ResetOutputs(); + + void HandleMsgBusStatus(const otsim::msgbus::Envelope& env); + +private: + ServerConfig config; + + Pusher pusher; + MetricsPusher metrics; + + std::map binaryInputs; + std::map binaryOutputs; + std::map analogInputs; + std::map analogOutputs; + + std::map points; + std::mutex pointsMu; + + std::atomic running; +}; + +} // namespace s7 +} // namespace otsim + +#endif // OTSIM_S7_SERVER_HPP diff --git a/src/c/cmd/ot-sim-message-bus/ot-sim-message-bus b/src/c/cmd/ot-sim-message-bus/ot-sim-message-bus new file mode 100755 index 0000000..ff281e6 Binary files /dev/null and b/src/c/cmd/ot-sim-message-bus/ot-sim-message-bus differ diff --git a/src/python/otsim.egg-info/PKG-INFO b/src/python/otsim.egg-info/PKG-INFO new file mode 100644 index 0000000..beb7d50 --- /dev/null +++ b/src/python/otsim.egg-info/PKG-INFO @@ -0,0 +1,16 @@ +Metadata-Version: 2.1 +Name: otsim +Version: 0.0.1 +Summary: OT-sim Python modules +Home-page: UNKNOWN +License: GPLv3 License +Platform: Linux +Classifier: License :: OSI Approved :: GPLv3 License +Classifier: Development Status :: 4 - Beta +Classifier: Operating System :: POSIX :: Linux +Classifier: Programming Language :: Python :: 3.5 +Classifier: Intended Audience :: Developers +Classifier: Natural Language :: English + +UNKNOWN + diff --git a/src/python/otsim.egg-info/SOURCES.txt b/src/python/otsim.egg-info/SOURCES.txt new file mode 100644 index 0000000..e9d6a56 --- /dev/null +++ b/src/python/otsim.egg-info/SOURCES.txt @@ -0,0 +1,26 @@ +setup.py +otsim/__init__.py +otsim.egg-info/PKG-INFO +otsim.egg-info/SOURCES.txt +otsim.egg-info/dependency_links.txt +otsim.egg-info/entry_points.txt +otsim.egg-info/requires.txt +otsim.egg-info/top_level.txt +otsim/ground_truth/__init__.py +otsim/ground_truth/ground_truth.py +otsim/helics_helper/__init__.py +otsim/helics_helper/version.py +otsim/io/__init__.py +otsim/io/io.py +otsim/msgbus/__init__.py +otsim/msgbus/envelope.py +otsim/msgbus/metrics.py +otsim/msgbus/pusher.py +otsim/msgbus/subscriber.py +otsim/rpi_gpio/__init__.py +otsim/rpi_gpio/rpi_gpio.py +otsim/wind_turbine/__init__.py +otsim/wind_turbine/anemometer/__init__.py +otsim/wind_turbine/anemometer/anemometer.py +otsim/wind_turbine/power_output/__init__.py +otsim/wind_turbine/power_output/power_output.py \ No newline at end of file diff --git a/src/python/otsim.egg-info/dependency_links.txt b/src/python/otsim.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/python/otsim.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/python/otsim.egg-info/entry_points.txt b/src/python/otsim.egg-info/entry_points.txt new file mode 100644 index 0000000..54a2c8f --- /dev/null +++ b/src/python/otsim.egg-info/entry_points.txt @@ -0,0 +1,7 @@ +[console_scripts] +ot-sim-ground-truth-module = otsim.ground_truth.ground_truth:main +ot-sim-io-module = otsim.io.io:main +ot-sim-rpi-gpio-module = otsim.rpi_gpio.rpi_gpio:main +ot-sim-wind-turbine-anemometer-module = otsim.wind_turbine.anemometer.anemometer:main +ot-sim-wind-turbine-power-output-module = otsim.wind_turbine.power_output.power_output:main + diff --git a/src/python/otsim.egg-info/requires.txt b/src/python/otsim.egg-info/requires.txt new file mode 100644 index 0000000..ec00028 --- /dev/null +++ b/src/python/otsim.egg-info/requires.txt @@ -0,0 +1,7 @@ +RPi.GPIO +helics~=3.4.0 +numpy +pandas +pyzmq +requests +windpowerlib diff --git a/src/python/otsim.egg-info/top_level.txt b/src/python/otsim.egg-info/top_level.txt new file mode 100644 index 0000000..84299a1 --- /dev/null +++ b/src/python/otsim.egg-info/top_level.txt @@ -0,0 +1 @@ +otsim