Rework driver code, again.

This commit is contained in:
2026-01-01 13:28:17 +01:00
parent 6b039e4b7f
commit 6e860d8d05
10 changed files with 91 additions and 71 deletions

View File

@@ -61,8 +61,8 @@ BCDriver::DriverState BCDriver::getState() const
void BCDriverDummy::onStartDriver() void BCDriverDummy::onStartDriver()
{ {
_driverState = DriverState::Ready; _driverState = DriverState::DeviceReady;
emit driverStateChanged( DriverState::Ready, "Driver Ready." ); emit driverStateChanged( DriverState::DeviceReady, "Driver Ready." );
} }
/* /*
try try
@@ -101,22 +101,21 @@ BCDriverDummy::BCDriverDummy( QObject* parent )
} }
uint32_t BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID ) const BCDriver::TransmitResult BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID ) const
{ {
if( getState() != DriverState::Ready) Q_UNUSED(deviceID)
throw BCException( "readRawValue error: driver not loaded." ); Q_UNUSED(registerID)
qDebug() << " --- DriverState: " << _driverState;
uint32_t myRandomByte = static_cast<uint32_t>(QRandomGenerator::global()->bounded(256)); uint8_t myRandomByte = static_cast<uint8_t>(QRandomGenerator::global()->bounded(256));
return myRandomByte; return myRandomByte;
} }
void BCDriverDummy::writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const BCDriver::TransmitResult BCDriverDummy::writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const
{ {
if( getState() != DriverState::Ready) Q_UNUSED(deviceID)
throw BCException( "readRawValue error: driver not loaded." ); Q_UNUSED(registerID)
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value; qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
return; return 0;
} }

View File

@@ -34,7 +34,7 @@
#define BCDRIVER_H #define BCDRIVER_H
#include <QObject> #include <QObject>
#include <expected>
#include <bc.h> #include <bc.h>
/* /*
@@ -75,7 +75,7 @@ class BCDriverStatus;
* @Abstrakte Basisklasse für alle CAN-Bus Treiber. * @Abstrakte Basisklasse für alle CAN-Bus Treiber.
* Das Bionx CAN-Bus System kann auf verschiedenen Wegen * Das Bionx CAN-Bus System kann auf verschiedenen Wegen
* angesprochen werden, etwa den über BBI USB2CAN Controller, * angesprochen werden, etwa den über BBI USB2CAN Controller,
* über den TinyCAN Adapter oder ggf. über einen EL327 Stecker. * über den TinyCAN Adapter oder ggf. über einen ELM327 Stecker.
* *
* Die hier relevante Implementierung über das TinyCan System * Die hier relevante Implementierung über das TinyCan System
* findet sich in der Unterklasse 'BCDriverTinyCan'. * findet sich in der Unterklasse 'BCDriverTinyCan'.
@@ -90,6 +90,9 @@ class BCDriver : public QObject
public: public:
// Die möglichen Zustände beim Laden
// des CAN-Bus Treibers.
enum class DriverState enum class DriverState
{ {
NotPresent, NotPresent,
@@ -97,17 +100,22 @@ public:
Loaded, Loaded,
Initialized, Initialized,
Opened, // bis hierher: dll vorhanden, Treiber geladen Opened, // bis hierher: dll vorhanden, Treiber geladen
Ready // hier: devices connectable DeviceReady // hier: devices connectable
}; };
Q_ENUM(DriverState) Q_ENUM(DriverState)
// Enthält den Treiberzustand oder einen Fehlerstring
using DriverStateResult = std::expected<DriverState,QString>;
// Enthält den gelesenen Wert oder einen Fehlerstring
using TransmitResult = std::expected<uint8_t,QString>;
explicit BCDriver( QObject* parent = nullptr ); explicit BCDriver( QObject* parent = nullptr );
virtual ~BCDriver() = default; virtual ~BCDriver() = default;
DriverState getState() const; DriverState getState() const;
virtual uint32_t readRawByte( uint32_t deviceID, uint8_t registerID ) const = 0; virtual TransmitResult readRawByte( uint32_t deviceID, uint8_t registerID ) const = 0;
virtual void writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const = 0; virtual TransmitResult writeRawByte(uint32_t deviceID, uint8_t registerID, uint8_t value ) const = 0;
public slots: public slots:
@@ -132,8 +140,8 @@ public:
explicit BCDriverDummy( QObject* parent = nullptr ); explicit BCDriverDummy( QObject* parent = nullptr );
uint32_t readRawByte( uint32_t deviceID, uint8_t registerID ) const override; TransmitResult readRawByte( uint32_t deviceID, uint8_t registerID ) const override;
void writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override; TransmitResult writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
public slots: public slots:

View File

@@ -35,7 +35,7 @@
#include <bcdrivertinycan.h> #include <bcdrivertinycan.h>
#include <can_drv.h> #include <can_drv.h>
#include <expected>
@@ -57,16 +57,15 @@ void BCDriverTinyCan::onStartDriver()
void BCDriverTinyCan::loadDriver() void BCDriverTinyCan::loadDriver()
{ {
using Result=std::expected<DriverState,QString>;
auto callLoadDriver = []() -> Result auto callLoadDriver = []() -> DriverStateResult
{ {
if( ::LoadDriver( NULL ) < 0 ) if( ::LoadDriver( NULL ) < 0 )
return std::unexpected(QString("Driver Error: 'LoadDriver'")); return std::unexpected(QString("Driver Error: 'LoadDriver'"));
return DriverState::Loaded; return DriverState::Loaded;
}; };
auto callInitDriver = [](DriverState state) -> Result auto callInitDriver = [](DriverState state) -> DriverStateResult
{ {
Q_UNUSED(state) Q_UNUSED(state)
if( ::CanInitDriver( NULL ) < 0 ) if( ::CanInitDriver( NULL ) < 0 )
@@ -74,7 +73,7 @@ void BCDriverTinyCan::loadDriver()
return DriverState::Initialized; return DriverState::Initialized;
}; };
auto callOpenDevice = [](DriverState state) -> Result auto callOpenDevice = [](DriverState state) -> DriverStateResult
{ {
Q_UNUSED(state) Q_UNUSED(state)
if( ::CanDeviceOpen( 0, NULL ) < 0 ) if( ::CanDeviceOpen( 0, NULL ) < 0 )
@@ -122,27 +121,27 @@ BCDriver::DriverState BCDriverTinyCan::connectDriver()
// Console already in slave mode. good! // Console already in slave mode. good!
if( readRawByte( console, slaveFlag ) ) if( readRawByte( console, slaveFlag ) )
return DriverState::Ready; return DriverState::DeviceReady;
qDebug() << "BCDriverTinyCan::BCDriverTinyCan::XXX Driver Init: putting Console in slave mode ... "; qDebug() << "BCDriverTinyCan::BCDriverTinyCan::XXX Driver Init: putting Console in slave mode ... ";
unsigned int retry = cTimeOuts; unsigned int retry = cTimeOuts;
emit driverStateChanged( _driverState, "Driver Init: putting Console in slave mode ... " ); emit driverStateChanged( _driverState, "Driver Init: putting Console in slave mode ... " );
uint32_t isSlave = 0; TransmitResult isSlave = 0;
do do
{ {
writeRawByte( console, slaveFlag, 1 ); writeRawByte( console, slaveFlag, 1 );
isSlave = readRawByte( console, slaveFlag ); isSlave = readRawByte( console, slaveFlag );
bc::delay_millis( 200 ); bc::delay_millis( 200 );
} while( retry-- && !isSlave ); } while( retry-- && !(*isSlave) );
bc::delay_millis( 500 ); // give the Console some time to settle bc::delay_millis( 500 ); // give the Console some time to settle
//if( !isSlave ) //if( !isSlave )
//emit statusHint( QString("putting Console in slave mode ") + (isSlave ? "done" : "failed") ); //emit statusHint( QString("putting Console in slave mode ") + (isSlave ? "done" : "failed") );
// ist das jetzt irgendwie schlimm, wenn wir keine slave Console haben // ist das jetzt irgendwie schlimm, wenn wir keine slave Console haben
return isSlave ? DriverState::Ready : DriverState::Opened; return isSlave ? DriverState::DeviceReady : DriverState::Opened;
} }
@@ -165,12 +164,18 @@ BCDriver::DriverState BCDriverTinyCan::connectDriver()
uint32_t BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) const BCDriver::TransmitResult BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) const
{ {
if( getState() != DriverState::Ready) //TransmitResult
throw BCException( "readRawValue error: driver not loaded." ); qDebug() << " --- DriverState: " << _driverState;
/*
Nicht hier!
if( getState() != DriverState::DeviceReady)
//throw BCException( "readRawValue error: driver not loaded." );
return std::nullopt;
*/
::TCanMsg msg; ::TCanMsg msg;
// msg verpacken // msg verpacken
@@ -192,7 +197,7 @@ uint32_t BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) c
bc::delay_millis( cTIMEOUT_MS ); bc::delay_millis( cTIMEOUT_MS );
if( timeOuts == -1 ) if( timeOuts == -1 )
throw BCException( "readRawValue error: could not send value" ); return std::unexpected(QString("readRawValue error: could not send value" ));
retry: retry:
@@ -202,8 +207,8 @@ retry:
while( timeOuts-- && !::CanReceiveGetCount( 0 ) ) while( timeOuts-- && !::CanReceiveGetCount( 0 ) )
bc::delay_millis( cTIMEOUT_MS ); bc::delay_millis( cTIMEOUT_MS );
if( timeOuts == -1 ) if( timeOuts == -1 )
throw BCException( "getValue error: no response from node" ); return std::unexpected(QString("getValue error: no response from node" ));
// message empfangen // message empfangen
int err = ::CanReceive( 0, &msg, 1 ); int err = ::CanReceive( 0, &msg, 1 );
@@ -222,22 +227,23 @@ retry:
goto retry; goto retry;
if( !timeOuts ) if( !timeOuts )
throw BCException( "CAN --response errror" ); return std::unexpected(QString("CAN response errror: timeout" ));
return (uint32_t) msg.MsgData[3]; return (uint8_t) msg.MsgData[3];
} }
// void BCDriverTinyCan::setValue( unsigned char receipient, unsigned char reg, unsigned char value ) // void BCDriverTinyCan::setValue( unsigned char receipient, unsigned char reg, unsigned char value )
void BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID ,uint8_t value ) const BCDriver::TransmitResult BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID ,uint8_t value ) const
{ {
if( getState() != DriverState::Ready) /*
Nicht hier!
if( getState() != DriverState::DeviceReady)
throw BCException( "writeRawValue error: driver not loaded." ); throw BCException( "writeRawValue error: driver not loaded." );
*/
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value; qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
return;
::TCanMsg msg; ::TCanMsg msg;
int timeout_count = cTIMEOUT_COUNT; int timeout_count = cTIMEOUT_COUNT;
@@ -256,7 +262,8 @@ void BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID ,uint8
bc::delay_millis( cTIMEOUT_MS ); bc::delay_millis( cTIMEOUT_MS );
if( timeout_count == -1 ) if( timeout_count == -1 )
emit driverStateChanged( _driverState, QString( "error: could not send value to %1" ).arg( deviceID ) ); return std::unexpected(QString("error: could not send value to %1" ).arg( deviceID ) );
return 1; // als 'true'
} }

View File

@@ -44,11 +44,14 @@ public:
explicit BCDriverTinyCan( QObject* parent=nullptr ); explicit BCDriverTinyCan( QObject* parent=nullptr );
virtual ~BCDriverTinyCan() = default; virtual ~BCDriverTinyCan() = default;
uint32_t readRawByte ( uint32_t deviceID, uint8_t registerID ) const override; TransmitResult readRawByte ( uint32_t deviceID, uint8_t registerID ) const override;
void writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override; TransmitResult writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
QString getNodeName( unsigned char id ); QString getNodeName( unsigned char id );
public slots: public slots:
void onStartDriver() override; void onStartDriver() override;

View File

@@ -46,14 +46,18 @@
BCMainWindow::BCMainWindow(QWidget *parent) BCMainWindow::BCMainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
{ {
// WICHTIG: Registriere sowohl das Struct als auch die LISTE des Structs // __fix! in der Form nötig?
qRegisterMetaType<BCValue>("BCValue"); qRegisterMetaType<BCValue>("BCValue");
qRegisterMetaType<QList<BCValue>>("BCValueList"); qRegisterMetaType<QList<BCValue>>("BCValueList");
setupUi(this); setupUi(this);
// BESTE PRAXIS: QTimer::singleShot mit Lambda // Wir schreiben den 'initMainWindow()' Aufruf mit Hilfe des
QTimer::singleShot(0, this, [this]() { // timers in die Event-Queue, damit er erst ausgeführt wird,
// wenn das Fenster sichtbar ist.
QTimer::singleShot(0, this, [this]()
{
initMainWindow(); initMainWindow();
}); });
@@ -88,13 +92,12 @@ void BCMainWindow::setHeaderLabel( const QString& headerText)
void BCMainWindow::initMainWindow() void BCMainWindow::initMainWindow()
{ {
// Lambda um die buttons mit ihren Actions zu verbinden
auto configureAction = [&]( QToolButton* button, QAction* action, BCDevice::ID deviceID ) auto configureAction = [&]( QToolButton* button, QAction* action, BCDevice::ID deviceID )
{ {
// Action an den Button binden // Action an den Button binden
button->setDefaultAction( action); button->setDefaultAction( action);
// old school, not used
//connect( action, &QAction::triggered, this, &BCMainWindow::onActionButtonTriggered );
//connect( action, &QAction::toggled, this, &BCMainWindow::onActionButtonToggled );
// new way: die DeviceID muss aber explizit vom Lambda eingefanden werden. // new way: die DeviceID muss aber explizit vom Lambda eingefanden werden.
connect( action, &QAction::triggered, this, [this,deviceID]() connect( action, &QAction::triggered, this, [this,deviceID]()
@@ -114,11 +117,11 @@ void BCMainWindow::initMainWindow()
} }
}; };
// Wir wollen die Devices den Views zuordnen können // Wir wollen die Devices den Views zuordnen können
_devicePanels[BCDevice::ID::Console] = _consolePanel; _devicePanels[BCDevice::ID::Console] = _consolePanel;
_devicePanels[BCDevice::ID::Battery] = _batteryPanel; _devicePanels[BCDevice::ID::Battery] = _batteryPanel;
_devicePanels[BCDevice::ID::Motor] = _motorPanel; _devicePanels[BCDevice::ID::Motor] = _motorPanel;
_devicePanels[BCDevice::ID::Pimp] = _pimpPanel;
// Die actions an die Buttons binden // Die actions an die Buttons binden
configureAction(_motorButton, _motorAction, BCDevice::ID::Motor ); configureAction(_motorButton, _motorAction, BCDevice::ID::Motor );
@@ -161,7 +164,7 @@ void BCMainWindow::initMainWindow()
_worker.start(); _worker.start();
bc::processEventsFor(2000);
// die Daten des eBikes laden // die Daten des eBikes laden
_dataManager.loadXmlBikeData(":/bikeinfo.xml"_L1); _dataManager.loadXmlBikeData(":/bikeinfo.xml"_L1);

View File

@@ -95,6 +95,7 @@ class ThemeSwitchButton : public QPushButton
Q_OBJECT Q_OBJECT
public: public:
explicit ThemeSwitchButton(QWidget *parent = nullptr) explicit ThemeSwitchButton(QWidget *parent = nullptr)
: QPushButton(parent), m_isDarkMode(true) : QPushButton(parent), m_isDarkMode(true)
{ {
@@ -103,9 +104,9 @@ public:
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
setFixedSize(24, 24); // Kleiner Footprint im StatusBar setFixedSize(24, 24); // Kleiner Footprint im StatusBar
// CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt // CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt
// Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind // Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind
setStyleSheet(R"( setStyleSheet(R"(
QPushButton { QPushButton {
border: none; border: none;
background-color: transparent; background-color: transparent;
@@ -113,7 +114,7 @@ public:
} }
QPushButton:hover { QPushButton:hover {
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
border-radius: 4px; border-radius: 24px;
} }
)"); )");

View File

@@ -47,12 +47,11 @@ void BCTransmitter::onToggleConnectionState( bool connect )
{ {
if( connect ) if( connect )
{ {
if( _canDriver->getState() != BCDriver::DriverState::Ready ) if( _canDriver->getState() != BCDriver::DriverState::DeviceReady )
_canDriver->onStartDriver(); _canDriver->onStartDriver();
// __fix! // __fix!
uint32_t hwVersion = _canDriver->readRawByte( (uint32_t)BCDevice::ID::Console, (uint8_t)BC::ID::Cons_Rev_Hw); BCDriver::TransmitResult hwVersion = _canDriver->readRawByte( (uint32_t)BCDevice::ID::Console, (uint8_t)BC::ID::Cons_Rev_Hw);
if(!hwVersion) if(!hwVersion)
{ {
qDebug() << "Console not responding"; qDebug() << "Console not responding";
@@ -63,7 +62,7 @@ void BCTransmitter::onToggleConnectionState( bool connect )
} }
qDebug() << " ---HAIL to the kings: " << hwVersion; qDebug() << " ---HAIL to the kings: " << hwVersion.value();
} }
} }
@@ -141,9 +140,9 @@ void BCTransmitter::processValueOp( BCValue::OpID opID )
} }
} }
uint32_t BCTransmitter::readRawByte( uint32_t deviceID, uint8_t registerID ) const uint8_t BCTransmitter::readByte( uint32_t deviceID, uint8_t registerID ) const
{ {
uint32_t result{}; BCDriver::TransmitResult result;
try try
{ {
result = _canDriver->readRawByte( deviceID, registerID ); result = _canDriver->readRawByte( deviceID, registerID );
@@ -152,11 +151,11 @@ uint32_t BCTransmitter::readRawByte( uint32_t deviceID, uint8_t registerID ) c
{ {
qDebug() << " -- OUCH: read exception: " << exception.what(); qDebug() << " -- OUCH: read exception: " << exception.what();
} }
return result; return result.value();
} }
void BCTransmitter::writeRawByte( uint32_t deviceID, uint8_t registerID , uint8_t value ) const void BCTransmitter::writeByte( uint32_t deviceID, uint8_t registerID , uint8_t value ) const
{ {
try try
{ {

View File

@@ -50,8 +50,8 @@ public:
explicit BCTransmitter(QObject *parent = nullptr); explicit BCTransmitter(QObject *parent = nullptr);
uint32_t readRawByte( uint32_t deviceID, uint8_t registerID ) const override; uint8_t readByte( uint32_t deviceID, uint8_t registerID ) const override;
void writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override; void writeByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
public slots: public slots:

View File

@@ -66,8 +66,8 @@ class BCAbstractTransmitter
public: public:
virtual uint32_t readRawByte( uint32_t deviceID, uint8_t registerID ) const = 0; virtual uint8_t readByte ( uint32_t deviceID, uint8_t registerID ) const = 0;
virtual void writeRawByte( uint32_t deviceID, uint8_t registerID , uint8_t value_ ) const = 0; virtual void writeByte( uint32_t deviceID, uint8_t registerID, uint8_t value_ ) const = 0;
}; };

View File

@@ -108,7 +108,7 @@ BCValueTypeByte::BCValueTypeByte( QString unitLabel_, double factor_, optDouble
QString BCValueTypeByte::createStringValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID ) const QString BCValueTypeByte::createStringValue( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID ) const
{ {
uint32_t result = transmitter.readRawByte( deviceID, registerID ); uint8_t result = transmitter.readByte( deviceID, registerID );
return formatValue( result ); return formatValue( result );
} }
@@ -124,9 +124,9 @@ QString BCValueTypeWord::createStringValue( const BCAbstractTransmitter& transmi
{ {
//getValue(CONSOLE, CONSOLE_SN_PN_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_PN_LO)), //getValue(CONSOLE, CONSOLE_SN_PN_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_PN_LO)),
// hi byte // hi byte
uint32_t result = transmitter.readRawByte( deviceID, registerID ) << 8; uint8_t result = transmitter.readByte( deviceID, registerID ) << 8;
// low byte, use followup register: +1 // low byte, use followup register: +1
result += transmitter.readRawByte( deviceID, registerID+1 ); result += transmitter.readByte( deviceID, registerID+1 );
return formatValue( result ); return formatValue( result );
} }