Precommit (#1)

* first commit

* cleanup
This commit is contained in:
tompzf
2025-11-04 13:28:06 +01:00
committed by GitHub
parent dba45dc636
commit 6ed4b1534e
898 changed files with 256340 additions and 0 deletions

View File

@@ -0,0 +1,215 @@
project(DoorDemoExample)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
set(CMAKE_CXX_STANDARD 17)
# Libary symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Include directory to the core framework
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
# Copy the config files
file (COPY ${PROJECT_SOURCE_DIR}/config/data_dispatch_example.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
file (COPY ${PROJECT_SOURCE_DIR}/config/task_timer_example.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
file (COPY ${PROJECT_SOURCE_DIR}/config/front_left_door_example.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
file (COPY ${PROJECT_SOURCE_DIR}/config/front_right_door_example.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
file (COPY ${PROJECT_SOURCE_DIR}/config/rear_left_door_example.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
file (COPY ${PROJECT_SOURCE_DIR}/config/rear_right_door_example.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
file (COPY ${PROJECT_SOURCE_DIR}/config/door_comple_service.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
file (COPY ${PROJECT_SOURCE_DIR}/config/data_link_door.toml DESTINATION ${CMAKE_BINARY_DIR}/bin/config)
# Copy the ASC files used by can_com_sim.sdv which includes the CAN messages
# Required in both locations when running standalone or as instance
file (COPY ${PROJECT_SOURCE_DIR}/door_example_receiver.asc DESTINATION ${CMAKE_BINARY_DIR}/bin)
file (COPY ${PROJECT_SOURCE_DIR}/door_example_receiver.asc DESTINATION ${CMAKE_BINARY_DIR}../../bin)
######################################################################################################################################################################
# preparation
######################################################################################################################################################################
message("Compiling Interface Door01Left RX")
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
message("Compiling Interface Door01Right RX")
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-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}/interfaces/vss_vehiclechassisdooraxle02left_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle02left_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-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}/interfaces/vss_vehiclechassisdooraxle02right_vd_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle02right_bs_rx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
message("Compiling Interface Door01Left TX")
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
message("Compiling Interface Door01Right TX")
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle01right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
message("Compiling Interface Door02Left TX")
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle02left_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle02left_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_proxystub)
message("Compiling Interface Door02Right TX")
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle02right_vd_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --no_ps)
execute_process(COMMAND "${SDV_IDL_COMPILER}" "${PROJECT_SOURCE_DIR}/interfaces/vss_vehiclechassisdooraxle02right_bs_tx.idl" "-O${PROJECT_SOURCE_DIR}/interfaces/" "-I${SDV_FRAMEWORK_DEV_INCLUDE}" -Igenerated/vss_files/ --ps_lib_namedoors_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(interfaces/ps)
add_subdirectory(vd/vd_front_door_left)
add_subdirectory(vd/vd_front_door_right)
add_subdirectory(vd/vd_rear_door_left)
add_subdirectory(vd/vd_rear_door_right)
add_subdirectory(bs/bs_front_door_left)
add_subdirectory(bs/bs_front_door_right)
add_subdirectory(bs/bs_rear_door_left)
add_subdirectory(bs/bs_rear_door_right)
add_subdirectory(can_dl_door)
######################################################################################################################################################################
# complex service
######################################################################################################################################################################
include_directories(interfaces)
include_directories(${CMAKE_CURRENT_LIST_DIR}/door_app/include)
message("Include: proxy/stub for complex doors service")
include_directories(${CMAKE_CURRENT_LIST_DIR}/generated/door_service)
add_subdirectory(generated/door_service/ps)
add_library(door_complex_service SHARED
door_service/complex_service.h
door_service/complex_service.cpp
door_service/lock_doors_thread.h)
set_target_properties(door_complex_service PROPERTIES OUTPUT_NAME "door_complex_service")
set_target_properties(door_complex_service PROPERTIES PREFIX "")
set_target_properties(door_complex_service PROPERTIES SUFFIX ".sdv")
######################################################################################################################################################################
# executable
######################################################################################################################################################################
add_executable(door_demo_example
"door_app/door_demo_example.cpp"
"door_app/include/door_application.h"
"door_app/door_application.cpp"
"door_app/include/console.h"
"door_app/console.cpp"
"door_app/include/signal_names.h"
"door_service/lock_doors_thread.h")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (WIN32)
target_link_libraries(door_demo_example Ws2_32 Winmm Rpcrt4.lib)
else()
target_link_libraries(door_demo_example ${CMAKE_DL_LIBS} rt ${CMAKE_THREAD_LIBS_INIT})
endif()
else()
target_link_libraries(door_demo_example Rpcrt4.lib)
endif()
######################################################################################################################################################################
# external application
######################################################################################################################################################################
add_executable(door_external_app
"door_app/door_extern_example.cpp"
"door_app/include/door_extern_application.h"
"door_app/door_extern_application.cpp"
"door_app/include/console.h"
"door_app/console.cpp"
"door_app/include/signal_names.h"
"door_service/lock_doors_thread.h")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (WIN32)
target_link_libraries(door_external_app Ws2_32 Winmm Rpcrt4.lib)
else()
target_link_libraries(door_external_app ${CMAKE_DL_LIBS} rt ${CMAKE_THREAD_LIBS_INIT})
endif()
else()
target_link_libraries(door_external_app Rpcrt4.lib)
endif()
######################################################################################################################################################################
# create instance 3002 of door demo example
######################################################################################################################################################################
add_custom_target(vehicle_device_doors_config
ALL
DEPENDS
can_dl_door
doors_vd_frontdoorleft
doors_vd_frontdoorright
doors_vd_reardoorleft
doors_vd_reardoorright
COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL VehicleDeviceDoors --instance3002 can_dl_door.sdv doors_vd_frontdoorleft.sdv doors_vd_frontdoorright.sdv doors_vd_reardoorleft.sdv doors_vd_reardoorright.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --interface_config --overwrite
VERBATIM
)
add_custom_target(basic_service_doors_config
ALL
DEPENDS
doors_proxystub
doors_bs_frontdoorleft
doors_bs_frontdoorright
doors_bs_reardoorleft
doors_bs_reardoorright
COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL BasicServiceDoors --instance3002 doors_proxystub.sdv doors_bs_frontdoorleft.sdv doors_bs_frontdoorright.sdv doors_bs_reardoorleft.sdv doors_bs_reardoorright.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --abstract_config --overwrite
VERBATIM
)
add_custom_target(door_complex_service_config
ALL
DEPENDS
door_complex_service
doors_service_proxystub
COMMAND "${SDV_PACKAGER}" DIRECT_INSTALL DoorComplexService --instance3002 door_complex_service.sdv doors_service_proxystub.sdv "-I${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" --user_config --overwrite
VERBATIM
)
######################################################################################################################################################################
# TODO: SDV_PACKAGER does not create the toml files, therefore we need to copy them
######################################################################################################################################################################
file (COPY ${PROJECT_SOURCE_DIR}/coreconfig/door_demo.toml DESTINATION ${SDV_FRAMEWORK_RUNTIME}/3002)
file (COPY ${PROJECT_SOURCE_DIR}/coreconfig/platform.toml DESTINATION ${SDV_FRAMEWORK_RUNTIME}/3002)
file (COPY ${PROJECT_SOURCE_DIR}/coreconfig/settings.toml DESTINATION ${SDV_FRAMEWORK_RUNTIME}/3002)
file (COPY ${PROJECT_SOURCE_DIR}/coreconfig/vehicle_abstract.toml DESTINATION ${SDV_FRAMEWORK_RUNTIME}/3002)
file (COPY ${PROJECT_SOURCE_DIR}/coreconfig/vehicle_ifc.toml DESTINATION ${SDV_FRAMEWORK_RUNTIME}/3002)
######################################################################################################################################################################
# the FMU files have been created via the dbc file
# ..\\..\\build\\<configurePreset>\\bin\\sdv_dbc_util datalink_2doors_example.dbc -Ogenerated\\ --nodesdoors --version1.0.0.1 --moduleDoors2ExampleFMU --dl_lib_namecan_dl_door
# ..\\..\\build\\<configurePreset>\\bin\\sdv_dbc_util datalink_4doors_example.dbc -Ogenerated\\ --nodesdoors --version1.0.0.1 --moduleDoors4ExampleFMU --dl_lib_namecan_dl_door
#
# following steps needs to be done:
# required configuration files have to be put into the subfolder
# ...\fmu_Doors2ExampleFMU\Doors2ExampleFMU\resources
# ...\fmu_Doors2ExampleFMU\Doors4ExampleFMU\resources
# function OpenAPILoad() needs to be updated in the model.cpp file
# ...\fmu_Doors2ExampleFMU\Doors2ExampleFMU\model.cpp
# ...\fmu_Doors2ExampleFMU\Doors4ExampleFMU\model.cpp
######################################################################################################################################################################
add_subdirectory(fmu_Doors2ExampleFMU)
add_subdirectory(fmu_Doors4ExampleFMU)

View File

@@ -0,0 +1,49 @@
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
# Define project
project(doors_bs_frontdoorleft VERSION 1.0 LANGUAGES CXX)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Libary symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set target name.
set(TARGET_NAME doors_bs_frontdoorleft)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
include_directories(../../interfaces)
# Set platform specific compile flags
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/W4 /WX /wd4996 /wd4100 /permissive- /Zc:rvalueCast)
else()
add_compile_options(-Werror -Wall -Wextra -Wshadow -Wpedantic -Wunreachable-code -fno-common)
endif()
# Add the dynamic library
add_library(${TARGET_NAME} SHARED
bs_front_door_left.h
bs_front_door_left.cpp)
# Set extension to .sdv
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".sdv")
# TODO: set target name.
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)

View File

@@ -0,0 +1,115 @@
/**
* @file bs_front_door_left.cpp
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <iostream>
#include "bs_front_door_left.h"
/**
* @brief ConstructorF
*/
CBasicServiceFrontDoorLeft::CBasicServiceFrontDoorLeft()
{
auto leftDoorIsOpen01Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_IsOpen>();
if (!leftDoorIsOpen01Device)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_IsOpen': [CBasicServiceFrontDoorLeft]");
throw std::runtime_error("Vehicle.Chassis.Door.Axle01.Left mode device not found");
}
leftDoorIsOpen01Device->RegisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteIsOpen_Event*> (this));
m_ptrLock = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteLock>();
if (!m_ptrLock)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_WriteLock': [CBasicServiceFrontDoorLeft]");
throw std::runtime_error("Lock device not found");
}
SDV_LOG_TRACE("CBasicServiceFrontDoorLeft created: [Vehicle.Chassis.Door.Axle01.Left_Device]");
m_leftDoorIsOpen01 = 0;
}
/**
* @brief User-Defined Destructor
*/
CBasicServiceFrontDoorLeft::~CBasicServiceFrontDoorLeft()
{
auto leftDoorIsOpen01Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_IsOpen>();
if (leftDoorIsOpen01Device)
{
leftDoorIsOpen01Device->UnregisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteIsOpen_Event*> (this));
}
leftDoorIsOpen01Device = nullptr;
}
/**
* @brief Set leftDoorIsOpen
* @param[in] value leftDoorIsOpen
*/
void CBasicServiceFrontDoorLeft::SetIsOpenL1(bool value)
{
m_leftDoorIsOpen01 = value;
std::lock_guard<std::mutex> lock(m_leftDoorIsOpen01MutexCallbacks);
for (auto callback : m_leftDoorIsOpen01Callbacks)
{
callback->SetIsOpenL1(value);
}
}
/**
* @brief Write leftDoorIsOpen
* @param[in] value leftDoorIsOpen
*/
void CBasicServiceFrontDoorLeft::WriteIsOpen(bool value)
{
SetIsOpenL1(value);
}
/**
* @brief Get leftDoorIsOpen
* @return Returns the leftDoorIsOpen
*/
bool CBasicServiceFrontDoorLeft::GetIsOpen() const
{
return m_leftDoorIsOpen01;
}
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void CBasicServiceFrontDoorLeft::RegisterOnSignalChangeOfLeftDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event* leftDoorIsOpen01Callback)
{
if ( leftDoorIsOpen01Callback)
{
std::lock_guard<std::mutex> lock(m_leftDoorIsOpen01MutexCallbacks);
m_leftDoorIsOpen01Callbacks.insert(leftDoorIsOpen01Callback);
}
}
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void CBasicServiceFrontDoorLeft::UnregisterOnSignalChangeOfLeftDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event* leftDoorIsOpen01Callback)
{
if (leftDoorIsOpen01Callback)
{
std::lock_guard<std::mutex> lock(m_leftDoorIsOpen01MutexCallbacks);
m_leftDoorIsOpen01Callbacks.erase(leftDoorIsOpen01Callback);
}
}
/**
* @brief Lock
* @param[in] value
* @return true on success otherwise false
*/
bool CBasicServiceFrontDoorLeft::SetLock(bool value)
{
return m_ptrLock->WriteLock(value);
}

View File

@@ -0,0 +1,95 @@
/**
* @file bs_front_door_left.h
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#ifndef __VSS_GENERATED__BS_FRONTDOORLEFT_H_20250711_125718_601__
#define __VSS_GENERATED__BS_FRONTDOORLEFT_H_20250711_125718_601__
#include <iostream>
#include <set>
#include <support/component_impl.h>
#include <support/signal_support.h>
#include "vss_vehiclechassisdooraxle01left_bs_rx.h"
#include "vss_vehiclechassisdooraxle01left_vd_tx.h"
#include "vss_vehiclechassisdooraxle01left_bs_tx.h"
/**
* @brief Basic Service Vehicle.Chassis.Door.Axle01.Left
*/
class CBasicServiceFrontDoorLeft
: public sdv::CSdvObject
, public vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_GetIsOpen
, public vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetLock
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_GetIsOpen)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetLock)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("Vehicle.Chassis.Door.Axle01.Left_Service")
/**
* @brief Constructor
*/
CBasicServiceFrontDoorLeft();
/**
* @brief User-Defined Destructor
*/
~CBasicServiceFrontDoorLeft();
/**
* @brief Set leftDoorIsOpen signal
* @param[in] value leftDoorIsOpen
*/
void SetIsOpenL1(bool value) override;
/**
* @brief Get leftDoorIsOpen
* @return Returns the leftDoorIsOpen
*/
bool GetIsOpen() const override;
/**
* @brief Write leftDoorIsOpen signal
* @param[in] value leftDoorIsOpen
*/
void WriteIsOpen(bool value) override;
/**
* @brief Set leftLatch signal
* @param[in] value
* @return true on success otherwise false
*/
bool SetLock(bool value) override;
/**
* @brief Register CallBack function on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfLeftDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event* callback) override;
/**
* @brief Unregister CallBack function on signal change
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfLeftDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event* callback) override;
private:
bool m_leftDoorIsOpen01 { 0 };
mutable std::mutex m_leftDoorIsOpen01MutexCallbacks; ///< Mutex protecting m_leftDoorIsOpen01Callbacks
std::set<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event*> m_leftDoorIsOpen01Callbacks; ///< collection of events to be called
vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteLock* m_ptrLock = nullptr;
};
DEFINE_SDV_OBJECT(CBasicServiceFrontDoorLeft)
#endif // !define __VSS_GENERATED__BS_FRONTDOORLEFT_H_20250711_125718_601__

View File

@@ -0,0 +1,49 @@
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
# Define project
project(doors_bs_frontdoorright VERSION 1.0 LANGUAGES CXX)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Libary symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set target name.
set(TARGET_NAME doors_bs_frontdoorright)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
include_directories(../../interfaces)
# Set platform specific compile flags
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/W4 /WX /wd4996 /wd4100 /permissive- /Zc:rvalueCast)
else()
add_compile_options(-Werror -Wall -Wextra -Wshadow -Wpedantic -Wunreachable-code -fno-common)
endif()
# Add the dynamic library
add_library(${TARGET_NAME} SHARED
bs_front_door_right.h
bs_front_door_right.cpp)
# Set extension to .sdv
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".sdv")
# TODO: set target name.
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)

View File

@@ -0,0 +1,115 @@
/**
* @file bs_front_door_right.cpp
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <iostream>
#include "bs_front_door_right.h"
/**
* @brief ConstructorF
*/
CBasicServiceFrontDoorRight::CBasicServiceFrontDoorRight()
{
auto rightDoorIsOpen01Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightDevice::IVSS_IsOpen>();
if (!rightDoorIsOpen01Device)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_IsOpen': [CBasicServiceFrontDoorRight]");
throw std::runtime_error("Vehicle.Chassis.Door.Axle01.Right mode device not found");
}
rightDoorIsOpen01Device->RegisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::RightDevice::IVSS_WriteIsOpen_Event*> (this));
m_ptrLock = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightDevice::IVSS_WriteLock>();
if (!m_ptrLock)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_WriteLock': [CBasicServiceFrontDoorRight]");
throw std::runtime_error("Lock device not found");
}
SDV_LOG_TRACE("CBasicServiceFrontDoorRight created: [Vehicle.Chassis.Door.Axle01.Right_Device]");
m_rightDoorIsOpen01 = 0;
}
/**
* @brief User-Defined Destructor
*/
CBasicServiceFrontDoorRight::~CBasicServiceFrontDoorRight()
{
auto rightDoorIsOpen01Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightDevice::IVSS_IsOpen>();
if (rightDoorIsOpen01Device)
{
rightDoorIsOpen01Device->UnregisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::RightDevice::IVSS_WriteIsOpen_Event*> (this));
}
rightDoorIsOpen01Device = nullptr;
}
/**
* @brief Set rightDoorIsOpen
* @param[in] value rightDoorIsOpen
*/
void CBasicServiceFrontDoorRight::SetIsOpenR1(bool value)
{
m_rightDoorIsOpen01 = value;
std::lock_guard<std::mutex> lock(m_rightDoorIsOpen01MutexCallbacks);
for (auto callback : m_rightDoorIsOpen01Callbacks)
{
callback->SetIsOpenR1(value);
}
}
/**
* @brief Write rightDoorIsOpen
* @param[in] value rightDoorIsOpen
*/
void CBasicServiceFrontDoorRight::WriteIsOpen(bool value)
{
SetIsOpenR1(value);
}
/**
* @brief Get rightDoorIsOpen
* @return Returns the rightDoorIsOpen
*/
bool CBasicServiceFrontDoorRight::GetIsOpen() const
{
return m_rightDoorIsOpen01;
}
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void CBasicServiceFrontDoorRight::RegisterOnSignalChangeOfRightDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event* rightDoorIsOpen01Callback)
{
if ( rightDoorIsOpen01Callback)
{
std::lock_guard<std::mutex> lock(m_rightDoorIsOpen01MutexCallbacks);
m_rightDoorIsOpen01Callbacks.insert(rightDoorIsOpen01Callback);
}
}
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void CBasicServiceFrontDoorRight::UnregisterOnSignalChangeOfRightDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event* rightDoorIsOpen01Callback)
{
if (rightDoorIsOpen01Callback)
{
std::lock_guard<std::mutex> lock(m_rightDoorIsOpen01MutexCallbacks);
m_rightDoorIsOpen01Callbacks.erase(rightDoorIsOpen01Callback);
}
}
/**
* @brief Lock
* @param[in] value
* @return true on success otherwise false
*/
bool CBasicServiceFrontDoorRight::SetLock(bool value)
{
return m_ptrLock->WriteLock(value);
}

View File

@@ -0,0 +1,95 @@
/**
* @file bs_front_door_right.h
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#ifndef __VSS_GENERATED__BS_FRONTDOORRIGHT_H_20250711_125718_606__
#define __VSS_GENERATED__BS_FRONTDOORRIGHT_H_20250711_125718_606__
#include <iostream>
#include <set>
#include <support/component_impl.h>
#include <support/signal_support.h>
#include "vss_vehiclechassisdooraxle01right_bs_rx.h"
#include "vss_vehiclechassisdooraxle01right_vd_tx.h"
#include "vss_vehiclechassisdooraxle01right_bs_tx.h"
/**
* @brief Basic Service Vehicle.Chassis.Door.Axle01.Right
*/
class CBasicServiceFrontDoorRight
: public sdv::CSdvObject
, public vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_GetIsOpen
, public vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle01::RightDevice::IVSS_WriteIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetLock
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_GetIsOpen)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetLock)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("Vehicle.Chassis.Door.Axle01.Right_Service")
/**
* @brief Constructor
*/
CBasicServiceFrontDoorRight();
/**
* @brief User-Defined Destructor
*/
~CBasicServiceFrontDoorRight();
/**
* @brief Set rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR1(bool value) override;
/**
* @brief Set signal
* @param[in] value rightLatche
* @return true on success otherwise false
*/
bool SetLock(bool value) override;
/**
* @brief Get rightDoorIsOpen
* @return Returns the rightDoorIsOpen
*/
bool GetIsOpen() const override;
/**
* @brief Write rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void WriteIsOpen(bool value) override;
/**
* @brief Register CallBack function on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfRightDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event* callback) override;
/**
* @brief Unregister CallBack function on signal change
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfRightDoorIsOpen01(vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event* callback) override;
private:
bool m_rightDoorIsOpen01 { 0 };
mutable std::mutex m_rightDoorIsOpen01MutexCallbacks; ///< Mutex protecting m_rightDoorIsOpen01Callbacks
std::set<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event*> m_rightDoorIsOpen01Callbacks; ///< collection of events to be called
vss::Vehicle::Chassis::Door::Axle01::RightDevice::IVSS_WriteLock* m_ptrLock = nullptr;
};
DEFINE_SDV_OBJECT(CBasicServiceFrontDoorRight)
#endif // !define __VSS_GENERATED__BS_FRONTDOORRIGHT_H_20250711_125718_606__

View File

@@ -0,0 +1,49 @@
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
# Define project
project(doors_bs_reardoorleft VERSION 1.0 LANGUAGES CXX)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Libary symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set target name.
set(TARGET_NAME doors_bs_reardoorleft)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
include_directories(../../interfaces)
# Set platform specific compile flags
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/W4 /WX /wd4996 /wd4100 /permissive- /Zc:rvalueCast)
else()
add_compile_options(-Werror -Wall -Wextra -Wshadow -Wpedantic -Wunreachable-code -fno-common)
endif()
# Add the dynamic library
add_library(${TARGET_NAME} SHARED
bs_rear_door_left.h
bs_rear_door_left.cpp)
# Set extension to .sdv
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".sdv")
# TODO: set target name.
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)

View File

@@ -0,0 +1,115 @@
/**
* @file bs_rear_door_left.cpp
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <iostream>
#include "bs_rear_door_left.h"
/**
* @brief ConstructorF
*/
CBasicServiceRearDoorLeft::CBasicServiceRearDoorLeft()
{
auto leftDoorIsOpen02Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftDevice::IVSS_IsOpen>();
if (!leftDoorIsOpen02Device)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_IsOpen': [CBasicServiceRearDoorLeft]");
throw std::runtime_error("Vehicle.Chassis.Door.Axle02.Left mode device not found");
}
leftDoorIsOpen02Device->RegisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::LeftDevice::IVSS_WriteIsOpen_Event*> (this));
m_ptrLock = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftDevice::IVSS_WriteLock>();
if (!m_ptrLock)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_WriteLock': [CBasicServiceRearDoorLeft]");
throw std::runtime_error("Lock device not found");
}
SDV_LOG_TRACE("CBasicServiceRearDoorLeft created: [Vehicle.Chassis.Door.Axle02.Left_Device]");
m_leftDoorIsOpen02 = 0;
}
/**
* @brief User-Defined Destructor
*/
CBasicServiceRearDoorLeft::~CBasicServiceRearDoorLeft()
{
auto leftDoorIsOpen02Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftDevice::IVSS_IsOpen>();
if (leftDoorIsOpen02Device)
{
leftDoorIsOpen02Device->UnregisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::LeftDevice::IVSS_WriteIsOpen_Event*> (this));
}
leftDoorIsOpen02Device = nullptr;
}
/**
* @brief Set rightDoorIsOpen
* @param[in] value rightDoorIsOpen
*/
void CBasicServiceRearDoorLeft::SetIsOpenL2(bool value)
{
m_leftDoorIsOpen02 = value;
std::lock_guard<std::mutex> lock(m_leftDoorIsOpen02MutexCallbacks);
for (auto callback : m_leftDoorIsOpen02Callbacks)
{
callback->SetIsOpenL2(value);
}
}
/**
* @brief Write rightDoorIsOpen
* @param[in] value rightDoorIsOpen
*/
void CBasicServiceRearDoorLeft::WriteIsOpen(bool value)
{
SetIsOpenL2(value);
}
/**
* @brief Get rightDoorIsOpen
* @return Returns the rightDoorIsOpen
*/
bool CBasicServiceRearDoorLeft::GetIsOpen() const
{
return m_leftDoorIsOpen02;
}
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void CBasicServiceRearDoorLeft::RegisterOnSignalChangeOfLeftDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event* leftDoorIsOpen02Callback)
{
if ( leftDoorIsOpen02Callback)
{
std::lock_guard<std::mutex> lock(m_leftDoorIsOpen02MutexCallbacks);
m_leftDoorIsOpen02Callbacks.insert(leftDoorIsOpen02Callback);
}
}
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void CBasicServiceRearDoorLeft::UnregisterOnSignalChangeOfLeftDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event* leftDoorIsOpen02Callback)
{
if (leftDoorIsOpen02Callback)
{
std::lock_guard<std::mutex> lock(m_leftDoorIsOpen02MutexCallbacks);
m_leftDoorIsOpen02Callbacks.erase(leftDoorIsOpen02Callback);
}
}
/**
* @brief Lock
* @param[in] value
* @return true on success otherwise false
*/
bool CBasicServiceRearDoorLeft::SetLock(bool value)
{
return m_ptrLock->WriteLock(value);
}

View File

@@ -0,0 +1,95 @@
/**
* @file bs_rear_door_left.h
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#ifndef __VSS_GENERATED__BS_REARDOORLEFT_H_20250711_125718_611__
#define __VSS_GENERATED__BS_REARDOORLEFT_H_20250711_125718_611__
#include <iostream>
#include <set>
#include <support/component_impl.h>
#include <support/signal_support.h>
#include "vss_vehiclechassisdooraxle02left_bs_rx.h"
#include "vss_vehiclechassisdooraxle02left_vd_tx.h"
#include "vss_vehiclechassisdooraxle02left_bs_tx.h"
/**
* @brief Basic Service Vehicle.Chassis.Door.Axle02.Left
*/
class CBasicServiceRearDoorLeft
: public sdv::CSdvObject
, public vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_GetIsOpen
, public vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::LeftDevice::IVSS_WriteIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetLock
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_GetIsOpen)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetLock)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("Vehicle.Chassis.Door.Axle02.Left_Service")
/**
* @brief Constructor
*/
CBasicServiceRearDoorLeft();
/**
* @brief User-Defined Destructor
*/
~CBasicServiceRearDoorLeft();
/**
* @brief Set rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenL2(bool value) override;
/**
* @brief Set leftLatch02 signal
* @param[in] value
* @return true on success otherwise false
*/
bool SetLock(bool value) override;
/**
* @brief Get rightDoorIsOpen
* @return Returns the rightDoorIsOpen
*/
bool GetIsOpen() const override;
/**
* @brief Write rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void WriteIsOpen(bool value) override;
/**
* @brief Register CallBack function on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfLeftDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event* callback) override;
/**
* @brief Unregister CallBack function on signal change
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfLeftDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event* callback) override;
private:
bool m_leftDoorIsOpen02 { 0 };
mutable std::mutex m_leftDoorIsOpen02MutexCallbacks; ///< Mutex protecting m_leftDoorIsOpen02Callbacks
std::set<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event*> m_leftDoorIsOpen02Callbacks; ///< collection of events to be called
vss::Vehicle::Chassis::Door::Axle02::LeftDevice::IVSS_WriteLock* m_ptrLock = nullptr;
};
DEFINE_SDV_OBJECT(CBasicServiceRearDoorLeft)
#endif // !define __VSS_GENERATED__BS_REARDOORLEFT_H_20250711_125718_611__

View File

@@ -0,0 +1,49 @@
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
# Define project
project(doors_bs_reardoorright VERSION 1.0 LANGUAGES CXX)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Libary symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set target name.
set(TARGET_NAME doors_bs_reardoorright)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
include_directories(../../interfaces)
# Set platform specific compile flags
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/W4 /WX /wd4996 /wd4100 /permissive- /Zc:rvalueCast)
else()
add_compile_options(-Werror -Wall -Wextra -Wshadow -Wpedantic -Wunreachable-code -fno-common)
endif()
# Add the dynamic library
add_library(${TARGET_NAME} SHARED
bs_rear_door_right.h
bs_rear_door_right.cpp)
# Set extension to .sdv
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".sdv")
# TODO: set target name.
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)

View File

@@ -0,0 +1,115 @@
/**
* @file bs_rear_door_right.cpp
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <iostream>
#include "bs_rear_door_right.h"
/**
* @brief ConstructorF
*/
CBasicServiceRearDoorRight::CBasicServiceRearDoorRight()
{
auto rightDoorIsOpen02Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightDevice::IVSS_IsOpen>();
if (!rightDoorIsOpen02Device)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_IsOpen': [CBasicServiceRearDoorRight]");
throw std::runtime_error("Vehicle.Chassis.Door.Axle02.Right mode device not found");
}
rightDoorIsOpen02Device->RegisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::RightDevice::IVSS_WriteIsOpen_Event*> (this));
m_ptrLock = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightDevice::IVSS_WriteLock>();
if (!m_ptrLock)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_WriteLock': [CBasicServiceRearDoorRight]");
throw std::runtime_error("Lock device not found");
}
SDV_LOG_TRACE("CBasicServiceRearDoorRight created: [Vehicle.Chassis.Door.Axle02.Right_Device]");
m_rightDoorIsOpen02 = 0;
}
/**
* @brief User-Defined Destructor
*/
CBasicServiceRearDoorRight::~CBasicServiceRearDoorRight()
{
auto rightDoorIsOpen02Device = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightDevice::IVSS_IsOpen>();
if (rightDoorIsOpen02Device)
{
rightDoorIsOpen02Device->UnregisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::RightDevice::IVSS_WriteIsOpen_Event*> (this));
}
rightDoorIsOpen02Device = nullptr;
}
/**
* @brief Set rightDoorIsOpen
* @param[in] value rightDoorIsOpen
*/
void CBasicServiceRearDoorRight::SetIsOpenR2(bool value)
{
m_rightDoorIsOpen02 = value;
std::lock_guard<std::mutex> lock(m_rightDoorIsOpen02MutexCallbacks);
for (auto callback : m_rightDoorIsOpen02Callbacks)
{
callback->SetIsOpenR2(value);
}
}
/**
* @brief Write rightDoorIsOpen
* @param[in] value rightDoorIsOpen
*/
void CBasicServiceRearDoorRight::WriteIsOpen(bool value)
{
SetIsOpenR2(value);
}
/**
* @brief Get rightDoorIsOpen
* @return Returns the rightDoorIsOpen
*/
bool CBasicServiceRearDoorRight::GetIsOpen() const
{
return m_rightDoorIsOpen02;
}
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void CBasicServiceRearDoorRight::RegisterOnSignalChangeOfRightDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event* rightDoorIsOpen02Callback)
{
if ( rightDoorIsOpen02Callback)
{
std::lock_guard<std::mutex> lock(m_rightDoorIsOpen02MutexCallbacks);
m_rightDoorIsOpen02Callbacks.insert(rightDoorIsOpen02Callback);
}
}
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void CBasicServiceRearDoorRight::UnregisterOnSignalChangeOfRightDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event* rightDoorIsOpen02Callback)
{
if (rightDoorIsOpen02Callback)
{
std::lock_guard<std::mutex> lock(m_rightDoorIsOpen02MutexCallbacks);
m_rightDoorIsOpen02Callbacks.erase(rightDoorIsOpen02Callback);
}
}
/**
* @brief Lock
* @param[in] value
* @return true on success otherwise false
*/
bool CBasicServiceRearDoorRight::SetLock(bool value)
{
return m_ptrLock->WriteLock(value);
}

View File

@@ -0,0 +1,95 @@
/**
* @file bs_rear_door_right.h
* @date 2025-07-11 12:57:18
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#ifndef __VSS_GENERATED__BS_REARDOORRIGHT_H_20250711_125718_616__
#define __VSS_GENERATED__BS_REARDOORRIGHT_H_20250711_125718_616__
#include <iostream>
#include <set>
#include <support/component_impl.h>
#include <support/signal_support.h>
#include "vss_vehiclechassisdooraxle02right_bs_rx.h"
#include "vss_vehiclechassisdooraxle02right_vd_tx.h"
#include "vss_vehiclechassisdooraxle02right_bs_tx.h"
/**
* @brief Basic Service Vehicle.Chassis.Door.Axle02.Right
*/
class CBasicServiceRearDoorRight
: public sdv::CSdvObject
, public vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_GetIsOpen
, public vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::RightDevice::IVSS_WriteIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetLock
{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_GetIsOpen)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetLock)
END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("Vehicle.Chassis.Door.Axle02.Right_Service")
/**
* @brief Constructor
*/
CBasicServiceRearDoorRight();
/**
* @brief User-Defined Destructor
*/
~CBasicServiceRearDoorRight();
/**
* @brief Set rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR2(bool value) override;
/**
* @brief Set rightLatch02 signal
* @param[in] value
* @return true on success otherwise false
*/
bool SetLock(bool value) override;
/**
* @brief Get rightDoorIsOpen
* @return Returns the rightDoorIsOpen
*/
bool GetIsOpen() const override;
/**
* @brief Write rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void WriteIsOpen(bool value) override;
/**
* @brief Register CallBack function on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfRightDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event* callback) override;
/**
* @brief Unregister CallBack function on signal change
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfRightDoorIsOpen02(vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event* callback) override;
private:
bool m_rightDoorIsOpen02 { 0 };
mutable std::mutex m_rightDoorIsOpen02MutexCallbacks; ///< Mutex protecting m_rightDoorIsOpen02Callbacks
std::set<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event*> m_rightDoorIsOpen02Callbacks; ///< collection of events to be called
vss::Vehicle::Chassis::Door::Axle02::RightDevice::IVSS_WriteLock* m_ptrLock = nullptr;
};
DEFINE_SDV_OBJECT(CBasicServiceRearDoorRight)
#endif // !define __VSS_GENERATED__BS_REARDOORRIGHT_H_20250711_125718_616__

View File

@@ -0,0 +1,42 @@
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
# Define project
project(can_dl_door VERSION 1.0 LANGUAGES CXX)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Library symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
# Set platform specific compile flags
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/W4 /WX /wd4996 /wd4100 /permissive- /Zc:rvalueCast)
else()
add_compile_options(-Werror -Wall -Wextra -Wshadow -Wpedantic -Wunreachable-code -fno-common)
endif()
# Add the dynamic library
add_library(can_dl_door SHARED
datalink.cpp
datalink.h)
# Set extension to .sdv
set_target_properties(can_dl_door PROPERTIES PREFIX "")
set_target_properties(can_dl_door PROPERTIES SUFFIX ".sdv")

View File

@@ -0,0 +1,412 @@
/**
* @file datalink.cpp
* @date 2025-09-06 08:00:37
* This file implements the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* "", "datalink_4doors_example.dbc"
* DBC file version: 1.0.0.1
*/
#include "datalink.h"
#include <algorithm>
#include <cmath>
#ifdef _MSC_VER
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#endif
CDataLink::CDataLink() :
m_sRxMsgCAN_Input_L1(m_dispatch),
m_sRxMsgCAN_Input_R1(m_dispatch),
m_sRxMsgCAN_Input_L2(m_dispatch),
m_sRxMsgCAN_Input_R2(m_dispatch),
m_sTxMsgCAN_Output(m_dispatch)
{}
CDataLink::~CDataLink()
{
Shutdown(); // Just in case
}
void CDataLink::Initialize(const sdv::u8string& /*ssObjectConfig*/)
{
if (m_eStatus != sdv::EObjectStatus::initialization_pending) return;
// Get the CAN communication object.
sdv::TInterfaceAccessPtr ptrCANObject = sdv::core::GetObject("CAN_Communication_Object");
if (!ptrCANObject)
{
SDV_LOG_ERROR("CDataLink::Initialize() failure, 'CAN_Communication_Object' not found");
m_eStatus = sdv::EObjectStatus::initialization_failure;
return;
}
// Get the CAN receiver registration interface.
m_pRegister = ptrCANObject.GetInterface<sdv::can::IRegisterReceiver>();
if (!m_pRegister)
{
SDV_LOG_ERROR("CDataLink::Initialize() failure, 'sdv::can::IRegisterReceiver' interface not found");
m_eStatus = sdv::EObjectStatus::initialization_failure;
return;
}
m_pRegister->RegisterReceiver(static_cast<sdv::can::IReceive*>(this));
// Get the CAN transmit interface
m_pSend = ptrCANObject.GetInterface<sdv::can::ISend>();
if (!m_pSend)
{
SDV_LOG_ERROR("CDataLink::Initialize() failure, 'sdv::can::ISend' interface not found");
m_eStatus = sdv::EObjectStatus::initialization_failure;
return;
}
// Initialize messages
bool bSuccess = true;
bSuccess &= m_sRxMsgCAN_Input_L1.Init();
bSuccess &= m_sRxMsgCAN_Input_R1.Init();
bSuccess &= m_sRxMsgCAN_Input_L2.Init();
bSuccess &= m_sRxMsgCAN_Input_R2.Init();
bSuccess &= m_sTxMsgCAN_Output.Init(m_pSend);
m_eStatus = bSuccess ? sdv::EObjectStatus::initialized : sdv::EObjectStatus::initialization_failure;
}
sdv::EObjectStatus CDataLink::GetStatus() const
{
return m_eStatus;
}
void CDataLink::SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eStatus == sdv::EObjectStatus::running || m_eStatus == sdv::EObjectStatus::initialized)
m_eStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eStatus == sdv::EObjectStatus::configuring || m_eStatus == sdv::EObjectStatus::initialized)
m_eStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
void CDataLink::Shutdown()
{
m_eStatus = sdv::EObjectStatus::shutdown_in_progress;
// Unregister receiver interface.
if (m_pRegister) m_pRegister->UnregisterReceiver(static_cast<sdv::can::IReceive*>(this));
m_pRegister = nullptr;
m_pSend = nullptr;
// Terminate messages
m_sRxMsgCAN_Input_L1.Term();
m_sRxMsgCAN_Input_R1.Term();
m_sRxMsgCAN_Input_L2.Term();
m_sRxMsgCAN_Input_R2.Term();
m_sTxMsgCAN_Output.Term();
// Update the status
m_eStatus = sdv::EObjectStatus::destruction_pending;
}
void CDataLink::Receive(/*in*/ [[maybe_unused]] const sdv::can::SMessage& sMsg, /*in*/ uint32_t uiIfcIndex)
{
if (static_cast<size_t>(uiIfcIndex) != m_nIfcIndex) return;
switch (sMsg.uiID)
{
case 1: // CAN_Input_L1
m_sRxMsgCAN_Input_L1.Process(sMsg.seqData);
break;
case 2: // CAN_Input_R1
m_sRxMsgCAN_Input_R1.Process(sMsg.seqData);
break;
case 3: // CAN_Input_L2
m_sRxMsgCAN_Input_L2.Process(sMsg.seqData);
break;
case 4: // CAN_Input_R2
m_sRxMsgCAN_Input_R2.Process(sMsg.seqData);
break;
default:
break;
}
}
void CDataLink::Error(/*in*/ [[maybe_unused]] const sdv::can::SErrorFrame& sError, /*in*/ uint32_t uiIfcIndex)
{
if (static_cast<size_t>(uiIfcIndex) != m_nIfcIndex) return;
// TODO: Currently no error frame handling...
}
CDataLink::SRxMsg_CAN_Input_L1::SRxMsg_CAN_Input_L1(sdv::core::CDispatchService& rdispatch) :
m_rdispatch(rdispatch)
{}
bool CDataLink::SRxMsg_CAN_Input_L1::Init()
{
// Register signals
[[maybe_unused]] bool bSuccess = true;
m_sigDoor01LeftIsOpen = m_rdispatch.RegisterRxSignal("CAN_Input_L1.Door01LeftIsOpen");
bSuccess &= m_sigDoor01LeftIsOpen ? true : false;
return bSuccess;
}
void CDataLink::SRxMsg_CAN_Input_L1::Term()
{
// Unregister signals
m_sigDoor01LeftIsOpen.Reset();
}
void CDataLink::SRxMsg_CAN_Input_L1::Process(const sdv::sequence<uint8_t>& rseqData)
{
// Check for the correct size.
if (rseqData.size() != 1)
{
// TODO: Error. Delivered data has different size as compared to the specification.
return;
}
// Helper variable
[[maybe_unused]] UValueHelper uValueHelper;
// Start a transaction
sdv::core::CTransaction transaction = m_rdispatch.CreateTransaction();
// Process CAN_Input_L1.Door01LeftIsOpen
uValueHelper.uiUint64Value = rseqData[0] & 3;
uValueHelper.uiUint64Value >>= 1;
m_sigDoor01LeftIsOpen.Write(std::min(std::max(uValueHelper.s32.u32.uiValue, 0u), 1u), transaction);
// Finalize the transaction
transaction.Finish();
}
CDataLink::SRxMsg_CAN_Input_R1::SRxMsg_CAN_Input_R1(sdv::core::CDispatchService& rdispatch) :
m_rdispatch(rdispatch)
{}
bool CDataLink::SRxMsg_CAN_Input_R1::Init()
{
// Register signals
[[maybe_unused]] bool bSuccess = true;
m_sigDoor01RightIsOpen = m_rdispatch.RegisterRxSignal("CAN_Input_R1.Door01RightIsOpen");
bSuccess &= m_sigDoor01RightIsOpen ? true : false;
return bSuccess;
}
void CDataLink::SRxMsg_CAN_Input_R1::Term()
{
// Unregister signals
m_sigDoor01RightIsOpen.Reset();
}
void CDataLink::SRxMsg_CAN_Input_R1::Process(const sdv::sequence<uint8_t>& rseqData)
{
// Check for the correct size.
if (rseqData.size() != 1)
{
// TODO: Error. Delivered data has different size as compared to the specification.
return;
}
// Helper variable
[[maybe_unused]] UValueHelper uValueHelper;
// Start a transaction
sdv::core::CTransaction transaction = m_rdispatch.CreateTransaction();
// Process CAN_Input_R1.Door01RightIsOpen
uValueHelper.uiUint64Value = rseqData[0] & 15;
uValueHelper.uiUint64Value >>= 3;
m_sigDoor01RightIsOpen.Write(std::min(std::max(uValueHelper.s32.u32.uiValue, 0u), 1u), transaction);
// Finalize the transaction
transaction.Finish();
}
CDataLink::SRxMsg_CAN_Input_L2::SRxMsg_CAN_Input_L2(sdv::core::CDispatchService& rdispatch) :
m_rdispatch(rdispatch)
{}
bool CDataLink::SRxMsg_CAN_Input_L2::Init()
{
// Register signals
[[maybe_unused]] bool bSuccess = true;
m_sigDoor02LeftIsOpen = m_rdispatch.RegisterRxSignal("CAN_Input_L2.Door02LeftIsOpen");
bSuccess &= m_sigDoor02LeftIsOpen ? true : false;
return bSuccess;
}
void CDataLink::SRxMsg_CAN_Input_L2::Term()
{
// Unregister signals
m_sigDoor02LeftIsOpen.Reset();
}
void CDataLink::SRxMsg_CAN_Input_L2::Process(const sdv::sequence<uint8_t>& rseqData)
{
// Check for the correct size.
if (rseqData.size() != 1)
{
// TODO: Error. Delivered data has different size as compared to the specification.
return;
}
// Helper variable
[[maybe_unused]] UValueHelper uValueHelper;
// Start a transaction
sdv::core::CTransaction transaction = m_rdispatch.CreateTransaction();
// Process CAN_Input_L2.Door02LeftIsOpen
uValueHelper.uiUint64Value = rseqData[0] & 63;
uValueHelper.uiUint64Value >>= 5;
m_sigDoor02LeftIsOpen.Write(std::min(std::max(uValueHelper.s32.u32.uiValue, 0u), 1u), transaction);
// Finalize the transaction
transaction.Finish();
}
CDataLink::SRxMsg_CAN_Input_R2::SRxMsg_CAN_Input_R2(sdv::core::CDispatchService& rdispatch) :
m_rdispatch(rdispatch)
{}
bool CDataLink::SRxMsg_CAN_Input_R2::Init()
{
// Register signals
[[maybe_unused]] bool bSuccess = true;
m_sigDoor02RightIsOpen = m_rdispatch.RegisterRxSignal("CAN_Input_R2.Door02RightIsOpen");
bSuccess &= m_sigDoor02RightIsOpen ? true : false;
return bSuccess;
}
void CDataLink::SRxMsg_CAN_Input_R2::Term()
{
// Unregister signals
m_sigDoor02RightIsOpen.Reset();
}
void CDataLink::SRxMsg_CAN_Input_R2::Process(const sdv::sequence<uint8_t>& rseqData)
{
// Check for the correct size.
if (rseqData.size() != 1)
{
// TODO: Error. Delivered data has different size as compared to the specification.
return;
}
// Helper variable
[[maybe_unused]] UValueHelper uValueHelper;
// Start a transaction
sdv::core::CTransaction transaction = m_rdispatch.CreateTransaction();
// Process CAN_Input_R2.Door02RightIsOpen
uValueHelper.uiUint64Value = rseqData[0];
uValueHelper.uiUint64Value >>= 7;
m_sigDoor02RightIsOpen.Write(std::min(std::max(uValueHelper.s32.u32.uiValue, 0u), 1u), transaction);
// Finalize the transaction
transaction.Finish();
}
CDataLink::STxMsg_CAN_Output::STxMsg_CAN_Output(sdv::core::CDispatchService& rdispatch) :
m_rdispatch(rdispatch)
{}
bool CDataLink::STxMsg_CAN_Output::Init(sdv::can::ISend* pSend)
{
if (!pSend) return false;
m_pSend = pSend;
// Register signals
bool bSuccess = true;
m_sigLockDoor02Right = m_rdispatch.RegisterTxSignal("CAN_Output.LockDoor02Right", sdv::any_t());
bSuccess &= m_sigLockDoor02Right ? true : false;
m_sigLockDoor02Left = m_rdispatch.RegisterTxSignal("CAN_Output.LockDoor02Left", sdv::any_t());
bSuccess &= m_sigLockDoor02Left ? true : false;
m_sigLockDoor01Right = m_rdispatch.RegisterTxSignal("CAN_Output.LockDoor01Right", sdv::any_t());
bSuccess &= m_sigLockDoor01Right ? true : false;
m_sigLockDoor01Left = m_rdispatch.RegisterTxSignal("CAN_Output.LockDoor01Left", sdv::any_t());
bSuccess &= m_sigLockDoor01Left ? true : false;
// Initialize the trigger
m_trigger = m_rdispatch.CreateTxTrigger([&] { Transmit(); }, false, 0, 10, false);
m_trigger.AddSignal(m_sigLockDoor02Right);
m_trigger.AddSignal(m_sigLockDoor02Left);
m_trigger.AddSignal(m_sigLockDoor01Right);
m_trigger.AddSignal(m_sigLockDoor01Left);
bSuccess &= m_trigger;
return bSuccess;
}
void CDataLink::STxMsg_CAN_Output::Term()
{
// Reset the trigger
m_trigger.Reset();
// Unregister signals
m_sigLockDoor02Right.Reset();
m_sigLockDoor02Left.Reset();
m_sigLockDoor01Right.Reset();
m_sigLockDoor01Left.Reset();
}
void CDataLink::STxMsg_CAN_Output::Transmit()
{
if (!m_pSend) return;
// Compose CAN message
sdv::can::SMessage msg;
msg.uiID = 5;
msg.bExtended = false;
msg.bCanFd = false; // TODO: Currently not supported
msg.seqData.resize(1);
std::fill(msg.seqData.begin(), msg.seqData.end(), static_cast<uint8_t>(0));
// Helper variable
[[maybe_unused]] UValueHelper uValueHelper;
// Start a transaction
sdv::core::CTransaction transaction = m_rdispatch.CreateTransaction();
// Compose CAN_Output.LockDoor02Right
uValueHelper.s32.u32.uiValue = static_cast<uint32_t>(std::min(std::max(static_cast<long long int>(m_sigLockDoor02Right.Read(transaction)), 0ll), 1ll));
uValueHelper.uiUint64Value <<= 7;
msg.seqData[0] |= uValueHelper.uiUint64Value & 0xff;
// Compose CAN_Output.LockDoor02Left
uValueHelper.s32.u32.uiValue = static_cast<uint32_t>(std::min(std::max(static_cast<long long int>(m_sigLockDoor02Left.Read(transaction)), 0ll), 1ll));
uValueHelper.uiUint64Value <<= 5;
msg.seqData[0] |= uValueHelper.uiUint64Value & 63;
// Compose CAN_Output.LockDoor01Right
uValueHelper.s32.u32.uiValue = static_cast<uint32_t>(std::min(std::max(static_cast<long long int>(m_sigLockDoor01Right.Read(transaction)), 0ll), 1ll));
uValueHelper.uiUint64Value <<= 3;
msg.seqData[0] |= uValueHelper.uiUint64Value & 15;
// Compose CAN_Output.LockDoor01Left
uValueHelper.s32.u32.uiValue = static_cast<uint32_t>(std::min(std::max(static_cast<long long int>(m_sigLockDoor01Left.Read(transaction)), 0ll), 1ll));
uValueHelper.uiUint64Value <<= 1;
msg.seqData[0] |= uValueHelper.uiUint64Value & 3;
// Finalize the transaction
transaction.Finish();
// Transmit the message
// TODO: Determine CAN interface index...
m_pSend->Send(msg, 0);
}

View File

@@ -0,0 +1,300 @@
/**
* @file datalink.h
* @date 2025-09-06 08:00:37
* This file defines the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* "", "datalink_4doors_example.dbc"
* DBC file version: 1.0.0.1
*/
#ifndef __DBC_GENERATED__DATALINK_H__20250906_080037_856__
#define __DBC_GENERATED__DATALINK_H__20250906_080037_856__
#include <support/component_impl.h>
#include <interfaces/can.h>
#include <support/interface_ptr.h>
#include <support/signal_support.h>
/**
* @brief Data link class.
*/
class CDataLink : public sdv::CSdvObject, public sdv::IObjectControl, public sdv::can::IReceive
{
public:
/**
* @brief Constructor
*/
CDataLink();
/**
* @brief Destructor
*/
~CDataLink();
// Interface map
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
SDV_INTERFACE_ENTRY(sdv::can::IReceive)
END_SDV_INTERFACE_MAP()
// Declarations
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("CAN_data_link")
DECLARE_DEFAULT_OBJECT_NAME("DataLink")
DECLARE_OBJECT_SINGLETON()
/**
* @brief Initialize the object. Overload of sdv::IObjectControl::Initialize.
* @param[in] ssObjectConfig Optional configuration string.
*/
void Initialize(const sdv::u8string& ssObjectConfig) override;
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
*/
sdv::EObjectStatus GetStatus() const override;
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode) override;
/**
* @brief Shutdown called before the object is destroyed. Overload of sdv::IObjectControl::Shutdown.
*/
void Shutdown() override;
/**
* @brief Process a receive a CAN message. Overload of sdv::can::IReceive::Receive.
* @param[in] sMsg Message that was received.
* @param[in] uiIfcIndex Interface index of the received message.
*/
virtual void Receive(/*in*/ const sdv::can::SMessage& sMsg, /*in*/ uint32_t uiIfcIndex) override;
/**
* @brief Process an error frame. Overload of sdv::can::IReceive::Error.
* @param[in] sError Error frame that was received.
* @param[in] uiIfcIndex Interface index of the received message.
*/
virtual void Error(/*in*/ const sdv::can::SErrorFrame& sError, /*in*/ uint32_t uiIfcIndex) override;
private:
/**
* @brief Union containing all the compound values needed to convert between the DBC defined types.
*/
union UValueHelper
{
uint64_t uiUint64Value; ///< The 64-bit unsingned value.
int64_t iInt64Value; ///< The 64-bit signed value.
/**
* @brief The structure mapping the 32-bit value types into the 64-bit.
*/
struct S32
{
#if (!defined(_MSC_VER) || defined(__clang__)) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
uint32_t uiPadding; ///< Padding for big endian byte ordering (MSB)
#endif
/**
* @brief The 32-bit union containing the possible 32-bit values.
*/
union U32Value
{
int32_t iValue; ///< 32-bit signed integer.
uint32_t uiValue; ///< 32-bit unsigned integer.
float fValue; ///< 32-bit floating point number.
} u32; ///< 32-bit union instance.
#if (defined(_MSC_VER) && !defined(__clang__)) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
uint32_t uiPadding; ///< Padding for little endian byte ordering (MSB)
#endif
} s32;
double dValue; ///< 64-bit double precision floating point number.
};
/**
* @brief RX CAN message definition of: CAN_Input_L1 [id=1]
*/
struct SRxMsg_CAN_Input_L1
{
/**
* @brief Constructor
* @param[in] rdispatch Reference to the dispatch service.
*/
SRxMsg_CAN_Input_L1(sdv::core::CDispatchService& rdispatch);
/**
* @brief Initialize the message by registering all signals.
*/
bool Init();
/**
* @brief Terminate the message by unregistering all signals.
*/
void Term();
/**
* @brief Process received data.
* @param[in] rseqData Reference to the message data to process.
*/
void Process(const sdv::sequence<uint8_t>& rseqData);
sdv::core::CDispatchService& m_rdispatch; ///< Reference to the dispatch service.
/// Signal Door01LeftIsOpen with unit
sdv::core::CSignal m_sigDoor01LeftIsOpen;
} m_sRxMsgCAN_Input_L1;
/**
* @brief RX CAN message definition of: CAN_Input_R1 [id=2]
*/
struct SRxMsg_CAN_Input_R1
{
/**
* @brief Constructor
* @param[in] rdispatch Reference to the dispatch service.
*/
SRxMsg_CAN_Input_R1(sdv::core::CDispatchService& rdispatch);
/**
* @brief Initialize the message by registering all signals.
*/
bool Init();
/**
* @brief Terminate the message by unregistering all signals.
*/
void Term();
/**
* @brief Process received data.
* @param[in] rseqData Reference to the message data to process.
*/
void Process(const sdv::sequence<uint8_t>& rseqData);
sdv::core::CDispatchService& m_rdispatch; ///< Reference to the dispatch service.
/// Signal Door01RightIsOpen with unit
sdv::core::CSignal m_sigDoor01RightIsOpen;
} m_sRxMsgCAN_Input_R1;
/**
* @brief RX CAN message definition of: CAN_Input_L2 [id=3]
*/
struct SRxMsg_CAN_Input_L2
{
/**
* @brief Constructor
* @param[in] rdispatch Reference to the dispatch service.
*/
SRxMsg_CAN_Input_L2(sdv::core::CDispatchService& rdispatch);
/**
* @brief Initialize the message by registering all signals.
*/
bool Init();
/**
* @brief Terminate the message by unregistering all signals.
*/
void Term();
/**
* @brief Process received data.
* @param[in] rseqData Reference to the message data to process.
*/
void Process(const sdv::sequence<uint8_t>& rseqData);
sdv::core::CDispatchService& m_rdispatch; ///< Reference to the dispatch service.
/// Signal Door02LeftIsOpen with unit
sdv::core::CSignal m_sigDoor02LeftIsOpen;
} m_sRxMsgCAN_Input_L2;
/**
* @brief RX CAN message definition of: CAN_Input_R2 [id=4]
*/
struct SRxMsg_CAN_Input_R2
{
/**
* @brief Constructor
* @param[in] rdispatch Reference to the dispatch service.
*/
SRxMsg_CAN_Input_R2(sdv::core::CDispatchService& rdispatch);
/**
* @brief Initialize the message by registering all signals.
*/
bool Init();
/**
* @brief Terminate the message by unregistering all signals.
*/
void Term();
/**
* @brief Process received data.
* @param[in] rseqData Reference to the message data to process.
*/
void Process(const sdv::sequence<uint8_t>& rseqData);
sdv::core::CDispatchService& m_rdispatch; ///< Reference to the dispatch service.
/// Signal Door02RightIsOpen with unit
sdv::core::CSignal m_sigDoor02RightIsOpen;
} m_sRxMsgCAN_Input_R2;
/**
* @brief TX CAN message definition of: CAN_Output [id=5]
*/
struct STxMsg_CAN_Output
{
/**
* @brief Constructor
* @param[in] rdispatch Reference to the dispatch service.
*/
STxMsg_CAN_Output(sdv::core::CDispatchService& rdispatch);
/**
* @brief Initialize the message by registering all signals.
* @param[in] pSend The send-interface of the CAN.
*/
bool Init(sdv::can::ISend* pSend);
/**
* @brief Terminate the message by unregistering all signals.
*/
void Term();
/**
* @brief Transmit data.
* @param[in] pCanSend Pointer to the CAN send interface.
*/
void Transmit();
sdv::core::CDispatchService& m_rdispatch; ///< Reference to the dispatch service.
sdv::core::CTrigger m_trigger; ///< Message trigger being called by the dispatch service.
sdv::can::ISend* m_pSend = nullptr; ///< Message sending interface.
/// Signal LockDoor02Right with unit
sdv::core::CSignal m_sigLockDoor02Right;
/// Signal LockDoor02Left with unit
sdv::core::CSignal m_sigLockDoor02Left;
/// Signal LockDoor01Right with unit
sdv::core::CSignal m_sigLockDoor01Right;
/// Signal LockDoor01Left with unit
sdv::core::CSignal m_sigLockDoor01Left;
} m_sTxMsgCAN_Output;
sdv::EObjectStatus m_eStatus = sdv::EObjectStatus::initialization_pending; ///< Keep track of the object status.
size_t m_nIfcIndex = 0; ///< CAN Interface index.
sdv::can::IRegisterReceiver* m_pRegister = nullptr; ///< CAN receiver registration interface.
sdv::can::ISend* m_pSend = nullptr; ///< CAN sender interface.
sdv::core::CDispatchService m_dispatch; ///< Dispatch service
};
DEFINE_SDV_OBJECT(CDataLink)
#endif // !defined __DBC_GENERATED__DATALINK_H__20250906_080037_856__

View File

@@ -0,0 +1,8 @@
[Configuration]
Version = 100
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"

View File

@@ -0,0 +1,12 @@
[Configuration]
Version = 100
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
Source="door_example_receiver.asc"
Target="door_example_writer.asc"
[[Component]]
Path = "can_dl_door.sdv"
Class = "CAN_data_link"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "door_complex_service.sdv"
Class = "Doors Example Service"

View File

@@ -0,0 +1,14 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Device"
[[Component]]
Path = "doors_bs_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Service"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Device"
[[Component]]
Path = "doors_bs_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Service"

View File

@@ -0,0 +1,14 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Device"
[[Component]]
Path = "doors_bs_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Service"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Device"
[[Component]]
Path = "doors_bs_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Service"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"

View File

@@ -0,0 +1,12 @@
[Configuration]
Version = 100
[[Component]]
Path = "door_complex_service.sdv"
Class = "Doors Example Service"
Name = "Doors Example Service"
[[Module]]
Path = "doors_service_proxystub.sdv"

View File

@@ -0,0 +1,9 @@
[Configuration]
Version = 100
[[Component]]
Path = "can_com_sim.sdv"
Class = "CAN_Com_Sim"
Source="door_example_receiver.asc"
Target="door_example_writer.asc"

View File

@@ -0,0 +1,28 @@
# Settings file
[Settings]
Version = 100
# The system config array can contain zero or more configurations that are loaded at the time
# the system ist started. It is advisable to split the configurations in:
# platform config - containing all the components needed to interact with the OS,
# middleware, vehicle bus, Ethernet.
# vehicle interface - containing the vehicle bus interpretation components like data link
# based on DBC and devices for their abstraction.
# vehicle abstraction - containing the basic services
# Load the system configurations by providing the "SystemConfig" keyword as an array of strings.
# A relative path is relative to the installation directory (being "exe_location/instance_id").
#
# Example:
# SystemConfig = [ "platform.toml", "vehicle_ifc.toml", "vehicle_abstract.toml" ]
SystemConfig = [ "platform.toml", "vehicle_ifc.toml", "vehicle_abstract.toml"]
# The application config contains the configuration file that can be updated when services and
# apps are being added to the system (or being removed from the system). Load the application
# config by providing the "AppConfig" keyword as a string value. A relative path is relative to
# the installation directory (being "exe_location/instance_id").
#
# Example
# AppConfig = "app_config.toml"
#
AppConfig = "door_demo.toml"

View File

@@ -0,0 +1,26 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_bs_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Service"
Name = "Vehicle.Chassis.Door.Axle01.Left_Service"
[[Component]]
Path = "doors_bs_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Service"
Name = "Vehicle.Chassis.Door.Axle01.Right_Service"
[[Component]]
Path = "doors_bs_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Service"
Name = "Vehicle.Chassis.Door.Axle02.Left_Service"
[[Component]]
Path = "doors_bs_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Service"
Name = "Vehicle.Chassis.Door.Axle02.Right_Service"
[[Module]]
Path = "doors_proxystub.sdv"

View File

@@ -0,0 +1,28 @@
[Configuration]
Version = 100
[[Component]]
Path = "can_dl_door.sdv"
Class = "CAN_data_link"
Name = "DataLink"
[[Component]]
Path = "doors_vd_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Device"
Name = "Vehicle.Chassis.Door.Axle01.Left_Device"
[[Component]]
Path = "doors_vd_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Device"
Name = "Vehicle.Chassis.Door.Axle01.Right_Device"
[[Component]]
Path = "doors_vd_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Device"
Name = "Vehicle.Chassis.Door.Axle02.Left_Device"
[[Component]]
Path = "doors_vd_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Device"
Name = "Vehicle.Chassis.Door.Axle02.Right_Device"

View File

@@ -0,0 +1,131 @@
VERSION "PrivateCAN"
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: doors
VAL_TABLE_ Fault_Codes 27 "UKWN" 26 "VEHSPDMAX_EXDD" 25 "STS_ALIVE" 24 "STEER_NOT_E2E_MODE" 23 "OTA_SPD" 22 "OTA_TIMER_DOWNLOAD_FAILED" 21 "OTA_MAX_TIME" 20 "CUBIXAD_STEERSTREQ_NOTACTV" 19 "CUBIXAD_DRVSTREQ_NOTACTV" 18 "SFTYDRV_INTV" 17 "LSDC_ALIVE" 16 "CUBIXAD_ALIVE" 15 "IBC_MAB_NO_PRIO" 14 "IBC_NOT_RDY" 13 "IBC_ALIVE" 12 "LSDC_GEAR" 11 "LSDC_SPD" 10 "LSDC_ACCL" 9 "IBC_NOT_MAB_MOD" 8 "GOLDBOX_ALIVE" 7 "CUBIXAD_GEAR" 6 "CUBIXAD_SPD_TESTTRACK" 5 "DRVREQCHG" 4 "RDY_TIMER" 3 "SFTY_CDN_FAILED" 2 "ACTVNCHK_SPD" 1 "ACTVNCHK_TIMR" 0 "NONE" ;
VAL_TABLE_ TestMapID 6 "E_TESTMAPID_UNDEFINED" 5 "E_TESTMAPID_TEST_DRIVE" 4 "E_TESTMAPID_AD_AREA" 3 "E_TESTMAPID_STUTT_ARENA" 2 "E_TESTMAPID_ZF_LASTMILE" 1 "E_TESTMAPID_ZF_TESTTRACK_2" 0 "E_TESTMAPID_NONE" ;
VAL_TABLE_ CtrlReqStates 7 "CtrlSts3b_RESERVED_4" 6 "CtrlSts3b_RESERVED_3" 5 "CtrlSts3b_RESERVED_2" 4 "CtrlSts3b_RESERVED_1" 3 "CtrlSts3b_ERROR" 2 "CtrlSts3b_CONTROL_REQUESTED" 1 "CtrlSts3b_CONTROL_NOT_REQUESTED" 0 "CtrlSts3b_INIT" ;
VAL_TABLE_ SteerActrReSts 7 "Diag" 6 "Inactive" 5 "Ramping" 4 "Yellow" 3 "Red" 2 "Normal" 1 "Pending" 0 "Initialisation" ;
VAL_TABLE_ SwtPark1 1 "SwtParkActv" 0 "SwtParkNotActv" ;
VAL_TABLE_ PE_State 2 "ERROR" 1 "INIT" 0 "NO_ERROR" ;
VAL_TABLE_ SSM_Req 7 "HMS_TAKEOVER" 6 "RESERVED" 5 "RELESE_VIA_RAMP" 4 "DRIVEOFF" 3 "HOLD_STANDBY" 2 "PARK" 1 "HOLD" 0 "NO_REQUEST" ;
VAL_TABLE_ IBC_StandStillMode 12 "SSM_ERROR" 11 "SSM_INIT" 10 "SSM_DRIVEOFF_STANDBY_ACTIVE" 9 "SSM_HOLD_STANDBY_ACTIVE" 8 "SSM_HILL_SLIPPOFF_DETECTED" 7 "SSM_RELEASE_REQ_FROM_DRIVER" 6 "SSM_RELEASE_REQ_ACTIVE" 5 "SSM_DRIVEOFF_ACTIVE" 4 "SSM_PARK_RETAINED_ACTIVE" 3 "SSM_PARK_ACTIVE" 2 "SSM_PARK_REQUESTED" 1 "SSM_HOLD_ACTIVE" 0 "SSM_NO_ACTIVE_FUNCTION" ;
VAL_TABLE_ AppTgtStDrv 3 "ACTIVE" 2 "READY" 1 "RESERVED" 0 "NOT_ACTIVE" ;
VAL_TABLE_ IBC_Status 4 "IBC_MAB_ERR_COMM" 3 "IBC_MAB_NO_PRIO" 2 "IBC_IN_MAB_MODE" 1 "IBC_READY" 0 "IBC_NOT_READY_FAILED" ;
VAL_TABLE_ GearLvrIndcn 7 "GearLvrIndcn2_Undefd" 6 "GearLvrIndcn2_Resd2" 5 "GearLvrIndcn2_Resd1" 4 "GearLvrIndcn2_ManModeIndcn" 3 "GearLvrIndcn2_DrvIndcn" 2 "GearLvrIndcn2_NeutIndcn" 1 "GearLvrIndcn2_RvsIndcn" 0 "GearLvrIndcn2_ParkIndcn" ;
VAL_TABLE_ LvlgAdjReq 7 "LvlgAdjReq_Resd2" 6 "LvlgAdjReq_Resd1" 5 "LvlgAdjReq_Ll2" 4 "LvlgAdjReq_Ll1" 3 "LvlgAdjReq_Nrh" 2 "LvlgAdjReq_Hl1" 1 "LvlgAdjReq_Hl2" 0 "LvlgAdjReq_Ukwn" ;
VAL_TABLE_ DrvModReq 15 "Err" 14 "Rock" 13 "Mud" 12 "Sand" 11 "Snow" 10 "Power" 9 "Hybrid" 8 "Pure_EV" 7 "Race" 6 "Adaptive" 5 "Offroad_CrossTerrain" 4 "Individual" 3 "Dynamic_Sport" 2 "Comfort_Normal" 1 "ECO" 0 "Undefd" ;
VAL_TABLE_ MAB_Info_Message 4 "DRV_GEARLVR_TO_P" 3 "DRV_P_TO_D" 2 "LSDC_DI_NOT_PSBL" 1 "LSDC_ENA_NOT_POSSIBLE" 0 "NONE" ;
VAL_TABLE_ MAB_OvrdTool_Sts 11 "HACKATHON" 10 "OTA" 9 "INIT" 8 "FINSHD" 7 "FLT" 6 "CUBIX_AD" 5 "SAVE_THE_SPOILER" 4 "LSDC" 3 "RDY" 2 "ACTVN_CHK" 1 "NO_MANIPULATION" 0 "NONE" ;
VAL_TABLE_ HMI_Drvr_Req 9 "FCT_DEACTVN_REQ" 8 "FCT_ACTVN_OTA_CFMD" 7 "FCT_ACTVN_OTA_REQ" 6 "FCT_ACTVN_SAVETHESPOILER_CFMD" 5 "FCT_ACTVN_SAVETHESPOILER_REQ" 4 "FCT_ACTVN_LSDC_CFMD" 3 "FCT_ACTVN_LSDC_REQ" 2 "FCT_ACTVN_CUBIXAD_CFMD" 1 "FCT_ACTVN_CUBIXAD_REQ" 0 "FCT_ACTVN_NONE" ;
VAL_TABLE_ Info_Message 4 "DRV_GEARLVR_TO_P" 3 "DRV_P_TO_D" 2 "LSDC_DI_NOT_PSBL" 1 "LSDC_ENA_NOT_POSSIBLE" 0 "NONE" ;
VAL_TABLE_ HMI_Fct_Req 8 "FCT_DEACTVN_REQ" 7 "FCT_ACTVN_OTA_REQ" 6 "FCT_ACTVN_SAVETHESPOILER_CFMD" 5 "FCT_ACTVN_SAVETHESPOILER_REQ" 4 "FCT_ACTVN_LSDC_CFMD" 3 "FCT_ACTVN_LSDC_REQ" 2 "FCT_ACTVN_AI4MTN_CFMD" 1 "FCT_ACTVN_AI4MTN_REQ" 0 "FCT_ACTVN_NONE" ;
VAL_TABLE_ SOVD_states 2 "SOVD_SHOWCASE_ACTIVE" 1 "SOVD_SHOWCASE_DEACTIVE" 0 "SOVD_NONE" ;
VAL_TABLE_ OTA_states 7 "OTA_DOWNLOAD_FAILED" 6 "OTA_INSTALL_FAILED" 5 "OTA_INSTALL_FINISHED" 4 "OTA_INSTALL_START" 3 "OTA_DOWNLOAD_START" 2 "OTA_SCHEDULED" 1 "OTA_STANDBY" 0 "OTA_NONE" ;
BO_ 2 CAN_Input_R1: 1 Vector__XXX
SG_ Door01RightIsOpen : 3|1@0+ (1,0) [0|1] "" doors
BO_ 1 CAN_Input_L1: 1 Vector__XXX
SG_ Door01LeftIsOpen : 1|1@0+ (1,0) [0|1] "" doors
BO_ 5 CAN_Output: 1 doors
SG_ LockDoor01Right : 3|1@0+ (1,0) [0|1] "" Vector__XXX
SG_ LockDoor01Left : 1|1@0+ (1,0) [0|1] "" Vector__XXX
CM_ SG_ 2 Door01RightIsOpen "Open / Closed signal of front right door";
CM_ SG_ 1 Door01LeftIsOpen "Open / Closed signal of front left door";
CM_ SG_ 5 LockDoor01Right "Lock / Unlock signal of front right door";
CM_ SG_ 5 LockDoor01Left "Lock / Unlock signal of front left door";
BA_DEF_ "Baudrate" INT 1000 1000000;
BA_DEF_ "BusType" STRING ;
BA_DEF_ "DBName" STRING ;
BA_DEF_ "ProtocolType" STRING ;
BA_DEF_ BU_ "NmAsrNode" ENUM "No","Yes";
BA_DEF_ BU_ "NmAsrNodeIdentifier" INT 0 255;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65536;
BA_DEF_ BO_ "GenMsgCycleTimeFast" FLOAT 0 300000;
BA_DEF_ BO_ "GenMsgDelayTime" INT 0 65536;
BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100000;
BA_DEF_ BO_ "GenMsgSendType" ENUM "cyclic","spontaneous","not-used","not-used","not-used","cyclicAndSpontaneous","not-used","cyclicIfActive","NoMsgSendType";
BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 65536;
BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType";
BA_DEF_ SG_ "GenSigStartValue" HEX 0 80000000;
BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes";
BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes";
BA_DEF_ "NmAsrBaseAddress" HEX 0 536870911;
BA_DEF_ "NmAsrMessageCount" INT 0 255;
BA_DEF_ BU_ "NodeLayerModules" STRING ;
BA_DEF_ BU_ "ILused" ENUM "No","Yes";
BA_DEF_ SG_ "GenSigFuncType" ENUM "NoFunction","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","CHK","CNTR","n/a","n/a","n/a","CNTR_AR_01","CRC_AR_01_BOTH","CRC_AR_01_ALT","CRC_AR_01_LOW","CRC_AR_01_NIBBLE","CNTR_AR_04","CRC_AR_04A","CNTR_AR_05","CRC_AR_05";
BA_DEF_ SG_ "GenSigDataID" STRING ;
BA_DEF_ SG_ "SigGroup" STRING ;
BA_DEF_DEF_ "Baudrate" 1000;
BA_DEF_DEF_ "BusType" "";
BA_DEF_DEF_ "DBName" "";
BA_DEF_DEF_ "ProtocolType" "";
BA_DEF_DEF_ "NmAsrNode" "No";
BA_DEF_DEF_ "NmAsrNodeIdentifier" 0;
BA_DEF_DEF_ "GenMsgCycleTime" 0;
BA_DEF_DEF_ "GenMsgCycleTimeFast" 0;
BA_DEF_DEF_ "GenMsgDelayTime" 0;
BA_DEF_DEF_ "GenMsgNrOfRepetition" 0;
BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType";
BA_DEF_DEF_ "GenMsgStartDelayTime" 0;
BA_DEF_DEF_ "GenSigSendType" "NoSigSendType";
BA_DEF_DEF_ "GenSigStartValue" 0;
BA_DEF_DEF_ "GenMsgILSupport" "Yes";
BA_DEF_DEF_ "NmAsrMessage" "No";
BA_DEF_DEF_ "NmAsrBaseAddress" 1280;
BA_DEF_DEF_ "NmAsrMessageCount" 64;
BA_DEF_DEF_ "NodeLayerModules" "CANoeILNLSPA.dll";
BA_DEF_DEF_ "ILused" "Yes";
BA_DEF_DEF_ "GenSigFuncType" "NoFunction";
BA_DEF_DEF_ "GenSigDataID" "";
BA_DEF_DEF_ "SigGroup" "";
BA_ "ProtocolType" "CAN";
BA_ "BusType" "CAN";
BA_ "Baudrate" 500000;
BA_ "DBName" "PrivateCAN";
BA_ "GenMsgCycleTime" BO_ 2 10;
BA_ "GenMsgSendType" BO_ 2 0;
BA_ "GenMsgSendType" BO_ 1 0;
BA_ "GenMsgCycleTime" BO_ 1 10;
BA_ "GenMsgSendType" BO_ 5 0;
BA_ "GenMsgCycleTime" BO_ 5 10;

View File

@@ -0,0 +1,147 @@
VERSION "PrivateCAN"
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: doors
VAL_TABLE_ Fault_Codes 27 "UKWN" 26 "VEHSPDMAX_EXDD" 25 "STS_ALIVE" 24 "STEER_NOT_E2E_MODE" 23 "OTA_SPD" 22 "OTA_TIMER_DOWNLOAD_FAILED" 21 "OTA_MAX_TIME" 20 "CUBIXAD_STEERSTREQ_NOTACTV" 19 "CUBIXAD_DRVSTREQ_NOTACTV" 18 "SFTYDRV_INTV" 17 "LSDC_ALIVE" 16 "CUBIXAD_ALIVE" 15 "IBC_MAB_NO_PRIO" 14 "IBC_NOT_RDY" 13 "IBC_ALIVE" 12 "LSDC_GEAR" 11 "LSDC_SPD" 10 "LSDC_ACCL" 9 "IBC_NOT_MAB_MOD" 8 "GOLDBOX_ALIVE" 7 "CUBIXAD_GEAR" 6 "CUBIXAD_SPD_TESTTRACK" 5 "DRVREQCHG" 4 "RDY_TIMER" 3 "SFTY_CDN_FAILED" 2 "ACTVNCHK_SPD" 1 "ACTVNCHK_TIMR" 0 "NONE" ;
VAL_TABLE_ TestMapID 6 "E_TESTMAPID_UNDEFINED" 5 "E_TESTMAPID_TEST_DRIVE" 4 "E_TESTMAPID_AD_AREA" 3 "E_TESTMAPID_STUTT_ARENA" 2 "E_TESTMAPID_ZF_LASTMILE" 1 "E_TESTMAPID_ZF_TESTTRACK_2" 0 "E_TESTMAPID_NONE" ;
VAL_TABLE_ CtrlReqStates 7 "CtrlSts3b_RESERVED_4" 6 "CtrlSts3b_RESERVED_3" 5 "CtrlSts3b_RESERVED_2" 4 "CtrlSts3b_RESERVED_1" 3 "CtrlSts3b_ERROR" 2 "CtrlSts3b_CONTROL_REQUESTED" 1 "CtrlSts3b_CONTROL_NOT_REQUESTED" 0 "CtrlSts3b_INIT" ;
VAL_TABLE_ SteerActrReSts 7 "Diag" 6 "Inactive" 5 "Ramping" 4 "Yellow" 3 "Red" 2 "Normal" 1 "Pending" 0 "Initialisation" ;
VAL_TABLE_ SwtPark1 1 "SwtParkActv" 0 "SwtParkNotActv" ;
VAL_TABLE_ PE_State 2 "ERROR" 1 "INIT" 0 "NO_ERROR" ;
VAL_TABLE_ SSM_Req 7 "HMS_TAKEOVER" 6 "RESERVED" 5 "RELESE_VIA_RAMP" 4 "DRIVEOFF" 3 "HOLD_STANDBY" 2 "PARK" 1 "HOLD" 0 "NO_REQUEST" ;
VAL_TABLE_ IBC_StandStillMode 12 "SSM_ERROR" 11 "SSM_INIT" 10 "SSM_DRIVEOFF_STANDBY_ACTIVE" 9 "SSM_HOLD_STANDBY_ACTIVE" 8 "SSM_HILL_SLIPPOFF_DETECTED" 7 "SSM_RELEASE_REQ_FROM_DRIVER" 6 "SSM_RELEASE_REQ_ACTIVE" 5 "SSM_DRIVEOFF_ACTIVE" 4 "SSM_PARK_RETAINED_ACTIVE" 3 "SSM_PARK_ACTIVE" 2 "SSM_PARK_REQUESTED" 1 "SSM_HOLD_ACTIVE" 0 "SSM_NO_ACTIVE_FUNCTION" ;
VAL_TABLE_ AppTgtStDrv 3 "ACTIVE" 2 "READY" 1 "RESERVED" 0 "NOT_ACTIVE" ;
VAL_TABLE_ IBC_Status 4 "IBC_MAB_ERR_COMM" 3 "IBC_MAB_NO_PRIO" 2 "IBC_IN_MAB_MODE" 1 "IBC_READY" 0 "IBC_NOT_READY_FAILED" ;
VAL_TABLE_ GearLvrIndcn 7 "GearLvrIndcn2_Undefd" 6 "GearLvrIndcn2_Resd2" 5 "GearLvrIndcn2_Resd1" 4 "GearLvrIndcn2_ManModeIndcn" 3 "GearLvrIndcn2_DrvIndcn" 2 "GearLvrIndcn2_NeutIndcn" 1 "GearLvrIndcn2_RvsIndcn" 0 "GearLvrIndcn2_ParkIndcn" ;
VAL_TABLE_ LvlgAdjReq 7 "LvlgAdjReq_Resd2" 6 "LvlgAdjReq_Resd1" 5 "LvlgAdjReq_Ll2" 4 "LvlgAdjReq_Ll1" 3 "LvlgAdjReq_Nrh" 2 "LvlgAdjReq_Hl1" 1 "LvlgAdjReq_Hl2" 0 "LvlgAdjReq_Ukwn" ;
VAL_TABLE_ DrvModReq 15 "Err" 14 "Rock" 13 "Mud" 12 "Sand" 11 "Snow" 10 "Power" 9 "Hybrid" 8 "Pure_EV" 7 "Race" 6 "Adaptive" 5 "Offroad_CrossTerrain" 4 "Individual" 3 "Dynamic_Sport" 2 "Comfort_Normal" 1 "ECO" 0 "Undefd" ;
VAL_TABLE_ MAB_Info_Message 4 "DRV_GEARLVR_TO_P" 3 "DRV_P_TO_D" 2 "LSDC_DI_NOT_PSBL" 1 "LSDC_ENA_NOT_POSSIBLE" 0 "NONE" ;
VAL_TABLE_ MAB_OvrdTool_Sts 11 "HACKATHON" 10 "OTA" 9 "INIT" 8 "FINSHD" 7 "FLT" 6 "CUBIX_AD" 5 "SAVE_THE_SPOILER" 4 "LSDC" 3 "RDY" 2 "ACTVN_CHK" 1 "NO_MANIPULATION" 0 "NONE" ;
VAL_TABLE_ HMI_Drvr_Req 9 "FCT_DEACTVN_REQ" 8 "FCT_ACTVN_OTA_CFMD" 7 "FCT_ACTVN_OTA_REQ" 6 "FCT_ACTVN_SAVETHESPOILER_CFMD" 5 "FCT_ACTVN_SAVETHESPOILER_REQ" 4 "FCT_ACTVN_LSDC_CFMD" 3 "FCT_ACTVN_LSDC_REQ" 2 "FCT_ACTVN_CUBIXAD_CFMD" 1 "FCT_ACTVN_CUBIXAD_REQ" 0 "FCT_ACTVN_NONE" ;
VAL_TABLE_ Info_Message 4 "DRV_GEARLVR_TO_P" 3 "DRV_P_TO_D" 2 "LSDC_DI_NOT_PSBL" 1 "LSDC_ENA_NOT_POSSIBLE" 0 "NONE" ;
VAL_TABLE_ HMI_Fct_Req 8 "FCT_DEACTVN_REQ" 7 "FCT_ACTVN_OTA_REQ" 6 "FCT_ACTVN_SAVETHESPOILER_CFMD" 5 "FCT_ACTVN_SAVETHESPOILER_REQ" 4 "FCT_ACTVN_LSDC_CFMD" 3 "FCT_ACTVN_LSDC_REQ" 2 "FCT_ACTVN_AI4MTN_CFMD" 1 "FCT_ACTVN_AI4MTN_REQ" 0 "FCT_ACTVN_NONE" ;
VAL_TABLE_ SOVD_states 2 "SOVD_SHOWCASE_ACTIVE" 1 "SOVD_SHOWCASE_DEACTIVE" 0 "SOVD_NONE" ;
VAL_TABLE_ OTA_states 7 "OTA_DOWNLOAD_FAILED" 6 "OTA_INSTALL_FAILED" 5 "OTA_INSTALL_FINISHED" 4 "OTA_INSTALL_START" 3 "OTA_DOWNLOAD_START" 2 "OTA_SCHEDULED" 1 "OTA_STANDBY" 0 "OTA_NONE" ;
BO_ 4 CAN_Input_R2: 1 Vector__XXX
SG_ Door02RightIsOpen : 7|1@0+ (1,0) [0|1] "" doors
BO_ 3 CAN_Input_L2: 1 Vector__XXX
SG_ Door02LeftIsOpen : 5|1@0+ (1,0) [0|1] "" doors
BO_ 2 CAN_Input_R1: 1 Vector__XXX
SG_ Door01RightIsOpen : 3|1@0+ (1,0) [0|1] "" doors
BO_ 1 CAN_Input_L1: 1 Vector__XXX
SG_ Door01LeftIsOpen : 1|1@0+ (1,0) [0|1] "" doors
BO_ 5 CAN_Output: 1 doors
SG_ LockDoor02Right : 7|1@0+ (1,0) [0|1] "" Vector__XXX
SG_ LockDoor02Left : 5|1@0+ (1,0) [0|1] "" Vector__XXX
SG_ LockDoor01Right : 3|1@0+ (1,0) [0|1] "" Vector__XXX
SG_ LockDoor01Left : 1|1@0+ (1,0) [0|1] "" Vector__XXX
CM_ SG_ 4 Door02RightIsOpen "Open / Closed signal of rear right door";
CM_ SG_ 3 Door02LeftIsOpen "Open / Closed signal of rear left door";
CM_ SG_ 2 Door01RightIsOpen "Open / Closed signal of front right door";
CM_ SG_ 1 Door01LeftIsOpen "Open / Closed signal of front left door";
CM_ SG_ 5 LockDoor02Right "Lock / Unlock signal of rear right door";
CM_ SG_ 5 LockDoor02Left "Lock / Unlock signal of frear left door";
CM_ SG_ 5 LockDoor01Right "Lock / Unlock signal of front right door";
CM_ SG_ 5 LockDoor01Left "Lock / Unlock signal of front left door";
BA_DEF_ "Baudrate" INT 1000 1000000;
BA_DEF_ "BusType" STRING ;
BA_DEF_ "DBName" STRING ;
BA_DEF_ "ProtocolType" STRING ;
BA_DEF_ BU_ "NmAsrNode" ENUM "No","Yes";
BA_DEF_ BU_ "NmAsrNodeIdentifier" INT 0 255;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 65536;
BA_DEF_ BO_ "GenMsgCycleTimeFast" FLOAT 0 300000;
BA_DEF_ BO_ "GenMsgDelayTime" INT 0 65536;
BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100000;
BA_DEF_ BO_ "GenMsgSendType" ENUM "cyclic","spontaneous","not-used","not-used","not-used","cyclicAndSpontaneous","not-used","cyclicIfActive","NoMsgSendType";
BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 65536;
BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType";
BA_DEF_ SG_ "GenSigStartValue" HEX 0 80000000;
BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes";
BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes";
BA_DEF_ "NmAsrBaseAddress" HEX 0 536870911;
BA_DEF_ "NmAsrMessageCount" INT 0 255;
BA_DEF_ BU_ "NodeLayerModules" STRING ;
BA_DEF_ BU_ "ILused" ENUM "No","Yes";
BA_DEF_ SG_ "GenSigFuncType" ENUM "NoFunction","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","n/a","CHK","CNTR","n/a","n/a","n/a","CNTR_AR_01","CRC_AR_01_BOTH","CRC_AR_01_ALT","CRC_AR_01_LOW","CRC_AR_01_NIBBLE","CNTR_AR_04","CRC_AR_04A","CNTR_AR_05","CRC_AR_05";
BA_DEF_ SG_ "GenSigDataID" STRING ;
BA_DEF_ SG_ "SigGroup" STRING ;
BA_DEF_DEF_ "Baudrate" 1000;
BA_DEF_DEF_ "BusType" "";
BA_DEF_DEF_ "DBName" "";
BA_DEF_DEF_ "ProtocolType" "";
BA_DEF_DEF_ "NmAsrNode" "No";
BA_DEF_DEF_ "NmAsrNodeIdentifier" 0;
BA_DEF_DEF_ "GenMsgCycleTime" 0;
BA_DEF_DEF_ "GenMsgCycleTimeFast" 0;
BA_DEF_DEF_ "GenMsgDelayTime" 0;
BA_DEF_DEF_ "GenMsgNrOfRepetition" 0;
BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType";
BA_DEF_DEF_ "GenMsgStartDelayTime" 0;
BA_DEF_DEF_ "GenSigSendType" "NoSigSendType";
BA_DEF_DEF_ "GenSigStartValue" 0;
BA_DEF_DEF_ "GenMsgILSupport" "Yes";
BA_DEF_DEF_ "NmAsrMessage" "No";
BA_DEF_DEF_ "NmAsrBaseAddress" 1280;
BA_DEF_DEF_ "NmAsrMessageCount" 64;
BA_DEF_DEF_ "NodeLayerModules" "CANoeILNLSPA.dll";
BA_DEF_DEF_ "ILused" "Yes";
BA_DEF_DEF_ "GenSigFuncType" "NoFunction";
BA_DEF_DEF_ "GenSigDataID" "";
BA_DEF_DEF_ "SigGroup" "";
BA_ "ProtocolType" "CAN";
BA_ "BusType" "CAN";
BA_ "Baudrate" 500000;
BA_ "DBName" "PrivateCAN";
BA_ "GenMsgCycleTime" BO_ 4 10;
BA_ "GenMsgSendType" BO_ 4 0;
BA_ "GenMsgCycleTime" BO_ 3 10;
BA_ "GenMsgSendType" BO_ 3 0;
BA_ "GenMsgCycleTime" BO_ 2 10;
BA_ "GenMsgSendType" BO_ 2 0;
BA_ "GenMsgSendType" BO_ 1 0;
BA_ "GenMsgCycleTime" BO_ 1 10;
BA_ "GenMsgSendType" BO_ 5 0;
BA_ "GenMsgCycleTime" BO_ 5 10;

View File

@@ -0,0 +1,448 @@
#include "include/console.h"
#ifdef _WIN32
#include <conio.h> // Needed for _kbhit
#else
#include <fcntl.h>
#endif
const CConsole::SConsolePos g_sTitle{ 1, 1 };
const CConsole::SConsolePos g_sSubTitle{ 2, 1 };
const CConsole::SConsolePos g_sSeparator11{ 4, 1 };
const CConsole::SConsolePos g_sSeparator12{ 6, 1 };
const CConsole::SConsolePos g_sFrontLeftDoorIsOpen{ 7, 1 };
const CConsole::SConsolePos g_sFrontRightDoorIsOpen{ 8, 1 };
const CConsole::SConsolePos g_sRearLeftDoorIsOpen{ 9, 1 };
const CConsole::SConsolePos g_sRearRightDoorIsOpen{ 10, 1 };
const CConsole::SConsolePos g_sFrontLeftDoorIsLocked{ 7, 42 };
const CConsole::SConsolePos g_sFrontRightDoorIsLocked{ 8, 42 };
const CConsole::SConsolePos g_sRearLeftDoorIsLocked{ 9, 42 };
const CConsole::SConsolePos g_sRearRightDoorIsLocked{ 10, 42 };
const CConsole::SConsolePos g_sSeparator21{ 12, 1 };
const CConsole::SConsolePos g_sSeparator22{ 14, 1 };
const CConsole::SConsolePos g_sVehicleDevice{ 15, 1 };
const CConsole::SConsolePos g_sSeparator31{ 17, 1 };
const CConsole::SConsolePos g_sSeparator32{ 19, 1 };
const CConsole::SConsolePos g_sBasicServiceL1{ 20, 1 };
const CConsole::SConsolePos g_sBasicServiceR1{ 21, 1 };
const CConsole::SConsolePos g_sBasicServiceL2{ 22, 1 };
const CConsole::SConsolePos g_sBasicServiceR2{ 23, 1 };
const CConsole::SConsolePos g_sSeparator41{ 25, 1 };
const CConsole::SConsolePos g_sSeparator42{ 26, 1 };
const CConsole::SConsolePos g_sComplexService{ 27, 1 };
const CConsole::SConsolePos g_sControlDescription{ 29, 1 };
const CConsole::SConsolePos g_sCursor{ 30, 1 };
CConsole::CConsole()
{
#ifdef _WIN32
// Enable ANSI escape codes
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != INVALID_HANDLE_VALUE && GetConsoleMode(hStdOut, &m_dwConsoleOutMode))
SetConsoleMode(hStdOut, m_dwConsoleOutMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
if (hStdIn != INVALID_HANDLE_VALUE && GetConsoleMode(hStdIn, &m_dwConsoleInMode))
SetConsoleMode(hStdIn, m_dwConsoleInMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
#elif defined __unix__
// Disable echo
tcgetattr(STDIN_FILENO, &m_sTermAttr);
struct termios sTermAttrTemp = m_sTermAttr;
sTermAttrTemp.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &sTermAttrTemp);
m_iFileStatus = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, m_iFileStatus | O_NONBLOCK);
#else
#error The OS is not supported!
#endif
}
CConsole::~CConsole()
{
SetCursorPos(g_sCursor);
#ifdef _WIN32
// Return to the stored console mode
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != INVALID_HANDLE_VALUE)
SetConsoleMode(hStdOut, m_dwConsoleOutMode);
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
if (hStdIn != INVALID_HANDLE_VALUE)
SetConsoleMode(hStdIn, m_dwConsoleInMode);
#elif defined __unix__
// Return the previous file status flags.
fcntl(STDIN_FILENO, F_SETFL, m_iFileStatus);
// Return to previous terminal state
tcsetattr(STDIN_FILENO, TCSANOW, &m_sTermAttr);
#endif
}
void CConsole::PrintHeader(const uint32_t numberOfDoors)
{
// Clear the screen...
std::cout << "\x1b[2J";
std::string title = "Door demo example: Data link attached (4 doors) ";
if (numberOfDoors <= 4)
{
title = "Door demo example: Vehicle has ";
title.append(std::to_string(numberOfDoors));
title.append(" doors.");
}
// Print the titles
PrintText(g_sTitle, title.c_str());
PrintText(g_sSubTitle, " Doors are locked automatically after 2 seconds when all doors are closed.");
PrintText(g_sSeparator11, "============================================================================");
PrintText(g_sSeparator12, "Data dispatch service:");
PrintText(g_sFrontLeftDoorIsOpen, "Front Left Door:.. not available");
PrintText(g_sFrontRightDoorIsOpen, "Front Right Door:.. not available");
PrintText(g_sRearLeftDoorIsOpen, "Rear Left Door:.. not available");
PrintText(g_sRearRightDoorIsOpen, "Rear Right Door:.. not available");
PrintText(g_sSeparator21, "----------------------------------------------------------------------------");
PrintText(g_sSeparator22, "Vehicle device:");
PrintText(g_sVehicleDevice, "Vehicle Device Interface not available.");
PrintText(g_sSeparator31, "----------------------------------------------------------------------------");
PrintText(g_sSeparator32, "Basic services:");
PrintText(g_sBasicServiceL1, "Basic Service Interface not available.");
PrintText(g_sSeparator41, "----------------------------------------------------------------------------");
PrintText(g_sSeparator42, "Complex service:");
PrintText(g_sComplexService, "Complex Service Interface not available.");
if (!m_isExternalApp)
{
PrintText(g_sControlDescription, "Press 'X' to quit; '1', '2', '3', '4' to toggle doors...");
}
else
{
title.append(" [Connected to an instance]");
PrintText(g_sTitle, title.c_str());
PrintText(g_sControlDescription, "Press 'X' to quit; Doors are toggled automatically");
}
}
bool CConsole::PrepareDataConsumers()
{
if (!m_isExternalApp)
{
if(!(PrepareDataConsumersForStandAlone()))
{
return false;
}
}
auto basicServiceL1 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_GetIsOpen>();
if (!basicServiceL1)
{
SDV_LOG_ERROR("Could not get interface 'LeftService::IVSS_IsOpen': [CConsole]");
return false;
}
else
{
/* Interface exists -> Clean the line for Console window */
PrintText(g_sBasicServiceL1, " ");
}
basicServiceL1->RegisterOnSignalChangeOfLeftDoorIsOpen01(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event*> (this));
bool value = false;
PrintValue(g_sFrontLeftDoorIsLocked, "Front Left Latch:", value, (value ? "locked" : "unlocked"));
// all other doors are optional
auto basicServiceR1 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_GetIsOpen>();
if (basicServiceR1)
{
basicServiceR1->RegisterOnSignalChangeOfRightDoorIsOpen01(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event*> (this));
PrintValue(g_sFrontRightDoorIsLocked, "Front Right Latch:", value, (value ? "locked" : "unlocked"));
}
auto basicServiceL2 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_GetIsOpen>();
if (basicServiceL2)
{
basicServiceL2->RegisterOnSignalChangeOfLeftDoorIsOpen02(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event*> (this));
PrintValue(g_sRearLeftDoorIsLocked, "Rear Left Latch:", value, (value ? "locked" : "unlocked"));
}
auto basicServiceR2 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_GetIsOpen>();
if (basicServiceR2)
{
basicServiceR2->RegisterOnSignalChangeOfRightDoorIsOpen02(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event*> (this));
PrintValue(g_sRearRightDoorIsLocked, "Rear Right Latch:", value, (value ? "locked" : "unlocked"));
}
m_pDoorService = sdv::core::GetObject("Doors Example Service").GetInterface<IDoorService>();
if (!m_pDoorService)
{
SDV_LOG_ERROR("Console ERROR: Could not get complex service interface 'IDoorService'");
return false;
}
if (m_isExternalApp)
{
PrintText(g_sFrontLeftDoorIsLocked, " ");
PrintText(g_sFrontRightDoorIsLocked, " ");
PrintText(g_sRearLeftDoorIsLocked, " ");
PrintText(g_sRearRightDoorIsLocked, " ");
PrintText(g_sFrontLeftDoorIsOpen, "External Application, no dispatch service.");
PrintText(g_sFrontRightDoorIsOpen, " ");
PrintText(g_sRearLeftDoorIsOpen, " ");
PrintText(g_sRearRightDoorIsOpen, " ");
}
return true;
}
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 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_IsOpen>();
if (vehicleDevice)
vehicleDevice->UnregisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteIsOpen_Event*> (this));
auto basicServiceL1 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_GetIsOpen>();
if (basicServiceL1)
basicServiceL1->UnregisterOnSignalChangeOfLeftDoorIsOpen01(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event*> (this));
auto basicServiceR1 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_GetIsOpen>();
if (basicServiceR1)
basicServiceR1->UnregisterOnSignalChangeOfRightDoorIsOpen01(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event*> (this));
auto basicServiceL2 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_GetIsOpen>();
if (basicServiceL2)
basicServiceL2->UnregisterOnSignalChangeOfLeftDoorIsOpen02(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event*> (this));
auto basicServiceR2 = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_GetIsOpen>();
if (basicServiceR2)
basicServiceR2->UnregisterOnSignalChangeOfRightDoorIsOpen02(dynamic_cast<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event*> (this));
// Unregister the data link signalss
if (m_SignalFrontLeftDoorIsOpen)
m_SignalFrontLeftDoorIsOpen.Reset();
if (m_SignalFrontRightDoorIsOpen)
m_SignalFrontRightDoorIsOpen.Reset();
if (m_SignalRearLeftDoorIsOpen)
m_SignalRearLeftDoorIsOpen.Reset();
if (m_SignalRearRightDoorIsOpen)
m_SignalRearRightDoorIsOpen.Reset();
if (m_SignalFrontLeftDoorIsLocked)
m_SignalFrontLeftDoorIsLocked.Reset();
if (m_SignalFrontRightDoorIsLocked)
m_SignalFrontRightDoorIsLocked.Reset();
if (m_SignalRearLeftDoorIsLocked)
m_SignalRearLeftDoorIsLocked.Reset();
if (m_SignalRearRightDoorIsLocked)
m_SignalRearRightDoorIsLocked.Reset();
}
void CConsole::StartUpdateDataThread()
{
if (m_bThreadStarted)
return;
m_bThreadStarted = true;
m_bRunning = true;
m_threadReadTxSignals = std::thread(&CConsole::UpdateDataThreadFunc, this);
}
void CConsole::StopUpdateDataThread()
{
// Stop running and wait for any thread to finalize
m_bRunning = false;
if (m_threadReadTxSignals.joinable())
m_threadReadTxSignals.join();
}
void CConsole::SetExternalApp()
{
m_isExternalApp = true;
}
void CConsole::WriteIsOpen(bool value)
{
PrintValue(g_sVehicleDevice, "Front Left Door:", value, (value ? "open" : "closed"));
}
void CConsole::SetIsOpenL1(bool value)
{
PrintValue(g_sBasicServiceL1, "Front Left Door:", value, (value ? "open" : "closed"));
}
void CConsole::SetIsOpenR1(bool value)
{
PrintValue(g_sBasicServiceR1, "Front Right Door:", value, (value ? "open" : "closed"));
}
void CConsole::SetIsOpenL2(bool value)
{
PrintValue(g_sBasicServiceL2, "Rear Left Door:", value, (value ? "open" : "closed"));
}
void CConsole::SetIsOpenR2(bool value)
{
PrintValue(g_sBasicServiceR2, "Rear Right Door:", value, (value ? "open" : "closed"));
}
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); });
if(m_SignalFrontLeftDoorIsOpen)
m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch01, 0);
m_SignalFrontRightDoorIsOpen = dispatch.Subscribe(doors::dsRightDoorIsOpen01, [&](sdv::any_t value) { CallbackFrontRightDoorIsOpen(value); });
if(m_SignalFrontRightDoorIsOpen)
m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch01, 0);
m_SignalRearLeftDoorIsOpen = dispatch.Subscribe(doors::dsLeftDoorIsOpen02, [&](sdv::any_t value) {CallbackRearLeftDoorIsOpen(value); });
if(m_SignalRearLeftDoorIsOpen)
m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch02, 0);
m_SignalRearRightDoorIsOpen = dispatch.Subscribe(doors::dsRightDoorIsOpen02, [&](sdv::any_t value) { CallbackRearRightDoorIsOpen(value); });
if(m_SignalRearRightDoorIsOpen)
m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch02, 0);
// Validate: Either both exists or none of them
if (m_SignalFrontLeftDoorIsOpen != m_SignalFrontLeftDoorIsLocked)
{
SDV_LOG_ERROR("Console ERROR: m_SignalFrontLeftDoorIsOpen != m_SignalFrontLeftDoorIsLocked do not match, failed");
return false;
}
if (m_SignalFrontRightDoorIsOpen != m_SignalFrontRightDoorIsLocked)
{
SDV_LOG_ERROR("Console ERROR: m_SignalFrontRightDoorIsOpen != m_SignalFrontRightDoorIsLocked do not match, failed");
return false;
}
if (m_SignalRearLeftDoorIsOpen != m_SignalRearLeftDoorIsLocked)
{
SDV_LOG_ERROR("Console ERROR: m_SignalRearLeftDoorIsOpen != m_SignalRearLeftDoorIsLockeddo not match, failed");
return false;
}
if (m_SignalRearRightDoorIsOpen != m_SignalRearRightDoorIsLocked)
{
SDV_LOG_ERROR("Console ERROR: m_SignalRearRightDoorIsOpen != m_SignalRearRightDoorIsLocked do not match, failed");
return false;
}
// Registrate for the vehicle device & basic service of the front left door. Front left door mzust exist, the others are optional
auto vehicleDevice = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Device").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_IsOpen>();
if (!vehicleDevice)
{
SDV_LOG_ERROR("Could not get interface 'LeftDevice::IVSS_IsOpen': [CConsole]");
return false;
}
vehicleDevice->RegisterIsOpenEvent(dynamic_cast<vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteIsOpen_Event*> (this));
return true;
}
void CConsole::CallbackFrontLeftDoorIsOpen(sdv::any_t value)
{
m_FrontLeftDoorIsOpen = value.get<bool>();
PrintValue(g_sFrontLeftDoorIsOpen, "Front Left Door:", m_FrontLeftDoorIsOpen, (m_FrontLeftDoorIsOpen ? "open" : "closed"));
}
void CConsole::CallbackFrontRightDoorIsOpen(sdv::any_t value)
{
m_FrontRightDoorIsOpen = value.get<bool>();
PrintValue(g_sFrontRightDoorIsOpen, "Front Right Door:", m_FrontRightDoorIsOpen, (m_FrontRightDoorIsOpen ? "open" : "closed"));
}
void CConsole::CallbackRearLeftDoorIsOpen(sdv::any_t value)
{
m_RearLeftDoorIsOpen = value.get<bool>();
PrintValue(g_sRearLeftDoorIsOpen, "Rear Left Door:", m_RearLeftDoorIsOpen, (m_RearLeftDoorIsOpen ? "open" : "closed"));
}
void CConsole::CallbackRearRightDoorIsOpen(sdv::any_t value)
{
m_RearRightDoorIsOpen = value.get<bool>();
PrintValue(g_sRearRightDoorIsOpen, "Rear Right Door:", m_RearRightDoorIsOpen, (m_RearRightDoorIsOpen ? "open" : "closed"));
}
void CConsole::UpdateDataThreadFunc()
{
bool bDoorsAreLocked = true;
bool bFirstStatusCheck = true;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
while (m_bRunning)
{
if (!m_isExternalApp)
{
UpdateTXSignal(g_sFrontLeftDoorIsLocked, "Front Left Latch:", m_SignalFrontLeftDoorIsLocked, m_FrontLeftDoorIsLocked);
UpdateTXSignal(g_sFrontRightDoorIsLocked, "Front Right Latch:", m_SignalFrontRightDoorIsLocked, m_FrontRightDoorIsLocked);
UpdateTXSignal(g_sRearLeftDoorIsLocked, "Rear Left Latch:", m_SignalRearLeftDoorIsLocked, m_RearLeftDoorIsLocked);
UpdateTXSignal(g_sRearRightDoorIsLocked, "Rear Right Latch:", m_SignalRearRightDoorIsLocked, m_RearRightDoorIsLocked);
}
if (m_pDoorService)
{
auto latch = m_pDoorService->GetDoorsStatus();
if ((bDoorsAreLocked != latch) || (bFirstStatusCheck))
{
bDoorsAreLocked = latch;
PrintText(g_sComplexService, bDoorsAreLocked ? "All doors are locked" :"All doors are unlocked");
bFirstStatusCheck = false;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
void CConsole::UpdateTXSignal(SConsolePos sPos, const std::string& label, sdv::core::CSignal& signal, bool& value)
{
// signal may be optional (door may not exist)
if (signal)
{
auto frontLeftDoorIsLocked = value;
value = signal.Read().get<bool>();
if (frontLeftDoorIsLocked != value)
{
PrintValue(sPos, label , value, (value ? "locked" : "unlocked"));
}
}
}
CConsole::SConsolePos CConsole::GetCursorPos() const
{
SConsolePos sPos{};
std::cout << "\033[6n";
char buff[128];
int indx = 0;
for(;;) {
int cc = std::cin.get();
buff[indx] = (char)cc;
indx++;
if(cc == 'R') {
buff[indx + 1] = '\0';
break;
}
}
int iRow = 0, iCol = 0;
sscanf(buff, "\x1b[%d;%dR", &iRow, &iCol);
sPos.uiRow = static_cast<uint32_t>(iRow);
sPos.uiCol = static_cast<uint32_t>(iCol);
fseek(stdin, 0, SEEK_END);
return sPos;
}
void CConsole::SetCursorPos(SConsolePos sPos)
{
std::cout << "\033[" << sPos.uiRow << ";" << sPos.uiCol << "H";
}
void CConsole::PrintText(SConsolePos sPos, const std::string& rssText)
{
auto text = rssText;
while (text.length() < 47)
{
text.append(" ");
}
std::lock_guard<std::mutex> lock(m_mtxPrintToConsole);
SetCursorPos(sPos);
std::cout << text;
}

View File

@@ -0,0 +1,246 @@
#include "../door_app/include/door_application.h"
#include "../door_app/include/signal_names.h"
#ifdef _WIN32
#include <conio.h> // Needed for _kbhit
#else
#include <fcntl.h>
#endif
bool CDoorControl::LoadConfigFile(const std::string& inputMsg, const std::string& configFileName)
{
std::string msg = inputMsg;
if (m_appcontrol.LoadConfig(configFileName) == sdv::core::EConfigProcessResult::successful)
{
msg.append("ok\n");
std::cout << msg.c_str();
return true;
}
msg.append("FAILED.\n");
std::cout << msg.c_str();
return false;
}
bool CDoorControl::KeyHit()
{
#ifdef _WIN32
return _kbhit();
#elif __unix__
int ch = getchar();
if (ch != EOF) {
ungetc(ch, stdin);
return true;
}
return false;
#endif
}
char CDoorControl::GetChar()
{
#ifdef _WIN32
return static_cast<char>(_getch());
#else
return getchar();
#endif
}
bool CDoorControl::RegisterSignals()
{
sdv::core::CDispatchService dispatch;
m_SignalFrontLeftDoorIsOpen = dispatch.RegisterRxSignal(doors::dsLeftDoorIsOpen01);
m_SignalFrontLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch01, 0);
if (m_iNumberOfDoors > 1)
{
m_SignalFrontRightDoorIsOpen = dispatch.RegisterRxSignal(doors::dsRightDoorIsOpen01);
m_SignalFrontRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch01, 0);
if (m_iNumberOfDoors > 2)
{
m_SignalRearLeftDoorIsOpen = dispatch.RegisterRxSignal(doors::dsLeftDoorIsOpen02);
m_SignalRearLeftDoorIsLocked = dispatch.RegisterTxSignal(doors::dsLeftLatch02, 0);
if (m_iNumberOfDoors > 3)
{
m_SignalRearRightDoorIsOpen = dispatch.RegisterRxSignal(doors::dsRightDoorIsOpen02);
m_SignalRearRightDoorIsLocked = dispatch.RegisterTxSignal(doors::dsRightLatch02, 0);
}
}
}
return true;
}
bool CDoorControl::IsSDVFrameworkEnvironmentSet()
{
const char* envVariable = std::getenv("SDV_FRAMEWORK_RUNTIME");
if (envVariable)
{
return true;
}
return false;
}
bool CDoorControl::Initialize(const uint32_t numberOfDoors)
{
if (m_bInitialized)
return true;
if ((numberOfDoors >= 1) && (numberOfDoors <= 4))
{
m_iNumberOfDoors = numberOfDoors;
}
if (!IsSDVFrameworkEnvironmentSet())
{
// if SDV_FRAMEWORK_RUNTIME environment variable is not set we need to set the Framework Runtime directory
m_appcontrol.SetFrameworkRuntimeDirectory("../../bin");
}
if(!m_appcontrol.Startup(""))
return false;
// Switch to config mode.
m_appcontrol.SetConfigMode();
bool bResult = LoadConfigFile("Load dispatch example: ", "data_dispatch_example.toml");
bResult &= LoadConfigFile("Load task timer: ", "task_timer_example.toml");
bResult &= RegisterSignals();
bResult &= LoadConfigFile("Load vehicle devices and basic services for front left door: ", "front_left_door_example.toml");
if (m_iNumberOfDoors > 1)
{
bResult &= LoadConfigFile("Load vehicle devices and basic services for front right door: ", "front_right_door_example.toml");
if (m_iNumberOfDoors > 2)
{
bResult &= LoadConfigFile("Load vehicle devices and basic services for rear left door: ", "rear_left_door_example.toml");
if (m_iNumberOfDoors > 3)
{
bResult &= LoadConfigFile("Load vehicle devices and basic services for rear right door: ", "rear_right_door_example.toml");
}
}
}
bResult &= LoadConfigFile("Load door service (complex service): ", "door_comple_service.toml");
if (!bResult)
{
SDV_LOG_ERROR("One or more configurations could not be loaded. Cannot continue.");
return false;
}
m_bInitialized = true;
return true;
}
uint32_t CDoorControl::GetNumberOfDoors() const
{
return m_iNumberOfDoors;
}
void CDoorControl::Shutdown()
{
if (!m_bInitialized)
m_appcontrol.Shutdown();
m_bInitialized = false;
}
void CDoorControl::SetRunningMode()
{
m_appcontrol.SetRunningMode();
}
void CDoorControl::RunUntilBreak()
{
bool bRunning = true;
bool openFrontLeftDoor = true;
bool openFrontRightDoor = true;
bool openRearLeftDoor = true;
bool openRearRightDoor = true;
// Update console by writing the first value if available
if (m_SignalFrontLeftDoorIsOpen)
m_SignalFrontLeftDoorIsOpen.Write<bool>(openFrontLeftDoor);
if (m_SignalFrontRightDoorIsOpen)
m_SignalFrontRightDoorIsOpen.Write<bool>(openFrontRightDoor);
if (m_SignalRearLeftDoorIsOpen)
m_SignalRearLeftDoorIsOpen.Write<bool>(openRearLeftDoor);
if (m_SignalRearRightDoorIsOpen)
m_SignalRearRightDoorIsOpen.Write<bool>(openRearRightDoor);
while (bRunning)
{
// Check for a key
if (!KeyHit())
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
continue;
}
// Get a keyboard value (if there is any).
char c = GetChar();
switch (c)
{
case '1':
openFrontLeftDoor = !openFrontLeftDoor;
if (m_SignalFrontLeftDoorIsOpen)
m_SignalFrontLeftDoorIsOpen.Write<bool>(openFrontLeftDoor);
break;
case '2':
openFrontRightDoor = !openFrontRightDoor;
if (m_SignalFrontRightDoorIsOpen)
m_SignalFrontRightDoorIsOpen.Write<bool>(openFrontRightDoor);
break;
case '3':
openRearLeftDoor = !openRearLeftDoor;
if (m_SignalRearLeftDoorIsOpen)
m_SignalRearLeftDoorIsOpen.Write<bool>(openRearLeftDoor);
break;
case '4':
openRearRightDoor = !openRearRightDoor;
if (m_SignalRearRightDoorIsOpen)
m_SignalRearRightDoorIsOpen.Write<bool>(openRearRightDoor);
break;
case 'x':
case 'X':
bRunning = false;
break;
default:
break;
}
}
}
uint32_t CDoorControl::UserInputNumberOfDoors()
{
uint32_t numberOfDoors = 4;
// Clear the screen and goto top...
std::cout << "\x1b[2J\033[0;0H";
std::cout << "How many doors does the vehicle have? Press a number between 1 and 4: ";
// Get a keyboard value (if there is any).
char c = GetChar();
switch (c)
{
case '1':
numberOfDoors = 1;
break;
case '2':
numberOfDoors = 2;
break;
case '3':
numberOfDoors = 3;
break;
case '4':
break;
default:
break;
}
return numberOfDoors;
}

View File

@@ -0,0 +1,27 @@
#include <iostream>
#include "../door_app/include/door_application.h"
#include "../door_app/include/console.h"
int main()
{
CDoorControl appobj;
if (!appobj.Initialize(appobj.UserInputNumberOfDoors()))
{
std::cout << "ERROR: Failed to initialize application control." << std::endl;
return 0;
}
CConsole visual_obj;
visual_obj.PrintHeader(appobj.GetNumberOfDoors());
visual_obj.PrepareDataConsumers();
visual_obj.StartUpdateDataThread();
appobj.SetRunningMode();
appobj.RunUntilBreak();
visual_obj.StopUpdateDataThread();
visual_obj.ResetSignals();
appobj.Shutdown();
return 0;
}

View File

@@ -0,0 +1,102 @@
#include "../door_app/include/door_extern_application.h"
#include "../door_app/include/signal_names.h"
#ifdef _WIN32
#include <conio.h> // Needed for _kbhit
#else
#include <fcntl.h>
#endif
bool CDoorExternControl::Initialize()
{
if (m_bInitialized)
return true;
if (!IsSDVFrameworkEnvironmentSet())
{
// if SDV_FRAMEWORK_RUNTIME environment variable is not set we need to set the Framework Runtime directory
m_appcontrol.SetFrameworkRuntimeDirectory("../../bin");
}
std::stringstream sstreamAppConfig;
sstreamAppConfig << "[Application]" << std::endl;
sstreamAppConfig << "Mode=\"External\"" << std::endl;
sstreamAppConfig << "Instance=\"3002\"" << std::endl;
sstreamAppConfig << "Retries=" << 6 << std::endl;
sstreamAppConfig << "[Console]" << std::endl;
sstreamAppConfig << "Report=\"Silent\"" << std::endl;
if (!m_appcontrol.Startup(sstreamAppConfig.str()))
return false;
m_bInitialized = true;
return true;
}
void CDoorExternControl::Shutdown()
{
if (!m_bInitialized)
m_appcontrol.Shutdown();
m_bInitialized = false;
}
void CDoorExternControl::RunUntilBreak()
{
bool bRunning = true;
while (bRunning)
{
// Check for a key
if (!KeyHit())
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
continue;
}
// Get a keyboard value (if there is any).
char c = GetChar();
switch (c)
{
case 'x':
case 'X':
bRunning = false;
break;
default:
break;
}
}
}
bool CDoorExternControl::IsSDVFrameworkEnvironmentSet()
{
const char* envVariable = std::getenv("SDV_FRAMEWORK_RUNTIME");
if (envVariable)
{
return true;
}
return false;
}
bool CDoorExternControl::KeyHit()
{
#ifdef _WIN32
return _kbhit();
#elif __unix__
int ch = getchar();
if (ch != EOF) {
ungetc(ch, stdin);
return true;
}
return false;
#endif
}
char CDoorExternControl::GetChar()
{
#ifdef _WIN32
return static_cast<char>(_getch());
#else
return getchar();
#endif
}

View File

@@ -0,0 +1,27 @@
#include <iostream>
#include "../door_app/include/door_extern_application.h"
#include "../door_app/include/console.h"
int main()
{
CDoorExternControl appobj;
if (!appobj.Initialize())
{
std::cout << "ERROR: Failed to initialize application control." << std::endl;
return 0;
}
CConsole visual_obj;
visual_obj.SetExternalApp();
visual_obj.PrintHeader(4);
visual_obj.PrepareDataConsumers();
visual_obj.StartUpdateDataThread();
appobj.RunUntilBreak();
visual_obj.StopUpdateDataThread();
visual_obj.ResetSignals();
appobj.Shutdown();
return 0;
}

View File

@@ -0,0 +1,271 @@
#ifndef CONSOLE_OUTPUT_H
#define CONSOLE_OUTPUT_H
#include <iostream>
#include <string>
#include <functional>
#include <support/signal_support.h>
#include <support/app_control.h>
#include <support/component_impl.h>
#include <support/timer.h>
#include "signal_names.h"
#include <fcntl.h>
#include "../interfaces/vss_vehiclechassisdooraxle01left_vd_rx.h"
#include "../interfaces/vss_vehiclechassisdooraxle01left_bs_rx.h"
#include "../interfaces/vss_vehiclechassisdooraxle01right_bs_rx.h"
#include "../interfaces/vss_vehiclechassisdooraxle02left_bs_rx.h"
#include "../interfaces/vss_vehiclechassisdooraxle02right_bs_rx.h"
#ifdef __unix__
#include <termios.h> // Needed for tcgetattr and fcntl
#include <unistd.h>
#endif
#include "../generated/door_service/door_ifc.h"
/**
* @brief Console operation class.
* @details This class retrieves RX data from the data dispatch service, vehicle device & basic service of front left door on event change.
* Furthermore, it shows TX value by polling the RX signals.
*/
class CConsole : public vss::Vehicle::Chassis::Door::Axle01::LeftDevice::IVSS_WriteIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event
{
public:
/**
* @brief Screen position structure
*/
struct SConsolePos
{
uint32_t uiRow; ///< Row position (starts at 1)
uint32_t uiCol; ///< Column position (starts at 1)
};
/**
* @brief Constructor
*/
CConsole();
/**
* @brief Destructor
*/
~CConsole();
/**
* @brief Print the header.
* @param[in] numberOfDoors number of doors
*/
void PrintHeader(const uint32_t numberOfDoors);
/**
* @brief Prepare the data consumers..
* @details Gets all signals (4 RX signals showing Open/Closed doors and 4 TX signals if the doors are locked)
* Open/Closed is done as input (user) while locking the doors is done automatically by complex service when all doors are closed
* Need to work independent from the number of doors (1-4)
* @return Returns whether the preparation of the data consumers was successful or not.
*/
bool PrepareDataConsumers();
/**
* @brief Write leftDoorIsOpen signal
* @param[in] value leftDoorIsOpen
*/
void WriteIsOpen(bool value) override;
/**
* @brief Set leftDoorIsOpen signal (front door)
* @param[in] value leftDoorIsOpen
*/
void SetIsOpenL1(bool value) override;
/**
* @brief Set rightDoorIsOpen signal (front door)
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR1(bool value) override;
/**
* @brief Set leftDoorIsOpen signal (rear door)
* @param[in] value leftDoorIsOpen
*/
void SetIsOpenL2(bool value) override;
/**
* @brief Set rightDoorIsOpen signal (rear door)
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR2(bool value) override;
/**
* @brief For gracefully shutdown all signals need to be reset.
*/
void ResetSignals();
/**
* @brief Starts thread for polling the TX signals (if the doors are locked by the complex service)
*/
void StartUpdateDataThread();
/**
* @brief Stops thread
*/
void StopUpdateDataThread();
/**
* @brief Used to set a flag for when we use external App
*/
void SetExternalApp();
private:
/**
* @brief Prepare the data consumers for Standalone application
* @return Returns whether the preparation of the Standalone data consumers was successful or not.
*/
bool PrepareDataConsumersForStandAlone();
/**
* @brief Callback function when front left door is opened or closed (by user).
* @param[in] value The value of the signal to update.
*/
void CallbackFrontLeftDoorIsOpen(sdv::any_t value);
/**
* @brief Callback function when front right door is opened or closed (by user).
* @param[in] value The value of the signal to update.
*/
void CallbackFrontRightDoorIsOpen(sdv::any_t value);
/**
* @brief Callback function when rear left door is opened or closed (by user).
* @param[in] value The value of the signal to update.
*/
void CallbackRearLeftDoorIsOpen(sdv::any_t value);
/**
* @brief Callback function when rear right door is opened or closed (by user).
* @param[in] value The value of the signal to update.
*/
void CallbackRearRightDoorIsOpen(sdv::any_t value);
/**
* @brief Read the data link TX signals and print them into the console.
*/
void UpdateDataThreadFunc();
/**
* @brief Update the signal on the console output depending on the signal
* @details Check if the signal is valid. If invalid, ignore it.
*/
void UpdateTXSignal(SConsolePos sPos, const std::string& label, sdv::core::CSignal& signal, bool& value);
/**
* @brief Get the cursor position of the console.
* @return The cursor position.
*/
SConsolePos GetCursorPos() const;
/**
* @brief Set the current cursor position for the console.
* @param[in] sPos Console position to place the current cursor at.
*/
void SetCursorPos(SConsolePos sPos);
/**
* @brief Print text at a specific location.
* @param[in] sPos The location to print text at.
* @param[in] rssText Reference to the text to print.
*/
void PrintText(SConsolePos sPos, const std::string& rssText);
/**
* @brief Print a value string at a specific location.
* @tparam TValue Type of value.
* @param[in] sPos The location to print the value at.
* @param[in] rssName Reference to the value.
* @param[in] tValue The value.
* @param[in] rssStatus Status, becuse we have signals of type bool
*/
template <typename TValue>
void PrintValue(SConsolePos sPos, const std::string& rssName, TValue tValue, const std::string& rssStatus);
/**
* @brief Align string between name and value.
* @param[in] message Reference to the message to align.
* @param[in] desiredLength The desired length or 0 when no length is specified.
* @return The aligned string.
*/
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.
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_mPrintToConsole; ///< Mutex to print complete message
std::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
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
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.
#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.
#elif defined __unix__
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
};
template <typename TValue>
inline void CConsole::PrintValue(SConsolePos sPos, const std::string& rssName, TValue tValue, const std::string& rssUnits)
{
std::string endName = " ";
const size_t nEndNameLen = 14 - rssUnits.size();
const size_t nValueNameLen = 26;
std::stringstream sstreamValueText;
sstreamValueText << rssName <<
std::string(nValueNameLen - std::min(rssName.size(), static_cast<size_t>(nValueNameLen - 1)) - 1, '.') <<
" " << std::fixed << std::setprecision(2) << tValue << " " << rssUnits <<
std::string(nEndNameLen - std::min(endName.size(), static_cast<size_t>(nEndNameLen - 1)) - 1, ' ');
std::lock_guard<std::mutex> lock(m_mPrintToConsole);
SetCursorPos(sPos);
std::cout << sstreamValueText.str();
}
template <>
inline void CConsole::PrintValue<bool>(SConsolePos sPos, const std::string& rssName, bool bValue, const std::string& rssStatus)
{;
PrintValue(sPos, rssName, bValue ? "" : "", rssStatus);
}
#endif // !define CONSOLE_OUTPUT_H

View File

@@ -0,0 +1,99 @@
#include <string>
#include <support/app_control.h>
#include <support/signal_support.h>
/**
* @brief Application Class of the door example
*/
class CDoorControl
{
public:
/**
* @brief Start and initialize the application control and load vehicle devices and
* basic services depending on the number of doors
* @param[in] numberOfDoors number of doors (1-4), default 4
* @return Return true on success otherwise false
*/
bool Initialize(const uint32_t numberOfDoors = 4);
/**
* @brief After initialization/configuration the system mode needs to be set to running mode
*/
void SetRunningMode();
/**
* @brief Ask user for input how many doors the vehicle should have (1-4)
* @return Return number of doors (default 4)
*/
uint32_t UserInputNumberOfDoors();
/**
* @brief Run loop as long as user input does not exit
* Allow user to open/close each door.
*/
void RunUntilBreak();
/**
* @brief Shutdown the system.
*/
void Shutdown();
/**
* @brief Get number of doors
* @return Return number of doors (default 4)
*/
uint32_t GetNumberOfDoors() const;
private:
/**
* @brief check if SDV_FRAMEWORK_RUNTIME environment variable exists
* @return Return true if environment variable is found otherwise false
*/
bool IsSDVFrameworkEnvironmentSet();
/**
* @brief Loac config file and register vehicle device and basic service.
* @remarks It is expected that each config file has the complete door:
* vehicle device & basic service for input and output
* @param[in] inputMsg message string to be printed on console in case of success and failure
* @param[in] configFileName config toml file name
* @return Return true on success otherwise false
*/
bool LoadConfigFile(const std::string& inputMsg, const std::string& configFileName);
/**
* @brief Key hit check. Windows uses the _kbhit function; POSIX emulates this.
* @return Returns whether a key has been pressed.
*/
bool KeyHit();
/**
* @brief Get the character from the keyboard buffer if pressed.
* @return Returns the character from the keyboard buffer.
*/
char GetChar();
/**
* @brief Register/Create Signals in the dispatch service depending on the number of doors
* @return Return true on success otherwise false
*/
bool RegisterSignals();
sdv::app::CAppControl m_appcontrol; ///< App-control of SDV V-API.
bool m_bInitialized = false; ///< Set when initialized.
uint32_t m_iNumberOfDoors = 4; ///< Number iof doors, maximuum 4
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_SignalFrontLeftDoorIsLocked; ///< Front Left Latch signal (TX output) - locked / unlocked
sdv::core::CSignal m_SignalFrontRightDoorIsLocked; ///< Front Right Latch signal (TX output) - locked / unlocked
sdv::core::CSignal m_SignalRearLeftDoorIsLocked; ///< Rear Left Latch signal (TX output) - locked / unlocked
sdv::core::CSignal m_SignalRearRightDoorIsLocked; ///< Rear Right Latch signal (TX output) - locked / unlocked
};

View File

@@ -0,0 +1,55 @@
#include <string>
#include <support/app_control.h>
#include <support/signal_support.h>
/**
* @brief Application Class of the door example
*/
class CDoorExternControl
{
public:
/**
* @brief Start and initialize the application control and load vehicle devices and
* basic services depending on the numerb of doors
* @return Return true on success otherwise false
*/
bool Initialize();
/**
* @brief Run loop as long as user input does not exit
* Allow user to open/close each door.
*/
void RunUntilBreak();
/**
* @brief Shutdown the system.
*/
void Shutdown();
private:
/**
* @brief check if SDV_FRAMEWORK_RUNTIME environment variable exists
* @return Return true if environment variable is found otherwise false
*/
bool IsSDVFrameworkEnvironmentSet();
/**
* @brief Key hit check. Windows uses the _kbhit function; POSIX emulates this.
* @return Returns whether a key has been pressed.
*/
bool KeyHit();
/**
* @brief Get the character from the keyboard buffer if pressed.
* @return Returns the character from the keyboard buffer.
*/
char GetChar();
sdv::app::CAppControl m_appcontrol; ///< App-control of SDV V-API.
bool m_bInitialized = false; ///< Set when initialized.
uint32_t m_iNumberOfDoors = 4; ///< Number iof doors, maximuum 4
};

View File

@@ -0,0 +1,30 @@
/**
* namespace for the signal names
* in case /interfaces/signal_identifier.h
* exists, use the file, otherwise define the namespace
*/
#ifndef SIGNAL_NAMES_H
#define SIGNAL_NAMES_H
#ifdef __has_include
#if __has_include("../interfaces/signal_identifier.h")
#include "../interfaces/signal_identifier.h"
#else
namespace doors
{
// Data Dispatch Service signal names to dbc variable names C-type RX/TX vss name space
static std::string dsLeftDoorIsOpen01 = "CAN_Input_L1.Door01LeftIsOpen"; ///< bool RX Vehicle.Chassis.Door.Axle01.Left
static std::string dsRightDoorIsOpen01 = "CAN_Input_R1.Door01RightIs"; ///< bool RX Vehicle.Chassis.Door.Axle01.Right
static std::string dsLeftDoorIsOpen02 = "CAN_Input_L2.Door02LeftIsOpen"; ///< bool RX Vehicle.Chassis.Door.Axle02.Left
static std::string dsRightDoorIsOpen02 = "CAN_Input_R2.Door02RightIsOpen"; ///< bool RX Vehicle.Chassis.Door.Axle02.Right
static std::string dsLeftLatch01 = "CAN_Output.LockDoor01Left" ; ///< bool TX Vehicle.Chassis.TX.Door.Axle01.Left
static std::string dsRightLatch01 = "CAN_Output.LockDoor01Right"; ///< bool TX Vehicle.Chassis.TX.Door.Axle01.Right
static std::string dsLeftLatch02 = "CAN_Output.LockDoor02Left" ; ///< bool TX Vehicle.Chassis.TX.Door.Axle02.Left
static std::string dsRightLatch02 = "CAN_Output.LockDoor02Right"; ///< bool TX Vehicle.Chassis.TX.Door.Axle02.Right
} // doors
#endif
#endif
#endif // SIGNAL_NAMES_H

View File

@@ -0,0 +1,42 @@
date 08/28/25 19:10:31
base hex timestamps absolute
Begin Triggerblock 08/28/25 19:10:31
0.000000 Start of measurement
0.021165 1 1 Rx d 1 02
0.031165 1 2 Rx d 1 08
0.041165 1 3 Rx d 1 20
0.051165 1 4 Rx d 1 80
3.002210 1 1 Rx d 1 00
3.502858 1 2 Rx d 1 00
4.002858 1 3 Rx d 1 00
4.502858 1 4 Rx d 1 00
9.021165 1 1 Rx d 1 02
9.031165 1 2 Rx d 1 08
9.041165 1 3 Rx d 1 20
9.051165 1 4 Rx d 1 80
13.021165 1 1 Rx d 1 00
13.031165 1 2 Rx d 1 00
13.041165 1 3 Rx d 1 00
13.051165 1 4 Rx d 1 00
17.021165 1 1 Rx d 1 02
17.031165 1 2 Rx d 1 08
17.041165 1 3 Rx d 1 20
17.051165 1 4 Rx d 1 80
19.002210 1 1 Rx d 1 00
19.502858 1 2 Rx d 1 00
20.002858 1 3 Rx d 1 00
20.502858 1 4 Rx d 1 00
24.021165 1 1 Rx d 1 02
24.031165 1 2 Rx d 1 08
24.041165 1 3 Rx d 1 20
24.051165 1 4 Rx d 1 80
27.021165 1 1 Rx d 1 00
27.031165 1 2 Rx d 1 00
27.041165 1 3 Rx d 1 00
27.051165 1 4 Rx d 1 00
30.021165 1 1 Rx d 1 02
30.031165 1 2 Rx d 1 08
30.041165 1 3 Rx d 1 20
30.051165 1 4 Rx d 1 80
End TriggerBlock

View File

@@ -0,0 +1,154 @@
#include <iostream>
#include "complex_service.h"
void CDoorsExampleService::Initialize(const sdv::u8string& /*ssObjectConfig*/)
{
m_eStatus = sdv::EObjectStatus::initializing;
// Request the basic service for front left door.
auto pFrontLeftDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_GetIsOpen>();
if (pFrontLeftDoorSvc)
{
// Register front left door change event handler.
pFrontLeftDoorSvc->RegisterOnSignalChangeOfLeftDoorIsOpen01(static_cast<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event*> (this));
}
// Request the basic service for front right door.
auto pFrontRightDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_GetIsOpen>();
if (pFrontRightDoorSvc)
{
// Register front right door change event handler.
pFrontRightDoorSvc->RegisterOnSignalChangeOfRightDoorIsOpen01(static_cast<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event*> (this));
}
// Request the basic service for rear left door.
auto pRearLeftDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_GetIsOpen>();
if (pRearLeftDoorSvc)
{
// Register rear left door change event handler.
pRearLeftDoorSvc->RegisterOnSignalChangeOfLeftDoorIsOpen02(static_cast<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event*> (this));
}
// Request the basic service for front right door.
auto pRearRightDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_GetIsOpen>();
if (pRearRightDoorSvc)
{
// Register rear right door change event handler.
pRearRightDoorSvc->RegisterOnSignalChangeOfRightDoorIsOpen02(static_cast<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event*> (this));
}
// Request the basic service for locking the front left door.
m_pFrontLeftDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetLock>();
// Request the basic service for locking the front right door.
m_pFrontRightDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetLock>();
// Request the basic service for locking the rear left door.
m_pRearLeftDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetLock>();
// Request the basic service for locking the rear right door.
m_pRearRightDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetLock>();
// Validate if we have the Open/Closed signal and the Lock/Unlock door signal, both must exist together or both must not exist
// Front left door is an exception, it isalways required
if ((!pFrontLeftDoorSvc) || (!m_pFrontLeftDoorSvc))
{
SDV_LOG_ERROR("Could not get interfaces for 'Front left door': [CDoorsExampleService]");
m_eStatus = sdv::EObjectStatus::initialization_failure;
return;
}
if ((pFrontRightDoorSvc == nullptr) != (m_pFrontRightDoorSvc == nullptr))
{
SDV_LOG_ERROR("Could not get both interfaces for 'Front right door': [CDoorsExampleService]");
m_eStatus = sdv::EObjectStatus::initialization_failure;
return;
}
if ((pRearLeftDoorSvc == nullptr) != (m_pRearLeftDoorSvc == nullptr))
{
SDV_LOG_ERROR("Could not get both interfaces for 'Rear left door': [CDoorsExampleService]");
m_eStatus = sdv::EObjectStatus::initialization_failure;
return;
}
if ((pRearRightDoorSvc == nullptr) != (m_pRearRightDoorSvc == nullptr))
{
SDV_LOG_ERROR("Could not get both interfaces for 'Rear right door': [CDoorsExampleService]");
m_eStatus = sdv::EObjectStatus::initialization_failure;
return;
}
m_doorsThread.start(m_Interval);
m_eStatus = sdv::EObjectStatus::initialized;
}
sdv::EObjectStatus CDoorsExampleService::GetStatus() const
{
return m_eStatus;
}
void CDoorsExampleService::SetOperationMode(sdv::EOperationMode /*eMode*/)
{
// Not applicable
}
void CDoorsExampleService::Shutdown()
{
// Unregister front left door change event handler.
auto pFrontLeftDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_GetIsOpen>();
if (pFrontLeftDoorSvc)
pFrontLeftDoorSvc->UnregisterOnSignalChangeOfLeftDoorIsOpen01(static_cast<vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event*> (this));
// Unregister front right door change event handler.
auto pFrontRightDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle01.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_GetIsOpen>();
if (pFrontRightDoorSvc)
pFrontRightDoorSvc->UnregisterOnSignalChangeOfRightDoorIsOpen01(static_cast<vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event*> (this));
// Unregister rear left door change event handler.
auto pRearLeftDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Left_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_GetIsOpen>();
if (pRearLeftDoorSvc)
pRearLeftDoorSvc->UnregisterOnSignalChangeOfLeftDoorIsOpen02(static_cast<vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event*> (this));
// Unregister rear right door change event handler.
auto pRearRightDoorSvc = sdv::core::GetObject("Vehicle.Chassis.Door.Axle02.Right_Service").GetInterface<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_GetIsOpen>();
if (pRearRightDoorSvc)
pRearRightDoorSvc->UnregisterOnSignalChangeOfRightDoorIsOpen02(static_cast<vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event*> (this));
m_doorsThread.stop();
}
void CDoorsExampleService::AreAllDoorsClosed()
{
if (m_bFrontLeftDoorIsOpen || m_bFrontRightDoorIsOpen || m_bRearLeftDoorIsOpen || m_bRearRightDoorIsOpen)
{
m_doorsThread.stop();
LockDoors(false);
m_bAllDoorsAreLocked = false;
return;
}
m_doorsThread.restart(m_Interval);
}
void CDoorsExampleService::LockDoorsIfAllDoorsAreClosed()
{
if (m_bFrontLeftDoorIsOpen || m_bFrontRightDoorIsOpen || m_bRearLeftDoorIsOpen || m_bRearRightDoorIsOpen)
{
return;
}
m_bAllDoorsAreLocked = true;
LockDoors(true);
}
void CDoorsExampleService::LockDoors(const bool lock) const
{
if (m_pFrontLeftDoorSvc)
m_pFrontLeftDoorSvc->SetLock(lock);
if (m_pFrontRightDoorSvc)
m_pFrontRightDoorSvc->SetLock(lock);
if (m_pRearLeftDoorSvc)
m_pRearLeftDoorSvc->SetLock(lock);
if (m_pRearRightDoorSvc)
m_pRearRightDoorSvc->SetLock(lock);
}

View File

@@ -0,0 +1,190 @@
#ifndef DOORS_COMPLEX_SERVICE_EXAMPLE_H
#define DOORS_COMPLEX_SERVICE_EXAMPLE_H
#include <iostream>
// SDV framework support
#include <support/component_impl.h>
#include <support/signal_support.h>
#include <support/timer.h>
// VSS interfaces - located in ../interfaces
#include "vss_vehiclechassisdooraxle01left_bs_rx.h"
#include "vss_vehiclechassisdooraxle01left_bs_tx.h"
#include "vss_vehiclechassisdooraxle01right_bs_rx.h"
#include "vss_vehiclechassisdooraxle01right_bs_tx.h"
#include "vss_vehiclechassisdooraxle02left_bs_rx.h"
#include "vss_vehiclechassisdooraxle02left_bs_tx.h"
#include "vss_vehiclechassisdooraxle02right_bs_rx.h"
#include "vss_vehiclechassisdooraxle02right_bs_tx.h"
#include "lock_doors_thread.h"
#include "../generated/door_service/door_ifc.h"
/**
* @brief Doors example service: locks/unlocks doors after closing/opening doors
*/
class CDoorsExampleService : public sdv::CSdvObject
, public sdv::IObjectControl
, public vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event
, public vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event
, public IDoorService
{
public:
/**
* @brief Constructor
*/
CDoorsExampleService() : m_doorsThread([&] { this->LockDoorsIfAllDoorsAreClosed(); }) {}
/**
* @brief Destructor
*/
~CDoorsExampleService()
{
// Just in case...
Shutdown();
}
// Interface map
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event)
SDV_INTERFACE_ENTRY(vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event)
SDV_INTERFACE_ENTRY(IDoorService)
END_SDV_INTERFACE_MAP()
// Object declarations
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::ComplexService)
DECLARE_OBJECT_CLASS_NAME("Doors Example Service")
DECLARE_OBJECT_SINGLETON()
/**
* @brief Initialize the object. Overload of sdv::IObjectControl::Initialize.
* @param[in] ssObjectConfig Optional configuration string.
*/
void Initialize(const sdv::u8string& ssObjectConfig) override;
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
*/
sdv::EObjectStatus GetStatus() const override;
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode) override;
/**
* @brief Shutdown called before the object is destroyed. Overload of sdv::IObjectControl::Shutdown.
*/
void Shutdown() override;
/**
* @brief Set leftDoorIsOpen signal (front door)
* @param[in] value leftDoorIsOpen
*/
void SetIsOpenL1(bool value) override
{
auto haschanged = (m_bFrontLeftDoorIsOpen != value);
m_bFrontLeftDoorIsOpen = value;
if (haschanged)
AreAllDoorsClosed();
}
/**
* @brief Set rightDoorIsOpen signal (front door)
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR1(bool value) override
{
auto haschanged = (m_bFrontRightDoorIsOpen != value);
m_bFrontRightDoorIsOpen = value;
if (haschanged)
AreAllDoorsClosed();
}
/**
* @brief Set leftDoorIsOpen signal (rear door)
* @param[in] value leftDoorIsOpen
*/
void SetIsOpenL2(bool value) override
{
auto haschanged = (m_bRearLeftDoorIsOpen != value);
m_bRearLeftDoorIsOpen = value;
if (haschanged)
AreAllDoorsClosed();
}
/**
* @brief Set rightDoorIsOpen signal (rear door)
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR2(bool value) override
{
auto haschanged = (m_bRearRightDoorIsOpen != value);
m_bRearRightDoorIsOpen = value;
if (haschanged)
AreAllDoorsClosed();
}
/**
* @brief Get doors state. If the doors are locked/unlocked
*/
virtual bool GetDoorsStatus() override
{
return m_bAllDoorsAreLocked;
}
private:
/**
* @brief Check if all doors are close
* @details If all doors are not closed, unlock doors
*/
void AreAllDoorsClosed();
/**
* @brief Check if all doors are close
* @details If all doors are closed, lock doors, otherwise do nothing. This is a callback function for timer.
*/
void LockDoorsIfAllDoorsAreClosed();
/**
* @brief Lock or unlock doors
* @param[in] lock if true lock doors, otherwise unlock doors
*/
void LockDoors(const bool lock) const;
sdv::EObjectStatus m_eStatus = sdv::EObjectStatus::initialization_pending; ///< Current object status
bool m_bFrontLeftDoorIsOpen = false; ///< Front Left Door Status
bool m_bFrontRightDoorIsOpen = false; ///< Front Right Door Status
bool m_bRearLeftDoorIsOpen = false; ///< Rear Left Door Status
bool m_bRearRightDoorIsOpen = false; ///< Rear Right Door Status
bool m_bAllDoorsAreLocked = false; ///< state for locked/unlocked of all doors
///< Door lock interfaces.
vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetLock* m_pFrontLeftDoorSvc = nullptr; ///< Front Left Door
vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetLock* m_pFrontRightDoorSvc = nullptr; ///< Front Right Door
vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetLock* m_pRearLeftDoorSvc = nullptr; ///< Rear Left Door
vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetLock* m_pRearRightDoorSvc = nullptr; ///< Rear Right Door
LockDoorsThread m_doorsThread; ///< timer thread
uint32_t m_Interval = 18; ///< interval value * 100 = x milliseconds
};
DEFINE_SDV_OBJECT(CDoorsExampleService)
#endif // !define DOORS_COMPLEX_SERVICE_EXAMPLE_H

View File

@@ -0,0 +1,17 @@
/*******************************************************************************
* @file door_ifc.idl
* @details Door service interface definition.
*/
/**
* @brief DoorService example service interface. The interface provides functions for the
* Doors example complex service.
*/
interface IDoorService
{
/**
* @brief Status of all doors together whether they are locked or unlocked.
* @return true if all doors are locked, otherwise unlocked.
*/
boolean GetDoorsStatus();
};

View File

@@ -0,0 +1,95 @@
#ifndef LOCK_DOORS_THREAD_H
#define LOCK_DOORS_THREAD_H
/**
* @brief Thread to lock the doors (or execute any other callback the thread gets) after a certain time. can be restarted
*/
class LockDoorsThread
{
public:
/**
* @brief Constructor, set the callback function
* @param[in] callback function to be called
* @param[in] m_running when set to false end thread
* @param[in] m_timeIn100MilliSeconds timespan * 100 in milliseconds before callback should be executed
*/
LockDoorsThread(std::function<void()> callback)
: m_callback(callback), m_running(false), m_timeIn100MilliSeconds(0) {}
/**
* @brief Stsrt thread
* @param[in] timeSpan the time span before the callback will be executed
*/
void start(uint32_t timeSpan)
{
if (m_running)
return;
m_timeIn100MilliSeconds = timeSpan;
m_counter = 0;
m_running = true;
m_thread = std::thread(&LockDoorsThread::run, this);
}
/**
* @brief Stop thread
*/
void stop()
{
m_running = false;
if (m_thread.joinable())
{
m_thread.join();
}
}
/**
* @brief Stop and restart thread with new time setting
* @param[in] timeSpan the time span before the callback will be executed
*/
void restart(uint32_t timeSpan)
{
stop();
m_counter = 0;
start(timeSpan);
}
/**
* @brief destructor
*/
~LockDoorsThread()
{
stop();
}
private:
/**
* @brief thread loop. If time span is reach, execute callback and reset. Only one execution required
*/
void run()
{
while (m_running && m_counter <= m_timeIn100MilliSeconds)
{
m_counter++;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (m_counter > m_timeIn100MilliSeconds && m_callback)
{
m_callback();
m_counter = 0;
}
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
};
#endif // !define LOCK_DOORS_THREAD_H

View File

@@ -0,0 +1,180 @@
# @file CMakeLists.txt
# This file is cmake project file.
# This file was generated by the DBC utility from:
# datalink_2doors_example.dbc
# DBC file version: 1.0.0.1
# Based on CMakeLists.txt from https://github.com/modelica/Reference-FMUs
# only FMI 2.0, only CoSimulation
# without fumsim
# Only valid for Windows
if ( WIN32 )
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
project (Doors2ExampleFMUProject)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Library symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
set(VAPI_CORE_SDV_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
set(MODEL_NAME Doors2ExampleFMU)
set(TARGET_NAME ${MODEL_NAME})
set(FMU_FULL_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/fmus/${MODEL_NAME}.fmu")
FUNCTION(cat IN_FILE OUT_FILE)
file(READ ${IN_FILE} CONTENTS)
file(APPEND ${OUT_FILE} "${CONTENTS}")
ENDFUNCTION()
set(FMI_VERSION 2 CACHE STRING "FMI Version")
set_property(CACHE FMI_VERSION PROPERTY STRINGS 2)
set(FMI_TYPE CS CACHE STRING "FMI Version")
set_property(CACHE FMI_TYPE PROPERTY STRINGS CS)
set(FMI_TYPE "")
set (FMI_PLATFORM win32)
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set (FMI_PLATFORM win64)
endif ()
SET(HEADERS
${MODEL_NAME}/config.h
include/cosimulation.h
include/model.h
)
SET(HEADERS
${HEADERS}
include/fmi2Functions.h
include/fmi2FunctionTypes.h
include/fmi2TypesPlatform.h
)
SET(SOURCES
${MODEL_NAME}/model.cpp
src/fmi${FMI_VERSION}Functions.c
src/cosimulation.c
)
add_library(${TARGET_NAME} SHARED
${HEADERS}
${SOURCES}
${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
${MODEL_NAME}/buildDescription.xml
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fmus)
set(FMU_BUILD_DIR temp/${MODEL_NAME})
target_compile_definitions(${TARGET_NAME} PRIVATE
FMI_VERSION=${FMI_VERSION}
DISABLE_PREFIX
)
#[[
if (MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
endif()
]]
target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION)
target_include_directories(${TARGET_NAME} PRIVATE include ${MODEL_NAME})
target_link_libraries(${TARGET_NAME} Winmm Ws2_32 Rpcrt4.lib)
set_target_properties(${TARGET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
)
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME})
# modelDescription.xml
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
"${FMU_BUILD_DIR}/modelDescription.xml"
)
set(ARCHIVE_FILES "modelDescription.xml" "binaries")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources")
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources"
"${FMU_BUILD_DIR}/resources/"
)
set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources")
endif()
# When windows robocopy command (using cmd.exe) is used to copy files its important to set the dependencies
# to assure that the copy command is finished before the next custom action to avoid copy/file access failures
# Copy sdv binaries of this FMU
set(DEST_DIR "${FMU_BUILD_DIR}/resources")
set(SOURCE_DIR_EXAMPLES_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
add_custom_target(copy_function_sdv_files_${TARGET_NAME} DEPENDS ${TARGET_NAME})
add_custom_command(TARGET copy_function_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_EXAMPLES_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_EXAMPLES_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_function_sdv_files_${TARGET_NAME} ${TARGET_NAME})
# Copy framework sdv binaries
set(SOURCE_DIR_CORE_BIN "${SDV_FRAMEWORK_RUNTIME}")
add_custom_target(copy_framework_sdv_files_${TARGET_NAME} DEPENDS copy_function_sdv_files_${TARGET_NAME})
add_custom_command(TARGET copy_framework_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_CORE_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_CORE_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_framework_sdv_files_${TARGET_NAME} copy_function_sdv_files_${TARGET_NAME})
# FMU content created, all files copied
# to zip the files create a new target 'create_zip' which is build after all files have been copied
add_custom_target(create_zip_${TARGET_NAME} ALL DEPENDS copy_framework_sdv_files_${TARGET_NAME} )
add_custom_command(TARGET create_zip_${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${FMU_FULL_FILE_NAME} --format=zip ${ARCHIVE_FILES}
WORKING_DIRECTORY ${FMU_BUILD_DIR}
COMMENT "Creating ZIP ${FMU_FULL_FILE_NAME}"
)
add_dependencies(create_zip_${TARGET_NAME} copy_framework_sdv_files_${TARGET_NAME})
#TODO
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)
endif ()

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<fmiModelDescription
fmiVersion = "2.0"
modelName = "Doors2ExampleFMU"
guid = "945aa152-f9fd-4d02-add5-a4320d05c0ab"
description = "TargetLink FMU for Doors2ExampleFMU"
generationTool = "TargetLink was generated by the DBC utility: datalink_2doors_example.dbc"
generationDateAndTime = "2025-09-06 15:15:34"
variableNamingConvention = "structured"
numberOfEventIndicators = "0">
<CoSimulation
modelIdentifier = "Doors2ExampleFMU"
canHandleVariableCommunicationStepSize = "false"
canGetAndSetFMUstate = "false"
canSerializeFMUstate = "false"
providesDirectionalDerivative = "false"
canBeInstantiatedOnlyOncePerProcess = "true"
canInterpolateInputs = "false"
canRunAsynchronuously = "false">
<SourceFiles>
<File name="all.c"/>
</SourceFiles>
</CoSimulation>
<DefaultExperiment startTime="0" stepSize="0.01"/>
<ModelVariables>
<!--Index for next variable = 1 -->
<ScalarVariable name = "Door01LeftIsOpen"
valueReference = "0"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 2 -->
<ScalarVariable name = "Door01RightIsOpen"
valueReference = "1"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 3 -->
<ScalarVariable name = "LockDoor01Right"
valueReference = "2"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 4 -->
<ScalarVariable name = "LockDoor01Left"
valueReference = "3"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
</ModelVariables>
<ModelStructure>
<Outputs>
<Unknown index="0"/>
</Outputs>
</ModelStructure>
</fmiModelDescription>

View File

@@ -0,0 +1,20 @@
<!--
@file buildDescription.xml
@date 2025-09-06 15:15:34
This file is the fmi Build Description xml.
This file was generated by the DBC utility from:
datalink_2doors_example.dbc
DBC file version: 1.0.0.1
-->
<?xml version="1.0" encoding="UTF-8"?>
<fmiBuildDescription fmiVersion="2.0">
<BuildConfiguration modelIdentifier="Doors2ExampleFMU">
<SourceFileSet language="C++17">
<SourceFile name="fmi2Functions.c"/>
<SourceFile name="model.c"/>
<SourceFile name="cosimulation.c"/>
<PreprocessorDefinition name="FMI_VERSION" value="2"/>
</SourceFileSet>
</BuildConfiguration>
</fmiBuildDescription>

View File

@@ -0,0 +1,54 @@
/**
* @file config.h
* @date 2025-09-06 15:15:34
* This file defines the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* datalink_2doors_example.dbc
* DBC file version: 1.0.0.1
*/
#ifndef __DBC_GENERATED__CONFIG_H__20250906_151534_698__
#define __DBC_GENERATED__CONFIG_H__20250906_151534_698__
#include <stdint.h>
// define class name and unique id
#define MODEL_IDENTIFIER Doors2ExampleFMU
#define INSTANTIATION_TOKEN "945aa152-f9fd-4d02-add5-a4320d05c0ab"
#define FMI_VERSION 2
#define CO_SIMULATION
// define model size
#define NX 0
#define NZ 0
#define GET_INT32
#define SET_INT32
#define GET_FLAOT64
#define SET_FLOAT64
#define EVENT_UPDATE
#define CLEAN_UP
#define FIXED_SOLVER_STEP 0.04
#define DEFAULT_STOP_TIME 10
typedef enum {
vr_Door01LeftIsOpen = 0,
vr_Door01RightIsOpen = 1,
vr_LockDoor01Right = 2,
vr_LockDoor01Left = 3,
} ValueReference;
typedef struct {
int32_t Door01LeftIsOpen;
int32_t Door01RightIsOpen;
int32_t LockDoor01Right;
int32_t LockDoor01Left;
} ModelData;
#endif // !defined __DBC_GENERATED__CONFIG_H__20250906_151534_698__

View File

@@ -0,0 +1,288 @@
/**
* @file model.cpp
* @date 2025-09-06 15:15:34
* This file defines the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* datalink_2doors_example.dbc
* DBC file version: 1.0.0.1
*/
#include <memory>
#include <vector>
#include <iostream>
#include <fstream>
#include <support/timer.h>
#include "signal_identifier.h"
#include <support/signal_support.h>
#include <support/app_control.h>
sdv::core::CSignal g_signalDoor01LeftIsOpen;
sdv::core::CSignal g_signalDoor01RightIsOpen;
sdv::core::CSignal g_signalLockDoor01Right;
sdv::core::CSignal g_signalLockDoor01Left;
// in case the simulation timer should be used
sdv::core::ITimerSimulationStep* g_pTimerSimulationStep;
std::unique_ptr<sdv::app::CAppControl> g_appcontrol;
bool InitializeAppControl(const std::string& resource, const std::string& configFileName)
{
auto bResult = g_appcontrol->AddModuleSearchDir( resource );
bResult &= g_appcontrol->Startup("");
g_appcontrol->SetConfigMode();
bResult &= g_appcontrol->AddConfigSearchDir( resource );
if (!configFileName.empty())
{
bResult &= g_appcontrol->LoadConfig(configFileName.c_str()) == sdv::core::EConfigProcessResult::successful;
}
return bResult;
}
sdv::core::EConfigProcessResult RegisterAllSignals()
{
std::string msg = "register all signals: ";
sdv::core::CDispatchService dispatch;
g_signalDoor01LeftIsOpen = dispatch.RegisterRxSignal("CAN_Input_L1.Door01LeftIsOpen");
g_signalDoor01RightIsOpen = dispatch.RegisterRxSignal("CAN_Input_R1.Door01RightIsOpen");
g_signalLockDoor01Right = dispatch.RegisterTxSignal("CAN_Output.LockDoor01Right",0);
g_signalLockDoor01Left = dispatch.RegisterTxSignal("CAN_Output.LockDoor01Left",0);
if (g_signalDoor01LeftIsOpen && g_signalDoor01RightIsOpen && g_signalLockDoor01Right && g_signalLockDoor01Left)
{
return sdv::core::EConfigProcessResult::successful;
}
return sdv::core::EConfigProcessResult::failed;
}
bool ResetAllSignals()
{
sdv::core::CDispatchService dispatch;
if (g_signalDoor01LeftIsOpen)
{
g_signalDoor01LeftIsOpen.Reset();
}
if (g_signalDoor01RightIsOpen)
{
g_signalDoor01RightIsOpen.Reset();
}
if (g_signalLockDoor01Right)
{
g_signalLockDoor01Right.Reset();
}
if (g_signalLockDoor01Left)
{
g_signalLockDoor01Left.Reset();
}
SDV_LOG_INFO("Reset signals");
return true;
}
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 << resources;
tomlFile << "\"\n";
tomlFile.close();
return true;
}
return false;
}
bool OpenAPILoad(const std::string& resources)
{
bool success = CreateCoreServiceTomlFile(resources);
g_appcontrol = std::make_unique<sdv::app::CAppControl> ();
//
// TODO: Dispatch service must be loaded first, adjust the correct toml file
//
success &= InitializeAppControl(resources, "data_dispatch_config_file.toml");
if (!success)
{
std::cout << "Error: InitializeAppControl() failed" << std::endl;
SDV_LOG_ERROR("Failed InitializeAppControl");
return false;
}
success &= RegisterAllSignals() == sdv::core::EConfigProcessResult::successful;
if (!success)
{
SDV_LOG_ERROR("Signals could not be registered");
}
//
//
// TODO: Load all configurations files
//
//
// Get the simulation task timer service if the simulation timer should be used
success &= g_appcontrol->LoadConfig("simulation_task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
g_pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
if (!g_pTimerSimulationStep)
{
SDV_LOG_WARNING("Simulation timer step not available, use normal task timer ");
success &= g_appcontrol->LoadConfig("task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
}
success &= g_appcontrol->LoadConfig("front_left_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("front_right_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("door_comple_service.toml") == sdv::core::EConfigProcessResult::successful;
g_appcontrol->SetRunningMode();
return success;
}
void OpenAPIShutdown()
{
ResetAllSignals();
}
#ifdef __cplusplus
extern "C" {
#endif
#include <float.h> // for DBL_EPSILON
#include <math.h> // for fabs()
#include "config.h"
#include "model.h"
Status cleanup(ModelInstance*)
{
SDV_LOG_INFO("Shutting down...");
OpenAPIShutdown();
return OK;
}
bool setStartValues(ModelInstance* comp)
{
std::string path(comp->resourceLocation);
std::string resourcePath = path.substr(8);
std::replace(resourcePath.begin(), resourcePath.end(), '\\', '/');
if (!OpenAPILoad(resourcePath))
{
std::cout << "Error: OpenAPILoad() failed." << std::endl;
comp->terminateSimulation = true;
return false;
}
// TODO: move this to initialize()?
comp->nextEventTime = 0;
comp->nextEventTimeDefined = true;
return true;
}
Status calculateValues(ModelInstance* comp)
{
UNUSED(comp);
// nothing to do
return OK;
}
Status getFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
return OK;
}
Status getInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
switch (vr)
{
case vr_Door01LeftIsOpen:
values[(*index)++] = M(Door01LeftIsOpen);
break;
case vr_Door01RightIsOpen:
values[(*index)++] = M(Door01RightIsOpen);
break;
case vr_LockDoor01Right:
values[(*index)++] = M(LockDoor01Right);
break;
case vr_LockDoor01Left:
values[(*index)++] = M(LockDoor01Left);
break;
default:
logError(comp, "Get Int32 is not allowed for value reference u.", vr);
return Error;
}
return OK;
}
Status setFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
return OK;
}
Status setInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
switch (vr)
{
case vr_Door01LeftIsOpen:
M(Door01LeftIsOpen) = values[(*index)++];
break;
case vr_Door01RightIsOpen:
M(Door01RightIsOpen) = values[(*index)++];
break;
case vr_LockDoor01Right:
M(LockDoor01Right) = values[(*index)++];
break;
case vr_LockDoor01Left:
M(LockDoor01Left) = values[(*index)++];
break;
default:
logError(comp, "Set Int32 is not allowed for value reference u.", vr);
return Error;
}
return OK;
}
void eventUpdate(ModelInstance* comp)
{
if (g_pTimerSimulationStep) // in case the simulation timer was used, maybe the step size has to be adjusted
{
g_pTimerSimulationStep->SimulationStep(1000);
}
g_signalDoor01LeftIsOpen.Write( M(Door01LeftIsOpen));
g_signalDoor01RightIsOpen.Write( M(Door01RightIsOpen));
M(LockDoor01Right) = g_signalLockDoor01Right.Read().get<uint32_t>();
M(LockDoor01Left) = g_signalLockDoor01Left.Read().get<uint32_t>();
double epsilon = (1.0 + fabs(comp->time)) * DBL_EPSILON;
if (comp->nextEventTimeDefined && comp->time + epsilon >= comp->nextEventTime) {
comp->nextEventTime += FIXED_SOLVER_STEP;
}
comp->valuesOfContinuousStatesChanged = false;
comp->nominalsOfContinuousStatesChanged = false;
comp->terminateSimulation = false;
comp->nextEventTimeDefined = true;
}
#ifdef __cplusplus
} // end of extern "C"
#endif

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "door_complex_service.sdv"
Class = "Doors Example Service"

View File

@@ -0,0 +1,14 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Device"
[[Component]]
Path = "doors_bs_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Service"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Device"
[[Component]]
Path = "doors_bs_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Service"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "simulation_task_timer.sdv"
Class = "SimulationTaskTimerService"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"

View File

@@ -0,0 +1,22 @@
/**
@file signal_identifier.h
@date 2025-09-06 15:15:34
This file is the signal identifier header.
This file was generated by the DBC utility from:
datalink_2doors_example.dbc
DBC file version: 1.0.0.1
*/
#ifndef __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_151534_698__
#define __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_151534_698__
namespace Doors2ExampleFMU
{
// Data Dispatch Service signal names to dbc variable names C-type RX/TX vss name space
static std::string dsDoor01LeftIsOpen = "CAN_Input_L1.Door01LeftIsOpen";
static std::string dsDoor01RightIsOpen = "CAN_Input_R1.Door01RightIsOpen";
static std::string dsLockDoor01Right = "CAN_Output.LockDoor01Right";
static std::string dsLockDoor01Left = "CAN_Output.LockDoor01Left";
} // Doors2ExampleFMU
#endif // __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_151534_698__

View File

@@ -0,0 +1,7 @@
#pragma once
#include "model.h"
#define EPSILON (FIXED_SOLVER_STEP * 1e-6)
void doFixedStep(ModelInstance *comp, bool* stateEvent, bool* timeEvent);

View File

@@ -0,0 +1,272 @@
#ifndef fmi2FunctionTypes_h
#define fmi2FunctionTypes_h
#include "fmi2TypesPlatform.h"
/* This header file must be utilized when compiling an FMU or an FMI master.
It declares data and function types for FMI 2.0.1
Revisions:
- Sep. 30, 2019: License changed to 2-clause BSD License (without extensions)
- Jul. 5, 2019: Remove const modifier from fields of fmi2CallbackFunctions (#216)
- Sep. 6, 2018: Parameter names added to function prototypes
- Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Apr. 3, 2014: Added #include <stddef.h> for size_t definition
- Mar. 27, 2014: Added #include "fmiTypesPlatform.h" (#179)
- Mar. 26, 2014: Introduced function argument "void" for the functions (#171)
fmiGetTypesPlatformTYPE and fmiGetVersionTYPE
- Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged:
fmiInstantiateModelTYPE , fmiInstantiateSlaveTYPE -> fmiInstantiateTYPE
fmiFreeModelInstanceTYPE, fmiFreeSlaveInstanceTYPE -> fmiFreeInstanceTYPE
fmiEnterModelInitializationModeTYPE, fmiEnterSlaveInitializationModeTYPE -> fmiEnterInitializationModeTYPE
fmiExitModelInitializationModeTYPE , fmiExitSlaveInitializationModeTYPE -> fmiExitInitializationModeTYPE
fmiTerminateModelTYPE , fmiTerminateSlaveTYPE -> fmiTerminate
fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation)
Functions renamed
fmiUpdateDiscreteStatesTYPE -> fmiNewDiscreteStatesTYPE
Renamed elements of the enumeration fmiEventInfo
upcomingTimeEvent -> nextEventTimeDefined // due to generic naming scheme: varDefined + var
newUpdateDiscreteStatesNeeded -> newDiscreteStatesNeeded;
- June 13, 2013: Changed type fmiEventInfo
Functions removed:
fmiInitializeModelTYPE
fmiEventUpdateTYPE
fmiCompletedEventIterationTYPE
fmiInitializeSlaveTYPE
Functions added:
fmiEnterModelInitializationModeTYPE
fmiExitModelInitializationModeTYPE
fmiEnterEventModeTYPE
fmiUpdateDiscreteStatesTYPE
fmiEnterContinuousTimeModeTYPE
fmiEnterSlaveInitializationModeTYPE;
fmiExitSlaveInitializationModeTYPE;
- Feb. 17, 2013: Added third argument to fmiCompletedIntegratorStepTYPE
Changed function name "fmiTerminateType" to "fmiTerminateModelType" (due to #113)
Changed function name "fmiGetNominalContinuousStateTYPE" to
"fmiGetNominalsOfContinuousStatesTYPE"
Removed fmiGetStateValueReferencesTYPE.
- Nov. 14, 2011: First public Version
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
#ifdef __cplusplus
extern "C" {
#endif
/* make sure all compiler use the same alignment policies for structures */
#if defined _MSC_VER || defined __GNUC__
#pragma pack(push,8)
#endif
/* Include stddef.h, in order that size_t etc. is defined */
#include <stddef.h>
/* Type definitions */
typedef enum {
fmi2OK,
fmi2Warning,
fmi2Discard,
fmi2Error,
fmi2Fatal,
fmi2Pending
} fmi2Status;
typedef enum {
fmi2ModelExchange,
fmi2CoSimulation
} fmi2Type;
typedef enum {
fmi2DoStepStatus,
fmi2PendingStatus,
fmi2LastSuccessfulTime,
fmi2Terminated
} fmi2StatusKind;
typedef void (*fmi2CallbackLogger) (fmi2ComponentEnvironment componentEnvironment,
fmi2String instanceName,
fmi2Status status,
fmi2String category,
fmi2String message,
...);
typedef void* (*fmi2CallbackAllocateMemory)(size_t nobj, size_t size);
typedef void (*fmi2CallbackFreeMemory) (void* obj);
typedef void (*fmi2StepFinished) (fmi2ComponentEnvironment componentEnvironment,
fmi2Status status);
typedef struct {
fmi2CallbackLogger logger;
fmi2CallbackAllocateMemory allocateMemory;
fmi2CallbackFreeMemory freeMemory;
fmi2StepFinished stepFinished;
fmi2ComponentEnvironment componentEnvironment;
} fmi2CallbackFunctions;
typedef struct {
fmi2Boolean newDiscreteStatesNeeded;
fmi2Boolean terminateSimulation;
fmi2Boolean nominalsOfContinuousStatesChanged;
fmi2Boolean valuesOfContinuousStatesChanged;
fmi2Boolean nextEventTimeDefined;
fmi2Real nextEventTime;
} fmi2EventInfo;
/* reset alignment policy to the one set before reading this file */
#if defined _MSC_VER || defined __GNUC__
#pragma pack(pop)
#endif
/* Define fmi2 function pointer types to simplify dynamic loading */
/***************************************************
Types for Common Functions
****************************************************/
/* Inquire version numbers of header files and setting logging status */
typedef const char* fmi2GetTypesPlatformTYPE(void);
typedef const char* fmi2GetVersionTYPE(void);
typedef fmi2Status fmi2SetDebugLoggingTYPE(fmi2Component c,
fmi2Boolean loggingOn,
size_t nCategories,
const fmi2String categories[]);
/* Creation and destruction of FMU instances and setting debug status */
typedef fmi2Component fmi2InstantiateTYPE(fmi2String instanceName,
fmi2Type fmuType,
fmi2String fmuGUID,
fmi2String fmuResourceLocation,
const fmi2CallbackFunctions* functions,
fmi2Boolean visible,
fmi2Boolean loggingOn);
typedef void fmi2FreeInstanceTYPE(fmi2Component c);
/* Enter and exit initialization mode, terminate and reset */
typedef fmi2Status fmi2SetupExperimentTYPE (fmi2Component c,
fmi2Boolean toleranceDefined,
fmi2Real tolerance,
fmi2Real startTime,
fmi2Boolean stopTimeDefined,
fmi2Real stopTime);
typedef fmi2Status fmi2EnterInitializationModeTYPE(fmi2Component c);
typedef fmi2Status fmi2ExitInitializationModeTYPE (fmi2Component c);
typedef fmi2Status fmi2TerminateTYPE (fmi2Component c);
typedef fmi2Status fmi2ResetTYPE (fmi2Component c);
/* Getting and setting variable values */
typedef fmi2Status fmi2GetRealTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]);
typedef fmi2Status fmi2GetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]);
typedef fmi2Status fmi2GetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]);
typedef fmi2Status fmi2GetStringTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]);
typedef fmi2Status fmi2SetRealTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]);
typedef fmi2Status fmi2SetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]);
typedef fmi2Status fmi2SetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]);
typedef fmi2Status fmi2SetStringTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]);
/* Getting and setting the internal FMU state */
typedef fmi2Status fmi2GetFMUstateTYPE (fmi2Component c, fmi2FMUstate* FMUstate);
typedef fmi2Status fmi2SetFMUstateTYPE (fmi2Component c, fmi2FMUstate FMUstate);
typedef fmi2Status fmi2FreeFMUstateTYPE (fmi2Component c, fmi2FMUstate* FMUstate);
typedef fmi2Status fmi2SerializedFMUstateSizeTYPE(fmi2Component c, fmi2FMUstate FMUstate, size_t* size);
typedef fmi2Status fmi2SerializeFMUstateTYPE (fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte[], size_t size);
typedef fmi2Status fmi2DeSerializeFMUstateTYPE (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate);
/* Getting partial derivatives */
typedef fmi2Status fmi2GetDirectionalDerivativeTYPE(fmi2Component c,
const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
const fmi2ValueReference vKnown_ref[], size_t nKnown,
const fmi2Real dvKnown[],
fmi2Real dvUnknown[]);
/***************************************************
Types for Functions for FMI2 for Model Exchange
****************************************************/
/* Enter and exit the different modes */
typedef fmi2Status fmi2EnterEventModeTYPE (fmi2Component c);
typedef fmi2Status fmi2NewDiscreteStatesTYPE (fmi2Component c, fmi2EventInfo* fmi2eventInfo);
typedef fmi2Status fmi2EnterContinuousTimeModeTYPE(fmi2Component c);
typedef fmi2Status fmi2CompletedIntegratorStepTYPE(fmi2Component c,
fmi2Boolean noSetFMUStatePriorToCurrentPoint,
fmi2Boolean* enterEventMode,
fmi2Boolean* terminateSimulation);
/* Providing independent variables and re-initialization of caching */
typedef fmi2Status fmi2SetTimeTYPE (fmi2Component c, fmi2Real time);
typedef fmi2Status fmi2SetContinuousStatesTYPE(fmi2Component c, const fmi2Real x[], size_t nx);
/* Evaluation of the model equations */
typedef fmi2Status fmi2GetDerivativesTYPE (fmi2Component c, fmi2Real derivatives[], size_t nx);
typedef fmi2Status fmi2GetEventIndicatorsTYPE (fmi2Component c, fmi2Real eventIndicators[], size_t ni);
typedef fmi2Status fmi2GetContinuousStatesTYPE (fmi2Component c, fmi2Real x[], size_t nx);
typedef fmi2Status fmi2GetNominalsOfContinuousStatesTYPE(fmi2Component c, fmi2Real x_nominal[], size_t nx);
/***************************************************
Types for Functions for FMI2 for Co-Simulation
****************************************************/
/* Simulating the slave */
typedef fmi2Status fmi2SetRealInputDerivativesTYPE (fmi2Component c,
const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[],
const fmi2Real value[]);
typedef fmi2Status fmi2GetRealOutputDerivativesTYPE(fmi2Component c,
const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[],
fmi2Real value[]);
typedef fmi2Status fmi2DoStepTYPE (fmi2Component c,
fmi2Real currentCommunicationPoint,
fmi2Real communicationStepSize,
fmi2Boolean noSetFMUStatePriorToCurrentPoint);
typedef fmi2Status fmi2CancelStepTYPE(fmi2Component c);
/* Inquire slave status */
typedef fmi2Status fmi2GetStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2Status* value);
typedef fmi2Status fmi2GetRealStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2Real* value);
typedef fmi2Status fmi2GetIntegerStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value);
typedef fmi2Status fmi2GetBooleanStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value);
typedef fmi2Status fmi2GetStringStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2String* value);
#ifdef __cplusplus
} /* end of extern "C" { */
#endif
#endif /* fmi2FunctionTypes_h */

View File

@@ -0,0 +1,328 @@
#ifndef fmi2Functions_h
#define fmi2Functions_h
/* This header file must be utilized when compiling a FMU.
It defines all functions of the
FMI 2.0.1 Model Exchange and Co-Simulation Interface.
In order to have unique function names even if several FMUs
are compiled together (e.g. for embedded systems), every "real" function name
is constructed by prepending the function name by "FMI2_FUNCTION_PREFIX".
Therefore, the typical usage is:
#define FMI2_FUNCTION_PREFIX MyModel_
#include "fmi2Functions.h"
As a result, a function that is defined as "fmi2GetDerivatives" in this header file,
is actually getting the name "MyModel_fmi2GetDerivatives".
This only holds if the FMU is shipped in C source code, or is compiled in a
static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function
names are used and "FMI2_FUNCTION_PREFIX" must not be defined.
Revisions:
- Sep. 29, 2019: License changed to 2-clause BSD License (without extensions)
- Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Mar. 26, 2014: FMI_Export set to empty value if FMI_Export and FMI_FUNCTION_PREFIX
are not defined (#173)
- Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged:
fmiInstantiateModel , fmiInstantiateSlave -> fmiInstantiate
fmiFreeModelInstance, fmiFreeSlaveInstance -> fmiFreeInstance
fmiEnterModelInitializationMode, fmiEnterSlaveInitializationMode -> fmiEnterInitializationMode
fmiExitModelInitializationMode , fmiExitSlaveInitializationMode -> fmiExitInitializationMode
fmiTerminateModel, fmiTerminateSlave -> fmiTerminate
fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation)
Functions renamed:
fmiUpdateDiscreteStates -> fmiNewDiscreteStates
- June 13, 2013: Functions removed:
fmiInitializeModel
fmiEventUpdate
fmiCompletedEventIteration
fmiInitializeSlave
Functions added:
fmiEnterModelInitializationMode
fmiExitModelInitializationMode
fmiEnterEventMode
fmiUpdateDiscreteStates
fmiEnterContinuousTimeMode
fmiEnterSlaveInitializationMode;
fmiExitSlaveInitializationMode;
- Feb. 17, 2013: Portability improvements:
o DllExport changed to FMI_Export
o FUNCTION_PREFIX changed to FMI_FUNCTION_PREFIX
o Allow undefined FMI_FUNCTION_PREFIX (meaning no prefix is used)
Changed function name "fmiTerminate" to "fmiTerminateModel" (due to #113)
Changed function name "fmiGetNominalContinuousState" to
"fmiGetNominalsOfContinuousStates"
Removed fmiGetStateValueReferences.
- Nov. 14, 2011: Adapted to FMI 2.0:
o Split into two files (fmiFunctions.h, fmiTypes.h) in order
that code that dynamically loads an FMU can directly
utilize the header files).
o Added C++ encapsulation of C-part, in order that the header
file can be directly utilized in C++ code.
o fmiCallbackFunctions is passed as pointer to fmiInstantiateXXX
o stepFinished within fmiCallbackFunctions has as first
argument "fmiComponentEnvironment" and not "fmiComponent".
o New functions to get and set the complete FMU state
and to compute partial derivatives.
- Nov. 4, 2010: Adapted to specification text:
o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform
o fmiInstantiateSlave: Argument GUID replaced by fmuGUID
Argument mimetype replaced by mimeType
o tabs replaced by spaces
- Oct. 16, 2010: Functions for FMI for Co-simulation added
- Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27)
(by M. Otter, DLR)
Added WIN32 pragma to define the struct layout (ticket #34)
(by J. Mauss, QTronic)
- Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize
Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion
Renamed macro fmiModelFunctionsVersion to fmiVersion
Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel
(by J. Mauss, QTronic)
- Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR).
- Dez. 14, 2009: Added eventInfo to meInitialize and added
meGetNominalContinuousStates (by Martin Otter, DLR)
- Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion)
(by A. Junghanns, QTronic)
- Sept. 9, 2009: Changes according to FMI-meeting on July 21:
meInquireModelTypesVersion -> meGetModelTypesPlatform
meInquireModelFunctionsVersion -> meGetModelFunctionsVersion
meSetStates -> meSetContinuousStates
meGetStates -> meGetContinuousStates
removal of meInitializeModelClass
removal of meGetTime
change of arguments of meInstantiateModel
change of arguments of meCompletedIntegratorStep
(by Martin Otter, DLR):
- July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR).
- March 2, 2009: Changed function definitions according to the last design
meeting with additional improvements (by Martin Otter, DLR).
- Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim).
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "fmi2TypesPlatform.h"
#include "fmi2FunctionTypes.h"
#include <stdlib.h>
/*
Export FMI2 API functions on Windows and under GCC.
If custom linking is desired then the FMI2_Export must be
defined before including this file. For instance,
it may be set to __declspec(dllimport).
*/
#if !defined(FMI2_Export)
#if !defined(FMI2_FUNCTION_PREFIX)
#if defined _WIN32 || defined __CYGWIN__
/* Note: both gcc & MSVC on Windows support this syntax. */
#define FMI2_Export __declspec(dllexport)
#else
#if __GNUC__ >= 4
#define FMI2_Export __attribute__ ((visibility ("default")))
#else
#define FMI2_Export
#endif
#endif
#else
#define FMI2_Export
#endif
#endif
/* Macros to construct the real function name
(prepend function name by FMI2_FUNCTION_PREFIX) */
#if defined(FMI2_FUNCTION_PREFIX)
#define fmi2Paste(a,b) a ## b
#define fmi2PasteB(a,b) fmi2Paste(a,b)
#define fmi2FullName(name) fmi2PasteB(FMI2_FUNCTION_PREFIX, name)
#else
#define fmi2FullName(name) name
#endif
/***************************************************
Common Functions
****************************************************/
#define fmi2GetTypesPlatform fmi2FullName(fmi2GetTypesPlatform)
#define fmi2GetVersion fmi2FullName(fmi2GetVersion)
#define fmi2SetDebugLogging fmi2FullName(fmi2SetDebugLogging)
#define fmi2Instantiate fmi2FullName(fmi2Instantiate)
#define fmi2FreeInstance fmi2FullName(fmi2FreeInstance)
#define fmi2SetupExperiment fmi2FullName(fmi2SetupExperiment)
#define fmi2EnterInitializationMode fmi2FullName(fmi2EnterInitializationMode)
#define fmi2ExitInitializationMode fmi2FullName(fmi2ExitInitializationMode)
#define fmi2Terminate fmi2FullName(fmi2Terminate)
#define fmi2Reset fmi2FullName(fmi2Reset)
#define fmi2GetReal fmi2FullName(fmi2GetReal)
#define fmi2GetInteger fmi2FullName(fmi2GetInteger)
#define fmi2GetBoolean fmi2FullName(fmi2GetBoolean)
#define fmi2GetString fmi2FullName(fmi2GetString)
#define fmi2SetReal fmi2FullName(fmi2SetReal)
#define fmi2SetInteger fmi2FullName(fmi2SetInteger)
#define fmi2SetBoolean fmi2FullName(fmi2SetBoolean)
#define fmi2SetString fmi2FullName(fmi2SetString)
#define fmi2GetFMUstate fmi2FullName(fmi2GetFMUstate)
#define fmi2SetFMUstate fmi2FullName(fmi2SetFMUstate)
#define fmi2FreeFMUstate fmi2FullName(fmi2FreeFMUstate)
#define fmi2SerializedFMUstateSize fmi2FullName(fmi2SerializedFMUstateSize)
#define fmi2SerializeFMUstate fmi2FullName(fmi2SerializeFMUstate)
#define fmi2DeSerializeFMUstate fmi2FullName(fmi2DeSerializeFMUstate)
#define fmi2GetDirectionalDerivative fmi2FullName(fmi2GetDirectionalDerivative)
/***************************************************
Functions for FMI2 for Model Exchange
****************************************************/
#define fmi2EnterEventMode fmi2FullName(fmi2EnterEventMode)
#define fmi2NewDiscreteStates fmi2FullName(fmi2NewDiscreteStates)
#define fmi2EnterContinuousTimeMode fmi2FullName(fmi2EnterContinuousTimeMode)
#define fmi2CompletedIntegratorStep fmi2FullName(fmi2CompletedIntegratorStep)
#define fmi2SetTime fmi2FullName(fmi2SetTime)
#define fmi2SetContinuousStates fmi2FullName(fmi2SetContinuousStates)
#define fmi2GetDerivatives fmi2FullName(fmi2GetDerivatives)
#define fmi2GetEventIndicators fmi2FullName(fmi2GetEventIndicators)
#define fmi2GetContinuousStates fmi2FullName(fmi2GetContinuousStates)
#define fmi2GetNominalsOfContinuousStates fmi2FullName(fmi2GetNominalsOfContinuousStates)
/***************************************************
Functions for FMI2 for Co-Simulation
****************************************************/
#define fmi2SetRealInputDerivatives fmi2FullName(fmi2SetRealInputDerivatives)
#define fmi2GetRealOutputDerivatives fmi2FullName(fmi2GetRealOutputDerivatives)
#define fmi2DoStep fmi2FullName(fmi2DoStep)
#define fmi2CancelStep fmi2FullName(fmi2CancelStep)
#define fmi2GetStatus fmi2FullName(fmi2GetStatus)
#define fmi2GetRealStatus fmi2FullName(fmi2GetRealStatus)
#define fmi2GetIntegerStatus fmi2FullName(fmi2GetIntegerStatus)
#define fmi2GetBooleanStatus fmi2FullName(fmi2GetBooleanStatus)
#define fmi2GetStringStatus fmi2FullName(fmi2GetStringStatus)
/* Version number */
#define fmi2Version "2.0"
/***************************************************
Common Functions
****************************************************/
/* Inquire version numbers of header files */
FMI2_Export fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform;
FMI2_Export fmi2GetVersionTYPE fmi2GetVersion;
FMI2_Export fmi2SetDebugLoggingTYPE fmi2SetDebugLogging;
/* Creation and destruction of FMU instances */
FMI2_Export fmi2InstantiateTYPE fmi2Instantiate;
FMI2_Export fmi2FreeInstanceTYPE fmi2FreeInstance;
/* Enter and exit initialization mode, terminate and reset */
FMI2_Export fmi2SetupExperimentTYPE fmi2SetupExperiment;
FMI2_Export fmi2EnterInitializationModeTYPE fmi2EnterInitializationMode;
FMI2_Export fmi2ExitInitializationModeTYPE fmi2ExitInitializationMode;
FMI2_Export fmi2TerminateTYPE fmi2Terminate;
FMI2_Export fmi2ResetTYPE fmi2Reset;
/* Getting and setting variables values */
FMI2_Export fmi2GetRealTYPE fmi2GetReal;
FMI2_Export fmi2GetIntegerTYPE fmi2GetInteger;
FMI2_Export fmi2GetBooleanTYPE fmi2GetBoolean;
FMI2_Export fmi2GetStringTYPE fmi2GetString;
FMI2_Export fmi2SetRealTYPE fmi2SetReal;
FMI2_Export fmi2SetIntegerTYPE fmi2SetInteger;
FMI2_Export fmi2SetBooleanTYPE fmi2SetBoolean;
FMI2_Export fmi2SetStringTYPE fmi2SetString;
/* Getting and setting the internal FMU state */
FMI2_Export fmi2GetFMUstateTYPE fmi2GetFMUstate;
FMI2_Export fmi2SetFMUstateTYPE fmi2SetFMUstate;
FMI2_Export fmi2FreeFMUstateTYPE fmi2FreeFMUstate;
FMI2_Export fmi2SerializedFMUstateSizeTYPE fmi2SerializedFMUstateSize;
FMI2_Export fmi2SerializeFMUstateTYPE fmi2SerializeFMUstate;
FMI2_Export fmi2DeSerializeFMUstateTYPE fmi2DeSerializeFMUstate;
/* Getting partial derivatives */
FMI2_Export fmi2GetDirectionalDerivativeTYPE fmi2GetDirectionalDerivative;
/***************************************************
Functions for FMI2 for Model Exchange
****************************************************/
/* Enter and exit the different modes */
FMI2_Export fmi2EnterEventModeTYPE fmi2EnterEventMode;
FMI2_Export fmi2NewDiscreteStatesTYPE fmi2NewDiscreteStates;
FMI2_Export fmi2EnterContinuousTimeModeTYPE fmi2EnterContinuousTimeMode;
FMI2_Export fmi2CompletedIntegratorStepTYPE fmi2CompletedIntegratorStep;
/* Providing independent variables and re-initialization of caching */
FMI2_Export fmi2SetTimeTYPE fmi2SetTime;
FMI2_Export fmi2SetContinuousStatesTYPE fmi2SetContinuousStates;
/* Evaluation of the model equations */
FMI2_Export fmi2GetDerivativesTYPE fmi2GetDerivatives;
FMI2_Export fmi2GetEventIndicatorsTYPE fmi2GetEventIndicators;
FMI2_Export fmi2GetContinuousStatesTYPE fmi2GetContinuousStates;
FMI2_Export fmi2GetNominalsOfContinuousStatesTYPE fmi2GetNominalsOfContinuousStates;
/***************************************************
Functions for FMI2 for Co-Simulation
****************************************************/
/* Simulating the slave */
FMI2_Export fmi2SetRealInputDerivativesTYPE fmi2SetRealInputDerivatives;
FMI2_Export fmi2GetRealOutputDerivativesTYPE fmi2GetRealOutputDerivatives;
FMI2_Export fmi2DoStepTYPE fmi2DoStep;
FMI2_Export fmi2CancelStepTYPE fmi2CancelStep;
/* Inquire slave status */
FMI2_Export fmi2GetStatusTYPE fmi2GetStatus;
FMI2_Export fmi2GetRealStatusTYPE fmi2GetRealStatus;
FMI2_Export fmi2GetIntegerStatusTYPE fmi2GetIntegerStatus;
FMI2_Export fmi2GetBooleanStatusTYPE fmi2GetBooleanStatus;
FMI2_Export fmi2GetStringStatusTYPE fmi2GetStringStatus;
#ifdef __cplusplus
} /* end of extern "C" { */
#endif
#endif /* fmi2Functions_h */

View File

@@ -0,0 +1,109 @@
#ifndef fmi2TypesPlatform_h
#define fmi2TypesPlatform_h
/* Standard header file to define the argument types of the
functions of the Functional Mock-up Interface 2.0.1
This header file must be utilized both by the model and
by the simulation engine.
Revisions:
- Sep. 29, 2019: License changed to 2-clause BSD License (without extensions)
- Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Mar 31, 2014: New datatype fmiChar introduced.
- Feb. 17, 2013: Changed fmiTypesPlatform from "standard32" to "default".
Removed fmiUndefinedValueReference since no longer needed
(because every state is defined in ScalarVariables).
- March 20, 2012: Renamed from fmiPlatformTypes.h to fmiTypesPlatform.h
- Nov. 14, 2011: Use the header file "fmiPlatformTypes.h" for FMI 2.0
both for "FMI for model exchange" and for "FMI for co-simulation"
New types "fmiComponentEnvironment", "fmiState", and "fmiByte".
The implementation of "fmiBoolean" is change from "char" to "int".
The #define "fmiPlatform" changed to "fmiTypesPlatform"
(in order that #define and function call are consistent)
- Oct. 4, 2010: Renamed header file from "fmiModelTypes.h" to fmiPlatformTypes.h"
for the co-simulation interface
- Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic)
- Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent"
according to meeting on Dec. 18 (by Martin Otter, DLR)
- Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR)
- Sept. 9, 2009: Changes according to FMI-meeting on July 21:
Changed "version" to "platform", "standard" to "standard32",
Added a precise definition of "standard32" as comment
(by Martin Otter, DLR)
- July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse,
and changed meValueReferenced from int to unsigned int
(by Martin Otter, DLR).
- March 2, 2009: Moved enums and function pointer definitions to
ModelFunctions.h (by Martin Otter, DLR).
- Dec. 3, 2008 : First version by Martin Otter (DLR) and
Hans Olsson (Dynasim).
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
/* Platform (unique identification of this header file) */
#define fmi2TypesPlatform "default"
/* Type definitions of variables passed as arguments
Version "default" means:
fmi2Component : an opaque object pointer
fmi2ComponentEnvironment: an opaque object pointer
fmi2FMUstate : an opaque object pointer
fmi2ValueReference : handle to the value of a variable
fmi2Real : double precision floating-point data type
fmi2Integer : basic signed integer data type
fmi2Boolean : basic signed integer data type
fmi2Char : character data type
fmi2String : a pointer to a vector of fmi2Char characters
('\0' terminated, UTF8 encoded)
fmi2Byte : smallest addressable unit of the machine, typically one byte.
*/
typedef void* fmi2Component; /* Pointer to FMU instance */
typedef void* fmi2ComponentEnvironment; /* Pointer to FMU environment */
typedef void* fmi2FMUstate; /* Pointer to internal FMU state */
typedef unsigned int fmi2ValueReference;
typedef double fmi2Real ;
typedef int fmi2Integer;
typedef int fmi2Boolean;
typedef char fmi2Char;
typedef const fmi2Char* fmi2String;
typedef char fmi2Byte;
/* Values for fmi2Boolean */
#define fmi2True 1
#define fmi2False 0
#endif /* fmi2TypesPlatform_h */

View File

@@ -0,0 +1,254 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#if FMI_VERSION != 1 && FMI_VERSION != 2 && FMI_VERSION != 3
#error FMI_VERSION must be one of 1, 2 or 3
#endif
#define UNUSED(x) (void)(x)
#include <stddef.h> // for size_t
#include <stdbool.h> // for bool
#include <stdint.h>
#include "config.h"
#if FMI_VERSION == 1
#define not_modelError (Instantiated| Initialized | Terminated)
typedef enum {
Instantiated = 1 << 0,
Initialized = 1 << 1,
Terminated = 1 << 2,
modelError = 1 << 3
} ModelState;
#elif FMI_VERSION == 2
typedef enum {
StartAndEnd = 1 << 0,
Instantiated = 1 << 1,
InitializationMode = 1 << 2,
// ME states
EventMode = 1 << 3,
ContinuousTimeMode = 1 << 4,
// CS states
StepComplete = 1 << 5,
StepInProgress = 1 << 6,
StepFailed = 1 << 7,
StepCanceled = 1 << 8,
Terminated = 1 << 9,
modelError = 1 << 10,
modelFatal = 1 << 11,
} ModelState;
#else
typedef enum {
StartAndEnd = 1 << 0,
ConfigurationMode = 1 << 1,
Instantiated = 1 << 2,
InitializationMode = 1 << 3,
EventMode = 1 << 4,
ContinuousTimeMode = 1 << 5,
StepMode = 1 << 6,
ClockActivationMode = 1 << 7,
StepDiscarded = 1 << 8,
ReconfigurationMode = 1 << 9,
IntermediateUpdateMode = 1 << 10,
Terminated = 1 << 11,
modelError = 1 << 12,
modelFatal = 1 << 13,
} ModelState;
#endif
typedef enum {
ModelExchange,
CoSimulation,
ScheduledExecution,
} InterfaceType;
typedef enum {
OK,
Warning,
Discard,
Error,
Fatal,
Pending
} Status;
#if FMI_VERSION < 3
typedef void (*loggerType) (void* componentEnvironment, const char* instanceName, int status, const char* category, const char* message, ...);
#else
typedef void (*loggerType) (void* componentEnvironment, int status, const char* category, const char* message);
#endif
typedef void (*lockPreemptionType) (void);
typedef void (*unlockPreemptionType) (void);
typedef void (*intermediateUpdateType) (void* instanceEnvironment,
double intermediateUpdateTime,
bool intermediateVariableSetRequested,
bool intermediateVariableGetAllowed,
bool intermediateStepFinished,
bool canReturnEarly,
bool* earlyReturnRequested,
double* earlyReturnTime);
typedef void(*clockUpdateType) (void* instanceEnvironment);
typedef struct {
double startTime;
double stopTime;
double time;
const char* instanceName;
InterfaceType type;
const char* resourceLocation;
Status status;
// callback functions
loggerType logger;
intermediateUpdateType intermediateUpdate;
clockUpdateType clockUpdate;
lockPreemptionType lockPreemtion;
unlockPreemptionType unlockPreemtion;
bool logEvents;
bool logErrors;
void* componentEnvironment;
ModelState state;
// event info
bool newDiscreteStatesNeeded;
bool terminateSimulation;
bool nominalsOfContinuousStatesChanged;
bool valuesOfContinuousStatesChanged;
bool nextEventTimeDefined;
double nextEventTime;
bool clocksTicked;
bool isDirtyValues;
ModelData modelData;
#if NZ > 0
// event indicators
double z[NZ];
#endif
// internal solver steps
uint64_t nSteps;
// Co-Simulation
bool earlyReturnAllowed;
bool eventModeUsed;
} ModelInstance;
ModelInstance* createModelInstance(
loggerType logger,
intermediateUpdateType intermediateUpdate,
void* componentEnvironment,
const char* instanceName,
const char* instantiationToken,
const char* resourceLocation,
bool loggingOn,
InterfaceType interfaceType);
void freeModelInstance(ModelInstance* comp);
void reset(ModelInstance* comp);
bool setStartValues(ModelInstance* comp);
Status calculateValues(ModelInstance* comp);
Status getFloat32(ModelInstance* comp, ValueReference vr, float values[], size_t nValues, size_t* index);
Status getFloat64(ModelInstance* comp, ValueReference vr, double values[], size_t nValues, size_t* index);
Status getInt8(ModelInstance* comp, ValueReference vr, int8_t values[], size_t nValues, size_t* index);
Status getUInt8(ModelInstance* comp, ValueReference vr, uint8_t values[], size_t nValues, size_t* index);
Status getInt16(ModelInstance* comp, ValueReference vr, int16_t values[], size_t nValues, size_t* index);
Status getUInt16(ModelInstance* comp, ValueReference vr, uint16_t values[], size_t nValues, size_t* index);
Status getInt32(ModelInstance* comp, ValueReference vr, int32_t values[], size_t nValues, size_t* index);
Status getUInt32(ModelInstance* comp, ValueReference vr, uint32_t values[], size_t nValues, size_t* index);
Status getInt64(ModelInstance* comp, ValueReference vr, int64_t values[], size_t nValues, size_t* index);
Status getUInt64(ModelInstance* comp, ValueReference vr, uint64_t values[], size_t nValues, size_t* index);
Status getBoolean(ModelInstance* comp, ValueReference vr, bool values[], size_t nValues, size_t* index);
Status getString(ModelInstance* comp, ValueReference vr, const char* values[], size_t nValues, size_t* index);
Status getBinary(ModelInstance* comp, ValueReference vr, size_t sizes[], const char* values[], size_t nValues, size_t* index);
Status setFloat32(ModelInstance* comp, ValueReference vr, const float values[], size_t nValues, size_t* index);
Status setFloat64(ModelInstance* comp, ValueReference vr, const double values[], size_t nValues, size_t* index);
Status setInt8(ModelInstance* comp, ValueReference vr, const int8_t values[], size_t nValues, size_t* index);
Status setUInt8(ModelInstance* comp, ValueReference vr, const uint8_t values[], size_t nValues, size_t* index);
Status setInt16(ModelInstance* comp, ValueReference vr, const int16_t values[], size_t nValues, size_t* index);
Status setUInt16(ModelInstance* comp, ValueReference vr, const uint16_t values[], size_t nValues, size_t* index);
Status setInt32(ModelInstance* comp, ValueReference vr, const int32_t values[], size_t nValues, size_t* index);
Status setUInt32(ModelInstance* comp, ValueReference vr, const uint32_t values[], size_t nValues, size_t* index);
Status setInt64(ModelInstance* comp, ValueReference vr, const int64_t values[], size_t nValues, size_t* index);
Status setUInt64(ModelInstance* comp, ValueReference vr, const uint64_t values[], size_t nValues, size_t* index);
Status setBoolean(ModelInstance* comp, ValueReference vr, const bool values[], size_t nValues, size_t* index);
Status setString(ModelInstance* comp, ValueReference vr, const char* const values[], size_t nValues, size_t* index);
Status setBinary(ModelInstance* comp, ValueReference vr, const size_t sizes[], const char* const values[], size_t nValues, size_t* index);
Status activateClock(ModelInstance* comp, ValueReference vr);
Status getClock(ModelInstance* comp, ValueReference vr, bool* value);
Status setClock(ModelInstance* comp, ValueReference vr, const bool* value);
Status getInterval(ModelInstance* comp, ValueReference vr, double* interval, int* qualifier);
Status activateModelPartition(ModelInstance* comp, ValueReference vr, double activationTime);
void getContinuousStates(ModelInstance* comp, double x[], size_t nx);
void setContinuousStates(ModelInstance* comp, const double x[], size_t nx);
void getDerivatives(ModelInstance* comp, double dx[], size_t nx);
Status getOutputDerivative(ModelInstance* comp, ValueReference valueReference, int order, double* value);
Status getPartialDerivative(ModelInstance* comp, ValueReference unknown, ValueReference known, double* partialDerivative);
void getEventIndicators(ModelInstance* comp, double z[], size_t nz);
void eventUpdate(ModelInstance* comp);
//void updateEventTime(ModelInstance *comp);
bool invalidNumber(ModelInstance* comp, const char* f, const char* arg, size_t actual, size_t expected);
bool invalidState(ModelInstance* comp, const char* f, int statesExpected);
bool nullPointer(ModelInstance* comp, const char* f, const char* arg, const void* p);
void logError(ModelInstance* comp, const char* message, ...);
Status setDebugLogging(ModelInstance* comp, bool loggingOn, size_t nCategories, const char* const categories[]);
void logEvent(ModelInstance* comp, const char* message, ...);
void logError(ModelInstance* comp, const char* message, ...);
void* getFMUState(ModelInstance* comp);
void setFMUState(ModelInstance* comp, void* FMUState);
// shorthand to access the variables
#define M(v) (comp->modelData.v)
// "stringification" macros
#define xstr(s) str(s)
#define str(s) #s
// assert size of nValues for scalar variables
#define ASSERT_NVALUES(N) do { \
if (*index + (N) > nValues) { \
logError(comp, "Expected nValues > %zu but was %zu.", *index, nValues); \
return Error; \
} \
} while (0)
#ifdef __cplusplus
} // end of extern "C"
#endif

View File

@@ -0,0 +1,598 @@
#include <stdlib.h> // for calloc(), free()
#include <float.h> // for DBL_EPSILON
#include <math.h> // for fabs()
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "config.h"
#include "cosimulation.h"
#if FMI_VERSION == 3
#include "fmi3Functions.h"
#endif
#ifdef _MSC_VER
#define strdup _strdup
#endif
ModelInstance *createModelInstance(
loggerType cbLogger,
intermediateUpdateType intermediateUpdate,
void *componentEnvironment,
const char *instanceName,
const char *instantiationToken,
const char *resourceLocation,
bool loggingOn,
InterfaceType interfaceType) {
ModelInstance *comp = NULL;
if (!instanceName || strlen(instanceName) == 0) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, "?", Error, "error", "Missing instance name.");
#else
cbLogger(componentEnvironment, Error, "error", "Missing instance name.");
#endif
}
return NULL;
}
if (!instantiationToken || strlen(instantiationToken) == 0) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, instanceName, Error, "error", "Missing GUID.");
#else
cbLogger(componentEnvironment, Error, "error", "Missing instantiationToken.");
#endif
}
return NULL;
}
if (strcmp(instantiationToken, INSTANTIATION_TOKEN)) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, instanceName, Error, "error", "Wrong GUID.");
#else
cbLogger(componentEnvironment, Error, "error", "Wrong instantiationToken.");
#endif
}
return NULL;
}
comp = (ModelInstance *)calloc(1, sizeof(ModelInstance));
if (comp) {
comp->componentEnvironment = componentEnvironment;
comp->logger = cbLogger;
comp->intermediateUpdate = intermediateUpdate;
comp->lockPreemtion = NULL;
comp->unlockPreemtion = NULL;
comp->instanceName = strdup(instanceName);
comp->resourceLocation = resourceLocation ? strdup(resourceLocation) : NULL;
comp->status = OK;
comp->logEvents = loggingOn;
comp->logErrors = true; // always log errors
comp->nSteps = 0;
comp->earlyReturnAllowed = false;
comp->eventModeUsed = false;
}
if (!comp || !comp->instanceName) {
logError(comp, "Out of memory.");
return NULL;
}
comp->time = 0.0; // overwrite in fmi*SetupExperiment, fmi*SetTime
comp->type = interfaceType;
comp->state = Instantiated;
comp->newDiscreteStatesNeeded = false;
comp->terminateSimulation = false;
comp->nominalsOfContinuousStatesChanged = false;
comp->valuesOfContinuousStatesChanged = false;
comp->nextEventTimeDefined = false;
comp->nextEventTime = 0;
if (!setStartValues(comp))
{
cbLogger(componentEnvironment, instanceName, Error, "error", "VAPI initialization failed.");
}
comp->isDirtyValues = true;
return comp;
}
void freeModelInstance(ModelInstance *comp) {
free((void *)comp->instanceName);
free(comp);
}
void reset(ModelInstance* comp) {
comp->state = Instantiated;
comp->startTime = 0.0;
comp->time = 0.0;
comp->nSteps = 0;
comp->status = OK;
setStartValues(comp);
comp->isDirtyValues = true;
}
bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected) {
if (actual != expected) {
comp->state = modelError;
logError(comp, "%s: Invalid argument %s = %d. Expected %d.", f, arg, actual, expected);
return true;
}
return false;
}
bool invalidState(ModelInstance *comp, const char *f, int statesExpected) {
UNUSED(f);
UNUSED(statesExpected);
if (!comp) {
return true;
}
// TODO: add missing states and check state
return false;
// if (!(comp->state & statesExpected)) {
// comp->state = modelError;
// logError(comp, "%s: Illegal call sequence.", f);
// return true;
// }
//
// return false;
}
bool nullPointer(ModelInstance* comp, const char *f, const char *arg, const void *p) {
if (!p) {
comp->state = modelError;
logError(comp, "%s: Invalid argument %s = NULL.", f, arg);
return true;
}
return false;
}
Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char * const categories[]) {
if (nCategories > 0) {
if (categories == NULL) {
logError(comp, "Argument categories must not be NULL.");
return Error;
}
for (size_t i = 0; i < nCategories; i++) {
if (categories[i] == NULL) {
logError(comp, "Argument categories[%zu] must not be NULL.", i);
return Error;
} else if (strcmp(categories[i], "logEvents") == 0) {
comp->logEvents = loggingOn;
} else if (strcmp(categories[i], "logStatusError") == 0) {
comp->logErrors = loggingOn;
} else {
logError(comp, "Log categories[%zu] must be one of \"logEvents\" or \"logStatusError\" but was \"%s\".", i, categories[i]);
return Error;
}
}
} else {
comp->logEvents = loggingOn;
comp->logErrors = loggingOn;
}
return OK;
}
static void logMessage(ModelInstance *comp, int status, const char *category, const char *message, va_list args) {
if (!comp->logger) {
return;
}
va_list args1;
int len = 0;
char *buf = "";
va_copy(args1, args);
len = vsnprintf(buf, len, message, args1);
va_end(args1);
if (len < 0) {
return;
}
va_copy(args1, args);
buf = (char *)calloc(len + 1, sizeof(char));
len = vsnprintf(buf, len + 1, message, args);
va_end(args1);
if (len >= 0) {
// no need to distinguish between FMI versions since we're not using variadic arguments
#if FMI_VERSION < 3
comp->logger(comp->componentEnvironment, comp->instanceName, status, category, buf);
#else
comp->logger(comp->componentEnvironment, status, category, buf);
#endif
}
free(buf);
}
void logEvent(ModelInstance *comp, const char *message, ...) {
if (!comp || !comp->logEvents) return;
va_list args;
va_start(args, message);
logMessage(comp, OK, "logEvents", message, args);
va_end(args);
}
void logError(ModelInstance *comp, const char *message, ...) {
if (!comp || !comp->logErrors) return;
va_list args;
va_start(args, message);
logMessage(comp, Error, "logStatusError", message, args);
va_end(args);
}
// default implementations
#if NZ < 1
void getEventIndicators(ModelInstance *comp, double z[], size_t nz) {
UNUSED(comp);
UNUSED(z);
UNUSED(nz);
// do nothing
}
#endif
#define GET_NOT_ALLOWED(t) do { \
UNUSED(vr); \
UNUSED(values); \
UNUSED(nValues); \
UNUSED(index); \
logError(comp, "Getting " t " is not allowed.");\
return Error; \
} while (false)
#ifndef GET_FLOAT32
Status getFloat32(ModelInstance* comp, ValueReference vr, float values[], size_t nValues, size_t* index) {
GET_NOT_ALLOWED("Float32");
}
#endif
#ifndef GET_INT8
Status getInt8(ModelInstance* comp, ValueReference vr, int8_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int8");
}
#endif
#ifndef GET_UINT8
Status getUInt8(ModelInstance* comp, ValueReference vr, uint8_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt8");
}
#endif
#ifndef GET_INT16
Status getInt16(ModelInstance* comp, ValueReference vr, int16_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int16");
}
#endif
#ifndef GET_UINT16
Status getUInt16(ModelInstance* comp, ValueReference vr, uint16_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt16");
}
#endif
#ifndef GET_INT32
Status getInt32(ModelInstance* comp, ValueReference vr, int32_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int32");
}
#endif
#ifndef GET_UINT32
Status getUInt32(ModelInstance* comp, ValueReference vr, uint32_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt32");
}
#endif
#ifndef GET_INT64
Status getInt64(ModelInstance* comp, ValueReference vr, int64_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int64");
}
#endif
#ifndef GET_UINT64
Status getUInt64(ModelInstance* comp, ValueReference vr, uint64_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt64");
}
#endif
#ifndef GET_BOOLEAN
Status getBoolean(ModelInstance* comp, ValueReference vr, bool values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Boolean");
}
#endif
#ifndef GET_STRING
Status getString(ModelInstance* comp, ValueReference vr, const char* values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("String");
}
#endif
#ifndef GET_BINARY
Status getBinary(ModelInstance* comp, ValueReference vr, size_t sizes[], const char* values[], size_t nValues, size_t *index) {
UNUSED(sizes);
GET_NOT_ALLOWED("Binary");
}
#endif
#define SET_NOT_ALLOWED(t) do { \
UNUSED(vr); \
UNUSED(values); \
UNUSED(nValues); \
UNUSED(index); \
logError(comp, "Setting " t " is not allowed.");\
return Error; \
} while (false)
#ifndef SET_FLOAT32
Status setFloat32(ModelInstance* comp, ValueReference vr, const float values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Float32");
}
#endif
#ifndef SET_FLOAT64
Status setFloat64(ModelInstance* comp, ValueReference vr, const double values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Float64");
}
#endif
#ifndef SET_INT8
Status setInt8(ModelInstance* comp, ValueReference vr, const int8_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int8");
}
#endif
#ifndef SET_UINT8
Status setUInt8(ModelInstance* comp, ValueReference vr, const uint8_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt8");
}
#endif
#ifndef SET_INT16
Status setInt16(ModelInstance* comp, ValueReference vr, const int16_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int16");
}
#endif
#ifndef SET_UINT16
Status setUInt16(ModelInstance* comp, ValueReference vr, const uint16_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt16");
}
#endif
#ifndef SET_INT32
Status setInt32(ModelInstance* comp, ValueReference vr, const int32_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int32");
}
#endif
#ifndef SET_UINT32
Status setUInt32(ModelInstance* comp, ValueReference vr, const uint32_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt32");
}
#endif
#ifndef SET_INT64
Status setInt64(ModelInstance* comp, ValueReference vr, const int64_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int64");
}
#endif
#ifndef SET_UINT64
Status setUInt64(ModelInstance* comp, ValueReference vr, const uint64_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt64");
}
#endif
#ifndef SET_BOOLEAN
Status setBoolean(ModelInstance* comp, ValueReference vr, const bool values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Boolean");
}
#endif
#ifndef SET_STRING
Status setString(ModelInstance* comp, ValueReference vr, const char *const values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("String");
}
#endif
#ifndef SET_BINARY
Status setBinary(ModelInstance* comp, ValueReference vr, const size_t size[], const char *const values[], size_t nValues, size_t* index) {
UNUSED(size);
SET_NOT_ALLOWED("Binary");
}
#endif
#ifndef ACTIVATE_CLOCK
Status activateClock(ModelInstance* comp, ValueReference vr) {
UNUSED(comp);
UNUSED(vr);
return Error;
}
#endif
#ifndef GET_CLOCK
Status getClock(ModelInstance* comp, ValueReference vr, bool* value) {
UNUSED(comp);
UNUSED(vr);
UNUSED(value);
return Error;
}
#endif
#ifndef GET_INTERVAL
Status getInterval(ModelInstance* comp, ValueReference vr, double* interval, int* qualifier) {
UNUSED(comp);
UNUSED(vr);
UNUSED(interval);
UNUSED(qualifier);
return Error;
}
#endif
#ifndef ACTIVATE_MODEL_PARTITION
Status activateModelPartition(ModelInstance* comp, ValueReference vr, double activationTime) {
UNUSED(comp);
UNUSED(vr);
UNUSED(activationTime);
return Error;
}
#endif
#if NX < 1
void getContinuousStates(ModelInstance *comp, double x[], size_t nx) {
UNUSED(comp);
UNUSED(x);
UNUSED(nx);
}
void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) {
UNUSED(comp);
UNUSED(x);
UNUSED(nx);
}
void getDerivatives(ModelInstance *comp, double dx[], size_t nx) {
UNUSED(comp);
UNUSED(dx);
UNUSED(nx);
}
#endif
#ifndef GET_PARTIAL_DERIVATIVE
Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative) {
UNUSED(comp);
UNUSED(unknown);
UNUSED(known);
UNUSED(partialDerivative);
logError(comp, "Directional derivatives are not supported.");
return Error;
}
#endif
void* getFMUState(ModelInstance* comp) {
ModelInstance* fmuState = (ModelInstance*)calloc(1, sizeof(ModelInstance));
if (fmuState) {
memcpy(fmuState, comp, sizeof(ModelInstance));
}
return fmuState;
}
void setFMUState(ModelInstance* comp, void* FMUState) {
ModelInstance* s = (ModelInstance*)FMUState;
comp->startTime = s->startTime;
comp->stopTime = s->stopTime;
comp->time = s->time;
comp->status = s->status;
comp->state = s->state;
comp->newDiscreteStatesNeeded = s->newDiscreteStatesNeeded;
comp->terminateSimulation = s->terminateSimulation;
comp->nominalsOfContinuousStatesChanged = s->nominalsOfContinuousStatesChanged;
comp->valuesOfContinuousStatesChanged = s->valuesOfContinuousStatesChanged;
comp->nextEventTimeDefined = s->nextEventTimeDefined;
comp->nextEventTime = s->nextEventTime;
comp->clocksTicked = s->clocksTicked;
comp->isDirtyValues = s->isDirtyValues;
comp->modelData = s->modelData;
#if NZ > 0
memcpy(comp->z, s->z, NZ * sizeof(double));
#endif
comp->nSteps = s->nSteps;
}
void doFixedStep(ModelInstance *comp, bool* stateEvent, bool* timeEvent) {
#if NX > 0
double x[NX] = { 0 };
double dx[NX] = { 0 };
getContinuousStates(comp, x, NX);
getDerivatives(comp, dx, NX);
// forward Euler step
for (int i = 0; i < NX; i++) {
x[i] += FIXED_SOLVER_STEP * dx[i];
}
setContinuousStates(comp, x, NX);
#endif
comp->nSteps++;
comp->time = comp->startTime + comp->nSteps * FIXED_SOLVER_STEP;
// state event
*stateEvent = false;
#if NZ > 0
double z[NZ] = { 0.0 };
getEventIndicators(comp, z, NZ);
// check for zero-crossings
for (int i = 0; i < NZ; i++) {
*stateEvent |= (comp->z[i] <= 0 && z[i] > 0) || (comp->z[i] > 0 && z[i] <= 0);
}
// remember the current event indicators
memcpy(comp->z, z, sizeof(double) * NZ);
#endif
// time event
*timeEvent = comp->nextEventTimeDefined && comp->time >= comp->nextEventTime;
bool earlyReturnRequested;
double earlyReturnTime;
// intermediate update
if (comp->intermediateUpdate) {
comp->intermediateUpdate(
comp->componentEnvironment, // instanceEnvironment
comp->time, // intermediateUpdateTime
false, // intermediateVariableSetRequested
true, // intermediateVariableGetAllowed
true, // intermediateStepFinished
false, // canReturnEarly
&earlyReturnRequested, // earlyReturnRequested
&earlyReturnTime); // earlyReturnTime
}
}

View File

@@ -0,0 +1,887 @@
#if FMI_VERSION != 2
#error FMI_VERSION must be 2
#endif
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <math.h>
#include "config.h"
#include "model.h"
#include "cosimulation.h"
// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_.
// Define DISABLE_PREFIX to build a binary FMU.
#ifndef DISABLE_PREFIX
#define pasteA(a,b) a ## b
#define pasteB(a,b) pasteA(a,b)
#define FMI2_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _)
#endif
#include "fmi2Functions.h"
#define ASSERT_NOT_NULL(p) \
do { \
if (!p) { \
logError(S, "Argument %s must not be NULL.", xstr(p)); \
S->state = modelError; \
return (fmi2Status)Error; \
} \
} while (0)
#define GET_VARIABLES(T) \
do { \
Status status = OK; \
if (nvr == 0) return (fmi2Status)status; \
ASSERT_NOT_NULL(vr); \
ASSERT_NOT_NULL(value); \
size_t index = 0; \
if (S->isDirtyValues) { \
Status s = calculateValues(S); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
S->isDirtyValues = false; \
} \
for (size_t i = 0; i < nvr; i++) { \
Status s = get ## T(S, vr[i], value, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#define SET_VARIABLES(T) \
do { \
Status status = OK; \
if (nvr == 0) return (fmi2Status)status; \
ASSERT_NOT_NULL(vr); \
ASSERT_NOT_NULL(value); \
size_t index = 0; \
for (size_t i = 0; i < nvr; i++) { \
Status s = set ## T(S, vr[i], value, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
if (nvr > 0) S->isDirtyValues = true; \
return (fmi2Status)status; \
} while (0)
#define GET_BOOLEAN_VARIABLES \
do { \
Status status = OK; \
for (size_t i = 0; i < nvr; i++) { \
bool v = false; \
size_t index = 0; \
Status s = getBoolean(S, vr[i], &v, nvr, &index); \
value[i] = v; \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#define SET_BOOLEAN_VARIABLES \
do { \
Status status = OK; \
for (size_t i = 0; i < nvr; i++) { \
bool v = value[i]; \
size_t index = 0; \
Status s = setBoolean(S, vr[i], &v, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
#ifndef DT_EVENT_DETECT
#define DT_EVENT_DETECT 1e-10
#endif
// ---------------------------------------------------------------------------
// Function calls allowed state masks for both Model-exchange and Co-simulation
// ---------------------------------------------------------------------------
#define MASK_fmi2GetTypesPlatform (StartAndEnd | Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepInProgress | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2GetVersion MASK_fmi2GetTypesPlatform
#define MASK_fmi2SetDebugLogging (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepInProgress | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2Instantiate (StartAndEnd)
#define MASK_fmi2FreeInstance (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2SetupExperiment Instantiated
#define MASK_fmi2EnterInitializationMode Instantiated
#define MASK_fmi2ExitInitializationMode InitializationMode
#define MASK_fmi2Terminate (EventMode | ContinuousTimeMode \
| StepComplete | StepFailed)
#define MASK_fmi2Reset MASK_fmi2FreeInstance
#define MASK_fmi2GetReal (InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2GetInteger MASK_fmi2GetReal
#define MASK_fmi2GetBoolean MASK_fmi2GetReal
#define MASK_fmi2GetString MASK_fmi2GetReal
#define MASK_fmi2SetReal (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete)
#define MASK_fmi2SetInteger (Instantiated | InitializationMode \
| EventMode \
| StepComplete)
#define MASK_fmi2SetBoolean MASK_fmi2SetInteger
#define MASK_fmi2SetString MASK_fmi2SetInteger
#define MASK_fmi2GetFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2SetFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2FreeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2SerializedFMUstateSize MASK_fmi2FreeInstance
#define MASK_fmi2SerializeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2DeSerializeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2GetDirectionalDerivative (InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
// ---------------------------------------------------------------------------
// Function calls allowed state masks for Model-exchange
// ---------------------------------------------------------------------------
#define MASK_fmi2EnterEventMode (EventMode | ContinuousTimeMode)
#define MASK_fmi2NewDiscreteStates EventMode
#define MASK_fmi2EnterContinuousTimeMode EventMode
#define MASK_fmi2CompletedIntegratorStep ContinuousTimeMode
#define MASK_fmi2SetTime (EventMode | ContinuousTimeMode)
#define MASK_fmi2SetContinuousStates ContinuousTimeMode
#define MASK_fmi2GetEventIndicators (InitializationMode \
| EventMode | ContinuousTimeMode \
| Terminated | modelError)
#define MASK_fmi2GetContinuousStates MASK_fmi2GetEventIndicators
#define MASK_fmi2GetDerivatives (EventMode | ContinuousTimeMode \
| Terminated | modelError)
#define MASK_fmi2GetNominalsOfContinuousStates ( Instantiated \
| EventMode | ContinuousTimeMode \
| Terminated | modelError)
// ---------------------------------------------------------------------------
// Function calls allowed state masks for Co-simulation
// ---------------------------------------------------------------------------
#define MASK_fmi2SetRealInputDerivatives (Instantiated | InitializationMode \
| StepComplete)
#define MASK_fmi2GetRealOutputDerivatives (StepComplete | StepFailed | StepCanceled \
| Terminated | Error)
#define MASK_fmi2DoStep StepComplete
#define MASK_fmi2CancelStep StepInProgress
#define MASK_fmi2GetStatus (StepComplete | StepInProgress | StepFailed \
| Terminated)
#define MASK_fmi2GetRealStatus MASK_fmi2GetStatus
#define MASK_fmi2GetIntegerStatus MASK_fmi2GetStatus
#define MASK_fmi2GetBooleanStatus MASK_fmi2GetStatus
#define MASK_fmi2GetStringStatus MASK_fmi2GetStatus
// shorthand to access the instance
#define S ((ModelInstance *)c)
#define ASSERT_STATE(S) \
if (!allowedState(c, MASK_fmi2##S, #S)) \
return fmi2Error;
static bool allowedState(ModelInstance *instance, int statesExpected, char *name) {
if (!instance) {
return false;
}
if (!(instance->state & statesExpected)) {
logError(instance, "fmi2%s: Illegal call sequence.", name);
return false;
}
return true;
}
// ---------------------------------------------------------------------------
// FMI functions
// ---------------------------------------------------------------------------
fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions,
fmi2Boolean visible, fmi2Boolean loggingOn) {
UNUSED(visible);
if (!functions || !functions->logger) {
return NULL;
}
return createModelInstance(
(loggerType)functions->logger,
NULL,
functions->componentEnvironment,
instanceName,
fmuGUID,
fmuResourceLocation,
loggingOn,
(InterfaceType)fmuType);
}
fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance,
fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
UNUSED(toleranceDefined);
UNUSED(tolerance);
ASSERT_STATE(SetupExperiment)
S->startTime = startTime;
S->stopTime = stopTimeDefined ? stopTime : INFINITY;
S->time = startTime;
return fmi2OK;
}
fmi2Status fmi2EnterInitializationMode(fmi2Component c) {
ASSERT_STATE(EnterInitializationMode)
S->state = InitializationMode;
return fmi2OK;
}
fmi2Status fmi2ExitInitializationMode(fmi2Component c) {
ASSERT_STATE(ExitInitializationMode);
fmi2Status status = fmi2OK;
// if values were set and no fmi2GetXXX triggered update before,
// ensure calculated values are updated now
if (S->isDirtyValues) {
status = (fmi2Status)calculateValues(S);
S->isDirtyValues = false;
}
if (S->type == ModelExchange) {
S->state = EventMode;
} else {
S->state = StepComplete;
}
return status;
}
fmi2Status fmi2Terminate(fmi2Component c) {
ASSERT_STATE(Terminate)
S->state = Terminated;
return fmi2OK;
}
fmi2Status fmi2Reset(fmi2Component c) {
ASSERT_STATE(Reset);
reset(S);
return fmi2OK;
}
void fmi2FreeInstance(fmi2Component c) {
if (S) {
freeModelInstance(S);
}
}
// ---------------------------------------------------------------------------
// FMI functions: class methods not depending of a specific model instance
// ---------------------------------------------------------------------------
const char* fmi2GetVersion(void) {
return fmi2Version;
}
const char* fmi2GetTypesPlatform(void) {
return fmi2TypesPlatform;
}
// ---------------------------------------------------------------------------
// FMI functions: logging control, setters and getters for Real, Integer,
// Boolean, String
// ---------------------------------------------------------------------------
fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
ASSERT_STATE(SetDebugLogging)
return (fmi2Status)setDebugLogging(S, loggingOn, nCategories, categories);
}
fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
ASSERT_STATE(GetReal)
if (nvr > 0 && nullPointer(S, "fmi2GetReal", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetReal", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(Float64);
}
fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
ASSERT_STATE(GetInteger)
if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(Int32);
}
fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
ASSERT_STATE(GetBoolean)
if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_BOOLEAN_VARIABLES;
}
fmi2Status fmi2GetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
ASSERT_STATE(GetString)
if (nvr>0 && nullPointer(S, "fmi2GetString", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2GetString", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(String);
}
fmi2Status fmi2SetReal (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
ASSERT_STATE(SetReal)
if (nvr > 0 && nullPointer(S, "fmi2SetReal", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2SetReal", "value[]", value))
return fmi2Error;
SET_VARIABLES(Float64);
}
fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
ASSERT_STATE(SetInteger)
if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "value[]", value))
return fmi2Error;
SET_VARIABLES(Int32);
}
fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
ASSERT_STATE(SetBoolean)
if (nvr>0 && nullPointer(S, "fmi2SetBoolean", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2SetBoolean", "value[]", value))
return fmi2Error;
SET_BOOLEAN_VARIABLES;
}
fmi2Status fmi2SetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
ASSERT_STATE(SetString);
if (nvr>0 && nullPointer(S, "fmi2SetString", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2SetString", "value[]", value))
return fmi2Error;
SET_VARIABLES(String);
}
fmi2Status fmi2GetFMUstate (fmi2Component c, fmi2FMUstate* FMUstate) {
ASSERT_STATE(GetFMUstate);
*FMUstate = getFMUState(S);
return fmi2OK;
}
fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) {
ASSERT_STATE(SetFMUstate);
if (nullPointer(S, "fmi2SetFMUstate", "FMUstate", FMUstate)) {
return fmi2Error;
}
setFMUState(S, FMUstate);
return fmi2OK;
}
fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
ASSERT_STATE(FreeFMUstate);
free(*FMUstate);
*FMUstate = NULL;
return fmi2OK;
}
fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) {
UNUSED(c);
UNUSED(FMUstate);
ASSERT_STATE(SerializedFMUstateSize);
*size = sizeof(ModelInstance);
return fmi2OK;
}
fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) {
ASSERT_STATE(SerializeFMUstate);
if (nullPointer(S, "fmi2SerializeFMUstate", "FMUstate", FMUstate)) {
return fmi2Error;
}
if (invalidNumber(S, "fmi2SerializeFMUstate", "size", size, sizeof(ModelInstance))) {
return fmi2Error;
}
memcpy(serializedState, FMUstate, sizeof(ModelInstance));
return fmi2OK;
}
fmi2Status fmi2DeSerializeFMUstate (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) {
ASSERT_STATE(DeSerializeFMUstate);
if (invalidNumber(S, "fmi2DeSerializeFMUstate", "size", size, sizeof(ModelInstance))) {
return fmi2Error;
}
if (*FMUstate == NULL) {
*FMUstate = calloc(1, sizeof(ModelInstance));
}
memcpy(*FMUstate, serializedState, sizeof(ModelInstance));
return fmi2OK;
}
fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
const fmi2ValueReference vKnown_ref[] , size_t nKnown,
const fmi2Real dvKnown[], fmi2Real dvUnknown[]) {
ASSERT_STATE(GetDirectionalDerivative);
// TODO: check value references
// TODO: assert nUnknowns == nDeltaOfUnknowns
// TODO: assert nKnowns == nDeltaKnowns
Status status = OK;
for (size_t i = 0; i < nUnknown; i++) {
dvUnknown[i] = 0;
for (size_t j = 0; j < nKnown; j++) {
double partialDerivative = 0;
Status s = getPartialDerivative(S, vUnknown_ref[i], vKnown_ref[j], &partialDerivative);
status = max(status, s);
if (status > Warning) {
return (fmi2Status)status;
}
dvUnknown[i] += partialDerivative * dvKnown[j];
}
}
return fmi2OK;
}
// ---------------------------------------------------------------------------
// Functions for FMI for Co-Simulation
// ---------------------------------------------------------------------------
/* Simulating the slave */
fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[], const fmi2Real value[]) {
UNUSED(vr);
UNUSED(nvr);
UNUSED(order);
UNUSED(value);
ASSERT_STATE(SetRealInputDerivatives);
logError(S, "fmi2SetRealInputDerivatives: ignoring function call."
" This model cannot interpolate inputs: canInterpolateInputs=\"fmi2False\"");
return fmi2Error;
}
fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[], fmi2Real value[]) {
ASSERT_STATE(GetRealOutputDerivatives);
#ifdef GET_OUTPUT_DERIVATIVE
Status status = OK;
for (size_t i = 0; i < nvr; i++) {
const Status s = getOutputDerivative(S, vr[i], order[i], &value[i]);
status = max(status, s);
if (status > Warning) {
return (fmi2Status)status;
}
}
return (fmi2Status)status;
#else
UNUSED(vr);
UNUSED(nvr);
UNUSED(order);
UNUSED(value);
logError(S, "fmi2GetRealOutputDerivatives: ignoring function call."
" This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\"");
return fmi2Error;
#endif
}
fmi2Status fmi2CancelStep(fmi2Component c) {
ASSERT_STATE(CancelStep);
logError(S, "fmi2CancelStep: Can be called when fmi2DoStep returned fmi2Pending."
" This is not the case.");
return fmi2Error;
}
fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint,
fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
UNUSED(noSetFMUStatePriorToCurrentPoint);
ASSERT_STATE(DoStep);
if (communicationStepSize <= 0) {
logError(S, "Communication step size must be > 0 but was %g.", communicationStepSize);
S->state = modelError;
return fmi2Error;
}
if (currentCommunicationPoint + communicationStepSize > S->stopTime + EPSILON) {
logError(S, "At communication point %.16g a step size of %.16g was requested but stop time is %.16g.",
currentCommunicationPoint, communicationStepSize, S->stopTime);
S->state = modelError;
return fmi2Error;
}
const fmi2Real nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON;
while (true) {
if (S->time + FIXED_SOLVER_STEP > nextCommunicationPoint) {
break; // next communication point reached
}
bool stateEvent, timeEvent;
doFixedStep(S, &stateEvent, &timeEvent);
#ifdef EVENT_UPDATE
if (stateEvent || timeEvent) {
eventUpdate(S);
}
#endif
}
return S->terminateSimulation ? fmi2Discard : fmi2OK;
}
/* Inquire slave status */
static fmi2Status getStatus(char* fname, fmi2Component c, const fmi2StatusKind s) {
switch(s) {
case fmi2DoStepStatus: logError(S,
"%s: Can be called with fmi2DoStepStatus when fmi2DoStep returned fmi2Pending."
" This is not the case.", fname);
break;
case fmi2PendingStatus: logError(S,
"%s: Can be called with fmi2PendingStatus when fmi2DoStep returned fmi2Pending."
" This is not the case.", fname);
break;
case fmi2LastSuccessfulTime: logError(S,
"%s: Can be called with fmi2LastSuccessfulTime when fmi2DoStep returned fmi2Discard."
" This is not the case.", fname);
break;
case fmi2Terminated: logError(S,
"%s: Can be called with fmi2Terminated when fmi2DoStep returned fmi2Discard."
" This is not the case.", fname);
break;
}
return fmi2Discard;
}
fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value) {
UNUSED(value);
ASSERT_STATE(GetStatus);
return getStatus("fmi2GetStatus", c, s);
}
fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value) {
ASSERT_STATE(GetRealStatus);
if (s == fmi2LastSuccessfulTime) {
*value = S->time;
return fmi2OK;
}
return getStatus("fmi2GetRealStatus", c, s);
}
fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value) {
UNUSED(value);
ASSERT_STATE(GetIntegerStatus);
return getStatus("fmi2GetIntegerStatus", c, s);
}
fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value) {
ASSERT_STATE(GetBooleanStatus);
if (s == fmi2Terminated) {
*value = S->terminateSimulation;
return fmi2OK;
}
return getStatus("fmi2GetBooleanStatus", c, s);
}
fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value) {
UNUSED(value);
ASSERT_STATE(GetStringStatus);
return getStatus("fmi2GetStringStatus", c, s);
}
// ---------------------------------------------------------------------------
// Functions for FMI2 for Model Exchange
// ---------------------------------------------------------------------------
/* Enter and exit the different modes */
fmi2Status fmi2EnterEventMode(fmi2Component c) {
ASSERT_STATE(EnterEventMode);
S->state = EventMode;
return fmi2OK;
}
fmi2Status fmi2NewDiscreteStates(fmi2Component c, fmi2EventInfo *eventInfo) {
ASSERT_STATE(NewDiscreteStates);
#ifdef EVENT_UPDATE
eventUpdate(S);
#endif
eventInfo->newDiscreteStatesNeeded = S->newDiscreteStatesNeeded;
eventInfo->terminateSimulation = S->terminateSimulation;
eventInfo->nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged;
eventInfo->valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged;
eventInfo->nextEventTimeDefined = S->nextEventTimeDefined;
eventInfo->nextEventTime = S->nextEventTime;
return fmi2OK;
}
fmi2Status fmi2EnterContinuousTimeMode(fmi2Component c) {
ASSERT_STATE(EnterContinuousTimeMode);
S->state = ContinuousTimeMode;
return fmi2OK;
}
fmi2Status fmi2CompletedIntegratorStep(fmi2Component c, fmi2Boolean noSetFMUStatePriorToCurrentPoint,
fmi2Boolean *enterEventMode, fmi2Boolean *terminateSimulation) {
UNUSED(noSetFMUStatePriorToCurrentPoint);
ASSERT_STATE(CompletedIntegratorStep);
if (nullPointer(S, "fmi2CompletedIntegratorStep", "enterEventMode", enterEventMode))
return fmi2Error;
if (nullPointer(S, "fmi2CompletedIntegratorStep", "terminateSimulation", terminateSimulation))
return fmi2Error;
*enterEventMode = fmi2False;
*terminateSimulation = fmi2False;
return fmi2OK;
}
/* Providing independent variables and re-initialization of caching */
fmi2Status fmi2SetTime(fmi2Component c, fmi2Real time) {
ASSERT_STATE(SetTime);
S->time = time;
return fmi2OK;
}
fmi2Status fmi2SetContinuousStates(fmi2Component c, const fmi2Real x[], size_t nx){
ASSERT_STATE(SetContinuousStates);
if (invalidNumber(S, "fmi2SetContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2SetContinuousStates", "x[]", x))
return fmi2Error;
setContinuousStates(S, x, nx);
return fmi2OK;
}
/* Evaluation of the model equations */
fmi2Status fmi2GetDerivatives(fmi2Component c, fmi2Real derivatives[], size_t nx) {
ASSERT_STATE(GetDerivatives);
if (invalidNumber(S, "fmi2GetDerivatives", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetDerivatives", "derivatives[]", derivatives))
return fmi2Error;
getDerivatives(S, derivatives, nx);
return fmi2OK;
}
fmi2Status fmi2GetEventIndicators(fmi2Component c, fmi2Real eventIndicators[], size_t ni) {
ASSERT_STATE(GetEventIndicators);
#if NZ > 0
if (invalidNumber(S, "fmi2GetEventIndicators", "ni", ni, NZ))
return fmi2Error;
getEventIndicators(S, eventIndicators, ni);
#else
UNUSED(c);
UNUSED(eventIndicators);
if (ni > 0) return fmi2Error;
#endif
return fmi2OK;
}
fmi2Status fmi2GetContinuousStates(fmi2Component c, fmi2Real states[], size_t nx) {
ASSERT_STATE(GetContinuousStates);
if (invalidNumber(S, "fmi2GetContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetContinuousStates", "states[]", states))
return fmi2Error;
getContinuousStates(S, states, nx);
return fmi2OK;
}
fmi2Status fmi2GetNominalsOfContinuousStates(fmi2Component c, fmi2Real x_nominal[], size_t nx) {
ASSERT_STATE(GetNominalsOfContinuousStates);
if (invalidNumber(S, "fmi2GetNominalContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetNominalContinuousStates", "x_nominal[]", x_nominal))
return fmi2Error;
for (size_t i = 0; i < nx; i++)
x_nominal[i] = 1;
return fmi2OK;
}

View File

@@ -0,0 +1,87 @@
/* */
/* This script file uses the Doors4ExampleFMU.fmu to be run in OpenXiL */
/* */
ADD_BBVARI(Loop, UDWORD)
SET_BBVARI(Loop = 0)
/* */
/* Door01Left = 1 represents a open door */
/* wait more then 2 seconds */
/* Open all doors */
/* */
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
/* */
/* Close each door one by one */
/* wait more then 2 seconds */
/* Open all doors */
/* */
WHILE(Loop < 10)
SET_BBVARI(Door01LeftIsOpen = 0)
DELAY(100)
SET_BBVARI(Door01RightIsOpen = 0)
DELAY(100)
SET_BBVARI(Door02LeftIsOpen = 0)
DELAY(100)
SET_BBVARI(Door02RightIsOpen = 0)
/* */
/* wait until the doors are locked, < 2 seconds */
/* */
DELAY(1000)
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
SET_BBVARI(Door02LeftIsOpen = 1)
SET_BBVARI(Door02RightIsOpen = 1)
DELAY(100)
SET(Loop = Loop + 1)
ENDWHILE
/* */
/* This script file uses the Doors4ExampleFMU.fmu to be run in OpenXiL */
/* */
ADD_BBVARI(Loop, UDWORD)
SET_BBVARI(Loop = 0)
/* */
/* Door01Left = 1 represents a open door */
/* wait more then 2 seconds */
/* Open all doors */
/* */
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
/* */
/* Close each door one by one */
/* wait more then 2 seconds */
/* Open all doors */
/* */
WHILE(Loop < 10)
SET_BBVARI(Door01LeftIsOpen = 0)
DELAY(100)
SET_BBVARI(Door01RightIsOpen = 0)
DELAY(100)
DELAY(2000)
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
DELAY(100)
SET(Loop = Loop + 1)
ENDWHILE

View File

@@ -0,0 +1,180 @@
# @file CMakeLists.txt
# This file is cmake project file.
# This file was generated by the DBC utility from:
# datalink_4doors_example.dbc
# DBC file version: 1.0.0.1
# Based on CMakeLists.txt from https://github.com/modelica/Reference-FMUs
# only FMI 2.0, only CoSimulation
# without fumsim
# Only valid for Windows
if ( WIN32 )
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
project (Doors4ExampleFMUProject)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Library symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
set(VAPI_CORE_SDV_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
set(MODEL_NAME Doors4ExampleFMU)
set(TARGET_NAME ${MODEL_NAME})
set(FMU_FULL_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/fmus/${MODEL_NAME}.fmu")
FUNCTION(cat IN_FILE OUT_FILE)
file(READ ${IN_FILE} CONTENTS)
file(APPEND ${OUT_FILE} "${CONTENTS}")
ENDFUNCTION()
set(FMI_VERSION 2 CACHE STRING "FMI Version")
set_property(CACHE FMI_VERSION PROPERTY STRINGS 2)
set(FMI_TYPE CS CACHE STRING "FMI Version")
set_property(CACHE FMI_TYPE PROPERTY STRINGS CS)
set(FMI_TYPE "")
set (FMI_PLATFORM win32)
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set (FMI_PLATFORM win64)
endif ()
SET(HEADERS
${MODEL_NAME}/config.h
include/cosimulation.h
include/model.h
)
SET(HEADERS
${HEADERS}
include/fmi2Functions.h
include/fmi2FunctionTypes.h
include/fmi2TypesPlatform.h
)
SET(SOURCES
${MODEL_NAME}/model.cpp
src/fmi${FMI_VERSION}Functions.c
src/cosimulation.c
)
add_library(${TARGET_NAME} SHARED
${HEADERS}
${SOURCES}
${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
${MODEL_NAME}/buildDescription.xml
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fmus)
set(FMU_BUILD_DIR temp/${MODEL_NAME})
target_compile_definitions(${TARGET_NAME} PRIVATE
FMI_VERSION=${FMI_VERSION}
DISABLE_PREFIX
)
#[[
if (MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
endif()
]]
target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION)
target_include_directories(${TARGET_NAME} PRIVATE include ${MODEL_NAME})
target_link_libraries(${TARGET_NAME} Winmm Ws2_32 Rpcrt4.lib)
set_target_properties(${TARGET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
)
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME})
# modelDescription.xml
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
"${FMU_BUILD_DIR}/modelDescription.xml"
)
set(ARCHIVE_FILES "modelDescription.xml" "binaries")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources")
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources"
"${FMU_BUILD_DIR}/resources/"
)
set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources")
endif()
# When windows robocopy command (using cmd.exe) is used to copy files its important to set the dependencies
# to assure that the copy command is finished before the next custom action to avoid copy/file access failures
# Copy sdv binaries of this FMU
set(DEST_DIR "${FMU_BUILD_DIR}/resources")
set(SOURCE_DIR_EXAMPLES_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
add_custom_target(copy_function_sdv_files_${TARGET_NAME} DEPENDS ${TARGET_NAME})
add_custom_command(TARGET copy_function_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_EXAMPLES_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_EXAMPLES_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_function_sdv_files_${TARGET_NAME} ${TARGET_NAME})
# Copy framework sdv binaries
set(SOURCE_DIR_CORE_BIN "${SDV_FRAMEWORK_RUNTIME}")
add_custom_target(copy_framework_sdv_files_${TARGET_NAME} DEPENDS copy_function_sdv_files_${TARGET_NAME})
add_custom_command(TARGET copy_framework_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_CORE_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_CORE_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_framework_sdv_files_${TARGET_NAME} copy_function_sdv_files_${TARGET_NAME})
# FMU content created, all files copied
# to zip the files create a new target 'create_zip' which is build after all files have been copied
add_custom_target(create_zip_${TARGET_NAME} ALL DEPENDS copy_framework_sdv_files_${TARGET_NAME} )
add_custom_command(TARGET create_zip_${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${FMU_FULL_FILE_NAME} --format=zip ${ARCHIVE_FILES}
WORKING_DIRECTORY ${FMU_BUILD_DIR}
COMMENT "Creating ZIP ${FMU_FULL_FILE_NAME}"
)
add_dependencies(create_zip_${TARGET_NAME} copy_framework_sdv_files_${TARGET_NAME})
#TODO
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)
endif ()

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<fmiModelDescription
fmiVersion = "2.0"
modelName = "Doors4ExampleFMU"
guid = "3fbc9066-6c16-4b98-b5fc-7a7c0735f200"
description = "TargetLink FMU for Doors4ExampleFMU"
generationTool = "TargetLink was generated by the DBC utility: datalink_4doors_example.dbc"
generationDateAndTime = "2025-09-06 14:55:42"
variableNamingConvention = "structured"
numberOfEventIndicators = "0">
<CoSimulation
modelIdentifier = "Doors4ExampleFMU"
canHandleVariableCommunicationStepSize = "false"
canGetAndSetFMUstate = "false"
canSerializeFMUstate = "false"
providesDirectionalDerivative = "false"
canBeInstantiatedOnlyOncePerProcess = "true"
canInterpolateInputs = "false"
canRunAsynchronuously = "false">
<SourceFiles>
<File name="all.c"/>
</SourceFiles>
</CoSimulation>
<DefaultExperiment startTime="0" stepSize="0.01"/>
<ModelVariables>
<!--Index for next variable = 1 -->
<ScalarVariable name = "Door01LeftIsOpen"
valueReference = "0"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 2 -->
<ScalarVariable name = "Door01RightIsOpen"
valueReference = "1"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 3 -->
<ScalarVariable name = "Door02LeftIsOpen"
valueReference = "2"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 4 -->
<ScalarVariable name = "Door02RightIsOpen"
valueReference = "3"
description = " "
causality = "input">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 5 -->
<ScalarVariable name = "LockDoor02Right"
valueReference = "4"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 6 -->
<ScalarVariable name = "LockDoor02Left"
valueReference = "5"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 7 -->
<ScalarVariable name = "LockDoor01Right"
valueReference = "6"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
<!--Index for next variable = 8 -->
<ScalarVariable name = "LockDoor01Left"
valueReference = "7"
description = " "
causality = "output">
<Integer start = "0"
min = "0u"
max = "1u" />
</ScalarVariable>
</ModelVariables>
<ModelStructure>
<Outputs>
<Unknown index="0"/>
</Outputs>
</ModelStructure>
</fmiModelDescription>

View File

@@ -0,0 +1,20 @@
<!--
@file buildDescription.xml
@date 2025-09-06 14:55:42
This file is the fmi Build Description xml.
This file was generated by the DBC utility from:
datalink_4doors_example.dbc
DBC file version: 1.0.0.1
-->
<?xml version="1.0" encoding="UTF-8"?>
<fmiBuildDescription fmiVersion="2.0">
<BuildConfiguration modelIdentifier="Doors4ExampleFMU">
<SourceFileSet language="C++17">
<SourceFile name="fmi2Functions.c"/>
<SourceFile name="model.c"/>
<SourceFile name="cosimulation.c"/>
<PreprocessorDefinition name="FMI_VERSION" value="2"/>
</SourceFileSet>
</BuildConfiguration>
</fmiBuildDescription>

View File

@@ -0,0 +1,62 @@
/**
* @file config.h
* @date 2025-09-06 14:55:42
* This file defines the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* datalink_4doors_example.dbc
* DBC file version: 1.0.0.1
*/
#ifndef __DBC_GENERATED__CONFIG_H__20250906_145542_578__
#define __DBC_GENERATED__CONFIG_H__20250906_145542_578__
#include <stdint.h>
// define class name and unique id
#define MODEL_IDENTIFIER Doors4ExampleFMU
#define INSTANTIATION_TOKEN "3fbc9066-6c16-4b98-b5fc-7a7c0735f200"
#define FMI_VERSION 2
#define CO_SIMULATION
// define model size
#define NX 0
#define NZ 0
#define GET_INT32
#define SET_INT32
#define GET_FLAOT64
#define SET_FLOAT64
#define EVENT_UPDATE
#define CLEAN_UP
#define FIXED_SOLVER_STEP 0.04
#define DEFAULT_STOP_TIME 10
typedef enum {
vr_Door01LeftIsOpen = 0,
vr_Door01RightIsOpen = 1,
vr_Door02LeftIsOpen = 2,
vr_Door02RightIsOpen = 3,
vr_LockDoor02Right = 4,
vr_LockDoor02Left = 5,
vr_LockDoor01Right = 6,
vr_LockDoor01Left = 7,
} ValueReference;
typedef struct {
int32_t Door01LeftIsOpen;
int32_t Door01RightIsOpen;
int32_t Door02LeftIsOpen;
int32_t Door02RightIsOpen;
int32_t LockDoor02Right;
int32_t LockDoor02Left;
int32_t LockDoor01Right;
int32_t LockDoor01Left;
} ModelData;
#endif // !defined __DBC_GENERATED__CONFIG_H__20250906_145542_578__

View File

@@ -0,0 +1,343 @@
/**
* @file model.cpp
* @date 2025-09-06 14:55:42
* This file defines the data link object between CAN and the V-API devices.
* This file was generated by the DBC utility from:
* datalink_4doors_example.dbc
* DBC file version: 1.0.0.1
*/
#include <memory>
#include <vector>
#include <iostream>
#include <fstream>
#include <support/timer.h>
#include "signal_identifier.h"
#include <support/signal_support.h>
#include <support/app_control.h>
sdv::core::CSignal g_signalDoor01LeftIsOpen;
sdv::core::CSignal g_signalDoor01RightIsOpen;
sdv::core::CSignal g_signalDoor02LeftIsOpen;
sdv::core::CSignal g_signalDoor02RightIsOpen;
sdv::core::CSignal g_signalLockDoor02Right;
sdv::core::CSignal g_signalLockDoor02Left;
sdv::core::CSignal g_signalLockDoor01Right;
sdv::core::CSignal g_signalLockDoor01Left;
// in case the simulation timer should be used
sdv::core::ITimerSimulationStep* g_pTimerSimulationStep;
std::unique_ptr<sdv::app::CAppControl> g_appcontrol;
bool InitializeAppControl(const std::string& resource, const std::string& configFileName)
{
auto bResult = g_appcontrol->AddModuleSearchDir( resource );
bResult &= g_appcontrol->Startup("");
g_appcontrol->SetConfigMode();
bResult &= g_appcontrol->AddConfigSearchDir( resource );
if (!configFileName.empty())
{
bResult &= g_appcontrol->LoadConfig(configFileName.c_str()) == sdv::core::EConfigProcessResult::successful;
}
return bResult;
}
sdv::core::EConfigProcessResult RegisterAllSignals()
{
std::string msg = "register all signals: ";
sdv::core::CDispatchService dispatch;
g_signalDoor01LeftIsOpen = dispatch.RegisterRxSignal("CAN_Input_L1.Door01LeftIsOpen");
g_signalDoor01RightIsOpen = dispatch.RegisterRxSignal("CAN_Input_R1.Door01RightIsOpen");
g_signalDoor02LeftIsOpen = dispatch.RegisterRxSignal("CAN_Input_L2.Door02LeftIsOpen");
g_signalDoor02RightIsOpen = dispatch.RegisterRxSignal("CAN_Input_R2.Door02RightIsOpen");
g_signalLockDoor02Right = dispatch.RegisterTxSignal("CAN_Output.LockDoor02Right",0);
g_signalLockDoor02Left = dispatch.RegisterTxSignal("CAN_Output.LockDoor02Left",0);
g_signalLockDoor01Right = dispatch.RegisterTxSignal("CAN_Output.LockDoor01Right",0);
g_signalLockDoor01Left = dispatch.RegisterTxSignal("CAN_Output.LockDoor01Left",0);
if (g_signalDoor01LeftIsOpen && g_signalDoor01RightIsOpen && g_signalDoor02LeftIsOpen && g_signalDoor02RightIsOpen && g_signalLockDoor02Right && g_signalLockDoor02Left
&& g_signalLockDoor01Right && g_signalLockDoor01Left)
{
return sdv::core::EConfigProcessResult::successful;
}
return sdv::core::EConfigProcessResult::failed;
}
bool ResetAllSignals()
{
sdv::core::CDispatchService dispatch;
if (g_signalDoor01LeftIsOpen)
{
g_signalDoor01LeftIsOpen.Reset();
}
if (g_signalDoor01RightIsOpen)
{
g_signalDoor01RightIsOpen.Reset();
}
if (g_signalDoor02LeftIsOpen)
{
g_signalDoor02LeftIsOpen.Reset();
}
if (g_signalDoor02RightIsOpen)
{
g_signalDoor02RightIsOpen.Reset();
}
if (g_signalLockDoor02Right)
{
g_signalLockDoor02Right.Reset();
}
if (g_signalLockDoor02Left)
{
g_signalLockDoor02Left.Reset();
}
if (g_signalLockDoor01Right)
{
g_signalLockDoor01Right.Reset();
}
if (g_signalLockDoor01Left)
{
g_signalLockDoor01Left.Reset();
}
SDV_LOG_INFO("Reset signals");
return true;
}
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 << resources;
tomlFile << "\"\n";
tomlFile.close();
return true;
}
return false;
}
bool OpenAPILoad(const std::string& resources)
{
bool success = CreateCoreServiceTomlFile(resources);
g_appcontrol = std::make_unique<sdv::app::CAppControl> ();
//
// TODO: Dispatch service must be loaded first, adjust the correct toml file
//
success &= InitializeAppControl(resources, "data_dispatch_config_file.toml");
if (!success)
{
std::cout << "Error: InitializeAppControl() failed" << std::endl;
SDV_LOG_ERROR("Failed InitializeAppControl");
return false;
}
success &= RegisterAllSignals() == sdv::core::EConfigProcessResult::successful;
if (!success)
{
SDV_LOG_ERROR("Signals could not be registered");
}
//
//
// TODO: Load all configurations files
//
//
// Get the simulation task timer service if the simulation timer should be used
success &= g_appcontrol->LoadConfig("simulation_task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
g_pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
if (!g_pTimerSimulationStep)
{
SDV_LOG_WARNING("Simulation timer step not available, use normal task timer ");
success &= g_appcontrol->LoadConfig("task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
}
success &= g_appcontrol->LoadConfig("front_left_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("front_right_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("rear_left_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("rear_right_door_example.toml") == sdv::core::EConfigProcessResult::successful;
success &= g_appcontrol->LoadConfig("door_comple_service.toml") == sdv::core::EConfigProcessResult::successful;
g_appcontrol->SetRunningMode();
return success;
}
void OpenAPIShutdown()
{
ResetAllSignals();
}
#ifdef __cplusplus
extern "C" {
#endif
#include <float.h> // for DBL_EPSILON
#include <math.h> // for fabs()
#include "config.h"
#include "model.h"
Status cleanup(ModelInstance*)
{
SDV_LOG_INFO("Shutting down...");
OpenAPIShutdown();
return OK;
}
bool setStartValues(ModelInstance* comp)
{
std::string path(comp->resourceLocation);
std::string resourcePath = path.substr(8);
std::replace(resourcePath.begin(), resourcePath.end(), '\\', '/');
if (!OpenAPILoad(resourcePath))
{
std::cout << "Error: OpenAPILoad() failed." << std::endl;
comp->terminateSimulation = true;
return false;
}
// TODO: move this to initialize()?
comp->nextEventTime = 0;
comp->nextEventTimeDefined = true;
return true;
}
Status calculateValues(ModelInstance* comp)
{
UNUSED(comp);
// nothing to do
return OK;
}
Status getFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
return OK;
}
Status getInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
switch (vr)
{
case vr_Door01LeftIsOpen:
values[(*index)++] = M(Door01LeftIsOpen);
break;
case vr_Door01RightIsOpen:
values[(*index)++] = M(Door01RightIsOpen);
break;
case vr_Door02LeftIsOpen:
values[(*index)++] = M(Door02LeftIsOpen);
break;
case vr_Door02RightIsOpen:
values[(*index)++] = M(Door02RightIsOpen);
break;
case vr_LockDoor02Right:
values[(*index)++] = M(LockDoor02Right);
break;
case vr_LockDoor02Left:
values[(*index)++] = M(LockDoor02Left);
break;
case vr_LockDoor01Right:
values[(*index)++] = M(LockDoor01Right);
break;
case vr_LockDoor01Left:
values[(*index)++] = M(LockDoor01Left);
break;
default:
logError(comp, "Get Int32 is not allowed for value reference u.", vr);
return Error;
}
return OK;
}
Status setFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
return OK;
}
Status setInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
switch (vr)
{
case vr_Door01LeftIsOpen:
M(Door01LeftIsOpen) = values[(*index)++];
break;
case vr_Door01RightIsOpen:
M(Door01RightIsOpen) = values[(*index)++];
break;
case vr_Door02LeftIsOpen:
M(Door02LeftIsOpen) = values[(*index)++];
break;
case vr_Door02RightIsOpen:
M(Door02RightIsOpen) = values[(*index)++];
break;
case vr_LockDoor02Right:
M(LockDoor02Right) = values[(*index)++];
break;
case vr_LockDoor02Left:
M(LockDoor02Left) = values[(*index)++];
break;
case vr_LockDoor01Right:
M(LockDoor01Right) = values[(*index)++];
break;
case vr_LockDoor01Left:
M(LockDoor01Left) = values[(*index)++];
break;
default:
logError(comp, "Set Int32 is not allowed for value reference u.", vr);
return Error;
}
return OK;
}
void eventUpdate(ModelInstance* comp)
{
if (g_pTimerSimulationStep) // in case the simulation timer was used, maybe the step size has to be adjusted
{
g_pTimerSimulationStep->SimulationStep(1000);
}
g_signalDoor01LeftIsOpen.Write( M(Door01LeftIsOpen));
g_signalDoor01RightIsOpen.Write( M(Door01RightIsOpen));
g_signalDoor02LeftIsOpen.Write( M(Door02LeftIsOpen));
g_signalDoor02RightIsOpen.Write( M(Door02RightIsOpen));
M(LockDoor02Right) = g_signalLockDoor02Right.Read().get<uint32_t>();
M(LockDoor02Left) = g_signalLockDoor02Left.Read().get<uint32_t>();
M(LockDoor01Right) = g_signalLockDoor01Right.Read().get<uint32_t>();
M(LockDoor01Left) = g_signalLockDoor01Left.Read().get<uint32_t>();
double epsilon = (1.0 + fabs(comp->time)) * DBL_EPSILON;
if (comp->nextEventTimeDefined && comp->time + epsilon >= comp->nextEventTime) {
comp->nextEventTime += FIXED_SOLVER_STEP;
}
comp->valuesOfContinuousStatesChanged = false;
comp->nominalsOfContinuousStatesChanged = false;
comp->terminateSimulation = false;
comp->nextEventTimeDefined = true;
}
#ifdef __cplusplus
} // end of extern "C"
#endif

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "door_complex_service.sdv"
Class = "Doors Example Service"

View File

@@ -0,0 +1,14 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Device"
[[Component]]
Path = "doors_bs_frontdoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Left_Service"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Device"
[[Component]]
Path = "doors_bs_frontdoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle01.Right_Service"

View File

@@ -0,0 +1,14 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Device"
[[Component]]
Path = "doors_bs_reardoorleft.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Left_Service"

View File

@@ -0,0 +1,10 @@
[Configuration]
Version = 100
[[Component]]
Path = "doors_vd_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Device"
[[Component]]
Path = "doors_bs_reardoorright.sdv"
Class = "Vehicle.Chassis.Door.Axle02.Right_Service"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "simulation_task_timer.sdv"
Class = "SimulationTaskTimerService"

View File

@@ -0,0 +1,6 @@
[Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"

View File

@@ -0,0 +1,26 @@
/**
@file signal_identifier.h
@date 2025-09-06 14:55:42
This file is the signal identifier header.
This file was generated by the DBC utility from:
datalink_4doors_example.dbc
DBC file version: 1.0.0.1
*/
#ifndef __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_145542_578__
#define __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_145542_578__
namespace Doors4ExampleFMU
{
// Data Dispatch Service signal names to dbc variable names C-type RX/TX vss name space
static std::string dsDoor01LeftIsOpen = "CAN_Input_L1.Door01LeftIsOpen";
static std::string dsDoor01RightIsOpen = "CAN_Input_R1.Door01RightIsOpen";
static std::string dsDoor02LeftIsOpen = "CAN_Input_L2.Door02LeftIsOpen";
static std::string dsDoor02RightIsOpen = "CAN_Input_R2.Door02RightIsOpen";
static std::string dsLockDoor02Right = "CAN_Output.LockDoor02Right";
static std::string dsLockDoor02Left = "CAN_Output.LockDoor02Left";
static std::string dsLockDoor01Right = "CAN_Output.LockDoor01Right";
static std::string dsLockDoor01Left = "CAN_Output.LockDoor01Left";
} // Doors4ExampleFMU
#endif // __DBC_GENERATED__SIGNALIDENTIFIER_H__20250906_145542_578__

View File

@@ -0,0 +1,7 @@
#pragma once
#include "model.h"
#define EPSILON (FIXED_SOLVER_STEP * 1e-6)
void doFixedStep(ModelInstance *comp, bool* stateEvent, bool* timeEvent);

View File

@@ -0,0 +1,272 @@
#ifndef fmi2FunctionTypes_h
#define fmi2FunctionTypes_h
#include "fmi2TypesPlatform.h"
/* This header file must be utilized when compiling an FMU or an FMI master.
It declares data and function types for FMI 2.0.1
Revisions:
- Sep. 30, 2019: License changed to 2-clause BSD License (without extensions)
- Jul. 5, 2019: Remove const modifier from fields of fmi2CallbackFunctions (#216)
- Sep. 6, 2018: Parameter names added to function prototypes
- Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Apr. 3, 2014: Added #include <stddef.h> for size_t definition
- Mar. 27, 2014: Added #include "fmiTypesPlatform.h" (#179)
- Mar. 26, 2014: Introduced function argument "void" for the functions (#171)
fmiGetTypesPlatformTYPE and fmiGetVersionTYPE
- Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged:
fmiInstantiateModelTYPE , fmiInstantiateSlaveTYPE -> fmiInstantiateTYPE
fmiFreeModelInstanceTYPE, fmiFreeSlaveInstanceTYPE -> fmiFreeInstanceTYPE
fmiEnterModelInitializationModeTYPE, fmiEnterSlaveInitializationModeTYPE -> fmiEnterInitializationModeTYPE
fmiExitModelInitializationModeTYPE , fmiExitSlaveInitializationModeTYPE -> fmiExitInitializationModeTYPE
fmiTerminateModelTYPE , fmiTerminateSlaveTYPE -> fmiTerminate
fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation)
Functions renamed
fmiUpdateDiscreteStatesTYPE -> fmiNewDiscreteStatesTYPE
Renamed elements of the enumeration fmiEventInfo
upcomingTimeEvent -> nextEventTimeDefined // due to generic naming scheme: varDefined + var
newUpdateDiscreteStatesNeeded -> newDiscreteStatesNeeded;
- June 13, 2013: Changed type fmiEventInfo
Functions removed:
fmiInitializeModelTYPE
fmiEventUpdateTYPE
fmiCompletedEventIterationTYPE
fmiInitializeSlaveTYPE
Functions added:
fmiEnterModelInitializationModeTYPE
fmiExitModelInitializationModeTYPE
fmiEnterEventModeTYPE
fmiUpdateDiscreteStatesTYPE
fmiEnterContinuousTimeModeTYPE
fmiEnterSlaveInitializationModeTYPE;
fmiExitSlaveInitializationModeTYPE;
- Feb. 17, 2013: Added third argument to fmiCompletedIntegratorStepTYPE
Changed function name "fmiTerminateType" to "fmiTerminateModelType" (due to #113)
Changed function name "fmiGetNominalContinuousStateTYPE" to
"fmiGetNominalsOfContinuousStatesTYPE"
Removed fmiGetStateValueReferencesTYPE.
- Nov. 14, 2011: First public Version
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
#ifdef __cplusplus
extern "C" {
#endif
/* make sure all compiler use the same alignment policies for structures */
#if defined _MSC_VER || defined __GNUC__
#pragma pack(push,8)
#endif
/* Include stddef.h, in order that size_t etc. is defined */
#include <stddef.h>
/* Type definitions */
typedef enum {
fmi2OK,
fmi2Warning,
fmi2Discard,
fmi2Error,
fmi2Fatal,
fmi2Pending
} fmi2Status;
typedef enum {
fmi2ModelExchange,
fmi2CoSimulation
} fmi2Type;
typedef enum {
fmi2DoStepStatus,
fmi2PendingStatus,
fmi2LastSuccessfulTime,
fmi2Terminated
} fmi2StatusKind;
typedef void (*fmi2CallbackLogger) (fmi2ComponentEnvironment componentEnvironment,
fmi2String instanceName,
fmi2Status status,
fmi2String category,
fmi2String message,
...);
typedef void* (*fmi2CallbackAllocateMemory)(size_t nobj, size_t size);
typedef void (*fmi2CallbackFreeMemory) (void* obj);
typedef void (*fmi2StepFinished) (fmi2ComponentEnvironment componentEnvironment,
fmi2Status status);
typedef struct {
fmi2CallbackLogger logger;
fmi2CallbackAllocateMemory allocateMemory;
fmi2CallbackFreeMemory freeMemory;
fmi2StepFinished stepFinished;
fmi2ComponentEnvironment componentEnvironment;
} fmi2CallbackFunctions;
typedef struct {
fmi2Boolean newDiscreteStatesNeeded;
fmi2Boolean terminateSimulation;
fmi2Boolean nominalsOfContinuousStatesChanged;
fmi2Boolean valuesOfContinuousStatesChanged;
fmi2Boolean nextEventTimeDefined;
fmi2Real nextEventTime;
} fmi2EventInfo;
/* reset alignment policy to the one set before reading this file */
#if defined _MSC_VER || defined __GNUC__
#pragma pack(pop)
#endif
/* Define fmi2 function pointer types to simplify dynamic loading */
/***************************************************
Types for Common Functions
****************************************************/
/* Inquire version numbers of header files and setting logging status */
typedef const char* fmi2GetTypesPlatformTYPE(void);
typedef const char* fmi2GetVersionTYPE(void);
typedef fmi2Status fmi2SetDebugLoggingTYPE(fmi2Component c,
fmi2Boolean loggingOn,
size_t nCategories,
const fmi2String categories[]);
/* Creation and destruction of FMU instances and setting debug status */
typedef fmi2Component fmi2InstantiateTYPE(fmi2String instanceName,
fmi2Type fmuType,
fmi2String fmuGUID,
fmi2String fmuResourceLocation,
const fmi2CallbackFunctions* functions,
fmi2Boolean visible,
fmi2Boolean loggingOn);
typedef void fmi2FreeInstanceTYPE(fmi2Component c);
/* Enter and exit initialization mode, terminate and reset */
typedef fmi2Status fmi2SetupExperimentTYPE (fmi2Component c,
fmi2Boolean toleranceDefined,
fmi2Real tolerance,
fmi2Real startTime,
fmi2Boolean stopTimeDefined,
fmi2Real stopTime);
typedef fmi2Status fmi2EnterInitializationModeTYPE(fmi2Component c);
typedef fmi2Status fmi2ExitInitializationModeTYPE (fmi2Component c);
typedef fmi2Status fmi2TerminateTYPE (fmi2Component c);
typedef fmi2Status fmi2ResetTYPE (fmi2Component c);
/* Getting and setting variable values */
typedef fmi2Status fmi2GetRealTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]);
typedef fmi2Status fmi2GetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]);
typedef fmi2Status fmi2GetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]);
typedef fmi2Status fmi2GetStringTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]);
typedef fmi2Status fmi2SetRealTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]);
typedef fmi2Status fmi2SetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]);
typedef fmi2Status fmi2SetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]);
typedef fmi2Status fmi2SetStringTYPE (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]);
/* Getting and setting the internal FMU state */
typedef fmi2Status fmi2GetFMUstateTYPE (fmi2Component c, fmi2FMUstate* FMUstate);
typedef fmi2Status fmi2SetFMUstateTYPE (fmi2Component c, fmi2FMUstate FMUstate);
typedef fmi2Status fmi2FreeFMUstateTYPE (fmi2Component c, fmi2FMUstate* FMUstate);
typedef fmi2Status fmi2SerializedFMUstateSizeTYPE(fmi2Component c, fmi2FMUstate FMUstate, size_t* size);
typedef fmi2Status fmi2SerializeFMUstateTYPE (fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte[], size_t size);
typedef fmi2Status fmi2DeSerializeFMUstateTYPE (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate);
/* Getting partial derivatives */
typedef fmi2Status fmi2GetDirectionalDerivativeTYPE(fmi2Component c,
const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
const fmi2ValueReference vKnown_ref[], size_t nKnown,
const fmi2Real dvKnown[],
fmi2Real dvUnknown[]);
/***************************************************
Types for Functions for FMI2 for Model Exchange
****************************************************/
/* Enter and exit the different modes */
typedef fmi2Status fmi2EnterEventModeTYPE (fmi2Component c);
typedef fmi2Status fmi2NewDiscreteStatesTYPE (fmi2Component c, fmi2EventInfo* fmi2eventInfo);
typedef fmi2Status fmi2EnterContinuousTimeModeTYPE(fmi2Component c);
typedef fmi2Status fmi2CompletedIntegratorStepTYPE(fmi2Component c,
fmi2Boolean noSetFMUStatePriorToCurrentPoint,
fmi2Boolean* enterEventMode,
fmi2Boolean* terminateSimulation);
/* Providing independent variables and re-initialization of caching */
typedef fmi2Status fmi2SetTimeTYPE (fmi2Component c, fmi2Real time);
typedef fmi2Status fmi2SetContinuousStatesTYPE(fmi2Component c, const fmi2Real x[], size_t nx);
/* Evaluation of the model equations */
typedef fmi2Status fmi2GetDerivativesTYPE (fmi2Component c, fmi2Real derivatives[], size_t nx);
typedef fmi2Status fmi2GetEventIndicatorsTYPE (fmi2Component c, fmi2Real eventIndicators[], size_t ni);
typedef fmi2Status fmi2GetContinuousStatesTYPE (fmi2Component c, fmi2Real x[], size_t nx);
typedef fmi2Status fmi2GetNominalsOfContinuousStatesTYPE(fmi2Component c, fmi2Real x_nominal[], size_t nx);
/***************************************************
Types for Functions for FMI2 for Co-Simulation
****************************************************/
/* Simulating the slave */
typedef fmi2Status fmi2SetRealInputDerivativesTYPE (fmi2Component c,
const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[],
const fmi2Real value[]);
typedef fmi2Status fmi2GetRealOutputDerivativesTYPE(fmi2Component c,
const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[],
fmi2Real value[]);
typedef fmi2Status fmi2DoStepTYPE (fmi2Component c,
fmi2Real currentCommunicationPoint,
fmi2Real communicationStepSize,
fmi2Boolean noSetFMUStatePriorToCurrentPoint);
typedef fmi2Status fmi2CancelStepTYPE(fmi2Component c);
/* Inquire slave status */
typedef fmi2Status fmi2GetStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2Status* value);
typedef fmi2Status fmi2GetRealStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2Real* value);
typedef fmi2Status fmi2GetIntegerStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value);
typedef fmi2Status fmi2GetBooleanStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value);
typedef fmi2Status fmi2GetStringStatusTYPE (fmi2Component c, const fmi2StatusKind s, fmi2String* value);
#ifdef __cplusplus
} /* end of extern "C" { */
#endif
#endif /* fmi2FunctionTypes_h */

View File

@@ -0,0 +1,328 @@
#ifndef fmi2Functions_h
#define fmi2Functions_h
/* This header file must be utilized when compiling a FMU.
It defines all functions of the
FMI 2.0.1 Model Exchange and Co-Simulation Interface.
In order to have unique function names even if several FMUs
are compiled together (e.g. for embedded systems), every "real" function name
is constructed by prepending the function name by "FMI2_FUNCTION_PREFIX".
Therefore, the typical usage is:
#define FMI2_FUNCTION_PREFIX MyModel_
#include "fmi2Functions.h"
As a result, a function that is defined as "fmi2GetDerivatives" in this header file,
is actually getting the name "MyModel_fmi2GetDerivatives".
This only holds if the FMU is shipped in C source code, or is compiled in a
static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function
names are used and "FMI2_FUNCTION_PREFIX" must not be defined.
Revisions:
- Sep. 29, 2019: License changed to 2-clause BSD License (without extensions)
- Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Mar. 26, 2014: FMI_Export set to empty value if FMI_Export and FMI_FUNCTION_PREFIX
are not defined (#173)
- Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged:
fmiInstantiateModel , fmiInstantiateSlave -> fmiInstantiate
fmiFreeModelInstance, fmiFreeSlaveInstance -> fmiFreeInstance
fmiEnterModelInitializationMode, fmiEnterSlaveInitializationMode -> fmiEnterInitializationMode
fmiExitModelInitializationMode , fmiExitSlaveInitializationMode -> fmiExitInitializationMode
fmiTerminateModel, fmiTerminateSlave -> fmiTerminate
fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation)
Functions renamed:
fmiUpdateDiscreteStates -> fmiNewDiscreteStates
- June 13, 2013: Functions removed:
fmiInitializeModel
fmiEventUpdate
fmiCompletedEventIteration
fmiInitializeSlave
Functions added:
fmiEnterModelInitializationMode
fmiExitModelInitializationMode
fmiEnterEventMode
fmiUpdateDiscreteStates
fmiEnterContinuousTimeMode
fmiEnterSlaveInitializationMode;
fmiExitSlaveInitializationMode;
- Feb. 17, 2013: Portability improvements:
o DllExport changed to FMI_Export
o FUNCTION_PREFIX changed to FMI_FUNCTION_PREFIX
o Allow undefined FMI_FUNCTION_PREFIX (meaning no prefix is used)
Changed function name "fmiTerminate" to "fmiTerminateModel" (due to #113)
Changed function name "fmiGetNominalContinuousState" to
"fmiGetNominalsOfContinuousStates"
Removed fmiGetStateValueReferences.
- Nov. 14, 2011: Adapted to FMI 2.0:
o Split into two files (fmiFunctions.h, fmiTypes.h) in order
that code that dynamically loads an FMU can directly
utilize the header files).
o Added C++ encapsulation of C-part, in order that the header
file can be directly utilized in C++ code.
o fmiCallbackFunctions is passed as pointer to fmiInstantiateXXX
o stepFinished within fmiCallbackFunctions has as first
argument "fmiComponentEnvironment" and not "fmiComponent".
o New functions to get and set the complete FMU state
and to compute partial derivatives.
- Nov. 4, 2010: Adapted to specification text:
o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform
o fmiInstantiateSlave: Argument GUID replaced by fmuGUID
Argument mimetype replaced by mimeType
o tabs replaced by spaces
- Oct. 16, 2010: Functions for FMI for Co-simulation added
- Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27)
(by M. Otter, DLR)
Added WIN32 pragma to define the struct layout (ticket #34)
(by J. Mauss, QTronic)
- Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize
Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion
Renamed macro fmiModelFunctionsVersion to fmiVersion
Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel
(by J. Mauss, QTronic)
- Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR).
- Dez. 14, 2009: Added eventInfo to meInitialize and added
meGetNominalContinuousStates (by Martin Otter, DLR)
- Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion)
(by A. Junghanns, QTronic)
- Sept. 9, 2009: Changes according to FMI-meeting on July 21:
meInquireModelTypesVersion -> meGetModelTypesPlatform
meInquireModelFunctionsVersion -> meGetModelFunctionsVersion
meSetStates -> meSetContinuousStates
meGetStates -> meGetContinuousStates
removal of meInitializeModelClass
removal of meGetTime
change of arguments of meInstantiateModel
change of arguments of meCompletedIntegratorStep
(by Martin Otter, DLR):
- July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR).
- March 2, 2009: Changed function definitions according to the last design
meeting with additional improvements (by Martin Otter, DLR).
- Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim).
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "fmi2TypesPlatform.h"
#include "fmi2FunctionTypes.h"
#include <stdlib.h>
/*
Export FMI2 API functions on Windows and under GCC.
If custom linking is desired then the FMI2_Export must be
defined before including this file. For instance,
it may be set to __declspec(dllimport).
*/
#if !defined(FMI2_Export)
#if !defined(FMI2_FUNCTION_PREFIX)
#if defined _WIN32 || defined __CYGWIN__
/* Note: both gcc & MSVC on Windows support this syntax. */
#define FMI2_Export __declspec(dllexport)
#else
#if __GNUC__ >= 4
#define FMI2_Export __attribute__ ((visibility ("default")))
#else
#define FMI2_Export
#endif
#endif
#else
#define FMI2_Export
#endif
#endif
/* Macros to construct the real function name
(prepend function name by FMI2_FUNCTION_PREFIX) */
#if defined(FMI2_FUNCTION_PREFIX)
#define fmi2Paste(a,b) a ## b
#define fmi2PasteB(a,b) fmi2Paste(a,b)
#define fmi2FullName(name) fmi2PasteB(FMI2_FUNCTION_PREFIX, name)
#else
#define fmi2FullName(name) name
#endif
/***************************************************
Common Functions
****************************************************/
#define fmi2GetTypesPlatform fmi2FullName(fmi2GetTypesPlatform)
#define fmi2GetVersion fmi2FullName(fmi2GetVersion)
#define fmi2SetDebugLogging fmi2FullName(fmi2SetDebugLogging)
#define fmi2Instantiate fmi2FullName(fmi2Instantiate)
#define fmi2FreeInstance fmi2FullName(fmi2FreeInstance)
#define fmi2SetupExperiment fmi2FullName(fmi2SetupExperiment)
#define fmi2EnterInitializationMode fmi2FullName(fmi2EnterInitializationMode)
#define fmi2ExitInitializationMode fmi2FullName(fmi2ExitInitializationMode)
#define fmi2Terminate fmi2FullName(fmi2Terminate)
#define fmi2Reset fmi2FullName(fmi2Reset)
#define fmi2GetReal fmi2FullName(fmi2GetReal)
#define fmi2GetInteger fmi2FullName(fmi2GetInteger)
#define fmi2GetBoolean fmi2FullName(fmi2GetBoolean)
#define fmi2GetString fmi2FullName(fmi2GetString)
#define fmi2SetReal fmi2FullName(fmi2SetReal)
#define fmi2SetInteger fmi2FullName(fmi2SetInteger)
#define fmi2SetBoolean fmi2FullName(fmi2SetBoolean)
#define fmi2SetString fmi2FullName(fmi2SetString)
#define fmi2GetFMUstate fmi2FullName(fmi2GetFMUstate)
#define fmi2SetFMUstate fmi2FullName(fmi2SetFMUstate)
#define fmi2FreeFMUstate fmi2FullName(fmi2FreeFMUstate)
#define fmi2SerializedFMUstateSize fmi2FullName(fmi2SerializedFMUstateSize)
#define fmi2SerializeFMUstate fmi2FullName(fmi2SerializeFMUstate)
#define fmi2DeSerializeFMUstate fmi2FullName(fmi2DeSerializeFMUstate)
#define fmi2GetDirectionalDerivative fmi2FullName(fmi2GetDirectionalDerivative)
/***************************************************
Functions for FMI2 for Model Exchange
****************************************************/
#define fmi2EnterEventMode fmi2FullName(fmi2EnterEventMode)
#define fmi2NewDiscreteStates fmi2FullName(fmi2NewDiscreteStates)
#define fmi2EnterContinuousTimeMode fmi2FullName(fmi2EnterContinuousTimeMode)
#define fmi2CompletedIntegratorStep fmi2FullName(fmi2CompletedIntegratorStep)
#define fmi2SetTime fmi2FullName(fmi2SetTime)
#define fmi2SetContinuousStates fmi2FullName(fmi2SetContinuousStates)
#define fmi2GetDerivatives fmi2FullName(fmi2GetDerivatives)
#define fmi2GetEventIndicators fmi2FullName(fmi2GetEventIndicators)
#define fmi2GetContinuousStates fmi2FullName(fmi2GetContinuousStates)
#define fmi2GetNominalsOfContinuousStates fmi2FullName(fmi2GetNominalsOfContinuousStates)
/***************************************************
Functions for FMI2 for Co-Simulation
****************************************************/
#define fmi2SetRealInputDerivatives fmi2FullName(fmi2SetRealInputDerivatives)
#define fmi2GetRealOutputDerivatives fmi2FullName(fmi2GetRealOutputDerivatives)
#define fmi2DoStep fmi2FullName(fmi2DoStep)
#define fmi2CancelStep fmi2FullName(fmi2CancelStep)
#define fmi2GetStatus fmi2FullName(fmi2GetStatus)
#define fmi2GetRealStatus fmi2FullName(fmi2GetRealStatus)
#define fmi2GetIntegerStatus fmi2FullName(fmi2GetIntegerStatus)
#define fmi2GetBooleanStatus fmi2FullName(fmi2GetBooleanStatus)
#define fmi2GetStringStatus fmi2FullName(fmi2GetStringStatus)
/* Version number */
#define fmi2Version "2.0"
/***************************************************
Common Functions
****************************************************/
/* Inquire version numbers of header files */
FMI2_Export fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform;
FMI2_Export fmi2GetVersionTYPE fmi2GetVersion;
FMI2_Export fmi2SetDebugLoggingTYPE fmi2SetDebugLogging;
/* Creation and destruction of FMU instances */
FMI2_Export fmi2InstantiateTYPE fmi2Instantiate;
FMI2_Export fmi2FreeInstanceTYPE fmi2FreeInstance;
/* Enter and exit initialization mode, terminate and reset */
FMI2_Export fmi2SetupExperimentTYPE fmi2SetupExperiment;
FMI2_Export fmi2EnterInitializationModeTYPE fmi2EnterInitializationMode;
FMI2_Export fmi2ExitInitializationModeTYPE fmi2ExitInitializationMode;
FMI2_Export fmi2TerminateTYPE fmi2Terminate;
FMI2_Export fmi2ResetTYPE fmi2Reset;
/* Getting and setting variables values */
FMI2_Export fmi2GetRealTYPE fmi2GetReal;
FMI2_Export fmi2GetIntegerTYPE fmi2GetInteger;
FMI2_Export fmi2GetBooleanTYPE fmi2GetBoolean;
FMI2_Export fmi2GetStringTYPE fmi2GetString;
FMI2_Export fmi2SetRealTYPE fmi2SetReal;
FMI2_Export fmi2SetIntegerTYPE fmi2SetInteger;
FMI2_Export fmi2SetBooleanTYPE fmi2SetBoolean;
FMI2_Export fmi2SetStringTYPE fmi2SetString;
/* Getting and setting the internal FMU state */
FMI2_Export fmi2GetFMUstateTYPE fmi2GetFMUstate;
FMI2_Export fmi2SetFMUstateTYPE fmi2SetFMUstate;
FMI2_Export fmi2FreeFMUstateTYPE fmi2FreeFMUstate;
FMI2_Export fmi2SerializedFMUstateSizeTYPE fmi2SerializedFMUstateSize;
FMI2_Export fmi2SerializeFMUstateTYPE fmi2SerializeFMUstate;
FMI2_Export fmi2DeSerializeFMUstateTYPE fmi2DeSerializeFMUstate;
/* Getting partial derivatives */
FMI2_Export fmi2GetDirectionalDerivativeTYPE fmi2GetDirectionalDerivative;
/***************************************************
Functions for FMI2 for Model Exchange
****************************************************/
/* Enter and exit the different modes */
FMI2_Export fmi2EnterEventModeTYPE fmi2EnterEventMode;
FMI2_Export fmi2NewDiscreteStatesTYPE fmi2NewDiscreteStates;
FMI2_Export fmi2EnterContinuousTimeModeTYPE fmi2EnterContinuousTimeMode;
FMI2_Export fmi2CompletedIntegratorStepTYPE fmi2CompletedIntegratorStep;
/* Providing independent variables and re-initialization of caching */
FMI2_Export fmi2SetTimeTYPE fmi2SetTime;
FMI2_Export fmi2SetContinuousStatesTYPE fmi2SetContinuousStates;
/* Evaluation of the model equations */
FMI2_Export fmi2GetDerivativesTYPE fmi2GetDerivatives;
FMI2_Export fmi2GetEventIndicatorsTYPE fmi2GetEventIndicators;
FMI2_Export fmi2GetContinuousStatesTYPE fmi2GetContinuousStates;
FMI2_Export fmi2GetNominalsOfContinuousStatesTYPE fmi2GetNominalsOfContinuousStates;
/***************************************************
Functions for FMI2 for Co-Simulation
****************************************************/
/* Simulating the slave */
FMI2_Export fmi2SetRealInputDerivativesTYPE fmi2SetRealInputDerivatives;
FMI2_Export fmi2GetRealOutputDerivativesTYPE fmi2GetRealOutputDerivatives;
FMI2_Export fmi2DoStepTYPE fmi2DoStep;
FMI2_Export fmi2CancelStepTYPE fmi2CancelStep;
/* Inquire slave status */
FMI2_Export fmi2GetStatusTYPE fmi2GetStatus;
FMI2_Export fmi2GetRealStatusTYPE fmi2GetRealStatus;
FMI2_Export fmi2GetIntegerStatusTYPE fmi2GetIntegerStatus;
FMI2_Export fmi2GetBooleanStatusTYPE fmi2GetBooleanStatus;
FMI2_Export fmi2GetStringStatusTYPE fmi2GetStringStatus;
#ifdef __cplusplus
} /* end of extern "C" { */
#endif
#endif /* fmi2Functions_h */

View File

@@ -0,0 +1,109 @@
#ifndef fmi2TypesPlatform_h
#define fmi2TypesPlatform_h
/* Standard header file to define the argument types of the
functions of the Functional Mock-up Interface 2.0.1
This header file must be utilized both by the model and
by the simulation engine.
Revisions:
- Sep. 29, 2019: License changed to 2-clause BSD License (without extensions)
- Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8)
- Mar 31, 2014: New datatype fmiChar introduced.
- Feb. 17, 2013: Changed fmiTypesPlatform from "standard32" to "default".
Removed fmiUndefinedValueReference since no longer needed
(because every state is defined in ScalarVariables).
- March 20, 2012: Renamed from fmiPlatformTypes.h to fmiTypesPlatform.h
- Nov. 14, 2011: Use the header file "fmiPlatformTypes.h" for FMI 2.0
both for "FMI for model exchange" and for "FMI for co-simulation"
New types "fmiComponentEnvironment", "fmiState", and "fmiByte".
The implementation of "fmiBoolean" is change from "char" to "int".
The #define "fmiPlatform" changed to "fmiTypesPlatform"
(in order that #define and function call are consistent)
- Oct. 4, 2010: Renamed header file from "fmiModelTypes.h" to fmiPlatformTypes.h"
for the co-simulation interface
- Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic)
- Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent"
according to meeting on Dec. 18 (by Martin Otter, DLR)
- Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR)
- Sept. 9, 2009: Changes according to FMI-meeting on July 21:
Changed "version" to "platform", "standard" to "standard32",
Added a precise definition of "standard32" as comment
(by Martin Otter, DLR)
- July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse,
and changed meValueReferenced from int to unsigned int
(by Martin Otter, DLR).
- March 2, 2009: Moved enums and function pointer definitions to
ModelFunctions.h (by Martin Otter, DLR).
- Dec. 3, 2008 : First version by Martin Otter (DLR) and
Hans Olsson (Dynasim).
Copyright (C) 2008-2011 MODELISAR consortium,
2012-2019 Modelica Association Project "FMI"
All rights reserved.
This file is licensed by the copyright holders under the 2-Clause BSD License
(https://opensource.org/licenses/BSD-2-Clause):
----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/
/* Platform (unique identification of this header file) */
#define fmi2TypesPlatform "default"
/* Type definitions of variables passed as arguments
Version "default" means:
fmi2Component : an opaque object pointer
fmi2ComponentEnvironment: an opaque object pointer
fmi2FMUstate : an opaque object pointer
fmi2ValueReference : handle to the value of a variable
fmi2Real : double precision floating-point data type
fmi2Integer : basic signed integer data type
fmi2Boolean : basic signed integer data type
fmi2Char : character data type
fmi2String : a pointer to a vector of fmi2Char characters
('\0' terminated, UTF8 encoded)
fmi2Byte : smallest addressable unit of the machine, typically one byte.
*/
typedef void* fmi2Component; /* Pointer to FMU instance */
typedef void* fmi2ComponentEnvironment; /* Pointer to FMU environment */
typedef void* fmi2FMUstate; /* Pointer to internal FMU state */
typedef unsigned int fmi2ValueReference;
typedef double fmi2Real ;
typedef int fmi2Integer;
typedef int fmi2Boolean;
typedef char fmi2Char;
typedef const fmi2Char* fmi2String;
typedef char fmi2Byte;
/* Values for fmi2Boolean */
#define fmi2True 1
#define fmi2False 0
#endif /* fmi2TypesPlatform_h */

View File

@@ -0,0 +1,254 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#if FMI_VERSION != 1 && FMI_VERSION != 2 && FMI_VERSION != 3
#error FMI_VERSION must be one of 1, 2 or 3
#endif
#define UNUSED(x) (void)(x)
#include <stddef.h> // for size_t
#include <stdbool.h> // for bool
#include <stdint.h>
#include "config.h"
#if FMI_VERSION == 1
#define not_modelError (Instantiated| Initialized | Terminated)
typedef enum {
Instantiated = 1 << 0,
Initialized = 1 << 1,
Terminated = 1 << 2,
modelError = 1 << 3
} ModelState;
#elif FMI_VERSION == 2
typedef enum {
StartAndEnd = 1 << 0,
Instantiated = 1 << 1,
InitializationMode = 1 << 2,
// ME states
EventMode = 1 << 3,
ContinuousTimeMode = 1 << 4,
// CS states
StepComplete = 1 << 5,
StepInProgress = 1 << 6,
StepFailed = 1 << 7,
StepCanceled = 1 << 8,
Terminated = 1 << 9,
modelError = 1 << 10,
modelFatal = 1 << 11,
} ModelState;
#else
typedef enum {
StartAndEnd = 1 << 0,
ConfigurationMode = 1 << 1,
Instantiated = 1 << 2,
InitializationMode = 1 << 3,
EventMode = 1 << 4,
ContinuousTimeMode = 1 << 5,
StepMode = 1 << 6,
ClockActivationMode = 1 << 7,
StepDiscarded = 1 << 8,
ReconfigurationMode = 1 << 9,
IntermediateUpdateMode = 1 << 10,
Terminated = 1 << 11,
modelError = 1 << 12,
modelFatal = 1 << 13,
} ModelState;
#endif
typedef enum {
ModelExchange,
CoSimulation,
ScheduledExecution,
} InterfaceType;
typedef enum {
OK,
Warning,
Discard,
Error,
Fatal,
Pending
} Status;
#if FMI_VERSION < 3
typedef void (*loggerType) (void* componentEnvironment, const char* instanceName, int status, const char* category, const char* message, ...);
#else
typedef void (*loggerType) (void* componentEnvironment, int status, const char* category, const char* message);
#endif
typedef void (*lockPreemptionType) (void);
typedef void (*unlockPreemptionType) (void);
typedef void (*intermediateUpdateType) (void* instanceEnvironment,
double intermediateUpdateTime,
bool intermediateVariableSetRequested,
bool intermediateVariableGetAllowed,
bool intermediateStepFinished,
bool canReturnEarly,
bool* earlyReturnRequested,
double* earlyReturnTime);
typedef void(*clockUpdateType) (void* instanceEnvironment);
typedef struct {
double startTime;
double stopTime;
double time;
const char* instanceName;
InterfaceType type;
const char* resourceLocation;
Status status;
// callback functions
loggerType logger;
intermediateUpdateType intermediateUpdate;
clockUpdateType clockUpdate;
lockPreemptionType lockPreemtion;
unlockPreemptionType unlockPreemtion;
bool logEvents;
bool logErrors;
void* componentEnvironment;
ModelState state;
// event info
bool newDiscreteStatesNeeded;
bool terminateSimulation;
bool nominalsOfContinuousStatesChanged;
bool valuesOfContinuousStatesChanged;
bool nextEventTimeDefined;
double nextEventTime;
bool clocksTicked;
bool isDirtyValues;
ModelData modelData;
#if NZ > 0
// event indicators
double z[NZ];
#endif
// internal solver steps
uint64_t nSteps;
// Co-Simulation
bool earlyReturnAllowed;
bool eventModeUsed;
} ModelInstance;
ModelInstance* createModelInstance(
loggerType logger,
intermediateUpdateType intermediateUpdate,
void* componentEnvironment,
const char* instanceName,
const char* instantiationToken,
const char* resourceLocation,
bool loggingOn,
InterfaceType interfaceType);
void freeModelInstance(ModelInstance* comp);
void reset(ModelInstance* comp);
bool setStartValues(ModelInstance* comp);
Status calculateValues(ModelInstance* comp);
Status getFloat32(ModelInstance* comp, ValueReference vr, float values[], size_t nValues, size_t* index);
Status getFloat64(ModelInstance* comp, ValueReference vr, double values[], size_t nValues, size_t* index);
Status getInt8(ModelInstance* comp, ValueReference vr, int8_t values[], size_t nValues, size_t* index);
Status getUInt8(ModelInstance* comp, ValueReference vr, uint8_t values[], size_t nValues, size_t* index);
Status getInt16(ModelInstance* comp, ValueReference vr, int16_t values[], size_t nValues, size_t* index);
Status getUInt16(ModelInstance* comp, ValueReference vr, uint16_t values[], size_t nValues, size_t* index);
Status getInt32(ModelInstance* comp, ValueReference vr, int32_t values[], size_t nValues, size_t* index);
Status getUInt32(ModelInstance* comp, ValueReference vr, uint32_t values[], size_t nValues, size_t* index);
Status getInt64(ModelInstance* comp, ValueReference vr, int64_t values[], size_t nValues, size_t* index);
Status getUInt64(ModelInstance* comp, ValueReference vr, uint64_t values[], size_t nValues, size_t* index);
Status getBoolean(ModelInstance* comp, ValueReference vr, bool values[], size_t nValues, size_t* index);
Status getString(ModelInstance* comp, ValueReference vr, const char* values[], size_t nValues, size_t* index);
Status getBinary(ModelInstance* comp, ValueReference vr, size_t sizes[], const char* values[], size_t nValues, size_t* index);
Status setFloat32(ModelInstance* comp, ValueReference vr, const float values[], size_t nValues, size_t* index);
Status setFloat64(ModelInstance* comp, ValueReference vr, const double values[], size_t nValues, size_t* index);
Status setInt8(ModelInstance* comp, ValueReference vr, const int8_t values[], size_t nValues, size_t* index);
Status setUInt8(ModelInstance* comp, ValueReference vr, const uint8_t values[], size_t nValues, size_t* index);
Status setInt16(ModelInstance* comp, ValueReference vr, const int16_t values[], size_t nValues, size_t* index);
Status setUInt16(ModelInstance* comp, ValueReference vr, const uint16_t values[], size_t nValues, size_t* index);
Status setInt32(ModelInstance* comp, ValueReference vr, const int32_t values[], size_t nValues, size_t* index);
Status setUInt32(ModelInstance* comp, ValueReference vr, const uint32_t values[], size_t nValues, size_t* index);
Status setInt64(ModelInstance* comp, ValueReference vr, const int64_t values[], size_t nValues, size_t* index);
Status setUInt64(ModelInstance* comp, ValueReference vr, const uint64_t values[], size_t nValues, size_t* index);
Status setBoolean(ModelInstance* comp, ValueReference vr, const bool values[], size_t nValues, size_t* index);
Status setString(ModelInstance* comp, ValueReference vr, const char* const values[], size_t nValues, size_t* index);
Status setBinary(ModelInstance* comp, ValueReference vr, const size_t sizes[], const char* const values[], size_t nValues, size_t* index);
Status activateClock(ModelInstance* comp, ValueReference vr);
Status getClock(ModelInstance* comp, ValueReference vr, bool* value);
Status setClock(ModelInstance* comp, ValueReference vr, const bool* value);
Status getInterval(ModelInstance* comp, ValueReference vr, double* interval, int* qualifier);
Status activateModelPartition(ModelInstance* comp, ValueReference vr, double activationTime);
void getContinuousStates(ModelInstance* comp, double x[], size_t nx);
void setContinuousStates(ModelInstance* comp, const double x[], size_t nx);
void getDerivatives(ModelInstance* comp, double dx[], size_t nx);
Status getOutputDerivative(ModelInstance* comp, ValueReference valueReference, int order, double* value);
Status getPartialDerivative(ModelInstance* comp, ValueReference unknown, ValueReference known, double* partialDerivative);
void getEventIndicators(ModelInstance* comp, double z[], size_t nz);
void eventUpdate(ModelInstance* comp);
//void updateEventTime(ModelInstance *comp);
bool invalidNumber(ModelInstance* comp, const char* f, const char* arg, size_t actual, size_t expected);
bool invalidState(ModelInstance* comp, const char* f, int statesExpected);
bool nullPointer(ModelInstance* comp, const char* f, const char* arg, const void* p);
void logError(ModelInstance* comp, const char* message, ...);
Status setDebugLogging(ModelInstance* comp, bool loggingOn, size_t nCategories, const char* const categories[]);
void logEvent(ModelInstance* comp, const char* message, ...);
void logError(ModelInstance* comp, const char* message, ...);
void* getFMUState(ModelInstance* comp);
void setFMUState(ModelInstance* comp, void* FMUState);
// shorthand to access the variables
#define M(v) (comp->modelData.v)
// "stringification" macros
#define xstr(s) str(s)
#define str(s) #s
// assert size of nValues for scalar variables
#define ASSERT_NVALUES(N) do { \
if (*index + (N) > nValues) { \
logError(comp, "Expected nValues > %zu but was %zu.", *index, nValues); \
return Error; \
} \
} while (0)
#ifdef __cplusplus
} // end of extern "C"
#endif

View File

@@ -0,0 +1,598 @@
#include <stdlib.h> // for calloc(), free()
#include <float.h> // for DBL_EPSILON
#include <math.h> // for fabs()
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "config.h"
#include "cosimulation.h"
#if FMI_VERSION == 3
#include "fmi3Functions.h"
#endif
#ifdef _MSC_VER
#define strdup _strdup
#endif
ModelInstance *createModelInstance(
loggerType cbLogger,
intermediateUpdateType intermediateUpdate,
void *componentEnvironment,
const char *instanceName,
const char *instantiationToken,
const char *resourceLocation,
bool loggingOn,
InterfaceType interfaceType) {
ModelInstance *comp = NULL;
if (!instanceName || strlen(instanceName) == 0) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, "?", Error, "error", "Missing instance name.");
#else
cbLogger(componentEnvironment, Error, "error", "Missing instance name.");
#endif
}
return NULL;
}
if (!instantiationToken || strlen(instantiationToken) == 0) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, instanceName, Error, "error", "Missing GUID.");
#else
cbLogger(componentEnvironment, Error, "error", "Missing instantiationToken.");
#endif
}
return NULL;
}
if (strcmp(instantiationToken, INSTANTIATION_TOKEN)) {
if (cbLogger) {
#if FMI_VERSION < 3
cbLogger(componentEnvironment, instanceName, Error, "error", "Wrong GUID.");
#else
cbLogger(componentEnvironment, Error, "error", "Wrong instantiationToken.");
#endif
}
return NULL;
}
comp = (ModelInstance *)calloc(1, sizeof(ModelInstance));
if (comp) {
comp->componentEnvironment = componentEnvironment;
comp->logger = cbLogger;
comp->intermediateUpdate = intermediateUpdate;
comp->lockPreemtion = NULL;
comp->unlockPreemtion = NULL;
comp->instanceName = strdup(instanceName);
comp->resourceLocation = resourceLocation ? strdup(resourceLocation) : NULL;
comp->status = OK;
comp->logEvents = loggingOn;
comp->logErrors = true; // always log errors
comp->nSteps = 0;
comp->earlyReturnAllowed = false;
comp->eventModeUsed = false;
}
if (!comp || !comp->instanceName) {
logError(comp, "Out of memory.");
return NULL;
}
comp->time = 0.0; // overwrite in fmi*SetupExperiment, fmi*SetTime
comp->type = interfaceType;
comp->state = Instantiated;
comp->newDiscreteStatesNeeded = false;
comp->terminateSimulation = false;
comp->nominalsOfContinuousStatesChanged = false;
comp->valuesOfContinuousStatesChanged = false;
comp->nextEventTimeDefined = false;
comp->nextEventTime = 0;
if (!setStartValues(comp))
{
cbLogger(componentEnvironment, instanceName, Error, "error", "VAPI initialization failed.");
}
comp->isDirtyValues = true;
return comp;
}
void freeModelInstance(ModelInstance *comp) {
free((void *)comp->instanceName);
free(comp);
}
void reset(ModelInstance* comp) {
comp->state = Instantiated;
comp->startTime = 0.0;
comp->time = 0.0;
comp->nSteps = 0;
comp->status = OK;
setStartValues(comp);
comp->isDirtyValues = true;
}
bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected) {
if (actual != expected) {
comp->state = modelError;
logError(comp, "%s: Invalid argument %s = %d. Expected %d.", f, arg, actual, expected);
return true;
}
return false;
}
bool invalidState(ModelInstance *comp, const char *f, int statesExpected) {
UNUSED(f);
UNUSED(statesExpected);
if (!comp) {
return true;
}
// TODO: add missing states and check state
return false;
// if (!(comp->state & statesExpected)) {
// comp->state = modelError;
// logError(comp, "%s: Illegal call sequence.", f);
// return true;
// }
//
// return false;
}
bool nullPointer(ModelInstance* comp, const char *f, const char *arg, const void *p) {
if (!p) {
comp->state = modelError;
logError(comp, "%s: Invalid argument %s = NULL.", f, arg);
return true;
}
return false;
}
Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char * const categories[]) {
if (nCategories > 0) {
if (categories == NULL) {
logError(comp, "Argument categories must not be NULL.");
return Error;
}
for (size_t i = 0; i < nCategories; i++) {
if (categories[i] == NULL) {
logError(comp, "Argument categories[%zu] must not be NULL.", i);
return Error;
} else if (strcmp(categories[i], "logEvents") == 0) {
comp->logEvents = loggingOn;
} else if (strcmp(categories[i], "logStatusError") == 0) {
comp->logErrors = loggingOn;
} else {
logError(comp, "Log categories[%zu] must be one of \"logEvents\" or \"logStatusError\" but was \"%s\".", i, categories[i]);
return Error;
}
}
} else {
comp->logEvents = loggingOn;
comp->logErrors = loggingOn;
}
return OK;
}
static void logMessage(ModelInstance *comp, int status, const char *category, const char *message, va_list args) {
if (!comp->logger) {
return;
}
va_list args1;
int len = 0;
char *buf = "";
va_copy(args1, args);
len = vsnprintf(buf, len, message, args1);
va_end(args1);
if (len < 0) {
return;
}
va_copy(args1, args);
buf = (char *)calloc(len + 1, sizeof(char));
len = vsnprintf(buf, len + 1, message, args);
va_end(args1);
if (len >= 0) {
// no need to distinguish between FMI versions since we're not using variadic arguments
#if FMI_VERSION < 3
comp->logger(comp->componentEnvironment, comp->instanceName, status, category, buf);
#else
comp->logger(comp->componentEnvironment, status, category, buf);
#endif
}
free(buf);
}
void logEvent(ModelInstance *comp, const char *message, ...) {
if (!comp || !comp->logEvents) return;
va_list args;
va_start(args, message);
logMessage(comp, OK, "logEvents", message, args);
va_end(args);
}
void logError(ModelInstance *comp, const char *message, ...) {
if (!comp || !comp->logErrors) return;
va_list args;
va_start(args, message);
logMessage(comp, Error, "logStatusError", message, args);
va_end(args);
}
// default implementations
#if NZ < 1
void getEventIndicators(ModelInstance *comp, double z[], size_t nz) {
UNUSED(comp);
UNUSED(z);
UNUSED(nz);
// do nothing
}
#endif
#define GET_NOT_ALLOWED(t) do { \
UNUSED(vr); \
UNUSED(values); \
UNUSED(nValues); \
UNUSED(index); \
logError(comp, "Getting " t " is not allowed.");\
return Error; \
} while (false)
#ifndef GET_FLOAT32
Status getFloat32(ModelInstance* comp, ValueReference vr, float values[], size_t nValues, size_t* index) {
GET_NOT_ALLOWED("Float32");
}
#endif
#ifndef GET_INT8
Status getInt8(ModelInstance* comp, ValueReference vr, int8_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int8");
}
#endif
#ifndef GET_UINT8
Status getUInt8(ModelInstance* comp, ValueReference vr, uint8_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt8");
}
#endif
#ifndef GET_INT16
Status getInt16(ModelInstance* comp, ValueReference vr, int16_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int16");
}
#endif
#ifndef GET_UINT16
Status getUInt16(ModelInstance* comp, ValueReference vr, uint16_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt16");
}
#endif
#ifndef GET_INT32
Status getInt32(ModelInstance* comp, ValueReference vr, int32_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int32");
}
#endif
#ifndef GET_UINT32
Status getUInt32(ModelInstance* comp, ValueReference vr, uint32_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt32");
}
#endif
#ifndef GET_INT64
Status getInt64(ModelInstance* comp, ValueReference vr, int64_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Int64");
}
#endif
#ifndef GET_UINT64
Status getUInt64(ModelInstance* comp, ValueReference vr, uint64_t values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("UInt64");
}
#endif
#ifndef GET_BOOLEAN
Status getBoolean(ModelInstance* comp, ValueReference vr, bool values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("Boolean");
}
#endif
#ifndef GET_STRING
Status getString(ModelInstance* comp, ValueReference vr, const char* values[], size_t nValues, size_t *index) {
GET_NOT_ALLOWED("String");
}
#endif
#ifndef GET_BINARY
Status getBinary(ModelInstance* comp, ValueReference vr, size_t sizes[], const char* values[], size_t nValues, size_t *index) {
UNUSED(sizes);
GET_NOT_ALLOWED("Binary");
}
#endif
#define SET_NOT_ALLOWED(t) do { \
UNUSED(vr); \
UNUSED(values); \
UNUSED(nValues); \
UNUSED(index); \
logError(comp, "Setting " t " is not allowed.");\
return Error; \
} while (false)
#ifndef SET_FLOAT32
Status setFloat32(ModelInstance* comp, ValueReference vr, const float values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Float32");
}
#endif
#ifndef SET_FLOAT64
Status setFloat64(ModelInstance* comp, ValueReference vr, const double values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Float64");
}
#endif
#ifndef SET_INT8
Status setInt8(ModelInstance* comp, ValueReference vr, const int8_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int8");
}
#endif
#ifndef SET_UINT8
Status setUInt8(ModelInstance* comp, ValueReference vr, const uint8_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt8");
}
#endif
#ifndef SET_INT16
Status setInt16(ModelInstance* comp, ValueReference vr, const int16_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int16");
}
#endif
#ifndef SET_UINT16
Status setUInt16(ModelInstance* comp, ValueReference vr, const uint16_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt16");
}
#endif
#ifndef SET_INT32
Status setInt32(ModelInstance* comp, ValueReference vr, const int32_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int32");
}
#endif
#ifndef SET_UINT32
Status setUInt32(ModelInstance* comp, ValueReference vr, const uint32_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt32");
}
#endif
#ifndef SET_INT64
Status setInt64(ModelInstance* comp, ValueReference vr, const int64_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Int64");
}
#endif
#ifndef SET_UINT64
Status setUInt64(ModelInstance* comp, ValueReference vr, const uint64_t values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("UInt64");
}
#endif
#ifndef SET_BOOLEAN
Status setBoolean(ModelInstance* comp, ValueReference vr, const bool values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("Boolean");
}
#endif
#ifndef SET_STRING
Status setString(ModelInstance* comp, ValueReference vr, const char *const values[], size_t nValues, size_t* index) {
SET_NOT_ALLOWED("String");
}
#endif
#ifndef SET_BINARY
Status setBinary(ModelInstance* comp, ValueReference vr, const size_t size[], const char *const values[], size_t nValues, size_t* index) {
UNUSED(size);
SET_NOT_ALLOWED("Binary");
}
#endif
#ifndef ACTIVATE_CLOCK
Status activateClock(ModelInstance* comp, ValueReference vr) {
UNUSED(comp);
UNUSED(vr);
return Error;
}
#endif
#ifndef GET_CLOCK
Status getClock(ModelInstance* comp, ValueReference vr, bool* value) {
UNUSED(comp);
UNUSED(vr);
UNUSED(value);
return Error;
}
#endif
#ifndef GET_INTERVAL
Status getInterval(ModelInstance* comp, ValueReference vr, double* interval, int* qualifier) {
UNUSED(comp);
UNUSED(vr);
UNUSED(interval);
UNUSED(qualifier);
return Error;
}
#endif
#ifndef ACTIVATE_MODEL_PARTITION
Status activateModelPartition(ModelInstance* comp, ValueReference vr, double activationTime) {
UNUSED(comp);
UNUSED(vr);
UNUSED(activationTime);
return Error;
}
#endif
#if NX < 1
void getContinuousStates(ModelInstance *comp, double x[], size_t nx) {
UNUSED(comp);
UNUSED(x);
UNUSED(nx);
}
void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) {
UNUSED(comp);
UNUSED(x);
UNUSED(nx);
}
void getDerivatives(ModelInstance *comp, double dx[], size_t nx) {
UNUSED(comp);
UNUSED(dx);
UNUSED(nx);
}
#endif
#ifndef GET_PARTIAL_DERIVATIVE
Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative) {
UNUSED(comp);
UNUSED(unknown);
UNUSED(known);
UNUSED(partialDerivative);
logError(comp, "Directional derivatives are not supported.");
return Error;
}
#endif
void* getFMUState(ModelInstance* comp) {
ModelInstance* fmuState = (ModelInstance*)calloc(1, sizeof(ModelInstance));
if (fmuState) {
memcpy(fmuState, comp, sizeof(ModelInstance));
}
return fmuState;
}
void setFMUState(ModelInstance* comp, void* FMUState) {
ModelInstance* s = (ModelInstance*)FMUState;
comp->startTime = s->startTime;
comp->stopTime = s->stopTime;
comp->time = s->time;
comp->status = s->status;
comp->state = s->state;
comp->newDiscreteStatesNeeded = s->newDiscreteStatesNeeded;
comp->terminateSimulation = s->terminateSimulation;
comp->nominalsOfContinuousStatesChanged = s->nominalsOfContinuousStatesChanged;
comp->valuesOfContinuousStatesChanged = s->valuesOfContinuousStatesChanged;
comp->nextEventTimeDefined = s->nextEventTimeDefined;
comp->nextEventTime = s->nextEventTime;
comp->clocksTicked = s->clocksTicked;
comp->isDirtyValues = s->isDirtyValues;
comp->modelData = s->modelData;
#if NZ > 0
memcpy(comp->z, s->z, NZ * sizeof(double));
#endif
comp->nSteps = s->nSteps;
}
void doFixedStep(ModelInstance *comp, bool* stateEvent, bool* timeEvent) {
#if NX > 0
double x[NX] = { 0 };
double dx[NX] = { 0 };
getContinuousStates(comp, x, NX);
getDerivatives(comp, dx, NX);
// forward Euler step
for (int i = 0; i < NX; i++) {
x[i] += FIXED_SOLVER_STEP * dx[i];
}
setContinuousStates(comp, x, NX);
#endif
comp->nSteps++;
comp->time = comp->startTime + comp->nSteps * FIXED_SOLVER_STEP;
// state event
*stateEvent = false;
#if NZ > 0
double z[NZ] = { 0.0 };
getEventIndicators(comp, z, NZ);
// check for zero-crossings
for (int i = 0; i < NZ; i++) {
*stateEvent |= (comp->z[i] <= 0 && z[i] > 0) || (comp->z[i] > 0 && z[i] <= 0);
}
// remember the current event indicators
memcpy(comp->z, z, sizeof(double) * NZ);
#endif
// time event
*timeEvent = comp->nextEventTimeDefined && comp->time >= comp->nextEventTime;
bool earlyReturnRequested;
double earlyReturnTime;
// intermediate update
if (comp->intermediateUpdate) {
comp->intermediateUpdate(
comp->componentEnvironment, // instanceEnvironment
comp->time, // intermediateUpdateTime
false, // intermediateVariableSetRequested
true, // intermediateVariableGetAllowed
true, // intermediateStepFinished
false, // canReturnEarly
&earlyReturnRequested, // earlyReturnRequested
&earlyReturnTime); // earlyReturnTime
}
}

View File

@@ -0,0 +1,887 @@
#if FMI_VERSION != 2
#error FMI_VERSION must be 2
#endif
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <math.h>
#include "config.h"
#include "model.h"
#include "cosimulation.h"
// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_.
// Define DISABLE_PREFIX to build a binary FMU.
#ifndef DISABLE_PREFIX
#define pasteA(a,b) a ## b
#define pasteB(a,b) pasteA(a,b)
#define FMI2_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _)
#endif
#include "fmi2Functions.h"
#define ASSERT_NOT_NULL(p) \
do { \
if (!p) { \
logError(S, "Argument %s must not be NULL.", xstr(p)); \
S->state = modelError; \
return (fmi2Status)Error; \
} \
} while (0)
#define GET_VARIABLES(T) \
do { \
Status status = OK; \
if (nvr == 0) return (fmi2Status)status; \
ASSERT_NOT_NULL(vr); \
ASSERT_NOT_NULL(value); \
size_t index = 0; \
if (S->isDirtyValues) { \
Status s = calculateValues(S); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
S->isDirtyValues = false; \
} \
for (size_t i = 0; i < nvr; i++) { \
Status s = get ## T(S, vr[i], value, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#define SET_VARIABLES(T) \
do { \
Status status = OK; \
if (nvr == 0) return (fmi2Status)status; \
ASSERT_NOT_NULL(vr); \
ASSERT_NOT_NULL(value); \
size_t index = 0; \
for (size_t i = 0; i < nvr; i++) { \
Status s = set ## T(S, vr[i], value, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
if (nvr > 0) S->isDirtyValues = true; \
return (fmi2Status)status; \
} while (0)
#define GET_BOOLEAN_VARIABLES \
do { \
Status status = OK; \
for (size_t i = 0; i < nvr; i++) { \
bool v = false; \
size_t index = 0; \
Status s = getBoolean(S, vr[i], &v, nvr, &index); \
value[i] = v; \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#define SET_BOOLEAN_VARIABLES \
do { \
Status status = OK; \
for (size_t i = 0; i < nvr; i++) { \
bool v = value[i]; \
size_t index = 0; \
Status s = setBoolean(S, vr[i], &v, nvr, &index); \
status = max(status, s); \
if (status > Warning) return (fmi2Status)status; \
} \
return (fmi2Status)status; \
} while (0)
#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
#ifndef DT_EVENT_DETECT
#define DT_EVENT_DETECT 1e-10
#endif
// ---------------------------------------------------------------------------
// Function calls allowed state masks for both Model-exchange and Co-simulation
// ---------------------------------------------------------------------------
#define MASK_fmi2GetTypesPlatform (StartAndEnd | Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepInProgress | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2GetVersion MASK_fmi2GetTypesPlatform
#define MASK_fmi2SetDebugLogging (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepInProgress | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2Instantiate (StartAndEnd)
#define MASK_fmi2FreeInstance (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2SetupExperiment Instantiated
#define MASK_fmi2EnterInitializationMode Instantiated
#define MASK_fmi2ExitInitializationMode InitializationMode
#define MASK_fmi2Terminate (EventMode | ContinuousTimeMode \
| StepComplete | StepFailed)
#define MASK_fmi2Reset MASK_fmi2FreeInstance
#define MASK_fmi2GetReal (InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
#define MASK_fmi2GetInteger MASK_fmi2GetReal
#define MASK_fmi2GetBoolean MASK_fmi2GetReal
#define MASK_fmi2GetString MASK_fmi2GetReal
#define MASK_fmi2SetReal (Instantiated | InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete)
#define MASK_fmi2SetInteger (Instantiated | InitializationMode \
| EventMode \
| StepComplete)
#define MASK_fmi2SetBoolean MASK_fmi2SetInteger
#define MASK_fmi2SetString MASK_fmi2SetInteger
#define MASK_fmi2GetFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2SetFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2FreeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2SerializedFMUstateSize MASK_fmi2FreeInstance
#define MASK_fmi2SerializeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2DeSerializeFMUstate MASK_fmi2FreeInstance
#define MASK_fmi2GetDirectionalDerivative (InitializationMode \
| EventMode | ContinuousTimeMode \
| StepComplete | StepFailed | StepCanceled \
| Terminated | modelError)
// ---------------------------------------------------------------------------
// Function calls allowed state masks for Model-exchange
// ---------------------------------------------------------------------------
#define MASK_fmi2EnterEventMode (EventMode | ContinuousTimeMode)
#define MASK_fmi2NewDiscreteStates EventMode
#define MASK_fmi2EnterContinuousTimeMode EventMode
#define MASK_fmi2CompletedIntegratorStep ContinuousTimeMode
#define MASK_fmi2SetTime (EventMode | ContinuousTimeMode)
#define MASK_fmi2SetContinuousStates ContinuousTimeMode
#define MASK_fmi2GetEventIndicators (InitializationMode \
| EventMode | ContinuousTimeMode \
| Terminated | modelError)
#define MASK_fmi2GetContinuousStates MASK_fmi2GetEventIndicators
#define MASK_fmi2GetDerivatives (EventMode | ContinuousTimeMode \
| Terminated | modelError)
#define MASK_fmi2GetNominalsOfContinuousStates ( Instantiated \
| EventMode | ContinuousTimeMode \
| Terminated | modelError)
// ---------------------------------------------------------------------------
// Function calls allowed state masks for Co-simulation
// ---------------------------------------------------------------------------
#define MASK_fmi2SetRealInputDerivatives (Instantiated | InitializationMode \
| StepComplete)
#define MASK_fmi2GetRealOutputDerivatives (StepComplete | StepFailed | StepCanceled \
| Terminated | Error)
#define MASK_fmi2DoStep StepComplete
#define MASK_fmi2CancelStep StepInProgress
#define MASK_fmi2GetStatus (StepComplete | StepInProgress | StepFailed \
| Terminated)
#define MASK_fmi2GetRealStatus MASK_fmi2GetStatus
#define MASK_fmi2GetIntegerStatus MASK_fmi2GetStatus
#define MASK_fmi2GetBooleanStatus MASK_fmi2GetStatus
#define MASK_fmi2GetStringStatus MASK_fmi2GetStatus
// shorthand to access the instance
#define S ((ModelInstance *)c)
#define ASSERT_STATE(S) \
if (!allowedState(c, MASK_fmi2##S, #S)) \
return fmi2Error;
static bool allowedState(ModelInstance *instance, int statesExpected, char *name) {
if (!instance) {
return false;
}
if (!(instance->state & statesExpected)) {
logError(instance, "fmi2%s: Illegal call sequence.", name);
return false;
}
return true;
}
// ---------------------------------------------------------------------------
// FMI functions
// ---------------------------------------------------------------------------
fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions,
fmi2Boolean visible, fmi2Boolean loggingOn) {
UNUSED(visible);
if (!functions || !functions->logger) {
return NULL;
}
return createModelInstance(
(loggerType)functions->logger,
NULL,
functions->componentEnvironment,
instanceName,
fmuGUID,
fmuResourceLocation,
loggingOn,
(InterfaceType)fmuType);
}
fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance,
fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
UNUSED(toleranceDefined);
UNUSED(tolerance);
ASSERT_STATE(SetupExperiment)
S->startTime = startTime;
S->stopTime = stopTimeDefined ? stopTime : INFINITY;
S->time = startTime;
return fmi2OK;
}
fmi2Status fmi2EnterInitializationMode(fmi2Component c) {
ASSERT_STATE(EnterInitializationMode)
S->state = InitializationMode;
return fmi2OK;
}
fmi2Status fmi2ExitInitializationMode(fmi2Component c) {
ASSERT_STATE(ExitInitializationMode);
fmi2Status status = fmi2OK;
// if values were set and no fmi2GetXXX triggered update before,
// ensure calculated values are updated now
if (S->isDirtyValues) {
status = (fmi2Status)calculateValues(S);
S->isDirtyValues = false;
}
if (S->type == ModelExchange) {
S->state = EventMode;
} else {
S->state = StepComplete;
}
return status;
}
fmi2Status fmi2Terminate(fmi2Component c) {
ASSERT_STATE(Terminate)
S->state = Terminated;
return fmi2OK;
}
fmi2Status fmi2Reset(fmi2Component c) {
ASSERT_STATE(Reset);
reset(S);
return fmi2OK;
}
void fmi2FreeInstance(fmi2Component c) {
if (S) {
freeModelInstance(S);
}
}
// ---------------------------------------------------------------------------
// FMI functions: class methods not depending of a specific model instance
// ---------------------------------------------------------------------------
const char* fmi2GetVersion(void) {
return fmi2Version;
}
const char* fmi2GetTypesPlatform(void) {
return fmi2TypesPlatform;
}
// ---------------------------------------------------------------------------
// FMI functions: logging control, setters and getters for Real, Integer,
// Boolean, String
// ---------------------------------------------------------------------------
fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
ASSERT_STATE(SetDebugLogging)
return (fmi2Status)setDebugLogging(S, loggingOn, nCategories, categories);
}
fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
ASSERT_STATE(GetReal)
if (nvr > 0 && nullPointer(S, "fmi2GetReal", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetReal", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(Float64);
}
fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
ASSERT_STATE(GetInteger)
if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(Int32);
}
fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
ASSERT_STATE(GetBoolean)
if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_BOOLEAN_VARIABLES;
}
fmi2Status fmi2GetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
ASSERT_STATE(GetString)
if (nvr>0 && nullPointer(S, "fmi2GetString", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2GetString", "value[]", value))
return fmi2Error;
if (nvr > 0 && S->isDirtyValues) {
calculateValues(S);
S->isDirtyValues = false;
}
GET_VARIABLES(String);
}
fmi2Status fmi2SetReal (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
ASSERT_STATE(SetReal)
if (nvr > 0 && nullPointer(S, "fmi2SetReal", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2SetReal", "value[]", value))
return fmi2Error;
SET_VARIABLES(Float64);
}
fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
ASSERT_STATE(SetInteger)
if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "vr[]", vr))
return fmi2Error;
if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "value[]", value))
return fmi2Error;
SET_VARIABLES(Int32);
}
fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
ASSERT_STATE(SetBoolean)
if (nvr>0 && nullPointer(S, "fmi2SetBoolean", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2SetBoolean", "value[]", value))
return fmi2Error;
SET_BOOLEAN_VARIABLES;
}
fmi2Status fmi2SetString (fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
ASSERT_STATE(SetString);
if (nvr>0 && nullPointer(S, "fmi2SetString", "vr[]", vr))
return fmi2Error;
if (nvr>0 && nullPointer(S, "fmi2SetString", "value[]", value))
return fmi2Error;
SET_VARIABLES(String);
}
fmi2Status fmi2GetFMUstate (fmi2Component c, fmi2FMUstate* FMUstate) {
ASSERT_STATE(GetFMUstate);
*FMUstate = getFMUState(S);
return fmi2OK;
}
fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) {
ASSERT_STATE(SetFMUstate);
if (nullPointer(S, "fmi2SetFMUstate", "FMUstate", FMUstate)) {
return fmi2Error;
}
setFMUState(S, FMUstate);
return fmi2OK;
}
fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
ASSERT_STATE(FreeFMUstate);
free(*FMUstate);
*FMUstate = NULL;
return fmi2OK;
}
fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) {
UNUSED(c);
UNUSED(FMUstate);
ASSERT_STATE(SerializedFMUstateSize);
*size = sizeof(ModelInstance);
return fmi2OK;
}
fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) {
ASSERT_STATE(SerializeFMUstate);
if (nullPointer(S, "fmi2SerializeFMUstate", "FMUstate", FMUstate)) {
return fmi2Error;
}
if (invalidNumber(S, "fmi2SerializeFMUstate", "size", size, sizeof(ModelInstance))) {
return fmi2Error;
}
memcpy(serializedState, FMUstate, sizeof(ModelInstance));
return fmi2OK;
}
fmi2Status fmi2DeSerializeFMUstate (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) {
ASSERT_STATE(DeSerializeFMUstate);
if (invalidNumber(S, "fmi2DeSerializeFMUstate", "size", size, sizeof(ModelInstance))) {
return fmi2Error;
}
if (*FMUstate == NULL) {
*FMUstate = calloc(1, sizeof(ModelInstance));
}
memcpy(*FMUstate, serializedState, sizeof(ModelInstance));
return fmi2OK;
}
fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
const fmi2ValueReference vKnown_ref[] , size_t nKnown,
const fmi2Real dvKnown[], fmi2Real dvUnknown[]) {
ASSERT_STATE(GetDirectionalDerivative);
// TODO: check value references
// TODO: assert nUnknowns == nDeltaOfUnknowns
// TODO: assert nKnowns == nDeltaKnowns
Status status = OK;
for (size_t i = 0; i < nUnknown; i++) {
dvUnknown[i] = 0;
for (size_t j = 0; j < nKnown; j++) {
double partialDerivative = 0;
Status s = getPartialDerivative(S, vUnknown_ref[i], vKnown_ref[j], &partialDerivative);
status = max(status, s);
if (status > Warning) {
return (fmi2Status)status;
}
dvUnknown[i] += partialDerivative * dvKnown[j];
}
}
return fmi2OK;
}
// ---------------------------------------------------------------------------
// Functions for FMI for Co-Simulation
// ---------------------------------------------------------------------------
/* Simulating the slave */
fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[], const fmi2Real value[]) {
UNUSED(vr);
UNUSED(nvr);
UNUSED(order);
UNUSED(value);
ASSERT_STATE(SetRealInputDerivatives);
logError(S, "fmi2SetRealInputDerivatives: ignoring function call."
" This model cannot interpolate inputs: canInterpolateInputs=\"fmi2False\"");
return fmi2Error;
}
fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr,
const fmi2Integer order[], fmi2Real value[]) {
ASSERT_STATE(GetRealOutputDerivatives);
#ifdef GET_OUTPUT_DERIVATIVE
Status status = OK;
for (size_t i = 0; i < nvr; i++) {
const Status s = getOutputDerivative(S, vr[i], order[i], &value[i]);
status = max(status, s);
if (status > Warning) {
return (fmi2Status)status;
}
}
return (fmi2Status)status;
#else
UNUSED(vr);
UNUSED(nvr);
UNUSED(order);
UNUSED(value);
logError(S, "fmi2GetRealOutputDerivatives: ignoring function call."
" This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\"");
return fmi2Error;
#endif
}
fmi2Status fmi2CancelStep(fmi2Component c) {
ASSERT_STATE(CancelStep);
logError(S, "fmi2CancelStep: Can be called when fmi2DoStep returned fmi2Pending."
" This is not the case.");
return fmi2Error;
}
fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint,
fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
UNUSED(noSetFMUStatePriorToCurrentPoint);
ASSERT_STATE(DoStep);
if (communicationStepSize <= 0) {
logError(S, "Communication step size must be > 0 but was %g.", communicationStepSize);
S->state = modelError;
return fmi2Error;
}
if (currentCommunicationPoint + communicationStepSize > S->stopTime + EPSILON) {
logError(S, "At communication point %.16g a step size of %.16g was requested but stop time is %.16g.",
currentCommunicationPoint, communicationStepSize, S->stopTime);
S->state = modelError;
return fmi2Error;
}
const fmi2Real nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON;
while (true) {
if (S->time + FIXED_SOLVER_STEP > nextCommunicationPoint) {
break; // next communication point reached
}
bool stateEvent, timeEvent;
doFixedStep(S, &stateEvent, &timeEvent);
#ifdef EVENT_UPDATE
if (stateEvent || timeEvent) {
eventUpdate(S);
}
#endif
}
return S->terminateSimulation ? fmi2Discard : fmi2OK;
}
/* Inquire slave status */
static fmi2Status getStatus(char* fname, fmi2Component c, const fmi2StatusKind s) {
switch(s) {
case fmi2DoStepStatus: logError(S,
"%s: Can be called with fmi2DoStepStatus when fmi2DoStep returned fmi2Pending."
" This is not the case.", fname);
break;
case fmi2PendingStatus: logError(S,
"%s: Can be called with fmi2PendingStatus when fmi2DoStep returned fmi2Pending."
" This is not the case.", fname);
break;
case fmi2LastSuccessfulTime: logError(S,
"%s: Can be called with fmi2LastSuccessfulTime when fmi2DoStep returned fmi2Discard."
" This is not the case.", fname);
break;
case fmi2Terminated: logError(S,
"%s: Can be called with fmi2Terminated when fmi2DoStep returned fmi2Discard."
" This is not the case.", fname);
break;
}
return fmi2Discard;
}
fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value) {
UNUSED(value);
ASSERT_STATE(GetStatus);
return getStatus("fmi2GetStatus", c, s);
}
fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value) {
ASSERT_STATE(GetRealStatus);
if (s == fmi2LastSuccessfulTime) {
*value = S->time;
return fmi2OK;
}
return getStatus("fmi2GetRealStatus", c, s);
}
fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value) {
UNUSED(value);
ASSERT_STATE(GetIntegerStatus);
return getStatus("fmi2GetIntegerStatus", c, s);
}
fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value) {
ASSERT_STATE(GetBooleanStatus);
if (s == fmi2Terminated) {
*value = S->terminateSimulation;
return fmi2OK;
}
return getStatus("fmi2GetBooleanStatus", c, s);
}
fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value) {
UNUSED(value);
ASSERT_STATE(GetStringStatus);
return getStatus("fmi2GetStringStatus", c, s);
}
// ---------------------------------------------------------------------------
// Functions for FMI2 for Model Exchange
// ---------------------------------------------------------------------------
/* Enter and exit the different modes */
fmi2Status fmi2EnterEventMode(fmi2Component c) {
ASSERT_STATE(EnterEventMode);
S->state = EventMode;
return fmi2OK;
}
fmi2Status fmi2NewDiscreteStates(fmi2Component c, fmi2EventInfo *eventInfo) {
ASSERT_STATE(NewDiscreteStates);
#ifdef EVENT_UPDATE
eventUpdate(S);
#endif
eventInfo->newDiscreteStatesNeeded = S->newDiscreteStatesNeeded;
eventInfo->terminateSimulation = S->terminateSimulation;
eventInfo->nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged;
eventInfo->valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged;
eventInfo->nextEventTimeDefined = S->nextEventTimeDefined;
eventInfo->nextEventTime = S->nextEventTime;
return fmi2OK;
}
fmi2Status fmi2EnterContinuousTimeMode(fmi2Component c) {
ASSERT_STATE(EnterContinuousTimeMode);
S->state = ContinuousTimeMode;
return fmi2OK;
}
fmi2Status fmi2CompletedIntegratorStep(fmi2Component c, fmi2Boolean noSetFMUStatePriorToCurrentPoint,
fmi2Boolean *enterEventMode, fmi2Boolean *terminateSimulation) {
UNUSED(noSetFMUStatePriorToCurrentPoint);
ASSERT_STATE(CompletedIntegratorStep);
if (nullPointer(S, "fmi2CompletedIntegratorStep", "enterEventMode", enterEventMode))
return fmi2Error;
if (nullPointer(S, "fmi2CompletedIntegratorStep", "terminateSimulation", terminateSimulation))
return fmi2Error;
*enterEventMode = fmi2False;
*terminateSimulation = fmi2False;
return fmi2OK;
}
/* Providing independent variables and re-initialization of caching */
fmi2Status fmi2SetTime(fmi2Component c, fmi2Real time) {
ASSERT_STATE(SetTime);
S->time = time;
return fmi2OK;
}
fmi2Status fmi2SetContinuousStates(fmi2Component c, const fmi2Real x[], size_t nx){
ASSERT_STATE(SetContinuousStates);
if (invalidNumber(S, "fmi2SetContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2SetContinuousStates", "x[]", x))
return fmi2Error;
setContinuousStates(S, x, nx);
return fmi2OK;
}
/* Evaluation of the model equations */
fmi2Status fmi2GetDerivatives(fmi2Component c, fmi2Real derivatives[], size_t nx) {
ASSERT_STATE(GetDerivatives);
if (invalidNumber(S, "fmi2GetDerivatives", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetDerivatives", "derivatives[]", derivatives))
return fmi2Error;
getDerivatives(S, derivatives, nx);
return fmi2OK;
}
fmi2Status fmi2GetEventIndicators(fmi2Component c, fmi2Real eventIndicators[], size_t ni) {
ASSERT_STATE(GetEventIndicators);
#if NZ > 0
if (invalidNumber(S, "fmi2GetEventIndicators", "ni", ni, NZ))
return fmi2Error;
getEventIndicators(S, eventIndicators, ni);
#else
UNUSED(c);
UNUSED(eventIndicators);
if (ni > 0) return fmi2Error;
#endif
return fmi2OK;
}
fmi2Status fmi2GetContinuousStates(fmi2Component c, fmi2Real states[], size_t nx) {
ASSERT_STATE(GetContinuousStates);
if (invalidNumber(S, "fmi2GetContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetContinuousStates", "states[]", states))
return fmi2Error;
getContinuousStates(S, states, nx);
return fmi2OK;
}
fmi2Status fmi2GetNominalsOfContinuousStates(fmi2Component c, fmi2Real x_nominal[], size_t nx) {
ASSERT_STATE(GetNominalsOfContinuousStates);
if (invalidNumber(S, "fmi2GetNominalContinuousStates", "nx", nx, NX))
return fmi2Error;
if (nullPointer(S, "fmi2GetNominalContinuousStates", "x_nominal[]", x_nominal))
return fmi2Error;
for (size_t i = 0; i < nx; i++)
x_nominal[i] = 1;
return fmi2OK;
}

View File

@@ -0,0 +1,52 @@
/* */
/* This script file uses the Doors4ExampleFMU.fmu to be run in OpenXiL */
/* */
ADD_BBVARI(Loop, UDWORD)
SET_BBVARI(Loop = 0)
/* */
/* Door01Left = 1 represents a open door */
/* wait more then 2 seconds */
/* Open all doors */
/* */
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
SET_BBVARI(Door02LeftIsOpen = 1)
SET_BBVARI(Door02RightIsOpen = 1)
/* */
/* Close each door one by one */
/* wait more then 2 seconds */
/* Open all doors */
/* */
WHILE(Loop < 10)
SET_BBVARI(Door01LeftIsOpen = 0)
DELAY(100)
SET_BBVARI(Door01RightIsOpen = 0)
DELAY(100)
SET_BBVARI(Door02LeftIsOpen = 0)
DELAY(100)
SET_BBVARI(Door02RightIsOpen = 0)
/* */
/* wait until the doors are locked, < 2 seconds */
/* */
DELAY(1000)
SET_BBVARI(Door01LeftIsOpen = 1)
SET_BBVARI(Door01RightIsOpen = 1)
SET_BBVARI(Door02LeftIsOpen = 1)
SET_BBVARI(Door02RightIsOpen = 1)
DELAY(100)
SET(Loop = Loop + 1)
ENDWHILE

View File

@@ -0,0 +1,63 @@
/**
* @file vss_vehiclechassisdooraxle01left_bs_rx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include "interfaces/core.idl"
#include "vss_vehiclechassisdooraxle01left_vd_rx.idl"
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module LeftService
{
/**
* @brief IVSS_SetIsOpen event interface
*/
interface IVSS_SetIsOpen_Event
{
/**
* @brief Set leftDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenL1(in boolean value);
};
/**
* @brief IVSS_GetIsOpen Service interface
*/
interface IVSS_GetIsOpen
{
/**
* @brief Get rightDoorIsOpen signal
* @return Returns the rightDoorIsOpen
*/
boolean GetIsOpen() const;
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfLeftDoorIsOpen01(in vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event callback);
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfLeftDoorIsOpen01(in vss::Vehicle::Chassis::Door::Axle01::LeftService::IVSS_SetIsOpen_Event callback);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,39 @@
/**
* @file vss_vehiclechassisdooraxle01left_bs_tx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <interfaces/core.idl>
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module LeftService
{
/**
* @brief IVSS_SetLock Service interface
*/
interface IVSS_SetLock
{
/**
* @brief Set leftLatch02 signal
* @param[in] value
* @return true on success otherwise false
*/
boolean SetLock(in boolean value);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,57 @@
/**
* @file vss_vehiclechassisdooraxle01left_vd_rx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include "interfaces/core.idl"
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module LeftDevice
{
/**
* @brief IVSS_WriteIsOpen event interface
*/
interface IVSS_WriteIsOpen_Event
{
/**
* @brief Write leftDoorIsOpen signal
* @param[in] value leftDoorIsOpen
*/
void WriteIsOpen(in boolean value);
};
/**
* @brief IVSS_IsOpen abstract Device interface
*/
interface IVSS_IsOpen
{
/**
* @brief Register WriteIsOpen event on signal change
* Register all events and call them on signal change
* @param[in] event function
*/
void RegisterIsOpenEvent(in IVSS_WriteIsOpen_Event event);
/**
* @brief Unregister IsOpen event
* @param[in] event function
*/
void UnregisterIsOpenEvent(in IVSS_WriteIsOpen_Event event);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,39 @@
/**
* @file vss_vehiclechassisdooraxle01left_vd_tx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <interfaces/core.idl>
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module LeftDevice
{
/**
* @brief IVSS_WriteLock Device interface
*/
interface IVSS_WriteLock
{
/**
* @brief Write leftLatch01 signal
* @param[in] value
* @return true on success otherwise false
*/
boolean WriteLock(in boolean value);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,64 @@
/**
* @file vss_vehiclechassisdooraxle01right_bs_rx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include "interfaces/core.idl"
#include "vss_vehiclechassisdooraxle01right_vd_rx.idl"
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module RightService
{
/**
* @brief IVSS_SetIsOpen event interface
*/
interface IVSS_SetIsOpen_Event
{
/**
* @brief Set rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR1(in boolean value);
};
/**
* @brief IVSS_GetIsOpen Service interface
*/
interface IVSS_GetIsOpen
{
/**
* @brief Get rightDoorIsOpen signal
* @return Returns the rightDoorIsOpen
*/
boolean GetIsOpen() const;
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfRightDoorIsOpen01(in vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event callback);
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfRightDoorIsOpen01(in vss::Vehicle::Chassis::Door::Axle01::RightService::IVSS_SetIsOpen_Event callback);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,39 @@
/**
* @file vss_vehiclechassisdooraxle01right_bs_tx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <interfaces/core.idl>
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module RightService
{
/**
* @brief IVSS_SetLock Service interface
*/
interface IVSS_SetLock
{
/**
* @brief Set rightLatch signal
* @param[in] value
* @return true on success otherwise false
*/
boolean SetLock(in boolean value);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,58 @@
/**
* @file vss_vehiclechassisdooraxle01right_vd_rx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include "interfaces/core.idl"
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module RightDevice
{
/**
* @brief IVSS_WriteIsOpen event interface
*/
interface IVSS_WriteIsOpen_Event
{
/**
* @brief Write rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void WriteIsOpen(in boolean value);
};
/**
* @brief IVSS_IsOpen abstract Device interface
*/
interface IVSS_IsOpen
{
/**
* @brief Register WriteIsOpen event on signal change
* Register all events and call them on signal change
* @param[in] event function
*/
void RegisterIsOpenEvent(in IVSS_WriteIsOpen_Event event);
/**
* @brief Unregister IsOpen event
* @param[in] event function
*/
void UnregisterIsOpenEvent(in IVSS_WriteIsOpen_Event event);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,39 @@
/**
* @file vss_vehiclechassisdooraxle01right_vd_tx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <interfaces/core.idl>
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle01
{
module RightDevice
{
/**
* @brief IVSS_WriteLock Device interface
*/
interface IVSS_WriteLock
{
/**
* @brief Write rightLatch signal
* @param[in] value
* @return true on success otherwise false
*/
boolean WriteLock(in boolean value);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,63 @@
/**
* @file vss_vehiclechassisdooraxle02left_bs_rx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include "interfaces/core.idl"
#include "vss_vehiclechassisdooraxle02left_vd_rx.idl"
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle02
{
module LeftService
{
/**
* @brief IVSS_SetIsOpen event interface
*/
interface IVSS_SetIsOpen_Event
{
/**
* @brief Set leftDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenL2(in boolean value);
};
/**
* @brief IVSS_GetIsOpen Service interface
*/
interface IVSS_GetIsOpen
{
/**
* @brief Get rightDoorIsOpen signal
* @return Returns the rightDoorIsOpen
*/
boolean GetIsOpen() const;
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfLeftDoorIsOpen02(in vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event callback);
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfLeftDoorIsOpen02(in vss::Vehicle::Chassis::Door::Axle02::LeftService::IVSS_SetIsOpen_Event callback);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,39 @@
/**
* @file vss_vehiclechassisdooraxle02left_bs_tx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <interfaces/core.idl>
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle02
{
module LeftService
{
/**
* @brief IVSS_SetLock Service interface
*/
interface IVSS_SetLock
{
/**
* @brief Set leftLatch02 signal
* @param[in] value
* @return true on success otherwise false
*/
boolean SetLock(in boolean value);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,57 @@
/**
* @file vss_vehiclechassisdooraxle02left_vd_rx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include "interfaces/core.idl"
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle02
{
module LeftDevice
{
/**
* @brief IVSS_WriteIsOpen event interface
*/
interface IVSS_WriteIsOpen_Event
{
/**
* @brief Write leftDoorIsOpen signal
* @param[in] value leftDoorIsOpen
*/
void WriteIsOpen(in boolean value);
};
/**
* @brief IVSS_IsOpen abstract Device interface
*/
interface IVSS_IsOpen
{
/**
* @brief Register WriteIsOpen event on signal change
* Register all events and call them on signal change
* @param[in] event function
*/
void RegisterIsOpenEvent(in IVSS_WriteIsOpen_Event event);
/**
* @brief Unregister IsOpen event
* @param[in] event function
*/
void UnregisterIsOpenEvent(in IVSS_WriteIsOpen_Event event);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,39 @@
/**
* @file vss_vehiclechassisdooraxle02left_vd_tx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include <interfaces/core.idl>
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle02
{
module LeftDevice
{
/**
* @brief IVSS_WriteLock Device interface
*/
interface IVSS_WriteLock
{
/**
* @brief Write leftLatch02 signal
* @param[in] value
* @return true on success otherwise false
*/
boolean WriteLock(in boolean value);
};
};
};
};
};
};
};

View File

@@ -0,0 +1,64 @@
/**
* @file vss_vehiclechassisdooraxle02right_bs_rx.idl
* @date 2025-07-11 11:03:55
* File is auto generated from VSS utility.
* VSS Version:1.0.0.1
*/
#include "interfaces/core.idl"
#include "vss_vehiclechassisdooraxle02right_vd_rx.idl"
module vss
{
module Vehicle
{
module Chassis
{
module Door
{
module Axle02
{
module RightService
{
/**
* @brief IVSS_SetIsOpen event interface
*/
interface IVSS_SetIsOpen_Event
{
/**
* @brief Set rightDoorIsOpen signal
* @param[in] value rightDoorIsOpen
*/
void SetIsOpenR2(in boolean value);
};
/**
* @brief IVSS_GetIsOpen Service interface
*/
interface IVSS_GetIsOpen
{
/**
* @brief Get rightDoorIsOpen signal
* @return Returns the rightDoorIsOpen
*/
boolean GetIsOpen() const;
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOfRightDoorIsOpen02(in vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event callback);
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void UnregisterOnSignalChangeOfRightDoorIsOpen02(in vss::Vehicle::Chassis::Door::Axle02::RightService::IVSS_SetIsOpen_Event callback);
};
};
};
};
};
};
};

Some files were not shown because too many files have changed in this diff Show More