mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 15:18:45 +00:00
29
sdv_executables/sdv_dbc_util/CMakeLists.txt
Normal file
29
sdv_executables/sdv_dbc_util/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
# Define project
|
||||
project (sdv_dbc_util VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
# Add include directories
|
||||
include_directories(../export)
|
||||
|
||||
# Define the executable
|
||||
add_executable(sdv_dbc_util
|
||||
main.cpp
|
||||
can_dl.h
|
||||
can_dl.cpp
|
||||
fmu.h
|
||||
fmu.cpp
|
||||
cmake_generator.cpp
|
||||
cmake_generator.h
|
||||
codegen_base.cpp
|
||||
"fmu_templates.h")
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(sdv_dbc_util ${CMAKE_DL_LIBS} Rpcrt4.lib)
|
||||
else()
|
||||
target_link_libraries(sdv_dbc_util ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
|
||||
# Build dependencies
|
||||
add_dependencies(sdv_dbc_util CompileCoreIDL)
|
||||
|
||||
# Appending the executable to the service list
|
||||
set(SDV_Executable_List ${SDV_Executable_List} sdv_dbc_util PARENT_SCOPE)
|
||||
1721
sdv_executables/sdv_dbc_util/can_dl.cpp
Normal file
1721
sdv_executables/sdv_dbc_util/can_dl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
198
sdv_executables/sdv_dbc_util/can_dl.h
Normal file
198
sdv_executables/sdv_dbc_util/can_dl.h
Normal file
@@ -0,0 +1,198 @@
|
||||
#ifndef CAN_DL_H
|
||||
#define CAN_DL_H
|
||||
|
||||
#include "../global/dbcparser/dbcparser.h"
|
||||
#include <fstream>
|
||||
#include "codegen_base.h"
|
||||
|
||||
/**
|
||||
* @brief CAN data link generator class.
|
||||
*/
|
||||
class CCanDataLinkGen : public CCodeGeneratorBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] rpathOutputDir Reference to the outpur directory.
|
||||
* @param[in] rparser Reference to the DBC parser containing the definitions.
|
||||
* @param[in] rssVersion Reference to a string representing a version of the dbc file (could be empty).
|
||||
* @param[in] rssIfcName Reference to the string holding the interface name (could be empty).
|
||||
* @param[in] nIfcIdx The interface index (valid if no name is provided).
|
||||
* @param[in] rvecNodes Reference to a list of nodes this data link object is representing. An empty list will implement
|
||||
* sending and receiving functions for all nodes.
|
||||
*/
|
||||
CCanDataLinkGen(const std::filesystem::path& rpathOutputDir, const dbc::CDbcParser& rparser, const std::string& rssVersion,
|
||||
const std::string& rssIfcName, size_t nIfcIdx, const std::vector<std::string>& rvecNodes);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Keyword map for keyword replacement in a string.
|
||||
*/
|
||||
typedef std::map<std::string, std::string> CKeywordMap;
|
||||
|
||||
/**
|
||||
* @brief Replace keywords in a string.
|
||||
* @param[in] rssStr Reference to the string containing the keywords.
|
||||
* @param[in] rmapKeywords Map with keywords to replace.
|
||||
* @param[in] cMarker Character to identify the keyword with (placed before and after the keyword; e.g. %keyword%).
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
static std::string ReplaceKeywords(const std::string& rssStr, const CKeywordMap& rmapKeywords, char cMarker = '%');
|
||||
|
||||
/**
|
||||
* @brief validates that the string represents a float
|
||||
* @param[in] rssInput Reference to the string representing a float.
|
||||
* @return Returns the input string. If '.' not found it adds ".0" to the string
|
||||
*/
|
||||
std::string StringMustBeFloatValue(const std::string& rssInput);
|
||||
|
||||
/**
|
||||
* @brief Composes a dbc file version information string
|
||||
* @param[in] rssVersion Reference to a string representing a version of the dbc file.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeDBCFileVersion(const std::string& rssVersion);
|
||||
|
||||
/**
|
||||
* @brief Provide code to determine the interface index based on the interface name (if supplied).
|
||||
* @param[in] rssIfcName Reference to the string holding the interface name (could be empty).
|
||||
* @return The code to insert during initialization.
|
||||
*/
|
||||
std::string CodeInitInterfaceIndex(const std::string& rssIfcName);
|
||||
|
||||
/**
|
||||
* @brief Provide code for the RX message definition.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the message definition for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeRxMessageDefinition(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Provide code for the TX message definition.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the message definition for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeTxMessageDefinition(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Provide code for the signal declaration.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide a declaration for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeSignalDecl(const dbc::SSignalDef& rsSig);
|
||||
|
||||
/**
|
||||
* @brief Initialize the RX message variable.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeInitVarRxMessage(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Initialize the TX message variable.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeInitVarTxMessage(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Initialize the RX message structure.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeInitRxMessage(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Initialize the TX message structure.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeInitTxMessage(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Terminate the RX message structure.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeTermRxMessage(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Terminate the TX message structure.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeTermTxMessage(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Provide the RX message structure functions.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeRxMessageFunctions(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Provide the TX message structure functions.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeTxMessageFunctions(const dbc::SMessageDef& rsMsg);
|
||||
|
||||
/**
|
||||
* @brief Initialize the signal registration.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the registration for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeRegisterRxSignal(const dbc::SMessageDef& rsMsg, const dbc::SSignalDef& rsSig);
|
||||
|
||||
/**
|
||||
* @brief Initialize the signal registration.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the registration for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeRegisterTxSignal(const dbc::SMessageDef& rsMsg, const dbc::SSignalDef& rsSig);
|
||||
|
||||
/**
|
||||
* @brief Remove the signal registration.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the unregistration for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeUnregisterSignal(const dbc::SMessageDef& rsMsg, const dbc::SSignalDef& rsSig);
|
||||
|
||||
/**
|
||||
* @brief Process the signal data for the specific message.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the processing for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeProcessRxSignal(const dbc::SMessageDef& rsMsg, const dbc::SSignalDef& rsSig);
|
||||
|
||||
/**
|
||||
* @brief Initialize the TX trigger with the signal..
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the trigger initialization for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string InitTrigger(const dbc::SMessageDef& rsMsg, const dbc::SSignalDef& rsSig);
|
||||
|
||||
/**
|
||||
* @brief Compose the message from the signal data.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the composition for.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeComposeTxSignal(const dbc::SMessageDef& rsMsg, const dbc::SSignalDef& rsSig);
|
||||
|
||||
std::filesystem::path m_pathProject; ///< Project file path
|
||||
std::filesystem::path m_pathHeader; ///< Header file path
|
||||
std::filesystem::path m_pathCpp; ///< C++ file path
|
||||
std::ofstream m_fstreamHeader; ///< The header file
|
||||
std::ofstream m_fstreamCpp; ///< The C++ file
|
||||
const dbc::CDbcParser& m_rparser; ///< Reference to the DBC parser.
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // !defined CAN_DL_H
|
||||
141
sdv_executables/sdv_dbc_util/cmake_generator.cpp
Normal file
141
sdv_executables/sdv_dbc_util/cmake_generator.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "cmake_generator.h"
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
CDbcUtilCMakeGenerator::CDbcUtilCMakeGenerator(const std::filesystem::path& rpathOutputDir, const std::string& rssComponent)
|
||||
{
|
||||
if (rssComponent.empty()) return; // TODO: Exception
|
||||
|
||||
// Create project directory
|
||||
if (!rpathOutputDir.empty())
|
||||
m_pathProject = rpathOutputDir;
|
||||
if (!rssComponent.empty())
|
||||
m_pathProject /= "can_dl";
|
||||
std::filesystem::create_directories(m_pathProject);
|
||||
|
||||
// The source string
|
||||
std::string ssSource;
|
||||
|
||||
// File with "CMakeLists.txt" function; read completely if existing
|
||||
std::filesystem::path pathFile = m_pathProject / "CMakeLists.txt";
|
||||
if (std::filesystem::exists(pathFile))
|
||||
{
|
||||
std::ifstream stream;
|
||||
stream.open(pathFile);
|
||||
if (!stream.is_open()) return; // TODO: Exception: throw CCompileException("Failed to open the CMakeLists.txt file for reading.");
|
||||
|
||||
// Read the complete source
|
||||
std::stringstream sstream;
|
||||
sstream << stream.rdbuf();
|
||||
ssSource = std::move(sstream.str());
|
||||
}
|
||||
else // Create the file in memory
|
||||
{
|
||||
ssSource = R"code(# 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(%component% 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(%component% SHARED)
|
||||
|
||||
# Set extension to .sdv
|
||||
set_target_properties(%component% PROPERTIES PREFIX "")
|
||||
set_target_properties(%component% PROPERTIES SUFFIX ".sdv")
|
||||
)code";
|
||||
CKeywordMap mapKeywords;
|
||||
mapKeywords["component"] = rssComponent;
|
||||
ssSource = ReplaceKeywords(ssSource, mapKeywords);
|
||||
}
|
||||
|
||||
// Search function for caseless finding in the string.
|
||||
auto fnNCFind = [&](const std::string& rssText, size_t nPos = 0) -> size_t
|
||||
{
|
||||
auto it = std::search(ssSource.begin() + nPos, ssSource.end(), rssText.begin(), rssText.end(),
|
||||
[](unsigned char ch1, unsigned char ch2) { return std::tolower(ch1) == std::tolower(ch2); }
|
||||
);
|
||||
if (it == ssSource.end()) return std::string::npos;
|
||||
return std::distance(ssSource.begin(), it);
|
||||
};
|
||||
|
||||
// Find the add_library function
|
||||
size_t nPos = fnNCFind("add_library");
|
||||
if (nPos == std::string::npos) return; // TODO: Exception: throw CCompileException("Missing 'add_library' keyword.");
|
||||
|
||||
// Search for shared keyword
|
||||
nPos = fnNCFind("shared", nPos);
|
||||
if (nPos == std::string::npos) return; // TODO: Exception: throw CCompileException("Missing 'shared' keyword.");
|
||||
nPos += 6;
|
||||
|
||||
// Build set with files
|
||||
size_t nStop = fnNCFind(")", nPos);
|
||||
if (nStop == std::string::npos) return; // TODO: Exception: throw CCompileException("Missing ')' closing the 'add_library' statement.");
|
||||
std::set<std::string> setFiles;
|
||||
while (nPos < nStop)
|
||||
{
|
||||
// Skip whitespace
|
||||
while (std::isspace(ssSource[nPos])) nPos++;
|
||||
|
||||
// Read file name
|
||||
size_t nFileBegin = nPos;
|
||||
while (nPos < nStop && !std::isspace(ssSource[nPos])) nPos++;
|
||||
|
||||
// Store the file
|
||||
setFiles.insert(ssSource.substr(nFileBegin, nPos - nFileBegin));
|
||||
}
|
||||
|
||||
// Insert additional files if needed
|
||||
size_t nSourceSize = ssSource.size();
|
||||
if (setFiles.find("datalink.h") == setFiles.end())
|
||||
ssSource.insert(nStop, std::string("\n datalink.h"));
|
||||
if (setFiles.find("datalink.cpp") == setFiles.end())
|
||||
ssSource.insert(nStop, std::string("\n datalink.cpp"));
|
||||
|
||||
// Write the file again if needed
|
||||
if (nSourceSize != ssSource.size())
|
||||
{
|
||||
std::ofstream stream;
|
||||
stream.open(pathFile, std::ofstream::trunc);
|
||||
if (!stream.is_open()) return; // TODO: Exception: throw CCompileException("Failed to open the CMakeLists.txt file for writing.");
|
||||
|
||||
// Write the complete source
|
||||
stream << ssSource;
|
||||
}
|
||||
}
|
||||
|
||||
CDbcUtilCMakeGenerator::~CDbcUtilCMakeGenerator()
|
||||
{}
|
||||
|
||||
30
sdv_executables/sdv_dbc_util/cmake_generator.h
Normal file
30
sdv_executables/sdv_dbc_util/cmake_generator.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef CMAKE_GENERATOR_H
|
||||
#define CMAKE_GENERATOR_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include "codegen_base.h"
|
||||
|
||||
/**
|
||||
* @brief CMake generator class.
|
||||
*/
|
||||
class CDbcUtilCMakeGenerator : public CCodeGeneratorBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] rpathOutputDir Reference to the outpur directory.
|
||||
* @param[in] rssComponent Current component this CMake file is for.
|
||||
*/
|
||||
CDbcUtilCMakeGenerator(const std::filesystem::path& rpathOutputDir, const std::string& rssComponent);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CDbcUtilCMakeGenerator();
|
||||
|
||||
private:
|
||||
std::filesystem::path m_pathProject; ///< Project file path
|
||||
};
|
||||
|
||||
#endif // !defined CMAKE_GENERATOR_H
|
||||
38
sdv_executables/sdv_dbc_util/codegen_base.cpp
Normal file
38
sdv_executables/sdv_dbc_util/codegen_base.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "codegen_base.h"
|
||||
#include <sstream>
|
||||
|
||||
std::string CCodeGeneratorBase::ReplaceKeywords(const std::string& rssStr, const CKeywordMap& rmapKeywords, char cMarker /*= '%'*/)
|
||||
{
|
||||
std::stringstream sstream;
|
||||
size_t nPos = 0;
|
||||
while (nPos < rssStr.size())
|
||||
{
|
||||
// Find the initial separator
|
||||
size_t nSeparator = rssStr.find(cMarker, nPos);
|
||||
sstream << rssStr.substr(nPos, nSeparator == std::string::npos ? nSeparator : nSeparator - nPos);
|
||||
nPos = nSeparator;
|
||||
if (nSeparator == std::string::npos) continue;
|
||||
nPos++;
|
||||
|
||||
// Find the next separator.
|
||||
nSeparator = rssStr.find(cMarker, nPos);
|
||||
if (nSeparator == std::string::npos)
|
||||
{
|
||||
// Internal error: missing second separator during code building.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the keyword in the keyword map (between the separator and the position).
|
||||
CKeywordMap::const_iterator itKeyword = rmapKeywords.find(rssStr.substr(nPos, nSeparator - nPos));
|
||||
if (itKeyword == rmapKeywords.end())
|
||||
{
|
||||
// Internal error: invalid keyword during building code.
|
||||
nPos = nSeparator + 1;
|
||||
continue;
|
||||
}
|
||||
sstream << itKeyword->second;
|
||||
nPos = nSeparator + 1;
|
||||
}
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
71
sdv_executables/sdv_dbc_util/codegen_base.h
Normal file
71
sdv_executables/sdv_dbc_util/codegen_base.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef CODEGEN_BASE_H
|
||||
#define CODEGEN_BASE_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
/**
|
||||
* @brief Code generator base class.
|
||||
*/
|
||||
class CCodeGeneratorBase
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* @brief Keyword map for keyword replacement in a string.
|
||||
*/
|
||||
typedef std::map<std::string, std::string> CKeywordMap;
|
||||
|
||||
/**
|
||||
* @brief Replace keywords in a string.
|
||||
* @param[in] rssStr Reference to the string containing the keywords.
|
||||
* @param[in] rmapKeywords Map with keywords to replace.
|
||||
* @param[in] cMarker Character to identify the keyword with (placed before and after the keyword; e.g. %keyword%).
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
static std::string ReplaceKeywords(const std::string& rssStr, const CKeywordMap& rmapKeywords, char cMarker = '%');
|
||||
|
||||
/**
|
||||
* @brief Generator specific string generator. The std::to_string doesn't handle floating points very well.
|
||||
* @tparam T Type of the variable to stringetize.
|
||||
* @param[in] rtVar Reference to the variable.
|
||||
* @return The generated string object.
|
||||
*/
|
||||
template <typename T>
|
||||
static std::string to_string(const T& rtVar)
|
||||
{
|
||||
std::ostringstream sstream;
|
||||
sstream << rtVar;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overloading for double.
|
||||
* @param[in] rdVar Reference to the double variable.
|
||||
* @return The generated string object.
|
||||
*/
|
||||
static std::string to_string(const double& rdVar)
|
||||
{
|
||||
std::ostringstream sstream;
|
||||
sstream << rdVar;
|
||||
if (std::round(rdVar) == rdVar) sstream << ".0";
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overloading for float.
|
||||
* @param[in] rfVar Reference to the float variable.
|
||||
* @return The generated string object.
|
||||
*/
|
||||
static std::string to_string(const float& rfVar)
|
||||
{
|
||||
std::ostringstream sstream;
|
||||
sstream << rfVar;
|
||||
if (std::round(rfVar) == rfVar) sstream << ".0";
|
||||
sstream << "f";
|
||||
return sstream.str();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !defined CODEGEN_BASE_H
|
||||
1205
sdv_executables/sdv_dbc_util/fmu.cpp
Normal file
1205
sdv_executables/sdv_dbc_util/fmu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
398
sdv_executables/sdv_dbc_util/fmu.h
Normal file
398
sdv_executables/sdv_dbc_util/fmu.h
Normal file
@@ -0,0 +1,398 @@
|
||||
#ifndef SOFTCAR_FMU_H
|
||||
#define SOFTCAR_FMU_H
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Rpc.h>
|
||||
#endif
|
||||
|
||||
#include "../global/dbcparser/dbcparser.h"
|
||||
#include <fstream>
|
||||
#include "codegen_base.h"
|
||||
|
||||
/**
|
||||
* @brief Signal definition structure
|
||||
*/
|
||||
struct signalDefinition
|
||||
{
|
||||
std::string message_name; ///< Message name
|
||||
std::string name; ///< Signal name
|
||||
std::string attributes; ///< Attributes
|
||||
uint32_t index = 0; ///< Index
|
||||
bool isInput = false; ///< Is input signal
|
||||
bool isDouble = false; ///< for FMU we distinguish only between integer and double (float)
|
||||
uint32_t uiSize = 0; ///< everything > 8 we declare as isDouble
|
||||
dbc::SSignalDef::EValueType signalType = dbc::SSignalDef::EValueType::signed_integer; ///< Signal type
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief CAN data link generator class.
|
||||
*/
|
||||
class CSoftcarFMUGen : public CCodeGeneratorBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] rpathOutputDir Reference to the outpur directory.
|
||||
* @param[in] rparser Reference to the DBC parser containing the definitions.
|
||||
* @param[in] ssModelIdentifier Reference to the modelIdentifier of the FMU.
|
||||
* @param[in] rsVersion Reference to a string representing a version of the dbc file (could be empty).
|
||||
* @param[in] rvecNodes Reference to a list of nodes this data link object is representing. An empty list will implement
|
||||
* sending and receiving functions for all nodes.
|
||||
*/
|
||||
CSoftcarFMUGen(const std::filesystem::path& rpathOutputDir, const dbc::CDbcParser& rparser, const std::string& ssModelIdentifier, const std::string& rsVersion, const std::vector<std::string>& rvecNodes);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Keyword map for keyword replacement in a string.
|
||||
*/
|
||||
typedef std::map<std::string, std::string> CKeywordMap;
|
||||
|
||||
/**
|
||||
* @brief Add keywords to the map.
|
||||
* @param[in] rsModelIdentifier Reference to the modelIdentifier of the FMU.
|
||||
* @param[in] rsVersion Reference to a string representing a version of the dbc file (could be empty).
|
||||
* @param[in] rvecNodes Reference to a list of nodes this data link object is representing. An empty list will implement
|
||||
* @param[in] rmapKeywords Map with keywords to replace.
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
void UpdateKeywordMap(const std::string& rsModelIdentifier, const std::string& rsVersion,
|
||||
const std::vector<std::string>& rvecNodes, CKeywordMap& rmapKeywords) const;
|
||||
|
||||
/**
|
||||
* @brief Create files in the resources folder.
|
||||
* @param[in] rRootPath parent folder
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
void CreateResourcesFiles(const std::filesystem::path& rRootPath) const;
|
||||
|
||||
/**
|
||||
* @brief Create files in the source folder.
|
||||
* @param[in] rRootPath parent folder
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
void CreateSourceFiles(const std::filesystem::path& rRootPath) const;
|
||||
|
||||
/**
|
||||
* @brief Create files in the include folder.
|
||||
* @param[in] rRootPath parent folder
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
void CreateIncludeFiles(const std::filesystem::path& rRootPath) const;
|
||||
|
||||
/**
|
||||
* @brief Create files in the include folder.
|
||||
* @param[in] rRootPath parent folder
|
||||
* @param[in] rsModelIdentifier Reference to the modelIdentifier of the FMU.
|
||||
* @param[in] rmapKeywords Map with keywords to replace.
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
void CreateFMUFiles(const std::filesystem::path& rRootPath, const std::string& rsModelIdentifier, CKeywordMap& rmapKeywords) const;
|
||||
|
||||
/**
|
||||
* @brief Cleanup the directory except of the root cmake file
|
||||
* @param[in] rpathRootDirectory root folder.
|
||||
* @return Returns true if folder exists or could be created, otherwise false.
|
||||
*/
|
||||
bool CleanUpDirectory(const std::filesystem::path& rpathRootDirectory) const;
|
||||
|
||||
/**
|
||||
* @brief Create subfolder if not exists
|
||||
* @param[in] rpathRootDirectory root folder.
|
||||
* @param[in] rpathSubDirectory sub folder.
|
||||
* @return Returns true if folder exists or could be created, otherwise false.
|
||||
*/
|
||||
bool CreateDirectories(const std::filesystem::path& rpathRootDirectory, const std::filesystem::path& rpathSubDirectory) const;
|
||||
|
||||
/**
|
||||
* @brief Create content of the signal_identifier file
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string Code_AllSignalsIdentifierList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Create single signal line of the signal_identifier file
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string Code_SignalIdentifierList(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Replace keywords in a string.
|
||||
* @param[in] rsStr Reference to the string containing the keywords.
|
||||
* @param[in] rmapKeywords Map with keywords to replace.
|
||||
* @param[in] cMarker Character to identify the keyword with (placed before and after the keyword; e.g. %keyword%).
|
||||
* @return Returns the string with replacements.
|
||||
*/
|
||||
static std::string ReplaceKeywords(const std::string& rsStr, const CKeywordMap& rmapKeywords, char cMarker = '%');
|
||||
|
||||
/**
|
||||
* @brief Composes the fmi build description xml
|
||||
* @param[in] rsModelIdentifier Reference to model identifier.*
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeBuildDescriptionXML(const std::string& rsModelIdentifier) const;
|
||||
|
||||
/**
|
||||
* @brief Composes a dbc file version information string
|
||||
* @param[in] rsVersion Reference to a string representing a version of the dbc file.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeDBCFileVersion(const std::string& rsVersion) const;
|
||||
|
||||
/**
|
||||
* @brief returns a basic model identifier if not available
|
||||
* @param[in] rsModelIdentifier Reference to a string representing a version of the dbc file.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelIdentifier(const std::string& rsModelIdentifier) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the fmi xml file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeFMIFile_VariableList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the fmi xml file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeFMIFile_SignalVariableList(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the value reference in the config.h file.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rIndex Reference to the index of the variable starting with 0.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeConfigH_Rx_ValueReference(const dbc::SMessageDef& rsMsg, uint32_t& rIndex,
|
||||
std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the value reference in the config.h file.
|
||||
* @param[in] rsMsg Reference to the DBC message to provide the code for.
|
||||
* @param[in] rIndex Reference to the index of the variable starting with 0.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeConfigH_Tx_ValueReference(const dbc::SMessageDef& rsMsg, uint32_t& rIndex,
|
||||
std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the value reference in the config.h file.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the information for.
|
||||
* @param[in] index Reference to the index of the variable starting with 0.
|
||||
* @param[in] rsMessageName Reference to the message name.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeConfigH_Rx_SignalForValueReference(const dbc::SSignalDef& rsSig, const uint32_t index,
|
||||
const std::string& rsMessageName, std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the value reference in the config.h file.
|
||||
* @param[in] rsSig Reference to the DBC signal to provide the information for.
|
||||
* @param[in] index Reference to the index of the variable starting with 0.
|
||||
* @param[in] rsMessageName Reference to the message name.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeConfigH_Tx_SignalForValueReference(const dbc::SSignalDef& rsSig, const uint32_t index,
|
||||
const std::string& rsMessageName, std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the model data in the config.h file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeConfigH_ModelDataList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the model data in the config.h file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeConfigH_SignalForModelData(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the mapping trigger file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeVariableList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of variables for the mapping trigger file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeVariableName(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of global signals definitions for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalDefinitionList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get global signal definitions for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalSignalDefinition(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of registering the global signals for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalRegisterList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Check list of registered global signals for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalRegisterCheckList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get registering the a global signal for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalRegisterSignal(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get check of a global signal for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @param[in] first should be true for the first call, otherwise false.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalRegisterSignalCheck(const signalDefinition& rSignal, bool first) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of resetting the global signals for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalResetList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get resetting the a global signal for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GlobalResetSignal(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of signals for the update event for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_EventUpdateList(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get Signal for writing int the update event method for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_EventUpdateSignalDefinitionWrite(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get Signal for reading the update event method for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_EventUpdateSignalDefinitionRead(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of signals for the GetFloat64 method for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GetFloat64(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of signals for the GetInt32 method for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GetInt32(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of signals for the SetFloat64 method for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_SetFloat64(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get List of signals for the SetInt32 method for the model.cpp file.
|
||||
* @param[in] rvecSignalDefinitions Reference to the container for all signal definitions.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_SetInt32(const std::vector<signalDefinition>& rvecSignalDefinitions) const;
|
||||
|
||||
/**
|
||||
* @brief Get Signal for GetFloat64 method for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GetFloat64SignalDefinition(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get Signal for GetInt32 method for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_GetInt32SignalDefinition(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get Signal for SetFloat64 method for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_SetFloat64SignalDefinition(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get Signal for SetInt32 method for the model.cpp file.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_SetInt32SignalDefinition(const signalDefinition& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get comment for the OpenAPILoad function for the model.cpp file.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeModelCPP_OpenAPILoadFunction() const;
|
||||
|
||||
/**
|
||||
* @brief Get default value of a tx signal. Used as start value un the build description.
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string CodeGetDefaultValueOfTxSignal(const dbc::SSignalDef& rSignal) const;
|
||||
|
||||
/**
|
||||
* @brief Get minimum and maximum of a signal
|
||||
* @param[in] rSignal Reference to the signal definition.
|
||||
* @param[in] isDouble Reference to bool variable. Signal is either integer or double.
|
||||
* @return The code to insert.
|
||||
*/
|
||||
std::string GetAttributes(const dbc::SSignalDef& rSignal, const bool& isDouble) const;
|
||||
|
||||
/**
|
||||
* @brief returns guid string
|
||||
* @return The guid.
|
||||
*/
|
||||
std::string newUUID() const;
|
||||
|
||||
const dbc::CDbcParser& m_rparser; ///< Reference to the DBC parser.
|
||||
};
|
||||
|
||||
#endif // !defined SOFTCAR_FMU_H
|
||||
2512
sdv_executables/sdv_dbc_util/fmu_fmi_templates.h
Normal file
2512
sdv_executables/sdv_dbc_util/fmu_fmi_templates.h
Normal file
File diff suppressed because it is too large
Load Diff
550
sdv_executables/sdv_dbc_util/fmu_templates.h
Normal file
550
sdv_executables/sdv_dbc_util/fmu_templates.h
Normal file
@@ -0,0 +1,550 @@
|
||||
|
||||
/**
|
||||
* @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";
|
||||
|
||||
103
sdv_executables/sdv_dbc_util/main.cpp
Normal file
103
sdv_executables/sdv_dbc_util/main.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "../../global/process_watchdog.h"
|
||||
#include <interfaces/core.h>
|
||||
#include <interfaces/mem.h>
|
||||
#include "../../global/cmdlnparser/cmdlnparser.cpp"
|
||||
#include "../../global/dbcparser/dbcparser.cpp"
|
||||
#include "../../global/localmemmgr.h"
|
||||
#include <iostream>
|
||||
#include "can_dl.h"
|
||||
#include "fmu.h"
|
||||
#include "cmake_generator.h"
|
||||
#include "../error_msg.h"
|
||||
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
extern "C" int wmain(int iArgc, const wchar_t* rgszArgv[])
|
||||
#else
|
||||
extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
#endif
|
||||
{
|
||||
// Workaround for GCC to make certain that POSIX thread library is loaded before the components are loaded.
|
||||
// REASON: If the first call to a thread is done in a dynamic library, the application is already classified as single
|
||||
// threaded and a termination is initiated.
|
||||
// See: https://stackoverflow.com/questions/51209268/using-stdthread-in-a-library-loaded-with-dlopen-leads-to-a-sigsev
|
||||
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
// Suppress the warning supplied by ccpcheck about an unsused variable. The memory manager registers itself into the system and
|
||||
// needs to stay in scope.
|
||||
// cppcheck-suppress unusedVariable
|
||||
CLocalMemMgr memmgr;
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bError = false;
|
||||
bool bSilent = false;
|
||||
bool bVerbose = false;
|
||||
size_t nIfcIndex = 0;
|
||||
std::string ssIfcName;
|
||||
std::string ssVersion;
|
||||
std::string ssModelIdentifier;
|
||||
std::string ssDataLinkLibName = "can_dl";
|
||||
std::vector<std::filesystem::path> vecFileNames;
|
||||
std::vector<std::string> vecNodes;
|
||||
std::filesystem::path pathOutputDir;
|
||||
try
|
||||
{
|
||||
auto& rArgHelpDef = cmdln.DefineOption("?", bHelp, "Show help");
|
||||
rArgHelpDef.AddSubOptionName("help");
|
||||
auto& rArgSilentDef = cmdln.DefineOption("s", bSilent, "Do not show any information on STDOUT. Not compatible with 'verbose'.");
|
||||
rArgSilentDef.AddSubOptionName("silent");
|
||||
auto& rArgVerboseDef = cmdln.DefineOption("v", bVerbose, "Provide verbose information. Not compatible with 'silent'.");
|
||||
rArgVerboseDef.AddSubOptionName("verbose");
|
||||
cmdln.DefineSubOption("version", ssVersion, "Optional: version information of the dbc file.");
|
||||
cmdln.DefineSubOption("module", ssModelIdentifier, "Optional: module identifier for the fmu. Default 'BasicModelIdentifier'");
|
||||
cmdln.DefineSubOption("dl_lib_name", ssDataLinkLibName, "Data link library target name in the generated cmake file (default=\"can_dl\")..");
|
||||
cmdln.DefineOption("O", pathOutputDir, "Set output directory");
|
||||
cmdln.DefineSubOption("ifc_idx", nIfcIndex, "Interface index this DBC file is aiming for.");
|
||||
cmdln.DefineSubOption("ifc_name", ssIfcName, "Name of the interface this DBC file is aiming for.");
|
||||
cmdln.DefineSubOption("nodes", vecNodes, "List of nodes that will be implemented.");
|
||||
cmdln.DefineDefaultArgument(vecFileNames, "One or more DBC files");
|
||||
cmdln.Parse(static_cast<size_t>(iArgc), rgszArgv);
|
||||
} catch (const SArgumentParseException& rsExcept)
|
||||
{
|
||||
std::cout << "ERROR: " << rsExcept.what() << std::endl;
|
||||
bHelp = true;
|
||||
bError = true;
|
||||
}
|
||||
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "DBC utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl;
|
||||
}
|
||||
if (bHelp)
|
||||
{
|
||||
if (!bSilent)
|
||||
cmdln.PrintHelp(std::cout);
|
||||
return bError ? CMDLN_ARG_ERR : NO_ERROR;
|
||||
}
|
||||
|
||||
dbc::CDbcParser parser;
|
||||
for (const std::filesystem::path& rpath : vecFileNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (bVerbose)
|
||||
std::cout << "Processing: " << rpath.generic_u8string() << std::endl;
|
||||
dbc::CDbcSource src(rpath);
|
||||
parser.Parse(src);
|
||||
CSoftcarFMUGen fmu(pathOutputDir, parser, ssModelIdentifier, ssVersion, vecNodes);
|
||||
CCanDataLinkGen dl(pathOutputDir, parser, ssVersion, ssIfcName, nIfcIndex, vecNodes);
|
||||
CDbcUtilCMakeGenerator cmakegen(pathOutputDir, ssDataLinkLibName);
|
||||
}
|
||||
catch (dbc::SDbcParserException& rsException)
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cout << "ERROR " << LOAD_DBC_FILE_ERROR_MSG << " Reason: " << rsException.what() << std::endl;
|
||||
return LOAD_DBC_FILE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
Reference in New Issue
Block a user