mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 15:18:45 +00:00
551 lines
16 KiB
C++
551 lines
16 KiB
C++
|
|
/**
|
|
* @brief Build description template. File 'buildDescription.xml'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szBuildDescriptionTemplate[] = R"code(<!--
|
|
@file %buiddescription_path%
|
|
@date %date%
|
|
This file is the fmi Build Description xml.
|
|
This file was generated by the DBC utility from:
|
|
%dbc_sources%
|
|
%dbc_version%
|
|
-->
|
|
%buildDescription_xml%
|
|
)code";
|
|
|
|
|
|
/**
|
|
* @brief CMake build project template. File 'CMakeLists.txt'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szMappingCMakeFileListsTemplate[] = R"code(
|
|
# @file %cmakefilelists_path%
|
|
# This file is cmake project file.
|
|
# This file was generated by the DBC utility from:
|
|
# %dbc_sources%
|
|
# %dbc_version%
|
|
|
|
|
|
# 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 (%model_Identifier%Project)
|
|
|
|
# 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 %model_Identifier%)
|
|
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 ()
|
|
|
|
)code";
|
|
|
|
|
|
/**
|
|
*@brief Config Header template. File 'config.h'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szConfigHTemplate[] = R"code(/**
|
|
* @file %configH_path%
|
|
* @date %date%
|
|
* This file defines the data link object between CAN and the V-API devices.
|
|
* This file was generated by the DBC utility from:
|
|
* %dbc_sources%
|
|
* %dbc_version%
|
|
*/
|
|
#ifndef %safeguardconfig%
|
|
#define %safeguardconfig%
|
|
|
|
#include <stdint.h>
|
|
|
|
// define class name and unique id
|
|
#define MODEL_IDENTIFIER %model_Identifier%
|
|
#define INSTANTIATION_TOKEN "%model_guid%"
|
|
#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 {
|
|
%value_reference%
|
|
|
|
} ValueReference;
|
|
|
|
typedef struct {
|
|
%model_data%
|
|
|
|
} ModelData;
|
|
|
|
#endif // !defined %safeguardconfig%
|
|
|
|
)code";
|
|
|
|
|
|
/**
|
|
*@brief FMI2 xml template. File 'FMI2.XML'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szFMI2XMLTemplate[] = R"code(<?xml version="1.0" encoding="UTF-8"?>
|
|
<fmiModelDescription
|
|
fmiVersion = "2.0"
|
|
modelName = "%model_Identifier%"
|
|
guid = "%model_guid%"
|
|
description = "TargetLink FMU for %model_Identifier%"
|
|
generationTool = "TargetLink was generated by the DBC utility: %dbc_sources%"
|
|
generationDateAndTime = "%date%"
|
|
variableNamingConvention = "structured"
|
|
numberOfEventIndicators = "0">
|
|
<CoSimulation
|
|
modelIdentifier = "%model_Identifier%"
|
|
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>
|
|
%model_variables%
|
|
</ModelVariables>
|
|
<ModelStructure>
|
|
<Outputs>
|
|
<Unknown index="%unknown_index%"/>
|
|
</Outputs>
|
|
</ModelStructure>
|
|
</fmiModelDescription>
|
|
)code";
|
|
|
|
|
|
/**
|
|
*@brief Model cpp template. File 'model.cpp'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szModelCPPTemplate[] = R"code(/**
|
|
* @file %modelcpp_path%
|
|
* @date %date%
|
|
* This file defines the data link object between CAN and the V-API devices.
|
|
* This file was generated by the DBC utility from:
|
|
* %dbc_sources%
|
|
* %dbc_version%
|
|
*/
|
|
|
|
#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>
|
|
|
|
%global_signals%
|
|
// 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;
|
|
|
|
%global_signals_register%
|
|
%global_signals_register_check%
|
|
|
|
return sdv::core::EConfigProcessResult::failed;
|
|
}
|
|
|
|
bool ResetAllSignals()
|
|
{
|
|
sdv::core::CDispatchService dispatch;
|
|
|
|
%global_signals_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");
|
|
}
|
|
%vapi_load_config_files%
|
|
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);
|
|
%getFloat64%
|
|
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);
|
|
%getInt32%
|
|
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);
|
|
%setFloat64%
|
|
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);
|
|
%setInt32%
|
|
return OK;
|
|
}
|
|
|
|
void eventUpdate(ModelInstance* comp)
|
|
{
|
|
%event_update%
|
|
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
|
|
|
|
)code";
|
|
|
|
|
|
/**
|
|
*@brief Signal name mapping template. Signal names contain the can names of the signal which must match the names of the vehicle devices.
|
|
* File 'signal_identifier.h'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szMappingSignalIdentifierTemplate[] = R"code(/**
|
|
@file %signalidentifierfile_path%
|
|
@date %date%
|
|
This file is the signal identifier header.
|
|
This file was generated by the DBC utility from:
|
|
%dbc_sources%
|
|
%dbc_version%
|
|
*/
|
|
#ifndef %safeguardsignalidentifier%
|
|
#define %safeguardsignalidentifier%
|
|
|
|
namespace %object_prefix%
|
|
{
|
|
// Data Dispatch Service signal names to dbc variable names C-type RX/TX vss name space
|
|
%signals%
|
|
} // %object_prefix%
|
|
|
|
#endif // %safeguardsignalidentifier%
|
|
)code";
|
|
|
|
|
|
/**
|
|
*@brief Data dispatch service config template. File 'data_dispatch_config_file.toml'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szDataDispatchServiceTomlFile[] = R"code([Configuration]
|
|
Version = 100
|
|
|
|
[[Component]]
|
|
Path = "data_dispatch_service.sdv"
|
|
Class = "DataDispatchService"
|
|
)code";
|
|
|
|
/**
|
|
*@brief Simulation task timer service config template. File 'simulation_task_timer_config_file.toml'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szSimulationTaskTimerServiceTomlFile[] = R"code([Configuration]
|
|
Version = 100
|
|
|
|
[[Component]]
|
|
Path = "simulation_task_timer.sdv"
|
|
Class = "SimulationTaskTimerService"
|
|
)code";
|
|
|
|
/**
|
|
*@brief Task timer service config template. File 'task_timer_config_file.toml'. Code chunks are inserted at the keywords surrounded by %%.
|
|
*/
|
|
const char szTaskTimerhServiceTomlFile[] = R"code([Configuration]
|
|
Version = 100
|
|
|
|
[[Component]]
|
|
Path = "task_timer.sdv"
|
|
Class = "TaskTimerService"
|
|
)code";
|
|
|