mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-08-30 04:15:10 +00:00
connection between 2 systems and bug fixes (#14)
This commit is contained in:
@@ -119,6 +119,9 @@ else()
|
||||
if (WIN32)
|
||||
message("Use g++ compiler under Windows (mingw)...")
|
||||
add_compile_definitions(UNICODE _UNICODE main=wmain)
|
||||
# MinGW COFF object files can hit section limits for large translation units.
|
||||
# Enable big object format to avoid assembler 'too many sections' failures.
|
||||
add_compile_options(-Wa,-mbig-obj)
|
||||
add_link_options(-municode)
|
||||
else()
|
||||
message("Use g++ compiler...")
|
||||
|
||||
17
README.md
17
README.md
@@ -1,3 +1,20 @@
|
||||
The 'Eclipse Open Vehicle API' project is supported by Chips JU.
|
||||
|
||||
<img src="funding_logos\CHIPS_logo_RGB_full_colour.png" alt="arch-module-if" height="80"/>
|
||||
|
||||
<img src="funding_logos\EN_Co-fundedbytheEU_RGB_POS.png" alt="arch-module-if" height="80"/>
|
||||
|
||||
The HAL4SDV project (Grant Agreement No. 101139789) is supported by the Chips Joint Undertaking and its members, including top-up funding by the national authorities.
|
||||
|
||||
<img src="funding_logos\HAL4SDV_logo_on_white.jpg" alt="arch-module-if" height="80"/>
|
||||
|
||||
The Shift2SDV project (Grant Agreement No. 101194245) is supported by the Chips Joint Undertaking and its members, including top-up funding by the national authorities.
|
||||
|
||||
<img src="funding_logos\Shift2sdv_logo_tagline_blue.svg" alt="arch-module-if" height="80"/>
|
||||
|
||||
---
|
||||
|
||||
|
||||
# This is the latest news about 'Eclipse Open Vehicle API'
|
||||
#
|
||||
# for more information see documentation: https://eclipse.dev/openvehicle-api/
|
||||
|
||||
1089
doxygen.config
1089
doxygen.config
File diff suppressed because it is too large
Load Diff
@@ -353,7 +353,7 @@ void CConsole::StartUpdateDataThread()
|
||||
m_bThreadStarted = true;
|
||||
|
||||
m_bRunning = true;
|
||||
m_threadReadTxSignals = std::thread(&CConsole::UpdateDataThreadFunc, this);
|
||||
m_threadReadTxSignals = sdv::core::secure_thread(&CConsole::UpdateDataThreadFunc, this);
|
||||
}
|
||||
|
||||
void CConsole::StopUpdateDataThread()
|
||||
|
||||
@@ -200,33 +200,33 @@ private:
|
||||
*/
|
||||
std::string AlignString(const std::string& message, uint32_t desiredLength = 0);
|
||||
|
||||
mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
|
||||
std::thread m_threadReadTxSignals; ///< Simulation datalink thread.
|
||||
bool m_bThreadStarted = false; ///< Set when initialized.
|
||||
std::atomic_bool m_bRunning = false; ///< When set, the application is running.
|
||||
mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
|
||||
sdv::core::secure_thread m_threadReadTxSignals; ///< Simulation datalink thread.
|
||||
bool m_bThreadStarted = false; ///< Set when initialized.
|
||||
std::atomic_bool m_bRunning = false; ///< When set, the application is running.
|
||||
|
||||
sdv::core::CSignal m_signalCurrentLatitude; ///< Signal Current latitude
|
||||
sdv::core::CSignal m_signalCurrentLongitude; ///< Signal Current longitude
|
||||
sdv::core::CSignal m_signalHeadlight; ///< Signal Headlight status
|
||||
sdv::core::CSignal m_signalCurrentLatitude; ///< Signal Current latitude
|
||||
sdv::core::CSignal m_signalCurrentLongitude; ///< Signal Current longitude
|
||||
sdv::core::CSignal m_signalHeadlight; ///< Signal Headlight status
|
||||
|
||||
float m_fCurrentLongitude = 0.0f; //< Current latitude
|
||||
float m_fCurrentLatitude = 0.0f; //< Current longitude
|
||||
bool m_bHeadLight = true; ///< Head light
|
||||
float m_fCurrentLongitude = 0.0f; //< Current latitude
|
||||
float m_fCurrentLatitude = 0.0f; //< Current longitude
|
||||
bool m_bHeadLight = true; ///< Head light
|
||||
|
||||
float m_fVehicleDeviceCurrentLatitude = 0.0f; ///< Current latitude (Vehicle Device)
|
||||
float m_fVehicleDeviceCurrentLongitude = 0.0; ///< Current longitude (Vehicle Device)
|
||||
float m_fVehicleDeviceCurrentLatitude = 0.0f; ///< Current latitude (Vehicle Device)
|
||||
float m_fVehicleDeviceCurrentLongitude = 0.0; ///< Current longitude (Vehicle Device)
|
||||
|
||||
float m_fBasicServiceCurrentLatitude = 0.0f; ///< Current latitude (basic Service)
|
||||
float m_fBasicServiceCurrentLongitude = 0.0; ///< Current longitude (basic Service)
|
||||
float m_fBasicServiceCurrentLatitude = 0.0f; ///< Current latitude (basic Service)
|
||||
float m_fBasicServiceCurrentLongitude = 0.0; ///< Current longitude (basic Service)
|
||||
|
||||
IAutoheadlightService* m_pIAutoheadlightComplexService = nullptr; ///< Autoheadlight Service interface pointer.
|
||||
IAutoheadlightService* m_pIAutoheadlightComplexService = nullptr; ///< Autoheadlight Service interface pointer.
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
#elif defined __unix__
|
||||
struct termios m_sTermAttr {}; ///< The terminal attributes before disabling echo.
|
||||
struct termios m_sTermAttr {}; ///< The terminal attributes before disabling echo.
|
||||
int m_iFileStatus = 0; ///< The file status flags for STDIN.
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
|
||||
@@ -94,7 +94,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
|
||||
std::ofstream tomlFile("sdv_core_reloc.toml");
|
||||
if (tomlFile.is_open())
|
||||
{
|
||||
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
|
||||
tomlFile << R"toml(# Location of the SDV binaries and configuration files
|
||||
[CoreLocation]
|
||||
Version = 100
|
||||
Framework = ")toml";
|
||||
tomlFile << resources;
|
||||
tomlFile << "\"\n";
|
||||
tomlFile.close();
|
||||
|
||||
@@ -43,59 +43,63 @@ file (COPY ${PROJECT_SOURCE_DIR}/door_example_receiver.asc DESTINATION ${CMAKE_B
|
||||
######################################################################################################################################################################
|
||||
|
||||
# Execute sdv_vss_util to create IDL files for devices and basic services.
|
||||
# In this example we split into into front and rear (frontdoors_proxystub.sdv and frontdoors_proxystub.sdv)
|
||||
# because all interfaces combined in doors_proxystub.sdv would be to large
|
||||
message("Create interface code for devices and basic services of doors example.")
|
||||
execute_process(COMMAND "${SDV_VSS_UTIL}" "${PROJECT_SOURCE_DIR}/vss_doors_example.csv" "-O${PROJECT_SOURCE_DIR}/generated/" --prefixdoors --version1.0.0.1 --enable_components)
|
||||
execute_process(COMMAND "${SDV_VSS_UTIL}" "${PROJECT_SOURCE_DIR}/vss_doors_front_example.csv" "-O${PROJECT_SOURCE_DIR}/generated/front/" --prefixfrontdoors --version1.0.0.1 --enable_components)
|
||||
execute_process(COMMAND "${SDV_VSS_UTIL}" "${PROJECT_SOURCE_DIR}/vss_doors_rear_example.csv" "-O${PROJECT_SOURCE_DIR}/generated/rear/" --prefixreardoors --version1.0.0.1 --enable_components)
|
||||
|
||||
|
||||
message("Compiling Interface Door01Left RX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door01Right RX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door02Left RX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door02Right RX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door01Left TX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door01Right TX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/front/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namefrontdoors_proxystub)
|
||||
|
||||
|
||||
message("Compiling Interface Door02Left RX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door02Right RX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door02Left TX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
|
||||
|
||||
message("Compiling Interface Door02Right TX")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/generated/rear/vss_files/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namereardoors_proxystub)
|
||||
|
||||
# Execute the IDL compiler for the complex service to digest interface code.
|
||||
message("Compiling door_ifc.idl")
|
||||
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/door_service/door_ifc.idl" "-O${PROJECT_SOURCE_DIR}/generated/door_service/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Iexample_service/ --ps_lib_namedoors_service_proxystub)
|
||||
|
||||
add_subdirectory(generated/door_service/ps)
|
||||
add_subdirectory(generated/vss_files/ps)
|
||||
add_subdirectory(generated/front/vss_files/ps)
|
||||
add_subdirectory(generated/rear/vss_files/ps)
|
||||
|
||||
add_subdirectory(generated/vss_files/vd_frontdoorleft)
|
||||
add_subdirectory(generated/vss_files/vd_frontdoorright)
|
||||
add_subdirectory(generated/vss_files/vd_reardoorleft)
|
||||
add_subdirectory(generated/vss_files/vd_reardoorright)
|
||||
add_subdirectory(generated/front/vss_files/vd_frontdoorleft)
|
||||
add_subdirectory(generated/front/vss_files/vd_frontdoorright)
|
||||
add_subdirectory(generated/front/vss_files/bs_frontdoorleft)
|
||||
add_subdirectory(generated/front/vss_files/bs_frontdoorright)
|
||||
|
||||
add_subdirectory(generated/vss_files/bs_frontdoorleft)
|
||||
add_subdirectory(generated/vss_files/bs_frontdoorright)
|
||||
add_subdirectory(generated/vss_files/bs_reardoorleft)
|
||||
add_subdirectory(generated/vss_files/bs_reardoorright)
|
||||
add_subdirectory(generated/rear/vss_files/vd_reardoorleft)
|
||||
add_subdirectory(generated/rear/vss_files/vd_reardoorright)
|
||||
add_subdirectory(generated/rear/vss_files/bs_reardoorleft)
|
||||
add_subdirectory(generated/rear/vss_files/bs_reardoorright)
|
||||
|
||||
# Execute sdv_dbc_util to create data link code & FMU code.
|
||||
message("Create data link for doors example")
|
||||
@@ -167,7 +171,6 @@ else()
|
||||
target_link_libraries(door_external_app Rpcrt4.lib)
|
||||
endif()
|
||||
|
||||
|
||||
######################################################################################################################################################################
|
||||
# create instance 3002 of door demo example
|
||||
######################################################################################################################################################################
|
||||
@@ -175,23 +178,25 @@ add_custom_target(vehicle_device_doors_config
|
||||
ALL
|
||||
DEPENDS
|
||||
can_dl_doors
|
||||
doors_vd_frontdoorleft_rx
|
||||
doors_vd_frontdoorright_rx
|
||||
doors_vd_reardoorleft_rx
|
||||
doors_vd_reardoorright_rx
|
||||
COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL VehicleDeviceDoors --instance3002 can_dl_doors.sdv doors_vd_frontdoorleft_rx.sdv doors_vd_frontdoorright_rx.sdv doors_vd_reardoorleft_rx.sdv doors_vd_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --interface_config --overwrite
|
||||
frontdoors_vd_frontdoorleft_rx
|
||||
frontdoors_vd_frontdoorright_rx
|
||||
reardoors_vd_reardoorleft_rx
|
||||
reardoors_vd_reardoorright_rx
|
||||
COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL VehicleDeviceDoors --instance3002 can_dl_doors.sdv frontdoors_vd_frontdoorleft_rx.sdv frontdoors_vd_frontdoorright_rx.sdv reardoors_vd_reardoorleft_rx.sdv reardoors_vd_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --interface_config --overwrite
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
|
||||
add_custom_target(basic_service_doors_config
|
||||
ALL
|
||||
DEPENDS
|
||||
doors_proxystub
|
||||
doors_bs_frontdoorleft_rx
|
||||
doors_bs_frontdoorright_rx
|
||||
doors_bs_reardoorleft_rx
|
||||
doors_bs_reardoorright_rx
|
||||
COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL BasicServiceDoors --instance3002 doors_proxystub.sdv doors_bs_frontdoorleft_rx.sdv doors_bs_frontdoorright_rx.sdv doors_bs_reardoorleft_rx.sdv doors_bs_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --abstract_config --overwrite
|
||||
frontdoors_proxystub
|
||||
reardoors_proxystub
|
||||
frontdoors_bs_frontdoorleft_rx
|
||||
frontdoors_bs_frontdoorright_rx
|
||||
reardoors_bs_reardoorleft_rx
|
||||
reardoors_bs_reardoorright_rx
|
||||
COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL BasicServiceDoors --instance3002 frontdoors_proxystub.sdv reardoors_proxystub.sdv frontdoors_bs_frontdoorleft_rx.sdv frontdoors_bs_frontdoorright_rx.sdv reardoors_bs_reardoorleft_rx.sdv reardoors_bs_reardoorright_rx.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --abstract_config --overwrite
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_frontdoorleft_rx.sdv"
|
||||
Path = "frontdoors_vd_frontdoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Left_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_frontdoorleft_rx.sdv"
|
||||
Path = "frontdoors_bs_frontdoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Left_Service"
|
||||
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_frontdoorright_rx.sdv"
|
||||
Path = "frontdoors_vd_frontdoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Right_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_frontdoorright_rx.sdv"
|
||||
Path = "frontdoors_bs_frontdoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Right_Service"
|
||||
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_reardoorleft_rx.sdv"
|
||||
Path = "reardoors_vd_reardoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Left_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_reardoorleft_rx.sdv"
|
||||
Path = "reardoors_bs_reardoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Left_Service"
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_reardoorright_rx.sdv"
|
||||
Path = "reardoors_vd_reardoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Right_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_reardoorright_rx.sdv"
|
||||
Path = "reardoors_bs_reardoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Right_Service"
|
||||
|
||||
@@ -128,7 +128,6 @@ void CConsole::PrintHeader(const uint32_t numberOfDoors)
|
||||
PrintText(g_sTitle, title.c_str());
|
||||
PrintText(g_sControlDescription, "Press 'X' to quit; Doors are toggled automatically");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CConsole::PrepareDataConsumers()
|
||||
@@ -205,8 +204,7 @@ void CConsole::ResetSignals()
|
||||
// Set the cursor position at the end
|
||||
SetCursorPos(g_sCursor);
|
||||
|
||||
// Registrate for the vehicle device & basic service of the front left door. Front left door mzust exist, the others are optional
|
||||
auto vehicleDevice =
|
||||
auto vehicleDevice =
|
||||
sdv::core::GetObject("Vehicle.Body.Door.Axle._01.Left_Device").GetInterface < vss::Vehicle::Body::Door::Axle::_01 ::LeftDevice::IVSS_ReadIsOpen > ();
|
||||
if (vehicleDevice)
|
||||
vehicleDevice->UnregisterIsOpenEvent(dynamic_cast<vss::Vehicle::Body::Door::Axle::_01::LeftDevice::IVSS_WriteIsOpen_Event*> (this));
|
||||
@@ -254,7 +252,7 @@ void CConsole::StartUpdateDataThread()
|
||||
m_bThreadStarted = true;
|
||||
|
||||
m_bRunning = true;
|
||||
m_threadReadTxSignals = std::thread(&CConsole::UpdateDataThreadFunc, this);
|
||||
m_threadReadTxSignals = sdv::core::secure_thread(&CConsole::UpdateDataThreadFunc, this);
|
||||
}
|
||||
|
||||
void CConsole::StopUpdateDataThread()
|
||||
@@ -299,21 +297,21 @@ bool CConsole::PrepareDataConsumersForStandAlone()
|
||||
{
|
||||
// Subscribe for the door and if available get TX signal. Either both exists or none of them
|
||||
sdv::core::CDispatchService dispatch;
|
||||
m_SignalFrontLeftDoorIsOpen = dispatch.Subscribe(doors::dsLeftDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontLeftDoorIsOpen(value); });
|
||||
m_SignalFrontLeftDoorIsOpen = dispatch.Subscribe(frontdoors::dsLeftDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontLeftDoorIsOpen(value); });
|
||||
if(m_SignalFrontLeftDoorIsOpen)
|
||||
m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch01, 0);
|
||||
m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsLeftLatch01, 0);
|
||||
|
||||
m_SignalFrontRightDoorIsOpen = dispatch.Subscribe(doors::dsRightDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontRightDoorIsOpen(value); });
|
||||
m_SignalFrontRightDoorIsOpen = dispatch.Subscribe(frontdoors::dsRightDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontRightDoorIsOpen(value); });
|
||||
if(m_SignalFrontRightDoorIsOpen)
|
||||
m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch01, 0);
|
||||
m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsRightLatch01, 0);
|
||||
|
||||
m_SignalRearLeftDoorIsOpen = dispatch.Subscribe(doors::dsLeftDoorIsOpen02, [&](sdv::any_t value) {CallbackRearLeftDoorIsOpen(value); });
|
||||
m_SignalRearLeftDoorIsOpen = dispatch.Subscribe(reardoors::dsLeftDoorIsOpen02, [&](sdv::any_t value) {CallbackRearLeftDoorIsOpen(value); });
|
||||
if(m_SignalRearLeftDoorIsOpen)
|
||||
m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch02, 0);
|
||||
m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsLeftLatch02, 0);
|
||||
|
||||
m_SignalRearRightDoorIsOpen = dispatch.Subscribe(doors::dsRightDoorIsOpen02, [&](sdv::any_t value) { CallbackRearRightDoorIsOpen(value); });
|
||||
m_SignalRearRightDoorIsOpen = dispatch.Subscribe(reardoors::dsRightDoorIsOpen02, [&](sdv::any_t value) { CallbackRearRightDoorIsOpen(value); });
|
||||
if(m_SignalRearRightDoorIsOpen)
|
||||
m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch02, 0);
|
||||
m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsRightLatch02, 0);
|
||||
|
||||
// Validate: Either both exists or none of them
|
||||
if (m_SignalFrontLeftDoorIsOpen != m_SignalFrontLeftDoorIsLocked)
|
||||
@@ -337,7 +335,7 @@ bool CConsole::PrepareDataConsumersForStandAlone()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Registrate for the vehicle device & basic service of the front left door. Front left door mzust exist, the others are optional
|
||||
// Register for the vehicle device & basic service of the front left door. Front left door must exist, the others are optional
|
||||
auto vehicleDevice = sdv::core::GetObject("Vehicle.Body.Door.Axle._01.Left_Device").GetInterface<vss::Vehicle::Body::Door::Axle::_01::LeftDevice::IVSS_ReadIsOpen>();
|
||||
if (!vehicleDevice)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "../door_app/include/door_application.h"
|
||||
#include "../generated/vss_files/signal_identifier.h"
|
||||
#include "../generated/front/vss_files/signal_identifier.h"
|
||||
#include "../generated/rear/vss_files/signal_identifier.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <conio.h> // Needed for _kbhit
|
||||
@@ -61,23 +62,23 @@ bool CDoorControl::RegisterSignals()
|
||||
{
|
||||
sdv::core::CDispatchService dispatch;
|
||||
|
||||
m_SignalFrontLeftDoorIsOpen = dispatch.RegisterRxSignal(doors::dsLeftDoorIsOpen01);
|
||||
m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch01, 0);
|
||||
m_SignalFrontLeftDoorIsOpen = dispatch.RegisterRxSignal(frontdoors::dsLeftDoorIsOpen01);
|
||||
m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsLeftLatch01, 0);
|
||||
|
||||
if (m_iNumberOfDoors > 1)
|
||||
{
|
||||
m_SignalFrontRightDoorIsOpen = dispatch.RegisterRxSignal(doors::dsRightDoorIsOpen01);
|
||||
m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch01, 0);
|
||||
m_SignalFrontRightDoorIsOpen = dispatch.RegisterRxSignal(frontdoors::dsRightDoorIsOpen01);
|
||||
m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(frontdoors::dsRightLatch01, 0);
|
||||
|
||||
if (m_iNumberOfDoors > 2)
|
||||
{
|
||||
m_SignalRearLeftDoorIsOpen = dispatch.RegisterRxSignal(doors::dsLeftDoorIsOpen02);
|
||||
m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch02, 0);
|
||||
m_SignalRearLeftDoorIsOpen = dispatch.RegisterRxSignal(reardoors::dsLeftDoorIsOpen02);
|
||||
m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsLeftLatch02, 0);
|
||||
|
||||
if (m_iNumberOfDoors > 3)
|
||||
{
|
||||
m_SignalRearRightDoorIsOpen = dispatch.RegisterRxSignal(doors::dsRightDoorIsOpen02);
|
||||
m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch02, 0);
|
||||
m_SignalRearRightDoorIsOpen = dispatch.RegisterRxSignal(reardoors::dsRightDoorIsOpen02);
|
||||
m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(reardoors::dsRightLatch02, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "../door_app/include/door_extern_application.h"
|
||||
#include "../generated/vss_files/signal_identifier.h"
|
||||
#include "../generated/front/vss_files/signal_identifier.h"
|
||||
#include "../generated/rear/vss_files/signal_identifier.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <conio.h> // Needed for _kbhit
|
||||
|
||||
@@ -19,15 +19,16 @@
|
||||
#include <support/app_control.h>
|
||||
#include <support/component_impl.h>
|
||||
#include <support/timer.h>
|
||||
#include "../../generated/vss_files/signal_identifier.h"
|
||||
#include "../../generated/front/vss_files/signal_identifier.h"
|
||||
#include "../../generated/rear/vss_files/signal_identifier.h"
|
||||
#include <fcntl.h>
|
||||
#include <atomic>
|
||||
|
||||
#include "../../generated/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.h"
|
||||
#include "../../generated/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
|
||||
#include "../../generated/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
|
||||
#include "../../generated/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
|
||||
#include "../../generated/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
|
||||
#include "../../generated/front/vss_files/vss_vehiclebodydooraxle_01left_vd_rx.h"
|
||||
#include "../../generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
|
||||
#include "../../generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
|
||||
#include "../../generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
|
||||
#include "../../generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
|
||||
|
||||
#ifdef __unix__
|
||||
#include <termios.h> // Needed for tcgetattr and fcntl
|
||||
@@ -215,41 +216,41 @@ private:
|
||||
*/
|
||||
std::string AlignString(const std::string& message, uint32_t desiredLength = 0);
|
||||
|
||||
mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
|
||||
bool m_bThreadStarted = false; ///< Set when initialized.
|
||||
std::atomic_bool m_bRunning = false; ///< When set, the application is running.
|
||||
bool m_isExternalApp = false; ///< True when we have an external application
|
||||
mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
|
||||
bool m_bThreadStarted = false; ///< Set when initialized.
|
||||
std::atomic_bool m_bRunning = false; ///< When set, the application is running.
|
||||
bool m_isExternalApp = false; ///< True when we have an external application
|
||||
|
||||
std::thread m_threadReadTxSignals; ///< Simulation datalink thread.
|
||||
sdv::core::secure_thread m_threadReadTxSignals; ///< Simulation datalink thread.
|
||||
|
||||
sdv::core::CSignal m_SignalFrontLeftDoorIsOpen; ///< Front Left Door signal (RX input) - open / closed
|
||||
sdv::core::CSignal m_SignalFrontRightDoorIsOpen; ///< Front Right Door signal (RX input) - open / closed
|
||||
sdv::core::CSignal m_SignalRearLeftDoorIsOpen; ///< Rear Left Door signal (RX input) - open / closed
|
||||
sdv::core::CSignal m_SignalRearRightDoorIsOpen; ///< Rear Right Door signal (RX input) - open / closed
|
||||
sdv::core::CSignal m_SignalFrontLeftDoorIsOpen; ///< Front Left Door signal (RX input) - open / closed
|
||||
sdv::core::CSignal m_SignalFrontRightDoorIsOpen; ///< Front Right Door signal (RX input) - open / closed
|
||||
sdv::core::CSignal m_SignalRearLeftDoorIsOpen; ///< Rear Left Door signal (RX input) - open / closed
|
||||
sdv::core::CSignal m_SignalRearRightDoorIsOpen; ///< Rear Right Door signal (RX input) - open / closed
|
||||
|
||||
bool m_FrontLeftDoorIsOpen = false; ///< Front Left Door value (RX input signal) - open / closed
|
||||
bool m_FrontRightDoorIsOpen = false; ///< Front Right Door value (RX input signal) - open / closed
|
||||
bool m_RearLeftDoorIsOpen = false; ///< Rear Left Door value (RX input signal) - open / closed
|
||||
bool m_RearRightDoorIsOpen = false; ///< Rear Right Door value (RX input signal) - open / closed
|
||||
bool m_FrontLeftDoorIsOpen = false; ///< Front Left Door value (RX input signal) - open / closed
|
||||
bool m_FrontRightDoorIsOpen = false; ///< Front Right Door value (RX input signal) - open / closed
|
||||
bool m_RearLeftDoorIsOpen = false; ///< Rear Left Door value (RX input signal) - open / closed
|
||||
bool m_RearRightDoorIsOpen = false; ///< Rear Right Door value (RX input signal) - open / closed
|
||||
|
||||
sdv::core::CSignal m_SignalFrontLeftDoorIsLocked; ///< Front Left Door signal (TX output) - locked / unlocked
|
||||
sdv::core::CSignal m_SignalFrontRightDoorIsLocked; ///< Front Right Door signal (TX output) - locked / unlocked
|
||||
sdv::core::CSignal m_SignalRearLeftDoorIsLocked; ///< Rear Left Door signal (TX output) - locked / unlocked
|
||||
sdv::core::CSignal m_SignalRearRightDoorIsLocked; ///< Rear Right Door signal (TX output) - locked / unlocked
|
||||
sdv::core::CSignal m_SignalFrontLeftDoorIsLocked; ///< Front Left Door signal (TX output) - locked / unlocked
|
||||
sdv::core::CSignal m_SignalFrontRightDoorIsLocked; ///< Front Right Door signal (TX output) - locked / unlocked
|
||||
sdv::core::CSignal m_SignalRearLeftDoorIsLocked; ///< Rear Left Door signal (TX output) - locked / unlocked
|
||||
sdv::core::CSignal m_SignalRearRightDoorIsLocked; ///< Rear Right Door signal (TX output) - locked / unlocked
|
||||
|
||||
bool m_FrontLeftDoorIsLocked = false; ///< Front Left Door value (TX output) - locked / unlocked
|
||||
bool m_FrontRightDoorIsLocked = false; ///< Front Right Door value (TX output) - locked / unlocked
|
||||
bool m_RearLeftDoorIsLocked = false; ///< Rear Left Door value (TX output) - locked / unlocked
|
||||
bool m_RearRightDoorIsLocked = false; ///< Rear Right Door value (TX output) - locked / unlocked
|
||||
bool m_FrontLeftDoorIsLocked = false; ///< Front Left Door value (TX output) - locked / unlocked
|
||||
bool m_FrontRightDoorIsLocked = false; ///< Front Right Door value (TX output) - locked / unlocked
|
||||
bool m_RearLeftDoorIsLocked = false; ///< Rear Left Door value (TX output) - locked / unlocked
|
||||
bool m_RearRightDoorIsLocked = false; ///< Rear Right Door value (TX output) - locked / unlocked
|
||||
|
||||
IDoorService* m_pDoorService = nullptr; ///< Door service interface pointer.
|
||||
IDoorService* m_pDoorService = nullptr; ///< Door service interface pointer.
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
DWORD m_dwConsoleOutMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
DWORD m_dwConsoleInMode = 0u; ///< The console mode before switching on ANSI support.
|
||||
#elif defined __unix__
|
||||
struct termios m_sTermAttr{}; ///< The terminal attributes before disabling echo.
|
||||
int m_iFileStatus = 0; ///< The file status flags for STDIN.
|
||||
struct termios m_sTermAttr{}; ///< The terminal attributes before disabling echo.
|
||||
int m_iFileStatus = 0; ///< The file status flags for STDIN.
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
#include <support/timer.h>
|
||||
|
||||
// VSS interfaces - located in ../generated/vss_files/
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.h"
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.h"
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.h"
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
|
||||
#include "../generated/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.h"
|
||||
#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_rx.h"
|
||||
#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01left_bs_tx.h"
|
||||
#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_rx.h"
|
||||
#include "../generated/front/vss_files/vss_vehiclebodydooraxle_01right_bs_tx.h"
|
||||
#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_rx.h"
|
||||
#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02left_bs_tx.h"
|
||||
#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_rx.h"
|
||||
#include "../generated/rear/vss_files/vss_vehiclebodydooraxle_02right_bs_tx.h"
|
||||
|
||||
#include "lock_doors_thread.h"
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
m_timeIn100MilliSeconds = timeSpan;
|
||||
m_counter = 0;
|
||||
m_running = true;
|
||||
m_thread = std::thread(&LockDoorsThread::run, this);
|
||||
m_thread = sdv::core::secure_thread(&LockDoorsThread::run, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,11 +94,11 @@ public:
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
std::function<void()> m_callback; ///< callback function
|
||||
std::atomic<bool> m_running; ///< status if loop is running
|
||||
std::thread m_thread; ///< timer thread
|
||||
uint32_t m_counter; ///< loop counter
|
||||
uint32_t m_timeIn100MilliSeconds; ///< time before the callback will be executed
|
||||
std::function<void()> m_callback; ///< callback function
|
||||
std::atomic<bool> m_running; ///< status if loop is running
|
||||
sdv::core::secure_thread m_thread; ///< timer thread
|
||||
uint32_t m_counter; ///< loop counter
|
||||
uint32_t m_timeIn100MilliSeconds; ///< time before the callback will be executed
|
||||
};
|
||||
|
||||
#endif // !define LOCK_DOORS_THREAD_H
|
||||
|
||||
@@ -100,7 +100,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
|
||||
std::ofstream tomlFile("sdv_core_reloc.toml");
|
||||
if (tomlFile.is_open())
|
||||
{
|
||||
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
|
||||
tomlFile << R"toml(# Location of the SDV binaries and configuration files
|
||||
[CoreLocation]
|
||||
Version = 100
|
||||
Framework = ")toml";
|
||||
tomlFile << resources;
|
||||
tomlFile << "\"\n";
|
||||
tomlFile.close();
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_frontdoorleft_rx.sdv"
|
||||
Path = "frontdoors_vd_frontdoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Left_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_frontdoorleft_rx.sdv"
|
||||
Path = "frontdoors_bs_frontdoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Left_Service"
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_frontdoorright_rx.sdv"
|
||||
Path = "frontdoors_vd_frontdoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Right_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_frontdoorright_rx.sdv"
|
||||
Path = "frontdoors_bs_frontdoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Right_Service"
|
||||
|
||||
|
||||
@@ -125,7 +125,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
|
||||
std::ofstream tomlFile("sdv_core_reloc.toml");
|
||||
if (tomlFile.is_open())
|
||||
{
|
||||
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
|
||||
tomlFile << R"toml(# Location of the SDV binaries and configuration files
|
||||
[CoreLocation]
|
||||
Version = 100
|
||||
Framework = ")toml";
|
||||
tomlFile << resources;
|
||||
tomlFile << "\"\n";
|
||||
tomlFile.close();
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_frontdoorleft_rx.sdv"
|
||||
Path = "frontdoors_vd_frontdoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Left_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_frontdoorleft_rx.sdv"
|
||||
Path = "frontdoors_bs_frontdoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Left_Service"
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_frontdoorright_rx.sdv"
|
||||
Path = "frontdoors_vd_frontdoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Right_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_frontdoorright_rx.sdv"
|
||||
Path = "frontdoors_bs_frontdoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._01.Right_Service"
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_reardoorleft_rx.sdv"
|
||||
Path = "reardoors_vd_reardoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Left_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_reardoorleft_rx.sdv"
|
||||
Path = "reardoors_bs_reardoorleft_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Left_Service"
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
Version = 100
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_vd_reardoorright_rx.sdv"
|
||||
Path = "reardoors_vd_reardoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Right_Device"
|
||||
|
||||
[[Component]]
|
||||
Path = "doors_bs_reardoorright_rx.sdv"
|
||||
Path = "reardoors_bs_reardoorright_rx.sdv"
|
||||
Class = "Vehicle.Body.Door.Axle._02.Right_Service"
|
||||
|
||||
@@ -2,17 +2,9 @@
|
||||
;;;;;;;
|
||||
VD;FrontDoorLeft;IsOpen;leftDoorIsOpen01;Vehicle.Body.Door.Axle.01.Left;RX;boolean;CAN_Input_L1.Door01LeftIsOpen
|
||||
VD;FrontDoorRight;IsOpen;rightDoorIsOpen01;Vehicle.Body.Door.Axle.01.Right;RX;boolean;CAN_Input_R1.Door01RightIsOpen
|
||||
VD;RearDoorLeft;IsOpen;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;CAN_Input_L2.Door02LeftIsOpen
|
||||
VD;RearDoorRight;IsOpen;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;CAN_Input_R2.Door02RightIsOpen
|
||||
VD;FrontDoorLeft;Lock;leftLatch01;Vehicle.Body.Door.Axle.01.Left;TX;boolean;CAN_Output.LockDoor01Left
|
||||
VD;FrontDoorRight;Lock;rightLatch01;Vehicle.Body.Door.Axle.01.Right;TX;boolean;CAN_Output.LockDoor01Right
|
||||
VD;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;CAN_Output.LockDoor02Left
|
||||
VD;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;CAN_Output.LockDoor02Right
|
||||
BS;FrontDoorLeft;IsOpenL1;leftDoorIsOpen01;Vehicle.Body.Door.Axle.01.Left;RX;boolean;Vehicle.Body.Door.Axle.01.Left
|
||||
BS;FrontDoorRight;IsOpenR1;rightDoorIsOpen01;Vehicle.Body.Door.Axle.01.Right;RX;boolean;Vehicle.Body.Door.Axle.01.Right
|
||||
BS;RearDoorLeft;IsOpenL2;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;Vehicle.Body.Door.Axle.02.Left
|
||||
BS;RearDoorRight;IsOpenR2;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;Vehicle.Body.Door.Axle.02.Right
|
||||
BS;FrontDoorLeft;Lock;leftLatch01;Vehicle.Body.Door.Axle.01.Left;TX;boolean;Vehicle.Body.Door.Axle.01.Left
|
||||
BS;FrontDoorRight;Lock;rightLatch01;Vehicle.Body.Door.Axle.01.Right;TX;boolean;Vehicle.Body.Door.Axle.01.Right
|
||||
BS;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;Vehicle.Body.Door.Axle.02.Left
|
||||
BS;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;Vehicle.Body.Door.Axle.02.Right
|
||||
|
10
examples/door_demo_example/vss_doors_rear_example.csv
Normal file
10
examples/door_demo_example/vss_doors_rear_example.csv
Normal file
@@ -0,0 +1,10 @@
|
||||
;Class name;Function name;Signal name;vss;Signal direction;type;DBC CAN name includes CAN message name
|
||||
;;;;;;;
|
||||
VD;RearDoorLeft;IsOpen;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;CAN_Input_L2.Door02LeftIsOpen
|
||||
VD;RearDoorRight;IsOpen;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;CAN_Input_R2.Door02RightIsOpen
|
||||
VD;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;CAN_Output.LockDoor02Left
|
||||
VD;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;CAN_Output.LockDoor02Right
|
||||
BS;RearDoorLeft;IsOpenL2;leftDoorIsOpen02;Vehicle.Body.Door.Axle.02.Left;RX;boolean;Vehicle.Body.Door.Axle.02.Left
|
||||
BS;RearDoorRight;IsOpenR2;rightDoorIsOpen02;Vehicle.Body.Door.Axle.02.Right;RX;boolean;Vehicle.Body.Door.Axle.02.Right
|
||||
BS;RearDoorLeft;Lock;leftLatch02;Vehicle.Body.Door.Axle.02.Left;TX;boolean;Vehicle.Body.Door.Axle.02.Left
|
||||
BS;RearDoorRight;Lock;rightLatch02;Vehicle.Body.Door.Axle.02.Right;TX;boolean;Vehicle.Body.Door.Axle.02.Right
|
||||
|
@@ -34,9 +34,11 @@ const CConsole::SConsolePos g_sComment3{ 24, 1 };
|
||||
const CConsole::SConsolePos g_sSeparator5{ 26, 1 };
|
||||
const CConsole::SConsolePos g_sOpenViaDevice{ 28, 1 };
|
||||
const CConsole::SConsolePos g_sOpenViaService{ 29, 1 };
|
||||
const CConsole::SConsolePos g_sSeparator6{ 31, 1 };
|
||||
const CConsole::SConsolePos g_sControlDescription{ 33, 1 };
|
||||
const CConsole::SConsolePos g_sCursor{ 34, 1 };
|
||||
const CConsole::SConsolePos g_sAutoCloseTrunk{ 30, 1 };
|
||||
const CConsole::SConsolePos g_sStatusTrunk{ 32, 1 };
|
||||
const CConsole::SConsolePos g_sSeparator6{ 34, 1 };
|
||||
const CConsole::SConsolePos g_sControlDescription{ 36, 1 };
|
||||
const CConsole::SConsolePos g_sCursor{ 37, 1 };
|
||||
|
||||
CConsole::CConsole()
|
||||
{
|
||||
@@ -92,6 +94,7 @@ void CConsole::PrintHeader(uint32_t uiInstance)
|
||||
{
|
||||
subTtitle = "Connected to core instance ";
|
||||
subTtitle.append(std::to_string(uiInstance));
|
||||
subTtitle.append(" (not all interfaces available)");
|
||||
}
|
||||
// Print the titles
|
||||
PrintText(g_sTitle, "Open Trunk example: Open trunk when vehicle is not moving");
|
||||
@@ -108,7 +111,7 @@ void CConsole::PrintHeader(uint32_t uiInstance)
|
||||
PrintText(g_sSeparator4, "============================================================================");
|
||||
PrintText(g_sComment1, "The Open Trunk signal has a safety request.");
|
||||
PrintText(g_sComment2, "Therefore the speed value is required and must be checked.");
|
||||
PrintText(g_sComment3, "If the car is moving, open is blocked and trunk is closed automatically.");
|
||||
PrintText(g_sComment3, "If the vehicle is moving, open is blocked and trunk is closed automatically.");
|
||||
PrintText(g_sSeparator5, "============================================================================");
|
||||
PrintText(g_sOpenViaDevice, "Vehicle Device Interface not available.");
|
||||
PrintText(g_sOpenViaService, "Basic Service Interface not available.");
|
||||
@@ -124,7 +127,7 @@ bool CConsole::PrepareDataConsumers()
|
||||
if (m_SignalSpeed)
|
||||
PrintValue(g_sDataLinkSpeed, "Vehicle Speed RX", m_SpeedDL, "m/s");
|
||||
|
||||
// Registrate for the vehicle device & basic service of the speed.
|
||||
// Register for the vehicle device & basic service of the speed.
|
||||
auto vehicleDevice = sdv::core::GetObject("Vehicle.Speed_Device").GetInterface<vss::Vehicle::SpeedDevice::IVSS_ReadSpeed>();
|
||||
if (vehicleDevice)
|
||||
{
|
||||
@@ -153,6 +156,10 @@ bool CConsole::PrepareDataConsumers()
|
||||
else
|
||||
PrintText(g_sOpenViaDevice, "Trunk Device NOT available");
|
||||
|
||||
m_SignalStatusTrunk = dispatch.RegisterTxSignal(trunk::dsTrunk, 0);
|
||||
if (!m_SignalStatusTrunk)
|
||||
PrintText(g_sStatusTrunk, "Trunk Status not available.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -172,6 +179,9 @@ void CConsole::ResetSignals()
|
||||
// Unregister the data link signals
|
||||
if (m_SignalSpeed)
|
||||
m_SignalSpeed.Reset();
|
||||
|
||||
if (m_SignalStatusTrunk)
|
||||
m_SignalStatusTrunk.Reset();
|
||||
}
|
||||
|
||||
void CConsole::CallbackSpeed(sdv::any_t value)
|
||||
@@ -246,7 +256,13 @@ void CConsole::SetSpeed(float value)
|
||||
|
||||
if (bIsMoving && !m_bWasMovingBS)
|
||||
{
|
||||
PrintText(g_sOpenViaService, "Safety active: speed > 0, trunk close command sent.");
|
||||
if (m_pTrunkService)
|
||||
{
|
||||
if (m_pTrunkService->SetOpen(false))
|
||||
PrintText(g_sAutoCloseTrunk, "Safety feature active: Trunk closed as the vehicle started moving.");
|
||||
else
|
||||
PrintText(g_sOpenViaService, "Close trunk automatically failed.");
|
||||
}
|
||||
}
|
||||
m_bWasMovingBS = bIsMoving;
|
||||
}
|
||||
@@ -278,9 +294,24 @@ char CConsole::GetChar()
|
||||
void CConsole::RunUntilBreak()
|
||||
{
|
||||
bool bRunning = true;
|
||||
bool bTrunkClosed = true;
|
||||
|
||||
while (bRunning)
|
||||
{
|
||||
if(m_SignalStatusTrunk)
|
||||
{
|
||||
auto value =m_SignalStatusTrunk.Read().get<bool>();
|
||||
if (bTrunkClosed != value)
|
||||
{
|
||||
bTrunkClosed = value;
|
||||
if (bTrunkClosed)
|
||||
PrintText(g_sStatusTrunk, "Status: Trunk is open.");
|
||||
else
|
||||
PrintText(g_sStatusTrunk, "Status: Trunk is closed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check for a key
|
||||
if (!KeyHit())
|
||||
{
|
||||
@@ -294,17 +325,19 @@ void CConsole::RunUntilBreak()
|
||||
{
|
||||
case 'c':
|
||||
case 'C':
|
||||
PrintText(g_sOpenViaDevice, " ");
|
||||
PrintText(g_sOpenViaService, " ");
|
||||
PrintText(g_sOpenViaDevice, " ");
|
||||
PrintText(g_sOpenViaService, " ");
|
||||
PrintText(g_sAutoCloseTrunk, " ");
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
if (m_pTrunkDevice)
|
||||
{
|
||||
PrintText(g_sAutoCloseTrunk, " ");
|
||||
if (m_pTrunkDevice->WriteOpen(true))
|
||||
{
|
||||
if (m_SpeedVD || m_SpeedBS)
|
||||
PrintText(g_sOpenViaDevice, "Trunk opened directly although car was moving, not safe.");
|
||||
PrintText(g_sOpenViaDevice, "Trunk opened directly although vehicle was moving, not safe.");
|
||||
else
|
||||
PrintText(g_sOpenViaDevice, "Trunk opened directly, not safe.");
|
||||
}
|
||||
@@ -316,10 +349,11 @@ void CConsole::RunUntilBreak()
|
||||
case 'O':
|
||||
if (m_pTrunkService)
|
||||
{
|
||||
PrintText(g_sAutoCloseTrunk, " ");
|
||||
if (m_pTrunkService->SetOpen(true))
|
||||
PrintText(g_sOpenViaService, "Trunk opened safely (auto-close if vehicle starts moving).");
|
||||
else
|
||||
PrintText(g_sOpenViaService, "Open trunk failed, car is moving.");
|
||||
PrintText(g_sOpenViaService, "Open trunk failed, vehicle is moving.");
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
|
||||
@@ -157,6 +157,7 @@ private:
|
||||
mutable std::mutex m_mtxPrintToConsole; ///< Mutex to print complete message
|
||||
bool m_bRunning = false; ///< When set, the application is running.
|
||||
|
||||
sdv::core::CSignal m_SignalStatusTrunk; ///< Status of the trunk, only available in the standalone example
|
||||
sdv::core::CSignal m_SignalSpeed; ///< Speed
|
||||
float m_SpeedDL = 0.0; ///< Speed Data Link
|
||||
float m_SpeedVD = 0.0; ///< Speed Vehicle Device
|
||||
|
||||
@@ -209,8 +209,7 @@ bool CConsole::PrepareDataConsumers()
|
||||
m_pCounterSteeringSvc = sdv::core::GetObject("Counter Steering Example Service").GetInterface<ICounterSteeringService>();
|
||||
if (!m_pCounterSteeringSvc)
|
||||
{
|
||||
std::cerr << "Console ERROR: Could not get complex service interface 'ICounterSteeringService'" << std::endl;
|
||||
return false;
|
||||
PrintText(g_sCSActive, "Attention: Complex service 'CounterSteeringService' is not available.");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -103,7 +103,7 @@ void CExampleControl::StartTestRun()
|
||||
|
||||
// Start the simulated datalink
|
||||
m_bRunning = true;
|
||||
m_threadSimulateDatalink = std::thread(&CExampleControl::SimulateDatalinkThreadFunc, this);
|
||||
m_threadSimulateDatalink = sdv::core::secure_thread(&CExampleControl::SimulateDatalinkThreadFunc, this);
|
||||
}
|
||||
|
||||
void CExampleControl::StopTestRun()
|
||||
|
||||
@@ -163,20 +163,20 @@ private:
|
||||
verbose, ///< Extensive reporting by application control
|
||||
};
|
||||
|
||||
bool m_bInitialized = false; ///< Set when initialized.
|
||||
bool m_bCmdLnError = false; ///< Command line error occurred.
|
||||
bool m_bCmdLnHelp = false; ///< Command line help provided.
|
||||
std::atomic_bool m_bRunning = false; ///< When set, the application is running.
|
||||
ERunAs m_eRunAs = ERunAs::standalone; ///< Application operation.
|
||||
EAppControlReporting m_eReporting = EAppControlReporting::silent; ///< Application control reporting.
|
||||
uint32_t m_uiInstance = 1000u; ///< Server instance to connect to.
|
||||
std::filesystem::path m_pathFramework; ///< Path to the SDV V-API framework.
|
||||
sdv::app::CAppControl m_appcontrol; ///< App-control of SDV V-API.
|
||||
std::thread m_threadSimulateDatalink; ///< Simulation datalink thread.
|
||||
sdv::core::CSignal m_signalSteeringWheel; ///< Steering wheel angle signal (input) - simulated datalink
|
||||
sdv::core::CSignal m_signalSpeed; ///< Speed signal (input) - simulated datalink
|
||||
sdv::core::CSignal m_signalRearAngle; ///< Rear angle signal (output) - simulated datalink
|
||||
sdv::core::CSignal m_signalCounter; ///< Simple counter signal (output) - simulated datalink
|
||||
bool m_bInitialized = false; ///< Set when initialized.
|
||||
bool m_bCmdLnError = false; ///< Command line error occurred.
|
||||
bool m_bCmdLnHelp = false; ///< Command line help provided.
|
||||
std::atomic_bool m_bRunning = false; ///< When set, the application is running.
|
||||
ERunAs m_eRunAs = ERunAs::standalone; ///< Application operation.
|
||||
EAppControlReporting m_eReporting = EAppControlReporting::silent; ///< Application control reporting.
|
||||
uint32_t m_uiInstance = 1000u; ///< Server instance to connect to.
|
||||
std::filesystem::path m_pathFramework; ///< Path to the SDV V-API framework.
|
||||
sdv::app::CAppControl m_appcontrol; ///< App-control of SDV V-API.
|
||||
sdv::core::secure_thread m_threadSimulateDatalink; ///< Simulation datalink thread.
|
||||
sdv::core::CSignal m_signalSteeringWheel; ///< Steering wheel angle signal (input) - simulated datalink
|
||||
sdv::core::CSignal m_signalSpeed; ///< Speed signal (input) - simulated datalink
|
||||
sdv::core::CSignal m_signalRearAngle; ///< Rear angle signal (output) - simulated datalink
|
||||
sdv::core::CSignal m_signalCounter; ///< Simple counter signal (output) - simulated datalink
|
||||
};
|
||||
|
||||
template <typename TCharType>
|
||||
|
||||
@@ -103,7 +103,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
|
||||
std::ofstream tomlFile("sdv_core_reloc.toml");
|
||||
if (tomlFile.is_open())
|
||||
{
|
||||
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
|
||||
tomlFile << R"toml(# Location of the SDV binaries and configuration files
|
||||
[CoreLocation]
|
||||
Version = 100
|
||||
Framework = ")toml";
|
||||
tomlFile << resources;
|
||||
tomlFile << "\"\n";
|
||||
tomlFile.close();
|
||||
|
||||
@@ -103,12 +103,6 @@ module sdv
|
||||
* @return The instance ID.
|
||||
*/
|
||||
uint32 GetInstanceID() const;
|
||||
|
||||
/**
|
||||
* @brief Return the number of retries to establish a connection.
|
||||
* @return Number of retries.
|
||||
*/
|
||||
uint32 GetRetries() const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -181,5 +175,96 @@ module sdv
|
||||
void RequestShutdown() raises(XAccessDenied, XInvalidState);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Load and save the application settings.
|
||||
* @remarks The interface is only available in maintenance mode.
|
||||
*/
|
||||
interface IAppSettingsPersist
|
||||
{
|
||||
/**
|
||||
* @brief Load the application settings.
|
||||
* @remarks When there is no settings file, this is not an error. Default settings will be assumed.
|
||||
* @return Returns whether the loading was successful.
|
||||
*/
|
||||
boolean LoadSettings();
|
||||
|
||||
/**
|
||||
* @brief Save the application settings file (or create when not existing yet).
|
||||
* @return Returns whether the saving was successful.
|
||||
*/
|
||||
boolean SaveSettings();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Application connections
|
||||
* @remarks The interface is only available in maintenance mode.
|
||||
*/
|
||||
interface IAppConnections
|
||||
{
|
||||
/**
|
||||
* @brief Get a sequence with listener names.
|
||||
* @return Sequence with listener name strings.
|
||||
*/
|
||||
sequence<u8string> GetListeners() const;
|
||||
|
||||
/**
|
||||
* @brief Get the listener configuration.
|
||||
* @param[in] ssName Name of the listener.
|
||||
* @return String containing the listener configuration.
|
||||
*/
|
||||
u8string GetListenerConfig(in u8string ssName) const;
|
||||
|
||||
/**
|
||||
* @brief Add or update a listener configuration.
|
||||
* @param[in] ssName Name of the listener configuration.
|
||||
* @param[in] ssConfig The configuration string for the listener.
|
||||
* @return Returns whether the listener could be added.
|
||||
*/
|
||||
boolean AddListenerConfig(in u8string ssName, in u8string ssConfig);
|
||||
|
||||
/**
|
||||
* @brief Remove a listener configuration with the provided name.
|
||||
* @param[in] ssName Name of the listener configuration.
|
||||
* @return Returns whether the removal was successful.
|
||||
*/
|
||||
boolean RemoveListenerConfig(in u8string ssName);
|
||||
|
||||
/**
|
||||
* @brief Get a sequence with connection names.
|
||||
* @return Sequence with name strings.
|
||||
*/
|
||||
sequence<u8string> GetConnections() const;
|
||||
|
||||
/**
|
||||
* @brief Get the connection configuration.
|
||||
* @param[in] ssName Name of the connection.
|
||||
* @return String containing the connection configuration.
|
||||
*/
|
||||
u8string GetConnectionConfig(in u8string ssName) const;
|
||||
|
||||
/**
|
||||
* @brief Add or update a connection configuration.
|
||||
* @param[in] ssName Name of the connection configuration.
|
||||
* @param[in] ssConfig The configuration string for the connection.
|
||||
* @param[in] ssInsertBefore Reference to the string to connection to insert the the new connection before, or empty
|
||||
* when the the new connection should be placed at the end.
|
||||
* @return Returns whether the connection could be added (fails when the connection already exists).
|
||||
*/
|
||||
boolean AddConnectionConfig(in u8string ssName, in u8string ssConfig, in u8string ssInsertBefore);
|
||||
|
||||
/**
|
||||
* @brief Remove a connection configuration with the provided name.
|
||||
* @param[in] ssName Name of the connection configuration.
|
||||
* @return Returns whether the removal was successful.
|
||||
*/
|
||||
boolean RemoveConnectionConfig(in u8string ssName);
|
||||
|
||||
/**
|
||||
* @brief Return the number of retries to establish a connection.
|
||||
* @return Number of retries.
|
||||
*/
|
||||
uint32 GetConnectRetries() const;
|
||||
};
|
||||
|
||||
}; // module app
|
||||
}; // module sdv
|
||||
|
||||
@@ -53,31 +53,56 @@ module sdv
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Connect to a remote system. Provided by the ConnectClient utility.
|
||||
* @brief Connect to a remote system. Provided by the Connection service.
|
||||
* @details This interface is exposed by the connection client service. The configuration is provided during instantiation
|
||||
* of the object and is of the form:
|
||||
* @code
|
||||
* # Provider to use for the connection
|
||||
* [Provider]
|
||||
* Name = ""
|
||||
*
|
||||
* # Additional channel information for the client
|
||||
* [IpcChannel]
|
||||
* xyz = ""
|
||||
* @endcode
|
||||
*
|
||||
* For example for shared memory:
|
||||
* @code
|
||||
* [Provider]
|
||||
* Name = "DefaultSharedMemory"
|
||||
* [IpcChannel]
|
||||
* Name = "LISTENER_1234"
|
||||
* @endcode
|
||||
*/
|
||||
interface IClientConnect
|
||||
{
|
||||
/**
|
||||
* @brief Connect to a remote system using the connection string to contact the system.
|
||||
* @remarks After a successful connection, the ConnectClient utility is not needed any more.
|
||||
* @param[in] ssConnectString Optional connection string to use for connection. If not provided, the connection will
|
||||
* automatically get the connection ID from the app-control service (default). The connection string for a local
|
||||
* connection can be of the form:
|
||||
* @code
|
||||
* [Client]
|
||||
* Type = "local"
|
||||
* Instance = 1234 # Optional: only use when connecting to a system with a different instance ID.
|
||||
* @endcode
|
||||
* And the following can be used for a remote connection:
|
||||
* @code
|
||||
* [Client]
|
||||
* Type = "remote"
|
||||
* Interface = "127.0.0.1"
|
||||
* Port = 2000
|
||||
* @endcode
|
||||
* @return Returns an interface to the repository of the remote system or a NULL pointer if not found.
|
||||
* @brief Connect to a remote system.
|
||||
* @return Returns whether connect was successful.
|
||||
*/
|
||||
IInterfaceAccess Connect(in u8string ssConnectString) raises(XAccessDenied, XNotFound, XInvalidState, XTimeout);
|
||||
boolean Connect() raises(XAccessDenied, XNotFound, XInvalidState, XTimeout);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from a connected system.
|
||||
* @return Returns whether disconnect was successful.
|
||||
*/
|
||||
boolean Disconnect() raises(XAccessDenied, XNotFound, XInvalidState, XTimeout);
|
||||
|
||||
/**
|
||||
* @brief State of the current connection.
|
||||
* @return Returns whether an active connection exists.
|
||||
*/
|
||||
boolean IsConnected() const;
|
||||
|
||||
/**
|
||||
* @brief Get the remote repository that is available after connection.
|
||||
* @remarks For main, isolated and external applications, the remote repository will be automatically linked to the
|
||||
* local repository. Hence a requests for the repository is not needed. For all other applications, access must be
|
||||
* explicitly acquired through this interface.
|
||||
* @return Interface to the remote repository if a successful connection is established. The interface is valid until
|
||||
* disconnect is called or the client connection service is terminated.
|
||||
*/
|
||||
IInterfaceAccess GetRemoteRepository();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -389,6 +389,17 @@ module sdv
|
||||
u8string ssInstallName; ///< Name of the installation.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The package exceeds the maximum size.
|
||||
*/
|
||||
exception XPackageSizeExceeded : XSysExcept
|
||||
{
|
||||
/** Description */
|
||||
const char _description[] = "Maximum package size exceeded.";
|
||||
|
||||
u8string ssFileName; ///< Name of the file which causes the exception.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The installation doesn't contain a module.
|
||||
*/
|
||||
|
||||
@@ -57,11 +57,28 @@ module sdv
|
||||
template <typename TInterface>
|
||||
TInterface* GetInterface()
|
||||
{
|
||||
return GetInterface(sdv::GetInterfaceId<TInterface>()).template get<TInterface>();
|
||||
try
|
||||
{
|
||||
return GetInterface(sdv::GetInterfaceId<TInterface>()).template get<TInterface>();
|
||||
} catch (const XSysExcept&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#verbatim_end
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/**
|
||||
* @brief Object ID.
|
||||
*/
|
||||
typedef uint64 TObjectID;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object type enumeration.
|
||||
*/
|
||||
@@ -163,13 +180,24 @@ module sdv
|
||||
|
||||
/**
|
||||
* @brief Component operation mode.
|
||||
*/
|
||||
*/
|
||||
enum EOperationMode : uint32
|
||||
{
|
||||
configuring = 20, ///< The component should switch to configuration mode.
|
||||
running = 30, ///< The component should switch to running mode.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Object information supplied to the object initialization function.
|
||||
*/
|
||||
struct SObjectInfo
|
||||
{
|
||||
core::TObjectID tObjectID; ///< Object ID (local for the running process)
|
||||
SClassInfo sClassInfo; ///< Object class information
|
||||
u8string ssName; ///< Object name
|
||||
u8string ssConfig; ///< Object configuration TOML
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional interface allowing for additional control of more complex SDVObjects.
|
||||
* To be implemented if the object in question calls other SDVobjects via running threads or callbacks,
|
||||
@@ -179,9 +207,9 @@ module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Initialize the object.
|
||||
* @param[in] ssObjectConfig Optional configuration string.
|
||||
* @param[in] sObjectInfo The registration information of this object.
|
||||
*/
|
||||
void Initialize(in u8string ssObjectConfig);
|
||||
void Initialize(in SObjectInfo sObjectInfo);
|
||||
|
||||
/**
|
||||
* @brief Get the current state of the object.
|
||||
@@ -247,50 +275,6 @@ module sdv
|
||||
*/
|
||||
uint32 GetCount() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attribute flags.
|
||||
*/
|
||||
enum EAttributeFlags : uint32
|
||||
{
|
||||
read_only = 0x100, ///< When set, the attribute is readonly.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attribute interface
|
||||
*/
|
||||
interface IAttributes
|
||||
{
|
||||
/**
|
||||
* @brief Get a sequence with the available attribute names.
|
||||
* @return The sequence of attribute names.
|
||||
*/
|
||||
sequence<u8string> GetNames() const;
|
||||
|
||||
/**
|
||||
* @brief Get the attribute value.
|
||||
* @param[in] ssAttribute Name of the attribute.
|
||||
* @return The attribute value or an empty any-value if the attribute wasn't found or didn't have a value.
|
||||
*/
|
||||
any Get(in u8string ssAttribute) const;
|
||||
|
||||
/**
|
||||
* @brief Set the attribute value.
|
||||
* @param[in] ssAttribute Name of the attribute.
|
||||
* @param[in] anyAttribute Attribute value to set.
|
||||
* @return Returns 'true' when setting the attribute was successful or 'false' when the attribute was not found or the
|
||||
* attribute is read-only or another error occurred.
|
||||
*/
|
||||
boolean Set(in u8string ssAttribute, in any anyAttribute);
|
||||
|
||||
/**
|
||||
* @brief Get the attribute flags belonging to a certain attribute.
|
||||
* @param[in] ssAttribute Name of the attribute.
|
||||
* @return Returns the attribute flags (zero or more EAttributeFlags flags) or 0 when the attribute could not be found.
|
||||
*/
|
||||
uint32 GetFlags(in u8string ssAttribute) const;
|
||||
};
|
||||
|
||||
}; // module sdv
|
||||
|
||||
#verbatim_begin
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "core.idl"
|
||||
#include "process.idl"
|
||||
#include "permission.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
@@ -149,6 +150,7 @@ module sdv
|
||||
TMarshallID tProxyID; ///< Proxy id to identify the proxy this packet is sending from or destined to.
|
||||
TMarshallID tStubID; ///< Stub id to identify the stub this packet is destined to or receiving from.
|
||||
uint64 uiCallIndex; ///< Call index to uniquely identify the call.
|
||||
core::TPermissionID tPermissionID; ///< Permission ID used to elevate permission, or 0 for standard permission.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,12 +35,15 @@ module sdv
|
||||
///< identification must be similar to the following example:
|
||||
///< @code
|
||||
///< [Provider]
|
||||
///< Name = "DefaultSharedMemoryChannelControl"
|
||||
///< Name = "DefaultSharedMemory"
|
||||
///< @endcode
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for creating an IPC connection, which other participants can connect to via IChannelAccess
|
||||
* @brief Interface for creating an IPC connection, which other participants can connect to via IChannelAccess.
|
||||
* @attention The channel control object should allow the creation of channels with a fixed configuration (e.g. a provided
|
||||
* name or a port), which is necessary for the creation of a listener. It also should allow dynamic channel creation (e.g.
|
||||
* automatic name or port-number) to create additional connections between components.
|
||||
*/
|
||||
interface ICreateEndpoint
|
||||
{
|
||||
|
||||
96
export/interfaces/permission.idl
Normal file
96
export/interfaces/permission.idl
Normal file
@@ -0,0 +1,96 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#include "core.idl"
|
||||
|
||||
/**
|
||||
* @brief Software Defined Vehicle framework.
|
||||
*/
|
||||
module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Core features.
|
||||
*/
|
||||
module core
|
||||
{
|
||||
/// ID corresponding to a thread specific permission request.
|
||||
typedef uint64 TPermissionID;
|
||||
|
||||
/// ID identifying a permission transfer.
|
||||
typedef uint64 TPermissionTransferID;
|
||||
|
||||
/**
|
||||
* @brief Access type restriction. The lower the access, the more restricted.
|
||||
*/
|
||||
enum EAccessPermission : int32
|
||||
{
|
||||
not_set = -1001, ///< Permissions are not set; will be treated as restricted access.
|
||||
restricted_access = -1000, ///< Restricted access (default when no other set).
|
||||
remote_access = -200, ///< Access for remote execution. Access allowed to basic and complex services.
|
||||
local_access = -100, ///< Access for isolated execution. Access allowed to system, basic and complex services.
|
||||
full_access = 0, ///< Full access is allowed to complete system.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Permission control interface. This interface is used for restricting permission on a thread and transferring
|
||||
* permissions from one thread to another.
|
||||
*/
|
||||
interface IPermissionControl
|
||||
{
|
||||
/**
|
||||
* @brief Restrict the access permission for the current thread.
|
||||
* @remarks The access restriction will be assigned to the current thread and combined with previous and future
|
||||
* permissions. The lowest assigned permission will determine the actual access permission for the current thread.
|
||||
* @remarks The access restriction will stay in effect until it is released by the function ReleaseAccessPermission.
|
||||
* @remarks A newly created thread has fully restricted access. This cannot be changed using this function. Use an
|
||||
* access restriction transfer from one thread to this thread to set a higher level of access permission.
|
||||
* @param[in] ePermission The permission to restrict to.
|
||||
* @return The permission ID for this restriction or 0 when the access permission could not be set. Use the
|
||||
* ReleaseAccessPermission to release the restriction again.
|
||||
*/
|
||||
TPermissionID RestrictAccessPermission(in EAccessPermission ePermission);
|
||||
|
||||
/**
|
||||
* @brief Release a previously set access restriction for the current thread.
|
||||
* @param[in] tPermissionID The ID of the access restriction previously set for the current thread.
|
||||
* @return Returns whether the restriction could be released successfully.
|
||||
*/
|
||||
boolean ReleaseAccessPermission(in TPermissionID tPermissionID);
|
||||
|
||||
/**
|
||||
* @brief Prepares a transfer of the access restriction from the current thread.
|
||||
* @return The ID of the transfer object containing the current access permissions or 0 when the transfer preparation
|
||||
* has failed.
|
||||
*/
|
||||
TPermissionTransferID TransferCurrentPermission();
|
||||
|
||||
/**
|
||||
* @brief Set the access permission using a transfer object from one thread to another.
|
||||
* @remarks An new thread has fully restricted access per default. Use this function to set the required access level.
|
||||
* If a thread has already initialized with the proper access level, this function will set identical or lower access
|
||||
* permissions for the current thread.
|
||||
* @param[in] tTransferID The IS of the prepared access permission transfer.
|
||||
* @return The permission ID for this restriction or 0 when the access permission could not be transferred. Use the
|
||||
* ReleaseAccessPermission to release the restriction again.
|
||||
*/
|
||||
TPermissionID SetAccessPermission(in TPermissionTransferID tTransferID);
|
||||
|
||||
/**
|
||||
* @brief Get the access permission level for the current thread. This will be the lowest restriction set for the
|
||||
* current thread.
|
||||
* @return The current access permission level.
|
||||
*/
|
||||
EAccessPermission GetCurrentPermission() const;
|
||||
};
|
||||
}; // module core
|
||||
}; // module sdv
|
||||
@@ -25,11 +25,6 @@ module sdv
|
||||
module core
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Object ID.
|
||||
*/
|
||||
typedef uint64 TObjectID;
|
||||
|
||||
/**
|
||||
* @brief Interface used to access objects from other modules via the repository service
|
||||
*/
|
||||
@@ -229,6 +224,32 @@ module sdv
|
||||
TObjectID RegisterObject(in IInterfaceAccess pObjectIfc, in u8string ssObjectName);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The object dependency can be used to state dependencies between two objects. This influence is used during
|
||||
* shutdown to determine the termination order.
|
||||
*/
|
||||
interface IObjectDependency
|
||||
{
|
||||
/**
|
||||
* @brief Add a dependency for an object.
|
||||
* @param ssObjectName Name of the object.
|
||||
* @param ssDependsOnObject Name of the object it depends on.
|
||||
*/
|
||||
void AddObjectDependency(in u8string ssObjectName, in u8string ssDependsOnObject);
|
||||
|
||||
/**
|
||||
* @brief Remove an object dependency.
|
||||
* @param ssObjectName Name of the object.
|
||||
* @param ssDependsOnObject Name of the object it depends on.
|
||||
*/
|
||||
void RemoveObjectDependency(in u8string ssObjectName, in u8string ssDependsOnObject);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Link ID.
|
||||
*/
|
||||
typedef uint64 TLinkID;
|
||||
|
||||
/**
|
||||
* @brief Connect the core repository to the local repository to allow object access by the locally running components.
|
||||
* @remarks This interface is available only for isolated and external applications.
|
||||
@@ -238,13 +259,15 @@ module sdv
|
||||
/**
|
||||
* @brief Register the core repository.
|
||||
* @param[in] pCoreRepository Pointer to the proxy interface of the core repository.
|
||||
* @return Returns a link ID to be used in the Unlink function. Or 0 on failure.
|
||||
*/
|
||||
void LinkCoreRepository(in IInterfaceAccess pCoreRepository);
|
||||
TLinkID LinkCoreRepository(in IInterfaceAccess pCoreRepository);
|
||||
|
||||
/**
|
||||
* @brief Unlink a previously linked core repository.
|
||||
* @param[in] tLinkID Link ID of the repository link to remove.
|
||||
*/
|
||||
void UnlinkCoreRepository();
|
||||
void UnlinkCoreRepository(in TLinkID tLinkID);
|
||||
};
|
||||
|
||||
}; // module core
|
||||
|
||||
@@ -142,10 +142,10 @@ module sdv
|
||||
u8string GetComment(in ECommentType eType);
|
||||
|
||||
/**
|
||||
* @brief Format the node automatically. This will remove the whitespace between the elements within the node. Comments
|
||||
* will not be changed.
|
||||
* @brief Format the node automatically, remove redundant whitespace.
|
||||
* @param[in] bRemoveComments When set, the comments are removed from the node.
|
||||
*/
|
||||
void AutomaticFormat();
|
||||
void AutomaticFormat(in boolean bRemoveComments);
|
||||
|
||||
/**
|
||||
* @brief Is the node inline?
|
||||
@@ -265,10 +265,21 @@ module sdv
|
||||
|
||||
/**
|
||||
* @brief Convert the node to a standard node.
|
||||
* @param[in] bIncludeChildren When set, applicable child nodes are made are converted to standard nodes as well (only
|
||||
* tables and table-arrays can be defined as standard).
|
||||
* @return Returns whether the conversion was successful. Returns 'true' when the node was already defined as standard
|
||||
* node.
|
||||
*/
|
||||
boolean MakeStandard();
|
||||
boolean MakeStandard(in boolean bIncludeChildren);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Insertion preference for tables and table arrays, being standard or inline.
|
||||
*/
|
||||
enum EInsertPreference
|
||||
{
|
||||
prefer_standard = 0, ///< When the parent node is not inline, the node will be inserted as standard node.
|
||||
prefer_inline = 1, ///< The node will be inserted as inline node.
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -278,71 +289,67 @@ module sdv
|
||||
{
|
||||
/**
|
||||
* @brief Insert a value into the collection at the location before the supplied index.
|
||||
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
|
||||
* collection count to insert the node at the end of the collection. Value nodes cannot be inserted behind external
|
||||
* tables and table arrays. If the index is referencing a position behind an external table or a table array, the index
|
||||
* is automatically corrected.
|
||||
* @param[in] ssName Name of the node to insert. Will be ignored for an array collection. The name must adhere to the
|
||||
* key names defined by the TOML specification. Defining the key multiple times is not allowed. Quotation of key names
|
||||
* is done automatically; the parser decides itself whether the key is bare-key, a literal key or a quoted key.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Since values are presented as inline node, they
|
||||
* will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
|
||||
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
|
||||
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
|
||||
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
|
||||
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
|
||||
* @param[in] anyValue The value of the node, being either an integer, floating point number, boolean value or a string.
|
||||
* Conversion is automatically done to int64, double float, bool or u8string.
|
||||
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
|
||||
*/
|
||||
IInterfaceAccess InsertValue(in uint32 uiIndex, in u8string ssName, in any anyValue);
|
||||
IInterfaceAccess InsertValue(in u8string ssInsertBefore, in u8string ssName, in any anyValue);
|
||||
|
||||
/**
|
||||
* @brief Insert an array into the collection at the location before the supplied index.
|
||||
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
|
||||
* collection count to insert the node at the end of the collection. Array nodes cannot be inserted behind external
|
||||
* tables and table arrays. If the index is referencing a position behind an external table or a table array, the index
|
||||
* is automatically corrected.
|
||||
* @param[in] ssName Name of the array node to insert. Will be ignored if the current node is also an array collection.
|
||||
* The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
|
||||
* allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
|
||||
* literal key or a quoted key.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Since arrays are presented as inline node, they
|
||||
* will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
|
||||
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
|
||||
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
|
||||
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
|
||||
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
|
||||
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
|
||||
*/
|
||||
IInterfaceAccess InsertArray(in uint32 uiIndex, in u8string ssName);
|
||||
|
||||
/**
|
||||
* @brief Insertion preference for tables and table arrays, being standard or inline.
|
||||
*/
|
||||
enum EInsertPreference
|
||||
{
|
||||
prefer_standard = 0, ///< When the parent node is not inline, the node will be inserted as standard node.
|
||||
prefer_inline = 1, ///< The node will be inserted as inline node.
|
||||
};
|
||||
IInterfaceAccess InsertArray(in u8string ssInsertBefore, in u8string ssName);
|
||||
|
||||
/**
|
||||
* @brief Insert a table into the collection at the location before the supplied index.
|
||||
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
|
||||
* collection count to insert the node at the end of the collection. Table nodes cannot be inserted before value nodes
|
||||
* or arrays. If the index is referencing a position before a value node or an array, the index is automatically
|
||||
* corrected.
|
||||
* @param[in] ssName Name of the table node to insert. Will be ignored if the parent node is an array collection.
|
||||
* The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
|
||||
* allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
|
||||
* literal key or a quoted key.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Tables can be inserted as inline node, in which
|
||||
* case they will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
|
||||
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
|
||||
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
|
||||
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
|
||||
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
|
||||
* @param[in] ePreference The preferred form of the node to be inserted.
|
||||
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
|
||||
*/
|
||||
IInterfaceAccess InsertTable(in uint32 uiIndex, in u8string ssName, in EInsertPreference ePreference);
|
||||
IInterfaceAccess InsertTable(in u8string ssInsertBefore, in u8string ssName, in EInsertPreference ePreference);
|
||||
|
||||
/**
|
||||
* @brief Insert a table array into the collection at the location before the supplied index.
|
||||
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
|
||||
* collection count to insert the node at the end of the collection. Table array nodes cannot be inserted before value
|
||||
* nodes or arrays. If the index is referencing a position before a value node or an array, the index is automatically
|
||||
* corrected.
|
||||
* @param[in] ssName Name of the array node to insert. Will be ignored if the parent node is also an array collection.
|
||||
* The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
|
||||
* allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
|
||||
* literal key or a quoted key.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Table arrays can be inserted as inline node, in
|
||||
* which case they will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
|
||||
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
|
||||
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
|
||||
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
|
||||
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
|
||||
* @param[in] ePreference The preferred form of the node to be inserted.
|
||||
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
|
||||
*/
|
||||
IInterfaceAccess InsertTableArray(in uint32 uiIndex, in u8string ssName, in EInsertPreference ePreference);
|
||||
IInterfaceAccess InsertTableArray(in u8string ssInsertBefore, in u8string ssName, in EInsertPreference ePreference);
|
||||
|
||||
/**
|
||||
* @brief The result of the TOML string to insert.
|
||||
@@ -358,17 +365,15 @@ module sdv
|
||||
* @brief Insert a TOML string as a child of the current collection node. If the collection is a table, the TOML string
|
||||
* should contain values and inline/external/array-table nodes with names. If the collection is an array, the TOML
|
||||
* string should contain and inline table nodes without names.
|
||||
* @attention Even though the TOML might be defining the node(s) in standard form, if the parent node is an inline node,
|
||||
* the node will be inserted as inline node.
|
||||
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
|
||||
* collection count to insert the node at the end of the collection. Table array nodes cannot be inserted before value
|
||||
* nodes or arrays. If the index is referencing a position before a value node or an array, the index is automatically
|
||||
* corrected.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Dependable on the nodes defined in the TOML they
|
||||
* might be transferred to inline or they might be inserted at a different location.
|
||||
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] ssTOML The TOML string to insert. This string can hold one or more nodes that should be inserted.
|
||||
* @param[in] bRollbackOnFailure If only part of the nodes could be inserted, no node will be inserted.
|
||||
* @return The result of the insertion.
|
||||
*/
|
||||
EInsertResult InsertTOML(in uint32 uiIndex, in u8string ssTOML, in boolean bRollbackOnFailure);
|
||||
EInsertResult InsertTOML(in u8string ssInsertBefore, in u8string ssTOML, in boolean bRollbackOnFailure);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26495)
|
||||
#else
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
namespace sdv
|
||||
@@ -1738,6 +1741,8 @@ namespace sdv
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // !defined SDV_ANY_INL
|
||||
@@ -65,6 +65,7 @@ namespace sdv
|
||||
bool Startup(const std::string& rssConfig)
|
||||
{
|
||||
IAppControl* pAppControl = core::GetCore() ? core::GetCore<IAppControl>() : nullptr;
|
||||
|
||||
if (!pAppControl) return false;
|
||||
if (m_eState != EAppOperationState::not_started) return false;
|
||||
try
|
||||
@@ -78,45 +79,6 @@ namespace sdv
|
||||
{
|
||||
m_eContext = pAppContext->GetContextType();
|
||||
m_uiInstanceID = pAppContext->GetInstanceID();
|
||||
m_uiRetries = pAppContext->GetRetries();
|
||||
}
|
||||
|
||||
// Automatically connect to the server
|
||||
if (m_eContext == EAppContext::external)
|
||||
{
|
||||
// Try to connect
|
||||
m_ptrServerRepository = sdv::com::ConnectToLocalServerRepository(m_uiInstanceID, m_uiRetries);
|
||||
if (!m_ptrServerRepository)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Failed to connect to the server repository." << std::endl;
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get access to the module control service
|
||||
sdv::core::IObjectAccess* pObjectAccess = m_ptrServerRepository.GetInterface<sdv::core::IObjectAccess>();
|
||||
const sdv::core::IRepositoryControl* pRepoControl = nullptr;
|
||||
if (pObjectAccess)
|
||||
pRepoControl = sdv::TInterfaceAccessPtr(pObjectAccess->GetObject("RepositoryService")).
|
||||
GetInterface<sdv::core::IRepositoryControl>();
|
||||
if (!pRepoControl)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Failed to access the server repository." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Link the local repository to the server repository.
|
||||
sdv::core::ILinkCoreRepository* pLinkCoreRepo =
|
||||
sdv::core::GetObject<sdv::core::ILinkCoreRepository>("RepositoryService");
|
||||
if (!pLinkCoreRepo)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Cannot link local and server repositories." << std::endl;
|
||||
return false;
|
||||
}
|
||||
pLinkCoreRepo->LinkCoreRepository(m_ptrServerRepository);
|
||||
}
|
||||
|
||||
return bRet;
|
||||
@@ -154,23 +116,6 @@ namespace sdv
|
||||
*/
|
||||
void Shutdown()
|
||||
{
|
||||
// Disconnect local and remote repositories.
|
||||
if (m_ptrServerRepository)
|
||||
{
|
||||
// Link the local repository to the server repository.
|
||||
sdv::core::ILinkCoreRepository* pLinkCoreRepo =
|
||||
sdv::core::GetObject<sdv::core::ILinkCoreRepository>("RepositoryService");
|
||||
if (!pLinkCoreRepo)
|
||||
{
|
||||
if (!ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Cannot unlink local and server repositories." << std::endl;
|
||||
} else
|
||||
pLinkCoreRepo->UnlinkCoreRepository();
|
||||
}
|
||||
|
||||
// Disconnect from the server (if connected at all).
|
||||
m_ptrServerRepository.Clear();
|
||||
|
||||
// Shutdown.
|
||||
IAppControl* pAppControl = core::GetCore() ? core::GetCore<IAppControl>() : nullptr;
|
||||
try
|
||||
@@ -194,28 +139,86 @@ namespace sdv
|
||||
return m_eState == EAppOperationState::running;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the absolute path to the currently run executable
|
||||
* @return Absolute std::filesystem::path to the currently run executable
|
||||
*/
|
||||
static std::filesystem::path GetAppDirectory()
|
||||
{
|
||||
static std::filesystem::path pathExeDir;
|
||||
if (!pathExeDir.empty())
|
||||
return pathExeDir;
|
||||
#ifdef _WIN32
|
||||
// Windows specific
|
||||
std::wstring ssPath(32768, '\0');
|
||||
GetModuleFileNameW(NULL, ssPath.data(), static_cast<DWORD>(ssPath.size() - 1));
|
||||
#elif defined __linux__
|
||||
// Linux specific
|
||||
std::string ssPath(PATH_MAX + 1, '\0');
|
||||
const ssize_t nCount = readlink("/proc/self/exe", ssPath.data(), PATH_MAX);
|
||||
if (nCount < 0 || nCount >= PATH_MAX)
|
||||
return pathExeDir; // some error
|
||||
ssPath.at(nCount) = '\0';
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
pathExeDir = std::filesystem::path{ssPath.c_str()}.parent_path() / ""; // To finish the folder path with (back)slash
|
||||
return pathExeDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the filename of the currently run executable
|
||||
* @return The filename to the currently run executable
|
||||
*/
|
||||
static std::filesystem::path GetAppFilename()
|
||||
{
|
||||
static std::filesystem::path pathExeFilename;
|
||||
if (!pathExeFilename.empty())
|
||||
return pathExeFilename;
|
||||
#ifdef _WIN32
|
||||
// Windows specific
|
||||
std::wstring ssPath(32768, '\0');
|
||||
GetModuleFileNameW(NULL, ssPath.data(), static_cast<DWORD>(ssPath.size() - 1));
|
||||
#elif defined __linux__
|
||||
// Linux specific
|
||||
std::string ssPath(PATH_MAX + 1, '\0');
|
||||
const ssize_t nCount = readlink("/proc/self/exe", ssPath.data(), PATH_MAX);
|
||||
if (nCount < 0 || nCount >= PATH_MAX)
|
||||
return pathExeFilename; // some error
|
||||
ssPath.at(nCount) = '\0';
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
pathExeFilename = std::filesystem::path{ssPath.c_str()}.filename();
|
||||
return pathExeFilename;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the SDV_FRAMEWORK_RUNTIME environment variable for this application.
|
||||
* @return Path directing to the SDV V-API Framework directory if available or an empty path if not.
|
||||
* @remarks If the environment variable is empty or if the variable contains a relative path, the path will be enhanced
|
||||
* with the application path.
|
||||
* @return Absolute path directing to the SDV Vehicle API Framework directory.
|
||||
*/
|
||||
static std::filesystem::path GetFrameworkRuntimeDirectory()
|
||||
{
|
||||
std::filesystem::path path;
|
||||
#ifdef _WIN32
|
||||
const wchar_t* szFrameworkDir = _wgetenv(L"SDV_FRAMEWORK_RUNTIME");
|
||||
if (!szFrameworkDir) return {};
|
||||
return szFrameworkDir;
|
||||
if (szFrameworkDir) path = szFrameworkDir;
|
||||
#elif defined __unix__
|
||||
const char* szFrameworkDir = getenv("SDV_FRAMEWORK_RUNTIME");
|
||||
if (!szFrameworkDir) return {};
|
||||
return szFrameworkDir;
|
||||
if (szFrameworkDir) path = szFrameworkDir;
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
if (path.empty() || path.is_relative()) path = GetAppDirectory() / path;
|
||||
return path.lexically_normal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set or overwrite the SDV_FRAMEWORK_RUNTIME environment variable for this application.
|
||||
* @param[in] rpathDir Reference of the path directing to the SDV V-API Framework directory.
|
||||
* @param[in] rpathDir Reference of the path directing to the SDV Vehicle API Framework directory.
|
||||
*/
|
||||
static void SetFrameworkRuntimeDirectory(const std::filesystem::path& rpathDir)
|
||||
{
|
||||
@@ -232,26 +235,30 @@ namespace sdv
|
||||
|
||||
/**
|
||||
* @brief Get the SDV_COMPONENT_INSTALL environment variable for this application.
|
||||
* @return Path directing to the SDV V-API component installation directory if available or an empty path if not.
|
||||
* @remarks If the environment variable is empty, the runtime directory is taken. If the variable contains a relative
|
||||
* path, the path will be enhanced with the application path.
|
||||
* @return Absolute path directing to the SDV Vehicle API component installation directory.
|
||||
*/
|
||||
static std::filesystem::path GetComponentInstallDirectory()
|
||||
{
|
||||
std::filesystem::path path;
|
||||
#ifdef _WIN32
|
||||
const wchar_t* szComponentDir = _wgetenv(L"SDV_COMPONENT_INSTALL");
|
||||
if (!szComponentDir) return {};
|
||||
return szComponentDir;
|
||||
if (szComponentDir) path = szComponentDir;
|
||||
#elif defined __unix__
|
||||
const char* szComponentDir = getenv("SDV_COMPONENT_INSTALL");
|
||||
if (!szComponentDir) return {};
|
||||
return szComponentDir;
|
||||
if (szComponentDir) path = szComponentDir;
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
if (path.empty()) return GetFrameworkRuntimeDirectory();
|
||||
if (path.is_relative()) path = GetAppDirectory() / path;
|
||||
return path.lexically_normal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set or overwrite the SDV_COMPONENT_INSTALL environment variable for this application.
|
||||
* @param[in] rpathDir Reference of the path directing to the SDV V-API component installation directory.
|
||||
* @param[in] rpathDir Reference of the path directing to the SDV Vehicle API component installation directory.
|
||||
*/
|
||||
static void SetComponentInstallDirectory(const std::filesystem::path& rpathDir)
|
||||
{
|
||||
@@ -527,8 +534,7 @@ namespace sdv
|
||||
EAppOperationState m_eState = EAppOperationState::not_started; ///< Application state.
|
||||
EAppContext m_eContext = EAppContext::no_context; ///< Application context.
|
||||
uint32_t m_uiInstanceID = 0u; ///< Core instance.
|
||||
uint32_t m_uiRetries = 0u; ///< Number of retries to establish a connection.
|
||||
sdv::TObjectPtr m_ptrServerRepository; ///< Server repository interface.
|
||||
uint32_t m_uiConnectRetries = 0u; ///< Number of retries to establish a connection.
|
||||
};
|
||||
} // namespace app
|
||||
} // namespace sdv
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#include "../interfaces/core_types.h"
|
||||
#include "../interfaces/core.h"
|
||||
@@ -683,9 +685,9 @@ namespace sdv
|
||||
|
||||
/**
|
||||
* @brief Initialize the object. Overload of IObjectControl::Initialize.
|
||||
* @param[in] ssObjectConfig Optional configuration string.
|
||||
* @param[in] sObjectInfo The registration information of this object.
|
||||
*/
|
||||
virtual void Initialize(/*in*/ const u8string& ssObjectConfig) override
|
||||
virtual void Initialize(/*in*/ const SObjectInfo& sObjectInfo) override
|
||||
{
|
||||
// Not started before or ended completely?
|
||||
if (GetObjectState() != EObjectState::initialization_pending && GetObjectState() != EObjectState::destruction_pending)
|
||||
@@ -700,19 +702,19 @@ namespace sdv
|
||||
// Initialize the parameter map.
|
||||
InitParamMap();
|
||||
|
||||
// Copy the configuration
|
||||
m_ssObjectConfig = ssObjectConfig;
|
||||
// Copy the object information
|
||||
m_sSelf = sObjectInfo;
|
||||
|
||||
// Prepare initialization
|
||||
OnPreInitialize();
|
||||
|
||||
// Parse the object configuration if there is any.
|
||||
if (!ssObjectConfig.empty())
|
||||
if (!m_sSelf.ssConfig.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the config TOML.
|
||||
toml::CTOMLParser parser(ssObjectConfig);
|
||||
toml::CTOMLParser parser(m_sSelf.ssConfig);
|
||||
if (!parser.IsValid())
|
||||
{
|
||||
m_eObjectState = EObjectState::config_error;
|
||||
@@ -781,6 +783,15 @@ namespace sdv
|
||||
return m_eObjectState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get information about ourself.
|
||||
* @return The object information about ourself.
|
||||
*/
|
||||
const SObjectInfo& Self() const
|
||||
{
|
||||
return m_sSelf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the component operation mode. Overload of IObjectControl::SetOperationMode.
|
||||
* @param[in] eMode The operation mode, the component should run in.
|
||||
@@ -831,15 +842,11 @@ namespace sdv
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the object configuration for persistence.
|
||||
* @brief Build the object configuration from the parameter map and the stored initial configuration.
|
||||
* @return The object configuration as TOML string.
|
||||
*/
|
||||
virtual u8string GetObjectConfig() const override
|
||||
virtual u8string BuildObjectConfig() const
|
||||
{
|
||||
// During the initialization, return the stored object configuration.
|
||||
if (m_eObjectState == EObjectState::initializing || m_eObjectState == EObjectState::initialization_pending)
|
||||
return m_ssObjectConfig;
|
||||
|
||||
// Split path function (splits the group from the parameter names)
|
||||
auto fnSplitPath = [](const u8string& rssPath) -> std::pair<u8string, u8string>
|
||||
{
|
||||
@@ -849,13 +856,10 @@ namespace sdv
|
||||
return std::make_pair(rssPath.substr(0, nPos), rssPath.substr(nPos + 1));
|
||||
};
|
||||
|
||||
// Create a new configuration string from the parameters.
|
||||
auto seqParameters = GetParamPaths();
|
||||
if (seqParameters.empty()) return {};
|
||||
|
||||
// Iterate through the list of parameter names and create the TOML entries for it.
|
||||
auto seqParameters = GetParamPaths();
|
||||
u8string ssGroup;
|
||||
toml::CTOMLParser parser("");
|
||||
toml::CTOMLParser parser(m_sSelf.ssConfig);
|
||||
toml::CNodeCollection table(parser);
|
||||
for (auto ssParamPath : seqParameters)
|
||||
{
|
||||
@@ -863,7 +867,7 @@ namespace sdv
|
||||
auto ptrParam = FindParamObject(ssParamPath);
|
||||
|
||||
// Read only and temporary parameters are not stored
|
||||
if ((!ptrParam->Locked() && ptrParam->ReadOnly()) || !ptrParam->Temporary())
|
||||
if ((!ptrParam->Locked() && ptrParam->ReadOnly()) || ptrParam->Temporary())
|
||||
continue;
|
||||
|
||||
// Get the value
|
||||
@@ -877,7 +881,9 @@ namespace sdv
|
||||
// Need to add a group?
|
||||
if (prParam.first != ssGroup)
|
||||
{
|
||||
table = parser.AddTable(prParam.first);
|
||||
table = parser.GetDirect(prParam.first);
|
||||
if (!table)
|
||||
table = parser.AddTable(prParam.first);
|
||||
ssGroup = prParam.first;
|
||||
}
|
||||
|
||||
@@ -888,6 +894,20 @@ namespace sdv
|
||||
return parser.GetTOML();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the object configuration for persistence. Overload of IObjectControl::GetObjectConfig.
|
||||
* @return The object configuration as TOML string.
|
||||
*/
|
||||
virtual u8string GetObjectConfig() const override
|
||||
{
|
||||
// During the initialization, return the stored object configuration.
|
||||
if (m_eObjectState == EObjectState::initializing || m_eObjectState == EObjectState::initialization_pending)
|
||||
return m_sSelf.ssConfig;
|
||||
|
||||
|
||||
return BuildObjectConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shutdown called before the object is destroyed. Overload of IObjectControl::Shutdown.
|
||||
* @attention Implement calls to other SDV objects here as this is no longer considered safe during the destructor of the
|
||||
@@ -930,7 +950,7 @@ namespace sdv
|
||||
* @post Reset by switching to configuration mode.
|
||||
*/
|
||||
void SetObjectIntoRuntimeErrorState()
|
||||
{
|
||||
{
|
||||
if (m_eObjectState == EObjectState::running)
|
||||
m_eObjectState = EObjectState::runtime_error;
|
||||
}
|
||||
@@ -992,6 +1012,12 @@ namespace sdv
|
||||
*/
|
||||
virtual void OnShutdown() {}
|
||||
|
||||
/**
|
||||
* @brief Last function called before destruction. The object integrity is still in tact. It can be assumed that all
|
||||
* dependencies to the object have been released.
|
||||
*/
|
||||
virtual void OnDestroy() {}
|
||||
|
||||
/**
|
||||
* @brief Interface map
|
||||
*/
|
||||
@@ -1002,7 +1028,8 @@ namespace sdv
|
||||
|
||||
private:
|
||||
std::atomic<EObjectState> m_eObjectState = EObjectState::initialization_pending; ///< Object state
|
||||
std::string m_ssObjectConfig; ///< Copy of the configuration TOML.
|
||||
CLifetimeCookie m_lifetime = CreateLifetimeCookie(); ///< Manage module lifetime.
|
||||
SObjectInfo m_sSelf; ///< Information about ourself.
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1022,6 +1049,206 @@ namespace sdv
|
||||
END_SDV_INTERFACE_MAP()
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Lifetime control implementation class.
|
||||
*/
|
||||
class CLifetimeControlImpl : public virtual IInterfaceAccess, public IObjectLifetime, protected IObjectDestroy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CLifetimeControlImpl()
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Deleted copy constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
*/
|
||||
CLifetimeControlImpl(const CLifetimeControlImpl& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Deleted move constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
*/
|
||||
CLifetimeControlImpl(CLifetimeControlImpl&& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~CLifetimeControlImpl()
|
||||
{}
|
||||
|
||||
// Interface map (IObjectDestroy is not exposed)
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(IObjectLifetime)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Deleted copy assignment constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CLifetimeControlImpl& operator=(const CLifetimeControlImpl& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Deleted move assignment constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CLifetimeControlImpl& operator=(CLifetimeControlImpl&& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Increment the lifetime. Needs to be balanced by a call to Decrement. Overload of IObjectLifetime::Increment.
|
||||
*/
|
||||
virtual void Increment() override
|
||||
{
|
||||
m_uiLifetimeCnt++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decrement the lifetime. If the lifetime reaches zero, the object will be destroyed (through the exposed
|
||||
* IObjectDestroy interface). Overload of IObjectLifetime::Decrement.
|
||||
* @return Returns 'true' if the object was destroyed, false if not.
|
||||
*/
|
||||
virtual bool Decrement() override
|
||||
{
|
||||
if (m_uiLifetimeCnt && !(--m_uiLifetimeCnt))
|
||||
{
|
||||
DestroyObject();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current lifetime count. Overload of IObjectLifetime::GetCount.
|
||||
* @remarks The GetCount function returns a momentary value, which can be changed at any moment.
|
||||
* @return Returns the current counter value.
|
||||
*/
|
||||
virtual uint32_t GetCount() const override
|
||||
{
|
||||
return m_uiLifetimeCnt;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Destroy the object. Default implementation deletes 'this'. Overload of IObjectDestroy::DestroyObject.
|
||||
* @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
|
||||
*/
|
||||
virtual void DestroyObject() override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
CLifetimeCookie m_lifetime = CreateLifetimeCookie(); ///< Module lifetime
|
||||
std::atomic_uint32_t m_uiLifetimeCnt = 1; ///< Lifetime reference counter
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Lifetime control implementation class based on shared pointer.
|
||||
* @tparam TClass The type of class deriving CSharedLifetimeControlImpl class.
|
||||
*/
|
||||
template <class TClass>
|
||||
class CSharedLifetimeControlImpl : public std::enable_shared_from_this<TClass>, public CLifetimeControlImpl
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CSharedLifetimeControlImpl()
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Deleted copy constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
*/
|
||||
CSharedLifetimeControlImpl(const CSharedLifetimeControlImpl& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Deleted move constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
*/
|
||||
CSharedLifetimeControlImpl(CSharedLifetimeControlImpl&& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~CSharedLifetimeControlImpl()
|
||||
{
|
||||
}
|
||||
|
||||
// Interface map (IObjectDestroy is not exposed)
|
||||
BEGIN_SDV_INTERFACE_MAP()
|
||||
SDV_INTERFACE_ENTRY(IObjectLifetime)
|
||||
END_SDV_INTERFACE_MAP()
|
||||
|
||||
/**
|
||||
* @brief Deleted copy assignment constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CSharedLifetimeControlImpl& operator=(const CSharedLifetimeControlImpl& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Deleted move assignment constructor.
|
||||
* @param[in] rClass Reference to the class to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CSharedLifetimeControlImpl& operator=(CSharedLifetimeControlImpl&& rClass) = delete;
|
||||
|
||||
/**
|
||||
* @brief Increment the lifetime. Needs to be balanced by a call to Decrement. Overload of IObjectLifetime::Increment.
|
||||
*/
|
||||
virtual void Increment() override
|
||||
{
|
||||
if (!m_uiLifetimeCnt++)
|
||||
m_ptrLocking = std::enable_shared_from_this<TClass>::shared_from_this();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decrement the lifetime. If the lifetime reaches zero, the object will be destroyed (through the exposed
|
||||
* IObjectDestroy interface). Overload of IObjectLifetime::Decrement.
|
||||
* @return Returns 'true' if the object was destroyed, false if not.
|
||||
*/
|
||||
virtual bool Decrement() override
|
||||
{
|
||||
if (m_uiLifetimeCnt && !(--m_uiLifetimeCnt))
|
||||
{
|
||||
DestroyObject();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current lifetime count. Overload of IObjectLifetime::GetCount.
|
||||
* @remarks The GetCount function returns a momentary value, which can be changed at any moment.
|
||||
* @return Returns the current counter value.
|
||||
*/
|
||||
virtual uint32_t GetCount() const override
|
||||
{
|
||||
return m_uiLifetimeCnt;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Destroy the object. Default implementation deletes 'this'. Overload of IObjectDestroy::DestroyObject.
|
||||
* @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
|
||||
*/
|
||||
virtual void DestroyObject() override
|
||||
{
|
||||
// Reset the locking; this might delete the class if no other references are present.
|
||||
m_ptrLocking.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<TClass> m_ptrLocking; ///< Holder of the instance of the class during lifetime.
|
||||
CLifetimeCookie m_lifetime = CreateLifetimeCookie(); ///< Module lifetime
|
||||
std::atomic_uint32_t m_uiLifetimeCnt = 0; ///< Lifetime reference counter
|
||||
};
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Object control class implementation //
|
||||
/////////////////////////////////////////
|
||||
@@ -1114,6 +1341,7 @@ namespace sdv
|
||||
auto objectPtr = std::move(*iter);
|
||||
m_vecActiveObjects.erase(iter);
|
||||
lockObjects.unlock();
|
||||
objectPtr->OnDestroy();
|
||||
objectPtr = nullptr;
|
||||
if (m_uiActiveObjectCount) --m_uiActiveObjectCount;
|
||||
return;
|
||||
|
||||
@@ -389,7 +389,13 @@ namespace sdv
|
||||
template <typename TIfc>
|
||||
TIfc* GetInterface() const
|
||||
{
|
||||
return m_pInterface ? m_pInterface.load()->GetInterface(GetInterfaceId<TIfc>()).template get<TIfc>() : nullptr;
|
||||
try
|
||||
{
|
||||
return m_pInterface ? m_pInterface.load()->GetInterface(GetInterfaceId<TIfc>()).template get<TIfc>() : nullptr;
|
||||
} catch (const XSysExcept&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,10 +18,17 @@
|
||||
#include "../interfaces/log.h"
|
||||
#include "../interfaces/repository.h"
|
||||
#include "../interfaces/com.h"
|
||||
#include "../interfaces/app.h"
|
||||
#include "../interfaces/param.h"
|
||||
#include "../interfaces/permission.h"
|
||||
#include "interface_ptr.h"
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#ifdef __GNUC__
|
||||
// Needed for getpid()
|
||||
#include <unistd.h>
|
||||
@@ -49,9 +56,11 @@ namespace sdv
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetObject(const std::string& rssObjectName)
|
||||
{
|
||||
if (!GetCore()) return nullptr;
|
||||
if (!GetCore())
|
||||
return nullptr;
|
||||
IObjectAccess* pRepository = GetCore<IObjectAccess>();
|
||||
if (!pRepository) return nullptr;
|
||||
if (!pRepository)
|
||||
return nullptr;
|
||||
return pRepository->GetObject(rssObjectName);
|
||||
}
|
||||
|
||||
@@ -63,9 +72,11 @@ namespace sdv
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetObject(TObjectID tObjectID)
|
||||
{
|
||||
if (!GetCore()) return nullptr;
|
||||
if (!GetCore())
|
||||
return nullptr;
|
||||
IObjectAccess* pRepository = GetCore<IObjectAccess>();
|
||||
if (!pRepository) return nullptr;
|
||||
if (!pRepository)
|
||||
return nullptr;
|
||||
return pRepository->GetObjectByID(tObjectID);
|
||||
}
|
||||
#else
|
||||
@@ -113,21 +124,23 @@ namespace sdv
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log function enables logging for SDV.
|
||||
* @param[in] eSeverity Severity level of the log message which will be logged, e.g. Info, Warning, Error etc.
|
||||
* @param[in] rssSrcFile Name of the file from which the message is logged.
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged.
|
||||
* @param[in] rssMessage Reference to the log message to be logged.
|
||||
*/
|
||||
* @brief Log function enables logging for SDV.
|
||||
* @param[in] eSeverity Severity level of the log message which will be logged, e.g. Info, Warning, Error etc.
|
||||
* @param[in] rssSrcFile Name of the file from which the message is logged.
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged.
|
||||
* @param[in] rssMessage Reference to the log message to be logged.
|
||||
*/
|
||||
inline void Log(ELogSeverity eSeverity, const u8string& rssSrcFile, uint32_t uiSrcLine, const u8string& rssMessage)
|
||||
{
|
||||
ILogger* pLogger = GetCore() ? GetCore<ILogger>() : nullptr;
|
||||
#ifdef _WIN32
|
||||
if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, _getpid(), "", rssMessage);
|
||||
if (pLogger)
|
||||
pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, _getpid(), "", rssMessage);
|
||||
#elif defined __unix__
|
||||
if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, getpid(), "", rssMessage);
|
||||
if (pLogger)
|
||||
pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, getpid(), "", rssMessage);
|
||||
#else
|
||||
#error The OS is currently not supported!
|
||||
#error The OS is currently not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -137,34 +150,34 @@ namespace sdv
|
||||
*/
|
||||
#define SDV_LOG(severity, ...) sdv::core::internal::CSDVLogImpl(severity, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Log a trace message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_TRACE(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::trace, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a debug message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log a debug message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_DEBUG(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::debug, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log an information message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log an information message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_INFO(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::info, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a warning message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log a warning message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_WARNING(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::warning, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log an error message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log an error message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_ERROR(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::error, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a fatal message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log a fatal message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_FATAL(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::fatal, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
namespace internal
|
||||
@@ -176,22 +189,22 @@ namespace sdv
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged. Specified by C++ standard.
|
||||
* @param[in] ...args identifier specified by C++ standard that uses the ellipsis notation in the parameters.
|
||||
*/
|
||||
template <typename ...Args>
|
||||
inline void CSDVLogImpl(ELogSeverity eSeverity, const char* szSrcFile, uint32_t uiSrcLine, Args&& ...args)
|
||||
template <typename... Args>
|
||||
inline void CSDVLogImpl(ELogSeverity eSeverity, const char* szSrcFile, uint32_t uiSrcLine, Args&&... args)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
(stream << ... << std::forward<Args>(args));
|
||||
|
||||
Log(eSeverity, szSrcFile ? szSrcFile : "", uiSrcLine, stream.str().c_str());
|
||||
}
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* @brief Create a utility
|
||||
* @param[in] rssUtilityName Reference to the utility name.
|
||||
* @param[in] rssUtilityConfig Optional reference to the utility configuration.
|
||||
* @return Smart pointer to the utility or NULL when the utility could not be found.
|
||||
*/
|
||||
*/
|
||||
inline TObjectPtr CreateUtility(const std::string& rssUtilityName, const std::string& rssUtilityConfig = std::string())
|
||||
{
|
||||
TInterfaceAccessPtr ptrRepository = GetObject("RepositoryService");
|
||||
@@ -199,8 +212,529 @@ namespace sdv
|
||||
if (!pUtilityCreate) return nullptr;
|
||||
return pUtilityCreate->CreateUtility(rssUtilityName, rssUtilityConfig);
|
||||
}
|
||||
} // namespace core
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the object smart pointer.
|
||||
* @param[in] pParameters Pointer to the parameter map interface of an object.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
|
||||
* bNoExcept was set.
|
||||
*/
|
||||
inline any_t GetParameter(const IParameters* pParameters, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
if (!pParameters)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The object doesn't expose IParameters interface.");
|
||||
}
|
||||
any_t any = pParameters->GetParam(rssParamName);
|
||||
if (any.empty())
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The parameter could not be found.");
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the parameter interface.
|
||||
* @param[in] rptrObject Reference to object smart pointer to the the parameter of.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
|
||||
* bNoExcept was set.
|
||||
*/
|
||||
inline any_t GetParameter(const TInterfaceAccessPtr& rptrObject, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
const IParameters* pParameters = rptrObject.GetInterface<IParameters>();
|
||||
if (!pParameters)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The object doesn't expose IParameters interface.");
|
||||
}
|
||||
return GetParameter(pParameters, rssParamName, bNoExcept);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the object with the supplied name.
|
||||
* @param[in] rssObjectName Reference to the string containing the name of the object or service.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
|
||||
* bNoExcept was set.
|
||||
*/
|
||||
inline any_t GetParameter(const std::string& rssObjectName, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
TInterfaceAccessPtr ptrObject = GetObject(rssObjectName);
|
||||
if (!ptrObject)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("An object with the name '" + rssObjectName + "' could not be found.");
|
||||
}
|
||||
return GetParameter(ptrObject, rssParamName, bNoExcept);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the object with the supplied name. Resolve enums and bitmask objects in the returned
|
||||
* parameter string.
|
||||
* @param[in] rssObjectName Reference to the string containing the name of the object or service.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter as a text string or an empty string when the object or the parameter could
|
||||
* not be found and bNoExcept was set.
|
||||
*/
|
||||
inline std::string GetParameterExpand(const std::string& rssObjectName, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
TInterfaceAccessPtr ptrObject = GetObject(rssObjectName);
|
||||
if (!ptrObject)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("An object with the name '" + rssObjectName + "' could not be found.");
|
||||
}
|
||||
|
||||
const IParameters* pParameters = ptrObject.GetInterface<IParameters>();
|
||||
if (!pParameters)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The object doesn't expose IParameters interface.");
|
||||
}
|
||||
any_t any = pParameters->GetParam(rssParamName);
|
||||
if (any.empty())
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The parameter could not be found.");
|
||||
}
|
||||
|
||||
SParamInfo sParamInfo = pParameters->GetParamInfo(rssParamName);
|
||||
if (sParamInfo.get_switch() == EParamType::enum_param)
|
||||
{
|
||||
for (const SLabelInfo::SLabel& rsLabel : sParamInfo.uExtInfo.sEnumInfo.seqLabels)
|
||||
{
|
||||
if (rsLabel.anyValue == any)
|
||||
return rsLabel.ssLabel;
|
||||
}
|
||||
}
|
||||
if (sParamInfo.get_switch() == EParamType::bitmask_param)
|
||||
{
|
||||
uint64_t uiValue = static_cast<uint64_t>(any);
|
||||
std::stringstream sstreamValue;
|
||||
for (const SLabelInfo::SLabel& rsLabel : sParamInfo.uExtInfo.sBitmaskInfo.seqLabels)
|
||||
{
|
||||
uint64_t uiValueLabel = static_cast<uint64_t>(rsLabel.anyValue);
|
||||
if (uiValue & uiValueLabel)
|
||||
{
|
||||
if (sstreamValue.rdbuf()->in_avail()) // Has characters
|
||||
sstreamValue << "|";
|
||||
sstreamValue << rsLabel.ssLabel;
|
||||
uiValue = uiValue & ~uiValueLabel;
|
||||
}
|
||||
}
|
||||
if (uiValue) // Not all bits have labels
|
||||
{
|
||||
if (sstreamValue.rdbuf()->in_avail()) // Has characters
|
||||
sstreamValue << "|";
|
||||
sstreamValue << uiValue;
|
||||
}
|
||||
return sstreamValue.str();
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
/// Internal namespace
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Trim whitespace at the begin and end of the text.
|
||||
* @param[in] rssText Reference to the text to trim whitespace for.
|
||||
* @return The trimmed text.
|
||||
*/
|
||||
inline std::string TrimWhitespace(const std::string& rssText)
|
||||
{
|
||||
size_t nFirst = rssText.find_first_not_of(" \t\r\n");
|
||||
if (nFirst == std::string::npos) return "";
|
||||
size_t nLast = rssText.find_last_not_of(" \t\r\n");
|
||||
return rssText.substr(nFirst, (nLast - nFirst + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to safely check if a string contains a valid, unescaped $(...) sequence.
|
||||
* @param[in] rssText The text to check.
|
||||
* @return Returns whether the text represents a valid variable.
|
||||
*/
|
||||
inline bool ContainsValidVariable(const std::string& rssText)
|
||||
{
|
||||
size_t nLength = rssText.length();
|
||||
size_t nIndex = 0;
|
||||
|
||||
while (nIndex < nLength)
|
||||
{
|
||||
if (rssText[nIndex] == '\\')
|
||||
{
|
||||
// Skip the escape and the escaped character
|
||||
nIndex += 2;
|
||||
}
|
||||
else if (rssText[nIndex] == '$')
|
||||
{
|
||||
// Check if it forms the start of a token sequence '$( '
|
||||
if (nIndex + 1 < nLength && rssText[nIndex + 1] == '(')
|
||||
{
|
||||
size_t nClose = rssText.find(')', nIndex + 2);
|
||||
if (nClose != std::string::npos)
|
||||
{
|
||||
// Found a valid structural candidate
|
||||
return true;
|
||||
}
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* @brief Resolves embedded object parameter variables formatted as $(object:param) within a text string.
|
||||
* @param[in] rssText The source text containing potential variables and backslash escapes.
|
||||
* @param[in] bRecursive If true, continues resolving until no more unescaped variables remain.
|
||||
* @param[in] bNoExcept If true, returns an empty string for errors; if false, throws std::runtime_error.
|
||||
* @return The fully resolved text string.
|
||||
*/
|
||||
inline std::string ResolveText(const std::string& rssText, bool bRecursive = true, bool bNoExcept = true)
|
||||
{
|
||||
std::string ssCurrentText = rssText;
|
||||
bool bMayHaveMoreVariables = true;
|
||||
|
||||
while (bMayHaveMoreVariables)
|
||||
{
|
||||
bMayHaveMoreVariables = false;
|
||||
std::string ssResult = "";
|
||||
ssResult.reserve(ssCurrentText.length()); // Pre-allocate memory for performance
|
||||
|
||||
size_t nLength = ssCurrentText.length();
|
||||
size_t nIndex = 0;
|
||||
|
||||
while (nIndex < nLength)
|
||||
{
|
||||
char cCurrent = ssCurrentText[nIndex];
|
||||
|
||||
// Handle backslash escape sequences
|
||||
if (cCurrent == '\\')
|
||||
{
|
||||
// Check if the next character is a '$'
|
||||
if (nIndex + 1 < nLength && ssCurrentText[nIndex + 1] == '$')
|
||||
{
|
||||
ssResult.push_back('$'); // Strip the escape character, keep the literal '$'
|
||||
nIndex += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssResult.push_back('\\'); // Preserve other backslashes for paths
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
// Identify potential variables
|
||||
else if (cCurrent == '$')
|
||||
{
|
||||
// extension 2: Only throw an error or treat as a variable if it is
|
||||
// explicitly part of a dynamic sequence tracking towards a '$(...)' match.
|
||||
if (nIndex + 1 >= nLength || ssCurrentText[nIndex + 1] != '(')
|
||||
{
|
||||
// It is a loose literal '$' (like currency). Keep it and do not throw.
|
||||
ssResult.push_back('$');
|
||||
nIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t nVarStart = nIndex + 2; // Position right after "$("
|
||||
size_t nVarEnd = ssCurrentText.find(')', nVarStart);
|
||||
|
||||
// Validate that a matching closing parenthesis exists
|
||||
if (nVarEnd == std::string::npos)
|
||||
{
|
||||
if (!bNoExcept)
|
||||
throw std::runtime_error(
|
||||
"Format error: Missing closing parenthesis ')' for variable starting at index "
|
||||
+ std::to_string(nIndex));
|
||||
return "";
|
||||
}
|
||||
|
||||
// Extract the inner payload block
|
||||
std::string sVariableContent = ssCurrentText.substr(nVarStart, nVarEnd - nVarStart);
|
||||
size_t nColonPos = sVariableContent.find(':');
|
||||
|
||||
// Validate that the delimiter ':' separates object and parameter names
|
||||
if (nColonPos == std::string::npos)
|
||||
{
|
||||
if (!bNoExcept)
|
||||
throw std::runtime_error("Format error: Variable content '" + sVariableContent
|
||||
+ "' lacks an 'object:param' colon separator");
|
||||
return "";
|
||||
}
|
||||
|
||||
// Extract and clean whitespace before/after tokens, preserving inner spaces
|
||||
std::string sObjName = internal::TrimWhitespace(sVariableContent.substr(0, nColonPos));
|
||||
std::string sParamName = internal::TrimWhitespace(sVariableContent.substr(nColonPos + 1));
|
||||
|
||||
// Request the parameter.
|
||||
std::string ssValue = GetParameterExpand(sObjName, sParamName, bNoExcept);
|
||||
|
||||
// Add the parameter to the string
|
||||
ssResult.append(ssValue);
|
||||
|
||||
nIndex = nVarEnd + 1; // Move parsing index past the ')'
|
||||
}
|
||||
else
|
||||
{
|
||||
ssResult.push_back(cCurrent);
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
ssCurrentText = ssResult;
|
||||
|
||||
// Exit immediately if recursive resolution was disabled
|
||||
if (!bRecursive) break;
|
||||
|
||||
// extension 2: Intelligently analyze if a recursive processing loop is required
|
||||
if (internal::ContainsValidVariable(ssCurrentText))
|
||||
bMayHaveMoreVariables = true;
|
||||
}
|
||||
|
||||
return ssCurrentText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current access permission.
|
||||
* @return The current access permission.
|
||||
*/
|
||||
inline EAccessPermission GetCurrentAccessPermission()
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl)
|
||||
return EAccessPermission::not_set;
|
||||
return pPermissionControl->GetCurrentPermission();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current transmission from this thread and prepare a transfer to another thread.
|
||||
* @return Transfer ID identifying the permission of this thread.
|
||||
*/
|
||||
inline TPermissionTransferID TransferCurrentPermission()
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return 0u;
|
||||
return pPermissionControl->TransferCurrentPermission();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Class managing the lifetime of an access permission.
|
||||
*/
|
||||
class CAccessPermission
|
||||
{
|
||||
// Friend functions
|
||||
friend CAccessPermission RestrictAccessPermission(EAccessPermission);
|
||||
friend CAccessPermission SetAccessPermission(TPermissionTransferID);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CAccessPermission() = default;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] tPermissionID The access permission to manage.
|
||||
*/
|
||||
CAccessPermission(TPermissionID tPermissionID) : m_tPermissionID(tPermissionID)
|
||||
{}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Copy constructor is deleted.
|
||||
* @param[in] rPermission Reference to the permission to copy from.
|
||||
*/
|
||||
CAccessPermission(const CAccessPermission& rPermission) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param[in] rPermission Reference to the permission to move from.
|
||||
*/
|
||||
CAccessPermission(CAccessPermission&& rPermission) : m_tPermissionID(rPermission.m_tPermissionID)
|
||||
{
|
||||
rPermission.m_tPermissionID = 0u;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CAccessPermission()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator is deleted.
|
||||
* @param[in] rPermission Reference to the permission to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CAccessPermission& operator=(const CAccessPermission& rPermission) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
* @param[in] rPermission Reference to the permission to move from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CAccessPermission& operator=(CAccessPermission&& rPermission)
|
||||
{
|
||||
m_tPermissionID = rPermission.m_tPermissionID;
|
||||
rPermission.m_tPermissionID = 0u;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean operator.
|
||||
* @return Returns whether a valid permission ID is assigned to this class.
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return m_tPermissionID ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Does the access permission class contain a valid permission ID.
|
||||
* @return Returns whether a valid permission ID is assigned to this class.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_tPermissionID ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release the permission.
|
||||
*/
|
||||
void Release()
|
||||
{
|
||||
if (!m_tPermissionID) return;
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return;
|
||||
pPermissionControl->ReleaseAccessPermission(m_tPermissionID);
|
||||
m_tPermissionID = 0u;
|
||||
}
|
||||
|
||||
private:
|
||||
TPermissionID m_tPermissionID = 0u; ///< Permission ID to be managed by this class.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Restrict the current access permission.
|
||||
* @param[in] ePermission The permission the access should be restricted to.
|
||||
* @return The access permission connected to this restriction. The lifetime of the access permission is managed by the
|
||||
* returned class.
|
||||
*/
|
||||
inline CAccessPermission RestrictAccessPermission(EAccessPermission ePermission)
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return {};
|
||||
return pPermissionControl->RestrictAccessPermission(ePermission);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the access permission from a transfer ID that defined the access permission of a different thread.
|
||||
* @param[in] tTransferID The ID of the transferred access permission.
|
||||
* @return The access permission for the current thread. The lifetime of the access permission is managed by the returned
|
||||
* class.
|
||||
*/
|
||||
inline CAccessPermission SetAccessPermission(TPermissionTransferID tTransferID)
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return {};
|
||||
return pPermissionControl->SetAccessPermission(tTransferID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Secure thread implementation based on std::thread transferring the permissions from the creation thread to the
|
||||
* execution thread.
|
||||
*/
|
||||
class secure_thread : public std::thread
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
secure_thread() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor is deleted.
|
||||
* @param[in] rthread Reference to the thread object.
|
||||
*/
|
||||
secure_thread(const secure_thread& rthread) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param[in] rthread Reference to the thread object.
|
||||
*/
|
||||
secure_thread(secure_thread&& rthread) : std::thread(static_cast<std::thread&&>(rthread))
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Assignment constructor for thread execution.
|
||||
* @tparam F The function to execute.
|
||||
* @tparam Args The argument types of the function to execute.
|
||||
* @param[in] f Reference to the function.
|
||||
* @param[in] args Reference to zero or more arguments.
|
||||
*/
|
||||
template <class F, class... Args>
|
||||
explicit secure_thread(F&& f, Args&&... args)
|
||||
{
|
||||
static_cast<std::thread&>(*this) = std::thread(
|
||||
[](TPermissionTransferID tTransferID, auto&& function, auto&&... arguments)
|
||||
{
|
||||
CAccessPermission permission = SetAccessPermission(tTransferID);
|
||||
std::invoke(std::forward<decltype(function)>(function), std::forward<decltype(arguments)>(arguments)...);
|
||||
}, TransferCurrentPermission(), std::forward<F>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
* @param[in] rthread Reference to the thread object.
|
||||
* @return Reference to this object.
|
||||
*/
|
||||
secure_thread& operator=(secure_thread&& rthread)
|
||||
{
|
||||
static_cast<std::thread&>(*this) = static_cast<std::thread&&>(rthread);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
} // namespace core
|
||||
}// namespace sdv
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Comparison operators
|
||||
* @param[in] e1 First permission
|
||||
* @param[in] e2 Second permission
|
||||
* @return Result of the comparison
|
||||
*/
|
||||
inline bool operator<(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) < static_cast<int32_t>(e2); }
|
||||
inline bool operator<=(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) <= static_cast<int32_t>(e2); }
|
||||
inline bool operator>(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) > static_cast<int32_t>(e2); }
|
||||
inline bool operator>=(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) >= static_cast<int32_t>(e2); }
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace app
|
||||
{
|
||||
/**
|
||||
@@ -208,11 +742,11 @@ namespace sdv
|
||||
* @param[in] rssAttribute Name of the attribute.
|
||||
* @return The attribute value or an empty any-value if the attribute wasn't found or didn't have a value.
|
||||
*/
|
||||
inline any_t GetAppAttribute(const std::string& rssAttribute)
|
||||
inline any_t GetAppSettingsAttribute(const std::string& rssAttribute)
|
||||
{
|
||||
const IAttributes* ptrAppAttributes = core::GetObject<IAttributes>("AppControlService");
|
||||
if (!ptrAppAttributes) return {};
|
||||
return ptrAppAttributes->Get(rssAttribute);
|
||||
const IParameters* pParameters = core::GetObject<IParameters>("AppSettingsService");
|
||||
if (!pParameters) return {};
|
||||
return pParameters->GetParam(rssAttribute);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +755,7 @@ namespace sdv
|
||||
*/
|
||||
inline bool ConsoleIsSilent()
|
||||
{
|
||||
return GetAppAttribute("console.info_level") == "silent";
|
||||
return GetAppSettingsAttribute("Console.Reporting") == "Silent";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,7 +764,7 @@ namespace sdv
|
||||
*/
|
||||
inline bool ConsoleIsVerbose()
|
||||
{
|
||||
return GetAppAttribute("console.info_level") == "verbose";
|
||||
return GetAppSettingsAttribute("Console.Reporting") == "Verbose";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +773,7 @@ namespace sdv
|
||||
*/
|
||||
inline uint32_t GetAppInstanceID()
|
||||
{
|
||||
return GetAppAttribute("app.instance_id");
|
||||
return GetAppSettingsAttribute("Application.Instance");
|
||||
}
|
||||
} // namespace app
|
||||
|
||||
@@ -247,64 +781,81 @@ namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Create a repository connection to a local server.
|
||||
* @param[in] uiInstanceID Optionally the instance ID of the target system to connect to or 0 (default) to connect to the
|
||||
* instance identified by app-control.
|
||||
* @param[in] nRetries Number of retries to connect (optional, default 30, minimum 3).
|
||||
* @return Returns a smart pointer to the repository proxy. Disconnection takes place when IObjectDestroy::DestroyObject is
|
||||
* called.
|
||||
*/
|
||||
inline TObjectPtr ConnectToLocalServerRepository(uint32_t uiInstanceID = 0, size_t nRetries = 30)
|
||||
inline TObjectPtr ConnectToLocalServerRepository(size_t nRetries = 30)
|
||||
{
|
||||
com::IClientConnect* pClientConnect = core::GetObject<com::IClientConnect>("ConnectionService");
|
||||
if (!pClientConnect)
|
||||
// This function works with main, external and maintenance applications.
|
||||
const app::IAppContext* pAppContext = core::GetCore<app::IAppContext>();
|
||||
if (!pAppContext) return {};
|
||||
switch (pAppContext->GetContextType())
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Could not access the connection service." << std::endl;
|
||||
case app::EAppContext::main:
|
||||
case app::EAppContext::external:
|
||||
case app::EAppContext::maintenance:
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
const sdv::app::IAppConnections* pConnections = core::GetObject<sdv::app::IAppConnections>("AppSettingsService");
|
||||
if (!pConnections) return {};
|
||||
std::string ssConnectionConfig = pConnections->GetConnectionConfig("Default");
|
||||
if (ssConnectionConfig.empty()) return {};
|
||||
|
||||
sdv::core::IRepositoryControl* pRepository = core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
|
||||
if (!pRepository) return {};
|
||||
auto tConnectSvcID = pRepository->CreateObject("ClientConnectService", "ClientDefault", ssConnectionConfig);
|
||||
if (!tConnectSvcID) return {};
|
||||
|
||||
sdv::TInterfaceAccessPtr ptrConnectSvc = core::GetObject(tConnectSvcID);
|
||||
sdv::com::IClientConnect* pClientConnect = ptrConnectSvc.GetInterface<sdv::com::IClientConnect>();
|
||||
if (!pClientConnect)
|
||||
{
|
||||
pRepository->DestroyObject("ClientDefault");
|
||||
return {};
|
||||
}
|
||||
|
||||
// Connect the client to the server and return the server repository interface.
|
||||
std::string ssConnectString = R"code([Client]
|
||||
Type = "Local"
|
||||
)code";
|
||||
if (uiInstanceID)
|
||||
ssConnectString += "Instance = " + std::to_string(uiInstanceID) + R"code(
|
||||
)code";
|
||||
try
|
||||
{
|
||||
// Try to connect (30 times with 1 second in between).
|
||||
size_t nCnt = 0;
|
||||
sdv::TObjectPtr ptrRepository;
|
||||
while (!ptrRepository && nCnt < nRetries)
|
||||
sdv::TObjectPtr ptrRemoteRepo;
|
||||
while (!ptrRemoteRepo && nCnt < std::max(nRetries, static_cast<size_t>(3u)))
|
||||
{
|
||||
nCnt++;
|
||||
ptrRepository = pClientConnect->Connect(ssConnectString);
|
||||
if (!ptrRepository)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
if (pClientConnect->IsConnected() || pClientConnect->Connect())
|
||||
{
|
||||
ptrRemoteRepo = pClientConnect->GetRemoteRepository();
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return ptrRepository;
|
||||
return ptrRemoteRepo;
|
||||
}
|
||||
catch (const XAccessDenied& /*rExcept*/)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Access denied trying to connect to a local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
|
||||
app::GetAppInstanceID() << "." << std::endl;
|
||||
return {};
|
||||
}
|
||||
catch (const XNotFound& /*rExcept*/)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " not found." << std::endl;
|
||||
app::GetAppInstanceID() << " not found." << std::endl;
|
||||
return {};
|
||||
}
|
||||
catch (const XInvalidState& rExcept)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "The local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " is in an invalid state: " << rExcept.what() <<
|
||||
app::GetAppInstanceID() << " is in an invalid state: " << rExcept.what() <<
|
||||
std::endl;
|
||||
return {};
|
||||
}
|
||||
@@ -312,12 +863,11 @@ Type = "Local"
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Timeout occurred trying to connect to a local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
|
||||
app::GetAppInstanceID() << "." << std::endl;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace com
|
||||
} // namespace sdv
|
||||
|
||||
#endif // !defined LOCAL_SERVICE_ACCESS_H
|
||||
@@ -435,12 +435,14 @@ namespace sdv
|
||||
* @tparam TInfoConstruct The type of the variables that are provided to the constructor function of the parameter
|
||||
* information.
|
||||
* @param[in] rtVar Reference to the parameter variable.
|
||||
* @param[in] bReadOnly When set, the parameter is read-only (even when writable) and will not be initialized.
|
||||
* @param[in] bLockable When set, the parameter is lockable. Only use with writable parameters.
|
||||
* @param[in] bAutoDirty When set, the parameter dirty flag is detected automatically. Only use with writable parameters.
|
||||
* @param[in] bAutoDirty When set, the parameter dirty flag is detected automatically. Only use with writable
|
||||
* parameters.
|
||||
* @param[in] tConstruct The construct function arguments.
|
||||
*/
|
||||
template <typename... TInfoConstruct>
|
||||
CParamValue(TVar& rtVar, bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct);
|
||||
CParamValue(TVar& rtVar, bool bReadOnly, bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct);
|
||||
|
||||
/**
|
||||
* @brief Set a value. Overload of CParamGuardian::Set.
|
||||
@@ -993,7 +995,7 @@ namespace sdv
|
||||
} \
|
||||
std::vector<std::shared_ptr<sdv::CSdvParamInfo>> vecParamInfo; \
|
||||
[[maybe_unused]] uint32_t uiFlags = 0; \
|
||||
[[maybe_unused]] std::string ssGroup; \
|
||||
[[maybe_unused]] std::string ssGroup; \
|
||||
[[maybe_unused]] bool bLockable = false;
|
||||
|
||||
/**
|
||||
@@ -1107,8 +1109,9 @@ namespace sdv
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string, \
|
||||
default_val, unit_string, ssGroup, description_string, uiFlags); \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, \
|
||||
uiFlags & static_cast<uint32_t>(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
|
||||
unit_string, ssGroup, description_string, uiFlags); \
|
||||
if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo)); \
|
||||
}
|
||||
|
||||
@@ -1126,7 +1129,7 @@ namespace sdv
|
||||
* @param description_string The description of the parameter.
|
||||
*/
|
||||
#define SDV_PARAM_NUMBER_ENTRY(var, name_string, default_val, low_limit, high_limit, unit_string, description_string) \
|
||||
{ \
|
||||
{ \
|
||||
auto prLowLimit = sdv::internal::SLowerLimit() low_limit; \
|
||||
sdv::any_t anyLower; \
|
||||
if (prLowLimit.second != sdv::internal::ELimitType::no_limit) anyLower = prLowLimit.first; \
|
||||
@@ -1144,8 +1147,9 @@ namespace sdv
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, \
|
||||
name_string, default_val, anyLower, prLowLimit.second != sdv::internal::ELimitType::up_to_limit, anyUpper, \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, \
|
||||
uiFlags & static_cast<uint32_t>(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
|
||||
anyLower, prLowLimit.second != sdv::internal::ELimitType::up_to_limit, anyUpper, \
|
||||
prHighLimit.second != sdv::internal::ELimitType::up_to_limit, unit_string, ssGroup, description_string, \
|
||||
uiFlags); \
|
||||
if (ptrParamInfo)vecParamInfo.push_back(std::move(ptrParamInfo)); \
|
||||
@@ -1181,8 +1185,9 @@ namespace sdv
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string, \
|
||||
default_val, pattern_string, unit_string, ssGroup, description_string, uiFlags); \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, \
|
||||
uiFlags & static_cast<uint32_t>(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
|
||||
pattern_string, unit_string, ssGroup, description_string, uiFlags); \
|
||||
if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo)); \
|
||||
}
|
||||
|
||||
@@ -1213,8 +1218,9 @@ namespace sdv
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string, \
|
||||
default_val, sdv::internal::GetLabelMapHelper().GetLabelMap<TEnum>(), ssGroup, description_string, uiFlags); \
|
||||
std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, \
|
||||
uiFlags & static_cast<uint32_t>(::sdv::EParamFlags::read_only), bLockable, true, name_string, default_val, \
|
||||
sdv::internal::GetLabelMapHelper().GetLabelMap<TEnum>(), ssGroup, description_string, uiFlags); \
|
||||
if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo)); \
|
||||
}
|
||||
|
||||
@@ -1238,11 +1244,12 @@ namespace sdv
|
||||
std::vector<std::shared_ptr<sdv::CSdvParamInfo>> vecParamInfoMember; \
|
||||
if constexpr (bStatic) \
|
||||
{ \
|
||||
vecParamInfoMember = sdv::internal::SMemberMap<decltype(member)>::BuildStatic(); \
|
||||
vecParamInfoMember = sdv::internal::SMemberMap<std::decay_t<decltype(member)>>::BuildStatic(); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
auto ptrMemberMap = std::make_shared<sdv::internal::SMemberMap<decltype(member)>>(pObject->member, pObject); \
|
||||
auto ptrMemberMap = \
|
||||
std::make_shared<sdv::internal::SMemberMap<std::decay_t<decltype(member)>>>(pObject->member, pObject); \
|
||||
if (ptrMemberMap) \
|
||||
{ \
|
||||
ptrMemberMap->BuildMap(); \
|
||||
@@ -1388,13 +1395,15 @@ namespace sdv
|
||||
* @tparam TVar Type of the variable.
|
||||
* @tparam TConstruct The arguments for the parameter info construct function.
|
||||
* @param[in] rtVar Reference to the parameter.
|
||||
* @param[in] bReadOnly When set, the parameter is read only and will not be initialized.
|
||||
* @param[in] bLockable When set, the parameter is lockable. Only use with writable parameters.
|
||||
* @param[in] bAutoDirty When set, the parameter dirty flag is detected automatically. Only use with writable parameters.
|
||||
* @param[in] tConstruct The construct function arguments.
|
||||
* @return Smart pointer to the parameter information structure.
|
||||
*/
|
||||
template <typename TVar, typename... TConstruct>
|
||||
std::shared_ptr<CSdvParamInfo> RegisterParameter(TVar& rtVar, bool bLockable, bool bAutoDirty, TConstruct... tConstruct);
|
||||
std::shared_ptr<CSdvParamInfo> RegisterParameter(TVar& rtVar, bool bReadOnly, bool bLockable, bool bAutoDirty,
|
||||
TConstruct... tConstruct);
|
||||
|
||||
/**
|
||||
* @brief Register a member parameter map into this parameter map.
|
||||
|
||||
@@ -412,13 +412,14 @@ namespace sdv
|
||||
|
||||
template <typename TVar>
|
||||
template <typename... TInfoConstruct>
|
||||
inline CParamValue<TVar>::CParamValue(TVar& rtVar, bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct) :
|
||||
inline CParamValue<TVar>::CParamValue(TVar& rtVar, bool bReadOnly, bool bLockable, bool bAutoDirty,
|
||||
TInfoConstruct... tConstruct) :
|
||||
CParamGuardian(bLockable, bAutoDirty, rtVar, tConstruct...), m_rtVar(rtVar)
|
||||
{
|
||||
// Assign the default value
|
||||
if constexpr (!CSdvParamInfo::TypeIsReadOnly<TVar>())
|
||||
{
|
||||
m_rtVar = DefaultVal().get<TVar>();
|
||||
if (!bReadOnly) m_rtVar = DefaultVal().get<TVar>();
|
||||
UpdateDirty(DefaultVal());
|
||||
ResetDirty();
|
||||
}
|
||||
@@ -678,10 +679,10 @@ namespace sdv
|
||||
}
|
||||
|
||||
template <typename TVar, typename... TConstruct>
|
||||
inline std::shared_ptr<CSdvParamInfo> CSdvParamMap::RegisterParameter(TVar& rtVar, bool bLockable, bool bAutoDirty,
|
||||
TConstruct... tConstruct)
|
||||
inline std::shared_ptr<CSdvParamInfo> CSdvParamMap::RegisterParameter(TVar& rtVar, bool bReadOnly, bool bLockable,
|
||||
bool bAutoDirty, TConstruct... tConstruct)
|
||||
{
|
||||
auto ptrParam = std::make_shared<internal::CParamValue<TVar>>(rtVar, bLockable, bAutoDirty, tConstruct...);
|
||||
auto ptrParam = std::make_shared<internal::CParamValue<TVar>>(rtVar, bReadOnly, bLockable, bAutoDirty, tConstruct...);
|
||||
m_vecParamMapRegistration.push_back(SParamRegistration(ptrParam));
|
||||
return ptrParam;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <list>
|
||||
|
||||
namespace serdes
|
||||
{
|
||||
@@ -378,7 +379,25 @@ namespace sdv
|
||||
|
||||
inline CRawDataBypass& GetRawDataBypass()
|
||||
{
|
||||
#if defined __GNUC__ && defined _WIN32
|
||||
// https://dev.azure.com/SW4ZF/AZP-431_DivDI_Vehicle_API/_workitems/edit/610009
|
||||
// In MINGW GCC implementation of thread_local, there is an issue with complex classes being used after the destruction.
|
||||
// This is caused by an architectural bug (https://github.com/msys2/MINGW-packages/issues/2519) causing the emutls (GCC
|
||||
// Emulated TLS) managing the memory allocation to be executed before the __cxa_thread_exit, the thread cleanup callback
|
||||
// of Windows. The solution is to use trivial data only (pointer, reference, integers, etc.). A workaround is
|
||||
// implemented to use a reference of the permission list and map instead of an instance to the list and map.
|
||||
static auto fnCreateBypass = []() -> CRawDataBypass&
|
||||
{
|
||||
static std::mutex mtx;
|
||||
static std::list<CRawDataBypass> lstRawDataBypasses;
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
lstRawDataBypasses.resize(lstRawDataBypasses.size() + 1);
|
||||
return lstRawDataBypasses.back();
|
||||
};
|
||||
thread_local static CRawDataBypass& bypass = fnCreateBypass();
|
||||
#else
|
||||
thread_local static CRawDataBypass bypass;
|
||||
#endif
|
||||
return bypass;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <cctype>
|
||||
#include <stdlib.h>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef _WIN32
|
||||
// Resolve conflict
|
||||
@@ -59,6 +60,8 @@
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
|
||||
#include "simple_toml.h"
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
/**
|
||||
@@ -148,7 +151,36 @@ namespace sdv{
|
||||
{
|
||||
/**
|
||||
* @brief The SDV core loader
|
||||
*/
|
||||
* @details The SDV core loader class searches for the core library and does the first startup. The core library uses
|
||||
* the following environment variables to identify its location:
|
||||
* - SDV_FRAMEWORK_RUNTIME directs to the Vehicle API core location.
|
||||
* - SDV_COMPONENT_INSTALL directs to the location of the component installations.
|
||||
* - SDV_FRAMEWORK_DEV_TOOLS directs to the location of the development tools used during the build process of SDV
|
||||
* components.
|
||||
* - SDV_FRAMEWORK_DEV_INCLUDE directs to the header file location to allow building components for use with the
|
||||
* Vehicle API framework.
|
||||
*
|
||||
* The SDV core loader supports different core stacks to coexist. For this there is a location procedure for the core
|
||||
* systems:
|
||||
* 1. Check for a "sdv_core_reloc.toml" file that contain one or more paths to the core system. The paths defined in the
|
||||
* file override the global environment variables for this application and all child applications.
|
||||
* 2. Check for the environment variables. If the SDV_FRAMEWORK_RUNTIM variable is set, it is used to extract all other
|
||||
* variables as well, if not set.
|
||||
* 3. If no variable is set, use the location of the EXE as core location. This might work in some situations if the
|
||||
* path variable has been set properly.
|
||||
*
|
||||
* If none of the above strategies work, the core cannot be loaded.
|
||||
*
|
||||
* The "sdv_core_reloc.toml" file has the following format:
|
||||
* @code
|
||||
* [CoreLocation]
|
||||
* Version = 100 # Version; currently supported 100 for version 1.0
|
||||
* Runtime = "<core runtime directory>"
|
||||
* Install = "<component install directory>" # Typically identical to runtime directory
|
||||
* DevTools = "<development tools directory>" # Typically identical to runtime directory
|
||||
* Include = "<include directory>" # Typically in the include subdirectory
|
||||
* @endcode
|
||||
*/
|
||||
class CSDVCoreLoader
|
||||
{
|
||||
public:
|
||||
@@ -189,77 +221,50 @@ namespace sdv{
|
||||
{
|
||||
if (m_bInit) return; // Prevent trying to load again.
|
||||
m_bInit = true;
|
||||
bool bRelocFileError = false;
|
||||
std::string ssRelocFileInfo = "";
|
||||
std::string ssEnvironmentInfo = "";
|
||||
|
||||
// Check for the executable directory
|
||||
std::filesystem::path pathCoreLib;
|
||||
if (std::filesystem::exists(GetExecDirectory() / "core_services.sdv"))
|
||||
pathCoreLib = GetExecDirectory() / "core_services.sdv";
|
||||
// Step 1: check for the "sdv_core_reloc.toml"
|
||||
ProcessRelocationFile();
|
||||
|
||||
if (pathCoreLib.empty())
|
||||
{
|
||||
if (std::filesystem::exists(GetExecDirectory() / "sdv_core_reloc.toml"))
|
||||
{
|
||||
// Check for the library in the relocation directory
|
||||
auto relocFolder = GetRelocationPath();
|
||||
if (!relocFolder.empty())
|
||||
{
|
||||
auto coreLibFolder = std::filesystem::path(relocFolder) / "core_services.sdv";
|
||||
if (coreLibFolder.is_relative())
|
||||
coreLibFolder = (GetExecDirectory() / coreLibFolder).lexically_normal();
|
||||
|
||||
if (std::filesystem::exists(coreLibFolder))
|
||||
pathCoreLib = coreLibFolder;
|
||||
}
|
||||
if (pathCoreLib.empty())
|
||||
{
|
||||
bRelocFileError = true; // we found the file but not the core library, we must run into an error
|
||||
ssRelocFileInfo = "Error: Invalid \"sdv_core_reloc.toml\" file found (but no core library), it contains: " + relocFolder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pathCoreLib.empty())
|
||||
{
|
||||
// Step 2: check for environment variables (either set globally or overwritten by the sdv_core_reloc.toml).
|
||||
#ifdef _WIN32
|
||||
std::wstring ssPathCoreTemp(32768, '\0');
|
||||
GetEnvironmentVariable(L"SDV_FRAMEWORK_RUNTIME", ssPathCoreTemp.data(), static_cast<DWORD>(ssPathCoreTemp.size()));
|
||||
ssPathCoreTemp.resize(wcsnlen(ssPathCoreTemp.c_str(), ssPathCoreTemp.size()));
|
||||
if (!ssPathCoreTemp.empty())
|
||||
{
|
||||
pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
|
||||
std::wstring ssPathCoreTemp(32768, '\0');
|
||||
GetEnvironmentVariable(
|
||||
L"SDV_FRAMEWORK_RUNTIME", ssPathCoreTemp.data(), static_cast<DWORD>(ssPathCoreTemp.size()));
|
||||
ssPathCoreTemp.resize(wcsnlen(ssPathCoreTemp.c_str(), ssPathCoreTemp.size()));
|
||||
if (!ssPathCoreTemp.empty())
|
||||
{
|
||||
m_pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
|
||||
#else
|
||||
std::string ssPathCoreTemp = std::getenv("SDV_FRAMEWORK_RUNTIME") ? std::getenv("SDV_FRAMEWORK_RUNTIME") : "";
|
||||
if (!ssPathCoreTemp.empty())
|
||||
{
|
||||
pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
|
||||
std::string ssPathCoreTemp = std::getenv("SDV_FRAMEWORK_RUNTIME") ? std::getenv("SDV_FRAMEWORK_RUNTIME") : "";
|
||||
if (!ssPathCoreTemp.empty())
|
||||
{
|
||||
m_pathCoreLib = std::filesystem::path(ssPathCoreTemp) / "core_services.sdv";
|
||||
#endif
|
||||
if (pathCoreLib.is_relative())
|
||||
pathCoreLib = (GetExecDirectory() / pathCoreLib).lexically_normal();
|
||||
if (m_pathCoreLib.is_relative())
|
||||
m_pathCoreLib = (GetExecDirectory() / m_pathCoreLib).lexically_normal();
|
||||
|
||||
if (!pathCoreLib.empty())
|
||||
ssEnvironmentInfo = "System environment path: " + pathCoreLib.generic_string();
|
||||
}
|
||||
}
|
||||
|
||||
// Depend on system path to find the library
|
||||
if (pathCoreLib.empty())
|
||||
pathCoreLib = "core_services.sdv";
|
||||
|
||||
// Open the library only if there is no or a valid 'sdv_core_reloc.toml' file
|
||||
if (!bRelocFileError)
|
||||
// Step 3: check for the executable directory or otherwise check globally
|
||||
if (m_pathCoreLib.empty())
|
||||
{
|
||||
if (std::filesystem::exists(GetExecDirectory() / "core_services.sdv"))
|
||||
m_pathCoreLib = GetExecDirectory() / "core_services.sdv";
|
||||
else
|
||||
m_pathCoreLib = "core_services.sdv";
|
||||
}
|
||||
|
||||
ssEnvironmentInfo = "System environment path: " + m_pathCoreLib.generic_string();
|
||||
|
||||
#ifdef _WIN32
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
m_tModule = reinterpret_cast<core::TModuleID>(LoadLibraryW(pathCoreLib.native().c_str()));
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
m_tModule = reinterpret_cast<core::TModuleID>(LoadLibraryW(m_pathCoreLib.native().c_str()));
|
||||
#elif defined __unix__
|
||||
m_tModule = reinterpret_cast<core::TModuleID>(dlopen(pathCoreLib.native().c_str(), RTLD_LAZY));
|
||||
m_tModule = reinterpret_cast<core::TModuleID>(dlopen(m_pathCoreLib.native().c_str(), RTLD_LAZY));
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!m_tModule)
|
||||
{
|
||||
@@ -275,16 +280,12 @@ namespace sdv{
|
||||
#else
|
||||
#error OS is not supported!
|
||||
#endif
|
||||
if (ssRelocFileInfo.empty() && ssEnvironmentInfo.empty())
|
||||
std::cerr << "No environment variable set and no realocation file found." << std::endl;
|
||||
if (!ssRelocFileInfo.empty())
|
||||
std::cerr << ssRelocFileInfo << std::endl;
|
||||
if (!ssEnvironmentInfo.empty())
|
||||
std::cerr << ssEnvironmentInfo << std::endl;
|
||||
|
||||
std::cerr << "Could not load \"core_services.sdv\" library";
|
||||
if (!ssError.empty()) std::cerr << ": " << ssError;
|
||||
std::cerr << std::endl;
|
||||
m_ssErrMsg = "Could not load \"core_services.sdv\" library";
|
||||
if (!ssError.empty())
|
||||
m_ssErrMsg += ": " + ssError;
|
||||
std::cerr << m_ssErrMsg << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -301,7 +302,8 @@ namespace sdv{
|
||||
#endif
|
||||
if (!fnSDVCore)
|
||||
{
|
||||
std::cerr << "The library \"core_services.sdv\" doesn't expose the SDVCore function." << std::endl;
|
||||
m_ssErrMsg = "The library \"core_services.sdv\" doesn't expose the SDVCore function.";
|
||||
std::cerr << m_ssErrMsg << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -311,7 +313,8 @@ namespace sdv{
|
||||
m_pCore = fnSDVCore();
|
||||
if (!m_pCore)
|
||||
{
|
||||
std::cerr << "The library \"core_services.sdv\" doesn't provide a valid interface." << std::endl;
|
||||
m_ssErrMsg = "The library \"core_services.sdv\" doesn't provide a valid interface.";
|
||||
std::cerr << m_ssErrMsg << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -321,7 +324,6 @@ namespace sdv{
|
||||
*/
|
||||
operator TInterfaceAccessPtr() const { return m_pCore; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Get the directory of the executable.
|
||||
* @return Path to the directory.
|
||||
@@ -346,86 +348,170 @@ namespace sdv{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the folder path in the file 'sdv_core_reloc.toml'.
|
||||
* @return Path content, empty string if not found.
|
||||
*/
|
||||
static std::string GetRelocationPath()
|
||||
* @brief Get the path to the core library.
|
||||
* @return Returns a reference to the path to the core library.
|
||||
*/
|
||||
const std::filesystem::path& GetCoreLibPath() const
|
||||
{
|
||||
if (std::filesystem::exists(GetExecDirectory() / "sdv_core_reloc.toml"))
|
||||
{
|
||||
std::ifstream fstream(GetExecDirectory() / "sdv_core_reloc.toml");
|
||||
std::string ssLine;
|
||||
while (std::getline(fstream, ssLine))
|
||||
{
|
||||
size_t nPos = 0;
|
||||
auto fnSkipWhitespace = [&]() { while (std::isspace(ssLine[nPos])) nPos++; };
|
||||
fnSkipWhitespace();
|
||||
if (ssLine[nPos] == '#') continue; // Rest of the line is comments
|
||||
if (ssLine.substr(nPos, 9) != "directory") continue; // not the keq of interest: skip line
|
||||
nPos += 9;
|
||||
fnSkipWhitespace();
|
||||
if (ssLine[nPos] != '=')
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting assignment character '=' following"
|
||||
" keyword 'directory'." << std::endl;
|
||||
break;
|
||||
}
|
||||
nPos++;
|
||||
fnSkipWhitespace();
|
||||
if (ssLine[nPos] != '\"')
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting double quote character '\"' indicating"
|
||||
" a string begin'." << std::endl;
|
||||
break;
|
||||
}
|
||||
nPos++;
|
||||
size_t nStart = nPos;
|
||||
while (nPos < ssLine.length() && ssLine[nPos] != '\"')
|
||||
{
|
||||
// Check for escape character
|
||||
if (ssLine[nPos] == '\\') nPos++;
|
||||
|
||||
// Skip character
|
||||
nPos++;
|
||||
}
|
||||
if (nPos >= ssLine.length() || ssLine[nPos] != '\"')
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting double quote character '\"' indicating"
|
||||
" a string end'." << std::endl;
|
||||
break;
|
||||
}
|
||||
std::string ssDirectory = ssLine.substr(nStart, nPos - nStart);
|
||||
while (ssDirectory.empty())
|
||||
{
|
||||
std::cout << "Error in \"sdv_core_reloc.toml\": expecting a valid value following the assignment"
|
||||
" of the 'directory' key." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
return ssDirectory;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return m_pathCoreLib;
|
||||
}
|
||||
|
||||
bool m_bInit = false; ///< Is the loader initialized?
|
||||
core::TModuleID m_tModule = 0; ///< Module ID
|
||||
IInterfaceAccess* m_pCore = nullptr; ///< Pointer to the core services.
|
||||
/**
|
||||
* @brief Has loaded successfully?
|
||||
* @return Returns whether loading was successful.
|
||||
*/
|
||||
bool HasLoaded() const
|
||||
{
|
||||
return m_bInit && m_tModule && m_pCore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the error message if loading was unsuccessful.
|
||||
* @return Returns the a reference to the string containing the error message or an empty string if not available.
|
||||
*/
|
||||
const std::string& GetErrorMsg() const
|
||||
{
|
||||
return m_ssErrMsg;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Check for the 'sdv_core_reloc.toml' file containing the information about core relocation.
|
||||
* @details Set the environment variables following the information from the core relocation file.
|
||||
*/
|
||||
static void ProcessRelocationFile()
|
||||
{
|
||||
if (!std::filesystem::exists(GetExecDirectory() / "sdv_core_reloc.toml")) return;
|
||||
|
||||
std::ifstream fstream(GetExecDirectory() / "sdv_core_reloc.toml");
|
||||
if (!fstream.is_open()) return;
|
||||
|
||||
std::stringstream sstreamContent;
|
||||
sstreamContent << fstream.rdbuf();
|
||||
fstream.close();
|
||||
|
||||
try
|
||||
{
|
||||
sdv::toml::simple_parser::CParser parser(sstreamContent.str());
|
||||
if (parser.Root().GetDirect("CoreLocation.Version").GetValue<uint32_t>() != SDVFrameworkInterfaceVersion)
|
||||
{
|
||||
std::cerr << "Invalid version in sdv_core_reloc.toml" << std::endl;
|
||||
return; // Version not supported
|
||||
}
|
||||
|
||||
const auto& sRuntimeNode = parser.Root().GetDirect("CoreLocation.Runtime");
|
||||
if (sRuntimeNode)
|
||||
{
|
||||
// Note: since the system might load multiple executables and the path is relative to this executable,
|
||||
// but maybe not to another executable, create an absolute path before assigning the environment
|
||||
// variable.
|
||||
std::filesystem::path pathRuntime = sRuntimeNode.GetValue<std::string>();
|
||||
if (pathRuntime.is_relative())
|
||||
pathRuntime = (GetExecDirectory() / pathRuntime).lexically_normal();
|
||||
#ifdef _WIN32
|
||||
// NOTE: In windows there are two environment variables which need to be updated.
|
||||
std::ignore = SetEnvironmentVariable(L"SDV_FRAMEWORK_RUNTIME", pathRuntime.native().c_str());
|
||||
std::ignore = _wputenv((std::wstring(L"SDV_FRAMEWORK_RUNTIME=") + pathRuntime.native()).c_str());
|
||||
#elif defined __unix__
|
||||
std::ignore = setenv("SDV_FRAMEWORK_RUNTIME", pathRuntime.generic_u8string().c_str(), 1);
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
const auto& sInstallNode = parser.Root().GetDirect("CoreLocation.Install");
|
||||
if (sInstallNode)
|
||||
{
|
||||
// Note: since the system might load multiple executables and the path is relative to this executable,
|
||||
// but maybe not to another executable, create an absolute path before assigning the environment
|
||||
// variable.
|
||||
std::filesystem::path pathInstall = sInstallNode.GetValue<std::string>();
|
||||
if (pathInstall.is_relative())
|
||||
pathInstall = (GetExecDirectory() / pathInstall).lexically_normal();
|
||||
#ifdef _WIN32
|
||||
// NOTE: In windows there are two environment variables which need to be updated.
|
||||
std::ignore = SetEnvironmentVariable(L"SDV_COMPONENT_INSTALL", pathInstall.native().c_str());
|
||||
std::ignore = _wputenv((std::wstring(L"SDV_COMPONENT_INSTALL=") + pathInstall.native()).c_str());
|
||||
#elif defined __unix__
|
||||
std::ignore = setenv("SDV_COMPONENT_INSTALL", pathInstall.generic_u8string().c_str(), 1);
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
const auto& sDevToolsNode = parser.Root().GetDirect("CoreLocation.DevTools");
|
||||
if (sDevToolsNode)
|
||||
{
|
||||
// Note: since the system might load multiple executables and the path is relative to this executable,
|
||||
// but maybe not to another executable, create an absolute path before assigning the environment
|
||||
// variable.
|
||||
std::filesystem::path pathDevTools = sDevToolsNode.GetValue<std::string>();
|
||||
if (pathDevTools.is_relative())
|
||||
pathDevTools = (GetExecDirectory() / pathDevTools).lexically_normal();
|
||||
#ifdef _WIN32
|
||||
// NOTE: In windows there are two environment variables which need to be updated.
|
||||
std::ignore = SetEnvironmentVariable(L"SDV_FRAMEWORK_DEV_TOOLS", pathDevTools.native().c_str());
|
||||
std::ignore = _wputenv((std::wstring(L"SDV_FRAMEWORK_DEV_TOOLS=") + pathDevTools.native()).c_str());
|
||||
#elif defined __unix__
|
||||
std::ignore = setenv("SDV_FRAMEWORK_DEV_TOOLS", pathDevTools.generic_u8string().c_str(), 1);
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
const auto& sIncludeNode = parser.Root().GetDirect("CoreLocation.Include");
|
||||
if (sIncludeNode)
|
||||
{
|
||||
// Note: since the system might load multiple executables and the path is relative to this executable,
|
||||
// but maybe not to another executable, create an absolute path before assigning the environment
|
||||
// variable.
|
||||
std::filesystem::path pathInclude = sIncludeNode.GetValue<std::string>();
|
||||
if (pathInclude.is_relative())
|
||||
pathInclude = (GetExecDirectory() / pathInclude).lexically_normal();
|
||||
#ifdef _WIN32
|
||||
// NOTE: In windows there are two environment variables which need to be updated.
|
||||
std::ignore = SetEnvironmentVariable(L"SDV_FRAMEWORK_DEV_INCLUDE", pathInclude.native().c_str());
|
||||
std::ignore = _wputenv((std::wstring(L"SDV_FRAMEWORK_DEV_INCLUDE=") + pathInclude.native()).c_str());
|
||||
#elif defined __unix__
|
||||
std::ignore = setenv("SDV_FRAMEWORK_DEV_INCLUDE", pathInclude.generic_u8string().c_str(), 1);
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{}
|
||||
}
|
||||
|
||||
bool m_bInit = false; ///< Is the loader initialized?
|
||||
core::TModuleID m_tModule = 0; ///< Module ID
|
||||
IInterfaceAccess* m_pCore = nullptr; ///< Pointer to the core services.
|
||||
std::filesystem::path m_pathCoreLib; ///< Path to the core library.
|
||||
std::string m_ssErrMsg; ///< Error message for failed loading.
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
#ifndef NO_SDV_CORE_FUNC
|
||||
/**
|
||||
* @brief Access to the core.
|
||||
* @return Smart pointer to the core services interface.
|
||||
* @brief Access to the core loader.
|
||||
* @return Reference to the one core loader instance.
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetCore()
|
||||
inline internal::CSDVCoreLoader& GetCoreLoader()
|
||||
{
|
||||
static internal::CSDVCoreLoader core;
|
||||
core.Load();
|
||||
return core;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to the core interfaces.
|
||||
* @return Smart pointer to the core services interfaces.
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetCore()
|
||||
{
|
||||
return GetCoreLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to specific interface of the core.
|
||||
* @tparam TInterface Type of interface to return.
|
||||
|
||||
@@ -546,10 +546,10 @@ namespace sdv
|
||||
if (m_ptrValue) m_ptrValue->Receive(anyVal);
|
||||
}
|
||||
|
||||
CDispatchService& m_rDispatch; ///< Reference to the dispatch service.
|
||||
std::function<void(any_t)> m_funcSignalReceive; ///< Receive signal data - callback function.
|
||||
IInterfaceAccess* m_pSubscription = nullptr; ///< Cookie received by adding an receive subscription.
|
||||
std::unique_ptr<CValueAssignmentHelper> m_ptrValue; ///< Value to update instead of a callback function.
|
||||
CDispatchService& m_rDispatch; ///< Reference to the dispatch service.
|
||||
std::function<void(any_t)> m_funcSignalReceive; ///< Receive signal data - callback function.
|
||||
IInterfaceAccess* m_pSubscription = nullptr; ///< Cookie received by adding a subscription.
|
||||
std::unique_ptr<CValueAssignmentHelper> m_ptrValue; ///< Value to update instead of callback func.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
1010
export/support/simple_toml.h
Normal file
1010
export/support/simple_toml.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,12 +11,14 @@
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef SDV_CONFIG_H
|
||||
#define SDV_CONFIG_H
|
||||
#ifndef SDV_TOML_H
|
||||
#define SDV_TOML_H
|
||||
|
||||
#include <charconv>
|
||||
#include "../interfaces/toml.h"
|
||||
#include "interface_ptr.h"
|
||||
#include "local_service_access.h"
|
||||
#include "interface_ptr.h"
|
||||
|
||||
namespace sdv::toml
|
||||
{
|
||||
@@ -82,6 +84,18 @@ namespace sdv::toml
|
||||
*/
|
||||
ENodeType GetType() const;
|
||||
|
||||
/**
|
||||
* @brief Get the index of this node within the parent collection.
|
||||
* @return The index of the node within the parent collection node or npos when no parent is available.
|
||||
*/
|
||||
uint32_t GetIndex() const;
|
||||
|
||||
/**
|
||||
* @brief Is the node defined as inline node?
|
||||
* @return The inline flag.
|
||||
*/
|
||||
bool IsInline() const;
|
||||
|
||||
/**
|
||||
* @brief Return any associated comment text for this node.
|
||||
* @return The node comment or an empty string when there is not comment for this node.
|
||||
@@ -132,6 +146,12 @@ namespace sdv::toml
|
||||
*/
|
||||
virtual void Clear();
|
||||
|
||||
/**
|
||||
* @brief Format the node automatically, remove redundant whitespace.
|
||||
* @param[in] bRemoveComments When set, the comments are removed from the node.
|
||||
*/
|
||||
void AutomaticFormat(bool bRemoveComments);
|
||||
|
||||
/**
|
||||
* @brief Get the TOML string from this node including all children.
|
||||
* @return The TOML string.
|
||||
@@ -228,23 +248,29 @@ namespace sdv::toml
|
||||
*/
|
||||
CNode GetDirect(const sdv::u8string& rssNode) const;
|
||||
|
||||
/**
|
||||
* @brief Return the node name for a node in the collection. If the collection is an array, provides the index between
|
||||
* square brackets.
|
||||
* @param[in] nIndex Index to return the node name for.
|
||||
* @return Name of the node or an empty string if the index is larger than the amount of nodes in the collection.
|
||||
*/
|
||||
std::string GetNodeNameByIndex(size_t nIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Insert a value node before the provided position.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @param[in] nIndex The index before which to insert the node. Can be larger than the count value as well as
|
||||
* sdv::toml::npos when adding the node at the end.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Since values are presented as inline node, they
|
||||
* will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] rssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] rssName Reference to the name of the new value node. If this collection is an array, the name is ignored.
|
||||
* Otherwise the name must be unique within this collection.
|
||||
* @param[in] ranyValue The value to assign to the node. The value also determines the type of value node.
|
||||
* @return Returns the node when successfully inserted or an empty node when not.
|
||||
*/
|
||||
CNode InsertValue(size_t nIndex, const std::string& rssName, const sdv::any_t& ranyValue);
|
||||
CNode InsertValue(const std::string& rssInsertBefore, const std::string& rssName, const sdv::any_t& ranyValue);
|
||||
|
||||
/**
|
||||
* @brief Add a value node to the collection.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @param[in] rssName Reference to the name of the new array collection node. If this collection is an array, the name is
|
||||
* ignored. Otherwise the name must be unique within this collection.
|
||||
* @param[in] ranyValue The value to assign to the node. The value also determines the type of value node.
|
||||
@@ -254,20 +280,18 @@ namespace sdv::toml
|
||||
|
||||
/**
|
||||
* @brief Insert an array collection before the provided position.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @param[in] nIndex The index before which to insert the node. Can be larger than the count value as well as
|
||||
* sdv::toml::npos when adding the node at the end.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Since arrays are presented as inline node, they
|
||||
* will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] rssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] rssName Reference to the name of the new value node. If this collection is an array, the name is ignored.
|
||||
* Otherwise the name must be unique within this collection.
|
||||
* @return Returns the collection node when successfully inserted or an empty node when not.
|
||||
*/
|
||||
CNodeCollection InsertArray(size_t nIndex, const std::string& rssName);
|
||||
CNodeCollection InsertArray(const std::string& rssInsertBefore, const std::string& rssName);
|
||||
|
||||
/**
|
||||
* @brief Add an array collection to this collection.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @param[in] rssName Reference to the name of the new array collection node. If this collection is an array, the name is
|
||||
* ignored. Otherwise the name must be unique within this collection.
|
||||
* @return Returns the collection node when successfully added or an empty node when not.
|
||||
@@ -276,22 +300,20 @@ namespace sdv::toml
|
||||
|
||||
/**
|
||||
* @brief Insert a table collection before the provided position.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @param[in] nIndex The index before which to insert the node. Can be larger than the count value as well as
|
||||
* sdv::toml::npos when adding the node at the end.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Tables can be inserted as inline node, in which
|
||||
* case they will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] rssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] rssName Reference to the name of the new table collection node. If this collection is an array, the name is
|
||||
* ignored. Otherwise the name must be unique within this collection.
|
||||
* @param[in] bFavorInline When set, the node will be added as inline collection node. When not, the node will be inserted
|
||||
* as inline collection if the this collection is also inline, as standard when not.
|
||||
* @return Returns the collection node when successfully inserted or an empty node when not.
|
||||
*/
|
||||
CNodeCollection InsertTable(size_t nIndex, const std::string& rssName, bool bFavorInline = false);
|
||||
CNodeCollection InsertTable(const std::string& rssInsertBefore, const std::string& rssName, bool bFavorInline = false);
|
||||
|
||||
/**
|
||||
* @brief Add a table collection to this collection.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @param[in] rssName Reference to the name of the new table collection node. If this collection is an array, the name is
|
||||
* ignored. Otherwise the name must be unique within this collection.
|
||||
* @param[in] bFavorInline When set, the node will be added as inline collection node. When not, the node will be inserted
|
||||
@@ -302,12 +324,12 @@ namespace sdv::toml
|
||||
|
||||
/**
|
||||
* @brief Insert a table array collection before the provided position.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @remarks A table array is an array with table inside. Inserting a table array node can also be done by creating an array,
|
||||
* if not existing already, and adding a table to the array.
|
||||
* @param[in] nIndex The index before which to insert the node. Can be larger than the count value as well as
|
||||
* sdv::toml::npos when adding the node at the end.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Table arrays can be inserted as inline node, in
|
||||
* which case they will be inserted before any standard node (table or table array if defined as standard node).
|
||||
* @param[in] rssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] rssName Reference to the name of the new table array node. If this collection is an array, the name is
|
||||
* ignored. Otherwise the name must be unique within this collection.
|
||||
* @param[in] bFavorInline When set, the node will be added as inline collection node. When not, the node will be inserted
|
||||
@@ -315,12 +337,10 @@ namespace sdv::toml
|
||||
* @return Returns the collection node when successfully inserted or an empty node when not. The collection node represents
|
||||
* a table collection.
|
||||
*/
|
||||
CNodeCollection InsertTableArray(size_t nIndex, const std::string& rssName, bool bFavorInline = false);
|
||||
CNodeCollection InsertTableArray(const std::string& rssInsertBefore, const std::string& rssName, bool bFavorInline = false);
|
||||
|
||||
/**
|
||||
* @brief Add a table array collection to this collection.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @remarks A table array is an array with table inside. Inserting a table array node can also be done by creating an array,
|
||||
* if not existing already, and adding a table to the array.
|
||||
* @param[in] rssName Reference to the name of the new table array node. If this collection is an array, the name is
|
||||
@@ -335,10 +355,10 @@ namespace sdv::toml
|
||||
/**
|
||||
* @brief Insert a TOML string to the collection. All nodes specified in the TOML will be added in the collection except
|
||||
* when the nodes already exist. Comment and whitespace are preserved when possible.
|
||||
* @remarks The actual position depends on the type of node and the order the nodes are stored. Inline nodes come before
|
||||
* standard nodes.
|
||||
* @param[in] nIndex The index before which to insert the node. Can be larger than the count value as well as
|
||||
* sdv::toml::npos when adding the node at the end.
|
||||
* @remarks In TOML, inline nodes are located before standard nodes. Dependable on the nodes defined in the TOML they
|
||||
* might be transferred to inline or they might be inserted at a different location.
|
||||
* @param[in] rssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
|
||||
* square brackets. Can be empty, causing the node to be inserted at the end.
|
||||
* @param[in] rssTOML Reference to the TOML string containing the nodes. The TOML string can be empty, which is not an
|
||||
* error. If required the TOML nodes are converted to inline nodes.
|
||||
* @param[in] bAllowPartial When set, duplicate nodes (already present in this collection) will be ignored and do not
|
||||
@@ -346,7 +366,7 @@ namespace sdv::toml
|
||||
* @return Returns 1 if the complete TOMl could be inserted, 0 if no TOML could be inserted or -1 when the TOML could be
|
||||
* partially inserted.
|
||||
*/
|
||||
int InsertTOML(size_t nIndex, const std::string& rssTOML, bool bAllowPartial = false);
|
||||
int InsertTOML(const std::string& rssInsertBefore, const std::string& rssTOML, bool bAllowPartial = false);
|
||||
|
||||
/**
|
||||
* @brief Add a TOML string to this collection. All nodes specified in the TOML will be added in the collection except
|
||||
@@ -372,16 +392,11 @@ namespace sdv::toml
|
||||
class CTOMLParser : public CNodeCollection
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
CTOMLParser() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor providing automatic processing.
|
||||
* @param[in] rssConfig Reference to the configuration.
|
||||
*/
|
||||
CTOMLParser(const std::string& rssConfig);
|
||||
CTOMLParser(const std::string& rssConfig = "");
|
||||
|
||||
/**
|
||||
* @brief Process a configuration. This will clear any previous configuration.
|
||||
@@ -414,6 +429,52 @@ namespace sdv::toml
|
||||
ITOMLParser* m_pParser = nullptr; ///< Pointer to the parser interface.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compare flags
|
||||
*/
|
||||
enum class ECompareFlags : uint32_t
|
||||
{
|
||||
compare_ignore_whitespace = 1, ///< Compare, but ignore whitespace
|
||||
compare_ignore_comments = 2, ///< Compare, but ignore comments
|
||||
compare_ignore_inline = 8, ///< Compare, but ignore inline or explicit
|
||||
compare_ignore_all = 255, ///< Compare with all ignore flags
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compare result
|
||||
*/
|
||||
enum class ECompareResult : int32_t
|
||||
{
|
||||
compare_identical = 0, ///< The comparison resulted into identical TOML strings
|
||||
compare_different = 1, ///< The comparison resulted into different TOML strings
|
||||
compare_error = -1 ///< The comparison could not be done due to a failure
|
||||
};
|
||||
|
||||
/// Internal namespace
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Compare the content of the node with the content of another node.
|
||||
* @attention This function changes the nodes dependable on the provided flags.
|
||||
* @param[in] rnode1 First node interface to compare with the second node.
|
||||
* @param[in] rnode2 Second node interface to compare with the first node.
|
||||
* @param[in] uiCompareFlags Zero or more flags from ECompareFlags.
|
||||
* @return The comparison result.
|
||||
*/
|
||||
ECompareResult CompareNodes(CNode& rnode1, CNode& rnode2,
|
||||
uint32_t uiCompareFlags = static_cast<uint32_t>(ECompareFlags::compare_ignore_all));
|
||||
} // namespace internal;
|
||||
|
||||
/**
|
||||
* @brief Compare the content of TOML string with the content of another TOML string.
|
||||
* @param[in] rssToml1 Reference to the first TOML string to compare with the second TOML string.
|
||||
* @param[in] rssToml2 Reference to the second TOML string to compare with the first TOML string.
|
||||
* @param[in] uiCompareFlags Zero or more flags from ECompareFlags.
|
||||
* @return The comparison result.
|
||||
*/
|
||||
ECompareResult Compare(const std::string& rssToml1, const std::string& rssToml2,
|
||||
uint32_t uiCompareFlags = static_cast<uint32_t>(ECompareFlags::compare_ignore_all));
|
||||
|
||||
inline CNode::CNode(const TInterfaceAccessPtr& rptrNode)
|
||||
{
|
||||
m_pNodeInfo = rptrNode.GetInterface<INodeInfo>();
|
||||
@@ -461,6 +522,16 @@ namespace sdv::toml
|
||||
return m_pNodeInfo ? m_pNodeInfo->GetType() : ENodeType::node_invalid;
|
||||
}
|
||||
|
||||
inline uint32_t CNode::GetIndex() const
|
||||
{
|
||||
return m_pNodeInfo ? m_pNodeInfo->GetIndex() : npos;
|
||||
}
|
||||
|
||||
inline bool CNode::IsInline() const
|
||||
{
|
||||
return m_pNodeInfo ? m_pNodeInfo->IsInline() : true;
|
||||
}
|
||||
|
||||
inline std::string CNode::GetComment() const
|
||||
{
|
||||
if (!m_pNodeInfo) return {};
|
||||
@@ -527,7 +598,9 @@ namespace sdv::toml
|
||||
{
|
||||
INodeUpdate* pNodeUpdate = m_ptrNode.GetInterface<INodeUpdate>();
|
||||
if (!pNodeUpdate) return false;
|
||||
return pNodeUpdate->DeleteNode();
|
||||
bool bRet = pNodeUpdate->DeleteNode();
|
||||
Clear(); // Not valid any more.
|
||||
return bRet;
|
||||
}
|
||||
|
||||
inline void CNode::Clear()
|
||||
@@ -536,6 +609,11 @@ namespace sdv::toml
|
||||
m_pNodeInfo = nullptr;
|
||||
}
|
||||
|
||||
inline void CNode::AutomaticFormat(bool bRemoveComments)
|
||||
{
|
||||
if (m_pNodeInfo) m_pNodeInfo->AutomaticFormat(bRemoveComments);
|
||||
}
|
||||
|
||||
inline sdv::u8string CNode::GetTOML() const
|
||||
{
|
||||
return m_pNodeInfo ? m_pNodeInfo->GetTOML() : sdv::u8string();
|
||||
@@ -605,76 +683,86 @@ namespace sdv::toml
|
||||
return m_pCollection ? CNode(m_pCollection->GetNodeDirect(rssNode)) : CNode();
|
||||
}
|
||||
|
||||
inline CNode CNodeCollection::InsertValue(size_t nIndex, const std::string& rssName, const sdv::any_t& ranyValue)
|
||||
inline std::string CNodeCollection::GetNodeNameByIndex(size_t nIndex) const
|
||||
{
|
||||
if (!m_pCollection) return {};
|
||||
if (nIndex >= m_pCollection->GetCount()) return {};
|
||||
if (GetType() == ENodeType::node_array) return "[" + std::to_string(nIndex) + "]";
|
||||
TInterfaceAccessPtr ptrNode = m_pCollection->GetNode(static_cast<uint32_t>(nIndex));
|
||||
const auto* pAccess = ptrNode.GetInterface<INodeInfo>();
|
||||
if (!pAccess) return {};
|
||||
return pAccess->GetName();
|
||||
}
|
||||
|
||||
inline CNode CNodeCollection::InsertValue(const std::string& rssInsertBefore, const std::string& rssName,
|
||||
const sdv::any_t& ranyValue)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNode(pInsert->InsertValue(static_cast<uint32_t>(nIndex), rssName, ranyValue));
|
||||
return CNode(pInsert->InsertValue(rssInsertBefore, rssName, ranyValue));
|
||||
}
|
||||
|
||||
inline CNode CNodeCollection::AddValue(const std::string& rssName, const sdv::any_t& ranyValue)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNode(pInsert->InsertValue(npos, rssName, ranyValue));
|
||||
return CNode(pInsert->InsertValue("", rssName, ranyValue));
|
||||
}
|
||||
|
||||
inline CNodeCollection CNodeCollection::InsertArray(size_t nIndex, const std::string& rssName)
|
||||
inline CNodeCollection CNodeCollection::InsertArray(const std::string& rssInsertBefore, const std::string& rssName)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNodeCollection(pInsert->InsertArray(static_cast<uint32_t>(nIndex), rssName));
|
||||
return CNodeCollection(pInsert->InsertArray(rssInsertBefore, rssName));
|
||||
}
|
||||
|
||||
inline CNodeCollection CNodeCollection::AddArray(const std::string& rssName)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNodeCollection(pInsert->InsertArray(npos, rssName));
|
||||
return CNodeCollection(pInsert->InsertArray("", rssName));
|
||||
}
|
||||
|
||||
inline CNodeCollection CNodeCollection::InsertTable(size_t nIndex, const std::string& rssName, bool bFavorInline /*= false*/)
|
||||
inline CNodeCollection CNodeCollection::InsertTable(const std::string& rssInsertBefore, const std::string& rssName,
|
||||
bool bFavorInline /*= false*/)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNodeCollection(pInsert->InsertTable(static_cast<uint32_t>(nIndex), rssName,
|
||||
bFavorInline ? INodeCollectionInsert::EInsertPreference::prefer_inline :
|
||||
INodeCollectionInsert::EInsertPreference::prefer_standard));
|
||||
return CNodeCollection(pInsert->InsertTable(rssInsertBefore, rssName, bFavorInline ? EInsertPreference::prefer_inline :
|
||||
EInsertPreference::prefer_standard));
|
||||
}
|
||||
|
||||
inline CNodeCollection CNodeCollection::AddTable(const std::string& rssName, bool bFavorInline /*= false*/)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNodeCollection(pInsert->InsertTable(npos, rssName,
|
||||
bFavorInline ? INodeCollectionInsert::EInsertPreference::prefer_inline :
|
||||
INodeCollectionInsert::EInsertPreference::prefer_standard));
|
||||
return CNodeCollection(pInsert->InsertTable("", rssName, bFavorInline ? EInsertPreference::prefer_inline :
|
||||
EInsertPreference::prefer_standard));
|
||||
}
|
||||
|
||||
inline CNodeCollection CNodeCollection::InsertTableArray(size_t nIndex, const std::string& rssName,
|
||||
inline CNodeCollection CNodeCollection::InsertTableArray(const std::string& rssInsertBefore, const std::string& rssName,
|
||||
bool bFavorInline /*= false*/)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNodeCollection(pInsert->InsertTableArray(static_cast<uint32_t>(nIndex), rssName,
|
||||
bFavorInline ? INodeCollectionInsert::EInsertPreference::prefer_inline :
|
||||
INodeCollectionInsert::EInsertPreference::prefer_standard));
|
||||
return CNodeCollection(pInsert->InsertTableArray(rssInsertBefore, rssName, bFavorInline ? EInsertPreference::prefer_inline :
|
||||
EInsertPreference::prefer_standard));
|
||||
}
|
||||
|
||||
inline CNodeCollection CNodeCollection::AddTableArray(const std::string& rssName, bool bFavorInline /*= false*/)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return {};
|
||||
return CNodeCollection(pInsert->InsertTableArray(npos, rssName,
|
||||
bFavorInline ? INodeCollectionInsert::EInsertPreference::prefer_inline :
|
||||
INodeCollectionInsert::EInsertPreference::prefer_standard));
|
||||
return CNodeCollection(pInsert->InsertTableArray("", rssName, bFavorInline ? EInsertPreference::prefer_inline :
|
||||
EInsertPreference::prefer_standard));
|
||||
}
|
||||
|
||||
inline int CNodeCollection::InsertTOML(size_t nIndex, const std::string& rssTOML, bool bAllowPartial /*= false*/)
|
||||
inline int CNodeCollection::InsertTOML(const std::string& rssInsertBefore, const std::string& rssTOML,
|
||||
bool bAllowPartial /*= false*/)
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return 0;
|
||||
INodeCollectionInsert::EInsertResult eRet = pInsert->InsertTOML(static_cast<uint32_t>(nIndex), rssTOML, !bAllowPartial);
|
||||
INodeCollectionInsert::EInsertResult eRet = pInsert->InsertTOML(rssInsertBefore, rssTOML, !bAllowPartial);
|
||||
switch (eRet)
|
||||
{
|
||||
case INodeCollectionInsert::EInsertResult::insert_success:
|
||||
@@ -691,7 +779,7 @@ namespace sdv::toml
|
||||
{
|
||||
INodeCollectionInsert* pInsert = m_ptrNode.GetInterface<INodeCollectionInsert>();
|
||||
if (!pInsert) return 0;
|
||||
INodeCollectionInsert::EInsertResult eRet = pInsert->InsertTOML(npos, rssTOML, !bAllowPartial);
|
||||
INodeCollectionInsert::EInsertResult eRet = pInsert->InsertTOML("", rssTOML, !bAllowPartial);
|
||||
switch (eRet)
|
||||
{
|
||||
case INodeCollectionInsert::EInsertResult::insert_success:
|
||||
@@ -746,6 +834,59 @@ namespace sdv::toml
|
||||
m_ptrParserUtil.Clear();
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
inline ECompareResult CompareNodes(CNode& rnode1, CNode& rnode2,
|
||||
uint32_t uiCompareFlags /*= static_cast<uint32_t>(ECompareFlags::compare_ignore_all)*/)
|
||||
{
|
||||
if (!rnode1 || !rnode2) return ECompareResult::compare_error;
|
||||
|
||||
// Format the nodes when ignore whitespace and/or comments
|
||||
bool bIgnoreComments = uiCompareFlags & static_cast<uint32_t>(ECompareFlags::compare_ignore_comments);
|
||||
bool bIgnoreWhitespace = bIgnoreComments ||
|
||||
(uiCompareFlags & static_cast<uint32_t>(ECompareFlags::compare_ignore_whitespace));
|
||||
if (bIgnoreWhitespace)
|
||||
{
|
||||
INodeInfo* pNodeInfo1 = rnode1.GetInterface().GetInterface<INodeInfo>();
|
||||
if (!pNodeInfo1) return ECompareResult::compare_error;
|
||||
pNodeInfo1->AutomaticFormat(bIgnoreComments);
|
||||
INodeInfo* pNodeInfo2 = rnode2.GetInterface().GetInterface<INodeInfo>();
|
||||
if (!pNodeInfo2) return ECompareResult::compare_error;
|
||||
pNodeInfo2->AutomaticFormat(bIgnoreComments);
|
||||
}
|
||||
|
||||
// Convert to standard if ignoring inline
|
||||
INodeCollectionConvert* pConvert1 = rnode1.GetInterface().GetInterface<INodeCollectionConvert>();
|
||||
INodeCollectionConvert* pConvert2 = rnode2.GetInterface().GetInterface<INodeCollectionConvert>();
|
||||
if (pConvert1 && pConvert2 && uiCompareFlags & static_cast<uint32_t>(ECompareFlags::compare_ignore_inline))
|
||||
{
|
||||
// Making inline nodes as standard, might only change the upper node.
|
||||
// Making standard nodes inline, will have all child nodes be made inline as well, because inline nodes can only
|
||||
// have inline nodes.
|
||||
pConvert1->MakeInline();
|
||||
pConvert2->MakeInline();
|
||||
}
|
||||
|
||||
// Generate the TOMLs and compare
|
||||
return rnode1.GetTOML() == rnode2.GetTOML() ? ECompareResult::compare_identical : ECompareResult::compare_different;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
inline ECompareResult Compare(const std::string& rssToml1, const std::string& rssToml2,
|
||||
uint32_t uiCompareFlags /*= static_cast<uint32_t>(ECompareFlags::compare_ignore_all)*/)
|
||||
{
|
||||
try
|
||||
{
|
||||
CTOMLParser parser1(rssToml1);
|
||||
CTOMLParser parser2(rssToml2);
|
||||
return internal::CompareNodes(parser1, parser2, uiCompareFlags);
|
||||
}
|
||||
catch (const sdv::toml::XTOMLParseException&)
|
||||
{
|
||||
return ECompareResult::compare_error;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // !defined SDV_CONFIG_H
|
||||
#endif // !defined SDV_TOML_H
|
||||
BIN
funding_logos/CHIPS_logo_RGB_full_colour.png
Normal file
BIN
funding_logos/CHIPS_logo_RGB_full_colour.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 158 KiB |
BIN
funding_logos/EN_Co-fundedbytheEU_RGB_POS.png
Normal file
BIN
funding_logos/EN_Co-fundedbytheEU_RGB_POS.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
BIN
funding_logos/HAL4SDV_logo_on_white.jpg
Normal file
BIN
funding_logos/HAL4SDV_logo_on_white.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 123 KiB |
56
funding_logos/Shift2sdv_logo_tagline_blue.svg
Normal file
56
funding_logos/Shift2sdv_logo_tagline_blue.svg
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 509.93 258.96">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #0023f4;
|
||||
stroke-width: 0px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g>
|
||||
<path class="cls-1" d="M16.52,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73H5.94v-15.36h10.58Z"/>
|
||||
<path class="cls-1" d="M23.45,243.21l6.39,10.07v-10.07h3.15v15.36h-2.89l-6.41-9.98v9.98h-3.15v-15.36h2.91Z"/>
|
||||
<path class="cls-1" d="M50.52,250.16v6.5c-.8.73-1.75,1.3-2.85,1.7-1.1.4-2.24.6-3.41.6-1.23,0-2.31-.19-3.23-.58-.92-.39-1.68-.93-2.29-1.64-.61-.7-1.06-1.55-1.37-2.55-.3-1-.46-2.1-.46-3.3s.17-2.37.5-3.36.81-1.84,1.42-2.54c.62-.7,1.37-1.24,2.25-1.61s1.87-.56,2.96-.56c1,0,1.86.12,2.57.37.72.24,1.33.58,1.83,1.01.5.43.9.93,1.2,1.51.3.57.51,1.19.64,1.85l-3.22.41c-.09-.39-.19-.73-.32-1.02s-.3-.54-.53-.75-.52-.37-.87-.47-.78-.16-1.3-.16c-1.26,0-2.2.47-2.82,1.4s-.93,2.25-.93,3.94.32,3.02.95,3.95c.63.92,1.65,1.39,3.07,1.39.68,0,1.27-.07,1.77-.21.5-.14.98-.35,1.44-.63v-2.56h-2.96v-2.67h5.95Z"/>
|
||||
<path class="cls-1" d="M57.69,243.21v15.36h-3.24v-15.36h3.24Z"/>
|
||||
<path class="cls-1" d="M65.04,243.21l6.39,10.07v-10.07h3.15v15.36h-2.89l-6.41-9.98v9.98h-3.15v-15.36h2.91Z"/>
|
||||
<path class="cls-1" d="M89.59,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73h-10.71v-15.36h10.58Z"/>
|
||||
<path class="cls-1" d="M104.19,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73h-10.71v-15.36h10.58Z"/>
|
||||
<path class="cls-1" d="M113.7,243.21c1.22,0,2.22.14,3.01.42.79.28,1.41.65,1.86,1.1s.76.95.93,1.51c.17.55.26,1.09.26,1.62,0,.99-.18,1.82-.54,2.5s-.97,1.24-1.83,1.7l3.15,6.52h-3.5l-2.61-5.77h-3.04v5.77h-3.19v-15.36h5.5ZM115.18,249.98c.33-.11.6-.26.79-.45s.33-.43.4-.7.11-.57.11-.9c0-.27-.04-.54-.13-.79s-.24-.47-.45-.67c-.21-.19-.5-.34-.87-.45s-.84-.16-1.4-.16h-2.24v4.28h2.52c.51,0,.93-.05,1.26-.16Z"/>
|
||||
<path class="cls-1" d="M126.89,243.21v15.36h-3.24v-15.36h3.24Z"/>
|
||||
<path class="cls-1" d="M134.23,243.21l6.39,10.07v-10.07h3.15v15.36h-2.89l-6.41-9.98v9.98h-3.15v-15.36h2.91Z"/>
|
||||
<path class="cls-1" d="M161.31,250.16v6.5c-.8.73-1.75,1.3-2.85,1.7-1.1.4-2.24.6-3.41.6-1.23,0-2.31-.19-3.23-.58-.92-.39-1.68-.93-2.29-1.64-.61-.7-1.06-1.55-1.37-2.55-.3-1-.46-2.1-.46-3.3s.17-2.37.5-3.36.81-1.84,1.42-2.54c.62-.7,1.37-1.24,2.25-1.61s1.87-.56,2.96-.56c1,0,1.86.12,2.57.37.72.24,1.33.58,1.83,1.01.5.43.9.93,1.2,1.51.3.57.51,1.19.64,1.85l-3.22.41c-.09-.39-.19-.73-.32-1.02s-.3-.54-.53-.75-.52-.37-.87-.47-.78-.16-1.3-.16c-1.26,0-2.2.47-2.82,1.4s-.93,2.25-.93,3.94.32,3.02.95,3.95c.63.92,1.65,1.39,3.07,1.39.68,0,1.27-.07,1.77-.21.5-.14.98-.35,1.44-.63v-2.56h-2.96v-2.67h5.95Z"/>
|
||||
<path class="cls-1" d="M169.95,245.99v-2.78h12.6v2.78h-4.67v12.59h-3.26v-12.59h-4.67Z"/>
|
||||
<path class="cls-1" d="M189.07,243.21v5.94h6.15v-5.94h3.24v15.36h-3.24v-6.45h-6.15v6.45h-3.24v-15.36h3.24Z"/>
|
||||
<path class="cls-1" d="M213.47,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73h-10.71v-15.36h10.58Z"/>
|
||||
<path class="cls-1" d="M225.16,243.21l3.76,10.86,3.87-10.86h3.48l-5.82,15.36h-3.06l-5.82-15.36h3.61Z"/>
|
||||
<path class="cls-1" d="M249.91,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73h-10.71v-15.36h10.58Z"/>
|
||||
<path class="cls-1" d="M257.16,243.21v5.94h6.15v-5.94h3.24v15.36h-3.24v-6.45h-6.15v6.45h-3.24v-15.36h3.24Z"/>
|
||||
<path class="cls-1" d="M274.22,243.21v15.36h-3.24v-15.36h3.24Z"/>
|
||||
<path class="cls-1" d="M291.33,255.53c-.31.7-.74,1.3-1.28,1.81-.54.51-1.21.91-2,1.19s-1.71.43-2.75.43c-1.17,0-2.21-.19-3.1-.58-.89-.39-1.64-.93-2.24-1.64-.6-.7-1.05-1.55-1.36-2.55-.3-1-.46-2.1-.46-3.3s.17-2.37.5-3.36c.33-.99.81-1.84,1.43-2.54.62-.7,1.38-1.24,2.26-1.61s1.88-.56,3-.56c.99,0,1.84.12,2.57.37.73.24,1.35.59,1.85,1.05s.9,1.01,1.21,1.66.53,1.37.67,2.17l-3.22.41c-.16-.9-.47-1.61-.92-2.13s-1.18-.77-2.16-.77c-1.25,0-2.19.46-2.84,1.39s-.97,2.23-.97,3.93.34,3.02,1.03,3.94,1.61,1.38,2.77,1.38c1,0,1.73-.25,2.21-.76.47-.51.76-1.24.88-2.18h3.48c-.07.82-.26,1.57-.58,2.27Z"/>
|
||||
<path class="cls-1" d="M298.64,243.21v12.61h7.34l-.35,2.75h-10.23v-15.36h3.24Z"/>
|
||||
<path class="cls-1" d="M319.93,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73h-10.71v-15.36h10.58Z"/>
|
||||
<path class="cls-1" d="M333.62,258.4c-.91-.37-1.69-.91-2.32-1.61-.64-.7-1.13-1.55-1.47-2.54-.34-.99-.51-2.11-.51-3.36s.17-2.37.51-3.36.83-1.84,1.48-2.54c.64-.7,1.42-1.24,2.34-1.61s1.94-.56,3.09-.56,2.19.19,3.11.56,1.68.91,2.31,1.61c.63.7,1.11,1.55,1.44,2.54s.5,2.11.5,3.36-.16,2.37-.49,3.36c-.33.99-.8,1.84-1.43,2.54-.63.7-1.4,1.24-2.31,1.61s-1.96.56-3.13.56-2.19-.19-3.11-.56ZM339.74,254.83c.67-.92,1-2.23,1-3.94s-.33-3-1-3.93-1.68-1.39-3.04-1.39-2.38.46-3.04,1.39-1,2.23-1,3.93.33,3.02,1,3.94,1.68,1.38,3.04,1.38,2.38-.46,3.04-1.38Z"/>
|
||||
<path class="cls-1" d="M358.21,243.21v2.75h-6.95v3.61h6.54v2.75h-6.54v6.24h-3.24v-15.36h10.19Z"/>
|
||||
<path class="cls-1" d="M366.68,245.99v-2.78h12.6v2.78h-4.67v12.59h-3.26v-12.59h-4.67Z"/>
|
||||
<path class="cls-1" d="M385.8,243.21v5.94h6.15v-5.94h3.24v15.36h-3.24v-6.45h-6.15v6.45h-3.24v-15.36h3.24Z"/>
|
||||
<path class="cls-1" d="M410.2,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73h-10.71v-15.36h10.58Z"/>
|
||||
<path class="cls-1" d="M430.28,243.21v2.75h-6.95v3.61h6.54v2.75h-6.54v6.24h-3.24v-15.36h10.19Z"/>
|
||||
<path class="cls-1" d="M436.97,243.21v9.14c0,1.31.23,2.27.7,2.9s1.24.95,2.32.95,1.86-.32,2.31-.95.68-1.6.68-2.9v-9.14h3.24v9.14c0,1.16-.14,2.16-.43,2.99s-.7,1.52-1.24,2.05c-.54.54-1.19.93-1.97,1.18s-1.65.38-2.62.38-1.87-.13-2.64-.39-1.43-.66-1.97-1.19-.94-1.23-1.22-2.08c-.28-.85-.41-1.85-.41-3.01v-9.08h3.24Z"/>
|
||||
<path class="cls-1" d="M449.2,245.99v-2.78h12.6v2.78h-4.67v12.59h-3.26v-12.59h-4.67Z"/>
|
||||
<path class="cls-1" d="M468.01,243.21v9.14c0,1.31.23,2.27.7,2.9s1.24.95,2.32.95,1.86-.32,2.31-.95.68-1.6.68-2.9v-9.14h3.24v9.14c0,1.16-.14,2.16-.43,2.99s-.7,1.52-1.24,2.05c-.54.54-1.19.93-1.97,1.18s-1.65.38-2.62.38-1.87-.13-2.64-.39-1.43-.66-1.97-1.19-.94-1.23-1.22-2.08c-.28-.85-.41-1.85-.41-3.01v-9.08h3.24Z"/>
|
||||
<path class="cls-1" d="M486.89,243.21c1.22,0,2.22.14,3.01.42.79.28,1.41.65,1.86,1.1s.76.95.93,1.51c.17.55.26,1.09.26,1.62,0,.99-.18,1.82-.54,2.5s-.97,1.24-1.83,1.7l3.15,6.52h-3.5l-2.61-5.77h-3.04v5.77h-3.19v-15.36h5.5ZM488.37,249.98c.33-.11.6-.26.79-.45s.33-.43.4-.7.11-.57.11-.9c0-.27-.04-.54-.13-.79s-.24-.47-.45-.67c-.21-.19-.5-.34-.87-.45s-.84-.16-1.4-.16h-2.24v4.28h2.52c.51,0,.93-.05,1.26-.16Z"/>
|
||||
<path class="cls-1" d="M507.43,243.21v2.73h-7.34v3.36h6.91v2.75h-6.91v3.79h7.8l-.33,2.73h-10.71v-15.36h10.58Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-1" d="M18.99,50.96c2.16,1.71,5.35,2.57,9.56,2.57,2.02,0,3.72-.21,5.1-.64s2.51-1,3.37-1.71,1.48-1.56,1.86-2.53c.37-.97.56-2.03.56-3.17,0-1.6-.61-3.1-1.82-4.5-1.21-1.4-3.43-2.41-6.66-3.04l-8.04-1.46c-3.17-.57-5.97-1.31-8.39-2.23-2.42-.91-4.45-2.1-6.1-3.55s-2.9-3.24-3.76-5.35c-.87-2.11-1.3-4.62-1.3-7.54s.59-5.48,1.77-7.71c1.18-2.23,2.83-4.08,4.93-5.57,2.1-1.49,4.63-2.61,7.57-3.38,2.94-.77,6.17-1.16,9.69-1.16,4.5,0,8.25.51,11.25,1.54s5.42,2.38,7.27,4.07,3.21,3.64,4.11,5.87c.89,2.23,1.48,4.54,1.77,6.94l-12.2,1.54c-.63-3.37-1.86-5.79-3.68-7.28-1.82-1.48-4.57-2.23-8.26-2.23-2.19,0-3.99.19-5.41.56-1.41.37-2.55.86-3.42,1.46s-1.47,1.3-1.82,2.1c-.35.8-.52,1.63-.52,2.48,0,2.28.65,4,1.95,5.14,1.3,1.14,3.5,2.03,6.62,2.66l8.48,1.63c6.69,1.31,11.59,3.44,14.71,6.38,3.11,2.94,4.67,7.18,4.67,12.72,0,2.68-.5,5.15-1.51,7.41-1.01,2.25-2.51,4.22-4.5,5.91s-4.48,3-7.48,3.94c-3,.94-6.52,1.41-10.55,1.41-8.42,0-14.86-1.78-19.33-5.35-4.47-3.57-6.88-8.95-7.22-16.14h13.06c.29,3.77,1.51,6.51,3.68,8.22Z"/>
|
||||
<path class="cls-1" d="M78.12,1.54v22.1c1.79-2.4,3.86-4.17,6.23-5.31,2.36-1.14,4.84-1.71,7.44-1.71,5.13,0,8.94,1.33,11.42,3.98,2.48,2.66,3.72,6.84,3.72,12.55v29.55h-12.11v-27.92c0-3.14-.61-5.28-1.82-6.42-1.21-1.14-2.83-1.71-4.84-1.71-1.56,0-2.9.23-4.02.69-1.12.46-2.18,1.11-3.16,1.97-.81.8-1.48,1.76-2.03,2.87s-.82,2.33-.82,3.64v26.89h-12.11V1.54h12.11Z"/>
|
||||
<path class="cls-1" d="M134.6,1.54v10.79h-12.46V1.54h12.46ZM134.43,17.99v44.71h-12.11V17.99h12.11Z"/>
|
||||
<path class="cls-1" d="M146.11,27.32v-9.34h7.09v-1.46c0-2.74.4-5.11,1.21-7.11.81-2,1.92-3.63,3.33-4.88,1.41-1.26,3.07-2.18,4.97-2.78s3.98-.9,6.23-.9c1.44,0,2.96.09,4.54.26,1.59.17,3.21.51,4.89,1.03l-1.64,8.74c-1.85-.46-3.6-.69-5.28-.69-1.56,0-2.97.44-4.24,1.33-1.27.89-1.9,2.47-1.9,4.75v1.71h10.47v9.34h-10.47v35.37h-12.11V27.32h-7.09Z"/>
|
||||
<path class="cls-1" d="M185.03,27.32v-9.34h7.09V6.08h12.11v11.91h10.38v9.34h-10.38v20.64c0,2.34.49,3.93,1.47,4.75.98.83,2.25,1.24,3.81,1.24.81,0,1.63-.04,2.47-.13.84-.09,1.66-.24,2.47-.47l1.73,8.82c-1.67.51-3.3.87-4.89,1.07-1.59.2-3.1.3-4.54.3-4.96,0-8.64-1.17-11.03-3.51-2.39-2.34-3.59-6.28-3.59-11.82v-20.9h-7.09Z"/>
|
||||
<path class="cls-1" d="M233.3,47.49c2.42-1.97,4.87-4.04,7.35-6.21,2.42-2.11,4.54-4.03,6.36-5.74,1.82-1.71,3.33-3.37,4.54-4.97,1.21-1.6,2.12-3.18,2.72-4.75.61-1.57.91-3.3.91-5.18,0-2.46-.71-4.47-2.12-6.04-1.41-1.57-3.33-2.36-5.75-2.36-2.88,0-5.15.64-6.79,1.93-1.64,1.29-2.87,3.73-3.68,7.32l-11.76-1.37c.52-2.46,1.27-4.78,2.25-6.98.98-2.2,2.32-4.14,4.02-5.82,1.7-1.68,3.85-3.01,6.44-3.98,2.6-.97,5.8-1.46,9.6-1.46,6.69,0,11.76,1.63,15.22,4.88,3.46,3.25,5.19,7.68,5.19,13.28,0,2.4-.3,4.61-.91,6.64-.61,2.03-1.51,4.01-2.72,5.95s-2.75,3.9-4.63,5.87-4.11,4.1-6.7,6.38c-1.38,1.14-2.78,2.28-4.2,3.43-1.41,1.14-2.93,2.46-4.54,3.94h24.57l-1.3,10.45h-41.43v-8.99c2.48-2.17,4.93-4.24,7.35-6.21Z"/>
|
||||
</g>
|
||||
<path class="cls-1" d="M29.38,103.53v60.85c-16.23,0-29.38-13.16-29.38-29.38v-2.09c0-16.23,13.16-29.38,29.38-29.38ZM127.44,164.38c16.12,0,29.18,13.06,29.18,29.17v7.96c0,16.1-13.06,29.17-29.17,29.17H2.81v-24.15h100.5c13.26,0,24.02,10.69,24.14,23.92v-66.08h0ZM127.45,164.38H29.38c0-13.33,10.81-24.15,24.15-24.15h49.77c13.34,0,24.15,10.81,24.15,24.15ZM154.94,103.53H29.39c0-13.33,10.81-24.15,24.14-24.15h101.41v24.15Z"/>
|
||||
<path class="cls-1" d="M343.48,137.25v36.19c0,15.51-12.57,28.07-28.06,28.07h-1.03c-.05,16.07-13.18,29.17-29.26,29.17h-100.45V79.38h100.93c15.84,0,28.7,12.86,28.72,28.7,16.1,0,29.15,13.07,29.15,29.17ZM314.31,108.1l-100.45-.03v93.44l100.45-.1v-93.31Z"/>
|
||||
<path class="cls-1" d="M509.93,79.18l-16.65,97.91c-2.73,16.08-17.56,29.12-32.63,29.17-.18,1-.51,2.09-.79,3.05-3.43,11.89-14.51,21.09-26.04,21.09h-4.24c-11.53,0-22.61-9.2-26.03-21.09-.29-1-.53-2.02-.7-3.05-15.1,0-29.98-13.07-32.72-29.17l-16.65-97.91h27.76l21.61,127.07,57.73-.09,21.59-126.98h27.76Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -451,7 +451,7 @@ namespace dbc
|
||||
if (!bNoDefaultDef)
|
||||
{
|
||||
// Parse the standard attribute definitions
|
||||
CDbcSource source(std::string(R"code(
|
||||
CDbcSource source(std::string(R"dbc(
|
||||
BA_DEF_ BO_ "VFrameFormat" ENUM "StandardCAN","ExtendedCAN","StandardFD","ExtendedFD";
|
||||
BA_DEF_ BO_ "GenMsgSendType" ENUM "cyclic","triggered","cyclicIfActive","cyclicAndTriggered","cyclicIfActiveAndTriggered","none";
|
||||
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 10000;
|
||||
@@ -472,7 +472,7 @@ BA_DEF_DEF_ "GenSigDelayTime" 0;
|
||||
BA_DEF_DEF_ "GenSigCycleTime" 0;
|
||||
BA_DEF_DEF_ "GenSigStartDelayTime" 0;
|
||||
BA_DEF_DEF_ "GenSigStartValue" 0;
|
||||
)code"));
|
||||
)dbc"));
|
||||
Parse(source);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,9 +176,9 @@ namespace debug
|
||||
*/
|
||||
struct SLogMsg
|
||||
{
|
||||
std::thread::id id; ///< Thread ID
|
||||
size_t nDepth; ///< Depth within the calls
|
||||
std::string ssMsg; ///< Message to log
|
||||
std::thread::id id; ///< Thread ID
|
||||
size_t nDepth; ///< Depth within the calls
|
||||
std::string ssMsg; ///< Message to log
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -271,7 +271,7 @@ namespace debug
|
||||
|
||||
std::filesystem::path m_pathLogFile; ///< Path to the log file.
|
||||
#if DECOUPLED_DEBUG_LOG != 0
|
||||
std::mutex m_mtxLogger; ///< Protect against multiple log entries at the same time.
|
||||
std::mutex m_mtxLogger; ///< Protect against multiple log entries at the same time.
|
||||
std::thread m_threadLogger; ///< Logger thread
|
||||
std::atomic_bool m_bShutdown = false; ///< When set, terminate the logging thread
|
||||
std::queue<SLogMsg> m_queueLogger; ///< Queue with messages to log.
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef THREAD_POOL_H
|
||||
#define THREAD_POOL_H
|
||||
#ifndef SCHEDULER_H
|
||||
#define SCHEDULER_H
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
@@ -27,33 +27,38 @@
|
||||
#include "../flags.h"
|
||||
|
||||
/**
|
||||
* @brief Job scheduler that uses a dynamic threadpool to schedule the task.
|
||||
* @brief Schedule flags to influence the scheduling.
|
||||
*/
|
||||
enum class EScheduleFlags
|
||||
{
|
||||
normal = 0x0, ///< If thread level threshold has been reached, queue the call at the end of the queue.
|
||||
priority = 0x1, ///< If thread level threshold has been reached, insert the call at the begin of the queue.
|
||||
no_queue = 0x2, ///< If thread level threshold has been reached, fail the schedule call.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Task scheduler that uses a dynamic threadpool to schedule the task.
|
||||
* @tparam TThread Type of thread class to use for scheduling; must be derived from std::thread.
|
||||
* @tparam nMinIdle The amount of idle threads that should stay present if there is nothing to process at the moment.
|
||||
* @tparam nMaxBusy The maximum amount of threads that is used for processing.
|
||||
*/
|
||||
template <class TThread = std::thread, size_t nMinIdle = 4, size_t nMaxBusy = 32>
|
||||
class CTaskScheduler
|
||||
{
|
||||
public:
|
||||
// The thread class must be derived from std::thread.
|
||||
static_assert(std::is_base_of_v<std::thread, TThread>);
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] nMinIdle The amount of idle threads that should stay present if there is nothing to process at the moment.
|
||||
* @param[in] nMaxBusy The maximum amount of threads that is used for processing.
|
||||
*/
|
||||
CTaskScheduler(size_t nMinIdle = 4, size_t nMaxBusy = 32);
|
||||
CTaskScheduler();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CTaskScheduler();
|
||||
|
||||
/**
|
||||
* @brief Schedule flags to influence the scheduling.
|
||||
*/
|
||||
enum class EScheduleFlags
|
||||
{
|
||||
normal = 0x0, ///< If thread level threshold has been reached, queue the call at the end of the queue.
|
||||
priority = 0x1, ///< If thread level threshold has been reached, insert the call at the begin of the queue.
|
||||
no_queue = 0x2, ///< If thread level threshold has been reached, fail the schedule call.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Schedule the asynchronous execution of the task.
|
||||
* @details If an idle thread is available, the thread will execute the task. If no thread is available and the maximum thread
|
||||
@@ -125,7 +130,7 @@ private:
|
||||
*/
|
||||
void ThreadFunc();
|
||||
|
||||
std::thread m_thread; ///< The thread that executes the tasks.
|
||||
TThread m_thread; ///< The thread that executes the tasks.
|
||||
std::atomic_bool m_bShutdown = false; ///< Set when the thread should terminate.
|
||||
std::atomic_bool m_bStarted = false; ///< Set when the thread has started.
|
||||
std::function<void()> m_fnTask; ///< The task to execute (will be updated with new tasks before execution).
|
||||
@@ -143,15 +148,18 @@ private:
|
||||
* @param[in] itThread The thread to use for the execution.
|
||||
* @param[in] fnTask The task to execute.
|
||||
*/
|
||||
void Execute(std::list<std::shared_ptr<CThread>>::iterator itThread, std::function<void()> fnTask);
|
||||
void Execute(typename std::list<std::shared_ptr<CThread>>::iterator itThread, std::function<void()> fnTask);
|
||||
|
||||
size_t m_nMinIdle = 4; ///< The minimal required amount of idle threads
|
||||
size_t m_nMaxBusy = 32; ///< The maximum allowed amount of busy threads
|
||||
size_t m_nMaxThreads = 0; ///< The maximum amount threads at the same time.
|
||||
mutable std::mutex m_mtxQueueAccess; ///< Sync access to queue, list and double-ended-queue.
|
||||
std::queue<std::list<std::shared_ptr<CThread>>::iterator> m_queueIdleThreads; ///< Idle thread queue.
|
||||
std::list<std::shared_ptr<CThread>> m_lstThreads; ///< List with all threads.
|
||||
std::queue<typename std::list<std::shared_ptr<CThread>>::iterator> m_queueIdleThreads; ///< Idle thread queue.
|
||||
std::list<typename std::shared_ptr<CThread>> m_lstThreads; ///< List with all threads.
|
||||
std::deque<std::function<void()>> m_dequeTasks; ///< Double ended task queue.
|
||||
};
|
||||
|
||||
#endif // !defined THREAD_POOL_H
|
||||
// Include the implementation
|
||||
#include "scheduler.inl"
|
||||
|
||||
#endif // !defined SCHEDULER_H
|
||||
@@ -11,10 +11,17 @@
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef SCHEDULER_H
|
||||
#include "scheduler.h"
|
||||
#endif
|
||||
|
||||
#ifndef SCHEDULER_INL
|
||||
#define SCHEDULER_INL
|
||||
|
||||
#include <cassert>
|
||||
|
||||
CTaskScheduler::CTaskScheduler(size_t nMinIdle /*= 4*/, size_t nMaxBusy /*= 32*/) :
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline CTaskScheduler<TThread, nMinIdle, nMaxBusy>::CTaskScheduler() :
|
||||
m_nMinIdle(nMinIdle), m_nMaxBusy(nMaxBusy)
|
||||
{
|
||||
// Check min/max values
|
||||
@@ -30,17 +37,20 @@ CTaskScheduler::CTaskScheduler(size_t nMinIdle /*= 4*/, size_t nMaxBusy /*= 32*/
|
||||
m_nMaxThreads = m_lstThreads.size();
|
||||
}
|
||||
|
||||
CTaskScheduler::~CTaskScheduler()
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline CTaskScheduler<TThread, nMinIdle, nMaxBusy>::~CTaskScheduler()
|
||||
{
|
||||
WaitForExecution();
|
||||
}
|
||||
|
||||
bool CTaskScheduler::Schedule(std::function<void()> fnTask, hlpr::flags<EScheduleFlags> flags /*= 0*/)
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline bool CTaskScheduler<TThread, nMinIdle, nMaxBusy>::Schedule(std::function<void()> fnTask,
|
||||
hlpr::flags<EScheduleFlags> flags /*= 0*/)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxQueueAccess);
|
||||
|
||||
// Get a thread - either from the idle queue or new.
|
||||
std::list<std::shared_ptr<CThread>>::iterator itThread = m_lstThreads.end();
|
||||
typename std::list<std::shared_ptr<CThread>>::iterator itThread = m_lstThreads.end();
|
||||
if (m_queueIdleThreads.empty())
|
||||
{
|
||||
// No thread is available. Allowed to make one?
|
||||
@@ -77,7 +87,8 @@ bool CTaskScheduler::Schedule(std::function<void()> fnTask, hlpr::flags<ESchedul
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTaskScheduler::WaitForExecution()
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline void CTaskScheduler<TThread, nMinIdle, nMaxBusy>::WaitForExecution()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxQueueAccess);
|
||||
|
||||
@@ -111,31 +122,37 @@ void CTaskScheduler::WaitForExecution()
|
||||
m_nMinIdle = nMinIdleTemp;
|
||||
}
|
||||
|
||||
size_t CTaskScheduler::GetThreadCount() const
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline size_t CTaskScheduler<TThread, nMinIdle, nMaxBusy>::GetThreadCount() const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxQueueAccess);
|
||||
return m_lstThreads.size();
|
||||
}
|
||||
|
||||
size_t CTaskScheduler::GetMaxThreadCount() const
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline size_t CTaskScheduler<TThread, nMinIdle, nMaxBusy>::GetMaxThreadCount() const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxQueueAccess);
|
||||
return m_nMaxThreads;
|
||||
}
|
||||
|
||||
size_t CTaskScheduler::GetBusyThreadCount() const
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline size_t CTaskScheduler<TThread, nMinIdle, nMaxBusy>::GetBusyThreadCount() const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxQueueAccess);
|
||||
return m_lstThreads.size() - m_queueIdleThreads.size();
|
||||
}
|
||||
|
||||
size_t CTaskScheduler::GetIdleThreadCount() const
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline size_t CTaskScheduler<TThread, nMinIdle, nMaxBusy>::GetIdleThreadCount() const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mtxQueueAccess);
|
||||
return m_queueIdleThreads.size();
|
||||
}
|
||||
|
||||
void CTaskScheduler::Execute(std::list<std::shared_ptr<CThread>>::iterator itThread, std::function<void()> fnTask)
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline void CTaskScheduler<TThread, nMinIdle, nMaxBusy>::Execute(typename std::list<std::shared_ptr<CThread>>::iterator itThread,
|
||||
std::function<void()> fnTask)
|
||||
{
|
||||
std::shared_ptr<CThread>& rptrThread = *itThread;
|
||||
|
||||
@@ -176,16 +193,18 @@ void CTaskScheduler::Execute(std::list<std::shared_ptr<CThread>>::iterator itThr
|
||||
});
|
||||
}
|
||||
|
||||
CTaskScheduler::CThread::CThread()
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline CTaskScheduler<TThread, nMinIdle, nMaxBusy>::CThread::CThread()
|
||||
{
|
||||
// Wait for the start
|
||||
std::unique_lock<std::mutex> lockStart(m_mtxSyncStart);
|
||||
m_thread = std::thread(&CThread::ThreadFunc, this);
|
||||
m_thread = TThread(&CThread::ThreadFunc, this);
|
||||
while (!m_bStarted)
|
||||
m_cvStarted.wait_for(lockStart, std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
CTaskScheduler::CThread::~CThread()
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline CTaskScheduler<TThread, nMinIdle, nMaxBusy>::CThread::~CThread()
|
||||
{
|
||||
// Lock to prevent execution still to take place. Then shutdown.
|
||||
std::unique_lock<std::mutex> lock(m_mtxSyncExecute);
|
||||
@@ -196,7 +215,8 @@ CTaskScheduler::CThread::~CThread()
|
||||
m_thread.join();
|
||||
}
|
||||
|
||||
void CTaskScheduler::CThread::Execute(std::function<void()> fnTask)
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline void CTaskScheduler<TThread, nMinIdle, nMaxBusy>::CThread::Execute(std::function<void()> fnTask)
|
||||
{
|
||||
// Assign the task and notify for execution.
|
||||
std::unique_lock<std::mutex> lock(m_mtxSyncExecute);
|
||||
@@ -205,7 +225,8 @@ void CTaskScheduler::CThread::Execute(std::function<void()> fnTask)
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
void CTaskScheduler::CThread::ThreadFunc()
|
||||
template <class TThread, size_t nMinIdle, size_t nMaxBusy>
|
||||
inline void CTaskScheduler<TThread, nMinIdle, nMaxBusy>::CThread::ThreadFunc()
|
||||
{
|
||||
// Thread has started (needed, since the condition variable doesn't keep its state).
|
||||
m_bStarted = true;
|
||||
@@ -232,3 +253,5 @@ void CTaskScheduler::CThread::ThreadFunc()
|
||||
m_fnTask = {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined SCHEDULER_INL
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
/**
|
||||
* @brief trace fifo open flags
|
||||
|
||||
114
global/unique_id.h
Normal file
114
global/unique_id.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef UNIQUE_ID_H
|
||||
#define UNIQUE_ID_H
|
||||
|
||||
#include <set>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
|
||||
/**
|
||||
* @brief Create a unique ID using the random number generator.
|
||||
* @tparam TType Type of the variable that represents the ID.
|
||||
* @tparam nDepth The depth of the ID generation in bits.
|
||||
*/
|
||||
template <typename TType = uint64_t, size_t nDepth = sizeof(TType) * 8>
|
||||
class CUniqueID
|
||||
{
|
||||
public:
|
||||
static_assert(nDepth <= sizeof(TType) * 8);
|
||||
static_assert(nDepth > 0);
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CUniqueID()
|
||||
{
|
||||
std::srand(static_cast<unsigned int>(std::time(nullptr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate a unique ID.
|
||||
* @return The optional result with the ID if successful or 0 when not successful.
|
||||
*/
|
||||
TType Generate()
|
||||
{
|
||||
// Create a number with the supplied bit amount.
|
||||
auto fnCreate = [](size_t nMaxDepth)
|
||||
{
|
||||
TType tNumber{};
|
||||
|
||||
// Create a new number
|
||||
size_t nBitsFilled = 0;
|
||||
while (nBitsFilled < nMaxDepth)
|
||||
{
|
||||
size_t nBitsToShiftIn = std::min(nMaxDepth - nBitsFilled, m_nRandMaxBits);
|
||||
tNumber = (tNumber << nBitsToShiftIn) | static_cast<TType>(static_cast<size_t>(std::rand()) & ((1u << nBitsToShiftIn) - 1));
|
||||
nBitsFilled += nBitsToShiftIn;
|
||||
}
|
||||
return tNumber;
|
||||
};
|
||||
|
||||
// Treat a depth of 48 bits and more separately
|
||||
if constexpr (nDepth >= 48)
|
||||
{
|
||||
// Combination of the time in seconds (22 bits only - can hold 48 days).
|
||||
return (static_cast<TType>(std::time(nullptr)) << (nDepth - 22)) | fnCreate(nDepth - 22);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum iterations is 10000 for less than 24 bits and otherwise unlimited (value 0)
|
||||
size_t nMaxIterations = nDepth < 24 ? 10000u : 0u;
|
||||
|
||||
// Generate
|
||||
size_t nCnt = 0;
|
||||
while (!nMaxIterations || (++nCnt < nMaxIterations))
|
||||
{
|
||||
TType tID = fnCreate(nDepth);
|
||||
|
||||
// Check whether not 0 and not generated already
|
||||
if (tID && (m_setUsedNumbers.find(tID) == m_setUsedNumbers.end()))
|
||||
{
|
||||
m_setUsedNumbers.insert(tID);
|
||||
return tID;
|
||||
}
|
||||
}
|
||||
|
||||
// No ID found
|
||||
return TType{};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Recursive constexpr function to find the number of bits needed to hold the number.
|
||||
* @param uiNumber The number to check for.
|
||||
* @return The amount of bits needed to hold the number.
|
||||
*/
|
||||
static constexpr size_t GetBitWidth(uint64_t uiNumber)
|
||||
{
|
||||
return (!uiNumber) ? 0u : 1u + GetBitWidth(uiNumber >> 1);
|
||||
}
|
||||
|
||||
/// The bits needed to hold the random number
|
||||
static constexpr size_t m_nRandMaxBits = GetBitWidth(static_cast<uint64_t>(RAND_MAX));
|
||||
|
||||
// Static assertion to verify at compile-time
|
||||
static_assert(m_nRandMaxBits > 0, "RAND_MAX bits must be greater than 0");
|
||||
|
||||
std::set<TType> m_setUsedNumbers; ///< Numbers generated previously already (numbers < 48 bits only).
|
||||
};
|
||||
|
||||
#endif // !defined UNIQUE_ID_H
|
||||
@@ -60,12 +60,22 @@ MAKE_ERROR_MSG(-134, CONFIG_SERVICE_ACCESS_ERROR, "Configuration service is not
|
||||
MAKE_ERROR_MSG(-135, COMMUNICATION_CONTROL_SERVICE_ACCESS_ERROR, "Communication control service is not accessible.", "The communication control service service could not be accessed.")
|
||||
MAKE_ERROR_MSG(-136, APP_CONTROL_SERVICE_ACCESS_ERROR, "Application control service is not accessible.", "The application control service could not be accessed.")
|
||||
MAKE_ERROR_MSG(-170, CANNOT_FIND_OBJECT, "The object cannot be found.", "A search for an object with supplied name was not successful.")
|
||||
MAKE_ERROR_MSG(-180, CANNOT_LOAD_SETTINGS, "The system settings cannot be loaded.", "For a specific instance, the system settings cannot be loaded.")
|
||||
MAKE_ERROR_MSG(-180, CANNOT_SAVE_SETTINGS, "The system settings cannot be saved.", "For a specific instance, the system settings cannot be saved.")
|
||||
MAKE_ERROR_MSG(-181, PROCESS_LISTENER_CONFIG_ERROR, "The listener configuration contains errors.", "The listener configuration contains errors and cannot be processed.")
|
||||
MAKE_ERROR_MSG(-182, PROCESS_CONNECTION_CONFIG_ERROR, "The connection configuration contains errors.", "The connection configuration contains errors and cannot be processed.")
|
||||
MAKE_ERROR_MSG(-183, ADD_LISTENER_ERROR, "Failed to add a listener to the system settings.", "The listener configuration could not be added to the system settings. This might be caused by a duplicate listener configuration.")
|
||||
MAKE_ERROR_MSG(-184, REMOVE_LISTENER_ERROR, "Failed to remove a listener from the system settings.", "The listener configuration could not be removed from the system settings. This might be caused by a missing listener configuration.")
|
||||
MAKE_ERROR_MSG(-185, SHOW_LISTENER_ERROR, "Failed to request the listener configuration from the system settings.", "The listener configuration could not be requested. This might be caused by a missing listener configuration.")
|
||||
MAKE_ERROR_MSG(-186, ADD_CONNECTION_ERROR, "Failed to add a connection to the system settings.", "The connection configuration could not be added to the system settings. This might be caused by a duplicate connection configuration.")
|
||||
MAKE_ERROR_MSG(-187, REMOVE_CONNECTION_ERROR, "Failed to remove a connection from the system settings.", "The connection configuration could not be removed from the system settings. This might be caused by a missing connection configuration.")
|
||||
MAKE_ERROR_MSG(-188, SHOW_CONNECTION_ERROR, "Failed to request the connection configuration from the system settings.", "The connection configuration could not be requested. This might be caused by a missing connection configuration.")
|
||||
|
||||
|
||||
////////// LOCAL APP CONTROL ERROR CODES ////////////
|
||||
|
||||
MAKE_ERROR_MSG(-204, APP_CONTROL_STARTUP_ERROR, "Cannot start application control.", "Application control start was initiated, but returned an error.")
|
||||
MAKE_ERROR_MSG(-205, APP_CONTROL_START_LOOP_FAIELD, "Starting the running loop failed.", "Failed to enter the processing loop for a server application.")
|
||||
MAKE_ERROR_MSG(-205, APP_CONTROL_START_LOOP_FAILED, "Starting the running loop failed.", "Failed to enter the processing loop for a server application.")
|
||||
MAKE_ERROR_MSG(-206, APP_CONTROL_DUPLICATE_INSTANCE, "Another process with specified instance is already running.", "Another core process initiated the application control with the same instance. Only one core process per instance is allowed.")
|
||||
MAKE_ERROR_MSG(-210, APP_CONTROL_INVALID_ISOLATION_CONFIG, "An invalid isolation configuration was supplied.", "The application control configuration section contains an invalid isolation configuration.")
|
||||
MAKE_ERROR_MSG(-218, SETTING_FILE_VERSION_INVALID, "Settings file has an invalid version.", "Settings file contains an invalid/incompatible version number.")
|
||||
|
||||
@@ -25,7 +25,7 @@ add_executable(sdv_control
|
||||
"startup_shutdown.h"
|
||||
"startup_shutdown.cpp"
|
||||
"context.h"
|
||||
"print_table.h" "start_stop_service.cpp" "start_stop_service.h" "installation.h" "installation.cpp")
|
||||
"print_table.h" "start_stop_service.cpp" "start_stop_service.h" "installation.h" "installation.cpp" "connection_config.h" "connection_config.cpp")
|
||||
|
||||
target_link_libraries(sdv_control ${CMAKE_DL_LIBS})
|
||||
|
||||
|
||||
471
sdv_executables/sdv_control/connection_config.cpp
Normal file
471
sdv_executables/sdv_control/connection_config.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#include "connection_config.h"
|
||||
#include "../../global/cmdlnparser/cmdlnparser.h"
|
||||
#include <support/toml.h>
|
||||
#include <interfaces/app.h>
|
||||
#include "../error_msg.h"
|
||||
#include <charconv>
|
||||
|
||||
void ListenerHelp(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "LISTENER"
|
||||
if (rsContext.seqCmdLine.size() < 1)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: missing listener command..." << std::endl;
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "LISTENER"))
|
||||
{
|
||||
CCommandLine::PrintHelpText(std::cout,
|
||||
"Usage: sdv_control LISTENER ADD <name> <provider> <parameters...> [options...]\n"
|
||||
" sdv_control LISTENER REMOVE <name> [options...]\n"
|
||||
" sdv_control LISTENER SHOW <name> [options...]\n\n"
|
||||
"Configure the system to add (or update) or remove a listener. The command doesn't check for valid parameters. A "
|
||||
"server restart is required for the new listener settings to take effect.\n\n"
|
||||
"A list of actively configured listeners can be requested by executing \"sdv_control LIST LISTENERS\"\n\n"
|
||||
"Note: if not explicitly added, a default listener will added to the list for the communication between isolated "
|
||||
"applications and the core system.\n\n");
|
||||
return;
|
||||
}
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: invalid listener command..." << std::endl;
|
||||
}
|
||||
|
||||
void ConnectionHelp(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "CONNECTION"
|
||||
if (rsContext.seqCmdLine.size() < 1)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: missing connection command..." << std::endl;
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "CONNECTION"))
|
||||
{
|
||||
CCommandLine::PrintHelpText(std::cout,
|
||||
"Usage: sdv_control CONNECTION ADD <name> <provider> <parameters...> [options...]\n"
|
||||
" sdv_control CONNECTION REMOVE <name> [options...]\n"
|
||||
" sdv_control CONNECTION SHOW <name> [options...]\n\n"
|
||||
"Configure the system to add (or update) or remove a connection. The command doesn't check for valid parameters. A "
|
||||
"server restart is required for the new connection settings to take effect.\n\n"
|
||||
"A list of actively configured connections can be requested by executing \"sdv_control LIST CONNECTIONS\"\n\n"
|
||||
"Note: if not explicitly added, a default connetion will be added to the list for the communication between external "
|
||||
"applications and the core system.\n\n"
|
||||
"Options:\n"
|
||||
" --insert_before<string> With ADD, Insert the connection before an existing connection with the supplied name.\n\n");
|
||||
return;
|
||||
}
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: invalid connection command..." << std::endl;
|
||||
}
|
||||
|
||||
int ConfigureListener(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "CONNECTION"
|
||||
if (rsContext.seqCmdLine.size() < 2)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listener command... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
if (!iequals(rsContext.seqCmdLine[0], "LISTENER"))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid command: " << rsContext.seqCmdLine[0] << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Which list command is requested
|
||||
enum class ECommand { unknown, add, remove, show } eCommand = ECommand::unknown;
|
||||
if (iequals(rsContext.seqCmdLine[1], "ADD")) eCommand = ECommand::add;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "REMOVE")) eCommand = ECommand::remove;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "SHOW")) eCommand = ECommand::show;
|
||||
else
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
{
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid listener command." << std::endl;
|
||||
ListenerHelp(rsContext);
|
||||
}
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
if (rsContext.seqCmdLine.size() < 3)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listener name... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Get the name
|
||||
std::string ssListener = rsContext.seqCmdLine[2];
|
||||
|
||||
switch (eCommand)
|
||||
{
|
||||
case ECommand::remove:
|
||||
return RemoveListener(ssListener, rsContext);
|
||||
case ECommand::show:
|
||||
return ShowListenerConfig(ssListener, rsContext);
|
||||
case ECommand::add:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// For add, check for provider and parameters
|
||||
if (rsContext.seqCmdLine.size() < 4)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listener provider... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
std::string ssProvider = rsContext.seqCmdLine[3];
|
||||
|
||||
sdv::toml::CTOMLParser parser;
|
||||
parser.AddValue("Provider.Name", ssProvider);
|
||||
|
||||
// Check for parameters
|
||||
// Parameters have the format "param=value". It is possible that parameters have additional sub-tables. Then the format is:
|
||||
// "table.param=value".
|
||||
sdv::toml::CNodeCollection ipc_channel_table = parser.AddTable("IpcChannel");
|
||||
for (size_t nIndex = 4; nIndex < rsContext.seqCmdLine.size(); nIndex++)
|
||||
{
|
||||
std::string ssRawParam = rsContext.seqCmdLine[nIndex];
|
||||
|
||||
// Search for the equal sign
|
||||
size_t nEqualPos = ssRawParam.find_first_of('=');
|
||||
std::string ssParamName = ssRawParam.substr(0, nEqualPos);
|
||||
while (!ssParamName.empty() && std::isspace(ssParamName.back()))
|
||||
ssParamName.pop_back();
|
||||
if (ssParamName.empty() || nEqualPos == std::string::npos)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid listener parameter: " << ssRawParam << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
sdv::any_t anyValue;
|
||||
size_t nValuePos = nEqualPos + 1;
|
||||
while (nValuePos < ssRawParam.size() && std::isspace(ssRawParam[nValuePos]))
|
||||
nValuePos++;
|
||||
if (nValuePos < ssRawParam.size())
|
||||
{
|
||||
std::string ssValue = ssRawParam.substr(nValuePos);
|
||||
if (!ssValue.empty() && ssValue.find_first_not_of("-0123456789") == std::string::npos)
|
||||
{
|
||||
int64_t iValue = 0;
|
||||
if (std::from_chars(ssValue.data(), ssValue.data() + ssValue.size(), iValue).ec == std::errc())
|
||||
anyValue = iValue;
|
||||
else
|
||||
anyValue = ssValue;
|
||||
}
|
||||
else
|
||||
anyValue = ssValue;
|
||||
|
||||
}
|
||||
ipc_channel_table.AddValue(ssParamName, anyValue);
|
||||
}
|
||||
|
||||
return AddListener(ssListener, parser.GetTOML(), rsContext);
|
||||
}
|
||||
|
||||
int AddListener(const std::string& rssListener, const std::string& rssConfig, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Add the listener
|
||||
if (!pAppConnections->AddListenerConfig(rssListener, rssConfig))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << ADD_LISTENER_ERROR_MSG << std::endl;
|
||||
return ADD_LISTENER_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int RemoveListener(const std::string& rssListener, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the listener
|
||||
if (!pAppConnections->RemoveListenerConfig(rssListener))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << REMOVE_LISTENER_ERROR_MSG << std::endl;
|
||||
return REMOVE_LISTENER_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ShowListenerConfig(const std::string& rssListener, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the listener
|
||||
std::string ssConfig = pAppConnections->GetListenerConfig(rssListener);
|
||||
if (ssConfig.empty())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << SHOW_LISTENER_ERROR_MSG << std::endl;
|
||||
return SHOW_LISTENER_ERROR;
|
||||
}
|
||||
|
||||
std::cout << ssConfig << std::endl;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ConfigureConnection(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "CONNECTION"
|
||||
if (rsContext.seqCmdLine.size() < 2)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing connection command... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
if (!iequals(rsContext.seqCmdLine[0], "CONNECTION"))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid command: " << rsContext.seqCmdLine[0] << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Which list command is requested
|
||||
enum class ECommand { unknown, add, remove, show } eCommand = ECommand::unknown;
|
||||
if (iequals(rsContext.seqCmdLine[1], "ADD")) eCommand = ECommand::add;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "REMOVE")) eCommand = ECommand::remove;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "SHOW")) eCommand = ECommand::show;
|
||||
else
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
{
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid connection command." << std::endl;
|
||||
ConnectionHelp(rsContext);
|
||||
}
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
if (rsContext.seqCmdLine.size() < 3)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing connection name... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Get the name
|
||||
std::string ssConnection = rsContext.seqCmdLine[2];
|
||||
|
||||
switch (eCommand)
|
||||
{
|
||||
case ECommand::remove:
|
||||
return RemoveConnection(ssConnection, rsContext);
|
||||
case ECommand::show:
|
||||
return ShowConnectionConfig(ssConnection, rsContext);
|
||||
case ECommand::add:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// For add, check for provider and parameters
|
||||
if (rsContext.seqCmdLine.size() < 4)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing connection provider... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
std::string ssProvider = rsContext.seqCmdLine[3];
|
||||
|
||||
sdv::toml::CTOMLParser parser;
|
||||
parser.AddValue("Provider.Name", ssProvider);
|
||||
|
||||
// Check for parameters
|
||||
// Parameters have the format "param=value". It is possible that parameters have additional sub-tables. Then the format is:
|
||||
// "table.param=value".
|
||||
sdv::toml::CNodeCollection ipc_channel_table = parser.AddTable("IpcChannel");
|
||||
for (size_t nIndex = 4; nIndex < rsContext.seqCmdLine.size(); nIndex++)
|
||||
{
|
||||
std::string ssRawParam = rsContext.seqCmdLine[nIndex];
|
||||
|
||||
// Search for the equal sign
|
||||
size_t nEqualPos = ssRawParam.find_first_of('=');
|
||||
std::string ssParamName = ssRawParam.substr(0, nEqualPos);
|
||||
while (!ssParamName.empty() && std::isspace(ssParamName.back()))
|
||||
ssParamName.pop_back();
|
||||
if (ssParamName.empty() || nEqualPos == std::string::npos)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid listener parameter: " << ssRawParam << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
sdv::any_t anyValue;
|
||||
size_t nValuePos = nEqualPos + 1;
|
||||
while (nValuePos < ssRawParam.size() && std::isspace(ssRawParam[nValuePos]))
|
||||
nValuePos++;
|
||||
if (nValuePos < ssRawParam.size())
|
||||
{
|
||||
std::string ssValue = ssRawParam.substr(nValuePos);
|
||||
if (!ssValue.empty() && ssValue.find_first_not_of("-0123456789") == std::string::npos)
|
||||
{
|
||||
int64_t iValue = 0;
|
||||
if (std::from_chars(ssValue.data(), ssValue.data() + ssValue.size(), iValue).ec == std::errc())
|
||||
anyValue = iValue;
|
||||
else
|
||||
anyValue = ssValue;
|
||||
}
|
||||
else
|
||||
anyValue = ssValue;
|
||||
|
||||
}
|
||||
ipc_channel_table.AddValue(ssParamName, anyValue);
|
||||
}
|
||||
|
||||
return AddConnection(ssConnection, parser.GetTOML(), rsContext);
|
||||
}
|
||||
|
||||
int AddConnection(const std::string& rssConnection, const std::string& rssConfig, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Add the connection
|
||||
if (!pAppConnections->AddConnectionConfig(rssConnection, rssConfig, rsContext.ssInsertBeforeConnection))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << ADD_CONNECTION_ERROR_MSG << std::endl;
|
||||
return ADD_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int RemoveConnection(const std::string& rssConnection, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the connection
|
||||
if (!pAppConnections->RemoveConnectionConfig(rssConnection))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << REMOVE_CONNECTION_ERROR_MSG << std::endl;
|
||||
return REMOVE_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ShowConnectionConfig(const std::string& rssConnection, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the connection
|
||||
std::string ssConfig = pAppConnections->GetConnectionConfig(rssConnection);
|
||||
if (ssConfig.empty())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << SHOW_CONNECTION_ERROR_MSG << std::endl;
|
||||
return SHOW_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
std::cout << ssConfig << std::endl;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
98
sdv_executables/sdv_control/connection_config.h
Normal file
98
sdv_executables/sdv_control/connection_config.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef CONNECTION_CONFIG_H
|
||||
#define CONNECTION_CONFIG_H
|
||||
|
||||
#include "context.h"
|
||||
#include <support/sequence.h>
|
||||
#include <support/string.h>
|
||||
|
||||
/**
|
||||
* @brief Help for configuring listeners.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
*/
|
||||
void ListenerHelp(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Help for configuring connections.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
*/
|
||||
void ConnectionHelp(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Configure the listener.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ConfigureListener(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Add a listener to the system settings.
|
||||
* @param[in] rssListener Reference to the string containing the listener configuration name.
|
||||
* @param[in] rssConfig Reference to the string containing the listener configuration.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int AddListener(const std::string& rssListener, const std::string& rssConfig, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Remove a listener from the system settings.
|
||||
* @param[in] rssListener Reference to the string containing the listener configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int RemoveListener(const std::string& rssListener, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Show a listener configuration.
|
||||
* @param[in] rssListener Reference to the string containing the listener configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ShowListenerConfig(const std::string& rssListener, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Configure the connection.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ConfigureConnection(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Add a connection to the system settings.
|
||||
* @param[in] rssConnection Reference to the string containing the connection configuration name.
|
||||
* @param[in] rssConfig Reference to the string containing the connection configuration.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int AddConnection(const std::string& rssConnection, const std::string& rssConfig, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Remove a connection from the system settings.
|
||||
* @param[in] rssConnection Reference to the string containing the connection configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int RemoveConnection(const std::string& rssConnection, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Show a connection configuration.
|
||||
* @param[in] rssConnection Reference to the string containing the connection configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ShowConnectionConfig(const std::string& rssConnection, const SContext& rsContext);
|
||||
|
||||
|
||||
#endif // !defined CONNECTION_CONFIG_H
|
||||
@@ -33,6 +33,7 @@ struct SContext
|
||||
bool bListShort = false; ///< Print only a shortened list with one column.
|
||||
sdv::sequence<sdv::u8string> seqCmdLine; ///< The commands provided on the command line.
|
||||
std::filesystem::path pathInstallDir; ///< Optional installation directory.
|
||||
std::string ssInsertBeforeConnection; ///< Insert before the provided connection
|
||||
};
|
||||
|
||||
#include <cctype> // std::tolower
|
||||
|
||||
@@ -88,7 +88,7 @@ int Install(const SContext& rsContext)
|
||||
ssName = rsContext.seqCmdLine[1];
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
#include "list_elements.h"
|
||||
#include "print_table.h"
|
||||
#include <interfaces/config.h>
|
||||
#include <interfaces/app.h>
|
||||
#include <support/sdv_core.h>
|
||||
#include <support/local_service_access.h>
|
||||
#include <support/toml.h>
|
||||
#include "../../global/cmdlnparser/cmdlnparser.h"
|
||||
#include "../../global/exec_dir_helper.h"
|
||||
#include "../../global/flags.h"
|
||||
@@ -38,13 +40,14 @@ void ListHelp(const SContext& rsContext)
|
||||
}
|
||||
|
||||
// Which list command help is requested
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, connections } eListCommand = EListCommand::unknown;
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, listeners, connections } eListCommand = EListCommand::unknown;
|
||||
if (rsContext.seqCmdLine.size() >= 2)
|
||||
{
|
||||
if (iequals(rsContext.seqCmdLine[1], "MODULES")) eListCommand = EListCommand::modules;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CLASSES")) eListCommand = EListCommand::classes;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "COMPONENTS")) eListCommand = EListCommand::components;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "INSTALLATIONS")) eListCommand = EListCommand::installations;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "LISTENERS")) eListCommand = EListCommand::listeners;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CONNECTIONS")) eListCommand = EListCommand::connections;
|
||||
}
|
||||
|
||||
@@ -65,20 +68,24 @@ void ListHelp(const SContext& rsContext)
|
||||
case EListCommand::installations:
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST INSTALLATIONS [options...]\n\nShow a list of all installations.\n");
|
||||
break;
|
||||
case EListCommand::listeners:
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST LISTENERS [options...]\n\nShow a list of all configured listeners.\n");
|
||||
break;
|
||||
case EListCommand::connections:
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST CONNECTIONS [options...]\n\nShow a list of all connected applications.\n");
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST CONNECTIONS [options...]\n\nShow a list of all configured connections.\n");
|
||||
break;
|
||||
default:
|
||||
CCommandLine::PrintHelpText(std::cout, R"code(Usage: sdv_control LIST <list_command> [options...]
|
||||
CCommandLine::PrintHelpText(std::cout, R"text(Usage: sdv_control LIST <list_command> [options...]
|
||||
|
||||
Supported listing commands:
|
||||
LIST MODULES Show a list of loaded server modules.
|
||||
LIST CLASSES Show a list of available component classes.
|
||||
LIST COMPONENTS Show a list of instantiated server components
|
||||
LIST INSTALLATIONS Show a list of installations.
|
||||
LIST LISTENERS Show a list of current listeners.
|
||||
LIST CONNECTIONS Show a list of current connections.
|
||||
|
||||
)code");
|
||||
)text");
|
||||
break;
|
||||
}
|
||||
std::cout << "Options:\n";
|
||||
@@ -103,33 +110,39 @@ int ListElements(const SContext& rsContext, std::ostream& rstream /*= std::cout*
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Which list command help is requested
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, connections } eListCommand = EListCommand::unknown;
|
||||
// Which list command is requested
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, listeners, connections } eListCommand = EListCommand::unknown;
|
||||
if (rsContext.seqCmdLine.size() >= 2)
|
||||
{
|
||||
if (iequals(rsContext.seqCmdLine[1], "MODULES")) eListCommand = EListCommand::modules;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CLASSES")) eListCommand = EListCommand::classes;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "COMPONENTS")) eListCommand = EListCommand::components;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "INSTALLATIONS")) eListCommand = EListCommand::installations;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "LISTENERS")) eListCommand = EListCommand::listeners;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CONNECTIONS")) eListCommand = EListCommand::connections;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
{
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listing command.." << std::endl << std::endl;
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listing command." << std::endl;
|
||||
ListHelp(rsContext);
|
||||
}
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
if (!ptrRepository)
|
||||
// Try to connect (except when listing the listeners and connections... they can be read from the settings).
|
||||
sdv::TObjectPtr ptrRepository;
|
||||
if (eListCommand != EListCommand::listeners && eListCommand != EListCommand::connections)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CONNECT_SDV_SERVER_ERROR_MSG << " Instance #" << rsContext.uiInstanceID << "." << std::endl;
|
||||
return CONNECT_SDV_SERVER_ERROR;
|
||||
ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CONNECT_SDV_SERVER_ERROR_MSG << " Instance #" << rsContext.uiInstanceID << "."
|
||||
<< std::endl;
|
||||
return CONNECT_SDV_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int iRet = -100;
|
||||
@@ -147,12 +160,16 @@ int ListElements(const SContext& rsContext, std::ostream& rstream /*= std::cout*
|
||||
case EListCommand::installations:
|
||||
iRet = ListInstallations(rsContext, ptrRepository, rstream);
|
||||
break;
|
||||
case EListCommand::listeners:
|
||||
iRet = ListListeners(rsContext, rstream);
|
||||
break;
|
||||
case EListCommand::connections:
|
||||
iRet = ListConnections(rsContext, ptrRepository, rstream);
|
||||
iRet = ListConnections(rsContext, rstream);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rstream << std::endl;
|
||||
return iRet;
|
||||
}
|
||||
|
||||
@@ -388,8 +405,107 @@ int ListInstallations(const SContext& rsContext, const sdv::TObjectPtr& rptrRepo
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ListConnections(const SContext& /*rsContext*/, const sdv::TObjectPtr& /*rptrRepository*/, std::ostream& /*rstream = std::cout */ )
|
||||
std::string BuildParameters(const sdv::toml::CNodeCollection& rtable, const std::string& ssPrefix = std::string())
|
||||
{
|
||||
std::cout << "ERROR: " << NOT_IMPLEMENTED_MSG << " :-(" << std::endl;
|
||||
return NOT_IMPLEMENTED;
|
||||
std::string ssParams;
|
||||
for (uint32_t uiIndex = 0; uiIndex < rtable.GetCount(); uiIndex++)
|
||||
{
|
||||
sdv::toml::CNode node = rtable.Get(uiIndex);
|
||||
if (!node) continue;
|
||||
std::string ssNodeText;
|
||||
if (node.GetType() == sdv::toml::ENodeType::node_table)
|
||||
{
|
||||
sdv::toml::CNodeCollection tableChild(node);
|
||||
if (!tableChild) continue;
|
||||
ssNodeText = BuildParameters(tableChild, static_cast<std::string>(tableChild.GetName()) + ".");
|
||||
}
|
||||
else if (node.GetType() == sdv::toml::ENodeType::node_array)
|
||||
{
|
||||
// TODO...
|
||||
}
|
||||
else
|
||||
ssNodeText = ssPrefix + node.GetName() + "=" + node.GetValueAsString();
|
||||
|
||||
// Add the text
|
||||
if (!ssParams.empty())
|
||||
ssParams += ", ";
|
||||
ssParams += ssNodeText;
|
||||
}
|
||||
return ssParams;
|
||||
}
|
||||
|
||||
int ListListeners(const SContext& rsContext, std::ostream& rstream /*= std::cout */ )
|
||||
{
|
||||
std::vector<std::array<std::string, 3>> vecListenerList;
|
||||
vecListenerList.push_back({"Listener", "Provider", "Parameters"});
|
||||
|
||||
// Request the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
auto seqListeners = pAppConnections->GetListeners();
|
||||
for (const sdv::u8string& rssListener : seqListeners)
|
||||
{
|
||||
std::string ssListener = rssListener;
|
||||
auto ssConfig = pAppConnections->GetListenerConfig(rssListener);
|
||||
sdv::toml::CTOMLParser parser(ssConfig);
|
||||
if (!parser)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << PROCESS_LISTENER_CONFIG_ERROR_MSG << std::endl;
|
||||
return PROCESS_LISTENER_CONFIG_ERROR;
|
||||
}
|
||||
std::string ssProvider = parser.GetDirect("Provider.Name").GetValueAsString();
|
||||
std::string ssParams = BuildParameters(parser.GetDirect("IpcChannel"));
|
||||
vecListenerList.push_back({ssListener, ssProvider, ssParams});
|
||||
}
|
||||
|
||||
PrintTable(vecListenerList, rstream, rsContext.bListNoHdr);
|
||||
if (vecListenerList.size() < 2)
|
||||
rstream << " No listeners configured!" << std::endl;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ListConnections(const SContext& rsContext, std::ostream& rstream /*= std::cout */ )
|
||||
{
|
||||
std::vector<std::array<std::string, 3>> vecConnectionList;
|
||||
vecConnectionList.push_back({"Connection", "Provider", "Parameters"});
|
||||
|
||||
// Request the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
auto seqConnections = pAppConnections->GetConnections();
|
||||
for (const sdv::u8string& rssConnection : seqConnections)
|
||||
{
|
||||
std::string ssConnection = rssConnection;
|
||||
auto ssConfig = pAppConnections->GetConnectionConfig(rssConnection);
|
||||
sdv::toml::CTOMLParser parser(ssConfig);
|
||||
if (!parser)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << PROCESS_CONNECTION_CONFIG_ERROR_MSG << std::endl;
|
||||
return PROCESS_CONNECTION_CONFIG_ERROR;
|
||||
}
|
||||
std::string ssProvider = parser.GetDirect("Provider.Name").GetValueAsString();
|
||||
std::string ssParams = BuildParameters(parser.GetDirect("IpcChannel"));
|
||||
vecConnectionList.push_back({ssConnection, ssProvider, ssParams});
|
||||
}
|
||||
|
||||
PrintTable(vecConnectionList, rstream, rsContext.bListNoHdr);
|
||||
if (vecConnectionList.size() < 2)
|
||||
rstream << " No connections configured!" << std::endl;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -71,12 +71,19 @@ int ListComponents(const SContext& rsContext, const sdv::TObjectPtr& rptrReposit
|
||||
int ListInstallations(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream);
|
||||
|
||||
/**
|
||||
* @brief List the current connections.
|
||||
* @brief List the current configured listeners.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @param[in] rptrRepository Reference to the saerver repository.
|
||||
* @param[in] rstream The output stream to use for printing (table only).
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ListConnections(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream);
|
||||
int ListListeners(const SContext& rsContext, std::ostream& rstream);
|
||||
|
||||
/**
|
||||
* @brief List the current connections.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @param[in] rstream The output stream to use for printing (table only).
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ListConnections(const SContext& rsContext, std::ostream& rstream);
|
||||
|
||||
#endif // !defined LIST_ELEMENTS_H
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "list_elements.h"
|
||||
#include "start_stop_service.h"
|
||||
#include "installation.h"
|
||||
#include "connection_config.h"
|
||||
#include "../error_msg.h"
|
||||
|
||||
/**
|
||||
@@ -53,12 +54,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
SContext sContext;
|
||||
bool bError = false;
|
||||
@@ -67,24 +62,40 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
std::string ssArgError;
|
||||
try
|
||||
{
|
||||
auto& rArgHelpDef = cmdln.DefineOption("?", bHelp, "Show help. Use <COMMAND> --help for specific help on the command.");
|
||||
// Argument groups 1 - 10:
|
||||
// STARTUP
|
||||
// SHUTDOWN
|
||||
// LIST
|
||||
// INSTALL
|
||||
// UPDATE
|
||||
// UNINSTALL
|
||||
// START
|
||||
// STOP
|
||||
// LISTENER
|
||||
// CONNECTION
|
||||
auto& rArgHelpDef =
|
||||
cmdln.DefineOption("?", bHelp, "Show help. Use <COMMAND> --help for specific help on the command.");
|
||||
rArgHelpDef.AddSubOptionName("help");
|
||||
auto& rArgSilentDef = cmdln.DefineOption("s", sContext.bSilent, "Do not show any information on std::cout. Not compatible with 'verbose'.");
|
||||
auto& rArgSilentDef = cmdln.DefineOption("s", sContext.bSilent, "Do not show any information on std::cout. Not compatible "
|
||||
"with 'verbose'.");
|
||||
rArgSilentDef.AddSubOptionName("silent");
|
||||
auto& rArgVerboseDef = cmdln.DefineOption("v", sContext.bVerbose, "Provide verbose information. Not compatible with 'silent'.");
|
||||
auto& rArgVerboseDef = cmdln.DefineOption("v", sContext.bVerbose, "Provide verbose information. Not compatible with "
|
||||
"'silent'.");
|
||||
rArgVerboseDef.AddSubOptionName("verbose");
|
||||
cmdln.DefineSubOption("version", bVersion, "Show version information.");
|
||||
cmdln.DefineSubOption("instance", sContext.uiInstanceID, "The instance ID of the SDV instance (default ID is 1000).");
|
||||
cmdln.DefineSubOption("server_silent", sContext.bServerSilent, "Only used with STARTUP command: Server is started using "
|
||||
"silent option. Not compatible with 'server_verbose'.");
|
||||
"silent option. Not compatible with 'server_verbose'.", true, 1);
|
||||
cmdln.DefineSubOption("server_verbose", sContext.bServerVerbose, "Only used with STARTUP command: Server is started using "
|
||||
"verbose option. Not compatible with 'server_silent'.");
|
||||
"verbose option. Not compatible with 'server_silent'.", true, 1);
|
||||
cmdln.DefineSubOption("install_dir", sContext.pathInstallDir, "Only used with STARTUP command: Installation directory "
|
||||
"(absolute or relative to the sdv_core executable).");
|
||||
"(absolute or relative to the sdv_core executable).", true, 1);
|
||||
cmdln.DefineSubOption("no_header", sContext.bListNoHdr, "Only used with LIST command: Do not print a header for the "
|
||||
"listing table.");
|
||||
"listing table.", true, 3);
|
||||
cmdln.DefineSubOption("short", sContext.bListShort, "Only used with LIST command: Print only the most essential "
|
||||
"information as one column.");
|
||||
"information as one column.", true, 3);
|
||||
cmdln.DefineSubOption(
|
||||
"insert_before", sContext.ssInsertBeforeConnection, "Name of the connection to insert before.", true, 10);
|
||||
cmdln.DefineDefaultArgument(sContext.seqCmdLine, "COMMAND");
|
||||
|
||||
cmdln.Parse(static_cast<size_t>(iArgc), rgszArgv);
|
||||
@@ -98,7 +109,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!sContext.bSilent)
|
||||
{
|
||||
std::cout << "SDV Server Control Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
@@ -113,7 +124,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
bError = true;
|
||||
}
|
||||
|
||||
enum class ECommand { unknown, startup, shutdown, list, install, update, uninstall, start, stop } eCommand = ECommand::unknown;
|
||||
enum class ECommand { unknown, startup, shutdown, list, install, update, uninstall, start, stop, listener, connection } eCommand = ECommand::unknown;
|
||||
if (!sContext.seqCmdLine.empty())
|
||||
{
|
||||
if (iequals(sContext.seqCmdLine[0], "STARTUP")) eCommand = ECommand::startup;
|
||||
@@ -124,6 +135,8 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
else if (iequals(sContext.seqCmdLine[0], "UNINSTALL")) eCommand = ECommand::uninstall;
|
||||
else if (iequals(sContext.seqCmdLine[0], "START")) eCommand = ECommand::start;
|
||||
else if (iequals(sContext.seqCmdLine[0], "STOP")) eCommand = ECommand::stop;
|
||||
else if (iequals(sContext.seqCmdLine[0], "LISTENER")) eCommand = ECommand::listener;
|
||||
else if (iequals(sContext.seqCmdLine[0], "CONNECTION")) eCommand = ECommand::connection;
|
||||
else
|
||||
{
|
||||
if (!sContext.bSilent)
|
||||
@@ -157,17 +170,25 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
case ECommand::uninstall:
|
||||
InstallationHelp(sContext);
|
||||
break;
|
||||
case ECommand::listener:
|
||||
ListenerHelp(sContext);
|
||||
break;
|
||||
case ECommand::connection:
|
||||
ConnectionHelp(sContext);
|
||||
break;
|
||||
default:
|
||||
cmdln.PrintHelp(std::cout, R"code(Supported commands:
|
||||
STARTUP Start the core application server
|
||||
SHUTDOWN Stop the core application server
|
||||
LIST List module/classes/component/installation/connection information.
|
||||
INSTALL Install a new application or service.
|
||||
UPDATE Update an existing installation.
|
||||
UNINSTALL Uninstall an installed application or service.
|
||||
START Start a service (complex services only).
|
||||
STOP Stop a service (complex services only).
|
||||
)code");
|
||||
cmdln.PrintHelp(std::cout, R"text(Supported commands:
|
||||
STARTUP Start the core application server
|
||||
SHUTDOWN Stop the core application server
|
||||
LIST List information about modules/classes/components/installations/listeners/connections.
|
||||
INSTALL Install a new application or service.
|
||||
UPDATE Update an existing installation.
|
||||
UNINSTALL Uninstall an installed application or service.
|
||||
START Start a service (complex services and vehicle functions only).
|
||||
STOP Stop a service (complex services and vehicle functions only).
|
||||
LISTENER Add or remove a communication listener configuration.
|
||||
CONNECTION Add or remove a connection configuration.
|
||||
)text");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -185,11 +206,11 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (sContext.bVerbose)
|
||||
std::cout << "Starting local application control.." << std::endl;
|
||||
sdv::app::CAppControl appcontrol;
|
||||
std::string ssAppConfig = std::string(R"code(
|
||||
std::string ssAppConfig = std::string(R"toml(
|
||||
[Application]
|
||||
Mode = "Maintenance"
|
||||
Instance = )code") + std::to_string(sContext.uiInstanceID) + R"code(
|
||||
)code";
|
||||
Instance = )toml") + std::to_string(sContext.uiInstanceID) + R"toml(
|
||||
)toml";
|
||||
if (!appcontrol.Startup(ssAppConfig))
|
||||
{
|
||||
if (!sContext.bSilent)
|
||||
@@ -224,6 +245,12 @@ Instance = )code") + std::to_string(sContext.uiInstanceID) + R"code(
|
||||
case ECommand::uninstall:
|
||||
iRet = Uninstall(sContext);
|
||||
break;
|
||||
case ECommand::listener:
|
||||
iRet = ConfigureListener(sContext);
|
||||
break;
|
||||
case ECommand::connection:
|
||||
iRet = ConfigureConnection(sContext);
|
||||
break;
|
||||
default:
|
||||
std::cout << "Command missing :-(" << std::endl;
|
||||
break;
|
||||
|
||||
@@ -35,8 +35,8 @@ void StartStopServiceHelp(const SContext& rsContext)
|
||||
" sdv_control START <class> <name> [options...]\n\n"
|
||||
"Start a complex service with the supplied object name as is defined in the configuration (first usage) or the "
|
||||
"supplied class name and with object name assignment and add to the configuration (second usage).\n"
|
||||
"Only complex services can be started. If the service depends on not running other services, these are started as "
|
||||
"well.\n\n");
|
||||
"Only vehicle functions and complex services can be started. If the service depends on not running other services, "
|
||||
"these are started as well.\n\n");
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "STOP"))
|
||||
@@ -47,15 +47,14 @@ void StartStopServiceHelp(const SContext& rsContext)
|
||||
" sdv_control STOP <module> [options...]\n\n"
|
||||
"Stop the complex service(s) with the supplied object name (first usage), with supplied object ID (second usage), with "
|
||||
"supplied class name (third usage) or contained in the module with the supplied module name (fourth usage).\n"
|
||||
"Only complex services can be stopped. Dependent services are stopped as well. If one of object to be stopped is not a "
|
||||
"complex service, the command fails.\n\n");
|
||||
"Only vehicle functions and complex services can be stopped. Dependent services are stopped as well. If one of object "
|
||||
"to be stopped is not a vehicle function or a complex service, the command fails.\n\n");
|
||||
return;
|
||||
}
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: invalid start/stop command..." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int StartService(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "START"
|
||||
@@ -88,7 +87,7 @@ int StartService(const SContext& rsContext)
|
||||
ssName = rsContext.seqCmdLine[1];
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
@@ -154,7 +153,7 @@ int StopService(const SContext& rsContext)
|
||||
ssName = rsContext.seqCmdLine[1];
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
|
||||
@@ -76,9 +76,9 @@ void StartupShutdownHelp(const SContext& rsContext)
|
||||
"Start the SDV server with the supplied instance ID. If no instance ID is supplied, use the default instance "
|
||||
"ID #1000.\n\n"
|
||||
"Options:\n"
|
||||
" --server_silent Server is started using silent option. Not compatible with 'server_verbose'.\n"
|
||||
" --server_verbose Server is started using verbose option. Not compatible with 'server_silent'.\n"
|
||||
" --install_dir Installation directory (absolute or relative to the sdv_core executable).\n\n");
|
||||
" --server_silent Server is started using silent option. Not compatible with 'server_verbose'.\n"
|
||||
" --server_verbose Server is started using verbose option. Not compatible with 'server_silent'.\n"
|
||||
" --install_dir<path> Installation directory (absolute or relative to the sdv_core executable).\n\n");
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "SHUTDOWN"))
|
||||
@@ -156,7 +156,7 @@ int StartupSDVServer(const SContext& rsContext)
|
||||
}
|
||||
|
||||
// Try to connect
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
@@ -183,7 +183,7 @@ int ShutdownSDVServer(const SContext& rsContext)
|
||||
std::cout << "Connecting to the SDV #" << rsContext.uiInstanceID << " server..." << std::endl;
|
||||
|
||||
// Try to connect
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
|
||||
@@ -18,6 +18,40 @@
|
||||
#include <support/app_control.h>
|
||||
#include "../error_msg.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief Console application control handler (CTRL+C, close, shutdown, etc.).
|
||||
* @param[in] dwCtrlType The control type triggered by the system.
|
||||
* @return Returns TRUE when the signal was handled.
|
||||
*/
|
||||
static BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#elif defined __unix__
|
||||
#include <signal.h>
|
||||
|
||||
/**
|
||||
* @brief Signal handler to catch signal events.
|
||||
* @param[in] iSigNum The signal type that was triggered.
|
||||
*/
|
||||
static void SignalHandler(int /*iSigNum*/)
|
||||
{
|
||||
// Do nothing...
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main function of the executable.
|
||||
* @param[in] iArgc Amount of arguments provided.
|
||||
@@ -46,12 +80,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bError = false;
|
||||
@@ -91,7 +119,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent && !bNoBanner)
|
||||
{
|
||||
std::cout << "SDV core application" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
@@ -185,14 +213,40 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
return APP_CONTROL_STARTUP_ERROR;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Register the console control handler
|
||||
if (!SetConsoleCtrlHandler(&ControlHandler, TRUE))
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#elif defined __unix__
|
||||
// Install our signal handler
|
||||
struct sigaction sSigAction
|
||||
{};
|
||||
sSigAction.sa_handler = SignalHandler;
|
||||
sSigAction.sa_flags = SA_RESTART;
|
||||
if (sigaction(SIGINT, &sSigAction, NULL) == -1)
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Start the running loop
|
||||
if (!appcontrol.RunLoop())
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_DUPLICATE_INSTANCE_MSG << std::endl;
|
||||
return APP_CONTROL_DUPLICATE_INSTANCE;
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler(&ControlHandler, FALSE);
|
||||
#endif
|
||||
|
||||
if (bVerbose)
|
||||
{
|
||||
std::cout << "Shutdown request received..." << std::endl;
|
||||
|
||||
@@ -372,7 +372,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
|
||||
std::ofstream tomlFile("sdv_core_reloc.toml");
|
||||
if (tomlFile.is_open())
|
||||
{
|
||||
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
|
||||
tomlFile << R"toml(# Location of the SDV binaries and configuration files
|
||||
[CoreLocation]
|
||||
Version = 100
|
||||
Framework = ")toml";
|
||||
tomlFile << resources;
|
||||
tomlFile << "\"\n";
|
||||
tomlFile.close();
|
||||
|
||||
@@ -82,7 +82,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "DBC utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl;
|
||||
}
|
||||
if (bHelp)
|
||||
|
||||
@@ -174,6 +174,9 @@ std::string CProxyGenerator::GetFuncImpl(const SFuncInfo& rsFunc, CKeywordMap& r
|
||||
else
|
||||
sstreamExceptions << R"code(sdv::XUnknownException exception;
|
||||
exception.unknown_id = except_id;
|
||||
// Cpp-Check 2.7 warns about the uninitialized variable _id. This variable is allocated as inline static const and is
|
||||
// assigned a value. Suppress the warning.
|
||||
// cppcheck-suppress uninitvar
|
||||
throw exception;)code";
|
||||
for (const std::string& rssException : rvecExceptions)
|
||||
{
|
||||
@@ -181,6 +184,9 @@ std::string CProxyGenerator::GetFuncImpl(const SFuncInfo& rsFunc, CKeywordMap& r
|
||||
{
|
||||
)code" << rssException << R"code( exception;
|
||||
desOutput >> exception;
|
||||
// Cpp-Check 2.7 warns about the uninitialized variable _id. This variable is allocated as inline static const and is
|
||||
// assigned a value. Suppress the warning.
|
||||
// cppcheck-suppress uninitvar
|
||||
throw exception;
|
||||
}
|
||||
)code";
|
||||
@@ -190,6 +196,9 @@ std::string CProxyGenerator::GetFuncImpl(const SFuncInfo& rsFunc, CKeywordMap& r
|
||||
{
|
||||
sdv::XUnknownException exception;
|
||||
exception.unknown_id = except_id;
|
||||
// Cpp-Check 2.7 warns about the uninitialized variable _id. This variable is allocated as inline static const and is
|
||||
// assigned a value. Suppress the warning.
|
||||
// cppcheck-suppress uninitvar
|
||||
throw exception;
|
||||
}
|
||||
})code";
|
||||
|
||||
@@ -41,7 +41,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
std::cout << "SDV IDL Compiler" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl;
|
||||
|
||||
// Create a list of UTF-8 arguments
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "token.h"
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <clocale>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <cuchar>
|
||||
@@ -71,7 +72,7 @@ const std::string& CSource::GetCodeRef() const
|
||||
void CSource::ReadFile(const std::filesystem::path& rpath)
|
||||
{
|
||||
// Set the locale to work with UTF8
|
||||
std::setlocale(LC_ALL, "en_US.utf8");
|
||||
::setlocale(LC_ALL, "en_US.utf8");
|
||||
|
||||
if (rpath.empty())
|
||||
throw CCompileException("File name missing");
|
||||
|
||||
@@ -22,6 +22,40 @@
|
||||
#include <support/local_service_access.h>
|
||||
#include "../error_msg.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief Console application control handler (CTRL+C, close, shutdown, etc.).
|
||||
* @param[in] dwCtrlType The control type triggered by the system.
|
||||
* @return Returns TRUE when the signal was handled.
|
||||
*/
|
||||
static BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#elif defined __unix__
|
||||
#include <signal.h>
|
||||
|
||||
/**
|
||||
* @brief Signal handler to catch signal events.
|
||||
* @param[in] iSigNum The signal type that was triggered.
|
||||
*/
|
||||
static void SignalHandler(int /*iSigNum*/)
|
||||
{
|
||||
// Do nothing...
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Connect event callback wrapper. Calls shutdown request on disconnect or error.
|
||||
*/
|
||||
@@ -93,12 +127,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bError = false;
|
||||
@@ -126,23 +154,29 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
{
|
||||
ssArgError = rsExcept.what();
|
||||
bHelp = true;
|
||||
bError = true;
|
||||
}
|
||||
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "SDV isolation application" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
if (!ssArgError.empty() && !bSilent)
|
||||
if (!ssArgError.empty() && !bSilent && !bHelp && !bVersion)
|
||||
std::cerr << "ERROR: " << ssArgError << std::endl;
|
||||
|
||||
if (ssConfigBase64.empty())
|
||||
if (bVersion || bVerbose)
|
||||
{
|
||||
ssArgError = "Missing app configuration.";
|
||||
bHelp = true;
|
||||
std::cout << "Version: " << (SDVFrameworkBuildVersion / 100) << "." << (SDVFrameworkBuildVersion % 100) << " build "
|
||||
<< SDVFrameworkSubbuildVersion << " interface " << SDVFrameworkInterfaceVersion << std::endl;
|
||||
}
|
||||
|
||||
if (!bHelp && ssConfigBase64.empty())
|
||||
{
|
||||
if (!bSilent && !bVersion)
|
||||
std::cout << "Missing app configuration.";
|
||||
bError = true;
|
||||
}
|
||||
|
||||
if (bHelp)
|
||||
@@ -153,17 +187,14 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
std::cout << std::endl;
|
||||
cmdln.PrintHelp(std::cout, "The isolation application is used to isolate components from the core process. The "
|
||||
"isolation aims to improve the overall stability of the system.\n");
|
||||
return bError ? CMDLN_ARG_ERR : NO_ERROR;
|
||||
}
|
||||
return (bError && !bVersion && !bHelp) ? CMDLN_ARG_ERR : NO_ERROR;
|
||||
}
|
||||
if (bError) return CMDLN_ARG_ERR;
|
||||
if (bError) return (bError && !bVersion && !bHelp) ? CMDLN_ARG_ERR : NO_ERROR;
|
||||
|
||||
// Check for encoded configuration
|
||||
std::string ssIsoAppConfig = Base64DecodePlainText(ssConfigBase64);
|
||||
|
||||
if (bVersion || bVerbose)
|
||||
std::cout << "Version: " << (SDVFrameworkBuildVersion / 100) << "." << (SDVFrameworkBuildVersion % 100) << " build " <<
|
||||
SDVFrameworkSubbuildVersion << " interface " << SDVFrameworkInterfaceVersion << std::endl;
|
||||
if (!bSilent)
|
||||
std::cout << "Instance ID: " << uiInstanceID << std::endl;
|
||||
|
||||
@@ -267,7 +298,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
std::cerr << "ERROR: " << LINK_REPO_SERVICE_ERROR_MSG << std::endl;
|
||||
return LINK_REPO_SERVICE_ERROR;
|
||||
}
|
||||
pLinkCoreRepo->LinkCoreRepository(pCoreRepo);
|
||||
sdv::core::TLinkID tRepoLink = pLinkCoreRepo->LinkCoreRepository(pCoreRepo);
|
||||
|
||||
// Create the one object... is this a service or a utility?
|
||||
std::string ssClassName = parser.GetDirect("Isolation.Class").GetValue();
|
||||
@@ -332,6 +363,28 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// The lifetime of the object is now taken over by the core or if failed, the object will be destroyed.
|
||||
ptrObject.Clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Register the console control handler
|
||||
if (!SetConsoleCtrlHandler(&ControlHandler, TRUE))
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#elif defined __unix__
|
||||
// Install our signal handler
|
||||
struct sigaction sSigAction
|
||||
{};
|
||||
sSigAction.sa_handler = SignalHandler;
|
||||
sSigAction.sa_flags = SA_RESTART;
|
||||
if (sigaction(SIGINT, &sSigAction, NULL) == -1)
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Deactivate the configuration mode.
|
||||
appcontrol.SetRunningMode();
|
||||
|
||||
@@ -339,10 +392,14 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!appcontrol.RunLoop())
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAIELD_MSG << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAIELD;
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler(&ControlHandler, FALSE);
|
||||
#endif
|
||||
|
||||
// TODO EVE
|
||||
if (appcontrol.IsConfiguring())
|
||||
std::cout << "Iso app configuring... " << __LINE__ << std::endl;
|
||||
@@ -358,7 +415,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// Shutdwown
|
||||
pConnect->UnregisterStateEventCallback(uiCookie);
|
||||
parser.Clear();
|
||||
pLinkCoreRepo->UnlinkCoreRepository();
|
||||
pLinkCoreRepo->UnlinkCoreRepository(tRepoLink);
|
||||
appcontrol.Shutdown();
|
||||
|
||||
if (!bSilent)
|
||||
|
||||
@@ -32,12 +32,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bError = false;
|
||||
@@ -67,7 +61,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "SDV Local Instance Shutdown Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,4 +24,5 @@
|
||||
#include "../../sdv_services/core/toml_parser/character_reader_utf_8.cpp"
|
||||
#include "../../sdv_services/core/toml_parser/miscellaneous.cpp"
|
||||
#include "../../sdv_services/core/toml_parser/code_snippet.cpp"
|
||||
#include "../../sdv_services/core/toml_parser/parser_node_indexer.cpp"
|
||||
|
||||
|
||||
@@ -12,9 +12,8 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "environment.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "../../global/exec_dir_helper.h"
|
||||
#include "../../global/cmdlnparser/cmdlnparser.cpp"
|
||||
|
||||
CSdvPackagerEnvironment::CSdvPackagerEnvironment() :
|
||||
@@ -862,13 +861,16 @@ bool CSdvPackagerEnvironment::ProcessCommandLine(const std::vector<std::string>&
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const wchar_t* szInstallDir = _wgetenv(L"SDV_COMPONENT_INSTALL");
|
||||
if (!szInstallDir) szInstallDir = _wgetenv(L"SDV_FRAMEWORK_RUNTIME");
|
||||
if (szInstallDir) m_pathTargetLocation = szInstallDir;
|
||||
#elif defined __unix__
|
||||
const char* szInstallDir = getenv("SDV_COMPONENT_INSTALL");
|
||||
if (!szInstallDir) szInstallDir = getenv("SDV_FRAMEWORK_RUNTIME");
|
||||
if (szInstallDir) m_pathTargetLocation = std::filesystem::u8path(szInstallDir);
|
||||
#else
|
||||
#error OS not supported!
|
||||
#endif
|
||||
if (m_pathTargetLocation.empty()) m_pathTargetLocation = GetExecDirectory();
|
||||
}
|
||||
|
||||
// Is the directory existing? If not, create the directory
|
||||
|
||||
@@ -41,12 +41,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
// Process the command line.
|
||||
CSdvPackagerEnvironment environment(iArgc, rgszArgv);
|
||||
|
||||
@@ -54,7 +48,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!environment.Silent())
|
||||
{
|
||||
std::cout << "SDV Component Installation Package Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
@@ -114,7 +108,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
}
|
||||
|
||||
// If running as server, load the settings file
|
||||
if (!environment.Local() && !GetAppSettings().LoadSettingsFile())
|
||||
if (!environment.Local() && !GetAppSettings().LoadSettings())
|
||||
{
|
||||
std::cerr << "ERROR: Failed to load the application settings file; cannot continue!" << std::endl;
|
||||
return -1;
|
||||
|
||||
@@ -450,7 +450,7 @@ bool CPackager::Configure()
|
||||
m_ssArgError = CMDLN_MISSING_TARGET_MSG;
|
||||
return false;
|
||||
}
|
||||
if (!GetAppSettings().SaveSettingsFile())
|
||||
if (!GetAppSettings().SaveSettings())
|
||||
{
|
||||
SDV_LOG_ERROR("Failed to save application settings. Cannot configure components!");
|
||||
return false;
|
||||
@@ -743,7 +743,7 @@ bool CPackager::ConfigureFromManifest(const CInstallManifest& rmanifest)
|
||||
auto pathConfig = GetAppSettings().GetConfigPath(CAppSettings::EConfigType::user_config);
|
||||
WriteConfig(vecClasses, pathConfig, vecComponentsToAdd, true, vecAddedToConfig);
|
||||
}
|
||||
if (!GetAppSettings().SaveSettingsFile())
|
||||
if (!GetAppSettings().SaveSettings())
|
||||
{
|
||||
SDV_LOG_ERROR("Failed to save application settings. Cannot configure components!");
|
||||
return false;
|
||||
@@ -806,11 +806,11 @@ void CPackager::WriteConfig(const std::vector<sdv::SClassInfo>& rvecAllClasses,
|
||||
break;
|
||||
case sdv::EObjectType::complex_service:
|
||||
case sdv::EObjectType::vehicle_function:
|
||||
case sdv::EObjectType::utility:
|
||||
eIncompatible = bUserConfig ? ECompatibility::compatible : ECompatibility::incompatible;
|
||||
break;
|
||||
case sdv::EObjectType::proxy:
|
||||
case sdv::EObjectType::stub:
|
||||
case sdv::EObjectType::utility:
|
||||
eIncompatible = ECompatibility::silent_incompatible;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -65,7 +65,7 @@ static BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
}
|
||||
#elif defined __unix__
|
||||
/**
|
||||
* @brief Signal handler to catch signal eevents.
|
||||
* @brief Signal handler to catch signal events.
|
||||
* @param[in] iSigNum The signal type that was triggered.
|
||||
*/
|
||||
static void SignalHandler(int iSigNum)
|
||||
@@ -97,12 +97,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bVersion = false;
|
||||
@@ -123,7 +117,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
}
|
||||
|
||||
std::cout << "SDV Server Log Monitor Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
|
||||
if (bVersion)
|
||||
|
||||
@@ -109,7 +109,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "abtract device / basic services utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Thomas Pfleiderer" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,6 +170,14 @@ add_custom_command(
|
||||
COMMAND sdv_idl_compiler ${INTERFACE_DIR}/repository.idl -O${INTERFACE_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${INTERFACE_DIR}/permission.h
|
||||
DEPENDS sdv_idl_compiler
|
||||
MAIN_DEPENDENCY ${INTERFACE_DIR}/permission.idl
|
||||
COMMENT "Compiling permission.idl"
|
||||
COMMAND sdv_idl_compiler ${INTERFACE_DIR}/permission.idl -O${INTERFACE_DIR} --no_ps
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${INTERFACE_DIR}/timer.h
|
||||
DEPENDS sdv_idl_compiler
|
||||
@@ -198,6 +206,7 @@ add_custom_target(CompileCoreIDL
|
||||
${INTERFACE_DIR}/process.h
|
||||
${INTERFACE_DIR}/param.h
|
||||
${INTERFACE_DIR}/repository.h
|
||||
${INTERFACE_DIR}/permission.h
|
||||
${INTERFACE_DIR}/timer.h
|
||||
)
|
||||
|
||||
@@ -212,10 +221,14 @@ add_subdirectory(task_timer)
|
||||
add_subdirectory(ipc_com)
|
||||
add_subdirectory(ipc_connect)
|
||||
add_subdirectory(ipc_shared_mem)
|
||||
add_subdirectory(uds_unix_sockets)
|
||||
add_subdirectory(uds_unix_tunnel)
|
||||
add_subdirectory(uds_win_sockets)
|
||||
add_subdirectory(uds_win_tunnel)
|
||||
if(UNIX)
|
||||
add_subdirectory(uds_unix_sockets)
|
||||
add_subdirectory(uds_unix_tunnel)
|
||||
endif()
|
||||
if(WIN32)
|
||||
add_subdirectory(uds_win_sockets)
|
||||
add_subdirectory(uds_win_tunnel)
|
||||
endif()
|
||||
add_subdirectory(process_control)
|
||||
add_subdirectory(hardware_ident)
|
||||
add_subdirectory(manifest_util)
|
||||
|
||||
@@ -118,7 +118,7 @@ private:
|
||||
*/
|
||||
void PlaybackFunc(const asc::SCanMessage& rsMsg);
|
||||
|
||||
std::thread m_threadReceive; ///< Receive thread.
|
||||
sdv::core::secure_thread m_threadReceive; ///< Receive thread.
|
||||
mutable std::mutex m_mtxReceivers; ///< Protect the receiver set.
|
||||
std::set<sdv::can::IReceive*> m_setReceivers; ///< Set with receiver interfaces.
|
||||
mutable std::mutex m_mtxInterfaces; ///< Protect the nodes set.
|
||||
|
||||
@@ -64,7 +64,7 @@ bool CCANSockets::OnInitialize()
|
||||
}
|
||||
|
||||
LogConfigurations();
|
||||
m_threadReceive = std::thread(&CCANSockets::ReceiveThreadFunc, this);
|
||||
m_threadReceive = sdv::core::secure_thread(&CCANSockets::ReceiveThreadFunc, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ private:
|
||||
std::string name; ///< interface name, can be empty in case of an invalid socket element
|
||||
};
|
||||
|
||||
std::thread m_threadReceive; ///< Receive thread.
|
||||
sdv::core::secure_thread m_threadReceive; ///< Receive thread.
|
||||
mutable std::mutex m_mtxReceivers; ///< Protect the receiver set.
|
||||
std::set<sdv::can::IReceive*> m_setReceivers; ///< Set with receiver interfaces.
|
||||
mutable std::mutex m_mtxSockets; ///< Protect the socket list.
|
||||
|
||||
@@ -49,13 +49,14 @@ add_library(core_services SHARED
|
||||
"toml_parser_util.h"
|
||||
"installation_manifest.h"
|
||||
"installation_manifest.cpp"
|
||||
"../../global/tracefifo/trace_fifo.cpp"
|
||||
"local_shutdown_request.h"
|
||||
"iso_monitor.h"
|
||||
"iso_monitor.cpp"
|
||||
"installation_composer.h"
|
||||
"installation_composer.cpp"
|
||||
|
||||
"toml_parser/lexer_toml_token.h" "toml_parser/lexer_toml_token.cpp" "toml_parser/miscellaneous.h" "toml_parser/miscellaneous.cpp" "toml_parser/code_snippet.h" "toml_parser/code_snippet.cpp" "app_settings.h" "app_settings.cpp" "app_config_file.h" "app_config_file.cpp")
|
||||
"toml_parser/lexer_toml_token.h" "toml_parser/lexer_toml_token.cpp" "toml_parser/miscellaneous.h" "toml_parser/miscellaneous.cpp" "toml_parser/code_snippet.h" "toml_parser/code_snippet.cpp" "app_settings.h" "app_settings.cpp" "app_config_file.h" "app_config_file.cpp" "toml_parser/parser_node_indexer.h" "toml_parser/parser_node_indexer.cpp" "permission_control.h" "permission_control.cpp")
|
||||
|
||||
# Compiler settiings
|
||||
add_compile_definitions(SDV_NO_EXPORT_DEFINITION)
|
||||
|
||||
@@ -33,61 +33,6 @@ CAppConfig& GetAppConfig()
|
||||
return app_config;
|
||||
}
|
||||
|
||||
// GetCoreDirectory might have been redirected for unit tests.
|
||||
#ifndef GetCoreDirectory
|
||||
std::filesystem::path GetCoreDirectory()
|
||||
{
|
||||
static std::filesystem::path pathCoreDir;
|
||||
if (!pathCoreDir.empty())
|
||||
return pathCoreDir;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows specific
|
||||
std::wstring ssPath(32768, '\0');
|
||||
|
||||
MEMORY_BASIC_INFORMATION sMemInfo{};
|
||||
if (!VirtualQuery(&pathCoreDir, &sMemInfo, sizeof(sMemInfo)))
|
||||
return pathCoreDir;
|
||||
DWORD dwLength = GetModuleFileNameW(reinterpret_cast<HINSTANCE>(sMemInfo.AllocationBase), ssPath.data(), 32767);
|
||||
ssPath.resize(dwLength);
|
||||
pathCoreDir = std::filesystem::path(ssPath);
|
||||
return pathCoreDir.remove_filename();
|
||||
#elif __linux__
|
||||
// Read the maps file. It contains all loaded SOs.
|
||||
std::ifstream fstream("/proc/self/maps");
|
||||
std::stringstream sstreamMap;
|
||||
sstreamMap << fstream.rdbuf();
|
||||
std::string ssMap = sstreamMap.str();
|
||||
if (ssMap.empty())
|
||||
return pathCoreDir; // Some error
|
||||
|
||||
// Find the "core_services.sdv"
|
||||
size_t nPos = ssMap.find("core_services.sdv");
|
||||
if (nPos == std::string::npos)
|
||||
return pathCoreDir;
|
||||
size_t nEnd = nPos;
|
||||
|
||||
// Find the start... runbackwards until the beginning of the line and remember the earliest occurance of a slash
|
||||
size_t nBegin = 0;
|
||||
while (nPos && ssMap[nPos] != '\n')
|
||||
{
|
||||
if (ssMap[nPos] == '/')
|
||||
nBegin = nPos;
|
||||
nPos--;
|
||||
}
|
||||
if (!nBegin)
|
||||
nBegin = nPos;
|
||||
|
||||
// Return the path
|
||||
pathCoreDir = ssMap.substr(nBegin, nEnd - nBegin);
|
||||
|
||||
return pathCoreDir;
|
||||
#else
|
||||
#error The OS is not supported!
|
||||
#endif
|
||||
}
|
||||
#endif // !defined GetCoreDirectory
|
||||
|
||||
bool CAppConfig::LoadInstallationManifests()
|
||||
{
|
||||
// Check for allowance
|
||||
@@ -96,13 +41,14 @@ bool CAppConfig::LoadInstallationManifests()
|
||||
{
|
||||
case sdv::app::EAppContext::main:
|
||||
case sdv::app::EAppContext::isolated:
|
||||
case sdv::app::EAppContext::external:
|
||||
case sdv::app::EAppContext::maintenance:
|
||||
bServerApp = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::filesystem::path pathCore = GetCoreDirectory();
|
||||
std::filesystem::path pathCore = GetAppSettings().GetFrameworkDir();
|
||||
std::filesystem::path pathExe = GetExecDirectory();
|
||||
std::filesystem::path pathInstall = GetAppSettings().GetInstallDir();
|
||||
|
||||
@@ -155,8 +101,8 @@ void CAppConfig::UnloadInstallatonManifests()
|
||||
|
||||
bool CAppConfig::LoadAppConfigs()
|
||||
{
|
||||
// Isolated applications do not load configurations
|
||||
if (GetAppSettings().IsIsolatedApplication()) return false;
|
||||
// Isolated and external applications do not load configurations
|
||||
if (GetAppSettings().IsIsolatedApplication() || GetAppSettings().IsExternalApplication()) return false;
|
||||
|
||||
// When running as server application, load the system configurations
|
||||
if (GetAppSettings().IsMainApplication() || GetAppSettings().IsMaintenanceApplication())
|
||||
@@ -243,6 +189,7 @@ sdv::core::EConfigProcessResult CAppConfig::ProcessConfig(/*in*/ const sdv::u8st
|
||||
{
|
||||
case sdv::app::EAppContext::main:
|
||||
case sdv::app::EAppContext::isolated:
|
||||
case sdv::app::EAppContext::external:
|
||||
case sdv::app::EAppContext::maintenance:
|
||||
return sdv::core::EConfigProcessResult::failed;
|
||||
default:
|
||||
@@ -275,7 +222,7 @@ sdv::core::EConfigProcessResult CAppConfig::ProcessConfig(/*in*/ const sdv::u8st
|
||||
//size_t nLoadable = 0;
|
||||
//size_t nNotLoadable = 0;
|
||||
//if (!GetAppSettings().IsMainApplication() && !GetAppSettings().IsIsolatedApplication() &&
|
||||
// !GetAppSettings().IsMaintenanceApplication())
|
||||
// !GetAppSettings().IsExternalApplication() && !GetAppSettings().IsMaintenanceApplication())
|
||||
//{
|
||||
// // Load all modules in the component section
|
||||
// auto ptrComponents = parser.Root().Direct("Component");
|
||||
@@ -394,7 +341,7 @@ sdv::core::EConfigProcessResult CAppConfig::ProcessConfig(/*in*/ const sdv::u8st
|
||||
// // loaded; get the module ID.
|
||||
// sdv::core::TObjectID tObjectID = 0;
|
||||
// if (!GetAppSettings().IsMainApplication() && !GetAppSettings().IsIsolatedApplication() &&
|
||||
// !GetAppSettings().IsMaintenanceApplication())
|
||||
// !GetAppSettings().IsExternalApplication() && !GetAppSettings().IsMaintenanceApplication())
|
||||
// {
|
||||
// auto itModule = mapModules.find(pathModule);
|
||||
// if (itModule == mapModules.end()) continue; // Module was not loaded before...
|
||||
@@ -880,6 +827,7 @@ std::filesystem::path CAppConfig::FindInstalledModule(const std::filesystem::pat
|
||||
{
|
||||
case sdv::app::EAppContext::main:
|
||||
case sdv::app::EAppContext::isolated:
|
||||
case sdv::app::EAppContext::external:
|
||||
case sdv::app::EAppContext::maintenance:
|
||||
bServerApp = true;
|
||||
default:
|
||||
@@ -914,6 +862,7 @@ std::string CAppConfig::FindInstalledModuleManifest(const std::filesystem::path&
|
||||
{
|
||||
case sdv::app::EAppContext::main:
|
||||
case sdv::app::EAppContext::isolated:
|
||||
case sdv::app::EAppContext::external:
|
||||
case sdv::app::EAppContext::maintenance:
|
||||
bServerApp = true;
|
||||
default:
|
||||
@@ -948,6 +897,7 @@ std::optional<sdv::SClassInfo> CAppConfig::FindInstalledComponent(const std::str
|
||||
{
|
||||
case sdv::app::EAppContext::main:
|
||||
case sdv::app::EAppContext::isolated:
|
||||
case sdv::app::EAppContext::external:
|
||||
case sdv::app::EAppContext::maintenance:
|
||||
bServerApp = true;
|
||||
default:
|
||||
@@ -980,6 +930,7 @@ bool CAppConfig::RemoveFromConfig(const CInstallManifest& /*rManifest*/)
|
||||
//{
|
||||
//case sdv::app::EAppContext::main:
|
||||
//case sdv::app::EAppContext::isolated:
|
||||
//case sdv::app::EAppContext::external:
|
||||
//case sdv::app::EAppContext::maintenance:
|
||||
// bServerApp = true;
|
||||
//default:
|
||||
@@ -1043,7 +994,7 @@ void CAppConfig::AddCurrentPath()
|
||||
if (!m_lstSearchPaths.empty()) return;
|
||||
|
||||
// Add the core directory
|
||||
std::filesystem::path pathCoreDir = GetCoreDirectory().lexically_normal();
|
||||
std::filesystem::path pathCoreDir = GetAppSettings().GetFrameworkDir().lexically_normal();
|
||||
m_lstSearchPaths.push_back(pathCoreDir / "config/");
|
||||
|
||||
// Add the exe dir
|
||||
|
||||
@@ -39,12 +39,6 @@
|
||||
// The installation might need companion files to be installed in various relative sub-directories.
|
||||
// @endcond
|
||||
|
||||
/**
|
||||
* @brief Get the location of the core_services.sdv.
|
||||
* @return Path to the directory containing the loaded core directory.
|
||||
*/
|
||||
std::filesystem::path GetCoreDirectory();
|
||||
|
||||
/**
|
||||
* @brief Application configuration service
|
||||
* @details In the configuration system objects, devices, basic services, complex services and apps are defined and will be started
|
||||
|
||||
@@ -346,9 +346,9 @@ Version = )toml" + std::to_string(SDVFrameworkInterfaceVersion) + R"toml(
|
||||
// Modules leftover in the vector are added to the list
|
||||
auto vecModuleListCopy = m_vecModuleList;
|
||||
sdv::toml::CNodeCollection nodeModules = nodeConfig.GetDirect("Module");
|
||||
for (size_t nIndex = nodeModules.GetCount() - 1; nIndex < nodeModules.GetCount(); --nIndex)
|
||||
for (int64_t iIndex = static_cast<int64_t>(nodeModules.GetCount() - 1); iIndex >= 0; --iIndex)
|
||||
{
|
||||
sdv::toml::CNodeCollection tableModule = nodeModules.Get(nIndex);
|
||||
sdv::toml::CNodeCollection tableModule = nodeModules.Get(static_cast<size_t>(iIndex));
|
||||
std::filesystem::path pathModule = tableModule.GetDirect("Path").GetValue().get<std::string>();
|
||||
auto itModule = std::find_if(vecModuleListCopy.begin(), vecModuleListCopy.end(),
|
||||
[&](const SModule& rsModule) { return pathModule == rsModule.pathModule; });
|
||||
@@ -374,9 +374,9 @@ Version = )toml" + std::to_string(SDVFrameworkInterfaceVersion) + R"toml(
|
||||
// Classes leftover in the vector are added to the list
|
||||
auto vecClassListCopy = m_vecClassList;
|
||||
sdv::toml::CNodeCollection arrayClasses = nodeConfig.GetDirect("Class");
|
||||
for (size_t nIndex = arrayClasses.GetCount() -1; nIndex < arrayClasses.GetCount(); --nIndex)
|
||||
for (int64_t iIndex = static_cast<int64_t>(arrayClasses.GetCount() - 1); iIndex >= 0; --iIndex)
|
||||
{
|
||||
sdv::toml::CNodeCollection tableClass = arrayClasses.Get(nIndex);
|
||||
sdv::toml::CNodeCollection tableClass = arrayClasses.Get(static_cast<size_t>(iIndex));
|
||||
std::filesystem::path pathModule;
|
||||
if (!bServerApp)
|
||||
pathModule = tableClass.GetDirect("Path").GetValue().get<std::string>();
|
||||
@@ -419,8 +419,7 @@ Version = )toml" + std::to_string(SDVFrameworkInterfaceVersion) + R"toml(
|
||||
if (ssExistingTOML != itClass->ssDefaultConfig)
|
||||
{
|
||||
if (tableParams) tableParams.Delete();
|
||||
if (!itClass->ssDefaultConfig.empty())
|
||||
tableClass.InsertTOML(sdv::toml::npos, itClass->ssDefaultConfig);
|
||||
if (!itClass->ssDefaultConfig.empty()) tableClass.InsertTOML("", itClass->ssDefaultConfig);
|
||||
rbChanged = true;
|
||||
}
|
||||
|
||||
@@ -433,8 +432,7 @@ Version = )toml" + std::to_string(SDVFrameworkInterfaceVersion) + R"toml(
|
||||
tableClass.AddValue("Class", rsClass.ssName);
|
||||
if (!bServerApp)
|
||||
tableClass.AddValue("Path", std::filesystem::u8path(static_cast<std::string>(rsClass.ssModulePath)));
|
||||
if (!rsClass.ssDefaultConfig.empty())
|
||||
tableClass.InsertTOML(sdv::toml::npos, rsClass.ssDefaultConfig);
|
||||
if (!rsClass.ssDefaultConfig.empty()) tableClass.InsertTOML("", rsClass.ssDefaultConfig);
|
||||
rbChanged = true;
|
||||
}
|
||||
|
||||
@@ -444,9 +442,9 @@ Version = )toml" + std::to_string(SDVFrameworkInterfaceVersion) + R"toml(
|
||||
// Components leftover in the vector are added to the list
|
||||
auto vecComponentListCopy = m_vecComponentList;
|
||||
sdv::toml::CNodeCollection nodeComponents = nodeConfig.GetDirect("Component");
|
||||
for (size_t nIndex = nodeComponents.GetCount() - 1; nIndex < nodeComponents.GetCount(); --nIndex)
|
||||
for (int64_t iIndex = static_cast<int64_t>(nodeComponents.GetCount() - 1); iIndex >= 0; --iIndex)
|
||||
{
|
||||
sdv::toml::CNodeCollection tableComponent = nodeComponents.Get(nIndex);
|
||||
sdv::toml::CNodeCollection tableComponent = nodeComponents.Get(static_cast<size_t>(iIndex));
|
||||
std::filesystem::path pathModule;
|
||||
if (!bServerApp)
|
||||
pathModule = tableComponent.GetDirect("Path").GetValue().get<std::string>();
|
||||
@@ -518,8 +516,8 @@ Version = )toml" + std::to_string(SDVFrameworkInterfaceVersion) + R"toml(
|
||||
else if (!tableParams)
|
||||
{
|
||||
// Simply add the parameters
|
||||
tableParams = tableComponent.InsertTable(sdv::toml::npos, "Parameters");
|
||||
tableParams.InsertTOML(sdv::toml::npos, itComponent->ssParameterTOML);
|
||||
tableParams = tableComponent.InsertTable("", "Parameters");
|
||||
tableParams.InsertTOML("", itComponent->ssParameterTOML);
|
||||
rbChanged = true;
|
||||
}
|
||||
}
|
||||
@@ -536,8 +534,8 @@ Version = )toml" + std::to_string(SDVFrameworkInterfaceVersion) + R"toml(
|
||||
tableComponent.AddValue("Name", rsComponent.ssInstanceName);
|
||||
if (!rsComponent.ssParameterTOML.empty())
|
||||
{
|
||||
sdv::toml::CNodeCollection tableParams = tableComponent.InsertTable(sdv::toml::npos, "Parameters");
|
||||
tableParams.InsertTOML(sdv::toml::npos, rsComponent.ssParameterTOML);
|
||||
sdv::toml::CNodeCollection tableParams = tableComponent.InsertTable("", "Parameters");
|
||||
tableParams.InsertTOML("", rsComponent.ssParameterTOML);
|
||||
}
|
||||
rbChanged = true;
|
||||
}
|
||||
@@ -628,12 +626,12 @@ bool CAppConfigFile::InsertComponent(size_t nIndex, const std::filesystem::path&
|
||||
// Need to add a group?
|
||||
if (prKey.first != ssGroup)
|
||||
{
|
||||
group = root.InsertTable(sdv::toml::npos, prKey.first);
|
||||
group = root.InsertTable("", prKey.first);
|
||||
ssGroup = prKey.first;
|
||||
}
|
||||
|
||||
// Add the parameter
|
||||
group.InsertValue(sdv::toml::npos, prKey.second, prParameter.second);
|
||||
group.InsertValue("", prKey.second, prParameter.second);
|
||||
}
|
||||
ssParameterTOML = parser.GenerateTOML();
|
||||
}
|
||||
|
||||
@@ -266,6 +266,9 @@ public:
|
||||
*/
|
||||
void RemoveModule(const std::filesystem::path& rpathModule);
|
||||
|
||||
/**
|
||||
* @brief Merge result enum.
|
||||
*/
|
||||
enum class EMergeResult
|
||||
{
|
||||
successful,
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "module_control.h"
|
||||
#include "repository.h"
|
||||
#include "../../global/base64.h"
|
||||
#include "../../global/tracefifo/trace_fifo.cpp"
|
||||
#include "toml_parser/parser_toml.h"
|
||||
#include "local_shutdown_request.h"
|
||||
#include "app_settings.h"
|
||||
@@ -49,6 +48,9 @@ bool CAppControl::Startup(/*in*/ const sdv::u8string& ssConfig, /*in*/ IInterfac
|
||||
{
|
||||
m_pEvent = pEventHandler ? pEventHandler->GetInterface<sdv::app::IAppEvent>() : nullptr;
|
||||
|
||||
// Allow this thread full access
|
||||
m_optpermission = GetPermissionControl().CreatePermissionObject(sdv::core::EAccessPermission::full_access);
|
||||
|
||||
// Intercept the logging...
|
||||
std::stringstream sstreamCOUT, sstreamCLOG, sstreamCERR;
|
||||
std::streambuf* pstreambufCOUT = std::cout.rdbuf(sstreamCOUT.rdbuf());
|
||||
@@ -86,7 +88,7 @@ bool CAppControl::Startup(/*in*/ const sdv::u8string& ssConfig, /*in*/ IInterfac
|
||||
}
|
||||
|
||||
// Open the stream buffer and attach the streams if the application control is initialized as main app.
|
||||
if (GetAppSettings().IsMainApplication())
|
||||
if (!GetAppSettings().RedirectMonitorToConsole() && GetAppSettings().IsMainApplication())
|
||||
{
|
||||
m_fifoTraceStreamBuffer.SetInstanceID(GetAppSettings().GetInstanceID());
|
||||
m_fifoTraceStreamBuffer.Open(1000);
|
||||
@@ -99,7 +101,7 @@ bool CAppControl::Startup(/*in*/ const sdv::u8string& ssConfig, /*in*/ IInterfac
|
||||
std::cerr << sstreamCERR.str();
|
||||
|
||||
// Check for a correctly opened stream buffer
|
||||
if (GetAppSettings().IsMainApplication() && !m_fifoTraceStreamBuffer.IsOpened())
|
||||
if (!GetAppSettings().RedirectMonitorToConsole() && GetAppSettings().IsMainApplication() && !m_fifoTraceStreamBuffer.IsOpened())
|
||||
{
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cerr << "ERROR: Log streaming could not be initialized; cannot continue!" << std::endl;
|
||||
@@ -142,7 +144,7 @@ bool CAppControl::Startup(/*in*/ const sdv::u8string& ssConfig, /*in*/ IInterfac
|
||||
};
|
||||
auto fnCreateObject = [&ssErrorString](const sdv::u8string& rssClass, const sdv::u8string& rssObject, const sdv::u8string& rssConfig) -> bool
|
||||
{
|
||||
bool bLocalRet = GetRepository().CreateObject2(rssClass, rssObject, rssConfig);
|
||||
bool bLocalRet = GetRepository().CreateObject(rssClass, rssObject, rssConfig);
|
||||
if (!bLocalRet)
|
||||
{
|
||||
ssErrorString = std::string("Failed to instantiate a new object from class '") + rssClass + "'";
|
||||
@@ -179,7 +181,7 @@ bool CAppControl::Startup(/*in*/ const sdv::u8string& ssConfig, /*in*/ IInterfac
|
||||
sdv::IInterfaceAccess* pLoggerObj = GetRepository().GetObject(GetAppSettings().GetLoggerClass());
|
||||
if (!pLoggerObj)
|
||||
{
|
||||
GetRepository().DestroyObject2(GetAppSettings().GetLoggerClass());
|
||||
GetRepository().DestroyObject(GetAppSettings().GetLoggerClass());
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cerr << "ERROR: Failed to start the logger. Cannot continue!" << std::endl;
|
||||
Shutdown(true);
|
||||
@@ -247,7 +249,7 @@ bool CAppControl::Startup(/*in*/ const sdv::u8string& ssConfig, /*in*/ IInterfac
|
||||
}
|
||||
|
||||
// Load the application settings.
|
||||
if (!GetAppSettings().LoadSettingsFile())
|
||||
if (!GetAppSettings().LoadSettings())
|
||||
{
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cerr << "ERROR: Failed to load application settings file. Cannot continue!" << std::endl;
|
||||
@@ -275,32 +277,88 @@ bool CAppControl::Startup(/*in*/ const sdv::u8string& ssConfig, /*in*/ IInterfac
|
||||
bRet = fnLoadModule("hardware_ident.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("HardwareIdentificationService", "", "");
|
||||
|
||||
// Load shared memory channel
|
||||
if (bRet) bRet = fnLoadModule("ipc_shared_mem.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("DefaultSharedMemoryChannelControl", "", "");
|
||||
// Load default communication provider
|
||||
if (bRet) bRet = fnCreateObject(GetAppSettings().GetDefaultComProvider(), "", "");
|
||||
|
||||
// Load IPC service
|
||||
if (bRet) bRet = fnLoadModule("ipc_com.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("CommunicationControl", "", "");
|
||||
|
||||
// Load IPC service and create listener local connections
|
||||
if (bRet) bRet = fnLoadModule("ipc_listener.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("ConnectionListenerService", "", R"code([Listener]
|
||||
Type = "Local"
|
||||
)code");
|
||||
|
||||
// Load IPC service
|
||||
if (bRet) bRet = fnLoadModule("ipc_connect.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("ConnectionService", "", "");
|
||||
|
||||
// Load proxy/stub for core interfaces
|
||||
if (bRet) bRet = fnLoadModule("core_ps.sdv") ? true : false;
|
||||
|
||||
// // Start the listener
|
||||
// if (bRet) bRet = fnLoadModule("ipc_listener.sdv") ? true : false;
|
||||
// if (bRet) bRet = GetRepository().CreateObject("ConnectionListenerService", "ConnectionListenerService", R"code([Listener]
|
||||
//Type="local"
|
||||
//Instance=)code" + std::to_string(GetInstanceID()));
|
||||
// Load the connection services
|
||||
if (bRet) bRet = fnLoadModule("ipc_listener.sdv") ? true : false;
|
||||
if (bRet) bRet = fnLoadModule("ipc_connect.sdv") ? true : false;
|
||||
|
||||
// For the main application start the configured listeners.
|
||||
if (bRet)
|
||||
{
|
||||
auto seqListeners = GetAppSettings().GetListeners();
|
||||
for (const auto& rssListener : seqListeners)
|
||||
{
|
||||
if (!bRet) break;
|
||||
auto ssListenerConfig = GetAppSettings().GetListenerConfig(rssListener);
|
||||
bRet = fnCreateObject("ListenerConnectService", "Listener_" + rssListener, ssListenerConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// For the main application connect the configured connections (except default connection).
|
||||
if (bRet)
|
||||
{
|
||||
auto seqConnections = GetAppSettings().GetConnections();
|
||||
for (const auto& rssConnection : seqConnections)
|
||||
{
|
||||
if (!bRet) break;
|
||||
if (rssConnection == "Default") continue;
|
||||
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cout << "INFO: Trying to connect to " << rssConnection << "..." << std::endl;
|
||||
|
||||
auto ssConnectionConfig = GetAppSettings().GetConnectionConfig(rssConnection);
|
||||
std::string ssObjectName = "Client_" + rssConnection;
|
||||
bRet = fnCreateObject("ClientConnectService", ssObjectName, ssConnectionConfig);
|
||||
|
||||
// Try connect (for at least nTries) and when successful bind repositories
|
||||
sdv::TInterfaceAccessPtr ptrClient = GetRepository().GetObject(ssObjectName);
|
||||
sdv::com::IClientConnect* pClientConnect = ptrClient.GetInterface<sdv::com::IClientConnect>();
|
||||
if (pClientConnect)
|
||||
{
|
||||
for (uint32_t uiCnt = 0; uiCnt < GetAppSettings().GetConnectRetries(); uiCnt++)
|
||||
{
|
||||
// Try to connect. If not working, wait for 300 ms
|
||||
if (pClientConnect->Connect()) break;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
}
|
||||
|
||||
if (pClientConnect->IsConnected())
|
||||
{
|
||||
// Register the core repo as repo access
|
||||
sdv::core::TLinkID tLinkID = GetRepository().LinkCoreRepository(pClientConnect->GetRemoteRepository());
|
||||
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cout << "INFO: Connection established... " << std::endl;
|
||||
|
||||
// Store the connection object.
|
||||
m_vecConnections.push_back(std::make_pair(ssObjectName, tLinkID));
|
||||
}
|
||||
else
|
||||
{
|
||||
ssErrorString = "Not connected...";
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cout << "ERROR: Failed to connect to " << ssConnectionConfig << std::endl;
|
||||
bRet = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ssErrorString = "No client connect interface...";
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cerr << "ERROR: Cannot create connection object for " << rssConnection << std::endl;
|
||||
bRet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bRet)
|
||||
{
|
||||
@@ -314,25 +372,69 @@ Type = "Local"
|
||||
}
|
||||
else if (bRet && bLoadRPCClient)
|
||||
{
|
||||
// Interpret the connect string...
|
||||
|
||||
|
||||
// Load hardware identification
|
||||
bRet = fnLoadModule("hardware_ident.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("HardwareIdentificationService", "", "");
|
||||
|
||||
// Load shared memory channel
|
||||
if (bRet) bRet = fnLoadModule("ipc_shared_mem.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("DefaultSharedMemoryChannelControl", "", "");
|
||||
// Load default communication provider
|
||||
if (bRet) bRet = fnCreateObject(GetAppSettings().GetDefaultComProvider(), "", "");
|
||||
|
||||
// Load IPC service
|
||||
if (bRet) bRet = fnLoadModule("ipc_com.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("CommunicationControl", "", "");
|
||||
|
||||
// Load IPC service
|
||||
if (bRet) bRet = fnLoadModule("ipc_connect.sdv") ? true : false;
|
||||
if (bRet) bRet = fnCreateObject("ConnectionService", "", "");
|
||||
// Connect to the core system when running as external aplication. Use the default connection for this.
|
||||
if (bRet && GetAppSettings().GetContextType() == sdv::app::EAppContext::external)
|
||||
{
|
||||
// Load the connection services
|
||||
bRet = fnLoadModule("ipc_connect.sdv") ? true : false;
|
||||
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cout << "INFO: Trying to connect to the core system..." << std::endl;
|
||||
|
||||
// And the one connection
|
||||
auto ssConnectionConfig = GetAppSettings().GetConnectionConfig("Default");
|
||||
if (bRet && !ssConnectionConfig.empty())
|
||||
bRet = fnCreateObject("ClientConnectService", "Client_Default", ssConnectionConfig);
|
||||
|
||||
// Try connect (for at least nTries) and when successful bind repositories
|
||||
sdv::TInterfaceAccessPtr ptrClient = GetRepository().GetObject("Client_Default");
|
||||
sdv::com::IClientConnect* pClientConnect = ptrClient.GetInterface<sdv::com::IClientConnect>();
|
||||
if (pClientConnect)
|
||||
{
|
||||
for (uint32_t uiCnt = 0; uiCnt < GetAppSettings().GetConnectRetries(); uiCnt++)
|
||||
{
|
||||
// Try to connect. If not working, wait for 300 ms
|
||||
if (pClientConnect->Connect()) break;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
}
|
||||
|
||||
if (pClientConnect->IsConnected())
|
||||
{
|
||||
// Register the core repo as repo access
|
||||
sdv::core::TLinkID tLinkID = GetRepository().LinkCoreRepository(pClientConnect->GetRemoteRepository());
|
||||
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cout << "INFO: Connection established... " << std::endl;
|
||||
|
||||
// Store the connection object.
|
||||
m_vecConnections.push_back(std::make_pair("Default", tLinkID));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cout << "ERROR: Failed to connect to the core system" << std::endl;
|
||||
bRet = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GetAppSettings().IsConsoleSilent())
|
||||
std::cerr << "ERROR: Cannot create connection object for connecting to the core system." << std::endl;
|
||||
bRet = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Load proxy/stub for core interfaces
|
||||
if (bRet) bRet = fnLoadModule("core_ps.sdv") ? true : false;
|
||||
|
||||
@@ -428,6 +530,7 @@ void CAppControl::RunLoop()
|
||||
{
|
||||
case sdv::app::EAppContext::main:
|
||||
case sdv::app::EAppContext::isolated:
|
||||
case sdv::app::EAppContext::external:
|
||||
bLocal = false;
|
||||
break;
|
||||
case sdv::app::EAppContext::maintenance:
|
||||
@@ -490,8 +593,22 @@ void CAppControl::Shutdown(/*in*/ bool bForce)
|
||||
// Disable automatic configuration saving.
|
||||
m_bAutoSaveConfig = false;
|
||||
|
||||
// Update the application settings file
|
||||
GetAppSettings().SaveSettingsFile();
|
||||
// TODO EVE: This is likely not wanted
|
||||
//// Update the application settings file
|
||||
//GetAppSettings().SaveSettings();
|
||||
|
||||
// Disconnect all automatic connections.
|
||||
for (const auto& rprConnectObject : m_vecConnections)
|
||||
{
|
||||
// If there is a registered link ID, unlink the ID.
|
||||
if (rprConnectObject.second)
|
||||
GetRepository().UnlinkCoreRepository(rprConnectObject.second);
|
||||
|
||||
sdv::TInterfaceAccessPtr ptrClient = GetRepository().GetObject(rprConnectObject.first);
|
||||
sdv::com::IClientConnect* pClientConnect = ptrClient.GetInterface<sdv::com::IClientConnect>();
|
||||
if (pClientConnect) pClientConnect->Disconnect();
|
||||
}
|
||||
m_vecConnections.clear();
|
||||
|
||||
// Destroy all objects... this should also remove any registered services, except the custom logger.
|
||||
GetRepository().DestroyAllObjects(std::vector<std::string>({GetAppSettings().GetLoggerClass()}), bForce);
|
||||
@@ -537,7 +654,7 @@ void CAppControl::Shutdown(/*in*/ bool bForce)
|
||||
}
|
||||
|
||||
// End trace streaming
|
||||
if (GetAppSettings().IsMainApplication())
|
||||
if (!GetAppSettings().RedirectMonitorToConsole() && GetAppSettings().IsMainApplication())
|
||||
{
|
||||
std::cout << "**********************************************" << std::endl;
|
||||
|
||||
@@ -551,6 +668,7 @@ void CAppControl::Shutdown(/*in*/ bool bForce)
|
||||
m_bAutoSaveConfig = false;
|
||||
m_bEnableAutoSave = false;
|
||||
GetAppSettings().Reset();
|
||||
m_optpermission.reset();
|
||||
}
|
||||
|
||||
void CAppControl::RequestShutdown()
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <support/component_impl.h>
|
||||
#include <support/interface_ptr.h>
|
||||
#include "../../global/tracefifo/trace_fifo.h"
|
||||
#include "permission_control.h"
|
||||
#include <optional>
|
||||
|
||||
/**
|
||||
* @brief Application control class.
|
||||
@@ -140,17 +142,20 @@ private:
|
||||
*/
|
||||
void BroadcastOperationState(sdv::app::EAppOperationState eState);
|
||||
|
||||
sdv::app::EAppOperationState m_eState = sdv::app::EAppOperationState::not_started; ///< The current operation state.
|
||||
sdv::app::IAppEvent* m_pEvent = nullptr; ///< Pointer to the app event interface.
|
||||
sdv::core::TModuleID m_tLoggerModuleID = 0; ///< ID of the logger module.
|
||||
bool m_bEnableAutoSave = false; ///< When set and when enabled in the system settings, allows
|
||||
///< the automatic saving of the configuration.
|
||||
bool m_bRunLoop = false; ///< Used to detect end of running loop function.
|
||||
std::filesystem::path m_pathLockFile; ///< Lock file path name.
|
||||
FILE* m_pLockFile = nullptr; ///< Lock file to test for other instances.
|
||||
CTraceFifoStdBuffer m_fifoTraceStreamBuffer; ///< Trace stream buffer to redirect std::log, std::out and
|
||||
///< std::err when running as service.
|
||||
bool m_bAutoSaveConfig = false; ///< System setting for automatic saving of the user configuration.
|
||||
sdv::app::EAppOperationState m_eState = sdv::app::EAppOperationState::not_started; ///< The current operation state.
|
||||
sdv::app::IAppEvent* m_pEvent = nullptr; ///< Pointer to the app event interface.
|
||||
sdv::core::TModuleID m_tLoggerModuleID = 0; ///< ID of the logger module.
|
||||
bool m_bEnableAutoSave = false; ///< When set and when enabled in the system settings, allows
|
||||
///< the automatic saving of the configuration.
|
||||
bool m_bRunLoop = false; ///< Used to detect end of running loop function.
|
||||
std::filesystem::path m_pathLockFile; ///< Lock file path name.
|
||||
FILE* m_pLockFile = nullptr; ///< Lock file to test for other instances.
|
||||
CTraceFifoStdBuffer m_fifoTraceStreamBuffer; ///< Trace stream buffer to redirect std::log, std::out and
|
||||
///< std::err when running as service.
|
||||
bool m_bAutoSaveConfig = false; ///< System setting for automatic saving of the user configuration.
|
||||
std::vector<std::pair<std::string, sdv::core::TLinkID>> m_vecConnections; ///< Connection objects that were successfully
|
||||
///< connected.
|
||||
std::optional<CAccessPermission> m_optpermission; ///< Main access permission for the core.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user