Compare commits
12 Commits
try-smart-
...
4f1af0f4ae
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f1af0f4ae | |||
| 3e9c1cc20b | |||
| e118fa4a20 | |||
| 2c9e9be6b3 | |||
| c36e9053c4 | |||
| 193579e798 | |||
| 3a132bb584 | |||
| 68680db6b4 | |||
| 56ab0fbc0f | |||
| 61bf3b2cec | |||
| c5dc84179b | |||
| 6032abb35c |
@@ -27,16 +27,16 @@ windows
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
aalegacy.cpp \
|
||||
bc.cpp \
|
||||
bcanimateddelegate.cpp \
|
||||
bcdeviceview.cpp \
|
||||
bcdriver.cpp \
|
||||
bcdrivertinycan.cpp \
|
||||
bclegacy.cpp \
|
||||
bcguihelpers.cpp \
|
||||
bctransmitter.cpp \
|
||||
bcvalue.cpp \
|
||||
bcvaluemodel.cpp \
|
||||
bcvaluetype.cpp \
|
||||
bcxmlloader.cpp \
|
||||
lib/can_drv_win.c \
|
||||
main.cpp \
|
||||
@@ -48,11 +48,11 @@ HEADERS += \
|
||||
bcdeviceview.h \
|
||||
bcdriver.h \
|
||||
bcdrivertinycan.h \
|
||||
bcguihelpers.h \
|
||||
bcmainwindow.h \
|
||||
bctransmitter.h \
|
||||
bcvalue.h \
|
||||
bcvaluemodel.h \
|
||||
bcvaluetype.h \
|
||||
bcxmlloader.h
|
||||
|
||||
FORMS += \
|
||||
|
||||
@@ -185,102 +185,7 @@ double gSetSpeedLimit = -1, gSetMinSpeedLimit = -1, gSetThrottleSpeedLimit = -1;
|
||||
#define BATTERY 3
|
||||
#define BIB 4
|
||||
|
||||
/*
|
||||
class ThemeSwitchButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ThemeSwitchButton(QWidget *parent = nullptr)
|
||||
: QPushButton(parent), m_isDarkMode(true)
|
||||
{
|
||||
// 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
setFixedSize(32, 24); // Kleiner Footprint im StatusBar
|
||||
|
||||
// CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt
|
||||
// Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind
|
||||
setStyleSheet(R"(
|
||||
QPushButton {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 14pt;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
|
||||
border-radius: 4px;
|
||||
}
|
||||
)");
|
||||
|
||||
// 2. Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
||||
updateIcon();
|
||||
|
||||
// 3. Klick verbinden
|
||||
connect(this, &QPushButton::clicked, this, &ThemeSwitchButton::toggle);
|
||||
}
|
||||
|
||||
signals:
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
void toggle() {
|
||||
m_isDarkMode = !m_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(m_isDarkMode);
|
||||
}
|
||||
|
||||
private:
|
||||
void updateIcon() {
|
||||
// Logik:
|
||||
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
||||
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
||||
setText(m_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(m_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode");
|
||||
}
|
||||
|
||||
bool m_isDarkMode;
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
setWindowTitle("Fluent Theme Switcher");
|
||||
resize(800, 600);
|
||||
|
||||
// --- STATUSBAR SETUP ---
|
||||
QStatusBar *statBar = statusBar();
|
||||
|
||||
// Optional: Normale Nachricht links
|
||||
statBar->showMessage("Ready");
|
||||
|
||||
// 1. Unseren Switcher erstellen
|
||||
ThemeSwitchButton *themeBtn = new ThemeSwitchButton(this);
|
||||
|
||||
// 2. WICHTIG: Rechts hinzufügen
|
||||
statBar->addPermanentWidget(themeBtn);
|
||||
|
||||
// 3. Signal verbinden: Button klick -> Theme ändern
|
||||
connect(themeBtn, &ThemeSwitchButton::themeChanged, this, [this](bool isDark){
|
||||
if (isDark) {
|
||||
applyFluentDarkTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Dark Mode Activated", 3000);
|
||||
} else {
|
||||
applyFluentLightTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Light Mode Activated", 3000);
|
||||
}
|
||||
});
|
||||
|
||||
// Initiale Anwendung (Dark Mode)
|
||||
applyFluentDarkTheme(*qApp);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
char *getNodeName(unsigned char id)
|
||||
{
|
||||
@@ -727,24 +632,30 @@ int xmain(int argc, char **argv)
|
||||
CanSetMode(0, OP_CAN_START, CAN_CMD_ALL_CLEAR);
|
||||
CanGetDeviceStatus(0, &status);
|
||||
|
||||
if (status.DrvStatus >= DRV_STATUS_CAN_OPEN) {
|
||||
if (status.CanStatus == CAN_STATUS_BUS_OFF) {
|
||||
if (status.DrvStatus >= DRV_STATUS_CAN_OPEN)
|
||||
{
|
||||
if (status.CanStatus == CAN_STATUS_BUS_OFF)
|
||||
{
|
||||
printf("CAN Status BusOff" _NL);
|
||||
CanSetMode(0, OP_CAN_RESET, CAN_CMD_NONE);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("error: could not open device" _NL);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
|
||||
if (consoleInSlaveMode) {
|
||||
|
||||
if (consoleInSlaveMode)
|
||||
{
|
||||
printf("console already in salve mode. good!" _NL _NL);
|
||||
} else {
|
||||
if (gConsoleSetSlaveMode) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gConsoleSetSlaveMode)
|
||||
{
|
||||
int retry = 20;
|
||||
|
||||
printf("putting console in salve mode ... ");
|
||||
@@ -756,16 +667,21 @@ int xmain(int argc, char **argv)
|
||||
|
||||
doSleep(500); // give the console some time to settle
|
||||
printf("%s" _NL _NL, consoleInSlaveMode ? "done" : "failed");
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("console not in slave mode" _NL _NL);
|
||||
}
|
||||
}
|
||||
|
||||
if (gAssistInitLevel != -1) {
|
||||
if (gAssistInitLevel != -1)
|
||||
{
|
||||
printf("setting initial assistance level to %d" _NL, gAssistInitLevel);
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL, gAssistInitLevel);
|
||||
}
|
||||
|
||||
if (gSetSpeedLimit > 0) {
|
||||
if (gSetSpeedLimit > 0)
|
||||
{
|
||||
printf("set speed limit to %0.2f km/h" _NL, gSetSpeedLimit);
|
||||
setSpeedLimit(gSetSpeedLimit);
|
||||
doShutdown = 1;
|
||||
2
bc.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
9
bc.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -773,15 +773,16 @@ namespace BCTags
|
||||
inline constexpr auto Device = "Device"_L1;
|
||||
inline constexpr auto ID = "ID"_L1;
|
||||
inline constexpr auto Label = "Label"_L1;
|
||||
inline constexpr auto UnitLabel = "UnitLabel"_L1;
|
||||
inline constexpr auto IsWord = "IsWord"_L1;
|
||||
inline constexpr auto Default = "Default"_L1;
|
||||
|
||||
inline constexpr auto Current = "Current"_L1;
|
||||
inline constexpr auto Enabled = "Enabled"_L1;
|
||||
inline constexpr auto UnitType = "UnitType"_L1;
|
||||
inline constexpr auto ValueType = "ValueType"_L1;
|
||||
inline constexpr auto Min = "Min"_L1;
|
||||
inline constexpr auto Max = "Max"_L1;
|
||||
inline constexpr auto Factor = "Factor"_L1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // BC_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -79,7 +79,7 @@ void BCDeviceView::onValueListReady( BCDevice::ID deviceID, BCValueList valueLis
|
||||
|
||||
void BCDeviceView::onValueUpdated(int index, BCValue::State state, const QString& newVisibleValue )
|
||||
{
|
||||
_valueModel.onValueUpdated( index,state,newVisibleValue);
|
||||
_valueModel.onValueUpdated( index, state, newVisibleValue);
|
||||
_itemDelegate->onHighlightRow( index );
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
43
bcdriver.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -37,12 +37,6 @@
|
||||
|
||||
|
||||
|
||||
BCDriver::BCDriver(QObject* parent )
|
||||
: QObject{ parent }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BCDriver::DriverState BCDriver::getDriverState() const
|
||||
{
|
||||
return _driverState;
|
||||
@@ -59,47 +53,16 @@ BCDriver::DriverState BCDriver::getDriverState() const
|
||||
* aber die Console noch nicht eingeschaltet war.
|
||||
*/
|
||||
|
||||
void BCDriverDummy::onStartDriver()
|
||||
BCDriver::DriverStateResult BCDriverDummy::loadAndStartDriver()
|
||||
{
|
||||
_driverState = DriverState::DeviceReady;
|
||||
emit driverStateChanged( DriverState::DeviceReady, "Driver Ready." );
|
||||
return _driverState;
|
||||
}
|
||||
// __Fix
|
||||
/*
|
||||
try
|
||||
{
|
||||
|
||||
// erstmal die Dll Laden: State::sIdle -> State::sLoaded
|
||||
if( _driverState == DriverState::NotPresent)
|
||||
_driverState = loadAndInitDriver();
|
||||
|
||||
emit stateChanged( _driverState );
|
||||
|
||||
}
|
||||
catch( std::exception& except )
|
||||
{
|
||||
//::CanDownDriver();
|
||||
//::UnloadAndInitDriver();
|
||||
|
||||
emit statusHint( except.what() );
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief BCDriverDummy::BCDriverDummy
|
||||
* @param parent
|
||||
*/
|
||||
|
||||
BCDriverDummy::BCDriverDummy( QObject* parent )
|
||||
: BCDriver(parent)
|
||||
{
|
||||
}
|
||||
|
||||
TransmitResult BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID ) const
|
||||
{
|
||||
|
||||
32
bcdriver.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <QObject>
|
||||
#include <expected>
|
||||
#include <bcvalue.h>
|
||||
#include <bcvaluetype.h>
|
||||
|
||||
/*
|
||||
int32_t CanInitDriver(char *options);
|
||||
void CanDownDriver(void);
|
||||
@@ -84,16 +84,16 @@ class BCDriverStatus;
|
||||
*/
|
||||
|
||||
|
||||
class BCDriver : public QObject
|
||||
class BCDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
|
||||
// Die möglichen Zustände beim Laden
|
||||
// des CAN-Bus Treibers.
|
||||
|
||||
enum class DriverState
|
||||
enum class DriverState : uint8_t
|
||||
{
|
||||
NotPresent,
|
||||
Error,
|
||||
@@ -107,9 +107,11 @@ public:
|
||||
// Enthält den Treiberzustand oder einen Fehlerstring
|
||||
using DriverStateResult = std::expected<DriverState,QString>;
|
||||
|
||||
explicit BCDriver( QObject* parent = nullptr );
|
||||
explicit BCDriver() = default;
|
||||
virtual ~BCDriver() = default;
|
||||
|
||||
virtual BCDriver::DriverStateResult loadAndStartDriver() = 0;
|
||||
|
||||
// Gibt den aktuelle Zustand des Treibers zurück. Der DriverState
|
||||
// muss auf DeviceReady stehen, um Werte lesen & schreiben zu können.
|
||||
// Dazu muss das Bionx-System eingeschaltet sein.
|
||||
@@ -122,14 +124,6 @@ public:
|
||||
virtual TransmitResult readRawByte ( uint32_t deviceID, uint8_t registerID ) const = 0;
|
||||
virtual TransmitResult writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const = 0;
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void onStartDriver() = 0;
|
||||
|
||||
signals:
|
||||
|
||||
void driverStateChanged( DriverState state, const QString& message="" ) const;
|
||||
|
||||
protected:
|
||||
|
||||
DriverState _driverState{DriverState::NotPresent};
|
||||
@@ -137,20 +131,22 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class BCDriverDummy : public BCDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCDriverDummy( QObject* parent = nullptr );
|
||||
BCDriver::DriverStateResult loadAndStartDriver() override;
|
||||
|
||||
TransmitResult readRawByte( uint32_t deviceID, uint8_t registerID ) const override;
|
||||
TransmitResult writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void onStartDriver() override;
|
||||
};
|
||||
|
||||
#endif // BCDRIVER_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -36,44 +36,56 @@
|
||||
#include <can_drv.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Destruktor. Entlädt den CAN-Bus Treiber wieder.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
BCDriverTinyCan::BCDriverTinyCan( QObject* parent )
|
||||
: BCDriver(parent )
|
||||
BCDriverTinyCan::~BCDriverTinyCan()
|
||||
{
|
||||
|
||||
resetDriver();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BCDriverTinyCan::loadAndStartDriver
|
||||
* @return
|
||||
*/
|
||||
|
||||
void BCDriverTinyCan::onStartDriver()
|
||||
BCDriver::DriverStateResult BCDriverTinyCan::loadAndStartDriver()
|
||||
{
|
||||
DriverStateResult result;
|
||||
if( _driverState < DriverState::Opened)
|
||||
loadDriver();
|
||||
result = loadDriver();
|
||||
if( _driverState == DriverState::Opened)
|
||||
_driverState = connectDriver();
|
||||
result = setConsoleSlaveMode();
|
||||
return result;
|
||||
}
|
||||
|
||||
void BCDriverTinyCan::loadDriver()
|
||||
/**
|
||||
* @brief BCDriverTinyCan::loadDriver
|
||||
* @return
|
||||
*/
|
||||
|
||||
BCDriver::DriverStateResult BCDriverTinyCan::loadDriver()
|
||||
{
|
||||
|
||||
|
||||
auto callLoadDriver = []() -> DriverStateResult
|
||||
auto callLoadDriver = [&]() -> DriverStateResult
|
||||
{
|
||||
if( ::LoadDriver( NULL ) < 0 )
|
||||
return std::unexpected(QString("Driver Error: 'LoadDriver'"));
|
||||
return DriverState::Loaded;
|
||||
_driverState = DriverState::Loaded;
|
||||
return _driverState;
|
||||
};
|
||||
|
||||
auto callInitDriver = [](DriverState state) -> DriverStateResult
|
||||
auto callInitDriver = [&](DriverState state) -> DriverStateResult
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
if( ::CanInitDriver( NULL ) < 0 )
|
||||
return std::unexpected(QString("Driver Error: 'InitDriver'"));
|
||||
return DriverState::Initialized;
|
||||
_driverState = DriverState::Initialized;
|
||||
return _driverState;
|
||||
};
|
||||
|
||||
auto callOpenDevice = [](DriverState state) -> DriverStateResult
|
||||
auto callOpenDevice = [&](DriverState state) -> DriverStateResult
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
if( ::CanDeviceOpen( 0, NULL ) < 0 )
|
||||
@@ -93,41 +105,58 @@ void BCDriverTinyCan::loadDriver()
|
||||
::CanSetMode( 0, OP_CAN_RESET, CAN_CMD_NONE );
|
||||
return std::unexpected(QString("Driver Error: CAN Status 'BusOff'" ));
|
||||
}
|
||||
return DriverState::Opened;
|
||||
_driverState = DriverState::Opened;
|
||||
return _driverState;
|
||||
};
|
||||
|
||||
|
||||
// #1. erstmal komplett zurücksetzen
|
||||
resetDriver();
|
||||
// #2. Treiber laden, initialisieren und
|
||||
// mit dem tinyCan Interface verbinden.
|
||||
auto newDriverState = callLoadDriver()
|
||||
.and_then( callInitDriver )
|
||||
.and_then( callOpenDevice );
|
||||
|
||||
_driverState = DriverState::Error;
|
||||
QString message("Driver Ready.");
|
||||
|
||||
// success:
|
||||
if(newDriverState)
|
||||
_driverState = *newDriverState;
|
||||
else
|
||||
message = newDriverState.error();
|
||||
{
|
||||
// return 'DriverState::Opened'
|
||||
return _driverState;
|
||||
}
|
||||
// return driver error message,
|
||||
// _driverState ist irgendwo unter DriverState::Opened
|
||||
return newDriverState;
|
||||
|
||||
emit driverStateChanged( _driverState, message );
|
||||
}
|
||||
|
||||
// __fix
|
||||
BCDriver::DriverState BCDriverTinyCan::connectDriver()
|
||||
BCDriver::DriverStateResult BCDriverTinyCan::setConsoleSlaveMode()
|
||||
{
|
||||
|
||||
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
|
||||
uint8_t slaveFlag = static_cast<uint8_t>(BC::ID::Cons_Status_Slave);
|
||||
uint8_t slaveFlag = static_cast<uint8_t> (BC::ID::Cons_Status_Slave);
|
||||
|
||||
qDebug() << "XXX BCDriverTinyCan::Driver Init: putting Console in slave mode ... ";
|
||||
|
||||
// Console already in slave mode. good!
|
||||
if( readRawByte( console, slaveFlag ) )
|
||||
TransmitResult isSlave = 0;
|
||||
// Already slave?
|
||||
isSlave = readRawByte( console, slaveFlag );
|
||||
if( isSlave.has_value() )
|
||||
{
|
||||
qDebug() << "Console responded: " << isSlave.value();
|
||||
if( isSlave.value() == 1 )
|
||||
{
|
||||
qDebug() << "Console already in slave mode. good!";
|
||||
return DriverState::DeviceReady;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "BCDriverTinyCan::BCDriverTinyCan::XXX Driver Init: putting Console in slave mode ... ";
|
||||
|
||||
unsigned int retry = cTimeOuts;
|
||||
emit driverStateChanged( _driverState, "Driver Init: putting Console in slave mode ... " );
|
||||
TransmitResult isSlave = 0;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
writeRawByte( console, slaveFlag, 1 );
|
||||
@@ -145,20 +174,15 @@ BCDriver::DriverState BCDriverTinyCan::connectDriver()
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
try
|
||||
{
|
||||
initBCDevice::ID::Console();
|
||||
}
|
||||
|
||||
catch( std::exception& except )
|
||||
void BCDriverTinyCan::resetDriver()
|
||||
{
|
||||
if( _driverState > DriverState::NotPresent )
|
||||
{
|
||||
::CanDownDriver();
|
||||
::UnloadDriver();
|
||||
_driverState = DriverState::NotPresent;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BCDriverTinyCan::readRawByte
|
||||
@@ -170,17 +194,75 @@ BCDriver::DriverState BCDriverTinyCan::connectDriver()
|
||||
TransmitResult BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) const
|
||||
{
|
||||
|
||||
qDebug() << " --- CAN Read Byte: Device: "<< deviceID << " register: " << registerID << " TRY! ";
|
||||
|
||||
struct TCanMsg msg;
|
||||
int err, retry = 20;
|
||||
int timeout = 80;
|
||||
|
||||
unsigned char receipient = (unsigned char) deviceID;
|
||||
unsigned char reg = (unsigned char) registerID;
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = receipient;
|
||||
msg.MsgLen = 2;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = reg;
|
||||
|
||||
CanTransmit(0, &msg, 1);
|
||||
|
||||
while(timeout-- && CanTransmitGetCount(0))
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if (timeout == -1)
|
||||
qDebug() << "error: could not send value to node ";
|
||||
|
||||
retry:
|
||||
|
||||
timeout = 80;
|
||||
while(timeout-- && !CanReceiveGetCount(0))
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if (timeout == -1)
|
||||
{
|
||||
qDebug() << "error: no response from node";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((err = CanReceive(0, &msg, 1)) > 0)
|
||||
{
|
||||
qDebug() << " retry: " << retry << " BIB:" << BC::ID::ID_Bib << " msg.Id: " << msg.Id << " msg.MsgLen: " << msg.MsgLen << " msg.MsgData[1]: " << msg.MsgData[1] << " reg: " << reg;
|
||||
if (--retry && (msg.Id != (uint32_t)BC::ID::ID_Bib|| msg.MsgLen != 4 || msg.MsgData[1] != reg))
|
||||
goto retry;
|
||||
|
||||
if (!retry)
|
||||
{
|
||||
qDebug() << "XXX error: no response from node: " << err;
|
||||
return 0;
|
||||
}
|
||||
qDebug() << " --- CAN Read Byte: Device: "<< deviceID << " register: " << registerID << " BYTE: " << (uint32_t) msg.MsgData[3];
|
||||
return (unsigned int) msg.MsgData[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Error:" <<err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
//TransmitResult
|
||||
qDebug() << " --- BCDriverTinyCan::readRawByte DriverState: " << getDriverState();
|
||||
|
||||
if( getDriverState() != DriverState::DeviceReady)
|
||||
if( _driverState <DriverState::Opened )
|
||||
return std::unexpected(QString("readRawValue error: driver not loaded." ) );
|
||||
|
||||
unsigned char receipient = (unsigned char ) deviceID;
|
||||
::TCanMsg msg;
|
||||
|
||||
// msg verpacken
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = deviceID;
|
||||
msg.Id = receipient;//deviceID;
|
||||
msg.MsgLen = 2;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = registerID;
|
||||
@@ -212,15 +294,15 @@ retry:
|
||||
|
||||
// message empfangen
|
||||
int err = ::CanReceive( 0, &msg, 1 );
|
||||
qDebug() << "HÄÄ ?" << err << "reg: "<< registerID <<" timeOuts: " << timeOuts;
|
||||
//qDebug() << "HÄÄ ?" << err << "reg: "<< registerID <<" timeOuts: " << timeOuts;
|
||||
|
||||
if( err < 0 )
|
||||
//throw BCException( "getValue error: could not receive value" );
|
||||
qDebug( "getValue error: could not receive value" );
|
||||
|
||||
qDebug() << "HÄÄ 2" <<msg.Id;
|
||||
qDebug() << "HÄÄ 2" <<msg.MsgLen;
|
||||
qDebug() << "HÄÄ 2" <<msg.MsgData[1];
|
||||
//qDebug() << "HÄÄ 2" <<msg.Id;
|
||||
//qDebug() << "HÄÄ 2" <<msg.MsgLen;
|
||||
//qDebug() << "HÄÄ 2" <<msg.MsgData[1];
|
||||
|
||||
//if( err > 0 )
|
||||
if( --retries && ( msg.Id != BIB || msg.MsgLen != 4 || msg.MsgData[1] != registerID ) )
|
||||
@@ -229,23 +311,25 @@ retry:
|
||||
if( !timeOuts )
|
||||
return std::unexpected(QString("CAN response errror: timeout" ));
|
||||
|
||||
qDebug() << " --- CAN Read Byte: " << (uint32_t) msg.MsgData[3] << " Device:: "<< deviceID << " register: " << registerID;
|
||||
return (uint32_t) msg.MsgData[3];
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
// void BCDriverTinyCan::setValue( unsigned char receipient, unsigned char reg, unsigned char value )
|
||||
TransmitResult BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID ,uint8_t value ) const
|
||||
TransmitResult BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const
|
||||
{
|
||||
|
||||
if( getDriverState() != DriverState::DeviceReady)
|
||||
return std::unexpected(QString("writeRawValue error: driver not loaded." ) );
|
||||
if( _driverState <DriverState::Opened )
|
||||
return std::unexpected(QString("readRawValue error: driver not loaded." ) );
|
||||
|
||||
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
|
||||
|
||||
::TCanMsg msg;
|
||||
int timeout_count = cTIMEOUT_COUNT;
|
||||
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = deviceID;
|
||||
msg.MsgLen = 4;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -37,24 +37,23 @@
|
||||
|
||||
class BCDriverTinyCan : public BCDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCDriverTinyCan( QObject* parent=nullptr );
|
||||
virtual ~BCDriverTinyCan() = default;
|
||||
|
||||
virtual ~BCDriverTinyCan();
|
||||
|
||||
BCDriver::DriverStateResult loadAndStartDriver() override;
|
||||
void resetDriver();
|
||||
|
||||
TransmitResult readRawByte ( uint32_t deviceID, uint8_t registerID ) const override;
|
||||
TransmitResult writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
|
||||
|
||||
public slots:
|
||||
private:
|
||||
|
||||
void onStartDriver() override;
|
||||
BCDriver::DriverStateResult loadDriver();
|
||||
BCDriver::DriverStateResult setConsoleSlaveMode();
|
||||
|
||||
protected:
|
||||
|
||||
void loadDriver();
|
||||
DriverState connectDriver();
|
||||
|
||||
//const char* CBCDLL_LIN = "libmhstcan.so";
|
||||
//const char* CBCDLL_WIN = "mhstcan.dll";
|
||||
@@ -64,9 +63,6 @@ protected:
|
||||
static constexpr int cTIMEOUT_MS = 10; // 10ms
|
||||
static constexpr int cTIMEOUT_COUNT = 10;
|
||||
|
||||
//const unsigned int BATTERY = 0x010;
|
||||
//const unsigned int MOTOR = 0x020;
|
||||
const unsigned int BIB = 0x048;
|
||||
|
||||
|
||||
};
|
||||
|
||||
188
bcguihelpers.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <bcguihelpers.h>
|
||||
|
||||
BCThemeSwitchButton::BCThemeSwitchButton(QWidget *parent )
|
||||
: QPushButton(parent), _isDarkMode(true)
|
||||
{
|
||||
// 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
setFixedSize(24, 24); // Kleiner Footprint im StatusBar
|
||||
|
||||
// CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt
|
||||
// Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind
|
||||
setStyleSheet(R"(
|
||||
QPushButton {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 11pt;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
|
||||
border-radius: 24px;
|
||||
}
|
||||
)");
|
||||
|
||||
// 2. Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
||||
updateIcon();
|
||||
|
||||
// 3. Klick verbinden
|
||||
connect(this, &QPushButton::clicked, this, &BCThemeSwitchButton::toggle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BCThemeSwitchButton::toggle()
|
||||
{
|
||||
_isDarkMode = !_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(_isDarkMode);
|
||||
}
|
||||
|
||||
|
||||
void BCThemeSwitchButton::updateIcon()
|
||||
{
|
||||
// Logik:
|
||||
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
||||
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
||||
setText(_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode");
|
||||
}
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
BCDriverStateWidget::BCDriverStateWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(10, 2, 10, 2);
|
||||
layout->setSpacing(8);
|
||||
|
||||
_label = new QLabel(this);
|
||||
_label->setStyleSheet("font-weight: 500;"); // Medium weight
|
||||
|
||||
_led = new QLabel(this);
|
||||
_led->setFixedSize(12, 12);
|
||||
|
||||
layout->addWidget(_label);
|
||||
layout->addWidget(_led);
|
||||
|
||||
// Startzustand
|
||||
onDriverStateChanged(BCDriver::DriverState::NotPresent, "Not Present");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void BCDriverStateWidget::onDriverStateChanged(BCDriver::DriverState state, const QString& customMessage)
|
||||
{
|
||||
_state = state;
|
||||
qDebug() << " --- StateWidget: " << state << " - " << customMessage;
|
||||
// Standard-Texte, falls keine Nachricht übergeben wurde
|
||||
QString text = customMessage;
|
||||
if (text.isEmpty())
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
text = "Device Ready";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::Error:
|
||||
text = "Driver Error";
|
||||
break;
|
||||
|
||||
default:
|
||||
text = "Not Present";
|
||||
break;
|
||||
}
|
||||
}
|
||||
_label->setText(text);
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
|
||||
void BCDriverStateWidget::updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString labelColor;
|
||||
QString toolTipText;
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;#FF5F1F; #FF8C00;<- das isses #FF6700";
|
||||
labelColor = "#FFFFFF"; // Weiß (Hervorgehoben)
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
labelColor = "#FF99A4"; // Ein helleres Rot für Text, damit es auf Dunkel lesbar ist
|
||||
toolTipText = "Kritischer Fehler bei der Verbindung!";
|
||||
break;
|
||||
|
||||
default:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
labelColor = "#9E9E9E"; // Ausgegrauter Text
|
||||
toolTipText = "System ist offline.";
|
||||
break;
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
|
||||
// Textfarbe setzen
|
||||
_label->setStyleSheet(QString("color: %1; font-weight: %2;")
|
||||
.arg(labelColor)
|
||||
.arg(_state == BCDriver::DriverState::DeviceReady ? "bold" : "normal"));
|
||||
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
97
bcguihelpers.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCGUIHELPERS_H
|
||||
#define BCGUIHELPERS_H
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include <bcdriver.h>
|
||||
|
||||
|
||||
class BCThemeSwitchButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCThemeSwitchButton(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
|
||||
void toggle();
|
||||
|
||||
private:
|
||||
|
||||
void updateIcon();
|
||||
|
||||
bool _isDarkMode;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class BCDriverStateWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCDriverStateWidget(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void onDriverStateChanged(BCDriver::DriverState state, const QString& customMessage = QString());
|
||||
|
||||
private:
|
||||
|
||||
void updateStyle();
|
||||
|
||||
QLabel* _led;
|
||||
QLabel* _label;
|
||||
BCDriver::DriverState _state;
|
||||
|
||||
};
|
||||
|
||||
#endif // BCGUIHELPERS_H
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <bcmainwindow.h>
|
||||
#include <bcanimateddelegate.h>
|
||||
#include <ui_bcmainwindow.h>
|
||||
|
||||
#include <bcguihelpers.h>
|
||||
|
||||
/**
|
||||
* @brief Das Mainwindow erzeugen
|
||||
@@ -141,20 +141,21 @@ void BCMainWindow::initMainWindow()
|
||||
|
||||
fitzeButton->setStyleSheet(style);
|
||||
*/
|
||||
|
||||
initStatusBar();
|
||||
|
||||
// besser: model::emit dataChanged
|
||||
// also: emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, ValueRole});
|
||||
connect( _connectButton, &QToolButton::clicked, &_transmitter, &BCTransmitter::onToggleConnectionState );
|
||||
connect( _connectButton, &QToolButton::clicked, &_transmitter, &BCTransmitter::onToggleDriverConnection );
|
||||
connect( _syncButton, &QToolButton::clicked, this, &BCMainWindow::onSyncDeviceView );
|
||||
connect( &_transmitter, &BCTransmitter::valueUpdated, this, &BCMainWindow::onValueUpdated );
|
||||
|
||||
|
||||
_transmitter.moveToThread(&_worker);
|
||||
|
||||
connect(this, &BCMainWindow::requestValueUpdate, &_transmitter, &BCTransmitter::enqueueValue);
|
||||
connect(&_worker, &QThread::finished, &_transmitter, &QObject::deleteLater);
|
||||
connect( &_transmitter, &BCTransmitter::driverStateChanged, this, &BCMainWindow::onDriverStateChanged );
|
||||
|
||||
// transmitter starten
|
||||
_transmitter.moveToThread(&_worker);
|
||||
_worker.start();
|
||||
|
||||
// die Daten des eBikes laden
|
||||
@@ -167,30 +168,19 @@ void BCMainWindow::initMainWindow()
|
||||
|
||||
void BCMainWindow::initStatusBar()
|
||||
{
|
||||
// __fix
|
||||
QStatusBar *statBar = statusBar();
|
||||
|
||||
// Optional: Normale Nachricht links
|
||||
BCDriverStateWidget* connector = new BCDriverStateWidget(this);
|
||||
connect( &_transmitter, &BCTransmitter::driverStateChanged, connector, &BCDriverStateWidget::onDriverStateChanged );
|
||||
statBar->addPermanentWidget(connector);
|
||||
|
||||
statBar->showMessage("Ready");
|
||||
|
||||
// 1. Unseren Switcher erstellen
|
||||
ThemeSwitchButton *themeBtn = new ThemeSwitchButton(this);
|
||||
|
||||
// 2. WICHTIG: Rechts hinzufügen
|
||||
BCThemeSwitchButton *themeBtn = new BCThemeSwitchButton(this);
|
||||
statBar->addPermanentWidget(themeBtn);
|
||||
|
||||
// 3. Signal verbinden: Button klick -> Theme ändern
|
||||
connect(themeBtn, &ThemeSwitchButton::themeChanged, this, [this](bool isDark){
|
||||
if (isDark)
|
||||
connect(themeBtn, &BCThemeSwitchButton::themeChanged, this, [this](bool isDark)
|
||||
{
|
||||
//applyFluentDarkTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Dark Mode Activated", 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
//applyFluentLightTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Light Mode Activated", 3000);
|
||||
}
|
||||
QString message = isDark ? "Dark Mode Activated" : "Light Mode Activated";
|
||||
statusBar()->showMessage( message, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -216,6 +206,7 @@ void BCMainWindow::autoConnect()
|
||||
void BCMainWindow::onDriverStateChanged( BCDriver::DriverState state, const QString& message )
|
||||
{
|
||||
qDebug() << " --- on DriverStatusChanged: " << state << ":" << message;
|
||||
_statusbar->showMessage( message, 8000 );
|
||||
}
|
||||
|
||||
void BCMainWindow::onShowDevicePanel( BCDevice::ID deviceID )
|
||||
|
||||
170
bcmainwindow.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -34,9 +34,11 @@
|
||||
#define BCMAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QThread>
|
||||
|
||||
#include <ui_bcmainwindow.h>
|
||||
#include <bcxmlloader.h>
|
||||
#include <bctransmitter.h>
|
||||
|
||||
class BCDeviceView;
|
||||
|
||||
@@ -90,170 +92,4 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ThemeSwitchButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ThemeSwitchButton(QWidget *parent = nullptr)
|
||||
: QPushButton(parent), m_isDarkMode(true)
|
||||
{
|
||||
// 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
setFixedSize(24, 24); // Kleiner Footprint im StatusBar
|
||||
|
||||
// CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt
|
||||
// Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind
|
||||
setStyleSheet(R"(
|
||||
QPushButton {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 11pt;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
|
||||
border-radius: 24px;
|
||||
}
|
||||
)");
|
||||
|
||||
// 2. Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
||||
updateIcon();
|
||||
|
||||
// 3. Klick verbinden
|
||||
connect(this, &QPushButton::clicked, this, &ThemeSwitchButton::toggle);
|
||||
}
|
||||
|
||||
signals:
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
void toggle() {
|
||||
m_isDarkMode = !m_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(m_isDarkMode);
|
||||
}
|
||||
|
||||
private:
|
||||
void updateIcon() {
|
||||
// Logik:
|
||||
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
||||
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
||||
setText(m_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(m_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode");
|
||||
}
|
||||
|
||||
bool m_isDarkMode;
|
||||
};
|
||||
|
||||
|
||||
class BCConnectionWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Definition der 3 Zustände
|
||||
enum class State
|
||||
{
|
||||
Disconnected, // Grau: Offline / Standby
|
||||
Connected, // Grün: Alles OK
|
||||
Error // Rot: Fehler / Timeout / Abbruch
|
||||
};
|
||||
Q_ENUM(State) // Damit Qt das Enum kennt (optional, gut für Debugging)
|
||||
|
||||
explicit BCConnectionWidget(QWidget *parent = nullptr)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(10, 2, 10, 2);
|
||||
layout->setSpacing(8);
|
||||
|
||||
// 1. Die LED
|
||||
m_led = new QLabel(this);
|
||||
m_led->setFixedSize(12, 12);
|
||||
|
||||
// 2. Der Text
|
||||
m_label = new QLabel(this);
|
||||
m_label->setStyleSheet("font-weight: 500;"); // Medium weight
|
||||
|
||||
layout->addWidget(m_led);
|
||||
layout->addWidget(m_label);
|
||||
|
||||
// Startzustand
|
||||
setState(State::Disconnected, "Offline");
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void setState(State state, const QString &customMessage = QString())
|
||||
{
|
||||
m_state = state;
|
||||
|
||||
// Standard-Texte, falls keine Nachricht übergeben wurde
|
||||
QString text = customMessage;
|
||||
if (text.isEmpty()) {
|
||||
switch (state) {
|
||||
case State::Connected: text = "Online"; break;
|
||||
case State::Disconnected: text = "Not Connected"; break;
|
||||
case State::Error: text = "Connection Error"; break;
|
||||
}
|
||||
}
|
||||
m_label->setText(text);
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString labelColor;
|
||||
QString toolTipText;
|
||||
|
||||
switch (m_state) {
|
||||
case State::Connected:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;#FF5F1F; #FF8C00;<- das isses #FF6700";
|
||||
labelColor = "#FFFFFF"; // Weiß (Hervorgehoben)
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
|
||||
case State::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
labelColor = "#FF99A4"; // Ein helleres Rot für Text, damit es auf Dunkel lesbar ist
|
||||
toolTipText = "Kritischer Fehler bei der Verbindung!";
|
||||
break;
|
||||
|
||||
case State::Disconnected:
|
||||
default:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
labelColor = "#9E9E9E"; // Ausgegrauter Text
|
||||
toolTipText = "System ist offline.";
|
||||
break;
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
m_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
|
||||
// Textfarbe setzen
|
||||
m_label->setStyleSheet(QString("color: %1; font-weight: %2;")
|
||||
.arg(labelColor)
|
||||
.arg(m_state == State::Connected ? "bold" : "normal"));
|
||||
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
|
||||
QLabel *m_led;
|
||||
QLabel *m_label;
|
||||
State m_state;
|
||||
};
|
||||
|
||||
#endif // BCMAINWINDOW_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -30,43 +30,83 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "bcvaluetype.h"
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
|
||||
#include <bctransmitter.h>
|
||||
|
||||
/**
|
||||
* @brief Kosntruktion. Aktiviert erstmal den Dummy-Driver.
|
||||
*/
|
||||
|
||||
BCTransmitter::BCTransmitter(QObject *parent)
|
||||
: QObject(parent), _isBusy(false)
|
||||
{
|
||||
//_canDriver = new BCDriverTinyCan{this};
|
||||
_canDriver = new BCDriverDummy{this};
|
||||
// forward driver state
|
||||
connect( _canDriver, &BCDriver::driverStateChanged, this, &BCTransmitter::driverStateChanged );
|
||||
_canDriver = &_dummyDriver;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Steuert die Verbindung mit dem 'echten' CAN-Bus Treiber.
|
||||
* @param connect true: Vesuche den CAN-Bus Treiber zu laden und zu verbinden
|
||||
* false: Disconnect & Cleanup
|
||||
*/
|
||||
|
||||
void BCTransmitter::onToggleConnectionState( bool connect )
|
||||
void BCTransmitter::onToggleDriverConnection( bool connect )
|
||||
{
|
||||
if( connect )
|
||||
{
|
||||
if( _canDriver->getDriverState() != BCDriver::DriverState::DeviceReady )
|
||||
_canDriver->onStartDriver();
|
||||
qDebug() << " --- onToggleDriverConnection: " << connect;
|
||||
// FIX! Ende der current op abwarten!
|
||||
|
||||
// __fix!
|
||||
TransmitResult hwVersion = _canDriver->readRawByte( (uint32_t)BCDevice::ID::Console, (uint8_t)BC::ID::Cons_Rev_Hw);
|
||||
if(!hwVersion)
|
||||
// Hier sind wir noch in GUI Thread
|
||||
QMutexLocker locker(&_mutex);
|
||||
// weitere operation stoppen
|
||||
_isBusy = true;
|
||||
connect ? connectCanDriver() : disconnectCanDriver();
|
||||
_isBusy = false;
|
||||
}
|
||||
|
||||
void BCTransmitter::connectCanDriver()
|
||||
{
|
||||
// hier gehts nur um den echten Treiber
|
||||
|
||||
// Treiber laden und/oder starten:
|
||||
BCDriver::DriverStateResult result; //(defaults to 'NotPresent')
|
||||
if( _tinyCanDriver.getDriverState() != BCDriver::DriverState::DeviceReady )
|
||||
result = _tinyCanDriver.loadAndStartDriver();
|
||||
|
||||
QString message("FitzeFatze!");
|
||||
// hat geklappt
|
||||
if( _tinyCanDriver.getDriverState() >= BCDriver::DriverState::Opened )
|
||||
{
|
||||
qDebug() << "Console not responding";
|
||||
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
|
||||
uint8_t hwRev = static_cast<uint8_t> (BC::ID::Cons_Rev_Hw);
|
||||
|
||||
TransmitResult hwVersion = _tinyCanDriver.readRawByte( console, hwRev);
|
||||
if( hwVersion.has_value() )
|
||||
{
|
||||
message = " ---- HAIL to the king!";
|
||||
qDebug() << message;
|
||||
// swap driver
|
||||
_canDriver = &_tinyCanDriver;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
qDebug() << "Console not responding";
|
||||
}
|
||||
|
||||
qDebug() << " ---HAIL to the kings: " << hwVersion.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
message = result.error();
|
||||
}
|
||||
emit driverStateChanged( _tinyCanDriver.getDriverState(), message );
|
||||
}
|
||||
|
||||
void BCTransmitter::disconnectCanDriver()
|
||||
{
|
||||
_tinyCanDriver.resetDriver();
|
||||
_canDriver = &_dummyDriver;
|
||||
emit driverStateChanged( _tinyCanDriver.getDriverState(), "Disconnected" );
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +161,7 @@ void BCTransmitter::processValue()
|
||||
// Value ist 'under construction'
|
||||
//emit valueUpdated( value.deviceID, value.indexRow, BCValue::State::Locked );
|
||||
|
||||
const BCValueType& valueType = *value.valueType;
|
||||
|
||||
uint32_t devID = static_cast<uint32_t>(value.deviceID);
|
||||
uint8_t regID = static_cast<uint8_t> (value.registerID);
|
||||
|
||||
@@ -138,19 +178,17 @@ void BCTransmitter::processValue()
|
||||
|
||||
else if( value.state.testFlag( BCValue::State::ReadMe ) )
|
||||
{
|
||||
|
||||
// wir sind hier im anderen thread! nicht einfach so reinschreiben, nur lesen
|
||||
TransmitResult result = valueType.readValueFunc( *this, devID, regID );
|
||||
TransmitResult result = value.isWord ? readWordValue( devID, regID ) : readByteValue( devID, regID );
|
||||
if( result.has_value() )
|
||||
{
|
||||
newVisibleValue = valueType.formatValue( result.value() );
|
||||
newVisibleValue = value.formatValue( result.value() );
|
||||
newState = BCValue::State::InSync;
|
||||
}
|
||||
else
|
||||
{
|
||||
newState = BCValue::State::Failed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
emit valueUpdated( value.deviceID, value.indexRow, newState, newVisibleValue );
|
||||
@@ -164,30 +202,30 @@ void BCTransmitter::processValue()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief BCTransmitter::readByte
|
||||
* NEIN NEIN NEIN!
|
||||
* Reicht den read request an den aktuellen Treiber weiter. Wird von aussen, von der readValueFunc des ValueTypes
|
||||
* aufgerufen, deshalb public.
|
||||
*/
|
||||
|
||||
TransmitResult BCTransmitter::readByte( uint32_t deviceID, uint8_t registerID ) const
|
||||
TransmitResult BCTransmitter::readByteValue( uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
//qDebug() << " --- YES: Read ByteValue: " << registerID;
|
||||
// Wir lesen nur ein Byte und gut.
|
||||
return _canDriver->readRawByte( deviceID, registerID );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief BCTransmitter::writeByte
|
||||
* Reicht den write request an den aktuellen Treiber weiter. Wird von aussen, von der writeValueFunc des ValueTypes
|
||||
* aufgerufen, deshalb public.
|
||||
*/
|
||||
|
||||
TransmitResult BCTransmitter::writeByte( uint32_t deviceID, uint8_t registerID , uint8_t value ) const
|
||||
TransmitResult BCTransmitter::readWordValue( uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
return _canDriver->writeRawByte( deviceID, registerID, value );
|
||||
//qDebug() << " --- YES: Read WordValue: " << registerID;
|
||||
|
||||
uint32_t result{};
|
||||
// hi byte Leseversuch.
|
||||
TransmitResult value = _canDriver->readRawByte( deviceID, registerID );
|
||||
// Fehler? dann weg
|
||||
if( !value)
|
||||
return std::unexpected( value.error() );
|
||||
// hi byte speichern
|
||||
result = *value << 8;
|
||||
// low byte, liegt im followup register: +1
|
||||
value = _canDriver->readRawByte( deviceID, registerID+1 );
|
||||
if( !value)
|
||||
return std::unexpected( value.error() );
|
||||
result += *value;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <atomic>
|
||||
|
||||
#include <bcvalue.h>
|
||||
#include <bcvaluetype.h>
|
||||
#include <bcdrivertinycan.h>
|
||||
|
||||
/**
|
||||
@@ -53,7 +52,7 @@
|
||||
* implementiert sein und liest/schreibt Byteweise auf den Bus.
|
||||
*/
|
||||
|
||||
class BCTransmitter : public QObject, public BCAbstractTransmitter
|
||||
class BCTransmitter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -61,12 +60,9 @@ public:
|
||||
|
||||
explicit BCTransmitter(QObject *parent = nullptr);
|
||||
|
||||
TransmitResult readByte( uint32_t deviceID, uint8_t registerID ) const override;
|
||||
TransmitResult writeByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
|
||||
|
||||
public slots:
|
||||
|
||||
void onToggleConnectionState( bool connect );
|
||||
void onToggleDriverConnection( bool connect );
|
||||
void enqueueValue(BCValuePtrConst value );
|
||||
void processValue();
|
||||
|
||||
@@ -77,8 +73,11 @@ signals:
|
||||
|
||||
private:
|
||||
|
||||
void readRawValueX ( const BCValue& value ) const;
|
||||
void writeRawValueX( const BCValue& value ) const;
|
||||
void connectCanDriver();
|
||||
void disconnectCanDriver();
|
||||
|
||||
TransmitResult readByteValue( uint32_t deviceID, uint8_t registerID );
|
||||
TransmitResult readWordValue( uint32_t deviceID, uint8_t registerID );
|
||||
|
||||
using BCDataQueue = QQueue<BCValuePtrConst>;
|
||||
|
||||
@@ -86,8 +85,10 @@ private:
|
||||
QMutex _mutex;
|
||||
std::atomic<bool> _isBusy{ false };
|
||||
|
||||
// __fix! set two
|
||||
// __fix!
|
||||
BCDriver* _canDriver{};
|
||||
BCDriverTinyCan _tinyCanDriver{};
|
||||
BCDriverDummy _dummyDriver{};
|
||||
|
||||
};
|
||||
|
||||
|
||||
26
bcvalue.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -33,16 +33,34 @@
|
||||
#include <QMetaEnum>
|
||||
|
||||
#include <bcvalue.h>
|
||||
#include <bcvaluetype.h>
|
||||
|
||||
|
||||
///-------------------------------
|
||||
|
||||
|
||||
BCValue::BCValue(const BCValueType* valueType_, BCDevice::ID deviceID_, BC::ID registerID_)
|
||||
: valueType{valueType_}, deviceID{deviceID_}, registerID{registerID_}
|
||||
BCValue::BCValue( BCDevice::ID deviceID_, BC::ID registerID_)
|
||||
: deviceID{deviceID_}, registerID{registerID_}
|
||||
{
|
||||
visibleValue = "--";
|
||||
}
|
||||
|
||||
QString BCValue::formatValue( uint32_t value ) const
|
||||
{
|
||||
if( factor == 1 )
|
||||
return QString::number( value );
|
||||
|
||||
double result = value * factor;
|
||||
return QString::number(result, 'f', 2);
|
||||
}
|
||||
|
||||
void BCValue::dumpValue() const
|
||||
{
|
||||
|
||||
qDebug() << "DeviceID: " << deviceID << " Register: " << registerID << " state:" " << state << " << " label: " << label;
|
||||
qDebug() << "visibleValue: " << visibleValue << " min: " << min << " max: " << max << " factor: " << factor << " ValueType: " << (char)valueType << " ";
|
||||
qDebug() << "indexRow: " << indexRow << " isWord: " << isWord;
|
||||
qDebug();
|
||||
|
||||
}
|
||||
|
||||
/// ----
|
||||
|
||||
99
bcvalue.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
|
||||
#include <expected>
|
||||
#include <bc.h>
|
||||
|
||||
|
||||
@@ -55,16 +56,28 @@
|
||||
-
|
||||
*/
|
||||
|
||||
using OptDouble = std::optional<double>;
|
||||
|
||||
|
||||
|
||||
struct BCValueType;
|
||||
// Enthält den gelesenen Wert oder einen Fehlerstring
|
||||
using TransmitResult = std::expected<uint32_t,QString>;
|
||||
// Funktionsobject, um Werte aus der Transmitterschicht zu holden
|
||||
//using ReadValueFunc = std::function<TransmitResult( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )>;
|
||||
|
||||
class BCValue
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Aus dem Type ergibt sich
|
||||
// später der Editor
|
||||
enum class ValueType : uint8_t
|
||||
{
|
||||
Plain,
|
||||
Bool,
|
||||
Number,
|
||||
Float
|
||||
};
|
||||
|
||||
enum class State : uint8_t
|
||||
{
|
||||
NoState = 0x00,
|
||||
@@ -78,16 +91,23 @@ public:
|
||||
};
|
||||
Q_DECLARE_FLAGS(States, State )
|
||||
|
||||
BCValue( const BCValueType* valueType_, BCDevice::ID deviceID_, BC::ID registerID_ );
|
||||
BCValue( BCDevice::ID deviceID_, BC::ID registerID_ );
|
||||
|
||||
mutable States state{BCValue::State::NoState};
|
||||
const BCValueType* valueType{};
|
||||
QString formatValue( uint32_t value ) const;
|
||||
void dumpValue() const;
|
||||
|
||||
mutable States state{BCValue::State::ReadOnly};
|
||||
BCDevice::ID deviceID{BCDevice::ID::Invalid};
|
||||
BC::ID registerID{BC::ID::Invalid};
|
||||
ValueType valueType{ValueType::Plain};
|
||||
int indexRow{-1};
|
||||
QString label;
|
||||
mutable QString visibleValue;
|
||||
|
||||
bool isWord{false};
|
||||
QString unitLabel;
|
||||
double factor{1};
|
||||
OptDouble min;
|
||||
OptDouble max;
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BCValue::States)
|
||||
|
||||
@@ -103,72 +123,9 @@ using BCValueList = QList<BCValuePtr>;
|
||||
|
||||
Q_DECLARE_METATYPE(const BCValuePtr)
|
||||
|
||||
/*
|
||||
class BCValueList : public QList<BCValue>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
BCValueList()
|
||||
{
|
||||
qDebug() << "BC Construct: " << this;
|
||||
}
|
||||
|
||||
BCValueList(const BCValueList& other)
|
||||
: QList<BCValue>(other)
|
||||
{
|
||||
qDebug() << "BC: Copy from: " << &other << "to" << this;
|
||||
}
|
||||
|
||||
BCValueList(BCValueList&& other) noexcept
|
||||
: QList<BCValue>( other )
|
||||
{
|
||||
qDebug() << "Move from: " << &other << "to" << this;
|
||||
}
|
||||
|
||||
// Copy Assignment Operator
|
||||
BCValueList& operator=(const BCValueList& other)
|
||||
{
|
||||
qDebug() << "BC copy assignment: " << this;
|
||||
QList<BCValue>::operator=( other );
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Move Assignment Operator
|
||||
BCValueList& operator=(BCValueList&& other) noexcept
|
||||
{
|
||||
qDebug() << "BC move assignment: " << this;
|
||||
QList<BCValue>::operator=( other );
|
||||
return *this;
|
||||
}
|
||||
|
||||
~BCValueList()
|
||||
{
|
||||
qDebug() << "Destruct: " << this;
|
||||
}
|
||||
|
||||
};
|
||||
*/
|
||||
Q_DECLARE_METATYPE(BCValueList)
|
||||
|
||||
|
||||
// abbreviations:
|
||||
// SOC = State Of Charge
|
||||
// LMD = Last Measured Discharge
|
||||
// NIP = ?
|
||||
|
||||
/*
|
||||
|
||||
Needed ?
|
||||
#include <type_traits>
|
||||
|
||||
template <typename E>
|
||||
constexpr auto to_u(E e) noexcept {
|
||||
return static_cast<std::underlying_type_t<E>>(e);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // BCVALUE_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
#include <bcvaluemodel.h>
|
||||
#include <bcvaluetype.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Konstruktor, ohne Besonderheiten
|
||||
@@ -83,16 +83,25 @@ void BCValueModel::takeValueList(BCValueList& newValueList)
|
||||
|
||||
void BCValueModel::onValueUpdated( int row, BCValue::State state, const QString& newVisisbleValue )
|
||||
{
|
||||
qDebug() << " BCValueModel::onValueUpdated update: " << newVisisbleValue;
|
||||
if( row > -1 && row < _valueList.size() )
|
||||
{
|
||||
BCValuePtr value = _valueList[row];
|
||||
BCValue& value = *(_valueList[row].get());
|
||||
QModelIndex idx = index(row,1);
|
||||
value->state = state;
|
||||
if( !newVisisbleValue.isEmpty() && newVisisbleValue != value->visibleValue )
|
||||
|
||||
//qDebug();
|
||||
//qDebug() << " --- OLD:"<< newVisisbleValue;
|
||||
//value.dumpValue();
|
||||
|
||||
value.state = state;
|
||||
|
||||
if( !newVisisbleValue.isEmpty() && newVisisbleValue != value.visibleValue )
|
||||
{
|
||||
value->visibleValue = newVisisbleValue;
|
||||
value.visibleValue = newVisisbleValue;
|
||||
}
|
||||
|
||||
//qDebug() << " --- NEW: " << newVisisbleValue;
|
||||
//value.dumpValue();
|
||||
|
||||
// wir schicken auf jeden fall einen update request
|
||||
emit dataChanged(idx, idx, {Qt::DisplayRole, Qt::EditRole});
|
||||
}
|
||||
@@ -144,17 +153,17 @@ QVariant BCValueModel::data(const QModelIndex& index, int role) const
|
||||
if (wrongRole || !index.isValid() || row >= _valueList.size() )
|
||||
return QVariant();
|
||||
|
||||
BCValuePtr value = _valueList.at( row );
|
||||
const BCValue& value = *(_valueList.at( row ).get());
|
||||
|
||||
if( col == 0 )
|
||||
return value->label;
|
||||
return value.label;
|
||||
|
||||
if( col == 1)
|
||||
{
|
||||
if( role == Qt::DisplayRole )
|
||||
return QString("%1 %2").arg( value->visibleValue, value->valueType->unitLabel);
|
||||
return QString("%1 %2").arg( value.visibleValue, value.unitLabel);
|
||||
|
||||
return value->visibleValue;
|
||||
return value.visibleValue;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
183
bcvaluetype.cpp
@@ -1,183 +0,0 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <bcvaluetype.h>
|
||||
#include <bcvalue.h>
|
||||
|
||||
|
||||
/// reader functions
|
||||
|
||||
|
||||
|
||||
TransmitResult readDummy( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
qDebug() << " --- NO: Read DUMMY: " << registerID;
|
||||
return std::unexpected( QString("NO: Read DUMMY: %1 : %2 ").arg( deviceID, registerID ) );
|
||||
}
|
||||
|
||||
TransmitResult readByteValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
qDebug() << " --- YES: Read ByteValue: " << registerID;
|
||||
// Wir lesen nur ein Byte und gut.
|
||||
return transmitter.readByte( deviceID, registerID );
|
||||
}
|
||||
|
||||
|
||||
TransmitResult readWordValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
qDebug() << " --- YES: Read WordValue: " << registerID;
|
||||
|
||||
//getValue(CONSOLE, CONSOLE_SN_PN_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_PN_LO)),
|
||||
uint32_t result{};
|
||||
// hi byte Leseversuch.
|
||||
TransmitResult value = transmitter.readByte( deviceID, registerID );
|
||||
// Fehler? dann weg
|
||||
if( !value)
|
||||
return std::unexpected( value.error() );
|
||||
// hi byte speichern
|
||||
result = *value << 8;
|
||||
// low byte, liegt im followup register: +1
|
||||
value = transmitter.readByte( deviceID, registerID+1 );
|
||||
if( !value)
|
||||
return std::unexpected( value.error() );
|
||||
result += *value;
|
||||
return result;
|
||||
}
|
||||
|
||||
TransmitResult readSpeedValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
TransmitResult readODOValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
TransmitResult readVoltValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
TransmitResult readCircValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BCValueType::BCValueType
|
||||
*/
|
||||
|
||||
BCValueType::BCValueType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
BCValueType::BCValueType(QString unitKey_, QString unitLabel_, double factor_, optDouble min_, optDouble max_ )
|
||||
: unitLabel{unitLabel_}, factor{factor_}, min{min_}, max{max_}
|
||||
{
|
||||
std::optional<ReadValueFunc> readFn = fetchReadValueFunction( unitKey_ );
|
||||
readValueFunc = readFn.has_value() ? readFn.value() : readDummy;
|
||||
}
|
||||
|
||||
|
||||
QString BCValueType::formatValue( uint32_t value ) const
|
||||
{
|
||||
if( factor == 1 )
|
||||
return QString::number( value );
|
||||
|
||||
double result = value * factor;
|
||||
return QString::number(result, 'f', 2);
|
||||
}
|
||||
|
||||
std::optional<ReadValueFunc> BCValueType::fetchReadValueFunction( const QString& unitTypeKey )
|
||||
{
|
||||
static QHash<QString,ReadValueFunc> s_bcReadValueFunctions
|
||||
{
|
||||
{ "Byte", readByteValue },
|
||||
{ "Word", readWordValue },
|
||||
{ "Assist", readByteValue },
|
||||
|
||||
{ "Kmh", readByteValue },
|
||||
{ "Percent",readByteValue },
|
||||
{ "KWh", readByteValue },
|
||||
{ "Watt", readByteValue },
|
||||
{ "Km", readByteValue },
|
||||
|
||||
{ "Mm", readByteValue },
|
||||
{ "Sec", readByteValue },
|
||||
{ "Degree", readByteValue },
|
||||
{ "SoC", readByteValue },
|
||||
{ "Odo", readByteValue },
|
||||
|
||||
};
|
||||
|
||||
if( !s_bcReadValueFunctions.contains( unitTypeKey ) )
|
||||
return std::nullopt;
|
||||
|
||||
return s_bcReadValueFunctions[unitTypeKey];
|
||||
}
|
||||
|
||||
std::optional<BCValueType*> BCValueType::fetchValueType( const QString& unitTypeKey )
|
||||
{
|
||||
static QHash<QString,BCValueType*> s_bcDataTypes
|
||||
{
|
||||
{ "Byte", new BCValueType( "Byte", "", 1.5625F) },
|
||||
{ "Word", new BCValueType( "Word", "", 1.5625F) },
|
||||
{ "Percent", new BCValueType( "Byte", "%", 1.5625 ) },
|
||||
{ "AssInit", new BCValueType( "Byte", "", 1.0, 0 ,4 ) },
|
||||
{ "Assist", new BCValueType( "Byte", "%", 0,400 ) }
|
||||
/*
|
||||
{ "KWh", new BCValueType( "kwh", 1.5625 ) },
|
||||
{ "Watt", new BCValueType( "w", 1.5625 ) },
|
||||
{ "Km", new BCValueType( "km", 1.5625 ) },
|
||||
{ "Kmh", new BCValueType( "km/h", 0.1 ) },
|
||||
{ "Mm", new BCValueType( "mm", 1.5625 ) },
|
||||
{ "Sec", new BCValueType( "s", 1.5625 ) },
|
||||
{ "Degree", new BCValueType( "°C", 1.0 ) },
|
||||
{ "SoC", new BCValueType( "%", 1.5625 ) },
|
||||
{ "Odo", new BCValueType( "km", 1.5625 ) },
|
||||
|
||||
{ "Assist", new BCValueType( "%" ) },
|
||||
*/
|
||||
};
|
||||
|
||||
if( !s_bcDataTypes.contains( unitTypeKey ) )
|
||||
return std::nullopt;
|
||||
|
||||
return s_bcDataTypes[unitTypeKey];
|
||||
|
||||
}
|
||||
|
||||
/// ----
|
||||
|
||||
102
bcvaluetype.h
@@ -1,102 +0,0 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCVALUETYPE_H
|
||||
#define BCVALUETYPE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <expected>
|
||||
|
||||
#include <bc.h>
|
||||
|
||||
class BCValue;
|
||||
class BCAbstractTransmitter;
|
||||
|
||||
using optDouble = std::optional<double>;
|
||||
|
||||
// Enthält den gelesenen Wert oder einen Fehlerstring
|
||||
using TransmitResult = std::expected<uint32_t,QString>;
|
||||
// Funktionsobject, um Werte aus der Transmitterschicht zu holden
|
||||
using ReadValueFunc = std::function<TransmitResult( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )>;
|
||||
|
||||
|
||||
/**
|
||||
* @brief BCAbstractTransmitter ist das abstrakte Basisinterface für die eigentliche
|
||||
* Datenübertragung auf Treiberebene.
|
||||
*/
|
||||
|
||||
class BCAbstractTransmitter
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual TransmitResult readByte ( uint32_t deviceID, uint8_t registerID ) const = 0;
|
||||
virtual TransmitResult writeByte( uint32_t deviceID, uint8_t registerID, uint8_t value_ ) const = 0;
|
||||
};
|
||||
|
||||
|
||||
struct BCValueType
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
|
||||
BCValueType();
|
||||
BCValueType( QString unitKey_, QString unitLabel_, double factor_= 1.0, optDouble min_=std::nullopt, optDouble max_= std::nullopt );
|
||||
|
||||
virtual QString formatValue( uint32_t value ) const;
|
||||
|
||||
QString unitLabel;
|
||||
double factor;
|
||||
optDouble min;
|
||||
optDouble max;
|
||||
ReadValueFunc readValueFunc;
|
||||
//ReadValueFunc readValueFunc;
|
||||
|
||||
|
||||
static std::optional<BCValueType*> fetchValueType( const QString& unitTypeKey );
|
||||
static std::optional<ReadValueFunc> fetchReadValueFunction( const QString& unitTypeKey );
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//using BCTypeVariant = std::variant<BCValueType,BCValueTypeWord,Long,Fitz,Fatz>;
|
||||
|
||||
// really needed?
|
||||
//using BCValueTypeCRef = std::optional<std::reference_wrapper<const BCTypeVariant>>;
|
||||
|
||||
|
||||
#endif // BCVALUETYPE_H
|
||||
124
bcxmlloader.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -32,28 +32,20 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QTableView>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include <QStatusBar>
|
||||
#include <QApplication>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMetaEnum>
|
||||
#include <QHash>
|
||||
|
||||
#include <bcxmlloader.h>
|
||||
#include <bcvaluetype.h>
|
||||
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
|
||||
|
||||
BCXmlLoader::BCXmlLoader(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
//qRegisterMetaType<BCValue*>("BCValue*");
|
||||
//qRegisterMetaType<BCValue*>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -156,17 +148,22 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
if( _xml.attributes().hasAttribute(BCTags::ID) )
|
||||
{
|
||||
//qDebug() << " --- found: " << _xml.name() << " : " << _xml.attributes().value(BCTags::ID);
|
||||
QString id = _xml.attributes().value(BCTags::ID).toString();
|
||||
|
||||
// füllen des Parameter packs
|
||||
BCDataParams params
|
||||
BCValueParams params
|
||||
{
|
||||
.ID = id,
|
||||
.ID = _xml.attributes().value(BCTags::ID).toString(),
|
||||
.Label = _xml.attributes().value(BCTags::Label).toString(),
|
||||
.UnitType = _xml.attributes().value(BCTags::UnitType).toString(),
|
||||
.UnitLabel = _xml.attributes().value(BCTags::UnitLabel).toString(),
|
||||
.Factor = _xml.attributes().value(BCTags::Factor).toString(),
|
||||
.Min = _xml.attributes().value(BCTags::Min).toString(),
|
||||
.Max = _xml.attributes().value(BCTags::Max).toString(),
|
||||
.IsWord = _xml.attributes().value(BCTags::IsWord).toString(),
|
||||
.ValueType = _xml.attributes().value(BCTags::ValueType).toString(),
|
||||
};
|
||||
|
||||
// nur gültige Werte sind vorhanden und können gespeichert werden
|
||||
std::optional<BCValuePtr> newValue = makeDataValue( deviceID, params );
|
||||
std::optional<BCValuePtr> newValue = makeValue( deviceID, params );
|
||||
if(newValue)
|
||||
{
|
||||
// wir merken uns gleich den index in der Werteliste
|
||||
@@ -185,11 +182,18 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
|
||||
}
|
||||
|
||||
std::optional<BCValuePtr> BCXmlLoader::makeDataValue( BCDevice::ID deviceID, const BCDataParams& params )
|
||||
std::optional<BCValuePtr> BCXmlLoader::makeValue( BCDevice::ID deviceID, const BCValueParams& params )
|
||||
{
|
||||
|
||||
/*
|
||||
auto setIfExists = [&]( QStringView source, optDouble& target )
|
||||
static QHash<QString,BCValue::ValueType> s_valueTypes
|
||||
{
|
||||
{ "Plain", BCValue::ValueType::Plain },
|
||||
{ "Bool", BCValue::ValueType::Bool },
|
||||
{ "Number", BCValue::ValueType::Number },
|
||||
{ "Float", BCValue::ValueType::Float }
|
||||
};
|
||||
|
||||
auto setIfExists = [&]<typename T>( QStringView source, T& target )
|
||||
{
|
||||
if( !source.isEmpty() )
|
||||
{
|
||||
@@ -199,9 +203,6 @@ std::optional<BCValuePtr> BCXmlLoader::makeDataValue( BCDevice::ID deviceID, con
|
||||
target = testVal;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
static QMetaEnum s_bcValueEnum{QMetaEnum::fromType<BC::ID>()};
|
||||
|
||||
|
||||
/*
|
||||
@@ -214,70 +215,47 @@ std::optional<BCValuePtr> BCXmlLoader::makeDataValue( BCDevice::ID deviceID, con
|
||||
// geht nicht auf qt6.8 von debian trixie
|
||||
//std::optional<quint64> IDVal = s_bcValueEnum.keyToValue64( params.ID.toLatin1().constData() );
|
||||
bool ok;
|
||||
static QMetaEnum s_bcValueEnum{QMetaEnum::fromType<BC::ID>()};
|
||||
int IDVal = s_bcValueEnum.keyToValue( params.ID.toLatin1().constData(), &ok );
|
||||
qDebug() << " --- should create: " << params.Label << ": " << params.UnitType;
|
||||
qDebug() << " --- should create: " << params.Label;
|
||||
//if( IDVal.has_value() )
|
||||
if( ok )
|
||||
{
|
||||
auto valueType = BCValueType::fetchValueType(params.UnitType);
|
||||
if( valueType.has_value() )
|
||||
{
|
||||
BCValuePtr newValue = std::make_shared<BCValue>( *valueType, deviceID, static_cast<BC::ID>(IDVal) );
|
||||
BCValuePtr newValuePtr = std::make_shared<BCValue>( deviceID, static_cast<BC::ID>(IDVal) );
|
||||
BCValue& newValue = *newValuePtr.get();
|
||||
|
||||
/*
|
||||
setIfExists( params.Factor, newValue.factor );
|
||||
setIfExists( params.Min, newValue.min );
|
||||
setIfExists( params.Max, newValue.max );
|
||||
*/
|
||||
newValue->label = params.Label;
|
||||
qDebug() << " --- created: " << params.Label;
|
||||
setIfExists( params.IsWord, newValue.isWord );
|
||||
|
||||
return std::optional<BCValuePtr>( newValue );
|
||||
}
|
||||
newValue.label = params.Label;
|
||||
newValue.unitLabel = params.UnitLabel;
|
||||
|
||||
if( s_valueTypes.contains( params.ValueType ) )
|
||||
newValue.valueType = s_valueTypes[params.ValueType];
|
||||
|
||||
/*
|
||||
QString ID;
|
||||
QString Label;
|
||||
QString UnitLabel;
|
||||
QString Factor;
|
||||
QString Min;
|
||||
QString Max;
|
||||
QString IsWord;
|
||||
QString ValueType;
|
||||
*/
|
||||
|
||||
qDebug() << " --- created: " << params.Label;
|
||||
newValue.dumpValue();
|
||||
|
||||
return std::optional<BCValuePtr>( newValuePtr );
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// --- NEU: Speichern mit QXmlStreamWriter ---
|
||||
void BCXmlLoader::saveBikeData()
|
||||
{
|
||||
/*
|
||||
QString fileName = QFileDialog::getSaveFileName(this, "XML speichern", "", "XML Files (*.xml)");
|
||||
if (fileName.isEmpty()) return;
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QMessageBox::warning(this, "Fehler", "Datei konnte nicht zum Schreiben geöffnet werden.");
|
||||
return;
|
||||
}
|
||||
|
||||
QXmlStreamWriter xml(&file);
|
||||
xml.setAutoFormatting(true); // Sorgt für schöne Einrückungen (Tabs/Spaces)
|
||||
xml.writeStartDocument();
|
||||
xml.writeStartElement("devices");
|
||||
|
||||
// Daten vom Model holen
|
||||
const QList<Device> &devices = m_model->getDevices();
|
||||
|
||||
for (const Device &d : devices) {
|
||||
xml.writeStartElement("device");
|
||||
xml.writeAttribute("name", d.name);
|
||||
xml.writeAttribute("ip", d.ip);
|
||||
xml.writeEndElement(); // </device>
|
||||
}
|
||||
|
||||
xml.writeEndElement(); // </devices>
|
||||
xml.writeEndDocument();
|
||||
|
||||
// Prüfen ob alles geschrieben wurde
|
||||
if (file.error() != QFile::NoError) {
|
||||
QMessageBox::critical(this, "Fehler", "Fehler beim Schreiben der Datei.");
|
||||
} else {
|
||||
statusBar()->showMessage("Datei erfolgreich gespeichert!", 3000);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -33,15 +33,9 @@
|
||||
#ifndef BCXMLLOADER_H
|
||||
#define BCXMLLOADER_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QMetaEnum>
|
||||
|
||||
#include <QThread>
|
||||
#include <bcvaluemodel.h>
|
||||
|
||||
#include <bctransmitter.h>
|
||||
#include <bcvalue.h>
|
||||
|
||||
|
||||
class BCXmlLoader : public QObject
|
||||
@@ -55,8 +49,7 @@ public:
|
||||
|
||||
public slots:
|
||||
|
||||
void loadXmlBikeData( const QString& fileName );
|
||||
void saveBikeData();
|
||||
void loadXmlBikeData( const QString& fileName );;
|
||||
|
||||
signals:
|
||||
|
||||
@@ -64,16 +57,21 @@ signals:
|
||||
|
||||
protected:
|
||||
|
||||
struct BCDataParams
|
||||
struct BCValueParams
|
||||
{
|
||||
QString ID;
|
||||
QString Label;
|
||||
QString UnitType;
|
||||
QString UnitLabel;
|
||||
QString Factor;
|
||||
QString Min;
|
||||
QString Max;
|
||||
QString IsWord;
|
||||
QString ValueType;
|
||||
};
|
||||
|
||||
void loadXmlBikeDeviceData( BCDevice::ID deviceID );
|
||||
|
||||
std::optional<BCValuePtr> makeDataValue( BCDevice::ID deviceID, const BCDataParams& params );
|
||||
std::optional<BCValuePtr> makeValue( BCDevice::ID deviceID, const BCValueParams& params );
|
||||
|
||||
QXmlStreamReader _xml;
|
||||
|
||||
|
||||
BIN
doc/Challenges.docx
Normal file
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
@@ -1,7 +1,9 @@
|
||||
Challenges
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
BionxControl
|
||||
|
||||
Aufgabe:
|
||||
|
||||
@@ -10,12 +12,9 @@ Ansatz:
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
xtree
|
||||
|
||||
Aufgabe:
|
||||
|
||||
@@ -23,6 +22,7 @@ Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
znode
|
||||
|
||||
Aufgabe:
|
||||
|
||||
@@ -30,6 +30,7 @@ Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
libPigPio
|
||||
|
||||
Aufgabe:
|
||||
|
||||
@@ -37,6 +38,23 @@ Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
supportware
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
raDIYo
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
miniCash.connect
|
||||
|
||||
Aufgabe:
|
||||
|
||||
|
||||
BIN
doc/~$allenges.docx
Normal file
BIN
doc/~WRL0643.tmp
Normal file
2
main.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
BIN
resources/TinyCan_812.exe
Normal file
@@ -3,45 +3,50 @@
|
||||
<Bike name='franken-wheeler'>
|
||||
|
||||
<Device Type="Console">
|
||||
<Value ID='Cons_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Cons_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Cons_Sn_Product_Hi' Label='Product Number' ReadOnly='true' UnitType='Word'/>
|
||||
<Value ID='Cons_Sn_Oem_Hi' Label='OEM Number' ReadOnly='true' UnitType='Word' />
|
||||
<Value ID='Cons_Rev_Hw' Label='Hardware Version' />
|
||||
<Value ID='Cons_Rev_Sw' Label='Software Version' />
|
||||
|
||||
<Value ID='Cons_Assist_Initlevel' Label='Assistance Init Level' ReadOnly='false' UnitType='AssInit'/>
|
||||
<Value ID='Cons_Assist_Level_1' Label='Assistance Level 1' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_2' Label='Assistance Level 2' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_3' Label='Assistance Level 3' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_4' Label='Assistance Level 4' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Sn_Product_Hi' Label='Product Number' IsWord='1'/>
|
||||
<Value ID='Cons_Sn_Oem_Hi' Label='OEM Number' IsWord='1' />
|
||||
|
||||
<Value ID='Cons_Assist_Maxspeed_Flag' Label='Max Limit Enabled' ReadOnly='false' UnitType='Byte' />
|
||||
<Value ID='Cons_Assist_Maxspeed_Hi' Label='Max Speed Limit' ReadOnly='false' UnitType='Kmh' Factor='0.1'/>
|
||||
<Value ID='Cons_Assist_Initlevel' Label='Assistance Init Level' Min='0' Max='4'/>
|
||||
|
||||
<Value ID='Cons_Assist_Minspeed_Flag' Label='Min Limit Enabled' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Cons_Assist_Minspeed' Label='Min Speed Limit' ReadOnly='true' UnitType='Kmh'/>
|
||||
|
||||
<Value ID='Cons_Throttle_Maxspeed_Flag' Label='Throttle Limit Enabled' ReadOnly='true' UnitType='Byte'/>
|
||||
<Value ID='Cons_Throttle_Maxspeed_Hi' Label='Throttle Speed Limit' ReadOnly='true' UnitType='kmh' Factor='0.1'/>
|
||||
<Value ID='Cons_Assist_Level_1' Label='Assistance Level 1' Factor='1.5625' UnitLabel='%' Min='0' Max='400' />
|
||||
<Value ID='Cons_Assist_Level_2' Label='Assistance Level 2' Factor='1.5625' UnitLabel='%' Min='0' Max='400' />
|
||||
<Value ID='Cons_Assist_Level_3' Label='Assistance Level 3' Factor='1.5625' UnitLabel='%' Min='0' Max='400' />
|
||||
<Value ID='Cons_Assist_Level_4' Label='Assistance Level 4' Factor='1.5625' UnitLabel='%' Min='0' Max='400' />
|
||||
|
||||
<Value ID='Cons_Geometry_Circ_Hi' Label='Wheel Circumference' ReadOnly='true' UnitType='mm' />
|
||||
<Value ID='Cons_Assist_Mountain_Cap' Label='Mountain Cap' ReadOnly='true' UnitType='Percent' Factor='1.5625' />
|
||||
<Value ID='Cons_Assist_Maxspeed_Flag' Label='Max Limit Enabled' ValueType='bool' />
|
||||
<Value ID='Cons_Assist_Maxspeed_Hi' Label='Max Speed Limit' UnitLabel='km/h' Factor='0.1' Min='0' Max='70'/>
|
||||
|
||||
<Value ID='Cons_Assist_Minspeed_Flag' Label='Min Limit Enabled' ValueType='bool' />
|
||||
<Value ID='Cons_Assist_Minspeed' Label='Min Speed Limit' UnitLabel='km/h' Min='0' Max='70' />
|
||||
|
||||
<Value ID='Cons_Throttle_Maxspeed_Flag' Label='Throttle Limit Enabled' ValueType='bool'/>
|
||||
<Value ID='Cons_Throttle_Maxspeed_Hi' Label='Throttle Speed Limit' UnitLabel='km/h' Factor='0.1' Min='0' Max='70' />
|
||||
|
||||
<Value ID='Cons_Geometry_Circ_Hi' Label='Wheel Circumference' IsWord='1' UnitLabel='mm' Min='0' Max='2300' Factor='1.5625' />
|
||||
<Value ID='Cons_Assist_Mountain_Cap' Label='Mountain Cap' UnitLabel='%' Factor='1.5625' />
|
||||
</Device>
|
||||
|
||||
<!--
|
||||
<Device Type="Motor">
|
||||
<Value ID='Motor_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Motor_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Motor_Status_Temperature' Label='Motor Temperature' ReadOnly='true' UnitType='Degree'/>
|
||||
<Value ID='Motor_Assist_Maxspeed' Label='Motor max. Speed' ReadOnly='true' UnitType='Kmh' />
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Part Number' ReadOnly='true' UnitType='Word'/>
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Serial Number' ReadOnly='true' UnitType='Word' />
|
||||
<Value ID='Motor_Geometry_Circ_Hi' Label='Motor Gemetry' ReadOnly='true' UnitType='Mm' />
|
||||
<Value ID='Motor_Rev_Hw' Label='Hardware Version' />
|
||||
<Value ID='Motor_Rev_Sw' Label='Software Version' />
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Part Number' IsWord='1'/>
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Serial Number' IsWord='1' />
|
||||
<Value ID='Motor_Status_Temperature' Label='Motor Temperature' UnitLabel='°C' />
|
||||
<Value ID='Motor_Assist_Maxspeed' Label='Motor max. Speed' Reader='Kmh' />
|
||||
|
||||
<Value ID='Motor_Geometry_Circ_Hi' Label='Wheel Circumference' IsWord='1' UnitLabel='mm' Min='0' Max='2300' Factor='1.5625' />
|
||||
</Device>
|
||||
|
||||
<Device Type="Battery">
|
||||
<Value ID='Battery_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Battery_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Battery_Rev_Hw' Label='Hardware Version' />
|
||||
<Value ID='Battery_Rev_Sw' Label='Software Version' />
|
||||
</Device>
|
||||
|
||||
-->
|
||||
</Bike>
|
||||
|
||||
<!--
|
||||
@@ -57,106 +62,104 @@
|
||||
|
||||
|
||||
|
||||
<Value ID='Cons_Stat_Dist_Hi' Label='' ReadOnly='true' UnitType='mm' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Dist_Lo' Label='' ReadOnly='true' UnitType='mm'/>
|
||||
<Value ID='Cons_Stat_Avgspeed_Hi' Label='' ReadOnly='true' UnitType='mm' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Avgspeed_Lo' Label='' ReadOnly='true' UnitType='mm'/>
|
||||
<Value ID='Cons_Stat_Dist_Hi' Label='' Reader='mm' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Dist_Lo' Label='' Reader='mm'/>
|
||||
<Value ID='Cons_Stat_Avgspeed_Hi' Label='' Reader='mm' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Avgspeed_Lo' Label='' Reader='mm'/>
|
||||
|
||||
<Value ID='Cons_Stat_Odo_Hihi' Label='' ReadOnly='true' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Odo_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Odomoter_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Odo_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Odo_Hihi' Label='' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Odo_Hilo' Label='' />
|
||||
<Value ID='Cons_Stat_Odomoter_Lohi' Label='' />
|
||||
<Value ID='Cons_Stat_Odo_Lolo' Label='' />
|
||||
|
||||
<Value ID='Cons_Preference_Nip_Hihi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Calibrated' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Chrono_Second' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Chrono_Minute' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Chrono_Hour' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Lcd_Contrast' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Location' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Year' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Month' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Day' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Hihi' Label='' />
|
||||
<Value ID='Cons_Preference_Nip_Hilo' Label='' />
|
||||
<Value ID='Cons_Preference_Nip_Lohi' Label='' />
|
||||
<Value ID='Cons_Preference_Nip_Lolo' Label='' />
|
||||
<Value ID='Cons_Throttle_Calibrated' Label='' />
|
||||
<Value ID='Cons_Stat_Chrono_Second' Label='' />
|
||||
<Value ID='Cons_Stat_Chrono_Minute' Label='' />
|
||||
<Value ID='Cons_Stat_Chrono_Hour' Label='' />
|
||||
<Value ID='Cons_Preference_Lcd_Contrast' Label='' />
|
||||
<Value ID='Cons_Sn_Location' Label='' />
|
||||
<Value ID='Cons_Sn_Year' Label='' />
|
||||
<Value ID='Cons_Sn_Month' Label='' />
|
||||
<Value ID='Cons_Sn_Day' Label='' />
|
||||
|
||||
<Value ID='Cons_Sn_Pn_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Pn_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Item_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Item_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Pn_Hi' Label='' />
|
||||
<Value ID='Cons_Sn_Pn_Lo' Label='' />
|
||||
<Value ID='Cons_Sn_Item_Hi' Label='' />
|
||||
<Value ID='Cons_Sn_Item_Lo' Label='' />
|
||||
|
||||
<Value ID='Cons_Assist_Gauge_Joint' Label='' ReadOnly='true' Min='0' Max='11' />
|
||||
<Value ID='Cons_Throttle_Min_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Min_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Max_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Max_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Gauge_Joint' Label='' Min='0' Max='11' />
|
||||
<Value ID='Cons_Throttle_Min_Hi' Label='' />
|
||||
<Value ID='Cons_Throttle_Min_Lo' Label='' />
|
||||
<Value ID='Cons_Throttle_Max_Hi' Label='' />
|
||||
<Value ID='Cons_Throttle_Max_Lo' Label='' />
|
||||
|
||||
<Value ID='Cons_Preference_Light_On_At_Start' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Light_On_At_Start' Label='' />
|
||||
|
||||
|
||||
|
||||
<Value ID='Cons_Assist_Brake_Level' Label='' ReadOnly='true' Min='0' Max='64' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Preference_Trip_To_Empty_Flag' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Brake_Level' Label='' Min='0' Max='64' Factor='1.5625'/>
|
||||
<Value ID='Cons_Preference_Trip_To_Empty_Flag' Label='' />
|
||||
<Value ID='Cons_Preference_Display_Units' Default='1' />
|
||||
<Value ID='Cons_Throttle_Enabled_Onstrain' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Enabled_Onstrain' Label='' />
|
||||
|
||||
<Value ID='Cons_Assist_Brake_Flag' Default='1' />
|
||||
<Value ID='Cons_Assist_Brake_Polarity' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Gauge_Filter' Label='' ReadOnly='true' Min='0' Max='8' />
|
||||
<Value ID='Cons_Assist_Brake_Polarity' Label='' />
|
||||
<Value ID='Cons_Assist_Gauge_Filter' Label='' Min='0' Max='8' />
|
||||
|
||||
|
||||
<Value ID='Cons_Assist_Gauge_Gain' Label='' ReadOnly='true' Min='0.1' Max='4.0' Factor='0.1' />
|
||||
<Value ID='Cons_Assist_Gain_A' Label='' ReadOnly='true' Min='0.1' Max='4.0' Factor='0.1' />
|
||||
<Value ID='Cons_Assist_Gain_B' Label='' ReadOnly='true' Min='0.1' Max='25.0' Factor='0.1' />
|
||||
<Value ID='Cons_Sn_Type' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Region' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Configbit_0' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Enabled_Boost_Display' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Autoregen_Flag' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Gauge_Gain' Label='' Min='0.1' Max='4.0' Factor='0.1' />
|
||||
<Value ID='Cons_Assist_Gain_A' Label='' Min='0.1' Max='4.0' Factor='0.1' />
|
||||
<Value ID='Cons_Assist_Gain_B' Label='' Min='0.1' Max='25.0' Factor='0.1' />
|
||||
<Value ID='Cons_Sn_Type' Label='' />
|
||||
<Value ID='Cons_Preference_Region' Label='' />
|
||||
<Value ID='Cons_Preference_Configbit_0' Label='' />
|
||||
<Value ID='Cons_Throttle_Enabled_Boost_Display' Label='' />
|
||||
<Value ID='Cons_Assist_Autoregen_Flag' Label='' />
|
||||
|
||||
<Value ID='Cons_Rev_Sub' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Light_Button_Mode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Expertmode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Rev_Sub' Label='' />
|
||||
<Value ID='Cons_Preference_Light_Button_Mode' Label='' />
|
||||
<Value ID='Cons_Preference_Expertmode' Label='' />
|
||||
|
||||
|
||||
<Value ID='Cons_Preference_Codes_Hihi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hihi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Throttle_Mode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Hihi' Label='' />
|
||||
<Value ID='Cons_Preference_Codes_Hilo' Label='' />
|
||||
<Value ID='Cons_Preference_Codes_Lohi' Label='' />
|
||||
<Value ID='Cons_Preference_Codes_Lolo' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hihi' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hilo' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lohi' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lolo' Label='' />
|
||||
<Value ID='Cons_Preference_Throttle_Mode' Label='' />
|
||||
|
||||
|
||||
<Value ID='Cons_Throttle_Boost_Triggerlevel' Label='' ReadOnly='true' Min='1.5' Max='50.0' UnitType='Percent' Factor='1.5625' />
|
||||
<Value ID='Cons_Preference_Flip_Side' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Testmode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Testmode_Hw14' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Boost_Triggerlevel' Label='' Min='1.5' Max='50.0' Factor='1.5625' />
|
||||
<Value ID='Cons_Preference_Flip_Side' Label='' />
|
||||
<Value ID='Cons_Config_Testmode' Label='' />
|
||||
<Value ID='Cons_Config_Testmode_Hw14' Label='' />
|
||||
|
||||
<Value ID='Cons_Config_Last_Mode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Speedgain' Label='' ReadOnly='true' Factor='0.1' />
|
||||
<Value ID='Cons_Config_Last_Mode' Label='' />
|
||||
<Value ID='Cons_Assist_Speedgain' Label='' Factor='0.1' />
|
||||
|
||||
|
||||
<Value ID='Cons_Config_Last_Mode_On' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Last_Mode_Off' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Last_Mode_On' Label='' />
|
||||
<Value ID='Cons_Config_Last_Mode_Off' Label='' />
|
||||
|
||||
<Value ID='Cons_Status_Slave' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Status_Slave' Label='' />
|
||||
|
||||
<Value ID='Cons_Throttle_Raw_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Raw_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Position' Label='' ReadOnly='true' Factor='1.5625'/>
|
||||
<Value ID='Cons_Throttle_Raw_Hi' Label='' />
|
||||
<Value ID='Cons_Throttle_Raw_Lo' Label='' />
|
||||
<Value ID='Cons_Throttle_Position' Label='' Factor='1.5625'/>
|
||||
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_3' Label='' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_4' Label='' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Config_Service_Timestamp_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Service_Zimestamp_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Service_Distance_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Service_Distance_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_3' Label='' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_4' Label='' Factor='1.5625'/>
|
||||
<Value ID='Cons_Config_Service_Timestamp_Hi' Label='' />
|
||||
<Value ID='Cons_Config_Service_Zimestamp_Lo' Label='' />
|
||||
<Value ID='Cons_Config_Service_Distance_Hi' Label='' />
|
||||
<Value ID='Cons_Config_Service_Distance_Lo' Label='' />
|
||||
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_1' Label='' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_2' Label='' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_1' Label='' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_2' Label='' Factor='1.5625'/>
|
||||
|
||||
-->
|
||||
|
||||