mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-04-21 03:38:15 +00:00
tunnel component & update vehicle abstraction example (#8)
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
********************************************************************************/
|
||||
|
||||
#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_sSubTitle1{ 2, 1 };
|
||||
const CConsole::SConsolePos g_sSubTitle2{3, 1};
|
||||
const CConsole::SConsolePos g_sSeparator1{ 5, 1 };
|
||||
const CConsole::SConsolePos g_sDataUnit{ 7, 1 };
|
||||
const CConsole::SConsolePos g_sDataLinkSpeed{ 8, 1 };
|
||||
const CConsole::SConsolePos g_sSeparator2{ 10, 1 };
|
||||
const CConsole::SConsolePos g_sDeviceServiceSpeed{ 12, 1 };
|
||||
const CConsole::SConsolePos g_sSeparator3{ 14, 1 };
|
||||
const CConsole::SConsolePos g_sBasicServiceSpeed{ 16, 1 };
|
||||
const CConsole::SConsolePos g_sSeparator4{ 18, 1 };
|
||||
const CConsole::SConsolePos g_sComment1{ 20, 1 };
|
||||
const CConsole::SConsolePos g_sComment2{ 21, 1 };
|
||||
const CConsole::SConsolePos g_sComment3{ 23, 1 };
|
||||
const CConsole::SConsolePos g_sComment4{ 24, 1 };
|
||||
const CConsole::SConsolePos g_sComment5{ 25, 1 };
|
||||
const CConsole::SConsolePos g_sComment6{ 27, 1 };
|
||||
const CConsole::SConsolePos g_sComment7{ 28, 1 };
|
||||
const CConsole::SConsolePos g_sSeparator5{ 30, 1 };
|
||||
|
||||
const CConsole::SConsolePos g_sControlDescription{ 32, 1 };
|
||||
const CConsole::SConsolePos g_sCursor{ 33, 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()
|
||||
{
|
||||
// Clear the screen...
|
||||
std::cout << "\x1b[2J";
|
||||
|
||||
// Print the titles
|
||||
PrintText(g_sTitle, "Vehicle Abstraction: ");
|
||||
PrintText(g_sSubTitle1, "This example demonstrates that the vehicle function implementation is independent of the vehicle itself.");
|
||||
PrintText(g_sSubTitle2, "CAN bus vehicle 1 => km/h, CAN bus vehicle 2 => m/s.");
|
||||
PrintText(g_sSeparator1, "====================================================================================================================");
|
||||
PrintText(g_sDataUnit, m_DataUnit);
|
||||
PrintText(g_sDataLinkSpeed, "Data Link not available.");
|
||||
PrintText(g_sSeparator2, "--------------------------------------------------------------------------------------------------------------------");
|
||||
PrintText(g_sDeviceServiceSpeed, "Platform Abstraction Interface not available.");
|
||||
PrintText(g_sSeparator3, "--------------------------------------------------------------------------------------------------------------------");
|
||||
PrintText(g_sBasicServiceSpeed, "Basic Service Interface not available.");
|
||||
PrintText(g_sSeparator4, "====================================================================================================================");
|
||||
PrintText(g_sComment1, "The dispatch service displays the value that is written by the CAN message read from the ASC file.");
|
||||
PrintText(g_sComment2, "The speed should be increased by steps of 10 km/h.");
|
||||
PrintText(g_sComment3, "The 'Platform Abstraction' component is responsible for the vehicle abstraction and converts the value if necessary.");
|
||||
PrintText(g_sComment4, "The example contains 2 components for 'Platform Abstraction' with identical output interfaces.");
|
||||
PrintText(g_sComment5, "Depending on the input (m/s or km/h) the correct 'Platform Abstraction' component must be loaded.");
|
||||
PrintText(g_sComment6, "Therefore, only one speed sensor component is required, which always receives the speed in km/h.");
|
||||
PrintText(g_sComment7, "The vehicle function does not require any logic that depends on the specific vehicle.");
|
||||
PrintText(g_sSeparator5, "====================================================================================================================");
|
||||
PrintText(g_sControlDescription, "Press 'X' to quit;");
|
||||
}
|
||||
|
||||
bool CConsole::PrepareDataConsumers()
|
||||
{
|
||||
sdv::core::CDispatchService dispatch;
|
||||
m_SignalSpeed = dispatch.Subscribe(abstraction::dsVehicleSpeed, [&](sdv::any_t value) { CallbackSpeed(value); });
|
||||
if (m_SignalSpeed)
|
||||
{
|
||||
auto unit = m_Unit;
|
||||
unit.append(" [ data dispatch service - input from CAN bus ] ");
|
||||
PrintValue(g_sDataLinkSpeed, "Vehicle Speed RX", m_SpeedDataLink, unit);
|
||||
}
|
||||
|
||||
auto deviceServiceSpeed = sdv::core::GetObject("Vehicle.Speed_Device").GetInterface<vss::Vehicle::SpeedDevice::IVSS_ReadSpeed>();
|
||||
if (deviceServiceSpeed)
|
||||
{
|
||||
PrintValue(g_sDeviceServiceSpeed, "Vehicle Speed RX", m_PlatformSpeed, "km/h [ Output of Platform Abstraction, not accessible by application ] ");
|
||||
deviceServiceSpeed->RegisterSpeedEvent(dynamic_cast<vss::Vehicle::SpeedDevice::IVSS_WriteSpeed_Event*> (this));
|
||||
}
|
||||
|
||||
auto basicServiceSpeed = sdv::core::GetObject("Vehicle.Speed_Service").GetInterface<vss::Vehicle::SpeedService::IVSS_GetSpeed>();
|
||||
if (basicServiceSpeed)
|
||||
{
|
||||
PrintValue(g_sBasicServiceSpeed, "Vehicle Speed RX", m_BasicSpeed, "km/h [ Output of Speed Sensor Service, accessible by application ] ");
|
||||
basicServiceSpeed->RegisterOnSignalChangeOfVehicleSpeed(dynamic_cast<vss::Vehicle::SpeedService::IVSS_SetSpeed_Event*> (this));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CConsole::WriteSpeed( float value)
|
||||
{
|
||||
if (m_PlatformSpeed != value)
|
||||
{
|
||||
m_PlatformSpeed = value;
|
||||
PrintValue(g_sDeviceServiceSpeed, "Vehicle Speed RX", m_PlatformSpeed, "km/h [ Output of Platform Abstraction, not accessible by application ] ");
|
||||
}
|
||||
}
|
||||
|
||||
void CConsole::SetSpeed( float value)
|
||||
{
|
||||
if (m_BasicSpeed != value)
|
||||
{
|
||||
m_BasicSpeed= value;
|
||||
PrintValue(g_sBasicServiceSpeed, "Vehicle Speed RX", m_BasicSpeed, "km/h [ Output of Speed Sensor Service, accessible by application ] ");
|
||||
}
|
||||
}
|
||||
|
||||
void CConsole::ResetSignals()
|
||||
{
|
||||
// Set the cursor position at the end
|
||||
SetCursorPos(g_sCursor);
|
||||
|
||||
auto deviceServiceSpeed = sdv::core::GetObject("Vehicle.Speed_Devicee").GetInterface<vss::Vehicle::SpeedDevice::IVSS_ReadSpeed>();
|
||||
if (deviceServiceSpeed)
|
||||
{
|
||||
deviceServiceSpeed->UnregisterSpeedEvent(dynamic_cast<vss::Vehicle::SpeedDevice::IVSS_WriteSpeed_Event*> (this));
|
||||
}
|
||||
|
||||
auto basicServiceSpeed = sdv::core::GetObject("Vehicle.Speed_Service").GetInterface<vss::Vehicle::SpeedService::IVSS_GetSpeed>();
|
||||
if (basicServiceSpeed)
|
||||
{
|
||||
basicServiceSpeed->UnregisterOnSignalChangeOfVehicleSpeed(dynamic_cast<vss::Vehicle::SpeedService::IVSS_SetSpeed_Event*> (this));
|
||||
}
|
||||
|
||||
if (m_SignalSpeed)
|
||||
m_SignalSpeed.Reset();
|
||||
}
|
||||
|
||||
void CConsole::CallbackSpeed(sdv::any_t value)
|
||||
{
|
||||
if (m_SpeedDataLink != value.get<float>())
|
||||
{
|
||||
m_SpeedDataLink = value.get<float>();
|
||||
|
||||
auto unit = m_Unit;
|
||||
unit.append(" [ data dispatch service - input from CAN bus ] ");
|
||||
PrintValue(g_sDataLinkSpeed, "Vehicle Speed RX", m_SpeedDataLink, unit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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() < 76)
|
||||
text.append(" ");
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mtxPrintToConsole);
|
||||
SetCursorPos(sPos);
|
||||
std::cout << text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CConsole::KeyHit()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _kbhit();
|
||||
#elif __unix__
|
||||
int ch = getchar();
|
||||
if (ch != EOF) {
|
||||
ungetc(ch, stdin);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
char CConsole::GetChar()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return static_cast<char>(_getch());
|
||||
#else
|
||||
return getchar();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CConsole::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 CConsole::SelectInputDataUnits()
|
||||
{
|
||||
// Clear the screen and goto top...
|
||||
std::cout << "\x1b[2J\033[0;0H";
|
||||
std::cout << "Click '1' to select km/h or '2' to select m/s";
|
||||
|
||||
bool bIsKmh = false;
|
||||
char c = '0';
|
||||
while(c != '1' && c != '2')
|
||||
{
|
||||
c = GetChar();
|
||||
switch (c)
|
||||
{
|
||||
case '1':
|
||||
m_DataUnit = "[ --- Input data in km/h --- ]";
|
||||
m_Unit = "km/h";
|
||||
bIsKmh = true;
|
||||
break;
|
||||
case '2':
|
||||
m_DataUnit = "[ --- Input data in m/s --- ]";
|
||||
m_Unit = "m/s";
|
||||
bIsKmh = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bIsKmh;
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
********************************************************************************/
|
||||
|
||||
#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 "../generated/vss_files/signal_identifier.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../generated/vss_files/vss_vehiclespeed_vd_rx.h"
|
||||
#include "../generated/vss_files/vss_vehiclespeed_bs_rx.h"
|
||||
|
||||
#ifdef __unix__
|
||||
#include <termios.h> // Needed for tcgetattr and fcntl
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Console operation class.
|
||||
* @details This class retrieves RX data from the data dispatch service, platform abstraction & basic service of speed on event change.
|
||||
* Furthermore, it shows TX value by polling the RX signals.
|
||||
*/
|
||||
class CConsole : public vss::Vehicle::SpeedDevice::IVSS_WriteSpeed_Event
|
||||
, public vss::Vehicle::SpeedService::IVSS_SetSpeed_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.
|
||||
*/
|
||||
void PrintHeader();
|
||||
|
||||
/**
|
||||
* @brief Prepare the data consumers..
|
||||
* @return Returns whether the preparation of the data consumers was successful or not.
|
||||
*/
|
||||
bool PrepareDataConsumers();
|
||||
|
||||
/**
|
||||
* @brief Run loop as long as user input does not exit
|
||||
*/
|
||||
void RunUntilBreak();
|
||||
|
||||
/**
|
||||
* @brief Let the user decide which unit the input data should have
|
||||
* @return Return true if inout data should be km/h, otherwise false
|
||||
*/
|
||||
bool SelectInputDataUnits();
|
||||
|
||||
/**
|
||||
* @brief Write vehicleSpeed signal
|
||||
* @param[in] value vehicleSpeed
|
||||
*/
|
||||
void WriteSpeed( float value) override;
|
||||
|
||||
/**
|
||||
* @brief Set vehicleSpeed signal
|
||||
* @param[in] value vehicleSpeed
|
||||
*/
|
||||
void SetSpeed( float value) override;
|
||||
|
||||
/**
|
||||
* @brief For gracefully shutdown all signals need to be reset.
|
||||
*/
|
||||
void ResetSignals();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Callback function for speed.
|
||||
* @param[in] value The value of the signal to update.
|
||||
*/
|
||||
void CallbackSpeed(sdv::any_t value);
|
||||
|
||||
/**
|
||||
* @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 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, because 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_bRunning = false; ///< When set, the application is running.
|
||||
std::string m_DataUnit = "[ --- Input data in m/s --- ]";
|
||||
std::string m_Unit = "m/s";
|
||||
|
||||
sdv::core::CSignal m_SignalSpeed; ///< Signal to subscribe to the speed signal in dispatch service
|
||||
|
||||
float m_SpeedDataLink = 0.0; ///< Data Link value, either km/h or m/s
|
||||
float m_PlatformSpeed = 0.0; ///< Generalized Speed
|
||||
float m_BasicSpeed = 0.0; ///< Generalized Speed
|
||||
|
||||
#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)
|
||||
{
|
||||
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::lock_guard<std::mutex> lock(m_mtxPrintToConsole);
|
||||
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
|
||||
@@ -0,0 +1,103 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
********************************************************************************/
|
||||
|
||||
#include "vehicle_abstraction_application.h"
|
||||
#include "../generated/vss_files/signal_identifier.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <conio.h> // Needed for _kbhit
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
bool CAbstractionControl::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 CAbstractionControl::IsSDVFrameworkEnvironmentSet()
|
||||
{
|
||||
const char* envVariable = std::getenv("SDV_FRAMEWORK_RUNTIME");
|
||||
if (envVariable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAbstractionControl::Initialize(bool bSimulate)
|
||||
{
|
||||
if (m_bInitialized)
|
||||
return true;
|
||||
|
||||
m_bSimulate = bSimulate;
|
||||
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;
|
||||
|
||||
m_appcontrol.SetConfigMode();
|
||||
bool bResult = LoadConfigFile("Load dispatch service: ", "data_dispatch_vehicle_abstraction.toml");
|
||||
bResult &= LoadConfigFile("Load task_timer_vehicle: ", "task_timer_vehicle.toml");
|
||||
|
||||
if (bSimulate)
|
||||
{
|
||||
bResult &= LoadConfigFile("Load can_com_simulation_vehicle_abstraction_kmh: ", "can_com_simulation_vehicle_abstraction_kmh.toml");
|
||||
bResult &= LoadConfigFile("Load data_link_vehicle_abstraction: ", "data_link_vehicle_abstraction.toml");
|
||||
bResult &= LoadConfigFile("Load vehicle_abstraction_kmh: ", "vehicle_abstraction_device_kmh.toml");
|
||||
}
|
||||
else
|
||||
{
|
||||
bResult &= LoadConfigFile("Load can_com_simulation_vehicle_abstraction_ms: ", "can_com_simulation_vehicle_abstraction_ms.toml");
|
||||
bResult &= LoadConfigFile("Load data_link_vehicle_abstraction: ", "data_link_vehicle_abstraction.toml");
|
||||
bResult &= LoadConfigFile("Load vehicle_abstraction_ms: ", "vehicle_abstraction_device_ms.toml");
|
||||
}
|
||||
|
||||
bResult &= LoadConfigFile("Load vehicle_abstraction_basic_service: ", "vehicle_abstraction_basic_service.toml");
|
||||
|
||||
if (!bResult)
|
||||
{
|
||||
SDV_LOG_ERROR("One or more configurations could not be loaded. Cannot continue.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CAbstractionControl::Shutdown()
|
||||
{
|
||||
if (!m_bInitialized)
|
||||
m_appcontrol.Shutdown();
|
||||
m_bInitialized = false;
|
||||
}
|
||||
|
||||
void CAbstractionControl::SetRunningMode()
|
||||
{
|
||||
m_appcontrol.SetRunningMode();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <support/app_control.h>
|
||||
#include <support/signal_support.h>
|
||||
|
||||
/**
|
||||
* @brief Application Class of the vehicle abstraction example
|
||||
*/
|
||||
class CAbstractionControl
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Start and initialize the application control and load
|
||||
* platform abstraction components and basic services
|
||||
* @param[in] bSimulate If signals should be simulated or CAN input signals should be used
|
||||
* @return Return true on success otherwise false
|
||||
*/
|
||||
bool Initialize(bool bSimulate);
|
||||
|
||||
/**
|
||||
* @brief After initialization/configuration the system mode needs to be set to running mode
|
||||
*/
|
||||
void SetRunningMode();
|
||||
|
||||
/**
|
||||
* @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 Load config file and register vehicle device and basic service.
|
||||
* @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);
|
||||
|
||||
sdv::app::CAppControl m_appcontrol; ///< App-control of SDV V-API.
|
||||
bool m_bInitialized = false; ///< Set when initialized.
|
||||
|
||||
bool m_bSimulate = false;
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
********************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib> // for std::strtol
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <ostream>
|
||||
#include "vehicle_abstraction_application.h"
|
||||
#include "console.h"
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
extern "C" int wmain([[maybe_unused]] int argc, [[maybe_unused]] wchar_t* argv[])
|
||||
{
|
||||
#else
|
||||
extern "C" int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
|
||||
{
|
||||
#endif
|
||||
CConsole visual_obj;
|
||||
CAbstractionControl appobj;
|
||||
if (!appobj.Initialize(visual_obj.SelectInputDataUnits()))
|
||||
{
|
||||
std::cout << "ERROR: Failed to initialize application control." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
visual_obj.PrintHeader();
|
||||
visual_obj.PrepareDataConsumers();
|
||||
|
||||
appobj.SetRunningMode();
|
||||
|
||||
visual_obj.RunUntilBreak();
|
||||
|
||||
visual_obj.ResetSignals();
|
||||
|
||||
appobj.Shutdown();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user