├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LogIt.cmake ├── README.md ├── appveyor.yml ├── boost_appveyor_ci.cmake ├── boost_custom_cc7.cmake ├── boost_custom_win_VS2017.cmake ├── boost_lcg.cmake ├── boost_standard_install_cc7.cmake ├── cmake ├── Open62541CompatFetchContent.cmake └── Open62541CompatFetchContent │ └── CMakeLists.cmake.in ├── doc └── ChangeLog.html ├── examples ├── CMakeLists.txt └── src │ └── ex_simple_client_read.cpp ├── extern └── open62541 │ ├── include │ └── open62541.h │ ├── prepare_open62541.sh │ └── src │ └── open62541.c ├── include ├── array_templates.h ├── arrays.h ├── logit_logger.h ├── managed_uaarray.h ├── methodhandleuanode.h ├── methodmanager.h ├── nodemanagerbase.h ├── opcua_attributes.h ├── opcua_basedatavariabletype.h ├── opcua_baseobjecttype.h ├── opcua_identifiers.h ├── opcua_platformdefs.h ├── opcua_types.h ├── open62541_compat.h ├── open62541_compat_common.h ├── other.h ├── session.h ├── simple_arrays.h ├── stack_fake_structures.h ├── statuscode.h ├── uabasenodes.h ├── uabytestring.h ├── uaclient │ ├── uaclientsdk.h │ └── uasession.h ├── uadatavalue.h ├── uadatavariablecache.h ├── uadatetime.h ├── uaexpandednodeid.h ├── uanode.h ├── uanodeid.h ├── uaplatformlayer.h ├── uaserver.h ├── uastring.h └── uavariant.h ├── src ├── logit_logger.cpp ├── nodemanagerbase.cpp ├── opcua_basedatavariabletype.cpp ├── open62541_compat.cpp ├── statuscode.cpp ├── uabytearray.cpp ├── uabytestring.cpp ├── uaclient │ └── uasession.cpp ├── uadatavalue.cpp ├── uadatavariablecache.cpp ├── uadatetime.cpp ├── uanodeid.cpp ├── uaserver.cpp ├── uastring.cpp └── uavariant.cpp ├── test ├── CMakeLists.txt ├── include │ └── uavariant_test.h └── src │ ├── arrays_test.cpp │ ├── main.cpp │ ├── uabytestring_test.cpp │ ├── uadatavalue_test.cpp │ ├── uadatetime_test.cpp │ ├── uaqualifiedname_test.cpp │ └── uavariant_test.cpp └── xsd └── ServerConfig.xsd /.gitignore: -------------------------------------------------------------------------------- 1 | **/CMakeFiles 2 | **/Makefile 3 | include/open62541.h 4 | src/open62541.c 5 | cmake_install.cmake 6 | LogIt/ 7 | CMakeCache.txt 8 | Release/ 9 | *.vcxproj* 10 | *.sln 11 | x64/ 12 | *.dir/ 13 | .vs/ 14 | prepare.pyc 15 | libopen62541-compat.a 16 | libopen62541-compat.so 17 | Debug/ 18 | test/googletest/ 19 | **/*.swp 20 | **/gtest*.pc 21 | test/open62541-compat-Test 22 | .cproject 23 | .project 24 | .settings/ 25 | build 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | language: cpp 4 | 5 | services: 6 | - docker 7 | 8 | before_install: 9 | - docker pull bfarnham/quasar:quasar-open62541 10 | 11 | script: 12 | - docker run --interactive --tty bfarnham/quasar:quasar-open62541 /bin/sh -c " 13 | echo '********************************************************************' ; 14 | echo branch ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} ; 15 | echo '********************************************************************' ; 16 | git clone -b ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} https://github.com/quasar-team/open62541-compat ; 17 | cd open62541-compat ; 18 | mkdir build ; 19 | cd build ; 20 | cmake -DSTANDALONE_BUILD=ON -DOPEN62541-COMPAT_BUILD_CONFIG_FILE=boost_standard_install_cc7.cmake ../ ; 21 | make ; 22 | ./test/open62541-compat-Test ; 23 | " 24 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # LICENSE: 2 | # Copyright (c) 2016, Piotr Nikiel, CERN 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | # 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 12 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 13 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 14 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 15 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | 17 | # Authors: 18 | # Piotr Nikiel 19 | # Ben Farnham 20 | project(open62541-compat LANGUAGES C CXX) 21 | cmake_minimum_required(VERSION 3.3) 22 | cmake_policy(SET CMP0012 NEW) 23 | cmake_policy(SET CMP0057 NEW) # enables IN_LIST operator 24 | 25 | include (cmake/Open62541CompatFetchContent.cmake) 26 | option(PULL_OPEN62541 "Pull open62541 from their github instead of using the bundled one (not recommended!)" OFF) 27 | 28 | option(STANDALONE_BUILD "Build it as a stand-alone library instead of for Quasar" OFF ) 29 | option(STANDALONE_BUILD_SHARED "When building in stand-alone, build shared library rather than static library" OFF) 30 | option(SKIP_TESTS "do not build the tests (not advised)" OFF) 31 | message(STATUS "STANDALONE_BUILD [${STANDALONE_BUILD}] STANDALONE_BUILD_SHARED [${STANDALONE_BUILD_SHARED}]") 32 | # "OPEN62541_VERSION" will be used only if you use PULL_OPEN62541 33 | SET (OPEN62541_VERSION "v1.0" CACHE STRING "Which open62541 commit/tag/branch to take") 34 | option (UA_ENABLE_AMALGAMATION "Whether open62541 should amalgamate" ON ) 35 | option (UA_ENABLE_METHODCALLS "Whether open62541 should have methods enabled" ON ) 36 | option (SERVERCONFIG_LOADER "Whether we should support ServerConfig.xml loading, resembling UA-SDK" OFF ) 37 | 38 | if(${PULL_OPEN62541}) 39 | function ( fetch_open62541 ) 40 | message(STATUS "fetching open62541 from github. *NOTE* fetching tag [${OPEN62541_VERSION}]") 41 | Open62541CompatFetchContent_Declare( 42 | open62541 43 | GIT_REPOSITORY https://github.com/open62541/open62541.git 44 | GIT_TAG ${OPEN62541_VERSION} 45 | GIT_SHALLOW "1" 46 | SOURCE_DIR ${PROJECT_BINARY_DIR}/open62541 47 | BINARY_DIR ${PROJECT_BINARY_DIR}/open62541 48 | ) 49 | Open62541CompatFetchContent_Populate( open62541 ) 50 | message(STATUS "open62541 fetched") 51 | endfunction() 52 | 53 | function ( build_open62541 ) 54 | message(STATUS "generating platform specific build for open62541 library for [${CMAKE_GENERATOR}]") 55 | add_subdirectory( ${PROJECT_BINARY_DIR}/open62541 56 | ${PROJECT_BINARY_DIR}/open62541 57 | EXCLUDE_FROM_ALL # EXCLUDE_FROM_ALL will not add install() targets from open62541 which we clearly don't want/need 58 | ) 59 | set_target_properties( open62541 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/open62541 ) 60 | endfunction() 61 | 62 | endif(${PULL_OPEN62541}) 63 | 64 | SET( SRCS 65 | src/nodemanagerbase.cpp 66 | src/open62541_compat.cpp 67 | src/uabytestring.cpp 68 | src/uastring.cpp 69 | src/uavariant.cpp 70 | src/uadatavariablecache.cpp 71 | src/statuscode.cpp 72 | src/uanodeid.cpp 73 | src/uadatavalue.cpp 74 | src/uadatetime.cpp 75 | src/uabytearray.cpp 76 | src/opcua_basedatavariabletype.cpp 77 | src/uaserver.cpp 78 | src/logit_logger.cpp 79 | src/uaclient/uasession.cpp 80 | ) 81 | 82 | if(NOT ${PULL_OPEN62541}) # this is the default behaviour 83 | include_directories(extern/open62541/include) 84 | list(APPEND SRCS extern/open62541/src/open62541.c) 85 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUA_ARCHITECTURE_POSIX -Werror -Wall -Wextra -Wpedantic -Wno-static-in-inline -Wno-overlength-strings -Wno-unused-parameter -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wformat -Wformat-security -Wformat-nonliteral -Wuninitialized -Winit-self -Wcast-qual -Wstrict-overflow -Wnested-externs -Wmultichar -Wundef -Wc++-compat -fno-strict-aliasing -fexceptions -fstack-protector-strong -Wno-unused-function -Wshadow -Wconversion -fvisibility=hidden") 86 | endif(NOT ${PULL_OPEN62541}) 87 | 88 | if(${PULL_OPEN62541}) # this is not default 89 | fetch_open62541() 90 | build_open62541() 91 | set(OPEN62541_SDK_LIB -lopen62541) 92 | endif(${PULL_OPEN62541}) 93 | 94 | add_definitions(-DNOMINMAX) # doesn't include windows' min() and max() which break std c++ code. Should be neutral to non-windows code. 95 | 96 | if(SERVERCONFIG_LOADER) 97 | add_custom_command( 98 | OUTPUT ${PROJECT_BINARY_DIR}/ServerConfig.cxx ${PROJECT_BINARY_DIR}/ServerConfig.hxx 99 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 100 | COMMAND xsdcxx cxx-tree --namespace-map http://cern.ch/quasar/ServerConfig=ServerConfig --output-dir ${PROJECT_BINARY_DIR} --std c++11 ${PROJECT_SOURCE_DIR}/xsd/ServerConfig.xsd 101 | DEPENDS xsd/ServerConfig.xsd 102 | ) 103 | include_directories( ${PROJECT_BINARY_DIR} ) 104 | set(SRCS ${SRCS} ${PROJECT_BINARY_DIR}/ServerConfig.cxx) 105 | add_definitions(-DHAS_SERVERCONFIG_LOADER) 106 | endif(SERVERCONFIG_LOADER) 107 | 108 | if(NOT STANDALONE_BUILD) 109 | add_library ( open62541-compat OBJECT ${SRCS} ) 110 | if(${PULL_OPEN62541}) # fetching open62541 (NOT default) 111 | add_custom_target( quasar_opcua_backend_is_ready DEPENDS open62541-compat ) 112 | else(${PULL_OPEN62541}) # using bundled open62541 (default) 113 | add_custom_target( quasar_opcua_backend_is_ready ) # ready anytime basically. 114 | endif(${PULL_OPEN62541}) 115 | 116 | else() 117 | 118 | # We need some C++11 (via cmake platform agnostic flag) 119 | set(CMAKE_CXX_STANDARD 11) 120 | if( NOT WIN32 ) 121 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-literal-suffix" ) # gcc specific flags 122 | endif() 123 | 124 | # 125 | # Decide on open62541-compat build output (shared/static) 126 | # 127 | if (STANDALONE_BUILD_SHARED) 128 | set(OPEN62541_COMPAT_LIB_FORMAT SHARED) 129 | add_definitions(-fPIC) 130 | else() 131 | set(OPEN62541_COMPAT_LIB_FORMAT STATIC) 132 | endif() 133 | 134 | 135 | include_directories( include ) 136 | include_directories( ${PROJECT_BINARY_DIR}/open62541 ) 137 | 138 | # 139 | # Load stand-alone build toolchain file (used for defining build-specific boost (BOOST_LIBS), amongst other things) 140 | # 141 | if(DEFINED OPEN62541-COMPAT_BUILD_CONFIG_FILE) 142 | message("OPEN62541-COMPAT_BUILD_CONFIG_FILE is defined -- including [[${OPEN62541-COMPAT_BUILD_CONFIG_FILE}]]") 143 | include(${OPEN62541-COMPAT_BUILD_CONFIG_FILE}) 144 | endif() 145 | 146 | if( NOT DEFINED BOOST_LIBS) 147 | # try to resolve using find_package 148 | set(Boost_NO_BOOST_CMAKE ON) 149 | find_package(Boost REQUIRED system chrono date_time thread program_options) 150 | if(NOT Boost_FOUND) 151 | message(FATAL_ERROR "Failed to find boost installation. Install it (dev packages), if necessary make sure that BOOST_ROOT is exported, or use a dedicated build config file (some of which are attached to open62541-compat repository, e.g. boost_standard_install_cc7") 152 | else() 153 | message(STATUS "Found system boost, version [${Boost_VERSION}], include dir [${Boost_INCLUDE_DIRS}] library dir [${Boost_LIBRARY_DIRS}], libs [${Boost_LIBRARIES}]") 154 | include_directories( ${Boost_INCLUDE_DIRS} ) 155 | set( BOOST_LIBS ${Boost_LIBRARIES} ) 156 | endif() 157 | endif() 158 | 159 | message(STATUS "Using boost libraries: BOOST_LIBS [${BOOST_LIBS}]") 160 | 161 | include (LogIt.cmake) 162 | 163 | process_LogIt() 164 | message(STATUS "After process_LogIt, LOGIT_TARGET_OBJECTS=${LOGIT_TARGET_OBJECTS}") 165 | 166 | link_directories( 167 | ${PROJECT_BINARY_DIR}/open62541 168 | ${PROJECT_BINARY_DIR}/open62541/build 169 | ${PROJECT_BINARY_DIR}/open62541/Release/ 170 | ${PROJECT_BINARY_DIR}/open62541/Debug/ ) 171 | 172 | add_library( open62541-compat ${OPEN62541_COMPAT_LIB_FORMAT} ${SRCS} ${LOGIT_TARGET_OBJECTS} ) 173 | 174 | # 175 | # Set required libs, note windows build requires winsock. 176 | # 177 | 178 | target_link_libraries( open62541-compat ${BOOST_LIBS} ${OPEN62541_SDK_LIB} ${LOGITLIB}) 179 | 180 | if(WIN32) 181 | target_link_libraries( open62541-compat ws2_32 ) 182 | endif() 183 | 184 | # 185 | # Build unit tests (googletest). For the moment only build unit tests in stand-alone mode 186 | # until such time as the quasar framework has a comprehensive strategy for testing optional 187 | # modules. 188 | # 189 | if( NOT SKIP_TESTS ) 190 | add_subdirectory( ${PROJECT_SOURCE_DIR}/test ) 191 | else() 192 | message( STATUS "explicitly requested not to build unit tests!" ) 193 | endif() 194 | 195 | add_subdirectory(examples) 196 | 197 | endif() 198 | 199 | if(${PULL_OPEN62541}) # this is not default 200 | add_dependencies( open62541-compat open62541 ) 201 | endif(${PULL_OPEN62541}) 202 | 203 | install(TARGETS open62541-compat DESTINATION lib) 204 | install(DIRECTORY include/ DESTINATION include) 205 | if(NOT ${PULL_OPEN62541}) # this is the default behaviour 206 | install(FILES extern/open62541/include/open62541.h DESTINATION include) 207 | endif (NOT ${PULL_OPEN62541}) # this is the default behaviour 208 | -------------------------------------------------------------------------------- /LogIt.cmake: -------------------------------------------------------------------------------- 1 | # LICENSE: 2 | # Copyright (c) 2016, CERN 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | # 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 12 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 13 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 14 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 15 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | # 17 | # Authors: 18 | # Ben Farnham 19 | # Piotr Nikiel 20 | # 21 | # Note: the following code was mostly contributed by Ben, in the master CMakeLists of open62541-compat 22 | # Then moved by Piotr to this file for easier maintenance, further fixes by Piotr 23 | 24 | 25 | function ( fetch_LogIt ) 26 | SET (LOGIT_VERSION "v0.1.1") #change to master post-merge 27 | message(STATUS "fetching LogIt from github. *NOTE* fetching version [${LOGIT_VERSION}]") 28 | Open62541CompatFetchContent_Declare( 29 | LogIt 30 | GIT_REPOSITORY https://github.com/quasar-team/LogIt.git 31 | GIT_TAG ${LOGIT_VERSION} 32 | GIT_SHALLOW "1" 33 | SOURCE_DIR ${PROJECT_BINARY_DIR}/LogIt 34 | BINARY_DIR ${PROJECT_BINARY_DIR}/LogIt 35 | ) 36 | Open62541CompatFetchContent_Populate( LogIt ) 37 | message(STATUS "LogIt fetched from LogIt repo") 38 | endfunction() 39 | 40 | function ( process_LogIt ) 41 | # Parse LOGIT_BUILD_OPTION first as it determines almost any other behaviour that follows 42 | # Possible options: 43 | # - Source --> fetches LogIt into ${PROJECT_BINARY_DIR}/LogIt 44 | # - External shared --> uses existing LogIt, its headers should be in ${LOGIT_INCLUDE_DIR} 45 | # - External static --> uses existing LogIt, its headers should be in ${LOGIT_INCLUDE_DIR} 46 | # If nothing coming from outside, make "LOGIT_AS_INT_SRC" the default 47 | set(LOGIT_BUILD_OPTION "LOGIT_AS_INT_SRC" CACHE STRING "LogIt is a mandatory dependency of open62541-compat. Inclusion options LOGIT_AS_INT_SRC, LOGIT_AS_EXT_SHARED, LOGIT_AS_EXT_STATIC") 48 | set(LOGIT_BUILD_OPTIONS_SUPPORTED "LOGIT_AS_INT_SRC" "LOGIT_AS_EXT_SHARED" "LOGIT_AS_EXT_STATIC") 49 | 50 | if (NOT "${LOGIT_BUILD_OPTION}" IN_LIST LOGIT_BUILD_OPTIONS_SUPPORTED) 51 | message(FATAL_ERROR "Given LOGIT_BUILD_OPTION [${LOGIT_BUILD_OPTION}] is not supported. It must be one of: ${LOGIT_BUILD_OPTIONS_SUPPORTED}") 52 | endif() 53 | 54 | 55 | set_property(CACHE LOGIT_BUILD_OPTION PROPERTY STRINGS LOGIT_AS_INT_SRC LOGIT_AS_EXT_SHARED LOGIT_AS_EXT_STATIC) 56 | message(STATUS "LogIt build option LOGIT_BUILD_OPTION [${LOGIT_BUILD_OPTION}]") 57 | 58 | # 59 | # Fetch LogIt if needed 60 | # 61 | if("${LOGIT_BUILD_OPTION}" STREQUAL "LOGIT_AS_INT_SRC") 62 | fetch_LogIt() 63 | endif() 64 | 65 | # 66 | # Resolve LogIt include 67 | # 68 | set(LOGIT_INCLUDE_DIR ${PROJECT_BINARY_DIR}/LogIt/include CACHE PATH "Path to LogIt include directory. If building with LogIt as external shared/static library this must be specified using -DLOGIT_INCLUDE_DIR=path. Path can be absolute or relative to [${PROJECT_BINARY_DIR}/]") 69 | if( NOT EXISTS ${LOGIT_INCLUDE_DIR} ) 70 | message(FATAL_ERROR "Cannot build with LogIt. No LogIt include directory found at [${LOGIT_INCLUDE_DIR}]. If building with LogIt as external shared/static library this must be specified using -DLOGIT_INCLUDE_DIR=path. Path can be absolute or relative to [${PROJECT_BINARY_DIR}/]") 71 | endif() 72 | message(STATUS "Using LogIt include directory [${LOGIT_INCLUDE_DIR}]") 73 | include_directories( ${LOGIT_INCLUDE_DIR} ) 74 | 75 | # 76 | # Resolve LogIt library 77 | # 78 | set(LOGIT_EXT_LIB_DIR "UNINIALIZED" CACHE PATH "Path to the directory containing the LogIt shared/static library binary file. Use absolute path, or relative to [${PROJECT_BINARY_DIR}/]") 79 | message(STATUS "Using LogIt build option [${LOGIT_BUILD_OPTION}]") 80 | if("${LOGIT_BUILD_OPTION}" STREQUAL "LOGIT_AS_INT_SRC") 81 | add_subdirectory( ${PROJECT_BINARY_DIR}/LogIt ${PROJECT_BINARY_DIR}/LogIt ) 82 | set(LOGIT_TARGET_OBJECTS $ PARENT_SCOPE) 83 | message(STATUS "LogIt added as compiled object code from sub-directory LogIt") 84 | else() 85 | if("${LOGIT_BUILD_OPTION}" STREQUAL "LOGIT_AS_EXT_SHARED") 86 | SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".lib") # windows looks for lib file to link to target dll: lib contains dll exports, symbols etc (see LogIt.h SHARED_LIB_EXPORT_DEFN) 87 | find_library( LOGITLIB NAMES LogIt PATHS ${LOGIT_EXT_LIB_DIR} NO_DEFAULT_PATH ) 88 | elseif("${LOGIT_BUILD_OPTION}" STREQUAL "LOGIT_AS_EXT_STATIC") 89 | SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib") 90 | find_library( LOGITLIB NAMES LogIt PATHS ${LOGIT_EXT_LIB_DIR} NO_DEFAULT_PATH ) 91 | else() 92 | message(FATAL_ERROR "Invalid command given as to how to use LogIt in the open62541-compat library, see documentaton for property [LOGIT_BUILD_OPTION]") 93 | endif() 94 | if ( LOGITLIB STREQUAL "LOGITLIB-NOTFOUND") 95 | message(FATAL_ERROR "LogIt library (.a/.so/.dll) hasn't been found. Please set the variable LOGIT_EXT_LIB_DIR accordingly.") 96 | endif () 97 | message(STATUS "LogIt added as external library dependency LOGITLIB [${LOGITLIB}]") 98 | endif() 99 | 100 | 101 | endfunction() 102 | 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # open62541-compat 2 | Adapts open62541 API to UA Toolkit API for usage in (1)Quasar-based projects, (2) independent UASDK-based projects 3 | 4 | For bugs or suggestions please file a GitHub ticket. 5 | 6 | Versions 7 | -------- 8 | 9 | | Branch/Version | open62541 version included | LogIt version | Years active | Description | 10 | | -------------- | ----------------- | ------------- | --- | ----------- | 11 | | 1.4.x | 1.2.x | v0.1.1 | 2021- | Stable, widely used. | 12 | | 1.3.x | 1.1.x | v0.1.1 | 2020-2021 |Old-stable. | 13 | | 1.2.x | 1.0.x | v0.1.1 | 2019-2020 | Historic. Uses open62541 1.0. | 14 | | 1.1 | 0.3(-rc2) | v0.1.1 | 2018-2019 | Historic. Uses open62541 0.3. | 15 | | 1.0 | 0.2 rc2 | "master" | 2018 | Prehistoric. Significantly improved CMake scripting etc. Usable in Yocto and PetaLinux. | 16 | | 0.9 | 0.2 rc2 | "master" | 2015-2018 | Prehistoric. Will stay cmake2.8 compatible. OK for native Linux and Win. Not useful for Yocto or PetaLinux. | 17 | 18 | 19 | 20 | 21 | Quick-start guide in Quasar 22 | --------------------------- 23 | The procedure is documented in Quasar project. 24 | In Quasar repo, read: 25 | 26 | Documentation/AlternativeBackends.html 27 | 28 | Quick-start guide to get an stand-alone(independent) library 29 | ----------------------------------------------------------- 30 | 1. clone the repo 31 | 32 | 2. generate the makefiles / VS solution using cmake. A few options here, depending on 33 | 34 | (a) do you want to build open62541-compat as a shared or static library? 35 | 36 | (b) open62541-compat requires the boost library, do you want to use the system boost library or do you have a custom boost build? 37 | 38 | (c) open62541-compat depends on the quasar module LogIt, should the compat module clone, build and link LogIt source directly into 39 | the compat library or should the compat library consume LogIt from some external build. 40 | 41 | Time for an example... 42 | 43 | ### Linux examples 44 | - Build open62541-compat as a static library on linux. Use whatever the system installation of boost-devel is and build LogIt 45 | directly into the compat library 46 | ``` 47 | cmake -DOPEN62541-COMPAT_BUILD_CONFIG_FILE=boost_standard_install_cc7.cmake -DSTANDALONE_BUILD=ON 48 | ``` 49 | 50 | - Build open62541-compat as a **shared** library on linux (and boost/LogIt treated as above) - just add **STANDALONE_BUILD_SHARED** 51 | ``` 52 | cmake -DOPEN62541-COMPAT_BUILD_CONFIG_FILE=boost_standard_install_cc7.cmake -DSTANDALONE_BUILD=ON -DSTANDALONE_BUILD_SHARED=ON 53 | ``` 54 | 55 | - Build open62541-compat as a shared library on linux but with the LogIt library pulled in from some external build location (here LogIt is consumed as a shared library from /tmp/LogIt/). Note the **-DLOGIT** options define how LogIt is built into open62541-compat. 56 | ``` 57 | cmake -DOPEN62541-COMPAT_BUILD_CONFIG_FILE=boost_standard_install_cc7.cmake -DSTANDALONE_BUILD=ON -DSTANDALONE_BUILD_SHARED=ON -DLOGIT_BUILD_OPTION=LOGIT_AS_EXT_SHARED -DLOGIT_EXT_LIB_DIR=/tmp/LogIt/ -DLOGIT_INCLUDE_DIR=/tmp/LogIt/include/ 58 | ``` 59 | ### Windows examples (using a mingw 'git bash' command prompt) 60 | - Build open62541-compat as a static library on windows (visual studio 2017). Use a custom boost build (perhaps you built boost 61 | yourself, or have several boost installations available to choose from). Build LogIt directly into the compat library. 62 | ``` 63 | # (comment) - set environment variables to point to the custom boost headers/libs directories (required by the toolchain file) 64 | export BOOST_PATH_HEADERS=/c/3rdPartySoftware/boost_mapped_namespace_builder/work/MAPPED_NAMESPACE_INSTALL/include/ 65 | export BOOST_PATH_LIBS=/c/3rdPartySoftware/boost_mapped_namespace_builder/work/MAPPED_NAMESPACE_INSTALL/lib/ 66 | 67 | cmake -DOPEN62541-COMPAT_BUILD_CONFIG_FILE=boost_custom_win_VS2017.cmake -DSTANDALONE_BUILD=ON -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release 68 | ``` 69 | Note! Your boost build/installation may be more exotic than ours, take a look at the sample custom toolchain file (__boost_custom_win_VS2017.cmake__) 70 | for inspiration, write your own and use it in your build via the build option **OPEN62541-COMPAT_BUILD_CONFIG_FILE** 71 | 72 | - Build open62541-compat as a shared library on windows (visual studio 2017). Use a custom boost build. Use the LogIt library (here as a shared library) from some external build (as with the linux build above, the **-DLOGIT** options define how LogIt is built into open62541-compat). 73 | ``` 74 | # (comment) - set environment variables to point to the custom boost headers/libs directories (required by the toolchain file) 75 | export BOOST_PATH_HEADERS=/c/3rdPartySoftware/boost_mapped_namespace_builder/work/MAPPED_NAMESPACE_INSTALL/include/ 76 | export BOOST_PATH_LIBS=/c/3rdPartySoftware/boost_mapped_namespace_builder/work/MAPPED_NAMESPACE_INSTALL/lib/ 77 | 78 | cmake -DOPEN62541-COMPAT_BUILD_CONFIG_FILE=boost_custom_win_VS2017.cmake -DSTANDALONE_BUILD=ON -DSTANDALONE_BUILD_SHARED=ON -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release -DLOGIT_BUILD_OPTION=LOGIT_AS_EXT_SHARED -DLOGIT_EXT_LIB_DIR=/c/workspace/OPC-UA/LogIt/Release/ -DLOGIT_INCLUDE_DIR=/c/workspace/OPC-UA/LogIt/include/ 79 | ``` 80 | 81 | ### Unit tests 82 | Writing unit tests (and running unit tests) is a good habit; developers - if you're adding new features we recommend adding tests to really lock that work in place. Passing tests signify that features work now and provide an invaluable tool for future developers; to help them avoid inadvertently broken existing functionality. So, be a conscientious developer, write tests and run tests. By default (for stand-alone open62541-compat builds) unit tests are part of the build, if you need to skip them you can (but why would you?), more on skipping tests later. The open62541-compat module unit tests are based on the [googletest](https://github.com/google/googletest) framework. Note that the unit tests build to a stand-alone executable, this executable links to the stand-alone open62541-compat library as used in end-user applications - building the unit tests has ZERO effect on the actual end-user library binary that the build outputs. 83 | * Unit tests and their requirements (basically googletest) are in the test subdirectory. 84 | * New unit tests should be added to test/src (for help on writing tests see the googletest documentation, you might find inspiration in the existing tests too). 85 | * From a clean start, the googletest framework is built from source (cloned from [here](https://github.com/google/googletest)), so it should execute on your platform. 86 | * On running make for the open62541-compat module, the unit tests build to this executable: __test/open62541-compat-Test__. Note that executable is built after the open62541-compat library is built. 87 | * Run those tests by simply invoking that executable: 88 | ``` 89 | ./test/open62541-compat-Test 90 | ``` 91 | 92 | #### Skipping tests 93 | If, for some reason, you feel you must omit unit tests from the build then there is a way, just add __-DSKIP_TESTS=ON__ to your cmake invocation command line. Taking the example of the stand-alone static library build on linux above the command line would be 94 | ``` 95 | cmake -DOPEN62541-COMPAT_BUILD_CONFIG_FILE=boost_standard_install_cc7.cmake -DSTANDALONE_BUILD=ON -DSKIP_TESTS=ON 96 | ``` 97 | (and feel guilty.) 98 | 99 | ###### How do you use it in your independent UASDK server or client? ###### 100 | 101 | The include directory contains UASDK-(partially)-compatible headers, and you should link with the following libs: 102 | * build/libopen62541-compat.a 103 | * open62541/build/libopen62541.a 104 | 105 | For questions/issues: file a ticket or write to piotr.nikiel@cern.ch 106 | 107 | CI build info | CI build status 108 | ------------ | ------------- 109 | linux (travis-ci) | [![travis-ci](https://travis-ci.org/quasar-team/open62541-compat.svg?branch=master)](https://travis-ci.org/quasar-team/open62541-compat?branch=master) 110 | windows (appveyor) | [![Appveyor](https://ci.appveyor.com/api/projects/status/etdf9t9wkkeb7jpi/branch/master?svg=true)](https://ci.appveyor.com/project/ben-farnham/open62541-compat/branch/master) 111 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # version format 2 | version: 1.0.{build} 3 | image: Visual Studio 2017 4 | build: 5 | verbosity: normal 6 | notifications: 7 | - provider: Email 8 | to: 9 | - quasar-developers@cern.ch 10 | subject: open62541 windows build status changed 11 | on_build_success: false 12 | on_build_failure: false 13 | on_build_status_changed: true 14 | 15 | 16 | environment: 17 | WINDOWS_DEPENDENCIES_DIR: C:\workspace\OPC-UA\quasar-windows-dependencies 18 | BOOST_PATH_HEADERS: $(WINDOWS_DEPENDENCIES_DIR)\boost\lib\native\include 19 | BOOST_PATH_LIBS: $(WINDOWS_DEPENDENCIES_DIR) 20 | # 21 | # Set environment variables in powershell using command 22 | # [System.Environment]::SetEnvironmentVariable("VAR", "C:/target/path", "Machine")') 23 | # 24 | 25 | install: 26 | # delete and recreate clean directory for windows dependencies. 27 | - ps : | 28 | Write-Output "Cleaning and recreating windows dependencies dir: ${env:WINDOWS_DEPENDENCIES_DIR}" 29 | if(Test-Path "${env:WINDOWS_DEPENDENCIES_DIR}") 30 | { 31 | Remove-Item "${env:WINDOWS_DEPENDENCIES_DIR}" -Force -Recurse; 32 | } 33 | New-Item -ItemType Directory -Force -Path "${env:WINDOWS_DEPENDENCIES_DIR}" 34 | 35 | # nuget: package manager for installing libs 36 | - ps : Write-Output "Installing nuget packages to ${env:WINDOWS_DEPENDENCIES_DIR}" 37 | - ps : nuget install boost-vc141 -Version 1.67.0 -NonInteractive -ExcludeVersion -OutputDirectory "${env:WINDOWS_DEPENDENCIES_DIR}" 38 | - ps : Write-Output "Installed nuget packages to ${env:WINDOWS_DEPENDENCIES_DIR}" 39 | 40 | build_script: 41 | - ps : mkdir ..\open62541-compat-debug-build ; cd ..\open62541-compat-debug-build 42 | - cmd : cmake ..\open62541-compat\ -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release -DSTANDALONE_BUILD=ON -DOPEN62541-COMPAT_BUILD_CONFIG_FILE="boost_appveyor_ci.cmake" 43 | - cmd : cmake --build %cd% --config Release 44 | 45 | test_script: 46 | - ps : .\test\Release\open62541-compat-Test.exe 47 | 48 | # uncomment to block VM deletion for investigating broken builds. 49 | #on_finish: 50 | # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) 51 | 52 | -------------------------------------------------------------------------------- /boost_appveyor_ci.cmake: -------------------------------------------------------------------------------- 1 | # LICENSE: 2 | # Copyright (c) 2015, CERN 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | # 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 12 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 13 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 14 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 15 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | # 17 | # @author Ben Farnham 18 | # @date 06-Dec-2019 19 | # The purpose of this file is to locate boost for an appveyor (windows) continuous integration build 20 | 21 | #------- 22 | #Boost 23 | #------- 24 | message(STATUS "starting the quest for boost, relevant environment variables: BOOST_PATH_HEADERS [$ENV{BOOST_PATH_HEADERS}] BOOST_PATH_LIBS [$ENV{BOOST_PATH_LIBS}] BOOST_HOME [$ENV{BOOST_HOME}]") 25 | 26 | # headers path 27 | if(DEFINED ENV{BOOST_PATH_HEADERS}) 28 | SET( BOOST_PATH_HEADERS $ENV{BOOST_PATH_HEADERS} ) 29 | message(STATUS "using BOOST_PATH_HEADERS from environment BOOST_PATH_HEADERS [${BOOST_PATH_HEADERS}]") 30 | else() 31 | if( DEFINED ENV{BOOST_HOME} ) 32 | SET( BOOST_PATH_HEADERS $ENV{BOOST_HOME}/include ) 33 | message(STATUS "using BOOST_PATH_HEADERS from environment BOOST_HOME [$BOOST_HOME] -> BOOST_PATH_HEADERS [${BOOST_PATH_HEADERS}]") 34 | endif() 35 | endif() 36 | 37 | # libs path 38 | if(DEFINED ENV{BOOST_PATH_LIBS}) 39 | SET( BOOST_PATH_LIBS $ENV{BOOST_PATH_LIBS} ) 40 | message(STATUS "using BOOST_PATH_LIBS from environment BOOST_PATH_LIBS [${BOOST_PATH_LIBS}]") 41 | else() 42 | if( DEFINED ENV{BOOST_HOME} ) 43 | SET( BOOST_PATH_LIBS $ENV{BOOST_HOME}/lib ) 44 | message(STATUS "using BOOST_PATH_LIBS from environment BOOST_HOME [${BOOST_HOME}] -> BOOST_PATH_LIBS [${BOOST_PATH_LIBS}]") 45 | endif() 46 | endif() 47 | 48 | # final check 49 | if( NOT BOOST_PATH_HEADERS OR NOT BOOST_PATH_LIBS ) 50 | message( FATAL_ERROR "unable to determine boost headers and library paths from environment variables BOOST_PATH_HEADERS [$ENV{BOOST_PATH_HEADERS}] BOOST_PATH_LIBS [$ENV{BOOST_PATH_LIBS}] BOOST_HOME [$ENV{BOOST_HOME}]") 51 | endif() 52 | 53 | message(STATUS "BOOST - include [${BOOST_PATH_HEADERS}] libs [${BOOST_PATH_LIBS}]") 54 | include_directories( ${BOOST_PATH_HEADERS} ) 55 | 56 | if(NOT TARGET libboostprogramoptions) 57 | add_library(libboostprogramoptions STATIC IMPORTED) 58 | #libboost_program_options-vc141-mt-gd-x64-1_67.lib 59 | set_property(TARGET libboostprogramoptions PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_program_options-vc141/lib/native/libboost_program_options-vc141-mt-x64-1_67.lib) 60 | endif() 61 | if(NOT TARGET libboostsystem) 62 | add_library(libboostsystem STATIC IMPORTED) 63 | set_property(TARGET libboostsystem PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_system-vc141/lib/native/libboost_system-vc141-mt-x64-1_67.lib) 64 | endif() 65 | if(NOT TARGET libboostfilesystem) 66 | add_library(libboostfilesystem STATIC IMPORTED) 67 | set_property(TARGET libboostfilesystem PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_filesystem-vc141/lib/native/libboost_filesystem-vc141-mt-x64-1_67.lib) 68 | endif() 69 | if(NOT TARGET libboostchrono) 70 | add_library(libboostchrono STATIC IMPORTED) 71 | set_property(TARGET libboostchrono PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_chrono-vc141/lib/native/libboost_chrono-vc141-mt-x64-1_67.lib) 72 | endif() 73 | if(NOT TARGET libboostdatetime) 74 | add_library(libboostdatetime STATIC IMPORTED) 75 | set_property(TARGET libboostdatetime PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_date_time-vc141/lib/native/libboost_date_time-vc141-mt-x64-1_67.lib) 76 | endif() 77 | if(NOT TARGET libboostthread) 78 | add_library(libboostthread STATIC IMPORTED) 79 | set_property(TARGET libboostthread PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_thread-vc141/lib/native/libboost_thread-vc141-mt-x64-1_67.lib) 80 | endif() 81 | if(NOT TARGET libboostlog) 82 | add_library(libboostlog STATIC IMPORTED) 83 | set_property(TARGET libboostlog PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_log-vc141/lib/native/libboost_log-vc141-mt-x64-1_67.lib) 84 | endif() 85 | if(NOT TARGET libboostlogsetup) 86 | add_library(libboostlogsetup STATIC IMPORTED) 87 | set_property(TARGET libboostlogsetup PROPERTY IMPORTED_LOCATION ${BOOST_PATH_LIBS}/boost_log_setup-vc141/lib/native/libboost_log_setup-vc141-mt-x64-1_67.lib) 88 | endif() 89 | 90 | set( BOOST_LIBS libboostlogsetup libboostlog libboostsystem libboostfilesystem libboostthread libboostprogramoptions libboostchrono libboostdatetime -lrt) 91 | message( STATUS "BOOST_LIBS - [${BOOST_LIBS}]" ) 92 | 93 | -------------------------------------------------------------------------------- /boost_custom_cc7.cmake: -------------------------------------------------------------------------------- 1 | # LICENSE: 2 | # Copyright (c) 2018, Ben Farnham, CERN 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | # 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 12 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 13 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 14 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 15 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | 17 | # Authors: 18 | # Ben Farnham 19 | message(STATUS "Using file [boost_custom_cc7.cmake] toolchain file") 20 | 21 | message(STATUS "environment vars: BOOST_HOME [$ENV{BOOST_HOME}] UNIFIED_AUTOMATION_HOME [$ENV{UNIFIED_AUTOMATION_HOME}]") 22 | message(STATUS "Boost - include environment variable BOOST_PATH_HEADERS [$ENV{BOOST_PATH_HEADERS}] libs environment variable BOOST_PATH_LIBS [$ENV{BOOST_PATH_LIBS}]") 23 | 24 | #------- 25 | # Boost headers 26 | #------- 27 | if( NOT DEFINED ENV{BOOST_PATH_HEADERS} OR NOT EXISTS $ENV{BOOST_PATH_HEADERS} ) 28 | message(FATAL_ERROR "environment variable BOOST_PATH_HEADERS must be set to a valid path for boost header files. Current value [$ENV{BOOST_PATH_HEADERS}] rejected") 29 | endif() 30 | message(STATUS "Boost - headers will be included from [$ENV{BOOST_PATH_HEADERS}]") 31 | include_directories( $ENV{BOOST_PATH_HEADERS} ) 32 | 33 | 34 | #------- 35 | # Boost compiled libs 36 | #------- 37 | if( NOT DEFINED ENV{BOOST_PATH_LIBS} OR NOT EXISTS $ENV{BOOST_PATH_LIBS} ) 38 | message(FATAL_ERROR "environment variable BOOST_PATH_LIBS must be set to a valid path for boost compiled libraries. Current value [$ENV{BOOST_PATH_LIBS}] rejected") 39 | endif() 40 | message(STATUS "Boost - libraries will be linked from [$ENV{BOOST_PATH_LIBS}]") 41 | 42 | function( find_boost_static_library LIBRARY_IDENTIFIER LIBRARY_FILE_NAME) 43 | SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 44 | SET(CMAKE_FIND_LIBRARY_PREFIXES "") 45 | 46 | find_library(${LIBRARY_IDENTIFIER} NAMES ${LIBRARY_FILE_NAME} PATHS $ENV{BOOST_PATH_LIBS} NO_DEFAULT_PATH) 47 | message(STATUS "${LIBRARY_IDENTIFIER} has value [${${LIBRARY_IDENTIFIER}}]") 48 | if(NOT ${LIBRARY_IDENTIFIER}) 49 | message(FATAL_ERROR "Failed to load boost static library ID [${LIBRARY_IDENTIFIER}] file [${LIBRARY_FILE_NAME}]") 50 | endif() 51 | message(STATUS "loaded boost static library [${LIBRARY_IDENTIFIER}] -> file [${${LIBRARY_IDENTIFIER}}]") 52 | endfunction() 53 | 54 | find_boost_static_library( libboostprogramoptions libboost_1_59_0_program_options ) 55 | find_boost_static_library( libboostsystem libboost_1_59_0_system ) 56 | find_boost_static_library( libboostfilesystem libboost_1_59_0_filesystem ) 57 | find_boost_static_library( libboostchrono libboost_1_59_0_chrono ) 58 | find_boost_static_library( libboostdatetime libboost_1_59_0_date_time) 59 | find_boost_static_library( libboostthread libboost_1_59_0_thread) 60 | find_boost_static_library( libboostlog libboost_1_59_0_log) 61 | find_boost_static_library( libboostlogsetup libboost_1_59_0_log_setup) 62 | 63 | set( BOOST_LIBS ${libboostlogsetup} ${libboostlog} ${libboostsystem} ${libboostfilesystem} ${libboostthread} ${libboostprogramoptions} ${libboostchrono} ${libboostdatetime} -lrt) 64 | -------------------------------------------------------------------------------- /boost_custom_win_VS2017.cmake: -------------------------------------------------------------------------------- 1 | # LICENSE: 2 | # Copyright (c) 2018, Ben Farnham, CERN 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | # 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 12 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 13 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 14 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 15 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | 17 | # Authors: 18 | # Ben Farnham 19 | message(STATUS "Using file [boost_custom_win_VS2017.cmake] toolchain file") 20 | message(STATUS "Boost - include environment variable BOOST_PATH_HEADERS [$ENV{BOOST_PATH_HEADERS}] libs environment variable BOOST_PATH_LIBS [$ENV{BOOST_PATH_LIBS}]") 21 | 22 | #------- 23 | # Boost headers 24 | #------- 25 | if( NOT DEFINED ENV{BOOST_PATH_HEADERS} OR NOT EXISTS $ENV{BOOST_PATH_HEADERS} ) 26 | message(FATAL_ERROR "environment variable BOOST_PATH_HEADERS must be set to a valid path for boost header files. Current value [$ENV{BOOST_PATH_HEADERS}] rejected") 27 | endif() 28 | message(STATUS "Boost - headers will be included from [$ENV{BOOST_PATH_HEADERS}]") 29 | include_directories( $ENV{BOOST_PATH_HEADERS} ) 30 | 31 | 32 | #------- 33 | # Boost compiled libs 34 | #------- 35 | if( NOT DEFINED ENV{BOOST_PATH_LIBS} OR NOT EXISTS $ENV{BOOST_PATH_LIBS} ) 36 | message(FATAL_ERROR "environment variable BOOST_PATH_LIBS must be set to a valid path for boost compiled libraries. Current value [$ENV{BOOST_PATH_LIBS}] rejected") 37 | endif() 38 | message(STATUS "Boost - libraries will be linked from [$ENV{BOOST_PATH_LIBS}]") 39 | 40 | function( find_boost_static_library LIBRARY_IDENTIFIER LIBRARY_FILE_NAME) 41 | SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib") 42 | SET(CMAKE_FIND_LIBRARY_PREFIXES "") 43 | 44 | find_library(${LIBRARY_IDENTIFIER} NAMES ${LIBRARY_FILE_NAME} PATHS $ENV{BOOST_PATH_LIBS} NO_DEFAULT_PATH) 45 | message(STATUS "${LIBRARY_IDENTIFIER} has value [${${LIBRARY_IDENTIFIER}}]") 46 | if(NOT ${LIBRARY_IDENTIFIER}) 47 | message(FATAL_ERROR "Failed to load boost static library ID [${LIBRARY_IDENTIFIER}] file [${LIBRARY_FILE_NAME}]") 48 | endif() 49 | message(STATUS "loaded boost static library [${LIBRARY_IDENTIFIER}] -> file [${${LIBRARY_IDENTIFIER}}]") 50 | endfunction() 51 | 52 | if(${CMAKE_BUILD_TYPE} MATCHES Debug) 53 | set ( BOOST_DEBUG_LIB_MARKER "-gd" ) 54 | endif() 55 | 56 | find_boost_static_library( libboostprogramoptions libboost_1_68_0_program_options-vc141-mt-x64-1_68 ) 57 | find_boost_static_library( libboostsystem libboost_1_68_0_system-vc141-mt${BOOST_DEBUG_LIB_MARKER}-x64-1_68 ) 58 | find_boost_static_library( libboostfilesystem libboost_1_68_0_filesystem-vc141-mt${BOOST_DEBUG_LIB_MARKER}-x64-1_68 ) 59 | find_boost_static_library( libboostchrono libboost_1_68_0_chrono-vc141-mt${BOOST_DEBUG_LIB_MARKER}-x64-1_68 ) 60 | find_boost_static_library( libboostdatetime libboost_1_68_0_date_time-vc141-mt${BOOST_DEBUG_LIB_MARKER}-x64-1_68 ) 61 | find_boost_static_library( libboostthread libboost_1_68_0_thread-vc141-mt${BOOST_DEBUG_LIB_MARKER}-x64-1_68 ) 62 | find_boost_static_library( libboostlog libboost_1_68_0_log-vc141-mt${BOOST_DEBUG_LIB_MARKER}-x64-1_68 ) 63 | find_boost_static_library( libboostlogsetup libboost_1_68_0_log_setup-vc141-mt${BOOST_DEBUG_LIB_MARKER}-x64-1_68 ) 64 | 65 | set( BOOST_LIBS ${libboostlogsetup} ${libboostlog} ${libboostsystem} ${libboostfilesystem} ${libboostthread} ${libboostprogramoptions} ${libboostchrono} ${libboostdatetime}) 66 | -------------------------------------------------------------------------------- /boost_lcg.cmake: -------------------------------------------------------------------------------- 1 | message(STATUS "Using file [boost_lcg.cmake] file") 2 | 3 | # Disabling the search for boost-cmake to use FindBoost instead. 4 | # That is a workaround for boost-1.7.0 cmake config modules. 5 | set(Boost_NO_BOOST_CMAKE ON) 6 | 7 | find_package(Boost REQUIRED program_options system filesystem chrono date_time thread) 8 | if(NOT Boost_FOUND) 9 | message(FATAL_ERROR "Failed to find boost installation") 10 | else() 11 | message(STATUS "Found system boost, version [${Boost_VERSION}], include dir [${Boost_INCLUDE_DIRS}] library dir [${Boost_LIBRARY_DIRS}], libs [${Boost_LIBRARIES}]") 12 | include_directories( ${Boost_INCLUDE_DIRS} ) 13 | set( BOOST_LIBS ${Boost_LIBRARIES} ) 14 | endif() 15 | -------------------------------------------------------------------------------- /boost_standard_install_cc7.cmake: -------------------------------------------------------------------------------- 1 | # LICENSE: 2 | # Copyright (c) 2018, Ben Farnham, CERN 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | # 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | # 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 12 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 13 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 14 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 15 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | 17 | # Authors: 18 | # Ben Farnham 19 | cmake_minimum_required( VERSION 2.8 ) 20 | #project( FindSystemBoost CXX ) 21 | message(STATUS "Using file [boost_standard_install_cc7.cmake] toolchain file") 22 | 23 | message(STATUS "CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES [${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}]") 24 | 25 | # 26 | # Warning: *Distinctly* suspect that these should require be set but otherwise 27 | # no boost libs are found. Possibly fixed in some later version, but not in 28 | # cmake v2.8's FindBoost package 29 | # 30 | set(BOOST_INCLUDEDIR "/usr/include/") 31 | set(BOOST_LIBRARYDIR "/usr/lib64/") 32 | 33 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".so") 34 | set(CMAKE_FIND_LIBRARY_PREFIXES "lib") 35 | 36 | find_package(Boost REQUIRED 37 | program_options system filesystem chrono date_time thread) 38 | 39 | if(NOT Boost_FOUND) 40 | message(FATAL_ERROR "Failed to find system boost installation (is the boost-devel package installed on this machine?)") 41 | else() 42 | message(STATUS "Found system boost, version [${Boost_VERSION}], include dir [${Boost_INCLUDE_DIRS}] library dir [${Boost_LIBRARY_DIRS}], libs [${Boost_LIBRARIES}]") 43 | endif() 44 | 45 | include_directories( ${Boost_INCLUDE_DIRS} ) 46 | set( BOOST_LIBS ${Boost_LIBRARIES} ) 47 | -------------------------------------------------------------------------------- /cmake/Open62541CompatFetchContent/CMakeLists.cmake.in: -------------------------------------------------------------------------------- 1 | # Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 | # file Copyright.txt or https://cmake.org/licensing for details. 3 | 4 | cmake_minimum_required(VERSION ${CMAKE_VERSION}) 5 | 6 | # We name the project and the target for the ExternalProject_Add() call 7 | # to something that will highlight to the user what we are working on if 8 | # something goes wrong and an error message is produced. 9 | 10 | project(${contentName}-populate NONE) 11 | 12 | include(ExternalProject) 13 | ExternalProject_Add(${contentName}-populate 14 | ${ARG_EXTRA} 15 | SOURCE_DIR "${ARG_SOURCE_DIR}" 16 | BINARY_DIR "${ARG_BINARY_DIR}" 17 | CONFIGURE_COMMAND "" 18 | BUILD_COMMAND "" 19 | INSTALL_COMMAND "" 20 | TEST_COMMAND "" 21 | ) 22 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(ex_simple_client_read src/ex_simple_client_read.cpp) 2 | target_link_libraries (ex_simple_client_read 3 | ${BOOST_LIBS} 4 | open62541-compat 5 | 6 | ) -------------------------------------------------------------------------------- /examples/src/ex_simple_client_read.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | using namespace boost::program_options; 9 | 10 | struct Args 11 | { 12 | std::string endpointUrl; 13 | std::string variableAddress; 14 | Log::LOG_LEVEL logLevel; 15 | }; 16 | 17 | Args parseArgs (int argc, char* argv[]) 18 | { 19 | Args args; 20 | 21 | options_description options; 22 | 23 | std::string logLevelAsStr; 24 | 25 | options.add_options() 26 | ("help,h", "show help") 27 | ("endpoint,e", value(&args.endpointUrl)->default_value("opc.tcp://127.0.0.1:4841"), "OPC-UA Endpoint, e.g. opc.tcp://127.0.0.1:48020" ) 28 | ("address,a", value(&args.variableAddress)->default_value("object1.state"), "string address of the var in NS2") 29 | ("trace_level,t", value(&logLevelAsStr)->default_value("INF"), "Trace level, one of: ERR,WRN,INF,DBG,TRC") 30 | ; 31 | 32 | variables_map vm; 33 | store( parse_command_line (argc, argv, options), vm ); 34 | notify (vm); 35 | if (vm.count("help")) 36 | { 37 | std::cout << options << std::endl; 38 | exit(0); 39 | } 40 | if (! Log::logLevelFromString( logLevelAsStr, args.logLevel ) ) 41 | { 42 | std::cout << "Log level not recognized: '" << logLevelAsStr << "'" << std::endl; 43 | exit(1); 44 | } 45 | return args; 46 | } 47 | 48 | int main(int argc, char* argv[]) 49 | { 50 | Args args (parseArgs(argc, argv)); 51 | 52 | Log::initializeLogging(args.logLevel); 53 | Log::registerLoggingComponent("open62541", args.logLevel); 54 | 55 | try 56 | { 57 | UaClientSdk::UaSession session; 58 | 59 | UaClientSdk::SessionConnectInfo sessionConnectInfo; 60 | sessionConnectInfo.sApplicationName = "client@myComputer"; 61 | sessionConnectInfo.sApplicationUri = "client@myComputer"; 62 | sessionConnectInfo.sProductUri = "client"; 63 | 64 | UaClientSdk::SessionSecurityInfo security; 65 | 66 | session.connect( 67 | args.endpointUrl.c_str(), 68 | sessionConnectInfo, 69 | security, 70 | nullptr /* no cbk */ ); 71 | 72 | ServiceSettings defaultServiceSettings; 73 | 74 | UaReadValueIds ids; 75 | ids.create(1); 76 | ids[0].AttributeId = OpcUa_Attributes_Value; 77 | 78 | UaNodeId varNodeId (args.variableAddress.c_str(), 2); 79 | varNodeId.copyTo(&ids[0].NodeId); 80 | 81 | UaDataValues output; 82 | output.create(1); 83 | 84 | UaDiagnosticInfos diagnosticInfos; 85 | 86 | UaStatus status = session.read(defaultServiceSettings, 0 /*max age*/, OpcUa_TimestampsToReturn_Both, ids, output, diagnosticInfos ); 87 | std::cout << "Status of service call was: " << status.toString().toUtf8() << std::endl; 88 | if (status.isGood()) 89 | { 90 | std::cout << "Value read status was: " << output[0].StatusCode.toString().toUtf8() << std::endl; 91 | std::cout << "Value read was: " << output[0].Value.toString().toUtf8() << std::endl; 92 | } 93 | 94 | 95 | } 96 | catch (const std::exception &e) 97 | { 98 | LOG(Log::ERR) << "Caught: " << e.what(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /extern/open62541/prepare_open62541.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # the purpose of this script is to make the process of deploying open62541 in open62541-compat 4 | # automated, reproducible 5 | 6 | # this script was created to be used only by quasar-developers team. 7 | 8 | TAG=v1.2.2 9 | 10 | # prepare the dir structure 11 | mkdir include 12 | mkdir src 13 | 14 | # prepare (i.e. amalgamate... open62541) 15 | WD=`pwd` 16 | if [ -d tmp ]; then 17 | rm -frv tmp 18 | fi 19 | mkdir tmp && cd tmp 20 | git clone https://github.com/open62541/open62541.git --depth=1 -b $TAG || exit 21 | cd open62541 22 | mkdir build && cd build 23 | cmake -DUA_ENABLE_AMALGAMATION=ON -DUA_ENABLE_METHODCALLS=ON -DUA_LOGLEVEL=100 ../ || exit 24 | make || exit 25 | cd $WD 26 | 27 | # deploy files 28 | find tmp -name open62541.h -ok cp {} include \; || exit 29 | find tmp -name open62541.c -ok cp {} src \; || exit 30 | 31 | read -n 1 -p "Would you like to commit the freshly amalgamated open62541? type y if so." answer 32 | if [ $answer == "y" ]; then 33 | git add include/open62541.h 34 | git add src/open62541.c 35 | git commit --author="open62541 " -m "Amalgamated open62541 v $TAG by prepare_open62541.sh" 36 | fi 37 | 38 | # clean-up 39 | rm -fr tmp 40 | -------------------------------------------------------------------------------- /include/array_templates.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * array_templates.h 3 | * 4 | * Created on: 27 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_ARRAY_TEMPLATES_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_ARRAY_TEMPLATES_H_ 24 | 25 | #include 26 | 27 | template 28 | class UaCompatArray 29 | { 30 | public: 31 | 32 | void create(std::size_t n) 33 | { 34 | m_data.clear(); 35 | m_data.insert( m_data.begin(), n, T()); 36 | } 37 | 38 | void resize(std::size_t n) 39 | { 40 | m_data.resize(n, T()); 41 | } 42 | 43 | void clear() 44 | { 45 | m_data.clear(); 46 | } 47 | 48 | T& operator[](std::size_t i) { return m_data.at(i); } 49 | const T& operator[](std::size_t i) const { return m_data.at(i); } 50 | 51 | std::size_t size() const { return m_data.size(); } 52 | std::size_t length() const { return size(); } // TODO is this really necessary ... 53 | 54 | typename std::vector::iterator begin() { return m_data.begin(); } 55 | 56 | protected: 57 | std::vector m_data; 58 | }; 59 | 60 | 61 | 62 | #endif /* OPEN62541_COMPAT_INCLUDE_ARRAY_TEMPLATES_H_ */ 63 | -------------------------------------------------------------------------------- /include/arrays.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 1 May, 2017 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | #ifndef OPEN62541_COMPAT_INCLUDE_ARRAYS_H_ 22 | #define OPEN62541_COMPAT_INCLUDE_ARRAYS_H_ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | 32 | typedef UaCompatArray UaReadValueIds; 33 | typedef UaCompatArray UaDataValues; 34 | typedef UaCompatArray UaDiagnosticInfos; 35 | typedef UaCompatArray UaStatusCodes; 36 | typedef UaCompatArray UaWriteValues; 37 | typedef UaCompatArray UaStatusCodeArray; 38 | typedef UaCompatArray UaVariantArray; 39 | typedef UaCompatArray UaReferenceDescriptions; 40 | 41 | #endif /* OPEN62541_COMPAT_INCLUDE_ARRAYS_H_ */ 42 | -------------------------------------------------------------------------------- /include/logit_logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * logit_logger.h 3 | * 4 | * Created on: May 20, 2021 5 | * Author: pnikiel 6 | */ 7 | 8 | #ifndef INCLUDE_LOGIT_LOGGER_H_ 9 | #define INCLUDE_LOGIT_LOGGER_H_ 10 | 11 | #include 12 | #include 13 | 14 | //! Can be safely run many times, does anything only if the component does not exist yet. 15 | void initializeOpen62541LogIt (Log::LOG_LEVEL logLevel = Log::INF); 16 | 17 | extern UA_Logger theLogItLogger; 18 | 19 | #endif /* INCLUDE_LOGIT_LOGGER_H_ */ 20 | -------------------------------------------------------------------------------- /include/managed_uaarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | * managed_uaarray.h 3 | * 4 | * Created on: 12 Jul 2018 5 | * Author: pnikiel 6 | * 7 | * The purpose of this class is to provide UA_Array with: 8 | * - RAII (e.g. auto-destruction on going out-of-scope) 9 | * - without necessity to do void* casting by the programmer 10 | */ 11 | 12 | #ifndef INCLUDE_MANAGED_UAARRAY_H_ 13 | #define INCLUDE_MANAGED_UAARRAY_H_ 14 | 15 | #include 16 | #include 17 | 18 | /** T is the type contained in the array */ 19 | 20 | template 21 | class ManagedUaArray 22 | { 23 | public: 24 | 25 | //! This ctr is for constructing an array 26 | ManagedUaArray(size_t sz, const UA_DataType* type): 27 | m_size(sz), 28 | m_dataType(type) 29 | { 30 | m_array = static_cast (UA_Array_new(sz, type)); 31 | if (!m_array) 32 | { 33 | throw alloc_error(); 34 | } 35 | } 36 | 37 | //! This ctr is for already allocated array (e.g. returned from open62541 service call) 38 | ManagedUaArray(size_t sz, const UA_DataType* type, T* array): 39 | m_size(sz), 40 | m_dataType(type), 41 | m_array(array) 42 | {} 43 | 44 | virtual ~ManagedUaArray() 45 | { 46 | UA_Array_delete(m_array, m_size, m_dataType); 47 | } 48 | 49 | operator T* () 50 | { 51 | return m_array; 52 | } 53 | 54 | private: 55 | const size_t m_size; 56 | const UA_DataType* m_dataType; 57 | T* m_array; 58 | 59 | 60 | 61 | }; 62 | 63 | 64 | 65 | #endif /* INCLUDE_MANAGED_UAARRAY_H_ */ 66 | -------------------------------------------------------------------------------- /include/methodhandleuanode.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * nodemanagerbase.h 3 | * 4 | * Created on: 23 Apr, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef __METHODHANDLEUANODE_H__ 23 | #define __METHODHANDLEUANODE_H__ 24 | 25 | 26 | #include 27 | #include 28 | 29 | 30 | class MethodHandle 31 | { 32 | public: 33 | virtual ~MethodHandle() {}; 34 | }; 35 | 36 | class MethodHandleUaNode: public MethodHandle 37 | { 38 | public: 39 | virtual ~MethodHandleUaNode() {}; 40 | MethodHandleUaNode(): 41 | m_obj(0), 42 | m_method(0) 43 | {} 44 | 45 | UaMethod * pUaMethod () const { return m_method; } 46 | UaObject * pUaObject () const { return m_obj; } 47 | 48 | void setUaNodes (UaObject* uaObject, UaMethod* uaMethod) 49 | { 50 | m_obj = uaObject; 51 | m_method = uaMethod; 52 | } 53 | private: 54 | UaObject *m_obj; 55 | UaMethod *m_method; 56 | 57 | }; 58 | 59 | 60 | #endif // __METHODHANDLEUANODE_H__ 61 | -------------------------------------------------------------------------------- /include/methodmanager.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * methodmanager.h 3 | * 4 | * Created on: Apr 18, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_METHODMANAGER_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_METHODMANAGER_H_ 24 | 25 | #include 26 | #include 27 | 28 | 29 | 30 | class ServiceContext 31 | { 32 | 33 | }; 34 | 35 | 36 | class MethodManagerCallback 37 | { 38 | 39 | public: 40 | virtual UaStatus finishCall ( 41 | OpcUa_UInt32 callbackHandle, 42 | UaStatusCodeArray &inputArgumentResults, 43 | UaDiagnosticInfos &inputArgumentDiag, 44 | UaVariantArray &outputArguments, 45 | UaStatus &statusCode)=0; 46 | virtual ~MethodManagerCallback() {}; 47 | 48 | 49 | }; 50 | 51 | class MethodManager 52 | { 53 | public: 54 | virtual ~MethodManager() {}; 55 | virtual UaStatus beginCall ( 56 | MethodManagerCallback *callback, 57 | const ServiceContext &context, 58 | OpcUa_UInt32 callbackHandle, 59 | MethodHandle *methodHandle, 60 | const UaVariantArray &inputArguments)=0; 61 | 62 | }; 63 | 64 | 65 | 66 | 67 | 68 | #endif /* OPEN62541_COMPAT_INCLUDE_METHODMANAGER_H_ */ 69 | -------------------------------------------------------------------------------- /include/nodemanagerbase.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * nodemanagerbase.h 3 | * 4 | * Created on: 15 Nov, 2015 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef __NODEMANAGERBASE_H__ 23 | #define __NODEMANAGERBASE_H__ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | // forward-decls 30 | namespace OpcUa 31 | { 32 | class BaseDataVariableType; 33 | } 34 | 35 | class UaPropertyCache; 36 | 37 | class NodeManagerConfig 38 | { 39 | }; 40 | 41 | class NodeManagerBase: public NodeManagerConfig 42 | { 43 | public: 44 | NodeManagerBase( 45 | const char* sNamespaceUri, 46 | bool firesEvents = OpcUa_False, 47 | OpcUa_Int32 nHashTableSize = 9973 ); 48 | virtual ~NodeManagerBase(); 49 | UaNode* getNode( const UaNodeId& nodeId ) const; 50 | 51 | OpcUa_UInt16 getNameSpaceIndex () const { return 2; } 52 | 53 | UaStatus addNodeAndReference( 54 | const UaNodeId& from, 55 | UaNode* to, 56 | const UaNodeId& refType); 57 | UaStatus addNodeAndReference( 58 | UaNode* from, 59 | UaNode* to, 60 | const UaNodeId& refType); 61 | 62 | UaStatus addUaReference( 63 | const UaNodeId& from, 64 | const UaNodeId& to, 65 | const UaNodeId& refType); 66 | 67 | 68 | 69 | 70 | void linkServer( UA_Server* server ); 71 | 72 | virtual UaStatus afterStartUp(); 73 | 74 | 75 | private: 76 | UA_Server* m_server; 77 | std::list m_listNodes; 78 | std::string m_nameSpaceUri; 79 | 80 | UaStatus addObjectNodeAndReference( 81 | UaNode* parent, 82 | UaNode* to, 83 | const UaNodeId& refType); 84 | 85 | UaStatus addVariableNodeAndReference( 86 | UaNode* parent, 87 | UaNode* to, 88 | const UaNodeId& refType); 89 | UaStatus addDataVariableNodeAndReference( 90 | UaNode* parent, 91 | OpcUa::BaseDataVariableType* to, 92 | const UaNodeId& refType); 93 | UaStatus addPropertyNodeAndReference( 94 | UaNode* parent, 95 | UaPropertyCache* to, 96 | const UaNodeId& refType); 97 | UaStatus addMethodNodeAndReference( 98 | UaNode* parent, 99 | UaNode* to, 100 | const UaNodeId& refType); 101 | 102 | class ServerRootNode: public UaNode 103 | { 104 | public: 105 | ServerRootNode() {} 106 | virtual UaQualifiedName browseName() const override { return UaQualifiedName(0, "."); } 107 | virtual UaNodeId typeDefinitionId() const override { return UaNodeId(UA_NS0ID_BASEOBJECTTYPE,0); } 108 | virtual OpcUa_NodeClass nodeClass() const override { return OpcUa_NodeClass::OpcUa_NodeClass_Object; } 109 | virtual UaNodeId nodeId() const override {return UaNodeId(OpcUaId_ObjectsFolder, 0); } 110 | private: 111 | ServerRootNode( const ServerRootNode& other ); 112 | void operator=( const ServerRootNode& other ); 113 | 114 | }; 115 | ServerRootNode m_serverRootNode; 116 | 117 | 118 | }; 119 | 120 | 121 | 122 | #endif // __NODEMANAGERBASE_H__ 123 | -------------------------------------------------------------------------------- /include/opcua_attributes.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * opcua_attributes.h 3 | * 4 | * Created on: 30 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | 23 | #ifndef OPEN62541_COMPAT_INCLUDE_OPCUA_ATTRIBUTES_H_ 24 | #define OPEN62541_COMPAT_INCLUDE_OPCUA_ATTRIBUTES_H_ 25 | 26 | 27 | enum Attributes 28 | { 29 | OpcUa_Attributes_NodeId = UA_ATTRIBUTEID_NODEID, 30 | OpcUa_Attributes_NodeClass = UA_ATTRIBUTEID_NODECLASS, 31 | OpcUa_Attributes_BrowseName = UA_ATTRIBUTEID_BROWSENAME, 32 | OpcUa_Attributes_DisplayName = UA_ATTRIBUTEID_DISPLAYNAME, 33 | OpcUa_Attributes_Description = UA_ATTRIBUTEID_DESCRIPTION, 34 | OpcUa_Attributes_WriteMask = UA_ATTRIBUTEID_WRITEMASK, 35 | OpcUa_Attributes_UserWriteMask = UA_ATTRIBUTEID_USERWRITEMASK, 36 | OpcUa_Attributes_IsAbstract = UA_ATTRIBUTEID_ISABSTRACT, 37 | OpcUa_Attributes_Symmetric = UA_ATTRIBUTEID_SYMMETRIC, 38 | OpcUa_Attributes_InverseName = UA_ATTRIBUTEID_INVERSENAME, 39 | OpcUa_Attributes_ContainsNoLoops = UA_ATTRIBUTEID_CONTAINSNOLOOPS, 40 | OpcUa_Attributes_EventNotifier = UA_ATTRIBUTEID_EVENTNOTIFIER, 41 | OpcUa_Attributes_Value = UA_ATTRIBUTEID_VALUE, 42 | OpcUa_Attributes_DataType = UA_ATTRIBUTEID_DATATYPE, 43 | OpcUa_Attributes_ValueRank = UA_ATTRIBUTEID_VALUERANK, 44 | OpcUa_Attributes_ArrayDimensions = UA_ATTRIBUTEID_ARRAYDIMENSIONS, 45 | OpcUa_Attributes_AccessLevel = UA_ATTRIBUTEID_ACCESSLEVEL, 46 | OpcUa_Attributes_UserAccessLevel = UA_ATTRIBUTEID_USERACCESSLEVEL, 47 | OpcUa_Attributes_MinimumSamplingInterval = UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL, 48 | OpcUa_Attributes_Historizing = UA_ATTRIBUTEID_HISTORIZING, 49 | OpcUa_Attributes_Executable = UA_ATTRIBUTEID_EXECUTABLE, 50 | OpcUa_Attributes_UserExecutable = UA_ATTRIBUTEID_USEREXECUTABLE, 51 | OpcUa_Attributes_DataTypeDefinition = UA_ATTRIBUTEID_DATATYPEDEFINITION 52 | /* the following are not yet in open62541, at least not in 1.1.6. TODO! 53 | OpcUa_Attributes_RolePermissions 54 | OpcUa_Attributes_UserRolePermissions 55 | OpcUa_Attributes_AccessRestrictions 56 | OpcUa_Attributes_AccessLevelEx 57 | */ 58 | 59 | }; 60 | 61 | 62 | #endif /* OPEN62541_COMPAT_INCLUDE_OPCUA_ATTRIBUTES_H_ */ 63 | -------------------------------------------------------------------------------- /include/opcua_basedatavariabletype.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __OPCUA_BASEDATAVARIABLETYPE_H__ 23 | #define __OPCUA_BASEDATAVARIABLETYPE_H__ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace OpcUa 33 | { 34 | 35 | class BaseDataVariableType: public UaNode 36 | { 37 | public: 38 | BaseDataVariableType( 39 | const UaNodeId& nodeId, 40 | const UaString& name, 41 | OpcUa_UInt16 browseNameNameSpaceIndex, 42 | const UaVariant& initialValue, 43 | OpcUa_Byte accessLevel, 44 | NodeManagerConfig* pNodeConfig, 45 | UaMutexRefCounted* pSharedMutex = NULL); 46 | virtual ~BaseDataVariableType() {}; 47 | 48 | virtual UaStatus setValue( 49 | Session *session, 50 | const UaDataValue& dataValue, 51 | OpcUa_Boolean checkAccessLevel 52 | ); 53 | virtual OpcUa_Byte accessLevel() const { return m_accessLevel; } 54 | virtual UaDataValue value(Session* session) ; 55 | virtual UaQualifiedName browseName() const override { return m_browseName; } 56 | virtual void setAccessLevel (OpcUa_Byte accessLevel) { m_accessLevel = accessLevel; } 57 | virtual UaNodeId typeDefinitionId() const override { return m_typeDefinitionId; } 58 | virtual void setDataType( const UaNodeId& typeref ) { m_typeDefinitionId = typeref; } 59 | virtual void setValueRank (OpcUa_Int32 valueRank) { m_valueRank = valueRank; } 60 | virtual void setArrayDimensions( const UaUInt32Array &arrayDimensions ) {m_arrayDimensions = arrayDimensions;} 61 | virtual OpcUa_NodeClass nodeClass() const override { return OpcUa_NodeClass_Variable; } 62 | virtual UaNodeId nodeId() const override { return m_nodeId; } 63 | virtual OpcUa_Int32 valueRank() const { return m_valueRank; } 64 | virtual void arrayDimensions(UaUInt32Array & arrayDimensions ) const { arrayDimensions = m_arrayDimensions;} 65 | const UA_DataValue* valueImpl() const { return m_currentValue.impl(); } 66 | 67 | private: 68 | UaQualifiedName m_browseName; 69 | UaDataValue m_currentValue; 70 | UaNodeId m_nodeId; 71 | UaNodeId m_typeDefinitionId; 72 | OpcUa_Int32 m_valueRank; 73 | OpcUa_Byte m_accessLevel; 74 | UaUInt32Array m_arrayDimensions; 75 | }; 76 | 77 | 78 | 79 | } 80 | 81 | #endif // __OPCUA_BASEDATAVARIABLETYPE_H__ 82 | -------------------------------------------------------------------------------- /include/opcua_baseobjecttype.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __OPCUA_BASEOBJECTTYPE_H__ 23 | #define __OPCUA_BASEOBJECTTYPE_H__ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | 34 | 35 | 36 | 37 | namespace OpcUa 38 | { 39 | 40 | class BaseObjectType: public UaObject, MethodManager 41 | { 42 | public: 43 | BaseObjectType( 44 | const UaNodeId& nodeId, 45 | const UaString& name, 46 | OpcUa_UInt16 browseNameNameSpaceIndex, 47 | NodeManagerConfig *nm 48 | 49 | 50 | ); 51 | 52 | virtual UaQualifiedName browseName() const override { return m_browseName; } 53 | virtual OpcUa_NodeClass nodeClass() const override { return OpcUa_NodeClass_Object; } 54 | virtual UaNodeId typeDefinitionId() const override { return UaNodeId(UA_NS0ID_BASEOBJECTTYPE,0); } 55 | virtual UaNodeId nodeId() const override { return m_nodeId; } 56 | 57 | virtual UaStatus beginCall ( 58 | MethodManagerCallback *callback, 59 | const ServiceContext &context, 60 | OpcUa_UInt32 callbackHandle, 61 | MethodHandle *methodHandle, 62 | const UaVariantArray &inputArguments) { return OpcUa_Bad; } 63 | 64 | private: 65 | UaNodeId m_nodeId; 66 | UaQualifiedName m_browseName; 67 | }; 68 | 69 | 70 | 71 | class BaseMethod: public UaMethod 72 | { 73 | public: 74 | BaseMethod ( 75 | const UaNodeId &nodeId, 76 | const UaString &name, 77 | OpcUa_UInt16 browseNameNameSpaceIndex, 78 | UaMutexRefCounted *pSharedMutex=NULL); 79 | 80 | 81 | 82 | virtual OpcUa_NodeClass nodeClass() const override { return OpcUa_NodeClass_Method; } 83 | virtual UaQualifiedName browseName() const override { return m_browseName; } 84 | // FIXME 85 | virtual UaNodeId typeDefinitionId() const override { return UaNodeId(UA_NS0ID_BASEOBJECTTYPE,0); } 86 | virtual UaNodeId nodeId() const override { return m_nodeId; } 87 | private: 88 | UaNodeId m_nodeId; 89 | UaQualifiedName m_browseName; 90 | 91 | }; 92 | 93 | } 94 | 95 | #endif // __OPCUA_BASEOBJECTTYPE_H__ 96 | -------------------------------------------------------------------------------- /include/opcua_identifiers.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2021. All rights not expressly granted are reserved. 2 | * opcua_identifiers.h 3 | * 4 | * Created on: 28 Jan, 2021 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #pragma once 23 | 24 | // common NS0 ids 25 | 26 | #define OpcUaId_ObjectsFolder UA_NS0ID_OBJECTSFOLDER 27 | 28 | #define OpcUaId_BaseDataType UA_NS0ID_BASEDATATYPE 29 | 30 | // common reference types 31 | 32 | #define OpcUaId_HasComponent UA_NS0ID_HASCOMPONENT 33 | #define OpcUaId_Organizes UA_NS0ID_ORGANIZES 34 | #define OpcUaId_HasProperty UA_NS0ID_HASPROPERTY 35 | -------------------------------------------------------------------------------- /include/opcua_platformdefs.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #include 23 | 24 | typedef bool OpcUa_Boolean; 25 | typedef uint8_t OpcUa_Byte; 26 | typedef int8_t OpcUa_SByte; 27 | typedef uint16_t OpcUa_UInt16; 28 | typedef int16_t OpcUa_Int16; 29 | typedef uint32_t OpcUa_UInt32; 30 | typedef int32_t OpcUa_Int32; 31 | typedef uint64_t OpcUa_UInt64; 32 | typedef int64_t OpcUa_Int64; 33 | typedef float OpcUa_Float; 34 | typedef double OpcUa_Double; 35 | 36 | class UaVariant; 37 | -------------------------------------------------------------------------------- /include/opcua_types.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * opcua_types.h 3 | * 4 | * Created on: 30 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_OPCUA_TYPES_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_OPCUA_TYPES_H_ 24 | 25 | #include 26 | 27 | enum OpcUa_TimestampsToReturn 28 | { 29 | OpcUa_TimestampsToReturn_Both = UA_TIMESTAMPSTORETURN_BOTH 30 | }; 31 | 32 | 33 | enum OpcUa_NodeClass 34 | { 35 | OpcUa_NodeClass_Object = UA_NodeClass::UA_NODECLASS_OBJECT, 36 | OpcUa_NodeClass_Variable = UA_NodeClass::UA_NODECLASS_VARIABLE, 37 | OpcUa_NodeClass_Method = UA_NodeClass::UA_NODECLASS_METHOD, 38 | OpcUa_NodeClass_ObjectType = UA_NodeClass::UA_NODECLASS_OBJECTTYPE, 39 | OpcUa_NodeClass_VariableType = UA_NodeClass::UA_NODECLASS_VARIABLETYPE, 40 | OpcUa_NodeClass_ReferenceType = UA_NodeClass::UA_NODECLASS_REFERENCETYPE, 41 | OpcUa_NodeClass_DataType = UA_NodeClass::UA_NODECLASS_DATATYPE, 42 | OpcUa_NodeClass_View = UA_NodeClass::UA_NODECLASS_VIEW 43 | }; 44 | 45 | OpcUa_NodeClass safeConvertNodeClassToSdk (UA_NodeClass nc); 46 | 47 | enum OpcUa_AccessLevels 48 | { 49 | OpcUa_AccessLevels_CurrentRead = UA_ACCESSLEVELMASK_READ, 50 | OpcUa_AccessLevels_CurrentWrite = UA_ACCESSLEVELMASK_WRITE, 51 | OpcUa_AccessLevels_CurrentReadOrWrite = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE 52 | }; 53 | 54 | #endif /* OPEN62541_COMPAT_INCLUDE_OPCUA_TYPES_H_ */ 55 | -------------------------------------------------------------------------------- /include/open62541_compat.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * open62541_compat.h 3 | * 4 | * Created on: 15 Nov, 2015 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | 23 | #ifndef OPEN62541_COMPAT 24 | #define OPEN62541_COMPAT 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | 50 | #define OPEN62541_COMPAT_LOG_AND_THROW(EXCEPTION_TYPE, MSG) \ 51 | { \ 52 | LOG(Log::ERR) << MSG; \ 53 | throw EXCEPTION_TYPE (MSG); \ 54 | } 55 | 56 | 57 | class IOManager 58 | { 59 | }; 60 | 61 | 62 | 63 | #endif // OPEN62541_COMPAT 64 | -------------------------------------------------------------------------------- /include/open62541_compat_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * common.h 3 | * 4 | * Created on: Jan 26, 2017 5 | * Author: pnikiel 6 | */ 7 | 8 | #ifndef OPEN62541_COMPAT_INCLUDE_OPEN62541_COMPAT_COMMON_H_ 9 | #define OPEN62541_COMPAT_INCLUDE_OPEN62541_COMPAT_COMMON_H_ 10 | 11 | #include 12 | 13 | class alloc_error: public std::runtime_error 14 | { 15 | public: 16 | alloc_error(): std::runtime_error("memory allocation exception") {} 17 | }; 18 | 19 | 20 | #endif /* OPEN62541_COMPAT_INCLUDE_OPEN62541_COMPAT_COMMON_H_ */ 21 | -------------------------------------------------------------------------------- /include/other.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __OTHER_H__ 23 | #define __OTHER_H__ 24 | 25 | #include 26 | #include 27 | #include 28 | //TODO: amalgamated or not 29 | 30 | 31 | #define OpcUa_True true 32 | #define OpcUa_False false 33 | 34 | class UaLocalizedText 35 | { 36 | public: 37 | UaLocalizedText( const char* locate, const char* text); 38 | ~UaLocalizedText (); 39 | const UA_LocalizedText* impl () { return &m_impl; } 40 | private: 41 | UaLocalizedText( const UaLocalizedText & other ); 42 | void operator= ( const UaLocalizedText & other ); 43 | UA_LocalizedText m_impl ; 44 | }; 45 | 46 | 47 | class UaQualifiedName 48 | { 49 | public: 50 | UaQualifiedName(int ns, const UaString& name); 51 | UA_QualifiedName impl() const { return m_impl; } 52 | UaString unqualifiedName() const { return m_unqualifiedName; } 53 | UaString toString() const; 54 | UaString toFullString() const; 55 | private: 56 | UaString m_unqualifiedName; 57 | UA_QualifiedName m_impl; 58 | }; 59 | 60 | std::ostream& operator<<(std::ostream& os, const UaQualifiedName& n); 61 | 62 | class UaMutexRefCounted {}; 63 | 64 | #define UA_DISABLE_COPY(T) 65 | 66 | class ServiceSettings 67 | { 68 | 69 | }; 70 | 71 | class DiagnosticInfo 72 | { 73 | 74 | }; 75 | 76 | #endif // __OTHER_H__ 77 | -------------------------------------------------------------------------------- /include/session.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __SESSION_H__ 23 | #define __SESSION_H__ 24 | 25 | class Session {}; 26 | 27 | #endif // __SESSION_H__ 28 | -------------------------------------------------------------------------------- /include/simple_arrays.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2018. All rights not expressly granted are reserved. 2 | * simple_arrays.h 3 | * 4 | * Created on: 12 Mar 2018 5 | * Author: Piotr Nikiel 6 | * 7 | * Simple arrays are those which don't require UaVariant declaration, 8 | * therefore they can be directly included in UaVariant.h 9 | * 10 | * This file is part of Quasar. 11 | * 12 | * Quasar is free software: you can redistribute it and/or modify 13 | * it under the terms of the GNU Lesser General Public Licence as published by 14 | * the Free Software Foundation, either version 3 of the Licence. 15 | * 16 | * Quasar is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Lesser General Public Licence for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public License 22 | * along with Quasar. If not, see . 23 | */ 24 | 25 | #ifndef OPEN62541_COMPAT_INCLUDE_SIMPLE_ARRAYS_H_ 26 | #define OPEN62541_COMPAT_INCLUDE_SIMPLE_ARRAYS_H_ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | /* Piotr: 34 | * Here is a comment why we have the class below (AvoidStdVectorBoolSpecializationProblem). 35 | * It comes from a questionable decision of STL that std::vector is specialized 36 | * as a bitmap. While it clearly has some advantages (e.g. it is memory compact) it has 37 | * disadvantages: you can't get a reference to a particular element of the vector. 38 | * So we have this class below which hopefully evaluates to sizeof(bool) in the terms of 39 | * memory consumption. First and foremost though, std::vector<> of it is quite sane! 40 | */ 41 | 42 | struct AvoidStdVectorBoolSpecializationProblem 43 | { 44 | bool booleanValue; 45 | void operator= (bool in) { booleanValue=in; } 46 | operator bool() const { return booleanValue; } 47 | }; 48 | 49 | typedef UaCompatArray UaBooleanArray; 50 | typedef UaCompatArray UaSByteArray; 51 | typedef UaCompatArray UaInt16Array; 52 | typedef UaCompatArray UaUInt16Array; 53 | typedef UaCompatArray UaInt32Array; 54 | typedef UaCompatArray UaUInt32Array; 55 | typedef UaCompatArray UaInt64Array; 56 | typedef UaCompatArray UaUInt64Array; 57 | typedef UaCompatArray UaFloatArray; 58 | typedef UaCompatArray UaDoubleArray; 59 | typedef UaCompatArray UaStringArray; 60 | typedef UaCompatArray UaByteStringArray; 61 | typedef UaCompatArray UaVariantArray; 62 | 63 | class UaByteArray: public UaCompatArray 64 | /* UaByteArray has bit more on top of a regular array ... */ 65 | { 66 | public: 67 | UaByteArray(); 68 | UaByteArray(const char* data, unsigned int sz); 69 | 70 | const char* data() const; 71 | }; 72 | 73 | #endif /* OPEN62541_COMPAT_INCLUDE_SIMPLE_ARRAYS_H_ */ 74 | -------------------------------------------------------------------------------- /include/stack_fake_structures.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * stack_fake_structures.h 3 | * 4 | * Created on: 27 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_UACLIENT_STACK_FAKE_STRUCTURES_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_UACLIENT_STACK_FAKE_STRUCTURES_H_ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | struct ReadValueId 33 | { 34 | ReadValueId() : NodeId(0, 0), AttributeId (OpcUa_Attributes_Value) {} 35 | UaNodeId NodeId; 36 | Attributes AttributeId; 37 | }; 38 | 39 | struct DataValue 40 | { 41 | UaStatus StatusCode; 42 | UaVariant Value; 43 | UaDateTime SourceTimestamp; 44 | UaDateTime ServerTimestamp; 45 | 46 | }; 47 | 48 | struct WriteValue 49 | { 50 | WriteValue(): NodeId(0, 0), AttributeId( OpcUa_Attributes_Value), Value() {} 51 | UaNodeId NodeId; 52 | Attributes AttributeId; 53 | DataValue Value; 54 | }; 55 | 56 | struct ReferenceDescription 57 | { 58 | UaNodeId ReferenceTypeId; 59 | OpcUa_Boolean IsForward; 60 | UaExpandedNodeId NodeId; 61 | UaString BrowseName; // TODO: should be rather QualifiedName type, but keeping UaString for simplicity ... 62 | OpcUa_NodeClass NodeClass; 63 | UaExpandedNodeId TypeDefinition; 64 | }; 65 | 66 | #endif /* OPEN62541_COMPAT_INCLUDE_UACLIENT_STACK_FAKE_STRUCTURES_H_ */ 67 | -------------------------------------------------------------------------------- /include/statuscode.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | 23 | #ifndef __STATUSCODE_H__ 24 | #define __STATUSCODE_H__ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #define OpcUa_Good UA_STATUSCODE_GOOD 32 | #define OpcUa_Bad 0x80000000 33 | #define OpcUa_Uncertain 0x40000000 34 | #define OpcUa_BadNotImplemented UA_STATUSCODE_BADNOTIMPLEMENTED 35 | #define OpcUa_BadNoData UA_STATUSCODE_BADNODATA 36 | #define OpcUa_BadDataEncodingInvalid UA_STATUSCODE_BADDATAENCODINGINVALID 37 | #define OpcUa_BadDataUnavailable UA_STATUSCODE_BADDATAUNAVAILABLE 38 | #define OpcUa_BadInvalidArgument UA_STATUSCODE_BADINVALIDARGUMENT 39 | #define OpcUa_BadWaitingForInitialData UA_STATUSCODE_BADWAITINGFORINITIALDATA 40 | #define OpcUa_BadOutOfRange UA_STATUSCODE_BADOUTOFRANGE 41 | #define OpcUa_BadUserAccessDenied UA_STATUSCODE_BADUSERACCESSDENIED 42 | #define OpcUa_BadNoCommunication UA_STATUSCODE_BADNOCOMMUNICATION 43 | #define OpcUa_BadCommunicationError UA_STATUSCODE_BADCOMMUNICATIONERROR 44 | #define OpcUa_BadNotSupported UA_STATUSCODE_BADNOTSUPPORTED 45 | #define OpcUa_BadResourceUnavailable UA_STATUSCODE_BADRESOURCEUNAVAILABLE 46 | #define OpcUa_BadInternalError UA_STATUSCODE_BADINTERNALERROR 47 | #define OpcUa_BadInvalidState UA_STATUSCODE_BADINVALIDSTATE 48 | #define OpcUa_UncertainInitialValue UA_STATUSCODE_UNCERTAININITIALVALUE 49 | #define OpcUa_BadUnexpectedError UA_STATUSCODE_BADUNEXPECTEDERROR 50 | #define OpcUa_BadParentNodeIdInvalid UA_STATUSCODE_BADPARENTNODEIDINVALID 51 | #define OpcUa_BadServerNotConnected UA_STATUSCODE_BADSERVERNOTCONNECTED 52 | #define OpcUa_BadServerNotConnected UA_STATUSCODE_BADSERVERNOTCONNECTED 53 | #define OpcUa_BadIndexRangeInvalid UA_STATUSCODE_BADINDEXRANGEINVALID 54 | #define OpcUa_BadIndexRangeNoData UA_STATUSCODE_BADINDEXRANGENODATA 55 | #define OpcUa_BadArgumentsMissing UA_STATUSCODE_BADARGUMENTSMISSING 56 | #define OpcUa_BadConnectionClosed UA_STATUSCODE_BADCONNECTIONCLOSED 57 | 58 | typedef OpcUa_UInt32 OpcUa_StatusCode; 59 | 60 | struct StatusCodeDescription { 61 | OpcUa_StatusCode statusCode; 62 | const std::string description; 63 | }; 64 | 65 | class UaStatus 66 | { 67 | public: 68 | 69 | UaStatus (OpcUa_StatusCode s): m_status(s) {} // from status code 70 | UaStatus(): m_status(OpcUa_Bad) {} // by default, initialize to Bad 71 | 72 | const UaStatus& operator=(OpcUa_StatusCode status) { m_status = status; return *this; } 73 | 74 | bool isGood() const { return m_status == UA_STATUSCODE_GOOD; } 75 | bool isNotGood() const { return !isGood(); } 76 | bool isBad() const; 77 | bool isUncertain() const; 78 | UaString toString() const; 79 | 80 | OpcUa_StatusCode statusCode() const { return m_status; } 81 | operator UA_StatusCode() const { return (UA_StatusCode)m_status; } 82 | static std::vector s_statusCodeDescriptions; 83 | 84 | private: 85 | OpcUa_StatusCode m_status; 86 | 87 | }; 88 | 89 | #endif //__STATUSCODE_H__ 90 | -------------------------------------------------------------------------------- /include/uabasenodes.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * uabasenodes.h 3 | * 4 | * Created on: 26 Apr, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_UABASENODES_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_UABASENODES_H_ 24 | 25 | #include 26 | 27 | class UaObject: public UaNode 28 | { 29 | 30 | }; 31 | 32 | class UaMethod: public UaNode 33 | { 34 | public: 35 | UaMethod() {}; 36 | 37 | }; 38 | 39 | 40 | #endif /* OPEN62541_COMPAT_INCLUDE_UABASENODES_H_ */ 41 | -------------------------------------------------------------------------------- /include/uabytestring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uabytestring.h 3 | * 4 | * Created on: Jan 26, 2017 5 | * Author: pnikiel 6 | * 7 | * Contents moved from uavariant.h as a cleanup effort 8 | * 9 | * 10 | */ 11 | 12 | #ifndef OPEN62541_COMPAT_INCLUDE_UABYTESTRING_H_ 13 | #define OPEN62541_COMPAT_INCLUDE_UABYTESTRING_H_ 14 | 15 | #include 16 | #include 17 | 18 | class UaByteString 19 | { 20 | public: 21 | // a byte-string of length 0 22 | UaByteString (); 23 | 24 | UaByteString( const int len, const OpcUa_Byte* data); 25 | UaByteString( const UaByteString& other); 26 | UaByteString( const UA_ByteString& other); 27 | 28 | ~UaByteString (); 29 | 30 | UaByteString& operator= (const UaByteString& other); 31 | bool operator== (const UaByteString& other) const; 32 | 33 | OpcUa_Int32 length() const; 34 | const OpcUa_Byte* data() const { return m_impl->data; } 35 | 36 | void setByteString (const int len, const OpcUa_Byte *Data); 37 | 38 | void copyTo(UaByteString* other) const; 39 | 40 | UA_ByteString* impl() const { return m_impl; } 41 | private: 42 | 43 | void release(); 44 | UA_ByteString * m_impl; 45 | 46 | }; 47 | 48 | 49 | 50 | 51 | #endif /* OPEN62541_COMPAT_INCLUDE_UABYTESTRING_H_ */ 52 | -------------------------------------------------------------------------------- /include/uaclient/uaclientsdk.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * uaclientsdk.h 3 | * 4 | * Created on: 24 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_UACLIENT_UACLIENTSDK_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_UACLIENT_UACLIENTSDK_H_ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #endif /* OPEN62541_COMPAT_INCLUDE_UACLIENT_UACLIENTSDK_H_ */ 33 | -------------------------------------------------------------------------------- /include/uaclient/uasession.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * uasession.h 3 | * 4 | * Created on: 24 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef INCLUDE_UACLIENT_UASESSION_H_ 23 | #define INCLUDE_UACLIENT_UASESSION_H_ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | // forward-decl 35 | struct UA_Client; 36 | 37 | namespace UaClientSdk 38 | { 39 | 40 | struct SessionSecurityInfo 41 | { 42 | // TODO 43 | }; 44 | 45 | struct SessionConnectInfo 46 | { 47 | UaString sApplicationName; 48 | UaString sApplicationUri; 49 | UaString sProductUri; 50 | OpcUa_UInt32 internalServiceCallTimeout; 51 | OpcUa_UInt32 nSecureChannelLifetime; 52 | OpcUa_Double nSessionTimeout; 53 | 54 | SessionConnectInfo() : 55 | sApplicationName("OPC-UA client"), 56 | sApplicationUri("OPC-UA client"), 57 | sProductUri("OPC-UA client"), 58 | internalServiceCallTimeout(5000), 59 | nSecureChannelLifetime(60/*minutes*/ * 60/*seconds per minute*/ * 1000 /* the unit is miliseconds */ ), 60 | nSessionTimeout(60/*minutes*/ * 60/*seconds per minute*/ * 1000 /* the unit is miliseconds */) 61 | {} 62 | }; 63 | 64 | struct CallIn 65 | { 66 | CallIn(): objectId(0, 0), methodId(0,0) {} 67 | 68 | UaNodeId objectId; 69 | UaNodeId methodId; 70 | UaVariantArray inputArguments; 71 | }; 72 | 73 | struct CallOut 74 | { 75 | UaStatus callResult; 76 | UaStatusCodeArray inputArgumentResults; 77 | UaDiagnosticInfos inputArgumentDiagnosticInfos; 78 | UaVariantArray outputArguments; 79 | 80 | }; 81 | 82 | struct BrowseContext 83 | { 84 | /* TODO */ 85 | }; 86 | 87 | 88 | namespace UaClient 89 | { 90 | 91 | enum ServerStatus 92 | { 93 | 94 | }; 95 | 96 | } 97 | 98 | class UaSessionCallback 99 | { 100 | 101 | }; 102 | 103 | class UaSession 104 | { 105 | public: 106 | UaSession (); 107 | ~UaSession (); 108 | 109 | UaStatus connect( 110 | const UaString& endpoint, 111 | const SessionConnectInfo& connectInfo, 112 | const SessionSecurityInfo& securityInfo, 113 | UaSessionCallback* callback); 114 | 115 | UaStatus read( 116 | ServiceSettings & serviceSettings, 117 | OpcUa_Double maxAge, 118 | OpcUa_TimestampsToReturn timeStamps, 119 | const UaReadValueIds & nodesToRead, 120 | UaDataValues & values, 121 | UaDiagnosticInfos & diagnosticInfos ); 122 | 123 | UaStatus write( 124 | ServiceSettings & serviceSettings, 125 | const UaWriteValues & nodesToWrite, 126 | UaStatusCodeArray & results, 127 | UaDiagnosticInfos & diagnosticInfos ); 128 | 129 | UaStatus call( 130 | ServiceSettings & serviceSettings, 131 | const CallIn & callRequest, 132 | CallOut & callResponse 133 | ); 134 | 135 | UaStatus disconnect( 136 | ServiceSettings & serviceSettings, 137 | OpcUa_Boolean deleteSubscriptions 138 | ); 139 | 140 | 141 | UaStatus browse( 142 | ServiceSettings& serviceSettings, 143 | const UaNodeId& nodeToBrowse, 144 | const BrowseContext& browseContext, 145 | UaByteString& continuationPoint, 146 | UaReferenceDescriptions& referenceDescriptions); 147 | 148 | 149 | private: 150 | UA_Client *m_client; 151 | std::mutex m_accessMutex; // used to make all UaSession's methods synchronized 152 | 153 | #ifdef OPCUA_2603 154 | void clientRunIterateThread(void); 155 | std::future m_clientRunIterateThreadFuture; 156 | std::atomic m_clientRunIterateToggle; 157 | #endif 158 | 159 | }; 160 | 161 | } 162 | 163 | 164 | 165 | #endif /* INCLUDE_UACLIENT_UASESSION_H_ */ 166 | -------------------------------------------------------------------------------- /include/uadatavalue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uadatavalue.h 3 | * 4 | * Created on: 27 Nov 2017 5 | * Author: pnikiel 6 | */ 7 | 8 | #ifndef INCLUDE_UADATAVALUE_H_ 9 | #define INCLUDE_UADATAVALUE_H_ 10 | 11 | #include 12 | 13 | #include 14 | 15 | class UaDataValue 16 | { 17 | public: 18 | UaDataValue( const UaVariant& variant, OpcUa_StatusCode statusCode, const UaDateTime& serverTime, const UaDateTime& sourceTime ); 19 | UaDataValue( const UaDataValue& other ); 20 | void operator=(const UaDataValue& other ); 21 | bool operator==(const UaDataValue &other) const; 22 | bool operator!=(const UaDataValue &other) const; 23 | 24 | ~UaDataValue (); 25 | 26 | const UA_DataValue* impl() const { return m_impl; } 27 | const UA_Variant* value() const{ return &m_impl->value; } 28 | 29 | OpcUa_StatusCode statusCode() const { return m_impl->status; } 30 | 31 | UaDataValue clone(); // can't be const because of synchronization 32 | 33 | private: 34 | UA_DataValue *m_impl; 35 | 36 | //! The locking done here is to let UaDataValue be concurrently used from multiple threads 37 | // (e.g. network stack for monitoring and a quasar server "above" to publish) to make up for the UASDK behaviour. 38 | std::mutex m_lock; 39 | 40 | 41 | 42 | }; 43 | 44 | #endif /* INCLUDE_UADATAVALUE_H_ */ 45 | -------------------------------------------------------------------------------- /include/uadatavariablecache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uadatavariablecache.h 3 | * 4 | * Created on: May 1, 2017 5 | * Author: pnikiel 6 | */ 7 | 8 | #ifndef OPEN62541_COMPAT_INCLUDE_UADATAVARIABLECACHE_H_ 9 | #define OPEN62541_COMPAT_INCLUDE_UADATAVARIABLECACHE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | class UaPropertyMethodArgument: public UaNode 20 | { 21 | 22 | 23 | public: 24 | 25 | enum ArgumentType 26 | { 27 | INARGUMENTS, 28 | OUTARGUMENTS 29 | }; 30 | 31 | UaPropertyMethodArgument ( 32 | const UaNodeId &nodeId, 33 | OpcUa_Byte accessLevel, 34 | OpcUa_UInt32 numberOfArguments, 35 | ArgumentType argumentType); 36 | 37 | virtual UaNodeId nodeId() const override { return m_nodeId; } 38 | virtual UaNodeId typeDefinitionId() const override { return UaNodeId(UA_NS0ID_BASEDATAVARIABLETYPE,0); } 39 | virtual OpcUa_NodeClass nodeClass() const override { return OpcUa_NodeClass_Variable; } 40 | virtual UaQualifiedName browseName() const override { return m_browseName; } 41 | 42 | OpcUa_StatusCode setArgument ( 43 | OpcUa_UInt32 index, 44 | const UaString & name, 45 | const UaNodeId & dataType, 46 | OpcUa_Int32 valueRank, 47 | const UaUInt32Array & arrayDimensions, 48 | const UaLocalizedText & description 49 | ) ; 50 | 51 | // returns UA_Argument per given argument in this property 52 | const UA_Argument& implArgument (unsigned int index) const; 53 | 54 | unsigned int numArguments () const { return m_numberArguments; } 55 | 56 | ArgumentType argumentType () const { return m_argumentType; } 57 | 58 | private: 59 | const UaNodeId m_nodeId; 60 | const unsigned int m_numberArguments; 61 | const UaQualifiedName m_browseName; 62 | UA_Argument ** m_impl; 63 | const ArgumentType m_argumentType; 64 | 65 | }; 66 | 67 | class UaPropertyCache: public UaNode 68 | { 69 | public: 70 | UaPropertyCache ( 71 | const UaString &name, 72 | const UaNodeId &nodeId, 73 | const UaVariant &defaultValue, 74 | OpcUa_Byte accessLevel, 75 | const UaString& defaultLocaleId); 76 | 77 | virtual UaNodeId nodeId() const override { return m_nodeId; } 78 | virtual UaNodeId typeDefinitionId() const override { return m_typeDefinitionId; } 79 | virtual OpcUa_NodeClass nodeClass() const override { return OpcUa_NodeClass_Variable; } 80 | virtual UaQualifiedName browseName() const override { return m_browseName; } 81 | virtual UaDataValue value(Session* session) { return UaDataValue(m_value, OpcUa_Good, UaDateTime::now(), UaDateTime::now()); } 82 | 83 | private: 84 | const UaNodeId m_nodeId; 85 | const UaQualifiedName m_browseName; 86 | const UaVariant m_value; 87 | const UaNodeId m_typeDefinitionId; 88 | }; 89 | 90 | #endif /* OPEN62541_COMPAT_INCLUDE_UADATAVARIABLECACHE_H_ */ 91 | -------------------------------------------------------------------------------- /include/uadatetime.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __UADATETIME_H_ 23 | #define __UADATETIME_H_ 24 | 25 | #include 26 | #include 27 | 28 | class UaDateTime 29 | { 30 | public: 31 | UaDateTime(); 32 | UaDateTime(const UA_DateTime& dateTime); 33 | 34 | static UaDateTime now(); 35 | 36 | void addSecs(int secs); 37 | void addMilliSecs(int msecs); 38 | OpcUa_Int32 secsTo(const UaDateTime&) const; 39 | 40 | static UaDateTime fromString(const UaString&); 41 | UaString toString() const; 42 | explicit operator UA_DateTime() const {return m_dateTime;}; 43 | 44 | private: 45 | 46 | 47 | UA_DateTime m_dateTime; // (64bit signed int ) num of 100 nanosec intervals since windows epoch (1601-01-01T00:00:00) 48 | }; 49 | 50 | #endif // __UADATETIME_H_ 51 | -------------------------------------------------------------------------------- /include/uaexpandednodeid.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2020. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 08 Oct, 2020 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | #ifndef __UAEXPANDEDNODEID_H__ 22 | #define __UAEXPANDEDNODEID_H__ 23 | 24 | #include 25 | 26 | // Note from Piotr 27 | // There are many ways how ExpandedNodeId could be conceived -- 28 | // In the style of open62541-compat it simply should be a wrapper on top of UA_ExpandedNodeId, 29 | // But it's difficult to judge how that would affect API etc. So now we have sth simple that conforms for UA-SDK API, 30 | // And then "we will see" if to remap the implementation. 31 | 32 | class UaExpandedNodeId 33 | { 34 | public: 35 | UaExpandedNodeId () {}; 36 | 37 | UaExpandedNodeId ( 38 | const UaNodeId &id, 39 | const UaString &sNsUri, 40 | OpcUa_UInt32 serverIndex) : 41 | m_nodeId (id) 42 | {} 43 | 44 | UaNodeId nodeId() const { return m_nodeId; } 45 | 46 | private: 47 | UaNodeId m_nodeId; // might drift towards either o6 "m_imp" style, or might be supplemented by ns URL ... 48 | 49 | }; 50 | 51 | #endif // __UAEXPANDEDNODEID_H__ 52 | -------------------------------------------------------------------------------- /include/uanode.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __UANODE_H__ 23 | #define __UANODE_H__ 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | 32 | 33 | class UaNode 34 | { 35 | public: 36 | UaNode(); 37 | virtual ~UaNode() {} 38 | 39 | virtual UaNodeId nodeId() const = 0; 40 | 41 | virtual UaQualifiedName browseName() const = 0; 42 | virtual UaNodeId typeDefinitionId() const = 0; 43 | virtual OpcUa_NodeClass nodeClass() const = 0; 44 | 45 | struct ReferencedTarget 46 | { 47 | UaNode* target; 48 | UaNodeId referenceTypeId; 49 | ReferencedTarget( UaNode* aTarget, const UaNodeId& referencedtarget ): target(aTarget), referenceTypeId(referencedtarget) {} 50 | }; 51 | 52 | void releaseReference() {} // TODO: ?? 53 | 54 | void addReferencedTarget( UaNode* targetNode, UaNodeId referenceTypeId ) { m_referenceTargets.push_back( ReferencedTarget(targetNode, referenceTypeId)); } 55 | const std::list* referencedTargets() const { return &m_referenceTargets; } 56 | private: 57 | std::list m_referenceTargets; 58 | 59 | 60 | }; 61 | 62 | typedef UaNode UaReferenceLists; 63 | 64 | #endif // __UANODE_H__ 65 | -------------------------------------------------------------------------------- /include/uanodeid.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __UANODEID_H__ 23 | #define __UANODEID_H__ 24 | 25 | 26 | #include 27 | #include 28 | 29 | //TODO: switch for amalgamation 30 | #include 31 | 32 | enum IdentifierType 33 | { 34 | OpcUa_IdentifierType_Numeric = UA_NodeIdType::UA_NODEIDTYPE_NUMERIC, 35 | OpcUa_IdentifierType_String = UA_NodeIdType::UA_NODEIDTYPE_STRING 36 | }; 37 | 38 | 39 | class UaNodeId 40 | { 41 | public: 42 | //! Create the default - ns=0, numeric=0 - as per UA-SDK. 43 | UaNodeId (); 44 | 45 | //! Create string address 46 | UaNodeId ( const UaString& stringAddress, OpcUa_UInt16 ns); 47 | 48 | //! Create numeric address 49 | UaNodeId ( OpcUa_UInt32 numericAddress, OpcUa_UInt16 ns=0); 50 | 51 | UaNodeId ( const UaNodeId& other); 52 | UaNodeId ( const UA_NodeId& other); 53 | ~UaNodeId (); 54 | 55 | const UaNodeId& operator=(const UaNodeId & other); 56 | unsigned int namespaceIndex() const { return m_impl.namespaceIndex; } 57 | UaString identifierString() const; 58 | unsigned int identifierNumeric() const { return m_impl.identifier.numeric; } 59 | IdentifierType identifierType() const; 60 | UaString toString() const; 61 | UaString toFullString() const; 62 | //! Return Implementation specific data. Note: the data pointed to in the pointers hidden in the structure are valid as long as this object is alive and shall be regarded const. 63 | UA_NodeId impl() const { return m_impl; } 64 | const UA_NodeId* pimpl() const { return &m_impl; } 65 | 66 | void copyTo( UA_NodeId* other) const; 67 | void copyTo( UaNodeId* other) const; 68 | bool operator==(const UaNodeId& other) const; 69 | private: 70 | /* UaString m_stringId; */ 71 | UA_NodeId m_impl; 72 | 73 | }; 74 | 75 | 76 | 77 | #endif // __UANODEID_H__ 78 | -------------------------------------------------------------------------------- /include/uaplatformlayer.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * uaplatformlayer.h 3 | * 4 | * Created on: 29 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_UAPLATFORMLAYER_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_UAPLATFORMLAYER_H_ 24 | 25 | 26 | namespace UaPlatformLayer 27 | { 28 | void init() {}; // this obviously is a fake 29 | } 30 | 31 | 32 | #endif /* OPEN62541_COMPAT_INCLUDE_UAPLATFORMLAYER_H_ */ 33 | -------------------------------------------------------------------------------- /include/uaserver.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2019. All rights not expressly granted are reserved. 2 | * uaserver.h 3 | * 4 | * Created on: 29 Nov 2019 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef OPEN62541_COMPAT_INCLUDE_UASERVER_H_ 23 | #define OPEN62541_COMPAT_INCLUDE_UASERVER_H_ 24 | 25 | #include 26 | #include // for std::function 27 | 28 | #include 29 | 30 | // forward decls from open62541 31 | struct UA_Server; 32 | struct UA_ServerConfig; 33 | 34 | class UaServer 35 | { 36 | public: 37 | UaServer(); 38 | ~UaServer(); 39 | 40 | void setServerConfig(const UaString& configurationFile, const UaString& applicationPath); 41 | 42 | void addNodeManager(NodeManagerBase* pNodeManager); 43 | 44 | void linkRunningFlag (volatile OpcUa_Boolean* flag); 45 | 46 | //! Will start the server (in a separate thread). Non-blocking. 47 | void start(); 48 | 49 | //! Will stop the server, if running. Blocking. 50 | void stop(); 51 | 52 | 53 | private: 54 | UA_Server *m_server; 55 | NodeManagerBase* m_nodeManager; 56 | std::thread m_open62541_server_thread; 57 | 58 | volatile OpcUa_Boolean* m_runningFlag; 59 | 60 | void runThread(); 61 | 62 | unsigned int m_endpointPortNumber; 63 | }; 64 | 65 | #endif /* OPEN62541_COMPAT_INCLUDE_UASERVER_H_ */ 66 | -------------------------------------------------------------------------------- /include/uastring.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * 6 | * This file is part of Quasar. 7 | * 8 | * Quasar is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public Licence as published by 10 | * the Free Software Foundation, either version 3 of the Licence. 11 | * 12 | * Quasar is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public Licence for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Quasar. If not, see . 19 | */ 20 | 21 | 22 | #ifndef __UASTRING_H_ 23 | #define __UASTRING_H_ 24 | 25 | //TODO: amalgamate? 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | class UaString 33 | { 34 | //! NOTE: All constructors allocate memory for new string's data. There is no memory reuse of any kind. 35 | public: 36 | //! Constructs null string 37 | UaString (); 38 | //! From zero-terminated string; length taken by strlen 39 | UaString( const char* s); 40 | //! From another UaString 41 | UaString( const UaString& other ); 42 | //! From UA_String (open6xxxx) 43 | UaString( const UA_String* other ); 44 | 45 | UaString( const UA_String& other ): UaString(&other) {} 46 | 47 | //! Assignment operator 48 | const UaString& operator=(const UaString& other); 49 | 50 | const UaString& operator=(const UA_String& other); 51 | 52 | ~UaString (); 53 | 54 | UaString operator+(const UaString& other); 55 | bool operator==(const UaString& other); 56 | 57 | std::string toUtf8() const; 58 | 59 | const UA_String * impl() const{ return m_impl; } 60 | 61 | UA_String* toOpcUaString() const { return m_impl; } 62 | 63 | void detach(UaString* out); 64 | 65 | size_t length() const { return m_impl->length; /*FIXME: open62541 seems not UTF-8 aware so handle this we caution!*/ } 66 | void copyTo( UaString * output ) const { *output = *this; } 67 | 68 | private: 69 | UA_String * m_impl; 70 | }; 71 | 72 | #endif // __UASTRING_H_ 73 | -------------------------------------------------------------------------------- /include/uavariant.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * 3 | * Created on: 15 Nov, 2015 4 | * Author: Piotr Nikiel 5 | * Author: bfarnham 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __UAVARIANT_H__ 24 | #define __UAVARIANT_H__ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | enum OpcUaType 35 | { 36 | 37 | OpcUaType_Null = 0, 38 | OpcUaType_Boolean = UA_NS0ID_BOOLEAN, 39 | OpcUaType_SByte = UA_NS0ID_SBYTE, 40 | OpcUaType_Byte = UA_NS0ID_BYTE, 41 | OpcUaType_Int16 = UA_NS0ID_INT16, 42 | OpcUaType_UInt16 = UA_NS0ID_UINT16, 43 | OpcUaType_Int32 = UA_NS0ID_INT32, 44 | OpcUaType_UInt32 = UA_NS0ID_UINT32, 45 | OpcUaType_Int64 = UA_NS0ID_INT64, 46 | OpcUaType_UInt64 = UA_NS0ID_UINT64, 47 | OpcUaType_Float = UA_NS0ID_FLOAT, 48 | OpcUaType_Double = UA_NS0ID_DOUBLE, 49 | OpcUaType_String = UA_NS0ID_STRING, 50 | // support for datetime and guid missing in the compat module 51 | OpcUaType_ByteString = UA_NS0ID_BYTESTRING, 52 | OpcUaType_Variant = UA_NS0ID_BASEDATATYPE 53 | // support for remaining types, i.e. nodeid or statuscode also still missing 54 | }; 55 | 56 | class UaVariant 57 | { 58 | public: 59 | UaVariant (); 60 | UaVariant( const UaVariant& other); 61 | void operator= (const UaVariant &other); 62 | bool operator==(const UaVariant&) const; 63 | UaVariant( const UA_Variant& other ); 64 | 65 | UaVariant( const UaString& v ); 66 | UaVariant( OpcUa_UInt32 v ); 67 | UaVariant( OpcUa_Int32 v ); 68 | UaVariant( OpcUa_UInt64 v ); 69 | UaVariant( OpcUa_Int64 v ); 70 | UaVariant( OpcUa_Float v ); 71 | UaVariant( OpcUa_Double v ); 72 | UaVariant( OpcUa_Boolean v ); 73 | UaVariant( const UaByteString& v ); 74 | 75 | 76 | ~UaVariant(); 77 | OpcUaType type() const; 78 | 79 | // setters 80 | void setBool( OpcUa_Boolean value ); 81 | void setByte( OpcUa_Byte value ); 82 | void setSByte( OpcUa_SByte value ); 83 | void setInt16( OpcUa_Int16 value ); 84 | void setUInt16( OpcUa_UInt16 value ); 85 | void setInt32( OpcUa_Int32 value ); 86 | void setUInt32( OpcUa_UInt32 value ); 87 | void setInt64( OpcUa_Int64 value ); 88 | void setUInt64( OpcUa_UInt64 value ); 89 | 90 | void setFloat( OpcUa_Float value ); 91 | void setDouble( OpcUa_Double value ); 92 | 93 | void setString( const UaString& value ); 94 | 95 | void setByteString( const UaByteString& value, bool detach); 96 | 97 | void setBoolArray( UaBooleanArray& val, OpcUa_Boolean bDetach = OpcUa_False); 98 | void setSByteArray( UaSByteArray& val, OpcUa_Boolean bDetach = OpcUa_False); 99 | void setByteArray( UaByteArray& val, OpcUa_Boolean bDetach = OpcUa_False ); 100 | void setInt16Array( UaInt16Array& val, OpcUa_Boolean bDetach = OpcUa_False); 101 | void setUInt16Array( UaUInt16Array& val, OpcUa_Boolean bDetach = OpcUa_False ); 102 | void setInt32Array( UaInt32Array& val, OpcUa_Boolean bDetach = OpcUa_False); 103 | void setUInt32Array( UaUInt32Array& val, OpcUa_Boolean bDetach = OpcUa_False ); 104 | void setInt64Array( UaInt64Array& val, OpcUa_Boolean bDetach = OpcUa_False); 105 | void setUInt64Array( UaUInt64Array& val, OpcUa_Boolean bDetach = OpcUa_False ); 106 | void setFloatArray( UaFloatArray& val, OpcUa_Boolean bDetach = OpcUa_False); 107 | void setDoubleArray( UaDoubleArray& val, OpcUa_Boolean bDetach = OpcUa_False ); 108 | void setStringArray( UaStringArray& val, OpcUa_Boolean bDetach = OpcUa_False ); 109 | void setByteStringArray( UaByteStringArray& val, OpcUa_Boolean bDetach = OpcUa_False ); 110 | void setVariantArray( UaVariantArray& val, OpcUa_Boolean bDetach = OpcUa_False ); 111 | 112 | void clear (); 113 | 114 | 115 | 116 | // getters 117 | UaStatus toBool( OpcUa_Boolean& value) const; 118 | UaStatus toInt16( OpcUa_Int16& value) const; 119 | UaStatus toUInt16( OpcUa_UInt16& value) const; 120 | UaStatus toInt32( OpcUa_Int32& value ) const; 121 | UaStatus toUInt32( OpcUa_UInt32& value ) const; 122 | UaStatus toInt64( OpcUa_Int64& value ) const; 123 | UaStatus toByte(OpcUa_Byte& value ) const; 124 | UaStatus toSByte(OpcUa_SByte& value ) const; 125 | UaStatus toUInt64( OpcUa_UInt64& value ) const; 126 | UaStatus toFloat( OpcUa_Float& value ) const; 127 | UaStatus toDouble( OpcUa_Double& value ) const; 128 | UaStatus toByteString( UaByteString& value) const; 129 | 130 | UaString toString( ) const; 131 | UaString toFullString() const; 132 | 133 | OpcUa_StatusCode toBoolArray( UaBooleanArray& out ) const; 134 | OpcUa_StatusCode toSByteArray( UaSByteArray& out ) const; 135 | OpcUa_StatusCode toByteArray( UaByteArray& out ) const; 136 | OpcUa_StatusCode toInt16Array( UaInt16Array& out ) const; 137 | OpcUa_StatusCode toUInt16Array( UaUInt16Array& out ) const; 138 | OpcUa_StatusCode toInt32Array( UaInt32Array& out ) const; 139 | OpcUa_StatusCode toUInt32Array( UaUInt32Array& out ) const; 140 | OpcUa_StatusCode toInt64Array( UaInt64Array& out ) const; 141 | OpcUa_StatusCode toUInt64Array( UaUInt64Array& out ) const; 142 | OpcUa_StatusCode toFloatArray( UaFloatArray& out ) const; 143 | OpcUa_StatusCode toDoubleArray( UaDoubleArray& out ) const; 144 | OpcUa_StatusCode toStringArray( UaStringArray& out) const; 145 | OpcUa_StatusCode toByteStringArray( UaByteStringArray& out) const; 146 | OpcUa_StatusCode toVariantArray( UaVariantArray& out) const; 147 | 148 | // copy-To has a signature with UaVariant however it should be the stack type. This is best effort compat we can get at the moment. (pnikiel) 149 | UaStatus copyTo ( UaVariant* to ) const { *to = UaVariant( *m_impl ); return OpcUa_Good; } 150 | UaStatus copyTo ( UA_Variant* to) const; 151 | 152 | const UA_Variant* impl() const { return m_impl; } 153 | 154 | void arrayDimensions( UaUInt32Array &arrayDimensions ) const; 155 | OpcUa_Boolean isArray () const; 156 | /* For 1D arrays it should return the actual size. For higher dimensions it should return total number of elements. */ 157 | OpcUa_Int32 arraySize () const; 158 | 159 | OpcUa_Boolean isEmpty () const; 160 | 161 | private: 162 | static UA_Variant* createAndCheckOpen62541Variant(); 163 | static void destroyOpen62541Variant(UA_Variant* open62541Variant); 164 | 165 | UA_Variant * m_impl; 166 | //! Will assign a supplied newValue to the variant's value. If possible (matching old/new types) a realloc is avoided. 167 | void reuseOrRealloc( const UA_DataType* dataType, void* newValue ); 168 | 169 | template 170 | void set1DArray( const UA_DataType* dataType, const ArrayType& input ); 171 | 172 | template 173 | void set1DArrayComplexTypes( 174 | const UA_DataType* dataType, 175 | const ArrayType& input, 176 | UA_StatusCode(*copyFunction)(const StackType* from, StackType* to)); 177 | 178 | //! Will convert stored value to a simple type, if possible 179 | template 180 | UaStatus toSimpleType( const UA_DataType* targetDataType, T* out ) const; 181 | 182 | template 183 | UaStatus convertNumericType(TTargetNumericType* out ) const; 184 | 185 | bool isNumericType( const UA_DataType& dataType ) const; 186 | 187 | template 188 | OpcUa_StatusCode toArray( const UA_DataType* dataType, U& out) const; 189 | 190 | bool isScalarValue() const; 191 | }; 192 | 193 | 194 | 195 | #endif // __UAVARIANT_H__ 196 | -------------------------------------------------------------------------------- /src/logit_logger.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * logit_logger.cpp 3 | * 4 | * Created on: May 20, 2021 5 | * Author: pnikiel 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | static Log::LogComponentHandle logItComponentHandle = Log::INVALID_HANDLE; 12 | 13 | void initializeOpen62541LogIt (Log::LOG_LEVEL logLevel) 14 | { 15 | // register LogIt component for open62541 16 | Log::LogComponentHandle handle = Log::getComponentHandle("open62541"); 17 | if (handle == Log::INVALID_HANDLE) 18 | { 19 | logItComponentHandle = Log::registerLoggingComponent("open62541", logLevel); 20 | } 21 | } 22 | 23 | static void logFromOpen62541 ( 24 | void *logContext, 25 | UA_LogLevel level, 26 | UA_LogCategory category, 27 | const char *msg, 28 | va_list args) 29 | { 30 | // translate open62541 log level into LogIt log level 31 | Log::LOG_LEVEL logItLogLevel; 32 | switch (level) 33 | { 34 | case UA_LOGLEVEL_DEBUG: logItLogLevel = Log::DBG; break; 35 | case UA_LOGLEVEL_ERROR: logItLogLevel = Log::ERR; break; 36 | case UA_LOGLEVEL_FATAL: logItLogLevel = Log::ERR; break; 37 | case UA_LOGLEVEL_INFO: logItLogLevel = Log::INF; break; 38 | case UA_LOGLEVEL_TRACE: logItLogLevel = Log::TRC; break; 39 | case UA_LOGLEVEL_WARNING: logItLogLevel = Log::WRN; break; 40 | default: logItLogLevel = Log::ERR; // just in case they added a new level. 41 | } 42 | 43 | auto open62541LogItHandle = Log::getComponentHandle("open62541"); 44 | if (open62541LogItHandle == Log::INVALID_HANDLE) return; 45 | 46 | Log::LOG_LEVEL userLogLevel = Log::INF; 47 | if (!Log::getComponentLogLevel(open62541LogItHandle, userLogLevel)) return; 48 | 49 | if (userLogLevel > logItLogLevel) return; 50 | 51 | // translate open62541 category. 52 | std::string categoryStr ("category_unknown"); 53 | switch (category) 54 | { 55 | case UA_LOGCATEGORY_CLIENT: categoryStr = "client"; break; 56 | case UA_LOGCATEGORY_NETWORK: categoryStr = "network"; break; 57 | case UA_LOGCATEGORY_SECURECHANNEL: categoryStr = "securechannel"; break; 58 | case UA_LOGCATEGORY_SECURITYPOLICY: categoryStr = "securitypolicy"; break; 59 | case UA_LOGCATEGORY_SERVER: categoryStr = "server"; break; 60 | case UA_LOGCATEGORY_SESSION: categoryStr = "session"; break; 61 | case UA_LOGCATEGORY_USERLAND: categoryStr = "userland"; break; 62 | } 63 | char line [1024] = {0}; 64 | vsnprintf(line, sizeof line-1, msg, args); 65 | LOG(logItLogLevel, logItComponentHandle) << categoryStr << ": " << line; 66 | } 67 | 68 | UA_Logger theLogItLogger = 69 | { 70 | &logFromOpen62541, 71 | nullptr, 72 | nullptr 73 | }; 74 | -------------------------------------------------------------------------------- /src/opcua_basedatavariabletype.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * opcua_basedatavariabletype.cpp 3 | * 4 | * Created on: 12 Jun 2018 (by splitting open62541_compat.cpp) 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | namespace OpcUa 25 | { 26 | 27 | BaseDataVariableType::BaseDataVariableType( 28 | const UaNodeId& nodeId, 29 | const UaString& name, 30 | OpcUa_UInt16 browseNameNameSpaceIndex, 31 | const UaVariant& initialValue, 32 | OpcUa_Byte accessLevel, 33 | NodeManagerConfig* pNodeConfig, 34 | UaMutexRefCounted* pSharedMutex): 35 | 36 | m_browseName( browseNameNameSpaceIndex, name), 37 | m_currentValue( initialValue, OpcUa_Good, UaDateTime::now(), UaDateTime::now() ), 38 | m_nodeId (nodeId), 39 | m_typeDefinitionId( OpcUaType_Variant, 0), 40 | m_valueRank(-1), // by default: scalar 41 | m_accessLevel(accessLevel) 42 | 43 | { 44 | 45 | } 46 | 47 | 48 | UaStatus BaseDataVariableType::setValue( 49 | Session *session, 50 | const UaDataValue& dataValue, 51 | OpcUa_Boolean checkAccessLevel 52 | ) 53 | { 54 | if (!checkAccessLevel || (m_accessLevel & UA_ACCESSLEVELMASK_WRITE)) 55 | { 56 | m_currentValue = dataValue; 57 | return OpcUa_Good; 58 | } 59 | else 60 | return OpcUa_BadUserAccessDenied; 61 | 62 | } 63 | 64 | UaDataValue BaseDataVariableType::value(Session* session) 65 | { 66 | return m_currentValue.clone(); 67 | } 68 | 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/open62541_compat.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * open62541_compat.cpp 3 | * 4 | * Created on: 15 Nov, 2015 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | 29 | UaQualifiedName::UaQualifiedName(int ns, const UaString& name): 30 | m_unqualifiedName( name ) 31 | { 32 | m_impl.name = *m_unqualifiedName.impl(); 33 | m_impl.namespaceIndex = ns; 34 | } 35 | 36 | UaString UaQualifiedName::toString() const 37 | { 38 | return UaString(m_impl.name); 39 | } 40 | 41 | UaString UaQualifiedName::toFullString() const 42 | { 43 | std::ostringstream result; 44 | result << "ns="< 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | #include 17 | 18 | template 19 | static std::string toHexString (const T t) 20 | { 21 | std::ostringstream oss; 22 | oss << std::hex << (unsigned long)t << std::dec; 23 | return oss.str (); 24 | } 25 | 26 | /* 27 | * Stores the description of status codes that do not exist in open62541 and are used by quasar. 28 | */ 29 | std::vector UaStatus::s_statusCodeDescriptions { 30 | {OpcUa_Bad, "GenericBad"}, 31 | {OpcUa_Uncertain, "GenericUncertain"} 32 | }; 33 | 34 | UaString UaStatus::toString() const 35 | { 36 | 37 | std::string statusCodeDescription = UA_StatusCode_name(m_status); 38 | 39 | if ( statusCodeDescription == "Unknown StatusCode" ) 40 | { 41 | std::vector::iterator it = std::find_if(s_statusCodeDescriptions.begin(), s_statusCodeDescriptions.end(), [this](StatusCodeDescription &d){return d.statusCode==m_status;}); 42 | 43 | if ( it != s_statusCodeDescriptions.end()) 44 | statusCodeDescription = it->description; 45 | else if ( isBad() ) 46 | { 47 | statusCodeDescription="GenericBad StatusCode family"; 48 | } 49 | else if ( isUncertain() ) 50 | { 51 | statusCodeDescription="GenericUncertain StatusCode family"; 52 | } 53 | else 54 | statusCodeDescription="StatusCode was impossible to parse"; 55 | } 56 | 57 | statusCodeDescription.append(" (0x"+toHexString(m_status)+")"); 58 | 59 | return statusCodeDescription.c_str(); 60 | } 61 | 62 | bool UaStatus::isBad() const 63 | { 64 | return std::bitset<32>(m_status).test(31); // 31 ? BAD defines start at 0x8000000 (OPC-UA specification). 65 | } 66 | 67 | bool UaStatus::isUncertain() const 68 | { 69 | return std::bitset<32>(m_status).test(30); // 30 ? Uncertain defines start at 0x4000000 (OPC-UA specification). 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/uabytearray.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2018. All rights not expressly granted are reserved. 2 | * uabytearray.cpp 3 | * 4 | * Created on: 18 Apr 2018 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | UaByteArray::UaByteArray(): 25 | UaCompatArray() 26 | { 27 | } 28 | 29 | UaByteArray::UaByteArray(const char* data, unsigned int sz) 30 | { 31 | create(sz); 32 | std::copy(data, data+sz, m_data.begin()); 33 | } 34 | 35 | const char* UaByteArray::data() const 36 | { 37 | return this->size() > 0 ? reinterpret_cast (&m_data[0]) : 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/uabytestring.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * uabytestring.cpp 3 | * 4 | * Created on: Jan 26, 2017 5 | * Author: pnikiel 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | UaByteString::UaByteString () 17 | { 18 | m_impl = UA_ByteString_new(); 19 | if (!m_impl) 20 | throw alloc_error(); 21 | UA_ByteString_init(m_impl); 22 | } 23 | 24 | UaByteString::UaByteString( const UA_ByteString& other): 25 | UaByteString() 26 | { 27 | UaStatus status = UA_ByteString_copy(&other, m_impl); 28 | if (!status.isGood()) 29 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "UA_ByteString_copy failed: " + status.toString().toUtf8()); 30 | } 31 | 32 | UaByteString::UaByteString( const int length, const OpcUa_Byte* data): 33 | UaByteString() 34 | { 35 | try 36 | { 37 | setByteString( length, data ); 38 | } 39 | catch ( alloc_error &e) 40 | { 41 | release(); 42 | throw; 43 | } 44 | } 45 | 46 | UaByteString::UaByteString( const UaByteString& other ): 47 | UaByteString() 48 | { 49 | other.copyTo(this); 50 | } 51 | 52 | UaByteString::~UaByteString () 53 | { 54 | release(); 55 | if (m_impl) 56 | UA_ByteString_delete( m_impl ); 57 | m_impl = nullptr; 58 | } 59 | 60 | UaByteString& UaByteString::operator= (const UaByteString& other) 61 | { 62 | release(); 63 | other.copyTo(this); 64 | return *this; 65 | } 66 | 67 | void UaByteString::setByteString (const int len, const OpcUa_Byte *data) 68 | { 69 | release(); 70 | if (len>0) 71 | { 72 | m_impl->data = (UA_Byte*)malloc( len ); 73 | if (!m_impl->data) 74 | { 75 | throw alloc_error(); 76 | } 77 | memcpy( m_impl->data, data, len ); 78 | } 79 | m_impl->length = len; 80 | 81 | } 82 | 83 | OpcUa_Int32 UaByteString::length() const 84 | { 85 | if (m_impl->length > std::numeric_limits::max() ) 86 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "UaByteString::length() open62541 size too big for UASDK API") 87 | else 88 | return m_impl->length; 89 | } 90 | 91 | void UaByteString::copyTo(UaByteString* other) const 92 | { 93 | other->release(); 94 | UaStatus status = UA_ByteString_copy(m_impl, other->m_impl); 95 | if (!status.isGood()) 96 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "UA_ByteString_copy failed with: " + status.toString().toUtf8()); 97 | } 98 | 99 | void UaByteString::release() 100 | { 101 | if (m_impl->data) 102 | { 103 | UA_ByteString_clear( m_impl ); 104 | m_impl->data = nullptr; 105 | m_impl->length = 0; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/uaclient/uasession.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2017. All rights not expressly granted are reserved. 2 | * uasession.cpp 3 | * 4 | * Created on: 27 Nov, 2017 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | namespace UaClientSdk 38 | { 39 | 40 | UaSession::UaSession(): 41 | m_client(0) 42 | { 43 | 44 | } 45 | 46 | UaSession::~UaSession () 47 | { 48 | if (m_client) 49 | { 50 | ServiceSettings standardServiceSettings; 51 | this->disconnect( 52 | standardServiceSettings, 53 | /*delete subscriptions*/ OpcUa_True); 54 | } 55 | 56 | } 57 | 58 | #ifdef OPCUA_2603 59 | void UaSession::clientRunIterateThread(void) 60 | { 61 | 62 | while(m_clientRunIterateToggle) 63 | { 64 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 65 | UaStatus status = UA_Client_run_iterate(m_client, 1000); 66 | if( !status.isGood() ) 67 | { 68 | LOG(Log::ERR) << "in UaSession::clientRunIterateThread() " << status.toString().toUtf8(); 69 | } 70 | } 71 | 72 | } 73 | #endif 74 | 75 | UaStatus UaSession::connect( 76 | const UaString& endpoint, 77 | const SessionConnectInfo& connectInfo, 78 | const SessionSecurityInfo& securityInfo, 79 | UaSessionCallback* callback) 80 | { 81 | std::lock_guard lock (m_accessMutex); 82 | 83 | if (m_client) 84 | { 85 | LOG(Log::ERR) << "Connection already exists, can't call connect()"; 86 | return OpcUa_Bad; // Already connected! 87 | } 88 | m_client = UA_Client_new(); 89 | 90 | if (!m_client) 91 | throw alloc_error(); 92 | 93 | initializeOpen62541LogIt(); // safe to rerun 94 | UA_ClientConfig* clientConfig = UA_Client_getConfig(m_client); 95 | clientConfig->logger = theLogItLogger; 96 | 97 | UA_ClientConfig_setDefault(clientConfig); 98 | clientConfig->timeout = connectInfo.internalServiceCallTimeout; 99 | clientConfig->secureChannelLifeTime = connectInfo.nSecureChannelLifetime; 100 | clientConfig->requestedSessionTimeout = connectInfo.nSessionTimeout; 101 | // Look at OPCUA-2603 102 | // In cases where a long operation is taking place and the server max session timeout is reached 103 | // it is important that the client makes a periodic (2000ms) connectivy check 104 | clientConfig->connectivityCheckInterval = 2000; 105 | 106 | // TODO @Piotr note that many possibly important settings are not carried 107 | // from UA-SDK API to open6! At the moment, only timeout is. 108 | LOG(Log::DBG) << "Will connect to OPC-UA endpoint [" << endpoint.toUtf8().c_str() << "], " << 109 | "serviceCallTimeout=[" << clientConfig->timeout << "] ms, " << 110 | "requestedSessionTimeout=[" << clientConfig->requestedSessionTimeout << "] ms, " << 111 | "secureChannelLifeTime=[" << clientConfig->secureChannelLifeTime << "] ms, " << 112 | "connectivityCheckInterval=[" << clientConfig->connectivityCheckInterval << "] ms"; 113 | UaStatus status = UA_Client_connect(m_client, endpoint.toUtf8().c_str()); 114 | 115 | if(! status.isGood()) 116 | { 117 | UA_Client_delete(m_client); 118 | m_client = nullptr; 119 | LOG(Log::ERR) << "in UaSession::connect() " << status.toString().toUtf8(); 120 | return status; 121 | } 122 | 123 | #ifdef OPCUA_2603 124 | m_clientRunIterateToggle = true; 125 | m_clientRunIterateThreadFuture = std::async(std::launch::async, &UaSession::clientRunIterateThread, this); 126 | #endif 127 | 128 | return OpcUa_Good; 129 | } 130 | 131 | /** 132 | * TODO: serviceSettings, 133 | * TODO: deleteSubscriptions 134 | */ 135 | UaStatus UaSession::disconnect( 136 | ServiceSettings & serviceSettings, 137 | OpcUa_Boolean deleteSubscriptions 138 | ) 139 | { 140 | std::lock_guard lock (m_accessMutex); 141 | 142 | #ifdef OPCUA_2603 143 | m_clientRunIterateToggle = false; 144 | m_clientRunIterateThreadFuture.get(); 145 | #endif 146 | 147 | if (! m_client) 148 | { 149 | LOG(Log::WRN) << "Can't disconnect because not connected."; 150 | return OpcUa_BadInvalidState; // can't disconnect if not connected... 151 | } 152 | UaStatus status = UA_Client_disconnect(m_client); 153 | if (m_client) 154 | { 155 | UA_Client_delete(m_client); 156 | m_client = 0; 157 | } 158 | return status; 159 | } 160 | 161 | /** 162 | * What's not implemented: 163 | * - diagnostic infos (TODO) 164 | * - taking into account serviceSettings (TODO) 165 | * 166 | */ 167 | UaStatus UaSession::read( 168 | ServiceSettings & serviceSettings, 169 | OpcUa_Double maxAge, 170 | OpcUa_TimestampsToReturn timeStamps, 171 | const UaReadValueIds & nodesToRead, 172 | UaDataValues & values, 173 | UaDiagnosticInfos & diagnosticInfos ) 174 | { 175 | std::lock_guard lock (m_accessMutex); 176 | if (nodesToRead.size() != 1) 177 | { 178 | 179 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, 180 | "UaSession::read(): So far only single reads are supported, but you requested a read of " 181 | +boost::lexical_cast(nodesToRead.size())+" items. FIXME!"); 182 | // FIXME:implement this 183 | } 184 | 185 | LOG(Log::TRC) << "UaSession::read( nodesToRead=[" << nodesToRead[0].NodeId.toString().toUtf8() << "] )"; 186 | 187 | if (nodesToRead.size() != values.size()) 188 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, 189 | "Size of provided value holders (is " 190 | +boost::lexical_cast(values.size()) 191 | +" must match size of provided nodesToRead (is " 192 | +boost::lexical_cast(nodesToRead.size())); 193 | 194 | UA_ReadRequest readRequest; 195 | UA_ReadRequest_init(&readRequest); 196 | ManagedUaArray readValueIds (1, &UA_TYPES[UA_TYPES_READVALUEID]); 197 | readRequest.nodesToRead = readValueIds; 198 | readRequest.nodesToReadSize = 1; 199 | // The following should be safe because enum values are defined with open62541 defines 200 | readRequest.timestampsToReturn = (UA_TimestampsToReturn)timeStamps; 201 | readRequest.maxAge = maxAge; 202 | 203 | UA_NodeId_init(&readRequest.nodesToRead[0].nodeId); 204 | nodesToRead[0].NodeId.copyTo( &readRequest.nodesToRead[0].nodeId ); 205 | 206 | readRequest.nodesToRead[0].attributeId = nodesToRead[0].AttributeId; 207 | 208 | UA_ReadResponse readResponse = UA_Client_Service_read(m_client, readRequest); 209 | ManagedUaArray readResponseResults( readResponse.resultsSize, &UA_TYPES[UA_TYPES_DATAVALUE], readResponse.results); 210 | 211 | UaStatus serviceStatus = UaStatus(readResponse.responseHeader.serviceResult); 212 | 213 | if ( serviceStatus.isGood() ) 214 | { 215 | if (readResponse.resultsSize != nodesToRead.size()) 216 | { 217 | LOG(Log::ERR) << "after call to open62541: mismatch between requested size " 218 | << boost::lexical_cast(readRequest.nodesToReadSize) 219 | << " and returned size " 220 | << boost::lexical_cast(readResponse.resultsSize); 221 | return OpcUa_Bad; 222 | } 223 | for (size_t i=0; i lock (m_accessMutex); 262 | if (nodesToWrite.size() != 1) 263 | { 264 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, 265 | "UaSession::write(): So far only single writes are supported, but you requested a write of " 266 | +boost::lexical_cast(nodesToWrite.size())+" items. FIXME!"); 267 | // FIXME:implement this 268 | } 269 | 270 | UA_WriteRequest writeRequest; 271 | UA_WriteRequest_init( &writeRequest); 272 | 273 | writeRequest.nodesToWriteSize = nodesToWrite.size(); 274 | ManagedUaArray writeValues (nodesToWrite.size(), &UA_TYPES[UA_TYPES_WRITEVALUE]); 275 | writeRequest.nodesToWrite = writeValues; 276 | 277 | for (size_t i = 0; i statusCodes( writeResponse.resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE], writeResponse.results ); 291 | 292 | if (UaStatus(writeResponse.responseHeader.serviceResult).isGood()) 293 | { 294 | results.create( writeResponse.resultsSize ); 295 | for (size_t i=0; i lock (m_accessMutex); 317 | 318 | UA_CallMethodRequest methodCallRequest; 319 | UA_CallMethodRequest_init(&methodCallRequest); 320 | methodCallRequest.methodId = callIn.methodId.impl(); 321 | methodCallRequest.objectId = callIn.objectId.impl(); 322 | methodCallRequest.inputArgumentsSize = callIn.inputArguments.size(); 323 | ManagedUaArray inputArguments (callIn.inputArguments.size(), &UA_TYPES[UA_TYPES_VARIANT]); 324 | methodCallRequest.inputArguments = inputArguments; 325 | 326 | bool anyArgumentFailed = false; 327 | for (unsigned int i=0; i results ( // RAII holder for data allocated in o6, doesn't alloc anything. 352 | callResponse.resultsSize, 353 | &UA_TYPES[UA_TYPES_CALLMETHODRESULT], 354 | callResponse.results ); 355 | 356 | if (!UaStatus(callResponse.responseHeader.serviceResult).isGood()) 357 | { 358 | return callResponse.responseHeader.serviceResult; 359 | } 360 | 361 | callOut.inputArgumentDiagnosticInfos.create(0); 362 | callOut.inputArgumentResults.create(0); 363 | 364 | // there should be at least one callResponse result because we called one method 365 | if (callResponse.resultsSize != 1) 366 | OPEN62541_COMPAT_LOG_AND_THROW(std::logic_error, 367 | "One method called so expected one call response, but instead got: "+boost::lexical_cast(callResponse.resultsSize)+", open62541 error?"); 368 | 369 | UA_CallMethodResult *result = &callResponse.results[0]; 370 | 371 | callOut.outputArguments.create( result->outputArgumentsSize ); 372 | for (unsigned int i=0; ioutputArgumentsSize; ++i) 373 | { 374 | callOut.outputArguments[i] = result->outputArguments[i]; 375 | } 376 | 377 | callOut.callResult = callResponse.responseHeader.serviceResult; 378 | if (callOut.callResult.isGood()) 379 | callOut.callResult = callResponse.results[0].statusCode; // cast individual error as per OPCUA-1198 380 | 381 | return callOut.callResult; 382 | 383 | } 384 | 385 | UaStatus UaSession::browse( 386 | ServiceSettings& serviceSettings, 387 | const UaNodeId& nodeToBrowse, 388 | const BrowseContext& browseContext, 389 | UaByteString& continuationPoint, 390 | UaReferenceDescriptions& referenceDescriptions) 391 | { 392 | referenceDescriptions.clear(); 393 | 394 | UA_BrowseRequest browseRequest; 395 | UA_BrowseRequest_init(&browseRequest); 396 | 397 | browseRequest.nodesToBrowseSize = 1; 398 | browseRequest.nodesToBrowse = UA_BrowseDescription_new(); 399 | nodeToBrowse.copyTo(&browseRequest.nodesToBrowse[0].nodeId); 400 | browseRequest.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_FORWARD; // TODO!! Important!! This setting should come from BrowseContext! It might be an oversimplificatrion. 401 | browseRequest.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; 402 | 403 | UA_BrowseResponse browseResponse; 404 | UA_BrowseResponse_init(&browseResponse); 405 | 406 | browseResponse = UA_Client_Service_browse(m_client, browseRequest); 407 | UaStatus serviceResult (browseResponse.responseHeader.serviceResult); 408 | 409 | UaStatus finalStatusCode = serviceResult; // might change into more specific one when parsing results 410 | 411 | if (UaStatus(browseResponse.responseHeader.serviceResult).isGood()) 412 | { 413 | LOG(Log::TRC) << "After browse (was OK): resultsSize= " << browseResponse.resultsSize; 414 | if (browseResponse.resultsSize == 1) // we asked to browse one node, so should get one result. 415 | { 416 | UA_BrowseResult& br = browseResponse.results[0]; 417 | LOG(Log::DBG) << "Browse result 0, references size: " << br.referencesSize; 418 | referenceDescriptions.create(br.referencesSize); 419 | for (size_t j=0; j < br.referencesSize; j++) 420 | { 421 | UA_ReferenceDescription& rd = br.references[j]; 422 | LOG(Log::DBG) << "... ref #" << j << ": " << 423 | "isForward=" << rd.isForward << ", " << 424 | "refTypeId=" << UaNodeId(rd.referenceTypeId).toString().toUtf8() << ", " << 425 | "browseName=" << UaString(rd.browseName.name).toUtf8(); 426 | // populate the UA-SDK counter-part now 427 | referenceDescriptions[j].IsForward = rd.isForward; 428 | referenceDescriptions[j].ReferenceTypeId = rd.referenceTypeId; 429 | referenceDescriptions[j].NodeId = UaExpandedNodeId( 430 | rd.nodeId.nodeId, 431 | rd.nodeId.namespaceUri, 432 | rd.nodeId.serverIndex); 433 | referenceDescriptions[j].BrowseName = rd.browseName.name; 434 | referenceDescriptions[j].NodeClass = safeConvertNodeClassToSdk(rd.nodeClass); 435 | referenceDescriptions[j].TypeDefinition = UaExpandedNodeId( 436 | rd.typeDefinition.nodeId, 437 | rd.typeDefinition.namespaceUri, 438 | rd.typeDefinition.serverIndex); 439 | } 440 | } 441 | else 442 | { 443 | LOG(Log::ERR) << "Unexpected result size: " << browseResponse.resultsSize << ", expected was 1"; 444 | finalStatusCode = UA_STATUSCODE_BADUNKNOWNRESPONSE; 445 | } 446 | 447 | } 448 | else 449 | { 450 | LOG(Log::ERR) << "Error: the open62541 browse call on node " << nodeToBrowse.toString().toUtf8() << 451 | " returned bad status: " << serviceResult.toString().toUtf8(); 452 | } 453 | 454 | UA_BrowseRequest_clear(&browseRequest); 455 | UA_BrowseResponse_clear(&browseResponse); 456 | 457 | return finalStatusCode; 458 | } 459 | 460 | 461 | } 462 | -------------------------------------------------------------------------------- /src/uadatavalue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * uadatavalue.cpp 3 | * 4 | * Created on: 27 Nov 2017 5 | * Author: pnikiel 6 | * 7 | * This code used to live in open62541_compat.cpp since the beginning. 8 | * Now moved to this separate file for easier maintenance and separation 9 | * of concerns. 10 | */ 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | UaDataValue::UaDataValue( const UaVariant& variant, OpcUa_StatusCode statusCode, const UaDateTime& serverTime, const UaDateTime& sourceTime ) 19 | { 20 | m_impl = UA_DataValue_new (); 21 | if (!m_impl) 22 | OPEN62541_COMPAT_LOG_AND_THROW( 23 | std::runtime_error, 24 | "UA_DataValue_new returned null ptr" ); 25 | 26 | // TODO: duplicate the variant 27 | UA_Variant_copy( variant.impl(), &m_impl->value ); 28 | LOG(Log::TRC) << "After UA_Variant_copy: src="< lock(m_lock); 55 | if (m_impl) 56 | { 57 | UA_DataValue_clear (m_impl); 58 | UA_DataValue_delete( m_impl ); 59 | m_impl = 0; 60 | } 61 | m_impl = UA_DataValue_new (); 62 | // LOG(Log::INF) << "allocated new UA_DataValue @ " << m_impl; 63 | UA_DataValue_copy( other.m_impl, m_impl ); 64 | 65 | } 66 | 67 | bool UaDataValue:: operator==(const UaDataValue &other) const 68 | { 69 | if(this == &other) return true; 70 | if(m_impl->status == other.m_impl->status && 71 | m_impl->serverTimestamp == other.m_impl->serverTimestamp && 72 | m_impl->sourceTimestamp == other.m_impl->sourceTimestamp) 73 | { 74 | // compare values - apparently no direct open62541 comparator, so, compare via compat API 75 | return UaVariant(m_impl->value) == UaVariant(other.m_impl->value); 76 | } 77 | 78 | return false; 79 | } 80 | 81 | bool UaDataValue:: operator!=(const UaDataValue &other) const 82 | { 83 | return !(*this == other); 84 | } 85 | 86 | UaDataValue UaDataValue::clone() 87 | { 88 | std::lock_guard lock(m_lock); 89 | UaDataValue aCopy ( *this ); 90 | return aCopy; 91 | 92 | } 93 | 94 | UaDataValue:: ~UaDataValue () 95 | { 96 | if (m_impl) 97 | { 98 | UA_DataValue_clear( m_impl ); 99 | UA_DataValue_delete( m_impl ); 100 | m_impl = 0; 101 | } 102 | 103 | } 104 | 105 | 106 | -------------------------------------------------------------------------------- /src/uadatavariablecache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * uadatavariablecache.cpp 3 | * 4 | * Created on: May 1, 2017 5 | * Author: pnikiel 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | 14 | UaPropertyMethodArgument::UaPropertyMethodArgument ( 15 | const UaNodeId &nodeId, 16 | OpcUa_Byte accessLevel, 17 | OpcUa_UInt32 numberOfArguments, 18 | ArgumentType argumentType): 19 | m_nodeId(nodeId), 20 | m_numberArguments( numberOfArguments ), 21 | m_browseName(0, "args"), 22 | m_impl( new UA_Argument* [ numberOfArguments] ), 23 | m_argumentType(argumentType) 24 | { 25 | 26 | for (unsigned int i=0; i= m_numberArguments) 41 | return OpcUa_BadInvalidArgument; // TODO more refined error code 42 | 43 | 44 | m_impl[index]->dataType = dataType.impl(); 45 | 46 | if( UA_String_copy(name.impl(), &m_impl[index]->name) != OpcUa_Good ) 47 | return OpcUa_Bad; 48 | m_impl[index]->valueRank = valueRank; 49 | 50 | return OpcUa_Good; 51 | 52 | } 53 | 54 | const UA_Argument& UaPropertyMethodArgument::implArgument (unsigned int index) const 55 | { 56 | if (index >= m_numberArguments) 57 | OPEN62541_COMPAT_LOG_AND_THROW( 58 | std::out_of_range, 59 | "asking for argument past initially declared range"); 60 | return *m_impl[index]; 61 | } 62 | 63 | UaPropertyCache::UaPropertyCache ( 64 | const UaString &name, 65 | const UaNodeId &nodeId, 66 | const UaVariant &defaultValue, 67 | OpcUa_Byte accessLevel, 68 | const UaString& defaultLocaleId) : 69 | m_nodeId(nodeId), 70 | m_browseName(0, name), 71 | m_value(defaultValue), 72 | m_typeDefinitionId(defaultValue.type()) 73 | {} 74 | -------------------------------------------------------------------------------- /src/uadatetime.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright CERN, 2017. All rights not expressly granted are reserved. 2 | * opcua_types.h 3 | * 4 | * Moved on: 30 Nov 2017 5 | * Author: Ben Farnham 6 | * Piotr Nikiel 7 | * 8 | * This file is part of Quasar. 9 | * 10 | * Quasar is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public Licence as published by 12 | * the Free Software Foundation, either version 3 of the Licence. 13 | * 14 | * Quasar is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public Licence for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with Quasar. If not, see . 21 | */ 22 | 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | UaDateTime::UaDateTime() 31 | :m_dateTime{0} 32 | {} 33 | 34 | UaDateTime::UaDateTime(const UA_DateTime& dateTime) 35 | :m_dateTime(dateTime) 36 | {} 37 | 38 | UaDateTime UaDateTime::now() 39 | { 40 | return UaDateTime(UA_DateTime_now()); 41 | } 42 | 43 | void UaDateTime::addSecs(int secs) 44 | { 45 | m_dateTime += (secs * UA_DATETIME_SEC); 46 | } 47 | 48 | void UaDateTime::addMilliSecs(int msecs) 49 | { 50 | m_dateTime += (msecs * UA_DATETIME_MSEC); 51 | } 52 | 53 | /** 54 | * * Accepts format 55 | * * "%Y-%m-%dT%H:%M:%S%ZP" 56 | * * e.g. unix epoch: "1970-01-01T00:00:00Z" 57 | * * e.g. open62541 epoch "1601-01-01T00:00:00Z" (i.e. windows epoch) 58 | * */ 59 | UaDateTime UaDateTime::fromString(const UaString& dateTimeString) 60 | { 61 | const std::string stdDateTimeString(dateTimeString.toUtf8()); 62 | std::istringstream ss(stdDateTimeString); 63 | 64 | const static std::string timeFormatString("%Y-%m-%dT%H:%M:%S%ZP"); 65 | static std::locale timeFormatLocale(ss.getloc(), new boost::posix_time::time_input_facet(timeFormatString)); // Not a leak: std::locale deletes fa cet 66 | ss.imbue(timeFormatLocale); 67 | 68 | try 69 | { 70 | static const boost::posix_time::ptime unixEpoch(boost::gregorian::date(1970, 1, 1)); 71 | 72 | if(unixEpoch.is_not_a_date_time()) 73 | { 74 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "Failed to calculate unix epoch, cannot parse any dates from strings."); 75 | } 76 | 77 | boost::posix_time::ptime dateTime; 78 | ss >> dateTime; 79 | 80 | if(dateTime.is_not_a_date_time()) 81 | { 82 | std::ostringstream err; 83 | err << "Failed to convert string ["< 13 | #include 14 | #include 15 | #include 16 | 17 | UaNodeId::UaNodeId (): 18 | UaNodeId (0, 0) // similarly to UA-SDK 19 | { 20 | } 21 | 22 | UaNodeId::UaNodeId ( const UaString& stringAddress, OpcUa_UInt16 ns) 23 | { 24 | // TODO: not implemented yet in open62541 25 | // UA_NodeId_fromInteger( 2, 2); 26 | m_impl.namespaceIndex = ns; 27 | m_impl.identifierType = UA_NODEIDTYPE_STRING; 28 | UA_StatusCode status = UA_String_copy( stringAddress.impl(), &m_impl.identifier.string ); 29 | if (status != UA_STATUSCODE_GOOD) 30 | throw alloc_error(); 31 | } 32 | 33 | 34 | UaNodeId::UaNodeId( OpcUa_UInt32 numericAddress, OpcUa_UInt16 ns): 35 | m_impl( UA_NODEID_NUMERIC( ns, numericAddress )) 36 | { 37 | 38 | } 39 | 40 | UaNodeId::UaNodeId ( const UaNodeId & other) 41 | { 42 | UA_NodeId_init( &m_impl ); 43 | UA_StatusCode status = UA_NodeId_copy( other.pimpl(), &this->m_impl ); 44 | if (status != UA_STATUSCODE_GOOD) 45 | throw alloc_error(); 46 | } 47 | 48 | /* open62541 data format -> UA-SDK data format conversion */ 49 | UaNodeId::UaNodeId ( const UA_NodeId& other) 50 | { 51 | UA_NodeId_init( &m_impl ); 52 | UA_NodeId_copy( &other, &m_impl ); 53 | } 54 | 55 | const UaNodeId& UaNodeId::operator=(const UaNodeId & other) 56 | { 57 | UA_NodeId_clear( &m_impl ); 58 | UA_NodeId_init( &m_impl ); 59 | UA_StatusCode status = UA_NodeId_copy( other.pimpl(), &this->m_impl ); 60 | if (status != UA_STATUSCODE_GOOD) 61 | throw alloc_error(); 62 | return *this; 63 | } 64 | 65 | UaNodeId::~UaNodeId () 66 | { 67 | UA_NodeId_clear( &m_impl ); 68 | } 69 | 70 | IdentifierType UaNodeId::identifierType() const 71 | { 72 | switch (m_impl.identifierType) 73 | { 74 | case UA_NODEIDTYPE_NUMERIC: return IdentifierType::OpcUa_IdentifierType_Numeric; 75 | case UA_NODEIDTYPE_STRING: return IdentifierType::OpcUa_IdentifierType_String; 76 | default: OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "not-implemented"); 77 | } 78 | } 79 | 80 | UaString UaNodeId::identifierString() const 81 | { 82 | if (m_impl.identifierType != UA_NODEIDTYPE_STRING) 83 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "asking for identifierString from a non-string identifier!"); 84 | return UaString( &m_impl.identifier.string ); 85 | 86 | } 87 | 88 | bool UaNodeId::operator==(const UaNodeId& other) const 89 | { 90 | return UA_NodeId_equal( &m_impl, &other.m_impl ); 91 | } 92 | 93 | UaString UaNodeId::toString() const 94 | { 95 | if (identifierType() == IdentifierType::OpcUa_IdentifierType_String) 96 | { 97 | return identifierString(); 98 | } 99 | else if (identifierType() == IdentifierType::OpcUa_IdentifierType_Numeric) 100 | { 101 | std::string s = "(ns="+boost::lexical_cast(namespaceIndex())+","+boost::lexical_cast(identifierNumeric())+")"; 102 | return UaString(s.c_str()); 103 | } 104 | return "identifier-type-unsupported"; 105 | } 106 | 107 | UaString UaNodeId::toFullString() const 108 | { 109 | if (identifierType() == IdentifierType::OpcUa_IdentifierType_String) 110 | { 111 | std::string s = "(ns="+boost::lexical_cast(namespaceIndex())+","+UaString(identifierString()).toUtf8()+")"; 112 | return UaString(s.c_str()); 113 | } 114 | else 115 | return toString(); 116 | } 117 | 118 | void UaNodeId::copyTo( UaNodeId* other) const 119 | { 120 | *other = *this; 121 | } 122 | 123 | 124 | void UaNodeId::copyTo( UA_NodeId* other) const 125 | { 126 | if (!other) 127 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "passed a nullptr"); 128 | UA_StatusCode status = UA_NodeId_copy( &this->m_impl, other ); 129 | if (status != UA_STATUSCODE_GOOD) 130 | throw alloc_error(); 131 | 132 | } 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/uaserver.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2019. All rights not expressly granted are reserved. 2 | * uaserver.cpp 3 | * 4 | * Created on: 29 Nov 2019 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #ifdef HAS_SERVERCONFIG_LOADER 34 | #include 35 | #include 36 | #include 37 | #endif // HAS_SERVERCONFIG_LOADER 38 | 39 | 40 | UaServer::UaServer() : 41 | m_server(nullptr), 42 | m_nodeManager(nullptr), 43 | m_runningFlag(nullptr), 44 | m_endpointPortNumber(4841) 45 | { 46 | 47 | } 48 | 49 | UaServer::~UaServer() 50 | { 51 | // TODO: what if still running? 52 | } 53 | 54 | void UaServer::start() 55 | { 56 | if (!m_runningFlag) 57 | throw std::logic_error ("Establish the 'running flag' first"); 58 | m_server = UA_Server_new(); 59 | if (!m_server) 60 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "UA_Server_new failed"); 61 | UA_ServerConfig* config = UA_Server_getConfig(m_server); 62 | UA_ServerConfig_setMinimal(config, m_endpointPortNumber, nullptr); 63 | 64 | // use LogIt logger for open62541 65 | initializeOpen62541LogIt(); 66 | config->logger = theLogItLogger; 67 | 68 | m_nodeManager->linkServer(m_server); 69 | m_nodeManager->afterStartUp(); 70 | 71 | UA_StatusCode status = UA_Server_run_startup(m_server); 72 | if (status != UA_STATUSCODE_GOOD) 73 | throw std::runtime_error("UA_Server_run_startup returned not-good, server can't start. Error was:"+ 74 | UaStatus(status).toString().toUtf8()); 75 | else 76 | LOG(Log::INF) << 77 | "UA_Server_run_startup returned: " << UaStatus(status).toString().toUtf8() << ", continuing."; 78 | m_open62541_server_thread = std::thread ( &UaServer::runThread, this ); 79 | } 80 | 81 | void UaServer::runThread() 82 | { 83 | while (*m_runningFlag) 84 | { 85 | UA_Server_run_iterate(m_server, true); 86 | } 87 | UA_StatusCode status = UA_Server_run_shutdown(m_server); 88 | if (status != UA_STATUSCODE_GOOD) 89 | { 90 | LOG(Log::ERR) << "UA_Server_run_shutdown returned not-good. Error was:" << UaStatus(status).toString().toUtf8(); 91 | } 92 | else 93 | LOG(Log::INF) << "UA_Server_run_shutdown returned: " << UaStatus(status).toString().toUtf8(); 94 | } 95 | 96 | void UaServer::addNodeManager(NodeManagerBase* pNodeManager) 97 | { 98 | if (!m_nodeManager) 99 | m_nodeManager = pNodeManager; 100 | else 101 | OPEN62541_COMPAT_LOG_AND_THROW(std::logic_error, "Sorry, only 1 NodeManager is supported."); 102 | } 103 | 104 | void UaServer::linkRunningFlag (volatile OpcUa_Boolean* flag) 105 | { 106 | m_runningFlag = flag; 107 | } 108 | 109 | void UaServer::setServerConfig( 110 | const UaString& configurationFile, 111 | const UaString& applicationPath) 112 | { 113 | #ifndef HAS_SERVERCONFIG_LOADER 114 | LOG(Log::INF) << "Note: you built open62541-compat without configuration loading (option SERVERCONFIG_LOADER). So loading of ServerConfig.xml is not supported. Assuming hardcoded server settings (endpoint's port, etc.)"; 115 | //! With open62541 1.0, it is the UA_Server that holds the config. 116 | #else // HAS_SERVERCONFIG_LOADER is defined, means the user wants the option 117 | std::unique_ptr< ::ServerConfig::OpcServerConfig > serverConfig; 118 | try 119 | { 120 | serverConfig = ServerConfig::OpcServerConfig_ (configurationFile.toUtf8()); 121 | } 122 | catch (xsd::cxx::tree::parsing &exception) 123 | { 124 | LOG(Log::ERR) << "ServerConfig loader: failed when trying to open the file, with general error message: " << exception.what(); 125 | for( const xsd::cxx::tree::error &error : exception.diagnostics() ) 126 | { 127 | LOG(Log::ERR) << "ServerConfig: Problem at " << error.id() << ":" << error.line() << ": " << error.message(); 128 | } 129 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "ServerConfig: failed to load ServerConfig. The exact problem description should have been logged."); 130 | 131 | } 132 | // minimum one endpoint is guaranteed by the XSD, but in case user declared more, refuse to continue 133 | // TODO: implement multiple endpoints 134 | const ServerConfig::UaServerConfig& uaServerConfig = serverConfig->UaServerConfig(); 135 | if (uaServerConfig.UaEndpoint().size() > 1) 136 | { 137 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "No support for multiple UaEndpoints yet, simplify your ServerConfig.xml"); 138 | } 139 | boost::regex endpointUrlRegex("^opc\\.tcp:\\/\\/\\[NodeName\\]:(?\\d+)$"); 140 | boost::smatch matchResults; 141 | std::string endpointUrl (uaServerConfig.UaEndpoint()[0].Url() ); 142 | bool matched = boost::regex_match( endpointUrl, matchResults, endpointUrlRegex ); 143 | if (!matched) 144 | OPEN62541_COMPAT_LOG_AND_THROW(std::runtime_error, "Can't parse UaEndpoint/Url, note it should look like 'opc.tcp://[NodeName]:4841' perhaps with different port number, yours is '"+endpointUrl+"'"); 145 | unsigned int endpointUrlPort = boost::lexical_cast(matchResults["port"]); 146 | LOG(Log::INF) << "From your [" << configurationFile.toUtf8() << "] loaded endpoint port number: " << endpointUrlPort; 147 | m_endpointPortNumber = endpointUrlPort; 148 | #endif 149 | } 150 | 151 | void UaServer::stop () 152 | { 153 | if (m_open62541_server_thread.joinable()) // if start() was never called, or server failed to start, the thread is not joinable... 154 | m_open62541_server_thread.join(); 155 | delete m_nodeManager; 156 | m_nodeManager = nullptr; 157 | UA_Server_delete(m_server); 158 | m_server = nullptr; 159 | } 160 | -------------------------------------------------------------------------------- /src/uastring.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Piotr Nikiel, CERN, 2015. All rights not expressly granted are reserved. 2 | * uastring.cpp 3 | * 4 | * Created on: 15 Nov, 2015 5 | * Author: Piotr Nikiel 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | UaString::UaString () 28 | { 29 | m_impl = UA_String_new( ); 30 | if (! m_impl) 31 | throw alloc_error(); 32 | 33 | } 34 | 35 | UaString::UaString( const char* s) 36 | { 37 | m_impl = UA_String_new( ); 38 | if ( ! m_impl) 39 | throw alloc_error(); 40 | 41 | *m_impl = UA_String_fromChars( s ); 42 | if( m_impl->length < 0 ) 43 | { 44 | UA_String_delete( m_impl ); 45 | throw alloc_error(); 46 | } 47 | 48 | } 49 | 50 | UaString::UaString( const UaString& other) 51 | { 52 | m_impl = UA_String_new( ); 53 | if ( ! m_impl) 54 | throw alloc_error(); 55 | 56 | if( UA_String_copy( other.m_impl, m_impl ) != UA_STATUSCODE_GOOD) 57 | { 58 | UA_String_delete( m_impl ); 59 | throw alloc_error(); 60 | } 61 | 62 | } 63 | 64 | UaString::UaString( const UA_String* other ) 65 | { 66 | m_impl = UA_String_new( ); 67 | if ( ! m_impl) 68 | throw alloc_error(); 69 | if( UA_String_copy( other, m_impl ) != UA_STATUSCODE_GOOD) 70 | { 71 | UA_String_delete( m_impl ); 72 | throw alloc_error(); 73 | } 74 | } 75 | 76 | UaString::~UaString () 77 | { 78 | if (m_impl -> data) 79 | UA_String_clear( m_impl ); 80 | UA_String_delete( m_impl ); 81 | m_impl = 0; 82 | } 83 | 84 | UaString UaString::operator+(const UaString& other) 85 | { 86 | std::string concatenated = this->toUtf8() + other.toUtf8(); 87 | return UaString( concatenated.c_str() ); 88 | } 89 | 90 | const UaString& UaString::operator=(const UaString& other) 91 | { 92 | if (m_impl -> data) 93 | UA_String_clear( m_impl ); 94 | 95 | if( UA_String_copy( other.m_impl, m_impl ) != UA_STATUSCODE_GOOD) 96 | { 97 | UA_String_delete( m_impl ); 98 | throw alloc_error(); 99 | } 100 | return *this; 101 | } 102 | 103 | const UaString& UaString::operator=(const UA_String& other) 104 | { 105 | if (m_impl -> data) 106 | UA_String_clear( m_impl ); 107 | 108 | if( UA_String_copy( &other, m_impl ) != UA_STATUSCODE_GOOD) 109 | { 110 | UA_String_delete( m_impl ); 111 | throw alloc_error(); 112 | } 113 | return *this; 114 | } 115 | 116 | std::string UaString::toUtf8() const 117 | { 118 | return std::string( reinterpret_cast(m_impl->data), m_impl->length ); 119 | } 120 | 121 | /** Note(Piotr): this is not real detachment. 122 | * It was implemented to be fit for arrays stuff but perhaps an another overloaded 123 | * function should be created. 124 | */ 125 | void UaString::detach(UaString* out) 126 | { 127 | *out = *this; 128 | } 129 | 130 | bool UaString::operator==(const UaString& other) 131 | { 132 | return UA_String_equal(this->m_impl, other.m_impl); 133 | } 134 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(open62541-compat-Test) 3 | find_package(Threads REQUIRED) 4 | 5 | message( STATUS "building unit tests, a wise choice. Remember to execute the tests too!" ) 6 | 7 | function ( clone_googletest GOOGLETEST_VERSION) 8 | message(STATUS "cloning googletest from github. *NOTE* cloning [${GOOGLETEST_VERSION}]") 9 | execute_process(COMMAND git clone -b ${GOOGLETEST_VERSION} https://github.com/google/googletest.git WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) 10 | message(STATUS "googletest cloned") 11 | endfunction() 12 | 13 | set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) 14 | 15 | file(GLOB OPEN62541_COMPAT_MODULE_TEST_SRCS src/*.cpp) 16 | include_directories( include ) 17 | 18 | clone_googletest("release-1.10.0") 19 | set( BUILD_GTEST ON CACHE BOOL "We do want to build gtest") 20 | set( BUILD_GMOCK OFF CACHE BOOL "we do not want to build gmock") 21 | set( gtest_force_shared_crt ON CACHE BOOL "use shared CRT" FORCE) 22 | add_subdirectory( ${PROJECT_BINARY_DIR}/googletest ${PROJECT_BINARY_DIR}/googletest EXCLUDE_FROM_ALL) 23 | 24 | add_executable( open62541-compat-Test ${OPEN62541_COMPAT_MODULE_TEST_SRCS} ) 25 | 26 | message(STATUS "file [${CMAKE_CURRENT_LIST_FILE}]: Using BOOST_LIBS [${BOOST_LIBS}]") 27 | message(STATUS "file [${CMAKE_CURRENT_LIST_FILE}]: Using LogIt library: LOGIT_LIB [${LOGIT_LIB}]") 28 | 29 | target_link_libraries (open62541-compat-Test 30 | open62541-compat 31 | ${BOOST_LIBS} 32 | ${CMAKE_THREAD_LIBS_INIT} 33 | ${LOGIT_LIB} 34 | gtest 35 | -ldl 36 | ) 37 | 38 | add_dependencies (open62541-compat-Test gtest) 39 | -------------------------------------------------------------------------------- /test/include/uavariant_test.h: -------------------------------------------------------------------------------- 1 | /* © Copyright Ben Farnham, CERN, 2018. All rights not expressly granted are reserved. 2 | * nodemanagerbase.cpp 3 | * 4 | * Created on: reated on: Apr 11, 2018 5 | * Author: Ben Farnham 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #ifndef TEST_INCLUDE_UAVARIANT_TEST_H_ 23 | #define TEST_INCLUDE_UAVARIANT_TEST_H_ 24 | 25 | #include "gtest/gtest.h" 26 | #include "uavariant.h" 27 | 28 | class UaVariantTest : public ::testing::Test 29 | { 30 | public: 31 | 32 | UaVariant m_testee; 33 | }; 34 | 35 | 36 | #endif /* TEST_INCLUDE_UAVARIANT_TEST_H_ */ 37 | -------------------------------------------------------------------------------- /test/src/arrays_test.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Ben Farnham, CERN, 2018. All rights not expressly granted are reserved. 2 | * nodemanagerbase.cpp 3 | * 4 | * Created on: reated on: Apr 11, 2018 5 | * Author: Ben Farnham 6 | * Author: Piotr Nikiel 7 | * 8 | * This file is part of Quasar. 9 | * 10 | * Quasar is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public Licence as published by 12 | * the Free Software Foundation, either version 3 of the Licence. 13 | * 14 | * Quasar is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public Licence for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with Quasar. If not, see . 21 | */ 22 | #include "gtest/gtest.h" 23 | #include "arrays.h" 24 | #include "uavariant.h" 25 | 26 | TEST(ArraysTest, testDefaultInitializer) 27 | { 28 | UaVariantArray testee; 29 | EXPECT_EQ(0, testee.size()) << "default initialized array should be empty"; 30 | } 31 | 32 | TEST(ArraysTest, testInitializeAndSetValues) 33 | { 34 | UaVariantArray testee; 35 | 36 | testee.create(1000); 37 | for(size_t i=0; i<1000; ++i) 38 | { 39 | testee[i] = UaVariant(i); 40 | } 41 | 42 | EXPECT_EQ(1000, testee.size()) << "should be 1000 array elements"; 43 | for(size_t i=0; i<1000; ++i) 44 | { 45 | EXPECT_EQ(UaVariant(i), testee[i]) << "element values should match index"; 46 | } 47 | } 48 | 49 | TEST(ArraysTest, testUaVariantsHoldingArrays) 50 | { 51 | UaInt32Array intArray; 52 | intArray.create(100); 53 | 54 | for(int32_t i=0; i<100; ++i) 55 | { 56 | intArray[i]=i; 57 | } 58 | 59 | UaVariant testee; 60 | 61 | testee.setInt32Array(intArray); 62 | EXPECT_TRUE(testee.isArray()) << "variant should know it now holds an array value"; 63 | 64 | UaUInt32Array arrayDimensions; 65 | testee.arrayDimensions(arrayDimensions); 66 | 67 | EXPECT_EQ(1, arrayDimensions.size()) << "should be a 1D array"; 68 | EXPECT_EQ(100, arrayDimensions[0]) << "should be 100 elements in the 1D"; 69 | } 70 | 71 | TEST(ArraysTest, testEmptyArraySetter) 72 | { 73 | UaInt32Array emptyArray; 74 | UaVariant testee; 75 | 76 | testee.setInt32Array(emptyArray); 77 | 78 | EXPECT_TRUE(testee.isArray()) << "it should be just an empty array"; 79 | 80 | UaUInt32Array dimensions; 81 | testee.arrayDimensions(dimensions); 82 | EXPECT_EQ(0, dimensions[0]) << "arrayDimensions should say it's an empty array"; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /test/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Ben Farnham, CERN, 2018. All rights not expressly granted are reserved. 2 | * nodemanagerbase.cpp 3 | * 4 | * Created on: reated on: Apr 11, 2018 5 | * Author: Ben Farnham 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | #include "gtest/gtest.h" 22 | 23 | int main(int argc, char** argv) 24 | { 25 | ::testing::InitGoogleTest(&argc, argv); 26 | return RUN_ALL_TESTS(); 27 | } 28 | -------------------------------------------------------------------------------- /test/src/uabytestring_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * uabytestring_test.cpp 3 | * 4 | * Created on: 27 Mar 2020 5 | * Author: pnikiel 6 | */ 7 | 8 | #include "gtest/gtest.h" 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | const OpcUa_Byte reference[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10}; 15 | const size_t referenceSize = sizeof reference / sizeof reference[0]; 16 | 17 | TEST(UaByteStringTest, testDefaultConstructor) 18 | { 19 | UaByteString nullByteString; 20 | EXPECT_EQ(nullByteString.length(), 0); 21 | EXPECT_EQ(nullByteString.data(), nullptr); 22 | } 23 | 24 | TEST(UaByteStringTest, testFromDataConstructor) 25 | { 26 | UaByteString byteString(referenceSize, reference); 27 | EXPECT_EQ(byteString.length(), referenceSize); 28 | bool equal = std::equal( 29 | std::begin(reference), 30 | std::end(reference), 31 | byteString.data()); 32 | EXPECT_EQ(equal, true); 33 | } 34 | 35 | TEST(UaByteStringTest, testCopyConstructorUaByteString) 36 | { 37 | UaByteString byteString(referenceSize, reference); 38 | UaByteString copiedByteString (byteString); 39 | EXPECT_EQ(copiedByteString.length(), referenceSize); 40 | bool equal = std::equal( 41 | std::begin(reference), 42 | std::end(reference), 43 | copiedByteString.data()); 44 | EXPECT_EQ(equal, true); 45 | } 46 | 47 | TEST(UaByteStringTest, testCopyConstructorUA_ByteString) 48 | { 49 | /* prepare stack ByteString */ 50 | UA_ByteString stackByteString; 51 | UA_ByteString_init(&stackByteString); 52 | UA_ByteString_allocBuffer(&stackByteString, referenceSize); 53 | std::copy( 54 | std::begin(reference), 55 | std::end(reference), 56 | stackByteString.data); 57 | 58 | /* now construct open62541-compat ByteString from stack ByteString */ 59 | UaByteString byteString (stackByteString); 60 | EXPECT_EQ(byteString.length(), referenceSize); 61 | bool equal = std::equal( 62 | std::begin(reference), 63 | std::end(reference), 64 | byteString.data()); 65 | EXPECT_EQ(equal, true); 66 | } 67 | 68 | TEST(UaByteStringTest, testAssignmentOperator) 69 | { 70 | UaByteString referenceByteString(referenceSize, reference); 71 | 72 | UaByteString another; 73 | another = referenceByteString; 74 | 75 | EXPECT_EQ(another.length(), referenceSize); 76 | bool equal = std::equal( 77 | std::begin(reference), 78 | std::end(reference), 79 | another.data()); 80 | EXPECT_EQ(equal, true); 81 | } 82 | 83 | TEST(UaByteStringTest, testByteStringArray) 84 | { 85 | const unsigned int N = 100000; 86 | UaByteStringArray array; 87 | array.create(N); 88 | for (unsigned int i=0; i 10 | 11 | const auto g_sValueVariant = UaVariant(UaString("some string value")); 12 | const auto g_sSourceTime = UaDateTime::fromString(UaString("2021-08-02T14:30:00Z")); 13 | const auto g_sServerTime = UaDateTime::fromString(UaString("2021-08-02T14:30:01Z")); 14 | 15 | TEST(UaDataValueTest, testOperatorIsEqual) 16 | { 17 | UaDataValue testee(g_sValueVariant , OpcUa_Good, g_sServerTime, g_sSourceTime ); 18 | EXPECT_TRUE(testee == testee); 19 | EXPECT_TRUE(testee == UaDataValue( g_sValueVariant, OpcUa_Good, g_sServerTime, g_sSourceTime ) ) << "equivalent object"; 20 | EXPECT_FALSE(testee == UaDataValue( UaVariant(UaString("DIFFERENT string value")), OpcUa_Good, g_sServerTime, g_sSourceTime ) ) << "value changed"; 21 | EXPECT_FALSE(testee == UaDataValue( UaVariant(OpcUa_Int32(69)), OpcUa_Good, g_sServerTime, g_sSourceTime ) ) << "type changed"; 22 | EXPECT_FALSE(testee == UaDataValue( g_sValueVariant, OpcUa_Bad, g_sServerTime, g_sSourceTime ) ) << "status changed"; 23 | EXPECT_FALSE(testee == UaDataValue( g_sValueVariant, OpcUa_Good, UaDateTime::fromString("2222-08-02T14:30:01Z"), g_sSourceTime ) ) << "server timestamp changed"; 24 | EXPECT_FALSE(testee == UaDataValue( g_sValueVariant, OpcUa_Good, g_sServerTime, UaDateTime::fromString("2222-08-02T14:30:01Z") ) )<< "source timestamp changed"; 25 | } 26 | 27 | TEST(UaDataValueTest, testOperatorNotIsEqual) 28 | { 29 | UaDataValue testee( UaVariant("some string value"), OpcUa_Good, g_sServerTime, g_sSourceTime ); 30 | EXPECT_FALSE(testee != testee); 31 | } 32 | -------------------------------------------------------------------------------- /test/src/uadatetime_test.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Ben Farnham, CERN, 2021. All rights not expressly granted are reserved. 2 | * nodemanagerbase.cpp 3 | * 4 | * Created on: reated on: Mar 1, 2021 5 | * Author: Ben Farnham 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include "gtest/gtest.h" 23 | #include "uadatetime.h" 24 | 25 | TEST(UaDatetimeTest, testDefaultCtor) 26 | { 27 | UaDateTime testee; 28 | EXPECT_EQ(0, static_cast(testee)) << "default should be epoch + 0"; 29 | } 30 | 31 | TEST(UaDatetimeTest, testOpen62541TypeCtor) 32 | { 33 | UaDateTime testee(123); 34 | EXPECT_EQ(123, static_cast(testee)) << "ctor arg maps directly onto member"; 35 | } 36 | 37 | TEST(UaDatetimeTest, testAddSecs) 38 | { 39 | UaDateTime testee; 40 | testee.addSecs(1); 41 | EXPECT_EQ(1E7, static_cast(testee)) << "time stored as 100usec intervals since epoch"; 42 | } 43 | 44 | TEST(UaDatetimeTest, testAddMilliSecs) 45 | { 46 | UaDateTime testee; 47 | testee.addMilliSecs(1); 48 | EXPECT_EQ(1E4, static_cast(testee)) << "time stored as 100usec intervals since epoch"; 49 | } 50 | 51 | TEST(UaDatetimeTest, testSecsTo) 52 | { 53 | UaDateTime earlier(static_cast(1*1E7)); // 1s 54 | UaDateTime later(static_cast(5*1E7)); // 5s 55 | 56 | EXPECT_EQ(4, earlier.secsTo(later)); 57 | EXPECT_EQ(-4, later.secsTo(earlier)); 58 | 59 | later.addMilliSecs(1); 60 | EXPECT_EQ(4, earlier.secsTo(later)) << "4s difference (complete secs only)"; 61 | 62 | later.addMilliSecs(500); 63 | EXPECT_EQ(4, earlier.secsTo(later)) << "4s difference (complete secs only)"; 64 | 65 | later.addMilliSecs(500); 66 | EXPECT_EQ(5, earlier.secsTo(later)); 67 | } 68 | -------------------------------------------------------------------------------- /test/src/uaqualifiedname_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * uaqualifiedname_test.cpp 3 | * 4 | * Created on: 16 July 2021 5 | * Author: ben-farnham 6 | */ 7 | 8 | #include "gtest/gtest.h" 9 | #include 10 | 11 | #include 12 | 13 | TEST(UaQualifiedNameTest, testToString) 14 | { 15 | UaQualifiedName testee(2, "a.b.c"); 16 | EXPECT_EQ("a.b.c", testee.toString().toUtf8()); 17 | } 18 | 19 | TEST(UaQualifiedNameTest, testToFullString) 20 | { 21 | UaQualifiedName testee(2, "a.b.c"); 22 | EXPECT_EQ("ns=2|a.b.c", testee.toFullString().toUtf8()); 23 | } 24 | -------------------------------------------------------------------------------- /test/src/uavariant_test.cpp: -------------------------------------------------------------------------------- 1 | /* © Copyright Ben Farnham, CERN, 2018. All rights not expressly granted are reserved. 2 | * nodemanagerbase.cpp 3 | * 4 | * Created on: reated on: Apr 11, 2018 5 | * Author: Ben Farnham 6 | * 7 | * This file is part of Quasar. 8 | * 9 | * Quasar is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public Licence as published by 11 | * the Free Software Foundation, either version 3 of the Licence. 12 | * 13 | * Quasar is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public Licence for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with Quasar. If not, see . 20 | */ 21 | 22 | #include "uavariant_test.h" 23 | #include "arrays.h" 24 | 25 | #include 26 | #include 27 | 28 | using std::numeric_limits; 29 | 30 | TEST_F(UaVariantTest, testCannotConvertUninitalizedVariant) 31 | { 32 | OpcUa_Int32 result; 33 | EXPECT_EQ(OpcUa_Bad, m_testee.toInt32(result)) << "should not be able to convert an uninitialized variant to any type"; 34 | } 35 | 36 | TEST_F(UaVariantTest, testConvertToSameInternalType) 37 | { 38 | OpcUa_Int32 int32Value = 123; 39 | m_testee.setInt32(int32Value); 40 | 41 | OpcUa_Int32 int32Result; 42 | EXPECT_EQ(OpcUa_Good, m_testee.toInt32(int32Result)); 43 | EXPECT_EQ(int32Value, int32Result); 44 | 45 | OpcUa_UInt64 uint64Value = 456; 46 | m_testee.setUInt64(uint64Value); 47 | 48 | OpcUa_UInt64 uint64Result; 49 | EXPECT_EQ(OpcUa_Good, m_testee.toUInt64(uint64Result)); 50 | EXPECT_EQ(uint64Value, uint64Result); 51 | 52 | m_testee.setString(UaString("abcde")); 53 | EXPECT_EQ("abcde", m_testee.toString().toUtf8()); 54 | } 55 | 56 | TEST_F(UaVariantTest, testConvertFromBoolean) 57 | { 58 | m_testee.setBool(true); 59 | 60 | OpcUa_Boolean booleanResult = false; 61 | EXPECT_EQ(OpcUa_Good, m_testee.toBool(booleanResult)); 62 | EXPECT_TRUE(booleanResult); 63 | 64 | OpcUa_Byte byteResult; 65 | EXPECT_EQ(OpcUa_Good, m_testee.toByte(byteResult)); 66 | EXPECT_EQ(1, byteResult); 67 | 68 | OpcUa_Int16 int16Result; 69 | EXPECT_EQ(OpcUa_Good, m_testee.toInt16(int16Result)); 70 | EXPECT_EQ(1, int16Result); 71 | 72 | OpcUa_UInt32 uint32Result; 73 | EXPECT_EQ(OpcUa_Good, m_testee.toUInt32(uint32Result)); 74 | EXPECT_EQ(1, uint32Result); 75 | 76 | OpcUa_UInt64 uint64Result; 77 | EXPECT_EQ(OpcUa_Good, m_testee.toUInt64(uint64Result)); 78 | EXPECT_EQ(1, uint64Result); 79 | 80 | OpcUa_Float floatResult; 81 | EXPECT_EQ(OpcUa_Good, m_testee.toFloat(floatResult)); 82 | EXPECT_FLOAT_EQ(1, floatResult); 83 | 84 | OpcUa_Double doubleResult; 85 | EXPECT_EQ(OpcUa_Good, m_testee.toDouble(doubleResult)); 86 | EXPECT_DOUBLE_EQ(1, doubleResult); 87 | } 88 | 89 | TEST_F(UaVariantTest, testConvertToBoolean) 90 | { 91 | OpcUa_Boolean booleanResult; 92 | 93 | m_testee.setBool(true); 94 | EXPECT_EQ(OpcUa_Good, m_testee.toBool(booleanResult)); 95 | EXPECT_TRUE(booleanResult); 96 | 97 | m_testee.setInt16(1); 98 | EXPECT_EQ(OpcUa_Good, m_testee.toBool(booleanResult)); 99 | EXPECT_TRUE(booleanResult); 100 | 101 | m_testee.setUInt32(1); 102 | EXPECT_EQ(OpcUa_Good, m_testee.toBool(booleanResult)); 103 | EXPECT_TRUE(booleanResult); 104 | 105 | m_testee.setInt64(1); 106 | EXPECT_EQ(OpcUa_Good, m_testee.toBool(booleanResult)); 107 | EXPECT_TRUE(booleanResult); 108 | 109 | m_testee.setFloat(1); 110 | EXPECT_EQ(OpcUa_Good, m_testee.toBool(booleanResult)); 111 | EXPECT_TRUE(booleanResult); 112 | 113 | m_testee.setDouble(1); 114 | EXPECT_EQ(OpcUa_Good, m_testee.toBool(booleanResult)); 115 | EXPECT_TRUE(booleanResult); 116 | } 117 | 118 | TEST_F(UaVariantTest, testConvertFromInt32) 119 | { 120 | OpcUa_Byte byteResult; 121 | OpcUa_Int16 int16Result; 122 | OpcUa_UInt32 uint32Result; 123 | OpcUa_UInt64 uint64Result; 124 | OpcUa_Float floatResult; 125 | 126 | m_testee.setInt32(1); 127 | EXPECT_EQ(OpcUa_Good, m_testee.toByte(byteResult)); 128 | EXPECT_EQ(1, byteResult); 129 | EXPECT_EQ(OpcUa_Good, m_testee.toInt16(int16Result)); 130 | EXPECT_EQ(1, int16Result); 131 | EXPECT_EQ(OpcUa_Good, m_testee.toUInt32(uint32Result)); 132 | EXPECT_EQ(1, uint32Result); 133 | EXPECT_EQ(OpcUa_Good, m_testee.toUInt64(uint64Result)); 134 | EXPECT_EQ(1, uint64Result); 135 | EXPECT_EQ(OpcUa_Good, m_testee.toFloat(floatResult)); 136 | EXPECT_FLOAT_EQ(1, floatResult); 137 | 138 | m_testee.setInt32(-1); 139 | EXPECT_EQ(OpcUa_BadOutOfRange, m_testee.toByte(byteResult))<< "expected to fail: -1 out of range for conversion to unsigned"; 140 | EXPECT_EQ(OpcUa_Good, m_testee.toInt16(int16Result)); 141 | EXPECT_EQ(-1, int16Result); 142 | EXPECT_EQ(OpcUa_BadOutOfRange, m_testee.toUInt32(uint32Result))<< "expected to fail: -1 out of range for conversion to unsigned"; 143 | EXPECT_EQ(OpcUa_BadOutOfRange, m_testee.toUInt64(uint64Result))<< "expected to fail: -1 out of range for conversion to unsigned"; 144 | EXPECT_EQ(OpcUa_Good, m_testee.toFloat(floatResult)); 145 | EXPECT_FLOAT_EQ(-1, floatResult); 146 | 147 | m_testee.setInt32(numeric_limits::max()); 148 | EXPECT_EQ(OpcUa_BadOutOfRange, m_testee.toByte(byteResult))<< "expected to fail: number too large for byte"; 149 | EXPECT_EQ(OpcUa_BadOutOfRange, m_testee.toInt16(int16Result))<< "expected to fail: number too large for 16 bit integer"; 150 | EXPECT_EQ(OpcUa_Good, m_testee.toUInt32(uint32Result)); 151 | EXPECT_EQ(numeric_limits::max(), uint32Result); 152 | EXPECT_EQ(OpcUa_Good, m_testee.toUInt64(uint64Result)); 153 | EXPECT_EQ(numeric_limits::max(), uint64Result); 154 | EXPECT_EQ(OpcUa_Good, m_testee.toFloat(floatResult)); 155 | EXPECT_FLOAT_EQ(numeric_limits::max(), floatResult); 156 | } 157 | 158 | TEST_F(UaVariantTest, testConvertFromUInt32) 159 | { 160 | OpcUa_Int32 int32Result; 161 | 162 | m_testee.setUInt32(1); 163 | EXPECT_EQ(OpcUa_Good, m_testee.toInt32(int32Result)); 164 | EXPECT_EQ(1, int32Result); 165 | EXPECT_EQ(OpcUa_Good, m_testee.toInt32(int32Result)); 166 | EXPECT_EQ(1, int32Result); 167 | 168 | m_testee.setUInt32(numeric_limits::max()); 169 | EXPECT_EQ(OpcUa_BadOutOfRange, m_testee.toInt32(int32Result)); 170 | 171 | m_testee.setUInt32(numeric_limits::max()); 172 | EXPECT_EQ(OpcUa_Good, m_testee.toInt32(int32Result)); 173 | EXPECT_EQ(numeric_limits::max(), int32Result); 174 | } 175 | 176 | TEST_F(UaVariantTest, testisEqualOperatorForStringVariants) 177 | { 178 | m_testee.setString("some string value"); 179 | EXPECT_TRUE(m_testee == m_testee); 180 | EXPECT_TRUE(m_testee == UaVariant(UaString("some string value"))); 181 | EXPECT_FALSE(m_testee == UaVariant(UaString("DIFFERENT string value"))); 182 | } 183 | --------------------------------------------------------------------------------