From f84158eecf04e3bd548be0340a3654f480cc5a52 Mon Sep 17 00:00:00 2001 From: James Fantin-Hardesty <24646452+jfantinhardesty@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:50:14 -0700 Subject: [PATCH] Update nx version (#65) * Update nx version * Run clang-format * Fix spelling * Fix spelling issues * Fix clang format --- dependencies/nx_kit/CMakeLists.txt | 8 +- dependencies/nx_kit/build.bat | 70 +++++++ dependencies/nx_kit/build.sh | 83 ++++++++ dependencies/nx_kit/readme.md | 36 ++-- dependencies/nx_kit/src/json11/json11.cpp | 16 +- dependencies/nx_kit/src/nx/kit/debug.cpp | 4 +- dependencies/nx_kit/src/nx/kit/ini_config.h | 8 +- dependencies/nx_kit/src/nx/kit/utils.cpp | 37 ++-- dependencies/nx_kit/src/nx/kit/utils.h | 6 + .../nx_kit/unit_tests/src/ini_config_ut.cpp | 50 ++++- .../nx_kit/unit_tests/src/utils_ut.cpp | 13 ++ .../helpers/consuming_device_agent.cpp | 10 +- .../helpers/consuming_device_agent.h | 20 +- src/lib/nx/sdk/analytics/helpers/engine.cpp | 11 +- src/lib/nx/sdk/analytics/helpers/engine.h | 14 +- .../nx/sdk/analytics/helpers/event_metadata.h | 7 +- .../analytics/helpers/event_metadata_packet.h | 2 +- .../nx/sdk/analytics/helpers/metadata_types.h | 5 +- .../sdk/analytics/helpers/object_metadata.h | 6 +- .../helpers/object_metadata_packet.h | 2 +- .../helpers/object_track_best_shot_packet.h | 2 +- .../sdk/analytics/helpers/object_track_info.h | 4 +- src/lib/nx/sdk/analytics/helpers/plugin.h | 4 +- .../helpers/timestamped_object_metadata.h | 7 +- src/lib/nx/sdk/analytics/i_action.h | 15 +- .../analytics/i_compound_metadata_packet.h | 2 +- .../sdk/analytics/i_compressed_video_packet.h | 7 +- .../sdk/analytics/i_consuming_device_agent.h | 3 +- .../sdk/analytics/i_custom_metadata_packet.h | 3 +- src/lib/nx/sdk/analytics/i_device_agent.h | 14 +- src/lib/nx/sdk/analytics/i_engine.h | 14 +- .../sdk/analytics/i_event_metadata_packet.h | 2 +- src/lib/nx/sdk/analytics/i_metadata.h | 6 +- src/lib/nx/sdk/analytics/i_metadata_packet.h | 3 +- src/lib/nx/sdk/analytics/i_metadata_types.h | 3 +- .../sdk/analytics/i_motion_metadata_packet.h | 3 +- src/lib/nx/sdk/analytics/i_object_metadata.h | 6 +- .../sdk/analytics/i_object_metadata_packet.h | 2 +- .../i_object_track_best_shot_packet.h | 3 +- .../nx/sdk/analytics/i_object_track_info.h | 7 +- src/lib/nx/sdk/analytics/i_plugin.h | 5 +- .../analytics/i_uncompressed_media_frame.h | 3 +- .../analytics/i_uncompressed_video_frame.h | 5 +- src/lib/nx/sdk/analytics/manifests.md | 99 +++++---- src/lib/nx/sdk/analytics/taxonomy.md | 195 +++++++++++------- .../analytics/taxonomy_base_type_library.json | 10 +- src/lib/nx/sdk/attributes.md | 2 +- src/lib/nx/sdk/dynamic_libraries.md | 23 ++- src/lib/nx/sdk/helpers/action_response.cpp | 20 ++ src/lib/nx/sdk/helpers/action_response.h | 13 +- .../helpers/active_setting_changed_action.h | 3 +- .../helpers/active_setting_changed_response.h | 7 +- src/lib/nx/sdk/helpers/attribute.h | 2 +- src/lib/nx/sdk/helpers/device_info.h | 2 +- src/lib/nx/sdk/helpers/error.cpp | 3 +- src/lib/nx/sdk/helpers/lib_context.cpp | 1 + src/lib/nx/sdk/helpers/lib_context.h | 3 +- src/lib/nx/sdk/helpers/lib_context.md | 2 +- src/lib/nx/sdk/helpers/list.h | 5 +- src/lib/nx/sdk/helpers/log_utils.cpp | 8 +- src/lib/nx/sdk/helpers/log_utils.h | 6 +- .../nx/sdk/helpers/media_stream_statistics.h | 4 +- src/lib/nx/sdk/helpers/ref_countable.h | 2 +- src/lib/nx/sdk/helpers/settings_response.h | 5 +- src/lib/nx/sdk/helpers/string.h | 3 +- src/lib/nx/sdk/helpers/string_list.h | 4 +- src/lib/nx/sdk/helpers/string_map.h | 1 - src/lib/nx/sdk/helpers/to_string.h | 6 +- src/lib/nx/sdk/helpers/uuid_helper.h | 2 +- src/lib/nx/sdk/i_action_response.h | 20 +- src/lib/nx/sdk/i_attribute.h | 6 +- src/lib/nx/sdk/i_list.h | 2 + src/lib/nx/sdk/i_settings_response.h | 5 +- src/lib/nx/sdk/i_utility_provider.h | 7 +- src/lib/nx/sdk/ptr.h | 2 +- src/lib/nx/sdk/result.h | 2 + src/lib/nx/sdk/settings_model.md | 32 ++- src/lib/nx/sdk/uuid.h | 1 + src/lib/nx_sdk_version.inc | 2 +- src/unit_tests/src/analytics_plugin_ut.cpp | 2 +- 80 files changed, 692 insertions(+), 351 deletions(-) create mode 100644 dependencies/nx_kit/build.bat create mode 100755 dependencies/nx_kit/build.sh diff --git a/dependencies/nx_kit/CMakeLists.txt b/dependencies/nx_kit/CMakeLists.txt index 7402b9a..0ccba73 100644 --- a/dependencies/nx_kit/CMakeLists.txt +++ b/dependencies/nx_kit/CMakeLists.txt @@ -76,10 +76,12 @@ if(MSVC) endif() # Set the maximum warning level. -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") +if(MSVC) + # This block covers not only Visual Studio compiler but also clang-cl, which expands /W4 to + # the -Wall flag, while -Wall itself, if passed directly, will be expanded to -Weverything. + add_compile_options(/W4 /WX /utf-8) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") add_compile_options(-Wall -Wextra -Werror) -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - add_compile_options(/W4 /WX) endif() set(nxKitWithTests "YES" CACHE STRING "Whether to build unit tests") diff --git a/dependencies/nx_kit/build.bat b/dependencies/nx_kit/build.bat new file mode 100644 index 0000000..a970b41 --- /dev/null +++ b/dependencies/nx_kit/build.bat @@ -0,0 +1,70 @@ +:: Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/ + +@echo off +setlocal %= Reset errorlevel and prohibit changing env vars of the parent shell. =% + +if [%1] == [/?] goto :show_usage +if [%1] == [-h] goto :show_usage +if [%1] == [--help] goto :show_usage +goto :skip_show_usage +:show_usage + echo Usage: %~n0%~x0 [--no-tests] [--debug] [^...] + echo --debug Compile using Debug configuration (without optimizations) instead of Release. + goto :exit +:skip_show_usage + +:: Make the build dir at the same level as the parent dir of this script, suffixed with "-build". +set BASE_DIR_WITH_BACKSLASH=%~dp0 +set BASE_DIR=%BASE_DIR_WITH_BACKSLASH:~0,-1% +set BUILD_DIR=%BASE_DIR%-build + +:: Try to find the vcvars64.bat script, assuming that build_nx_kit.bat runs from the +:: "open/artifacts/nx_kit" subdirectory of the nx repository. +set VCVARS_BAT=%BASE_DIR%\..\..\build_utils\msvc\call_vcvars64.bat +if exist "%VCVARS_BAT%" ( + echo on + call "%VCVARS_BAT%" || goto :exit + @echo off +) + +if [%1] == [--no-tests] ( + shift + set NO_TESTS=1 +) else ( + set NO_TESTS=0 +) + +if [%1] == [--debug] ( + shift + set BUILD_TYPE=Debug +) else ( + set BUILD_TYPE=Release +) + +set GENERATOR_OPTIONS=-GNinja -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe + +echo on +rmdir /S /Q "%BUILD_DIR%" 2>NUL +mkdir "%BUILD_DIR%" || goto :exit +cmake "%BASE_DIR%" -B "%BUILD_DIR%" %GENERATOR_OPTIONS% %1 %2 %3 %4 %5 %6 %7 %8 %9 || goto :exit +cmake --build "%BUILD_DIR%" || goto :exit +@echo off + +:: Run unit tests if needed. +if [%NO_TESTS%] == [1] echo NOTE: Unit tests were not run. & goto :skip_tests + +cd "%BUILD_DIR%\unit_tests" +setlocal +PATH=%BUILD_DIR%;%PATH% +echo on +ctest --output-on-failure -C "${BUILD_TYPE}" || @goto :exit +@echo off +endlocal + +:skip_tests + +echo: +echo Nx kit built successfully, see the library in %BUILD_DIR% + +:exit + exit /b %ERRORLEVEL% %= Needed for a proper cmd.exe exit status. =% diff --git a/dependencies/nx_kit/build.sh b/dependencies/nx_kit/build.sh new file mode 100755 index 0000000..4282198 --- /dev/null +++ b/dependencies/nx_kit/build.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +## Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/ + +set -e #< Exit on error. +set -u #< Prohibit undefined variables. + +if [[ $# > 0 && ($1 == "/?" || $1 == "-h" || $1 == "--help") ]]; then + echo "Usage: $(basename "$0") [--no-tests] [--debug] [...]" + echo " --debug Compile using Debug configuration (without optimizations) instead of Release." + exit +fi + +# Make the build dir at the same level as the parent dir of this script, suffixed with "-build". +declare BASE_DIR="$(readlink -f "$(dirname "$0")")" #< Absolute path to this script's dir. +declare -r BUILD_DIR="${BASE_DIR}-build" + +declare NO_TESTS=0 +if [[ $# > 0 && $1 == "--no-tests" ]]; then + shift + NO_TESTS=1 +fi + +declare BUILD_TYPE="Release" +if [[ $# > 0 && $1 == "--debug" ]]; then + shift + BUILD_TYPE=Debug +fi + +declare -a GEN_OPTIONS=() +declare LIBRARY_NAME="" + +case "$(uname -s)" in #< Check if running in Windows from Cygwin/MinGW. + CYGWIN*|MINGW*) + # Assume that the MSVC environment is set up correctly and Ninja is installed. Also + # specify the compiler explicitly to avoid clashes with gcc. + GEN_OPTIONS+=( -GNinja -DCMAKE_CXX_COMPILER=cl.exe -DCMAKE_C_COMPILER=cl.exe ) + BASE_DIR=$(cygpath -w "${BASE_DIR}") #< Windows-native CMake requires Windows path. + LIBRARY_NAME="nx_kit.dll" + ;; + *) + if command -v ninja &> /dev/null; then #< Use Ninja if it is available on PATH. + GEN_OPTIONS+=( -GNinja ) + fi + LIBRARY_NAME="libnx_kit.so" + ;; +esac + +if [[ "${BUILD_TYPE}" == "Release" ]]; then + GEN_OPTIONS+=( -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" ) +fi + +(set -x #< Log each command. + rm -rf "${BUILD_DIR}/" +) + +cmake "${BASE_DIR}" -B "${BUILD_DIR}" \ + ${GEN_OPTIONS[@]+"${GEN_OPTIONS[@]}"} `#< allow empty array for bash before 4.4 #` \ + "$@" +cmake --build "${BUILD_DIR}" + +if [[ ! -f "${BUILD_DIR}/${LIBRARY_NAME}" ]]; then + echo "ERROR: Failed to build nx_kit." + exit 64 +fi + +echo "" +echo "Built: ${BUILD_DIR}/${LIBRARY_NAME}" +echo "" + +# Run unit tests if needed. +if (( ${NO_TESTS} == 1 )); then + echo "NOTE: Unit tests were not run." +else + cd "${BUILD_DIR}/unit_tests" + PATH="${BUILD_DIR}:${PATH}" + (set -x #< Log each command. + ctest --output-on-failure -C "${BUILD_TYPE}" + ) +fi +echo "" + +echo "Samples built successfully, see the binaries in ${BUILD_DIR}" diff --git a/dependencies/nx_kit/readme.md b/dependencies/nx_kit/readme.md index 1a6030c..78bbcf5 100644 --- a/dependencies/nx_kit/readme.md +++ b/dependencies/nx_kit/readme.md @@ -41,8 +41,8 @@ Currently, the following units are included into nx_kit: --------------------------------------------------------------------------------------------------- ## Building -This kit is suitable to form a source-only artifact `nx_kit` with the only `src` folder in it - -the source code files will be compiled as part of the project that uses the artifact. For cmake +This kit is suitable to form a source-only artifact `nx_kit` with the only `src` folder in it - the +source code files will be compiled as part of the project that uses the artifact. For the CMake users, `CMakeLists.txt` can also be deployed to the artifact to be used in `add_subdirectory()`. All classes and functions in this kit are prefixed with `NX_KIT_API` macro which allows to control @@ -52,18 +52,26 @@ Tests for these utils are located in the `unit_tests` folder. The test project c on Linux using cmake/ctest, on Windows with Cygwin using cmake/ctest or CLion IDE, or on Windows using Microsoft Visual Studio 2012+. -To build and run tests on Linux or Windows+Cygwin, with `CMake >= 3.3.2` and `g++ >= 4.8.4`: -``` -# Make a folder for build results: -mkdir .../nx_kit-build -cd .../nx_kit-build +For convenience and as an example, there are scripts named `build.bat` and `build.sh`. These +scripts build and run `nx_kit` library and its unit tests for Windows and Linux (or +Windows + Cygwin / MinGW / Git Bash), respectively. They serve as wrappers around the standard +CMake build procedure, including the generation stage, building and running ctest. -# Generate Makefiles: -cmake .../nx_kit +Prerequisites: +``` +- CMake >= 3.14 +- Windows (7, 10 or 11): Microsoft Visual Studio >= 2012 +- Linux (Ubuntu 18.04, 20.04, 22.04) + - g++ >= 7.5 + - make or Ninja +``` -# Compile and link: -cmake --build . +Please note that on the Windows platform, if you use one of the provided scripts, you should also +have Ninja installed as part of Microsoft Visual Studio. Additionally, if `build.bat` is +executed within the `nx` repository directory, it attempts to initialize the environment under the +assumption that the Microsoft Visual Studio 2022 Community edition is being used. If any of these +conditions (MSVC version or `nx_kit` directory placement) are not met, the build must be initiated +from an already initialized environment (e.g., the "x64 Native Tools Command Prompt for VS 2022" +for MSVC 2022, or its equivalent for the MSVC version installed on your machine). -# Run tests: -./nx_kit_ut -``` +To view the possible command-line options of the scripts, run them with `-h` or `/?`. diff --git a/dependencies/nx_kit/src/json11/json11.cpp b/dependencies/nx_kit/src/json11/json11.cpp index 503d73e..6de413d 100644 --- a/dependencies/nx_kit/src/json11/json11.cpp +++ b/dependencies/nx_kit/src/json11/json11.cpp @@ -157,7 +157,7 @@ class Value : public JsonValue { // Constructors explicit Value(const T &value) : m_value(value) {} - explicit Value(T &&value) : m_value(std::move(value)) {} + explicit Value(T &&value) : m_value(move(value)) {} // Get type tag Json::Type type() const override { @@ -204,7 +204,7 @@ class JsonString final : public Value { const string &string_value() const override { return m_value; } public: explicit JsonString(const string &value) : Value(value) {} - explicit JsonString(string &&value) : Value(std::move(value)) {} + explicit JsonString(string &&value) : Value(move(value)) {} }; class JsonArray final : public Value { @@ -212,7 +212,7 @@ class JsonArray final : public Value { const Json & operator[](size_t i) const override; public: explicit JsonArray(const Json::array &value) : Value(value) {} - explicit JsonArray(Json::array &&value) : Value(std::move(value)) {} + explicit JsonArray(Json::array &&value) : Value(move(value)) {} }; class JsonObject final : public Value { @@ -220,7 +220,7 @@ class JsonObject final : public Value { const Json & operator[](const string &key) const override; public: explicit JsonObject(const Json::object &value) : Value(value) {} - explicit JsonObject(Json::object &&value) : Value(std::move(value)) {} + explicit JsonObject(Json::object &&value) : Value(move(value)) {} }; class JsonNull final : public Value { @@ -262,12 +262,12 @@ Json::Json(double value) : m_ptr(make_shared(value)) { Json::Json(int value) : m_ptr(make_shared(value)) {} Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {} Json::Json(const string &value) : m_ptr(make_shared(value)) {} -Json::Json(string &&value) : m_ptr(make_shared(std::move(value))) {} +Json::Json(string &&value) : m_ptr(make_shared(move(value))) {} Json::Json(const char * value) : m_ptr(make_shared(value)) {} Json::Json(const Json::array &values) : m_ptr(make_shared(values)) {} -Json::Json(Json::array &&values) : m_ptr(make_shared(std::move(values))) {} +Json::Json(Json::array &&values) : m_ptr(make_shared(move(values))) {} Json::Json(const Json::object &values) : m_ptr(make_shared(values)) {} -Json::Json(Json::object &&values) : m_ptr(make_shared(std::move(values))) {} +Json::Json(Json::object &&values) : m_ptr(make_shared(move(values))) {} /* * * * * * * * * * * * * * * * * * * * * Accessors @@ -382,7 +382,7 @@ struct JsonParser final { * Mark this parse as failed. */ Json fail(string &&msg) { - return fail(std::move(msg), Json()); + return fail(move(msg), Json()); } template diff --git a/dependencies/nx_kit/src/nx/kit/debug.cpp b/dependencies/nx_kit/src/nx/kit/debug.cpp index e7e6085..63e4300 100644 --- a/dependencies/nx_kit/src/nx/kit/debug.cpp +++ b/dependencies/nx_kit/src/nx/kit/debug.cpp @@ -108,7 +108,7 @@ void assertionFailed( { printFunc((std::string("\n") + ">>> ASSERTION FAILED: " - + srcFileRelativePath(file) + ":" + toString(line) + + file + ":" + toString(line) + " (" + conditionStr + ") " + message ).c_str()); @@ -168,7 +168,7 @@ void printHexDump( return; } - s += "\n{\n"; + s += "\n{"; int count = size; const char* p = bytes; while (count > 0) diff --git a/dependencies/nx_kit/src/nx/kit/ini_config.h b/dependencies/nx_kit/src/nx/kit/ini_config.h index e42359d..05c9eaf 100644 --- a/dependencies/nx_kit/src/nx/kit/ini_config.h +++ b/dependencies/nx_kit/src/nx/kit/ini_config.h @@ -156,16 +156,16 @@ class NX_KIT_API IniConfig protected: #define NX_INI_FLAG(DEFAULT, PARAM, DESCRIPTION) \ - const bool PARAM = regBoolParam(&PARAM, DEFAULT, #PARAM, DESCRIPTION) + const bool PARAM = regBoolParam(&(PARAM), DEFAULT, #PARAM, DESCRIPTION) #define NX_INI_INT(DEFAULT, PARAM, DESCRIPTION) \ - const int PARAM = regIntParam(&PARAM, DEFAULT, #PARAM, DESCRIPTION) + const int PARAM = regIntParam(&(PARAM), DEFAULT, #PARAM, DESCRIPTION) #define NX_INI_STRING(DEFAULT, PARAM, DESCRIPTION) \ - const char* const PARAM = regStringParam(&PARAM, DEFAULT, #PARAM, DESCRIPTION) + const char* const PARAM = regStringParam(&(PARAM), DEFAULT, #PARAM, DESCRIPTION) #define NX_INI_FLOAT(DEFAULT, PARAM, DESCRIPTION) \ - const float PARAM = regFloatParam(&PARAM, DEFAULT, #PARAM, DESCRIPTION) + const float PARAM = regFloatParam(&(PARAM), DEFAULT, #PARAM, DESCRIPTION) protected: // Used by the above macros. bool regBoolParam(const bool* pValue, bool defaultValue, diff --git a/dependencies/nx_kit/src/nx/kit/utils.cpp b/dependencies/nx_kit/src/nx/kit/utils.cpp index 1c23d5c..ae0b535 100644 --- a/dependencies/nx_kit/src/nx/kit/utils.cpp +++ b/dependencies/nx_kit/src/nx/kit/utils.cpp @@ -15,8 +15,8 @@ #if defined(_WIN32) #define NOMINMAX //< Needed to prevent windows.h define macros min() and max(). #include + #include #include - #include #elif defined(__APPLE__) #include #else @@ -133,14 +133,24 @@ const std::vector& getProcessCmdLineArgs() LPWSTR* const argv = CommandLineToArgvW(GetCommandLineW(), &argc); if (!argv || argc == 0) { + LocalFree(argv); args = std::vector{""}; return args; } for (int i = 0; i < argc; ++i) { - args.push_back( - std::wstring_convert, wchar_t>().to_bytes(argv[i])); + int utf8Length = WideCharToMultiByte( + CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr); + if (utf8Length > 0) + { + std::string utf8Arg; + // Exclude null-terminator + utf8Arg.resize(utf8Length - 1); + WideCharToMultiByte( + CP_UTF8, 0, argv[i], -1, &utf8Arg[0], utf8Length, nullptr, nullptr); + args.push_back(utf8Arg); + } } LocalFree(argv); #elif defined(__APPLE__) @@ -587,20 +597,14 @@ std::string trimString(const std::string& s) return s.substr(start, end - start + 1); } -namespace { - //------------------------------------------------------------------------------------------------- // Parsing utils. -static bool isWhitespace(char c) -{ - // NOTE: Chars 128..255 should be treated as non-whitespace, thus, isprint() will not do. - return (((unsigned char) c) <= 32) || (c == 127); -} +namespace { static void skipWhitespace(const char** const pp) { - while (**pp != '\0' && isWhitespace(**pp)) + while (**pp != '\0' && isSpaceOrControlChar(**pp)) ++(*pp); } @@ -620,7 +624,7 @@ static ParsedNameValue parseNameValue(const std::string& lineStr) skipWhitespace(&p); if (*p == '\0' || *p == '#') //< Empty or comment line. return result; - while (*p != '\0' && *p != '=' && !isWhitespace(*p)) + while (*p != '\0' && *p != '=' && !isSpaceOrControlChar(*p)) result.name += *(p++); if (result.name.empty()) { @@ -631,7 +635,7 @@ static ParsedNameValue parseNameValue(const std::string& lineStr) if (*(p++) != '=') { - result.error = "Missing \"=\" after the name " + result.name + "."; + result.error = "Missing \"=\" after the name " + toString(result.name) + "."; return result; } skipWhitespace(&p); @@ -641,7 +645,7 @@ static ParsedNameValue parseNameValue(const std::string& lineStr) // Trim trailing whitespace in the value. int i = (int) result.value.size() - 1; - while (i >= 0 && isWhitespace(result.value[i])) + while (i >= 0 && isSpaceOrControlChar(result.value[i])) --i; result.value = result.value.substr(0, i + 1); @@ -670,6 +674,11 @@ bool parseNameValueFile( while (std::getline(file, lineStr)) { ++line; + + static constexpr char kBom[] = "\xEF\xBB\xBF"; + if (line == 1 && stringStartsWith(lineStr, kBom)) + lineStr.erase(0, sizeof(kBom) - /* Terminating NUL */ 1); + const ParsedNameValue parsed = parseNameValue(lineStr); if (!parsed.error.empty()) { diff --git a/dependencies/nx_kit/src/nx/kit/utils.h b/dependencies/nx_kit/src/nx/kit/utils.h index ad8472d..319b6fb 100644 --- a/dependencies/nx_kit/src/nx/kit/utils.h +++ b/dependencies/nx_kit/src/nx/kit/utils.h @@ -42,6 +42,12 @@ inline bool isAsciiPrintable(int c) return c >= 32 && c <= 126; } +inline bool isSpaceOrControlChar(char c) +{ + // NOTE: Chars 128..255 should be treated as non-whitespace, thus, isprint() will not do. + return (((unsigned char) c) <= 32) || (c == 127); +} + /** * Decodes a string encoded using C/C++ string literal rules: enquoted, potentially containing * escape sequences. Supports concatenation of consecutive literals, thus, fully compatible with diff --git a/dependencies/nx_kit/unit_tests/src/ini_config_ut.cpp b/dependencies/nx_kit/unit_tests/src/ini_config_ut.cpp index 0cc7670..a1bd78a 100644 --- a/dependencies/nx_kit/unit_tests/src/ini_config_ut.cpp +++ b/dependencies/nx_kit/unit_tests/src/ini_config_ut.cpp @@ -274,7 +274,7 @@ floatNumber=non-number /*suppress newline*/ 1 + (const char*) R"( test.ini [{iniFilePath}] -test.ini ERROR: Missing "=" after the name missingEqualsAfterName. Line 3, file {iniFilePath} +test.ini ERROR: Missing "=" after the name "missingEqualsAfterName". Line 3, file {iniFilePath} test.ini ERROR: The name part (before "=") is empty. Line 4, file {iniFilePath} ! enableOutput=false [invalid value in file] ! enableTime=true [invalid value in file] @@ -301,6 +301,54 @@ test.ini ERROR: The name part (before "=") is empty. Line 4, file {iniFilePath} )"); } +static void testBom(const char* iniFileContentPrefix) +{ + if (!IniConfig::isEnabled()) + { + std::cerr << "IniConfig::isEnabled() -> false" << std::endl; + return; //< Nothing to test if IniConfig is disabled at compile time. + } + + IniConfig::setIniFilesDir(nx::kit::test::tempDir()); + + TestIni ini; + + TestIni expectedIni; + const_cast(expectedIni.enableOutput) = true; + + nx::kit::test::createFile( + ini.iniFilePath(), + std::string(iniFileContentPrefix) + "enableOutput=true"); + + testReload(__LINE__, expectedIni, &ini, "testBom", + /*suppress newline*/ 1 + (const char*) +R"( +test.ini [{iniFilePath}] + * enableOutput=true + enableTime=true + enableFps=true + str0=" string with leading space" + str1="string with middle \" quote" + str2="\" string with leading quote" + str3="string with trailing quote \"" + str4="\"enquoted string\"" + str5="plain string" + str6="plain string with \\ backslash" + intNumber=113 + floatNumber=310.55 +)"); +} + +TEST(iniConfig, testBomAtStartOfFirstLine) +{ + testBom("\xEF\xBB\xBF"); +} + +TEST(iniConfig, testBomAsFirstLine) +{ + testBom("\xEF\xBB\xBF\n"); +} + TEST(iniConfig, testGetParamTypeAndValue) { if (!IniConfig::isEnabled()) diff --git a/dependencies/nx_kit/unit_tests/src/utils_ut.cpp b/dependencies/nx_kit/unit_tests/src/utils_ut.cpp index 740c642..0fb80d3 100644 --- a/dependencies/nx_kit/unit_tests/src/utils_ut.cpp +++ b/dependencies/nx_kit/unit_tests/src/utils_ut.cpp @@ -522,6 +522,19 @@ TEST(utils, trimString) ASSERT_EQ("a\nb", trimString("a\nb\n\n")); } +TEST(utils, isSpaceOrControlChar) +{ + for (char c = 0; c <= 32; ++c) + { + ASSERT_TRUE(isSpaceOrControlChar(c)); + } + ASSERT_TRUE(isSpaceOrControlChar(127)); + ASSERT_FALSE(isSpaceOrControlChar('a')); + ASSERT_FALSE(isSpaceOrControlChar('A')); + ASSERT_FALSE(isSpaceOrControlChar('\x9C')); + ASSERT_FALSE(isSpaceOrControlChar('\xEA')); +} + TEST(utils, toUpper) { ASSERT_EQ("", toUpper("")); diff --git a/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.cpp b/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.cpp index 848eb63..e44fe7d 100644 --- a/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.cpp +++ b/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.cpp @@ -2,10 +2,6 @@ #include "consuming_device_agent.h" -#define NX_PRINT_PREFIX (this->logUtils.printPrefix) -#define NX_DEBUG_ENABLE_OUTPUT (this->logUtils.enableOutput) -#include - #include #include #include @@ -19,6 +15,12 @@ #include #include +#undef NX_PRINT_PREFIX +#define NX_PRINT_PREFIX (this->logUtils.printPrefix) +#undef NX_DEBUG_ENABLE_OUTPUT +#define NX_DEBUG_ENABLE_OUTPUT (this->logUtils.enableOutput) +#include + namespace nx::sdk::analytics { static std::string makePrintPrefix( diff --git a/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.h b/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.h index 4770fac..3d9aa84 100644 --- a/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.h +++ b/src/lib/nx/sdk/analytics/helpers/consuming_device_agent.h @@ -11,22 +11,21 @@ #endif #endif -#include #include -#include #include +#include +#include -#include -#include -#include - -#include -#include #include -#include #include -#include +#include #include +#include +#include +#include +#include +#include +#include namespace nx::sdk::analytics { @@ -38,6 +37,7 @@ namespace nx::sdk::analytics { * To use NX_PRINT/NX_OUTPUT in a derived class with the prefix defined by this class, add the * following to the derived class .cpp: *

+ *     #undef NX_PRINT_PREFIX
  *     #define NX_PRINT_PREFIX (this->logUtils.printPrefix)
  *     #include 
  * 
diff --git a/src/lib/nx/sdk/analytics/helpers/engine.cpp b/src/lib/nx/sdk/analytics/helpers/engine.cpp index e3aa2dc..f0cc528 100644 --- a/src/lib/nx/sdk/analytics/helpers/engine.cpp +++ b/src/lib/nx/sdk/analytics/helpers/engine.cpp @@ -2,13 +2,8 @@ #include "engine.h" -#define NX_PRINT_PREFIX (this->logUtils.printPrefix) -#define NX_DEBUG_ENABLE_OUTPUT (this->logUtils.enableOutput) -#include #include - #include - #include #include #include @@ -19,6 +14,12 @@ #include #include +#undef NX_PRINT_PREFIX +#define NX_PRINT_PREFIX (this->logUtils.printPrefix) +#undef NX_DEBUG_ENABLE_OUTPUT +#define NX_DEBUG_ENABLE_OUTPUT (this->logUtils.enableOutput) +#include + namespace nx::sdk::analytics { static std::string makePrintPrefix( diff --git a/src/lib/nx/sdk/analytics/helpers/engine.h b/src/lib/nx/sdk/analytics/helpers/engine.h index 1614b2d..8ec6ffa 100644 --- a/src/lib/nx/sdk/analytics/helpers/engine.h +++ b/src/lib/nx/sdk/analytics/helpers/engine.h @@ -10,20 +10,17 @@ #define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR #endif #endif - -#include #include #include +#include -#include #include - -#include -#include - +#include #include +#include #include -#include +#include +#include namespace nx::sdk::analytics { @@ -34,6 +31,7 @@ namespace nx::sdk::analytics { * To use NX_PRINT/NX_OUTPUT in a derived class with the prefix defined by this class, add the * following to the derived class .cpp: *

+ *     #undef NX_PRINT_PREFIX
  *     #define NX_PRINT_PREFIX (this->logUtils.printPrefix)
  *     #include 
  * 
diff --git a/src/lib/nx/sdk/analytics/helpers/event_metadata.h b/src/lib/nx/sdk/analytics/helpers/event_metadata.h index c00e31f..8f2005f 100644 --- a/src/lib/nx/sdk/analytics/helpers/event_metadata.h +++ b/src/lib/nx/sdk/analytics/helpers/event_metadata.h @@ -6,10 +6,9 @@ #include #include - -#include -#include #include +#include +#include namespace nx::sdk::analytics { @@ -49,4 +48,4 @@ class EventMetadata: public RefCountable std::string m_key; }; -} // namespace nx::sdk::analytics \ No newline at end of file +} // namespace nx::sdk::analytics diff --git a/src/lib/nx/sdk/analytics/helpers/event_metadata_packet.h b/src/lib/nx/sdk/analytics/helpers/event_metadata_packet.h index 99e0bef..3b54ef6 100644 --- a/src/lib/nx/sdk/analytics/helpers/event_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/helpers/event_metadata_packet.h @@ -4,9 +4,9 @@ #include +#include #include #include -#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/helpers/metadata_types.h b/src/lib/nx/sdk/analytics/helpers/metadata_types.h index fcec405..9657284 100644 --- a/src/lib/nx/sdk/analytics/helpers/metadata_types.h +++ b/src/lib/nx/sdk/analytics/helpers/metadata_types.h @@ -2,11 +2,10 @@ #pragma once +#include #include - -#include #include -#include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/helpers/object_metadata.h b/src/lib/nx/sdk/analytics/helpers/object_metadata.h index 57cd455..2b8f896 100644 --- a/src/lib/nx/sdk/analytics/helpers/object_metadata.h +++ b/src/lib/nx/sdk/analytics/helpers/object_metadata.h @@ -5,13 +5,11 @@ #include #include +#include #include #include #include - #include -#include -#include namespace nx::sdk::analytics { @@ -46,4 +44,4 @@ class ObjectMetadata: public RefCountable Rect m_rect; }; -} // namespace nx::sdk::analytics \ No newline at end of file +} // namespace nx::sdk::analytics diff --git a/src/lib/nx/sdk/analytics/helpers/object_metadata_packet.h b/src/lib/nx/sdk/analytics/helpers/object_metadata_packet.h index ccedba8..b2a9462 100644 --- a/src/lib/nx/sdk/analytics/helpers/object_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/helpers/object_metadata_packet.h @@ -4,9 +4,9 @@ #include +#include #include #include -#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/helpers/object_track_best_shot_packet.h b/src/lib/nx/sdk/analytics/helpers/object_track_best_shot_packet.h index 8da657c..ba6aa85 100644 --- a/src/lib/nx/sdk/analytics/helpers/object_track_best_shot_packet.h +++ b/src/lib/nx/sdk/analytics/helpers/object_track_best_shot_packet.h @@ -4,9 +4,9 @@ #include +#include #include #include -#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/helpers/object_track_info.h b/src/lib/nx/sdk/analytics/helpers/object_track_info.h index c9547d3..3cbe96e 100644 --- a/src/lib/nx/sdk/analytics/helpers/object_track_info.h +++ b/src/lib/nx/sdk/analytics/helpers/object_track_info.h @@ -3,10 +3,10 @@ #pragma once #include -#include -#include #include +#include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/helpers/plugin.h b/src/lib/nx/sdk/analytics/helpers/plugin.h index b2f9e50..2522780 100644 --- a/src/lib/nx/sdk/analytics/helpers/plugin.h +++ b/src/lib/nx/sdk/analytics/helpers/plugin.h @@ -2,12 +2,12 @@ #pragma once -#include #include +#include -#include #include #include +#include #include #include "engine.h" diff --git a/src/lib/nx/sdk/analytics/helpers/timestamped_object_metadata.h b/src/lib/nx/sdk/analytics/helpers/timestamped_object_metadata.h index 85e0716..61d6eb9 100644 --- a/src/lib/nx/sdk/analytics/helpers/timestamped_object_metadata.h +++ b/src/lib/nx/sdk/analytics/helpers/timestamped_object_metadata.h @@ -4,12 +4,11 @@ #include -#include - -#include -#include #include +#include #include +#include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_action.h b/src/lib/nx/sdk/analytics/i_action.h index 1ec632c..cae217d 100644 --- a/src/lib/nx/sdk/analytics/i_action.h +++ b/src/lib/nx/sdk/analytics/i_action.h @@ -4,11 +4,10 @@ #include +#include +#include #include - #include -#include -#include namespace nx::sdk::analytics { @@ -65,6 +64,16 @@ class IAction: public Interface * actionUrl must be null or empty. */ Ptr messageToUser; + + /** + * Whether proxying through the connected server should be used for actionUrl. + */ + bool useProxy = false; + + /** + * Whether device authentication should be used for actionUrl. + */ + bool useDeviceCredentials = false; }; }; using IAction0 = IAction; diff --git a/src/lib/nx/sdk/analytics/i_compound_metadata_packet.h b/src/lib/nx/sdk/analytics/i_compound_metadata_packet.h index 9fa9a92..e8fa404 100644 --- a/src/lib/nx/sdk/analytics/i_compound_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/i_compound_metadata_packet.h @@ -6,8 +6,8 @@ #include -#include "i_metadata_packet.h" #include "i_metadata.h" +#include "i_metadata_packet.h" namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_compressed_video_packet.h b/src/lib/nx/sdk/analytics/i_compressed_video_packet.h index e24bdb5..2e4e86a 100644 --- a/src/lib/nx/sdk/analytics/i_compressed_video_packet.h +++ b/src/lib/nx/sdk/analytics/i_compressed_video_packet.h @@ -2,11 +2,10 @@ #pragma once -#include - -#include -#include #include +#include +#include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_consuming_device_agent.h b/src/lib/nx/sdk/analytics/i_consuming_device_agent.h index e94fb05..99d8b74 100644 --- a/src/lib/nx/sdk/analytics/i_consuming_device_agent.h +++ b/src/lib/nx/sdk/analytics/i_consuming_device_agent.h @@ -2,10 +2,9 @@ #pragma once -#include - #include #include +#include #include "i_data_packet.h" #include "i_device_agent.h" diff --git a/src/lib/nx/sdk/analytics/i_custom_metadata_packet.h b/src/lib/nx/sdk/analytics/i_custom_metadata_packet.h index 6cc0534..02e06cb 100644 --- a/src/lib/nx/sdk/analytics/i_custom_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/i_custom_metadata_packet.h @@ -2,9 +2,8 @@ #pragma once -#include - #include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_device_agent.h b/src/lib/nx/sdk/analytics/i_device_agent.h index 19ee417..02b11d6 100644 --- a/src/lib/nx/sdk/analytics/i_device_agent.h +++ b/src/lib/nx/sdk/analytics/i_device_agent.h @@ -2,16 +2,14 @@ #pragma once -#include -#include - -#include -#include +#include +#include #include #include - -#include -#include +#include +#include +#include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_engine.h b/src/lib/nx/sdk/analytics/i_engine.h index c8174d8..c7232aa 100644 --- a/src/lib/nx/sdk/analytics/i_engine.h +++ b/src/lib/nx/sdk/analytics/i_engine.h @@ -2,20 +2,18 @@ #pragma once -#include -#include - -#include -#include -#include - #include #include +#include +#include #include +#include +#include +#include +#include "i_action.h" #include "i_device_agent.h" #include "i_engine_info.h" -#include "i_action.h" namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_event_metadata_packet.h b/src/lib/nx/sdk/analytics/i_event_metadata_packet.h index 5b8458e..662ee5c 100644 --- a/src/lib/nx/sdk/analytics/i_event_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/i_event_metadata_packet.h @@ -4,8 +4,8 @@ #include -#include "i_event_metadata.h" #include "i_compound_metadata_packet.h" +#include "i_event_metadata.h" namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_metadata.h b/src/lib/nx/sdk/analytics/i_metadata.h index 5559a45..2fa50d5 100644 --- a/src/lib/nx/sdk/analytics/i_metadata.h +++ b/src/lib/nx/sdk/analytics/i_metadata.h @@ -2,8 +2,8 @@ #pragma once -#include #include +#include namespace nx::sdk::analytics { @@ -31,9 +31,9 @@ class IMetadata: public Interface /** * Provides values of so-called Metadata Attributes - typically, some object or event * properties (e.g. age or color), represented as a name-value map. - * + * * See the specification for Attribute names in @ref md_src_nx_sdk_attributes. - * + * * @param index 0-based index of the attribute. * @return Item of an attribute array, or null if index is out of range. */ diff --git a/src/lib/nx/sdk/analytics/i_metadata_packet.h b/src/lib/nx/sdk/analytics/i_metadata_packet.h index dce445a..af64e80 100644 --- a/src/lib/nx/sdk/analytics/i_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/i_metadata_packet.h @@ -2,9 +2,8 @@ #pragma once -#include - #include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_metadata_types.h b/src/lib/nx/sdk/analytics/i_metadata_types.h index 3a32f9d..c6e64c5 100644 --- a/src/lib/nx/sdk/analytics/i_metadata_types.h +++ b/src/lib/nx/sdk/analytics/i_metadata_types.h @@ -2,9 +2,8 @@ #pragma once -#include - #include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_motion_metadata_packet.h b/src/lib/nx/sdk/analytics/i_motion_metadata_packet.h index 61fed71..1ee0821 100644 --- a/src/lib/nx/sdk/analytics/i_motion_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/i_motion_metadata_packet.h @@ -2,9 +2,8 @@ #pragma once -#include - #include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_object_metadata.h b/src/lib/nx/sdk/analytics/i_object_metadata.h index 4ea9907..831c8fb 100644 --- a/src/lib/nx/sdk/analytics/i_object_metadata.h +++ b/src/lib/nx/sdk/analytics/i_object_metadata.h @@ -2,11 +2,11 @@ #pragma once +#include +#include +#include #include #include -#include -#include -#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_object_metadata_packet.h b/src/lib/nx/sdk/analytics/i_object_metadata_packet.h index 962a454..087cc23 100644 --- a/src/lib/nx/sdk/analytics/i_object_metadata_packet.h +++ b/src/lib/nx/sdk/analytics/i_object_metadata_packet.h @@ -4,8 +4,8 @@ #include -#include "i_object_metadata.h" #include "i_compound_metadata_packet.h" +#include "i_object_metadata.h" namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_object_track_best_shot_packet.h b/src/lib/nx/sdk/analytics/i_object_track_best_shot_packet.h index 202d75f..3a7a695 100644 --- a/src/lib/nx/sdk/analytics/i_object_track_best_shot_packet.h +++ b/src/lib/nx/sdk/analytics/i_object_track_best_shot_packet.h @@ -2,11 +2,10 @@ #pragma once -#include - #include #include #include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_object_track_info.h b/src/lib/nx/sdk/analytics/i_object_track_info.h index 624f3b5..ecf9bb9 100644 --- a/src/lib/nx/sdk/analytics/i_object_track_info.h +++ b/src/lib/nx/sdk/analytics/i_object_track_info.h @@ -2,12 +2,11 @@ #pragma once -#include -#include - +#include #include #include -#include +#include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_plugin.h b/src/lib/nx/sdk/analytics/i_plugin.h index 05c88f8..199c33f 100644 --- a/src/lib/nx/sdk/analytics/i_plugin.h +++ b/src/lib/nx/sdk/analytics/i_plugin.h @@ -2,12 +2,11 @@ #pragma once +#include +#include #include #include -#include -#include - #include "i_engine.h" namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_uncompressed_media_frame.h b/src/lib/nx/sdk/analytics/i_uncompressed_media_frame.h index f81c421..48b965b 100644 --- a/src/lib/nx/sdk/analytics/i_uncompressed_media_frame.h +++ b/src/lib/nx/sdk/analytics/i_uncompressed_media_frame.h @@ -2,9 +2,8 @@ #pragma once -#include - #include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/i_uncompressed_video_frame.h b/src/lib/nx/sdk/analytics/i_uncompressed_video_frame.h index 967ca23..71a2fbb 100644 --- a/src/lib/nx/sdk/analytics/i_uncompressed_video_frame.h +++ b/src/lib/nx/sdk/analytics/i_uncompressed_video_frame.h @@ -2,11 +2,10 @@ #pragma once -#include - -#include #include #include +#include +#include namespace nx::sdk::analytics { diff --git a/src/lib/nx/sdk/analytics/manifests.md b/src/lib/nx/sdk/analytics/manifests.md index 1def2e1..861596a 100644 --- a/src/lib/nx/sdk/analytics/manifests.md +++ b/src/lib/nx/sdk/analytics/manifests.md @@ -1,12 +1,11 @@ # Analytics Plugin Manifests -// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: +// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/ This document describes the schemas of JSON Manifests that are returned by various Analytics entities - nx::sdk::analytics::IPlugin, IEngine, and IDeviceAgent. Each Manifest is a JSON object containing fields which can be of the following semantic types: - - String. - Integer (Number). - Float (Number) - Floating-point number. @@ -23,7 +22,6 @@ Each Manifest is a JSON object containing fields which can be of the following s [src/nx/sdk/analytics/taxonomy.md](@ref md_src_nx_sdk_analytics_taxonomy). The following rules apply to the Manifest as a JSON document: - - Missing object fields are treated as having a default value. Default values are described in this document. - Unknown object fields are ignored. Thus, if a field name has a typo, it will be ignored and @@ -35,7 +33,6 @@ example can be found in Sample Analytics Plugin, and the most comprehensive exam possible features can be found in Stub Analytics Plugin. --------------------------------------------------------------------------------------------------- - ## Identifiers Various entities declared in the Manifests make use of identifiers, including the Plugin itself and @@ -62,7 +59,6 @@ features. Identifiers with `.sys.` in the middle are recognized by VMS to have s behavior. --------------------------------------------------------------------------------------------------- - ## Plugin Manifest Plugin Manifest is a JSON Object containing the following fields: @@ -113,7 +109,6 @@ Plugin Manifest is a JSON Object containing the following fields: Optional. If omitted or empty, means there are no settings. --------------------------------------------------------------------------------------------------- - ## Engine Manifest Engine Manifest is a JSON Object containing the following fields: @@ -122,23 +117,23 @@ Engine Manifest is a JSON Object containing the following fields: A combination of zero or more of the following flags, separated with `|`: - - Flags defining the format of video frames that the Server supplies to the Plugin. No more + - Flags defining the format of video frames that the Server supplies to the Plugin. No more than one of the following flags can be specified. If none are specified, the Plugin will be supplied the compressed video frames: IConsumingDeviceAgent::doPushDataPacket() will receive instances of ICompressedVideoPacket. Otherwise, IConsumingDeviceAgent::doPushDataPacket() will receive instances of IUncompressedVideoFrame. - - `needUncompressedVideoFrames_yuv420` - This is the most effective video format, because + - `needUncompressedVideoFrames_yuv420` - This is the most effective video format, because it is used internally by the Server, and thus no video frame decoding is needed. - - `needUncompressedVideoFrames_argb` - - `needUncompressedVideoFrames_abgr` - - `needUncompressedVideoFrames_rgba` - - `needUncompressedVideoFrames_bgra` - - `needUncompressedVideoFrames_rgb` - - `needUncompressedVideoFrames_bgr` - - - `deviceDependent` - If set, influences the certain aspects of handling of the Plugin. It is + - `needUncompressedVideoFrames_argb` + - `needUncompressedVideoFrames_abgr` + - `needUncompressedVideoFrames_rgba` + - `needUncompressedVideoFrames_bgra` + - `needUncompressedVideoFrames_rgb` + - `needUncompressedVideoFrames_bgr` + + - `deviceDependent` - If set, influences the certain aspects of handling of the Plugin. It is intended for Plugins which "work on a device", that is, are wrappers for the video analytics running inside the camera. For example, such Plugins are compatible with a certain camera family, and typically do not consume the video stream from the Server. Also, @@ -148,7 +143,7 @@ Engine Manifest is a JSON Object containing the following fields: for example, such Plugins may analyze video from any camera using either their own code, or via some backend (a server or an analytics device). - - `keepObjectBoundingBoxRotation` - When a camera for which the Plugin is working has frame + - `keepObjectBoundingBoxRotation` - When a camera for which the Plugin is working has frame rotation option set to 90, 180 or 270 degrees, the Plugin which requests uncompressed video frames receives them rotated accordingly. Regardless of whether the plugin requests compressed or uncompressed video, the Object Metadata rectangles produced by the Plugin are @@ -168,11 +163,11 @@ Engine Manifest is a JSON Object containing the following fields: of streaming data will the plugin receive from the Server in IConsumingDeviceAgent::doPushDataPacket(): - - `compressedVideo` - Compressed video packets, as ICompressedVideoPacket. - - `uncompressedVideo` - Uncompressed video frames, as IUncompressedVideoFrame. - - `metadata` - Metadata that comes in the stream (e.g. RTSP) that goes from the Device to the + - `compressedVideo` - Compressed video packets, as ICompressedVideoPacket. + - `uncompressedVideo` - Uncompressed video frames, as IUncompressedVideoFrame. + - `metadata` - Metadata that comes in the stream (e.g. RTSP) that goes from the Device to the Server, as ICustomMetadataPacket. - - `motion` - Motion metadata retrieved by the Server's Motion Engine, as IMotionMetadataPacket. + - `motion` - Motion metadata retrieved by the Server's Motion Engine, as IMotionMetadataPacket. Optional; default value is empty. @@ -181,9 +176,9 @@ Engine Manifest is a JSON Object containing the following fields: For plugins consuming a video stream, declares which of the video streams from a camera is preferred by the plugin: a low-resolution one, or a high-resolution one. - - `"undefined"` - VMS choses the stream automatically. - - `"primary"` - High-resolution stream. - - `"secondary"` - Low-resolution stream. + - `"undefined"` - VMS choses the stream automatically. + - `"primary"` - High-resolution stream. + - `"secondary"` - Low-resolution stream. Optional; default value is `"undefined"`. @@ -208,51 +203,51 @@ Engine Manifest is a JSON Object containing the following fields: This JSON object has the following fields: - - `"id"`: Id (String) + - `"id"`: Id (String) Id of the action type, like `"vendor.pluginName.actionName"`. - - `"name"`: String + - `"name"`: String Action name to be shown to the user. - - `"supportedObjectTypeIds"`: Array + - `"supportedObjectTypeIds"`: Array List of ObjectType ids that are compatible with this Action. An empty list means that the Action supports any type of Objects. - - `"parametersModel"`: SettingsModel (Object) + - `"parametersModel"`: SettingsModel (Object) Describes the names, types, and default values of the parameters that the user must supply before executing the Action. - - `"requirements"`: Object + - `"requirements"`: Object Information about the Action that the Server needs to know. A JSON object with the following fields: - - `"capabilities"`: Flag set (String) + - `"capabilities"`: Flag set (String) A combination of zero or more of the following flags, separated with `|`: - - `needBestShotVideoFrame` - Whether the Action requires the Server to provide it with + - `needBestShotVideoFrame` - Whether the Action requires the Server to provide it with the Best Shot video frame via IAction::getObjectTrackInfo(). If this capability is not set, then IObjectTrackInfo::bestShotVideoFrame() will return null to the plugin. - - `needBestShotImage` - Whether the Action requires the Server to provide it with the + - `needBestShotImage` - Whether the Action requires the Server to provide it with the Best Shot image, Best Shot image data size and Best Shot image data format via IAction::getObjectTrackInfo(). If this capability is not set, then IObjectTrackInfo::bestShotImageData() will return null to the plugin, IObjectTrackInfo::bestShotImageDataFormat() will return an empty string to the plugin, and IObjectTrackInfo::bestShotImageDataSize() will return 0 to the plugin. - - `needBestShotObjectMetadata` - Whether the Action requires the Server to provide it + - `needBestShotObjectMetadata` - Whether the Action requires the Server to provide it with the Best Shot rectangle via IAction::getObjectTrackInfo(). If this capability is not set, then IObjectTrackInfo::bestShotObjectMetadata() will return null to the plugin. - - `needFullTrack` - Whether the Action requires the Server to provide it with the full + - `needFullTrack` - Whether the Action requires the Server to provide it with the full Object track via IAction::getObjectTrackInfo(). If this capability is not set, then IObjectTrackInfo::track() will return null to the plugin, but the Server performance on executing the action will be much better, because there will @@ -261,17 +256,17 @@ Engine Manifest is a JSON Object containing the following fields: Optional; default value is empty. - - `"bestShotVideoFramePixelFormat"`: Enumeration (String) + - `"bestShotVideoFramePixelFormat"`: Enumeration (String) If the `"capabilities"` field includes `needBestShotVideoFrame`, this field must be present and have one of the following: - - `"yuv420"` - - `"argb"` - - `"abgr"` - - `"rgba"` - - `"bgra"` - - `"rgb"` - - `"bgr"` + - `"yuv420"` + - `"argb"` + - `"abgr"` + - `"rgba"` + - `"bgra"` + - `"rgb"` + - `"bgr"` - `"deviceAgentSettingsModel"`: SettingsModel (Object) @@ -281,7 +276,6 @@ Engine Manifest is a JSON Object containing the following fields: Optional. If omitted or empty, means there are no settings. --------------------------------------------------------------------------------------------------- - ## DeviceAgent Manifest DeviceAgent Manifest is a JSON Object containing the following fields: @@ -290,7 +284,7 @@ DeviceAgent Manifest is a JSON Object containing the following fields: A combination of zero or more of the following flags, separated with `|`: - - `disableStreamSelection` - If set, the user will not be offered to choose between the Primary + - `disableStreamSelection` - If set, the user will not be offered to choose between the Primary (high-quality) and Secondary (low-quality) streams when activating this plugin for a camera. @@ -298,12 +292,13 @@ DeviceAgent Manifest is a JSON Object containing the following fields: - `"supportedTypes"`: Array - Whitelist (filter) of Event and Object types for types declared in the owner Engine manifest, - or in imported libraries. Contains a list of JSON objects with the following fields: + Whitelist (filter) of Event and Object types for types declared in this DeviceAgent manifest, + or in the owner Engine manifest, or in the imported libraries. Contains a list of JSON objects + with the following fields: - - `"objectTypeId"` or `"eventTypeId"`: String + - `"objectTypeId"` or `"eventTypeId"`: String - - `"attributes"`: Array + - `"attributes"`: Array List of those Attributes of the specified type, which are supported (i.e. are expected to be generated) by this DeviceAgent. @@ -320,10 +315,10 @@ DeviceAgent Manifest is a JSON Object containing the following fields: - `"typeLibrary"`: Object Types of Events, Objects and their Attributes that can be generated by this particular - DeviceAgent instance or be used as an Attribute subtype. If an Event or Object of some type from - this section can be generated by DeviceAgent directly as an Object or Event (not as an - Attribute), it has to be whitelisted in the `"supportedTypes"` section to make VMS know how to - properly show it in the GUI. + DeviceAgent instance or be used as an Attribute subtype. If an Event or Object of some type + from this section can be generated by the DeviceAgent directly as an Object or Event (not as an + aggregated Attribute of a compound Object), it has to be whitelisted in the `"supportedTypes"` + section to make VMS know how to properly show it in the GUI. The structure of this JSON object is described in the dedicated document [src/nx/sdk/analytics/taxonomy.md](@ref md_src_nx_sdk_analytics_taxonomy). diff --git a/src/lib/nx/sdk/analytics/taxonomy.md b/src/lib/nx/sdk/analytics/taxonomy.md index 0ca5aa6..d4c33f4 100644 --- a/src/lib/nx/sdk/analytics/taxonomy.md +++ b/src/lib/nx/sdk/analytics/taxonomy.md @@ -1,6 +1,6 @@ # Analytics Taxonomy -// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: +// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/ This document describes the mechanism for defining Event and Object types and their Attributes. Such definitions are made in `"typeLibrary"` field in the Engine or DeviceAgent JSON manifest; for @@ -17,47 +17,46 @@ Analytics Plugin, "Taxonomy features" sub-plugin, located in this SDK: samples/stub_analytics_plugin/src/nx/vms_server_plugins/analytics/stub/taxonomy_features/device_agent_manifest.h --------------------------------------------------------------------------------------------------- - ## General information - Error processing: - - When a Library is parsed by the Server, it may produce errors, but the Server recovers in the + - When a Library is parsed by the Server, it may produce errors, but the Server recovers in the most obvious way (e.g. ignoring a faulty entity) and continues parsing. The errors are logged in the regular Server log. - Attribute values: - - The pack of Attributes is represented as a string-to-string multi-map. - - Any Attribute of a scalar type can hold more than one value, so actually every type is a + - The pack of Attributes is represented as a string-to-string multi-map. + - Any Attribute of a scalar type can hold more than one value, so actually every type is a set. - - Empty set is equivalent to the omitted value. - - Set with a single value is equivalent to a scalar value. - - Set with more than one value is called an underdetermined value - semantically, it + - Empty set is equivalent to the omitted value. + - Set with a single value is equivalent to a scalar value. + - Set with more than one value is called an underdetermined value - semantically, it may stand for an ambiguously or simultaneously detected properties. - - Attribute value is technically always a string: for String type, it's the value string as is, + - Attribute value is technically always a string: for String type, it's the value string as is, for other types it's a JSON value. - - Any Attribute value can be omitted; there is no concept of a default value of an Attribute. - - Empty string, `null` (for Attributes which values are JSON objects) and `[]` (for Attributes + - Any Attribute value can be omitted; there is no concept of a default value of an Attribute. + - Empty string, `null` (for Attributes which values are JSON objects) and `[]` (for Attributes which values are JSON lists) are equivalent to the omitted value. - Identifiers: - - Used as ids of Enums (not their names, nor their items), Object types, Event types. - - Contain only Latin letters, digits, minuses, underscores, and braces; must start with a + - Used as ids of Enums (not their names, nor their items), Object types, Event types. + - Contain only Latin letters, digits, minuses, underscores, and braces; must start with a letter, digit or an underscore. - - The period is used to form a domain-style notation, with the recommendation to drop the + - The period is used to form a domain-style notation, with the recommendation to drop the prefix `com.`. - - If this syntax is broken (including leading/trailing/multiple periods), it is an error; as a + - If this syntax is broken (including leading/trailing/multiple periods), it is an error; as a recovery, the incorrect identifier is accepted as is. - - If some entity with an identifier is defined more than once in the particular Library being + - If some entity with an identifier is defined more than once in the particular Library being parsed, all these definitions yield entities with the identical internal representation (thus, only syntactical JSON differences are allowed), and then they are treated as the same entity (thus, all definitions except one are ignored). If some definitions with the same id in the same library differ in the internal representation, it is an error. - Names: - - Used for names of Attributes, Object types, Event types, Enums, Enum items. - - Contain only ASCII chars 33..126, Unicode chars >=128 (non-printables are discouraged but not + - Used for names of Attributes, Object types, Event types, Enums, Enum items. + - Contain only ASCII chars 33..126, Unicode chars >=128 (non-printables are discouraged but not checked), spaces can occur only inside and no more than one in a row. - - If this syntax is broken, it is an error; as a recovery, illegal chars (including spaces) are + - If this syntax is broken, it is an error; as a recovery, illegal chars (including spaces) are stripped away. - If an Attribute value is sent from the Plugin which violates some restriction (e.g. a Number type @@ -68,7 +67,6 @@ samples/stub_analytics_plugin/src/nx/vms_server_plugins/analytics/stub/taxonomy_ by icon id. --------------------------------------------------------------------------------------------------- - ## JSON structure A Type Library is a JSON object which contain the following lists of entities (in any order): @@ -80,7 +78,8 @@ A Type Library is a JSON object which contain the following lists of entities (i "colorTypes": [ ... ], "objectTypes": [ ... ], "eventTypes": [ ... ], - "eventGroups": [ ... ] + "groups": [ ... ], + "extendedObjectTypes": [ ... ] } ``` @@ -129,12 +128,12 @@ following fields: List of color values. Each item is a JSON object with the following fields: - - `"name"`: Name (String) + - `"name"`: Name (String) Full name of the color value, in English. Will be shown to the user. May look like `"dark"`. - - `"rgb"`: RGB in HEX format (String) + - `"rgb"`: RGB in HEX format (String) The associated RGB value used for this color representation in the UI, for example, when the user is presented a palette to choose from when searching. This RGB value is not @@ -174,9 +173,9 @@ This JSON object describes an Object type. It has the following fields: Identifier of an icon from the icon library built into the VMS. The icons are taken from the open-source icon collection "IconPark", v1.1.1. The icon identifier has the form `bytedance.iconpark.`. For example, `"bytedance.iconpark.palace"`. The icons can be - browsed on the official website of the icon collection: . The + browsed on the official website of the icon collection: http://iconpark.bytedance.com/. The icon files can be downloaded from the official open-source repository of the icon collection: - . + https://github.com/bytedance/IconPark/. NOTE: The icons from the above mentioned icon collection that refer to various brands are not available for the VMS Taxonomy. @@ -185,37 +184,37 @@ This JSON object describes an Object type. It has the following fields: Optional. Defines the color of a bounding box used to show such Objects on the video. Can be one of the following fixed values: - - `"Magenta"` - - `"Blue"` - - `"Green"` - - `"Yellow"` - - `"Cyan"` - - `"Purple"` - - `"Orange"` - - `"Red"` - - `"White"` + - `"Magenta"` + - `"Blue"` + - `"Green"` + - `"Yellow"` + - `"Cyan"` + - `"Purple"` + - `"Orange"` + - `"Red"` + - `"White"` NOTE: This concept of color has no relation to the one used as an Attribute type. - `"base"`: String - + Optional name of an Object Type to inherit the Attributes from. - `"flags"`: Flag set (String) A combination of zero or more of the following flags, separated with `|`: - - `hiddenDerivedType` - this Object type will not be offered to the user in the Search GUI, but + - `hiddenDerivedType` - this Object type will not be offered to the user in the Search GUI, but all its Attributes will be appended to the Attribute list of its base type. Can be applied to derived Object types only. - - `liveOnly` - Objects of such types will not be stored in the video archive - they will be + - `liveOnly` - Objects of such types will not be stored in the video archive - they will be only visible when watching live video from the camera (and only when the Objects do not come too late from the Analytics Plugin), but they will not be visible when playing back the archive, and will not appear in the Search results. This can improve performance when a lot of Objects are generated by a Plugin. - - `nonIndexable` - Objects of such types will be stored in the video archive as usual, but will + - `nonIndexable` - Objects of such types will be stored in the video archive as usual, but will not be added to the Search index and thus will not appear in the Search results, though they will be visible when watching live video from the camera (and only when the Objects do not come too late from the Analytics Plugin), and when playing back the archive. This can @@ -254,9 +253,9 @@ This JSON object describes an Event type. It has the following fields: A combination of zero or more of the following flags, separated with `|`: - - `stateDependent` - Prolonged event with active and non-active states. - - `regionDependent` - Event has reference to a region on a video frame. - - `hidden` - Event type is hidden in the Client. + - `stateDependent` - Prolonged event with active and non-active states. + - `regionDependent` - Event has reference to a region on a video frame. + - `hidden` - Event type is hidden in the Client. Optional; default value is empty. @@ -278,7 +277,7 @@ This JSON object describes an Event type. It has the following fields: Similar to the same-name fields of an Object type. -### Event groups +### Groups This JSON object describes a Group for Event types. The particular Group is referenced from an Event Type via its `"groupId"` field. The Group definition has the following fields: @@ -298,8 +297,39 @@ Event Type via its `"groupId"` field. The Group definition has the following fie Mandatory. ---------------------------------------------------------------------------------------------------- +### Extended Object Types + +This section provides an alternative simplified syntax of defining "hidden" derived Object Types. +Each entity in the `"extendedObjectTypes"` array is technically a definition of a "hidden" derived +Object Type with an auto-generated id using the template `"$"`. The `"id"` +field of an Extended Object Type is an id of the base Object Type. The name of the derived Type must +be empty. The Extended Object Type definition has the following fields: + +- `"id"`: Id (String) + + Identifier of the base Object Type that is being extended. + +- `"attributes"`: Array + + List of Attributes of the newly defined "hidden" descendant. + +### Attribute Lists +Describes a list of Type Attributes, which can be used in the Type definition. Each List must have +an id, and a list of Attributes which uses that same syntax as used in specifying Attributes in +Object and Event Types. Semantically an Attribute List is like a macro - it can be used instead of +an Attribute definition in any Object Type or Event Type definition; its contents simply substitute +the invocation. The Attribute List definition has the following fields: + +- `"id"`: Id (String) + + Identifier of the Attribute List. + +- `"attributes"`: Array + + List of Attributes. + +--------------------------------------------------------------------------------------------------- ## Attributes Objects and Events can have a list of Attributes, each Attribute being defined with a JSON object @@ -313,14 +343,26 @@ containing the following fields: Must have one of the values listed below in the "Attribute types" section. +- `"subtype"`: String + + User-defined id of the particular type. Valid only for user-defined types like `"Enum"`, + `"Color"`, `"Object"`. + +- `"attributeList"`: String + Id of an Attribute List. If present, all other fields are ignored. + +- `"condition"`: String + Condition string that defines whether this Attribute makes sense for the Object or Event Type + depending on values of the other Attributes. Uses the same syntax as in the Object Search panel. + Other fields depend on the particular attribute type. Attributes that are inherited from the base type can be "re-defined" as follows: -- "subtype" and "unit" can be specified if not specified in the base type (or had exactly the +- `"subtype"` and `"unit"` can be specified if not specified in the base type (or had exactly the same value); -- "minValue" and "maxValue" can be specified if and only if the inherited range rather than +- `"minValue"` and `"maxValue"` can be specified if and only if the inherited range rather than extend it. - For Enums and Colors, the Attribute can be re-defined to use another Enum/Color @@ -333,67 +375,68 @@ The following behavior is observed in the GUI when several types inherited from override the same Attribute and declare it as a supported one. - For Numeric attributes: - - The widest possible range is applied. - - If units don't have the same value, the resulting unit is set to an empty string. - - If at least one Attribute has the `"float"` subtype, the resulting Attribute will be float as + - The widest possible range is applied. + - If units don't have the same value, the resulting unit is set to an empty string. + - If at least one Attribute has the `"float"` subtype, the resulting Attribute will be float as well. - For Enum and Color Attributes: - - The resulting Attribute will contain all the values from the initial Attributes. + - The resulting Attribute will contain all the values from the initial Attributes. - For Object Attributes (aggregated Objects): - - The resulting Attribute will contain all the sub-attributes that are declared as supported in + - The resulting Attribute will contain all the sub-attributes that are declared as supported in all the types that override the Attribute. - - All collisions are resolved recursively according to the rules described in this section. + - All collisions are resolved recursively according to the rules described in this section. - Boolean and String Attributes stay intact. - For other type combinations: - - All such Attributes (though with the same name) are shown in the Search filter GUI, treating + - All such Attributes (though with the same name) are shown in the Search filter GUI, treating all the values entered by the user as required criteria, so it makes sense for the user to fill only one of them as a filter. ### Attribute types - `"Number"`: - - Can hold both integer and floating-point values, as in JSON. - - Hints: `"minValue"`, `"maxValue"`, `"unit"` (for GUI only). - - `"subtype"` is treated like a hint: can be `"integer"` or `"float"` (default). + - Can hold both integer and floating-point values, as in JSON. + - Hints: `"minValue"`, `"maxValue"`, `"unit"` (for GUI only). + - `"subtype"` is treated like a hint: can be `"integer"` or `"float"` (default). - `"Boolean"`: - - Can be either True, False, or omitted (which is a distinct case). - - Case-insensitive `"true"`, `"false"` is accepted by the Server from a Plugin, as well as + - Can be either True, False, or omitted (which is a distinct case). + - Case-insensitive `"true"`, `"false"` is accepted by the Server from a Plugin, as well as `"0"` and `"1"`. - `"String"`: - - An empty string is equivalent to the omitted attribute. - - Cannot be restricted to be non-empty. - - May contain any Unicode chars, including '\n', '\0' and other control chars. + - An empty string is equivalent to the omitted attribute. + - Cannot be restricted to be non-empty. + - May contain any Unicode chars, including '\n', '\0' and other control chars. - `"Enum"`: - - Set of Enum items can be empty ­- it makes sense for extending Enums. - - `"subtype"` in the attribute definition refers to a Enum id. - - Item names are not Identifiers - they are Names. - - Enums can be inherited and extended via `"base"` and `"baseItems"` fields. + - The set of Enum items can be empty - it makes sense for extending Enums. + - `"subtype"` in the attribute definition refers to a user-defined Enum type id. + - Item names are not Identifiers - they are Names. + - Enums can be inherited and extended via `"base"` and `"baseItems"` fields. - `"Color"`: - - Similar to an Enum, but each item has an associated RGB value used for this color + - Similar to an Enum, but each item has an associated RGB value used for this color representation in the UI. - - The color Name is what appears as the Attbiture value. - - Like Enums, Colors can be inherited and extended via `"base"` and `"baseItems"` fields. + - `"subtype"` in the attribute definition refers to a user-defined Color type id. + - The color Name is what appears as the Attbiture value. + - Like Enums, Colors can be inherited and extended via `"base"` and `"baseItems"` fields. - `"Object"`: - - A nested (aggregated) Object of the specified `"subtype"` Object type, or of any type (if + - A nested (aggregated) Object of the specified `"subtype"` Object type, or of any type (if `"subtype"` is omitted). - - Can be null, which is equivalent to the omitted attribute. - - The following rules are used to represent a nested Object in the Attribute values of a + - Can be null, which is equivalent to the omitted attribute. + - The following rules are used to represent a nested Object in the Attribute values of a particular instance of the owner (outer) Object: - - For each Attribute of an inner Object, an Attribute with the required type and the name + - For each Attribute of an inner Object, an Attribute with the required type and the name `.` defines its value. - - Additionally, there may be a boolean Attribute with the name ``. - - If it equals `true`, the nested Object is considered present. - - If it equals `false`, the nested Object is considered omitted (null). - - If it is omitted, the presence of the nested Object is deduced by the presence of any + - Additionally, there may be a boolean Attribute with the name ``. + - If it equals `true`, the nested Object is considered present. + - If it equals `false`, the nested Object is considered omitted (null). + - If it is omitted, the presence of the nested Object is deduced by the presence of any of its individual Attributes. - - NOTE: This scheme allows for an instance that contains a nested Object which has no + - NOTE: This scheme allows for an instance that contains a nested Object which has no Attribute values, but the Object itself is considered to be present. diff --git a/src/lib/nx/sdk/analytics/taxonomy_base_type_library.json b/src/lib/nx/sdk/analytics/taxonomy_base_type_library.json index eca8244..cd896fe 100644 --- a/src/lib/nx/sdk/analytics/taxonomy_base_type_library.json +++ b/src/lib/nx/sdk/analytics/taxonomy_base_type_library.json @@ -149,7 +149,8 @@ "type": "Number", "subtype": "integer", "minValue": 0, - "unit": "°C" + "_comment": "\u00b0 is a degree symbol", + "unit": "\u00b0C" }, { "name": "Tattoo", @@ -363,7 +364,8 @@ "type": "Number", "subtype": "integer", "minValue": 0, - "unit": "°C" + "_comment": "\u00b0 is a degree symbol", + "unit": "\u00b0C" }, { "name": "Name", @@ -1175,7 +1177,7 @@ }, { "name": "Red", - "rgb": "#FF0000" + "rgb": "#DC0000" }, { "name": "Orange", @@ -1199,7 +1201,7 @@ }, { "name": "Brown", - "rgb": "#A52A2A" + "rgb": "#964B00" } ] } diff --git a/src/lib/nx/sdk/attributes.md b/src/lib/nx/sdk/attributes.md index 09d9b36..2c43589 100644 --- a/src/lib/nx/sdk/attributes.md +++ b/src/lib/nx/sdk/attributes.md @@ -27,7 +27,7 @@ having a certain special behavior, thus, must not be used when such special beha intended. Identifiers starting with `nx.` must not be used for the entities introduced by parties other than -Nx. +Nx. Some Attributes with pre-defined names starting with `nx.sys.` are used for the VMS internal purposes and to access certain, sometimes experimental, features. Some of such Attributes are diff --git a/src/lib/nx/sdk/dynamic_libraries.md b/src/lib/nx/sdk/dynamic_libraries.md index a4f9504..fc87f94 100644 --- a/src/lib/nx/sdk/dynamic_libraries.md +++ b/src/lib/nx/sdk/dynamic_libraries.md @@ -1,6 +1,6 @@ # Using dynamic libraries in Plugins -// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: +// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/ This document describes issues which may arise when a Plugin dynamic library depends on any other dynamic libraries, either taken from the OS (Windows or Linux), or coming with the Plugin in its @@ -11,14 +11,13 @@ to VMS Server crashes. And even if the Plugin works well with the particular VMS particular OS version, the failures may appear when VMS or OS is upgraded. The root cause of these issues is the fundamental deficiency of the OS mechanisms which resolve the -symbols after loading a dynamic library. +symbols after loading a dynamic library. Note that if a plugin is statically linked to certain libraries, it does not guarantee that symbols from that libraries are not present in the imported/exported symbol table in the plugin dynamic library. --------------------------------------------------------------------------------------------------- - ## Depending on libraries bundled with the VMS A properly written Plugin is expected to remain compatible with any future version of the VMS, @@ -31,7 +30,6 @@ code, or is a third-party library which the VMS depends on. SOLUTION: The Plugin should never depend on any dynamic library bundled with the VMS installation. --------------------------------------------------------------------------------------------------- - ## Depending on system libraries Using any dynamic library from the OS by a Plugin is unsafe. The reason for that is the limitation @@ -59,7 +57,6 @@ SOLUTION: The Plugin should be linked to system libraries statically, except for backwards-compatible, and will not be patched for the need of a certain project. --------------------------------------------------------------------------------------------------- - ## Depending on libstdc++ on Linux `libstdc++` - the GCC C++ standard library implementation - should be linked dynamically. There is @@ -80,7 +77,23 @@ link to `libc++` statically to make sure that the plugin will function properly will start using `libc++` at some point in the future. --------------------------------------------------------------------------------------------------- +## Depending on Visual C++ runtime on Windows + +When using Visual Studio to compile a plugin on Windows, and choosing to use dynamic linking with +the Visual C++ Runtime Redistributable (msvcp140.dll), the resulting plugin may be not compatible +with the VMS built using the toolsets (compilers) that use an older runtime version. The newer +runtime version will do fine. +For example, as of 2024-07-19, the std::mutex ABI has undergone a breaking change in the toolset +version 14.40 as opposed to 14.38, which did not happen for years before that. And now if a plugin +uses std::mutex, is compiled with 14.40, and is used in VMS compiled with 14.38, it will crash. +More details on this issue can be found here: +[Visual Studio forum](https://developercommunity.visualstudio.com/t/Access-violation-with-std::mutex::lock-a/10664660) + +Currently, the recommendation is either to use the toolset version not newer than 14.38, or to link +the plugin with the C++ runtime statically. + +--------------------------------------------------------------------------------------------------- ## Bundling public libraries with the Plugin NOTE: Here we discuss bundling the Plugin with publicly available dynamic libraries; bundling the diff --git a/src/lib/nx/sdk/helpers/action_response.cpp b/src/lib/nx/sdk/helpers/action_response.cpp index eedb779..673a525 100644 --- a/src/lib/nx/sdk/helpers/action_response.cpp +++ b/src/lib/nx/sdk/helpers/action_response.cpp @@ -16,6 +16,16 @@ void ActionResponse::setMessageToUser(std::string value) m_actionUrl = ""; } +void ActionResponse::setUseProxy(bool value) +{ + m_useProxy = value; +} + +void ActionResponse::setUseDeviceCredentials(bool value) +{ + m_useDeviceCredentials = value; +} + const char* ActionResponse::actionUrl() const { return m_actionUrl.c_str(); @@ -26,4 +36,14 @@ const char* ActionResponse::messageToUser() const return m_messageToUser.c_str(); } +bool ActionResponse::useProxy() const +{ + return m_useProxy; +} + +bool ActionResponse::useDeviceCredentials() const +{ + return m_useDeviceCredentials; +} + } // namespace nx::sdk diff --git a/src/lib/nx/sdk/helpers/action_response.h b/src/lib/nx/sdk/helpers/action_response.h index 29875d3..f962104 100644 --- a/src/lib/nx/sdk/helpers/action_response.h +++ b/src/lib/nx/sdk/helpers/action_response.h @@ -4,9 +4,8 @@ #include -#include - #include +#include namespace nx::sdk { @@ -21,12 +20,22 @@ class ActionResponse: public RefCountable /** Additionally, makes actionUrl() return an empty string. */ void setMessageToUser(std::string value); + /** Sets useProxy flag. */ + void setUseProxy(bool value); + + /** Sets useDeviceCredentials flag. */ + void setUseDeviceCredentials(bool value); + virtual const char* actionUrl() const override; virtual const char* messageToUser() const override; + virtual bool useProxy() const override; + virtual bool useDeviceCredentials() const override; private: std::string m_actionUrl; std::string m_messageToUser; + bool m_useProxy = false; + bool m_useDeviceCredentials = false; }; } // namespace nx::sdk diff --git a/src/lib/nx/sdk/helpers/active_setting_changed_action.h b/src/lib/nx/sdk/helpers/active_setting_changed_action.h index 5d9481a..c288ba0 100644 --- a/src/lib/nx/sdk/helpers/active_setting_changed_action.h +++ b/src/lib/nx/sdk/helpers/active_setting_changed_action.h @@ -4,10 +4,9 @@ #include -#include - #include #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/active_setting_changed_response.h b/src/lib/nx/sdk/helpers/active_setting_changed_response.h index 15a3d01..d1f7e2c 100644 --- a/src/lib/nx/sdk/helpers/active_setting_changed_response.h +++ b/src/lib/nx/sdk/helpers/active_setting_changed_response.h @@ -2,12 +2,11 @@ #pragma once -#include -#include - -#include #include +#include #include +#include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/attribute.h b/src/lib/nx/sdk/helpers/attribute.h index 74a7d3e..18b9cc4 100644 --- a/src/lib/nx/sdk/helpers/attribute.h +++ b/src/lib/nx/sdk/helpers/attribute.h @@ -4,8 +4,8 @@ #include -#include #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/device_info.h b/src/lib/nx/sdk/helpers/device_info.h index b0371e2..c91faaa 100644 --- a/src/lib/nx/sdk/helpers/device_info.h +++ b/src/lib/nx/sdk/helpers/device_info.h @@ -4,8 +4,8 @@ #include -#include #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/error.cpp b/src/lib/nx/sdk/helpers/error.cpp index 4e20023..c16fb8d 100644 --- a/src/lib/nx/sdk/helpers/error.cpp +++ b/src/lib/nx/sdk/helpers/error.cpp @@ -2,9 +2,10 @@ #include "error.h" -#define NX_PRINT_PREFIX "nx::sdk::error(): " #include +#undef NX_PRINT_PREFIX +#define NX_PRINT_PREFIX "nx::sdk::error(): " #include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/lib_context.cpp b/src/lib/nx/sdk/helpers/lib_context.cpp index 3647191..009f5c7 100644 --- a/src/lib/nx/sdk/helpers/lib_context.cpp +++ b/src/lib/nx/sdk/helpers/lib_context.cpp @@ -2,6 +2,7 @@ #include "lib_context.h" +#undef NX_PRINT_PREFIX #define NX_PRINT_PREFIX "[nx::sdk::LibContext] " #include diff --git a/src/lib/nx/sdk/helpers/lib_context.h b/src/lib/nx/sdk/helpers/lib_context.h index dd03e07..dc8d807 100644 --- a/src/lib/nx/sdk/helpers/lib_context.h +++ b/src/lib/nx/sdk/helpers/lib_context.h @@ -16,9 +16,8 @@ #include #include -#include - #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/lib_context.md b/src/lib/nx/sdk/helpers/lib_context.md index 8efc668..d358211 100644 --- a/src/lib/nx/sdk/helpers/lib_context.md +++ b/src/lib/nx/sdk/helpers/lib_context.md @@ -1,6 +1,6 @@ # LibContext and RefCountableRegistry mechanisms -// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: +// Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/ This document describes the SDK's "hidden" (working automatically) mechanism called LibContext. diff --git a/src/lib/nx/sdk/helpers/list.h b/src/lib/nx/sdk/helpers/list.h index 62d27f4..4bf8302 100644 --- a/src/lib/nx/sdk/helpers/list.h +++ b/src/lib/nx/sdk/helpers/list.h @@ -5,10 +5,9 @@ #include #include - -#include -#include #include +#include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/log_utils.cpp b/src/lib/nx/sdk/helpers/log_utils.cpp index 92ccbc1..63e0c20 100644 --- a/src/lib/nx/sdk/helpers/log_utils.cpp +++ b/src/lib/nx/sdk/helpers/log_utils.cpp @@ -2,12 +2,14 @@ #include "log_utils.h" -#define NX_DEBUG_ENABLE_OUTPUT (this->enableOutput) +#include + +#undef NX_PRINT_PREFIX #define NX_PRINT_PREFIX (this->printPrefix) +#undef NX_DEBUG_ENABLE_OUTPUT +#define NX_DEBUG_ENABLE_OUTPUT (this->enableOutput) #include -#include - namespace nx::sdk { void LogUtils::setPrintPrefix(std::string newPrefix) diff --git a/src/lib/nx/sdk/helpers/log_utils.h b/src/lib/nx/sdk/helpers/log_utils.h index 17c86fa..e5ab4c9 100644 --- a/src/lib/nx/sdk/helpers/log_utils.h +++ b/src/lib/nx/sdk/helpers/log_utils.h @@ -5,10 +5,10 @@ #include #include -namespace nx { namespace sdk { class IStringMap; } } - namespace nx::sdk { +class IStringMap; + /** * Plugin utils providing convenience for using NX_PRINT/NX_OUTPUT with their settings * (printPrefix string and enableOutput flag) taken from the particular plugin: these settings are @@ -17,7 +17,9 @@ namespace nx::sdk { * To use this tool in a class, make a field "const nx::sdk::LogUtils logUtils", and add * the following lines: *

+ *     #undef NX_PRINT_PREFIX
  *     #define NX_PRINT_PREFIX (this->logUtils.printPrefix)
+ *     #undef NX_DEBUG_ENABLE_OUTPUT
  *     #define NX_DEBUG_ENABLE_OUTPUT (this->logUtils.enableOutput)
  *     #include 
  * 
diff --git a/src/lib/nx/sdk/helpers/media_stream_statistics.h b/src/lib/nx/sdk/helpers/media_stream_statistics.h index ece6212..f47207b 100644 --- a/src/lib/nx/sdk/helpers/media_stream_statistics.h +++ b/src/lib/nx/sdk/helpers/media_stream_statistics.h @@ -11,10 +11,10 @@ #endif #endif -#include -#include #include +#include #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/ref_countable.h b/src/lib/nx/sdk/helpers/ref_countable.h index ae142fc..1124576 100644 --- a/src/lib/nx/sdk/helpers/ref_countable.h +++ b/src/lib/nx/sdk/helpers/ref_countable.h @@ -4,8 +4,8 @@ #include -#include #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/settings_response.h b/src/lib/nx/sdk/helpers/settings_response.h index 72787c2..9cc395a 100644 --- a/src/lib/nx/sdk/helpers/settings_response.h +++ b/src/lib/nx/sdk/helpers/settings_response.h @@ -2,12 +2,11 @@ #pragma once -#include -#include - #include #include #include +#include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/string.h b/src/lib/nx/sdk/helpers/string.h index 8287dd0..6645ba6 100644 --- a/src/lib/nx/sdk/helpers/string.h +++ b/src/lib/nx/sdk/helpers/string.h @@ -2,11 +2,10 @@ #pragma once -#include - #include #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/string_list.h b/src/lib/nx/sdk/helpers/string_list.h index 1c92108..6977cfd 100644 --- a/src/lib/nx/sdk/helpers/string_list.h +++ b/src/lib/nx/sdk/helpers/string_list.h @@ -2,11 +2,11 @@ #pragma once -#include #include +#include -#include #include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/string_map.h b/src/lib/nx/sdk/helpers/string_map.h index 14265b9..e0628e9 100644 --- a/src/lib/nx/sdk/helpers/string_map.h +++ b/src/lib/nx/sdk/helpers/string_map.h @@ -5,7 +5,6 @@ #include #include - #include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/to_string.h b/src/lib/nx/sdk/helpers/to_string.h index 16dfe5a..2f69df8 100644 --- a/src/lib/nx/sdk/helpers/to_string.h +++ b/src/lib/nx/sdk/helpers/to_string.h @@ -2,13 +2,13 @@ #pragma once -#include #include +#include -#include +#include #include #include -#include +#include namespace nx::sdk { diff --git a/src/lib/nx/sdk/helpers/uuid_helper.h b/src/lib/nx/sdk/helpers/uuid_helper.h index 10d758a..23374dd 100644 --- a/src/lib/nx/sdk/helpers/uuid_helper.h +++ b/src/lib/nx/sdk/helpers/uuid_helper.h @@ -3,8 +3,8 @@ #pragma once #include -#include #include +#include #include diff --git a/src/lib/nx/sdk/i_action_response.h b/src/lib/nx/sdk/i_action_response.h index ffd1dbb..0871b84 100644 --- a/src/lib/nx/sdk/i_action_response.h +++ b/src/lib/nx/sdk/i_action_response.h @@ -10,7 +10,7 @@ namespace nx::sdk { * Defines how the Client must interact with the user after the plugin executes some action * triggered by the user. */ -class IActionResponse: public Interface +class IActionResponse0: public Interface { public: static auto interfaceId() { return makeId("nx::sdk::IActionResponse"); } @@ -27,6 +27,22 @@ class IActionResponse: public Interface */ virtual const char* messageToUser() const = 0; }; -using IActionResponse0 = IActionResponse; + +class IActionResponse: public Interface +{ +public: + static auto interfaceId() { return makeId("nx::sdk::IActionResponse1"); } + + /** + * @return Whether proxying through the connected server should be used for actionUrl(). + */ + virtual bool useProxy() const = 0; + + /** + * @return Whether device authentication should be used for actionUrl(). + */ + virtual bool useDeviceCredentials() const = 0; +}; +using IActionResponse1 = IActionResponse; } // namespace nx::sdk diff --git a/src/lib/nx/sdk/i_attribute.h b/src/lib/nx/sdk/i_attribute.h index 1c3fdce..c0f580a 100644 --- a/src/lib/nx/sdk/i_attribute.h +++ b/src/lib/nx/sdk/i_attribute.h @@ -21,14 +21,14 @@ class IAttribute: public Interface static auto interfaceId() { return makeId("nx::sdk::IAttribute"); } virtual Type type() const = 0; - + /** * See the specification for Attribute names in @ref md_src_nx_sdk_attributes. */ virtual const char* name() const = 0; - + virtual const char* value() const = 0; - + virtual float confidence() const = 0; }; using IAttribute0 = IAttribute; diff --git a/src/lib/nx/sdk/i_list.h b/src/lib/nx/sdk/i_list.h index dad957b..353eb99 100644 --- a/src/lib/nx/sdk/i_list.h +++ b/src/lib/nx/sdk/i_list.h @@ -2,6 +2,8 @@ #pragma once +#include "interface.h" + namespace nx::sdk { template diff --git a/src/lib/nx/sdk/i_settings_response.h b/src/lib/nx/sdk/i_settings_response.h index 83f1c06..5dfb562 100644 --- a/src/lib/nx/sdk/i_settings_response.h +++ b/src/lib/nx/sdk/i_settings_response.h @@ -2,10 +2,9 @@ #pragma once -#include - #include #include +#include namespace nx::sdk { @@ -34,7 +33,7 @@ class ISettingsResponse0: public Interface /** * The data to be returned from the plugin describing the desired settings. - * + * * A combination of optional individual setting errors, optional new setting values in case they * were adjusted, and an optional new Settings Model. */ diff --git a/src/lib/nx/sdk/i_utility_provider.h b/src/lib/nx/sdk/i_utility_provider.h index de58920..2d5493f 100644 --- a/src/lib/nx/sdk/i_utility_provider.h +++ b/src/lib/nx/sdk/i_utility_provider.h @@ -2,6 +2,7 @@ #pragma once +#include #include #include @@ -101,7 +102,7 @@ class IUtilityProvider: public Interface /** Called by sendHttpRequest() */ protected: virtual void doSendHttpRequest( HttpDomainName requestDomainName, - const char* path, + const char* url, const char* httpMethod, const char* mimeType, const char* requestBody, @@ -114,14 +115,14 @@ class IUtilityProvider: public Interface */ public: void sendHttpRequest( HttpDomainName requestDomainName, - const char* path, + const char* url, const char* httpMethod, const char* mimeType, const char* requestBody, Ptr callback) const { doSendHttpRequest( - requestDomainName, path, httpMethod, mimeType, requestBody, callback.get()); + requestDomainName, url, httpMethod, mimeType, requestBody, callback.get()); } }; using IUtilityProvider4 = IUtilityProvider; diff --git a/src/lib/nx/sdk/ptr.h b/src/lib/nx/sdk/ptr.h index eeb18e9..a11b218 100644 --- a/src/lib/nx/sdk/ptr.h +++ b/src/lib/nx/sdk/ptr.h @@ -2,9 +2,9 @@ #pragma once -#include #include #include +#include namespace nx { namespace sdk { diff --git a/src/lib/nx/sdk/result.h b/src/lib/nx/sdk/result.h index 71e4abc..fea2edc 100644 --- a/src/lib/nx/sdk/result.h +++ b/src/lib/nx/sdk/result.h @@ -16,6 +16,8 @@ enum class ErrorCode: int invalidParams = -1001, //< Method arguments are invalid. notImplemented = -21, otherError = -100, + ioError = -31, + noData = -101, //< Call succeeded, but no valid data can be returned (EoF for example) }; class Error diff --git a/src/lib/nx/sdk/settings_model.md b/src/lib/nx/sdk/settings_model.md index 838993d..9e16edb 100644 --- a/src/lib/nx/sdk/settings_model.md +++ b/src/lib/nx/sdk/settings_model.md @@ -26,15 +26,17 @@ Certain fields are supported by some of the controls. value in the GUI immediately (or with some delay in the case of TextField-like fields) triggers sending a request to the Server, without waiting for the confirmation with the "Apply" button. The request executes the code of the Active Setting handler of the entity being set up by these - Settings. The setting values sent in such a request are not meant to be "applied" (stored in a - database) - they are intended only for preparing a proper reply to the user, which may include - an adjusted Settings Model, adjusted values of the GUI controls, and a message to be shown to - the user or a URL to be opened in the web browser. The main purpose of Active settings is to - give the entities being set up a way to change the Settings Model and values on-the-fly, - providing a better user experience. An example could be an Active combo-box which lists the - supported measurement units, and the handler code which converts the entered value into the - selected unit. - + Settings. Note that if the Settings dialog is shown before the entity is created, no Active + Setting requests will be fired before the user clicks "Apply" and the entity is created. The + setting values sent in such a request are not meant to be "applied" (stored in a database) - + they are intended only for preparing a proper reply to the user, which may include an adjusted + Settings Model, adjusted values of the GUI controls, and a message to be shown to the user or a + URL to be opened in the web browser. The main purpose of Active settings is to give the + entities being set up a way to change the Settings Model and values on-the-fly, providing a + better user experience. An example could be an Active combo-box which lists the supported + measurement units, and the handler code which converts the entered value into the selected + unit. + ATTENTION: The "Active Setting" feature requires the reaction with the entity that the settings are intended for, like an Analytics Engine or a Device Agent. In certain scenarios, this entity may not exist yet - for example, when an Engine is going to be turned on for a camera for the @@ -44,7 +46,7 @@ Certain fields are supported by some of the controls. may be found useful to present the initial Settings Model that does not count on `isActive`, and after the settings are applied and the entity (e.g. Device Agent) is created, it may present a more advanced Settings Model which makes use of `isActive`. - + - `"parametersModel"` - Settings Model JSON object. Applies only for controls with the `"isActive"` property set to `true`. Additional parameters are requested when the active control is triggered. NOTE: The `"parametersModel"` model does not support items with the `"isActive"` property set @@ -574,13 +576,21 @@ Property "name" must be unique, will be used as a caption if caption is not spec --------------------------------------------------------------------------------------------------- ## GroupBox -Grouping panel with a caption. Top-level groupboxes visually distinguished from the nested. +Grouping panel with a caption. Top-level groupboxes visually distinguished from the nested if the +style is not specified or set to `"default"`. + +The `"style"` field is optional and accepts the following values: +- `"default"` (top-level groupboxes will have style `"panel"` and nested will have style `"group"`) +- `"panel"` +- `"group"` +- `"label"` ### Setting Model { "type": "GroupBox", "caption": "Top-level groupbox", + "style": "default", "items": [ { "type": "CheckBox", "caption": "CheckBox", "description": "Hint" }, { "type": "SpinBox", "caption": "SpinBox", "description": "Hint" }, diff --git a/src/lib/nx/sdk/uuid.h b/src/lib/nx/sdk/uuid.h index 9e81407..113cdf9 100644 --- a/src/lib/nx/sdk/uuid.h +++ b/src/lib/nx/sdk/uuid.h @@ -4,6 +4,7 @@ #include #include + #include namespace nx::sdk { diff --git a/src/lib/nx_sdk_version.inc b/src/lib/nx_sdk_version.inc index 1db0a9b..b54c1b6 100644 --- a/src/lib/nx_sdk_version.inc +++ b/src/lib/nx_sdk_version.inc @@ -8,4 +8,4 @@ // version is available via IUtilityProvider::getServerSdkVersion(). -"5.1.4 R1" +"6.0.0 R7" diff --git a/src/unit_tests/src/analytics_plugin_ut.cpp b/src/unit_tests/src/analytics_plugin_ut.cpp index 18ca739..fe89744 100644 --- a/src/unit_tests/src/analytics_plugin_ut.cpp +++ b/src/unit_tests/src/analytics_plugin_ut.cpp @@ -211,7 +211,7 @@ class DeviceAgentHandler : public nx::sdk::RefCountable { ASSERT_TRUE(event); - NX_PRINT << "DeviceAgentHandler: Received a plugin diagnostic event: " + NX_PRINT << "EngineHandler: Received a plugin diagnostic event: " << "level " << (int)event->level() << ", " << "caption " << nx::kit::utils::toString(event->caption()) << ", " << "description " << nx::kit::utils::toString(event->description());