From 3782c1495e14a89ee824e60944ec6f521895642a Mon Sep 17 00:00:00 2001 From: "Edwards, Daniel" Date: Tue, 6 Feb 2024 10:24:27 +0100 Subject: [PATCH] SILKIT-1488: Support unicode-characters in filenames and participant names (#752) --- Demos/CMakeLists.txt | 1 + Demos/demo.manifest | 8 + SilKit/IntegrationTests/ITest_Dashboard.cpp | 23 ++ SilKit/include/silkit/SilKit.hpp | 4 +- SilKit/include/silkit/capi/Can.h | 4 +- SilKit/include/silkit/capi/DataPubSub.h | 4 +- SilKit/include/silkit/capi/Ethernet.h | 4 +- SilKit/include/silkit/capi/Lin.h | 4 +- SilKit/include/silkit/capi/Logger.h | 2 +- SilKit/include/silkit/capi/Orchestration.h | 18 +- SilKit/include/silkit/capi/Rpc.h | 4 +- SilKit/include/silkit/capi/SilKit.h | 20 +- .../config/IParticipantConfiguration.hpp | 4 +- .../impl/config/IParticipantConfiguration.ipp | 13 +- .../silkit/services/logging/ILogger.hpp | 2 +- .../services/orchestration/ISystemMonitor.hpp | 4 +- .../orchestration/OrchestrationDatatypes.hpp | 4 +- SilKit/source/capi/CapiParticipant.cpp | 79 +++++ SilKit/source/core/vasio/VAsioConnection.cpp | 8 +- Utilities/SilKitMonitor/CMakeLists.txt | 1 + Utilities/SilKitRegistry/CMakeLists.txt | 2 + .../SilKitSystemController/CMakeLists.txt | 1 + Utilities/utilities.manifest | 8 + docs/CHANGELOG.rst | 4 + .../faq-example-bad-output-codepage.png | Bin 0 -> 5349 bytes .../faq-example-good-output-codepage.png | Bin 0 -> 5571 bytes docs/faq/faq.rst | 281 ++++++++++-------- 27 files changed, 347 insertions(+), 160 deletions(-) create mode 100644 Demos/demo.manifest create mode 100644 Utilities/utilities.manifest create mode 100644 docs/_static/faq-example-bad-output-codepage.png create mode 100644 docs/_static/faq-example-good-output-codepage.png diff --git a/Demos/CMakeLists.txt b/Demos/CMakeLists.txt index 14c461c7c..9078fdbd7 100755 --- a/Demos/CMakeLists.txt +++ b/Demos/CMakeLists.txt @@ -100,6 +100,7 @@ endif() macro(make_silkit_demo executableName demoSourceFile) add_executable(${executableName} ${demoSourceFile} + $<$: "${CMAKE_CURRENT_SOURCE_DIR}/../demo.manifest" > ) remove_definitions(-DEXPORT_SilKitAPI) diff --git a/Demos/demo.manifest b/Demos/demo.manifest new file mode 100644 index 000000000..dab929e15 --- /dev/null +++ b/Demos/demo.manifest @@ -0,0 +1,8 @@ + + + + + UTF-8 + + + diff --git a/SilKit/IntegrationTests/ITest_Dashboard.cpp b/SilKit/IntegrationTests/ITest_Dashboard.cpp index af648d0f0..d2c94c6ca 100755 --- a/SilKit/IntegrationTests/ITest_Dashboard.cpp +++ b/SilKit/IntegrationTests/ITest_Dashboard.cpp @@ -293,6 +293,29 @@ TEST_F(ITest_Dashboard, dashboard_no_simulation) CheckTestResult(testResult, CreateExpectedTestResult({}, false)); } +TEST_F(ITest_Dashboard, dashboard_unicode_emoji_coordinated) +{ + // the two participants use the car emoji (🚗) in their name, which is escaped for the dashboard + const auto participantName1 = "\xf0\x9f\x9a\x97 CanReader"; + const auto expectedParticipantName1 = "%f0%9f%9a%97%20CanReader"; + const auto participantName2 = "\xf0\x9f\x9a\x97 CanWriter"; + const auto expectedParticipantName2 = "%f0%9f%9a%97%20CanWriter"; + const auto canonicalName = "CanController1"; + const auto networkName = "CAN1"; + SetupFromParticipantLists({participantName1, participantName2}, {}); + auto testResult = SilKit::Dashboard::RunDashboardTest( + ParticipantConfigurationFromStringImpl(_dashboardParticipantConfig), _registryUri, _dashboardUri, + [this, &participantName1, &participantName2, &canonicalName, &networkName]() { + RunCanDemo(participantName1, participantName2, canonicalName, networkName); + }); + _simTestHarness->ResetRegistry(); + CheckTestResult(testResult, + CreateExpectedTestResult( + {{{expectedParticipantName1, {{6, {"", "cancontroller", canonicalName, networkName, {}}}}}, + {expectedParticipantName2, {{6, {"", "cancontroller", canonicalName, networkName, {}}}}}}}, + true)); +} + TEST_F(ITest_Dashboard, dashboard_can_coordinated) { const auto participantName1 = "CanReader"; diff --git a/SilKit/include/silkit/SilKit.hpp b/SilKit/include/silkit/SilKit.hpp index 275823d8a..68866679a 100644 --- a/SilKit/include/silkit/SilKit.hpp +++ b/SilKit/include/silkit/SilKit.hpp @@ -37,7 +37,7 @@ DETAIL_SILKIT_DETAIL_VN_NAMESPACE_BEGIN * Become a participant based on the the given configuration options. * * \param participantConfig Configuration of the participant - * \param participantName Name of the participant + * \param participantName Name of the participant (UTF-8) * \return Instance of the communication adapter * * \throw SilKit::ConfigurationError if the config has errors @@ -52,7 +52,7 @@ DETAIL_SILKIT_CPP_API auto CreateParticipant( * Become a participant based on the the given configuration options. * * \param participantConfig Configuration of the participant - * \param participantName Name of the participant + * \param participantName Name of the participant (UTF-8) * \param registryUri The URI of the registry * \return Instance of the communication adapter * diff --git a/SilKit/include/silkit/capi/Can.h b/SilKit/include/silkit/capi/Can.h index 9f65511ea..7149c5cd1 100755 --- a/SilKit/include/silkit/capi/Can.h +++ b/SilKit/include/silkit/capi/Can.h @@ -205,8 +205,8 @@ typedef void (SilKitFPTR *SilKit_CanErrorStateChangeHandler_t)(void* context, Si /*! \brief Create a CAN controller at this SIL Kit simulation participant. * \param outCanController Pointer that refers to the resulting CAN controller (out parameter). * \param participant The simulation participant at which the CAN controller should be created. - * \param name The name of the new CAN controller. - * \param network The network of the CAN controller to operate in. + * \param name The name of the new CAN controller (UTF-8). + * \param network The network of the CAN controller to operate in (UTF-8). * * The lifetime of the resulting CAN controller is directly bound to the lifetime of the simulation participant. * There is no further cleanup necessary except for destroying the simulation participant at the end of the diff --git a/SilKit/include/silkit/capi/DataPubSub.h b/SilKit/include/silkit/capi/DataPubSub.h index 6e552fa07..1030e47a9 100755 --- a/SilKit/include/silkit/capi/DataPubSub.h +++ b/SilKit/include/silkit/capi/DataPubSub.h @@ -66,7 +66,7 @@ typedef void (SilKitFPTR *SilKit_DataMessageHandler_t)(void* context, SilKit_Dat /*! \brief Create a DataPublisher on the provided simulation participant with the provided properties. * \param outPublisher Pointer to which the resulting DataPublisher reference will be written. * \param participant The simulation participant for which the DataPublisher should be created. -* \param controllerName The name of this controller. +* \param controllerName The name of this controller (UTF-8). * \param dataSpec The specification of topic, media type and labels. * \param history A number indicating the number of historic values that should be replayed for a new DataSubscriber. * Restricted to {0|1}. @@ -84,7 +84,7 @@ typedef SilKit_ReturnCode(SilKitFPTR* SilKit_DataPublisher_Create_t)(SilKit_Data /*! \brief Create a DataSubscriber on the provided simulation participant with the provided properties. * \param outSubscriber Pointer to which the resulting DataSubscriber reference will be written. * \param participant The simulation participant for which the DataSubscriber should be created. -* \param controllerName The name of this controller. +* \param controllerName The name of this controller (UTF-8). * \param dataSpec The specification of topic, media type and labels. * \param dataHandlerContext A user provided context that is reobtained on data reception in the dataHandler. * \param dataHandler The handler that is called on data reception. Can be overwritten by \ref SilKit_DataSubscriber_SetDataMessageHandler. diff --git a/SilKit/include/silkit/capi/Ethernet.h b/SilKit/include/silkit/capi/Ethernet.h index 802496586..8d3b71841 100755 --- a/SilKit/include/silkit/capi/Ethernet.h +++ b/SilKit/include/silkit/capi/Ethernet.h @@ -148,8 +148,8 @@ typedef void (SilKitFPTR *SilKit_EthernetBitrateChangeHandler_t)(void* context, * * \param outController A pointer to a pointer in which the Ethernet controller will be stored (out parameter). * \param participant The simulation participant for which the Ethernet controller should be created. -* \param name The utf8 encoded name of the new Ethernet controller. -* \param network The network of the Ethernet controller to operate in. +* \param name The name of the new Ethernet controller (UTF-8). +* \param network The network of the Ethernet controller to operate in (UTF-8). * \result A return code identifying the success/failure of the call. * ! \note The object returned must not be deallocated using free()! * diff --git a/SilKit/include/silkit/capi/Lin.h b/SilKit/include/silkit/capi/Lin.h index 8e8b9bc42..16ffdc73b 100755 --- a/SilKit/include/silkit/capi/Lin.h +++ b/SilKit/include/silkit/capi/Lin.h @@ -348,8 +348,8 @@ typedef void (SilKitFPTR* SilKit_Experimental_LinFrameHeaderHandler_t)( * * \param outLinController Pointer into which the resulting LIN controller will be written (out parameter). * \param participant The simulation participant at which the LIN controller should be created. - * \param name The name of the new LIN controller. - * \param network The network of the LIN controller to operate in. + * \param name The name of the new LIN controller (UTF-8). + * \param network The network of the LIN controller to operate in (UTF-8). * * \return \ref SilKit_ReturnCode */ diff --git a/SilKit/include/silkit/capi/Logger.h b/SilKit/include/silkit/capi/Logger.h index 18bc5dd27..ff644165a 100644 --- a/SilKit/include/silkit/capi/Logger.h +++ b/SilKit/include/silkit/capi/Logger.h @@ -47,7 +47,7 @@ typedef struct SilKit_Logger SilKit_Logger; * * \param logger The logger to use. * \param level The log level for the message. - * \param message The message which shall be logged. + * \param message The message which shall be logged (UTF-8). */ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_Logger_Log(SilKit_Logger* logger, SilKit_LoggingLevel level, const char* message); diff --git a/SilKit/include/silkit/capi/Orchestration.h b/SilKit/include/silkit/capi/Orchestration.h index c5b9ea007..89ab46d84 100755 --- a/SilKit/include/silkit/capi/Orchestration.h +++ b/SilKit/include/silkit/capi/Orchestration.h @@ -115,9 +115,9 @@ typedef int8_t SilKit_OperationMode; typedef struct { SilKit_StructHeader structHeader; - const char* participantName; /*!< Name of the participant. */ + const char* participantName; /*!< Name of the participant (UTF-8). */ SilKit_ParticipantState participantState; /*!< The new state of the participant. */ - const char* enterReason; /*!< The reason for the participant to enter the new state. */ + const char* enterReason; /*!< The reason for the participant to enter the new state (UTF-8). */ SilKit_NanosecondsWallclockTime enterTime; /*!< The enter time of the participant. */ SilKit_NanosecondsWallclockTime refreshTime; /*!< The refresh time. */ } SilKit_ParticipantStatus; @@ -365,7 +365,7 @@ typedef SilKit_ReturnCode (SilKitFPTR *SilKit_LifecycleService_WaitForLifecycleT * report the error message in the SIL Kit system. * * \param lifecycleService The lifecycle service of the simulation. - * \param reason A string describing the error. + * \param reason A string describing the error (UTF-8). */ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_LifecycleService_ReportError(SilKit_LifecycleService* lifecycleService, const char* reason); @@ -382,6 +382,9 @@ typedef SilKit_ReturnCode (SilKitFPTR *SilKit_LifecycleService_ReportError_t)(Si * health monitoring related timeout occurs. * * Precondition: State() == \ref SilKit_ParticipantState_Running + * + * \param lifecycleService The lifecycle service of the simulation. + * \param reason A string describing the reason why the simulation was paused (UTF-8). */ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_LifecycleService_Pause(SilKit_LifecycleService* lifecycleService, const char* reason); @@ -412,6 +415,9 @@ typedef SilKit_ReturnCode (SilKitFPTR *SilKit_LifecycleService_Continue_t)(SilKi * cannot participate in the system simulation anymore. * * Precondition: State() == \ref SilKit_ParticipantState_Running + * + * \param lifecycleService The lifecycle service of the simulation. + * \param reason A string describing why the simulation was stopped (UTF-8). */ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_LifecycleService_Stop(SilKit_LifecycleService* lifecycleService, const char* reason); @@ -548,7 +554,7 @@ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_SystemMonitor_Create(SilKit_System typedef SilKit_ReturnCode(SilKitFPTR* SilKit_SystemMonitor_Create_t)(SilKit_SystemMonitor** outSystemMonitor, SilKit_Participant* participant); -/*! \brief Get the current participant state of the participant given by participantName +/*! \brief Get the current participant state of the participant given by participantName (UTF-8) */ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_SystemMonitor_GetParticipantStatus(SilKit_ParticipantStatus* outParticipantState, SilKit_SystemMonitor* systemMonitor, @@ -635,7 +641,7 @@ typedef SilKit_ReturnCode (SilKitFPTR *SilKit_SystemMonitor_RemoveParticipantSta typedef struct SilKit_ParticipantConnectionInformation { SilKit_StructHeader structHeader; - /*! \brief Name of the remote participant. */ + /*! \brief Name of the remote participant (UTF-8). */ const char* participantName; } SilKit_ParticipantConnectionInformation; @@ -680,7 +686,7 @@ typedef SilKit_ReturnCode (SilKitFPTR *SilKit_SystemMonitor_SetParticipantDiscon /*! \brief Check if a participant identified by the participantName is present. * * @param systemMonitor The system monitor obtained via \ref SilKit_SystemMonitor_Create. - * @param participantName The name of the participant for which presence is queried. + * @param participantName The name of the participant for which presence is queried (UTF-8). * @param out \ref SilKit_True is written to the pointee if the participant is present, otherwise \ref SilKit_False. */ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_SystemMonitor_IsParticipantConnected(SilKit_SystemMonitor* systemMonitor, diff --git a/SilKit/include/silkit/capi/Rpc.h b/SilKit/include/silkit/capi/Rpc.h index 485749c03..a3d8f6040 100755 --- a/SilKit/include/silkit/capi/Rpc.h +++ b/SilKit/include/silkit/capi/Rpc.h @@ -104,7 +104,7 @@ typedef void (SilKitFPTR *SilKit_RpcCallResultHandler_t)(void* context, SilKit_R /*! \brief Create a RPC server on a simulation participant with the provided properties. * \param outServer Pointer to which the resulting RPC server reference will be written. * \param participant The simulation participant for which the RPC server should be created. - * \param controllerName The name of this controller. + * \param controllerName The name of this controller (UTF-8). * \param rpcSpec A struct containing all matching related information * \param callHandlerContext A user provided context pointer that is passed to the callHandler on call. * \param callHandler A callback function that is triggered on invocation of the server functionality. @@ -148,7 +148,7 @@ typedef SilKit_ReturnCode (SilKitFPTR *SilKit_RpcServer_SetCallHandler_t)(SilKit /*! \brief Create a RPC client on a simulation participant with the provided properties. * \param outClient Pointer to which the resulting RPC client reference will be written. * \param participant The simulation participant for which the RPC client should be created. - * \param controllerName The name of this controller. + * \param controllerName The name of this controller (UTF-8). * \param rpcSpec The specification of function name, media type and labels. * \param resultHandlerContext A user provided context that is reobtained on call result in the resultHandler. * \param resultHandler A callback that is called when a call result is received. diff --git a/SilKit/include/silkit/capi/SilKit.h b/SilKit/include/silkit/capi/SilKit.h index ded6d1e84..87285db16 100644 --- a/SilKit/include/silkit/capi/SilKit.h +++ b/SilKit/include/silkit/capi/SilKit.h @@ -40,7 +40,7 @@ SILKIT_BEGIN_DECLS /*! \brief Get the corresponding static error string for a given return code. * - * \param outString The pointer through which the resulting human readable error string will be returned. + * \param outString The pointer through which the resulting human readable error string, encoded in UTF-8, will be returned. * \param returnCode The return code for which the string should be obtained. * * \ref SilKit_GetLastErrorString() @@ -67,7 +67,7 @@ typedef const char*(SilKitFPTR *SilKit_GetLastErrorString_t)(); * To destroy the participant configuration, call \ref SilKit_ParticipantConfiguration_Destroy. * * \param outParticipantConfiguration The pointer through which the participant configuration will be returned (out parameter). - * \param participantConfigurationString The configuration as a string (e.g., read from a configuration file or a string constant). + * \param participantConfigurationString The configuration as a UTF-8 encoded string (e.g., read from a configuration file or a string constant). */ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_ParticipantConfiguration_FromString( SilKit_ParticipantConfiguration** outParticipantConfiguration, @@ -78,6 +78,22 @@ typedef SilKit_ReturnCode (SilKitFPTR *SilKit_ParticipantConfiguration_FromStrin const char* participantConfigurationString); +/*! \brief Create an opaque participant configuration from the contents of the UTF-8 encoded text file. + * + * To destroy the participant configuration, call \ref SilKit_ParticipantConfiguration_Destroy. + * + * \param outParticipantConfiguration The pointer through which the participant configuration will be returned (out parameter). + * \param participantConfigurationPath The path to the configuration file as a UTF-8 encoded string. + */ +SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_ParticipantConfiguration_FromFile( + SilKit_ParticipantConfiguration** outParticipantConfiguration, + const char* participantConfigurationPath); + +typedef SilKit_ReturnCode (SilKitFPTR *SilKit_ParticipantConfiguration_FromFile_t)( + SilKit_ParticipantConfiguration** outParticipantConfiguration, + const char* participantConfigurationPath); + + /*! \brief Destroy a participant configuration. * * \param participantConfiguration The participant configuration to be destroyed. diff --git a/SilKit/include/silkit/config/IParticipantConfiguration.hpp b/SilKit/include/silkit/config/IParticipantConfiguration.hpp index 72d535def..f213513c8 100644 --- a/SilKit/include/silkit/config/IParticipantConfiguration.hpp +++ b/SilKit/include/silkit/config/IParticipantConfiguration.hpp @@ -49,7 +49,7 @@ namespace Config { * Create a configuration data object from settings described by a * YAML or JSON formatted string. * - * \param text A string that adheres to our JSON schema. + * \param text A string that adheres to our JSON schema (UTF-8). * \return The configuration data * * \throw SilKit::ConfigurationError The input string violates the @@ -63,7 +63,7 @@ DETAIL_SILKIT_CPP_API auto ParticipantConfigurationFromString(const std::string& * Create a configuration data object from settings described by a * YAML or JSON file. * - * \param filename Path to the YAML or JSON file. + * \param filename Path to the YAML or JSON file (UTF-8). * \return The configuration data * * \throw SilKit::ConfigurationError The file could not be read, or diff --git a/SilKit/include/silkit/detail/impl/config/IParticipantConfiguration.ipp b/SilKit/include/silkit/detail/impl/config/IParticipantConfiguration.ipp index 49ba60327..3c7e757a2 100644 --- a/SilKit/include/silkit/detail/impl/config/IParticipantConfiguration.ipp +++ b/SilKit/include/silkit/detail/impl/config/IParticipantConfiguration.ipp @@ -45,18 +45,15 @@ auto ParticipantConfigurationFromString(const std::string& text) return std::make_shared(participantConfiguration); } -auto ParticipantConfigurationFromFile(const std::string& filename) +auto ParticipantConfigurationFromFile(const std::string& path) -> std::shared_ptr { - std::ifstream fs(filename); - - if (!fs.is_open()) - throw SilKit::ConfigurationError("the file could not be opened"); + SilKit_ParticipantConfiguration* participantConfiguration{nullptr}; - std::stringstream buffer; - buffer << fs.rdbuf(); + const auto returnCode = SilKit_ParticipantConfiguration_FromFile(&participantConfiguration, path.c_str()); + Impl::ThrowOnError(returnCode); - return ParticipantConfigurationFromString(buffer.str()); + return std::make_shared(participantConfiguration); } } // namespace Config diff --git a/SilKit/include/silkit/services/logging/ILogger.hpp b/SilKit/include/silkit/services/logging/ILogger.hpp index 592d158eb..e00d51e33 100755 --- a/SilKit/include/silkit/services/logging/ILogger.hpp +++ b/SilKit/include/silkit/services/logging/ILogger.hpp @@ -37,7 +37,7 @@ class ILogger /*! \brief Log a message with a specified level * * \param level The log level for the message - * \param msg The message which shall be logged. + * \param msg The message which shall be logged (UTF-8). */ virtual void Log(Level level, const std::string& msg) = 0; diff --git a/SilKit/include/silkit/services/orchestration/ISystemMonitor.hpp b/SilKit/include/silkit/services/orchestration/ISystemMonitor.hpp index 16e4de630..3beb178ed 100644 --- a/SilKit/include/silkit/services/orchestration/ISystemMonitor.hpp +++ b/SilKit/include/silkit/services/orchestration/ISystemMonitor.hpp @@ -91,7 +91,7 @@ class ISystemMonitor /*! \brief Get the current \ref ParticipantStatus of specific participant * - * \param participantName The name of the participant for which the status is queried. + * \param participantName The name of the participant for which the status is queried (UTF-8). * \throw SilKit::SilKitError If the participant name does not * identify a participant that participates in synchronization. */ @@ -112,7 +112,7 @@ class ISystemMonitor /*! \brief Check if a participant identified by the participantName is present. * - * @param participantName The name of the participant for which presence is queried. + * @param participantName The name of the participant for which presence is queried (UTF-8). * @return true if the participant is present */ virtual auto IsParticipantConnected(const std::string& participantName) const -> bool = 0; diff --git a/SilKit/include/silkit/services/orchestration/OrchestrationDatatypes.hpp b/SilKit/include/silkit/services/orchestration/OrchestrationDatatypes.hpp index 10f332623..1da9ee78e 100755 --- a/SilKit/include/silkit/services/orchestration/OrchestrationDatatypes.hpp +++ b/SilKit/include/silkit/services/orchestration/OrchestrationDatatypes.hpp @@ -68,9 +68,9 @@ enum class ParticipantState : SilKit_ParticipantState //! \brief Details about a participant state change. struct ParticipantStatus { - std::string participantName; //!< Name of the participant. + std::string participantName; //!< Name of the participant (UTF-8). ParticipantState state{ParticipantState::Invalid}; //!< The new state of the participant. - std::string enterReason; //!< The reason for the participant to enter the new state. + std::string enterReason; //!< The reason for the participant to enter the new state (UTF-8). std::chrono::system_clock::time_point enterTime; //!< The enter time of the participant. std::chrono::system_clock::time_point refreshTime; //!< The refresh time. }; diff --git a/SilKit/source/capi/CapiParticipant.cpp b/SilKit/source/capi/CapiParticipant.cpp index 41715be42..b9f820874 100644 --- a/SilKit/source/capi/CapiParticipant.cpp +++ b/SilKit/source/capi/CapiParticipant.cpp @@ -35,6 +35,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include +#ifdef _WIN32 +# define NOMINMAX +# define WIN32_LEAN_AND_MEAN +# include "Windows.h" +#endif + + +namespace { +auto OpenTextFile(const std::string& path) -> std::ifstream; +} // namespace + SilKit_ReturnCode SilKitCALL SilKit_Participant_Create(SilKit_Participant** outParticipant, SilKit_ParticipantConfiguration *participantConfiguration, @@ -129,6 +140,30 @@ try CAPI_CATCH_EXCEPTIONS +SilKit_ReturnCode SilKitCALL SilKit_ParticipantConfiguration_FromFile( + SilKit_ParticipantConfiguration** outParticipantConfiguration, + const char* participantConfigurationPath) +try +{ + ASSERT_VALID_OUT_PARAMETER(outParticipantConfiguration); + ASSERT_VALID_POINTER_PARAMETER(participantConfigurationPath); + + std::stringstream ss; + + // read the whole configuration file + { + const auto fs = OpenTextFile(participantConfigurationPath); + ss << fs.rdbuf(); + } + + const auto string = ss.str(); + + // dispatch to the function reading the configuration from a string + return SilKit_ParticipantConfiguration_FromString(outParticipantConfiguration, string.c_str()); +} +CAPI_CATCH_EXCEPTIONS + + SilKit_ReturnCode SilKitCALL SilKit_ParticipantConfiguration_Destroy( SilKit_ParticipantConfiguration* participantConfiguration) try @@ -148,3 +183,47 @@ try return SilKit_ReturnCode_SUCCESS; } CAPI_CATCH_EXCEPTIONS + + +namespace { + +#ifdef _WIN32 + +auto OpenTextFile(const std::string& path) -> std::ifstream +{ + std::wstring widePath; + + constexpr DWORD MB2WC_FLAGS = 0; + + const auto pathSize = static_cast(path.size()); + + // determine the size of the required wide-character string + const int widePathSize = ::MultiByteToWideChar(CP_UTF8, MB2WC_FLAGS, path.c_str(), pathSize, NULL, 0); + if (widePathSize <= 0) + { + throw SilKit::ConfigurationError{"conversion from UTF-8 to UTF-16 failed"}; + } + + widePath.resize(static_cast(widePathSize)); + + // actually convert the path into a wide-character string + const int realWidePathSize = + ::MultiByteToWideChar(CP_UTF8, MB2WC_FLAGS, path.c_str(), pathSize, &widePath[0], widePathSize); + if (realWidePathSize != widePathSize) + { + throw SilKit::ConfigurationError{"conversion from UTF-8 to UTF-16 failed"}; + } + + return std::ifstream{widePath}; +} + +#else + +auto OpenTextFile(const std::string& path) -> std::ifstream +{ + return std::ifstream{path}; +} + +#endif + +} // namespace diff --git a/SilKit/source/core/vasio/VAsioConnection.cpp b/SilKit/source/core/vasio/VAsioConnection.cpp index 00f45673f..911a8356e 100755 --- a/SilKit/source/core/vasio/VAsioConnection.cpp +++ b/SilKit/source/core/vasio/VAsioConnection.cpp @@ -67,13 +67,17 @@ auto printableName(const std::string& participantName) -> std::string std::string safeName; for (const auto& ch : participantName) { - if (std::isalnum(ch)) + // do not use std::isalnum, as it may sensitive to the current locale + const bool isAlphaNumeric{('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9') + || (ch == '_' || ch == '-' || ch == '.' || ch == '~')}; + + if (isAlphaNumeric) { safeName.push_back(ch); } else { - safeName += fmt::format("{:x}", static_cast(ch)); + safeName += fmt::format("{:02X}", static_cast(ch)); } } return safeName; diff --git a/Utilities/SilKitMonitor/CMakeLists.txt b/Utilities/SilKitMonitor/CMakeLists.txt index 0e1c79fc9..8755255f7 100644 --- a/Utilities/SilKitMonitor/CMakeLists.txt +++ b/Utilities/SilKitMonitor/CMakeLists.txt @@ -27,6 +27,7 @@ include(SilKitInstall) add_executable(sil-kit-monitor PassiveSystemMonitor.cpp + $<$: "${CMAKE_CURRENT_SOURCE_DIR}/../utilities.manifest" > ) # Group this demo project into a folder diff --git a/Utilities/SilKitRegistry/CMakeLists.txt b/Utilities/SilKitRegistry/CMakeLists.txt index b7c6a8c14..70beb1499 100644 --- a/Utilities/SilKitRegistry/CMakeLists.txt +++ b/Utilities/SilKitRegistry/CMakeLists.txt @@ -40,6 +40,8 @@ add_executable(sil-kit-registry WindowsServiceMain.hpp WindowsServiceMain.cpp + + $<$: "${CMAKE_CURRENT_SOURCE_DIR}/../utilities.manifest" > ) # Group this demo project into a folder diff --git a/Utilities/SilKitSystemController/CMakeLists.txt b/Utilities/SilKitSystemController/CMakeLists.txt index 33ec53288..cd9779e0d 100644 --- a/Utilities/SilKitSystemController/CMakeLists.txt +++ b/Utilities/SilKitSystemController/CMakeLists.txt @@ -27,6 +27,7 @@ include(SilKitInstall) add_executable(sil-kit-system-controller SystemController.cpp + $<$: "${CMAKE_CURRENT_SOURCE_DIR}/../utilities.manifest" > ) # Group this demo project into a folder diff --git a/Utilities/utilities.manifest b/Utilities/utilities.manifest new file mode 100644 index 000000000..dab929e15 --- /dev/null +++ b/Utilities/utilities.manifest @@ -0,0 +1,8 @@ + + + + + UTF-8 + + + diff --git a/docs/CHANGELOG.rst b/docs/CHANGELOG.rst index 820d3f854..f7bcffcd7 100644 --- a/docs/CHANGELOG.rst +++ b/docs/CHANGELOG.rst @@ -29,6 +29,10 @@ Fixed - Registry failed to start correctly, if the dashboard is enabled, but the registry is letting the system determine the listening port, e.g., when using a URI like ``silkit://localhost:0``. +- Windows: Utilities and demos are now compiled with a manifest that sets the active codepage to UTF-8. + The required commands to change the output codepage of the Windows console in ``cmd`` or PowerShell + are documented in a new FAQ entry. + [4.0.44] - 2024-01-22 --------------------- diff --git a/docs/_static/faq-example-bad-output-codepage.png b/docs/_static/faq-example-bad-output-codepage.png new file mode 100644 index 0000000000000000000000000000000000000000..088939bcdc525e107dfe0eef55e90c8b800d22e1 GIT binary patch literal 5349 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 literal 0 HcmV?d00001 diff --git a/docs/_static/faq-example-good-output-codepage.png b/docs/_static/faq-example-good-output-codepage.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b6b5d65cce8336431486aca809ff4cef4cf8ca GIT binary patch literal 5571 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 ZyX2P4^|s+ZTs2-vbTq*lrE1op{{ypQFGm0X literal 0 HcmV?d00001 diff --git a/docs/faq/faq.rst b/docs/faq/faq.rst index e36e44109..892e6cb87 100644 --- a/docs/faq/faq.rst +++ b/docs/faq/faq.rst @@ -1,122 +1,159 @@ -========================== -Frequently Asked Questions -========================== - -.. contents:: - :depth: 3 - -This section provides frequently asked questions concerning SIL Kit and the corresponding answers. - -Data Generation & Transmission -============================== - -Is there a maximum payload size for Ethernet frames? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The size of the payload of Ethernet frames is not limited by SIL Kit. -Nonetheless, the maximum payload size might be constrained by the system resources available on the system on which SIL Kit is executed. - -Is there a maximum payload size for Publish/Subscribe or RPC data? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The size of the data payload of the Publish Subscribe and RPC service are not limited by SIL Kit. -Nonetheless, the maximum payload size might be constrained by the system resources available on the system on which SIL Kit is executed. - -Can I use a DBC file to generate CAN frames? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Within SIL Kit, there is no included support for DBC files. -You can use SIL Kit enabled tools that have support for DBC files, or you will need to implement DBC support within your implementation yourself. - -Setup -===== - -Is it possible to use statically configured ports for SIL Kit peer-to-peer communication between participants? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Since version 4.0.16 users can specify which port the participant opens for communication between participants by using the ``AcceptorUris`` field within the :ref:`Middeware section of the participant configuration`. -By doing so, a firewall can be configured to allow these static ports for communication. -The port used by the SIL Kit registry can be specified through its :ref:`CLI`. - -What is the sil-kit-registry? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The SIL Kit registry is a central utility that is necessary for running a SIL Kit simulation. -At the start, each participant connects to the registry and retrieves the connection information to all other participants. -In this sense, the registry acts as a phone book that tells the user the contact information to all other participants of a SIL Kit simulation. -The registry does not partake in the simulation itself. -It especially does not route messages between participants. -Please note that it is mandatory that all SIL Kit simulation participants can reach the SIL Kit registry for a proper simulation setup. - -Can I use Vector SIL Kit together with real hardware/in a Hardware-in-the-Loop setup? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Vector SIL Kit was designed deliberately with Software-in-the-Loop environments in mind. -Many aspects of it are designed for SIL settings (especially the virtual time synchronization, that adapts its speed to the execution speed of the participants) and not HIL settings. -These aspects might imply that SIL Kit does not fit the needs of your hardware setup. -Furthermore, SIL Kit itself does not provide capabilities to connect it to a hardware setup. - -Nonetheless, some SIL Kit enabled tools may allow you to bridge a SIL Kit simulation and a HIL setup. - -How can I interoperate a SIL Kit simulation that is distributed between Windows and Linux clients? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For SIL Kit it does not matter whether all simulation participants are running on the same kind of operating system. -All SIL Kit simulation participants must be able to connect to the SIL Kit registry, and they must be able to establish a connection to all other simulation participants. -In such a distributed setting, the SIL Kit registry must be started such that it is reachable through the network by other hosts. - -You might do so by running the command below: - -.. code-block:: console - - ./sil-kit-registry.exe --listen-uri silkit://0.0.0.0:8501 - -.. admonition:: Note - - This example uses a different port, as a tool may have already opened a registry on the default port 8500. - -All simulation participants must now specify a URI so that they connect to this registry (e.g., ``silkit://:8501``). - - -Other -===== - -How is the performance/latency/throughput of the SIL Kit? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The specific performance (latency, throughput, animation factor, etc.) of your SIL Kit simulation depends on a set of parameters that highly depend on your use case. -The number of simulation participants, whether virtual time synchronization is used, the size of simulation steps, the size and frequency of messages being exchanged, and many other aspects highly influence the performance for you use case. -Finally, the hardware being used, the network infrastructure and the distribution of simulation participants over different hosts affect the performance as well. - -To get a first impression of the performance that can be expected of the SIL Kit in your use case, refer to the :ref:`Benchmark Demo` where you can specify a set of relevant parameters and get real performance measurements for your setup. - -Can I control the order in which simulation participants execute their simulation steps, in case they occur at the same time? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -No, the order simulation step execution of synchronized participants can not be controlled. - -How can I configure a SIL Kit participant to write a trace log file? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A trace log file can be used in debugging scenarios to get a detailed insight into the execution of a SIL Kit participant. - -The :ref:`participant configuration` is a YAML file which enables you to modify some aspects of the runtime behavior of SIL Kit simulation participants. -In particular, you can also use it to let a participant generate a trace log file. - -For example, by adding the following configuration: - -.. code-block:: console - - Logging: - Sinks: - - Type: File - Level: Trace - LogName: TraceLogFile - -.. admonition:: Note - - If your participant configuration already contains a logging section, you must only add the sink. - -This will tell SIL Kit to write all log messages of Level trace and above to a file in the process working directory of the SIL Kit participant. -The file name will be ``TraceLogFile`` with a time-specific suffix. -The ``LogName`` field also supports an absolute path, e.g., ``LogName: C:\Temp\SimulationLog``. +========================== +Frequently Asked Questions +========================== + +.. contents:: + :depth: 3 + +This section provides frequently asked questions concerning SIL Kit and the corresponding answers. + +Data Generation & Transmission +============================== + +Is there a maximum payload size for Ethernet frames? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The size of the payload of Ethernet frames is not limited by SIL Kit. +Nonetheless, the maximum payload size might be constrained by the system resources available on the system on which SIL Kit is executed. + +Is there a maximum payload size for Publish/Subscribe or RPC data? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The size of the data payload of the Publish Subscribe and RPC service are not limited by SIL Kit. +Nonetheless, the maximum payload size might be constrained by the system resources available on the system on which SIL Kit is executed. + +Can I use a DBC file to generate CAN frames? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Within SIL Kit, there is no included support for DBC files. +You can use SIL Kit enabled tools that have support for DBC files, or you will need to implement DBC support within your implementation yourself. + +Setup +===== + +Is it possible to use statically configured ports for SIL Kit peer-to-peer communication between participants? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since version 4.0.16 users can specify which port the participant opens for communication between participants by using the ``AcceptorUris`` field within the :ref:`Middeware section of the participant configuration`. +By doing so, a firewall can be configured to allow these static ports for communication. +The port used by the SIL Kit registry can be specified through its :ref:`CLI`. + +What is the sil-kit-registry? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The SIL Kit registry is a central utility that is necessary for running a SIL Kit simulation. +At the start, each participant connects to the registry and retrieves the connection information to all other participants. +In this sense, the registry acts as a phone book that tells the user the contact information to all other participants of a SIL Kit simulation. +The registry does not partake in the simulation itself. +It especially does not route messages between participants. +Please note that it is mandatory that all SIL Kit simulation participants can reach the SIL Kit registry for a proper simulation setup. + +Can I use Vector SIL Kit together with real hardware/in a Hardware-in-the-Loop setup? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Vector SIL Kit was designed deliberately with Software-in-the-Loop environments in mind. +Many aspects of it are designed for SIL settings (especially the virtual time synchronization, that adapts its speed to the execution speed of the participants) and not HIL settings. +These aspects might imply that SIL Kit does not fit the needs of your hardware setup. +Furthermore, SIL Kit itself does not provide capabilities to connect it to a hardware setup. + +Nonetheless, some SIL Kit enabled tools may allow you to bridge a SIL Kit simulation and a HIL setup. + +How can I interoperate a SIL Kit simulation that is distributed between Windows and Linux clients? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For SIL Kit it does not matter whether all simulation participants are running on the same kind of operating system. +All SIL Kit simulation participants must be able to connect to the SIL Kit registry, and they must be able to establish a connection to all other simulation participants. +In such a distributed setting, the SIL Kit registry must be started such that it is reachable through the network by other hosts. + +You might do so by running the command below: + +.. code-block:: console + + ./sil-kit-registry.exe --listen-uri silkit://0.0.0.0:8501 + +.. admonition:: Note + + This example uses a different port, as a tool may have already opened a registry on the default port 8500. + +All simulation participants must now specify a URI so that they connect to this registry (e.g., ``silkit://:8501``). + + +Other +===== + +How is the performance/latency/throughput of the SIL Kit? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The specific performance (latency, throughput, animation factor, etc.) of your SIL Kit simulation depends on a set of parameters that highly depend on your use case. +The number of simulation participants, whether virtual time synchronization is used, the size of simulation steps, the size and frequency of messages being exchanged, and many other aspects highly influence the performance for you use case. +Finally, the hardware being used, the network infrastructure and the distribution of simulation participants over different hosts affect the performance as well. + +To get a first impression of the performance that can be expected of the SIL Kit in your use case, refer to the :ref:`Benchmark Demo` where you can specify a set of relevant parameters and get real performance measurements for your setup. + +Can I control the order in which simulation participants execute their simulation steps, in case they occur at the same time? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +No, the order simulation step execution of synchronized participants can not be controlled. + +How can I configure a SIL Kit participant to write a trace log file? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A trace log file can be used in debugging scenarios to get a detailed insight into the execution of a SIL Kit participant. + +The :ref:`participant configuration` is a YAML file which enables you to modify some aspects of the runtime behavior of SIL Kit simulation participants. +In particular, you can also use it to let a participant generate a trace log file. + +For example, by adding the following configuration: + +.. code-block:: console + + Logging: + Sinks: + - Type: File + Level: Trace + LogName: TraceLogFile + +.. admonition:: Note + + If your participant configuration already contains a logging section, you must only add the sink. + +This will tell SIL Kit to write all log messages of Level trace and above to a file in the process working directory of the SIL Kit participant. +The file name will be ``TraceLogFile`` with a time-specific suffix. +The ``LogName`` field also supports an absolute path, e.g., ``LogName: C:\Temp\SimulationLog``. + +How can I use unicode characters with SIL Kit? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +SIL Kit expects strings passed via the C and C++ API to be encoded as UTF-8. +This is particularly important for paths, e.g., the path to the participant configuration. + +This can lead to some confusion when SIL Kit is used on the Windows operating system. + +The utility executables (``sil-kit-registry``, ``sil-kit-system-controller``, and ``sil-kit-monitor``), and all demo applications are compiled using a manifest, that automatically activates the UTF-8 codepage. +This allows the correct handling of paths containing Unicode characters. + +Even in modern Windows systems, UTF-8 is usually not used as the default codepage, in order to be compatible with old applications. +Unfortunately this can lead to strange characters in the command line output of SIL Kit tools, when, e.g., the participant name contains non-ASCII characters. + +As an example, when the participant name is set to ``🚗`` (car emoji), if the output codepage is not changed to UTF-8, the output might look like this: + +.. figure:: ../_static/faq-example-bad-output-codepage.png + :alt: : Mangled output from SIL Kit when the output codepage is not UTF-8, and the participant name contains Unicode characters + :align: center + :width: 1000 + + : Mangled output from SIL Kit when the output codepage is not UTF-8, and the participant name contains Unicode characters + +If the output codepage is changed to UTF-8 (see below), the output should look like this: + +.. figure:: ../_static/faq-example-good-output-codepage.png + :alt: : Correct output from SIL Kit when the output codepage is set to UTF-8, and the participant name contains Unicode characters + :align: center + :width: 1000 + + : Correct output from SIL Kit when the output codepage is set to UTF-8, and the participant name contains Unicode characters + +If you use ``cmd.exe``, run the command ``chcp 65001`` before invoking any SIL Kit utilities or demos. +This command changes the output codepage of the console window to UTF-8, which is required to correctly decode the text output of the executables for presentation in the console window. + +If you use PowerShell, run ``[console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding`` before invoking any SIL Kit utilities or demos to achieve the same effect.