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()
{
_driverState = DriverState::Ready;
emit driverStateChanged( DriverState::Ready, "Driver Ready." );
_driverState = DriverState::DeviceReady;
emit driverStateChanged( DriverState::DeviceReady, "Driver Ready." );
}
/*
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)
throw BCException( "readRawValue error: driver not loaded." );
uint32_t myRandomByte = static_cast<uint32_t>(QRandomGenerator::global()->bounded(256));
Q_UNUSED(deviceID)
Q_UNUSED(registerID)
qDebug() << " --- DriverState: " << _driverState;
uint8_t myRandomByte = static_cast<uint8_t>(QRandomGenerator::global()->bounded(256));
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)
throw BCException( "readRawValue error: driver not loaded." );
Q_UNUSED(deviceID)
Q_UNUSED(registerID)
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
return;
return 0;
}

View File

@@ -34,7 +34,7 @@
#define BCDRIVER_H
#include <QObject>
#include <expected>
#include <bc.h>
/*
@@ -75,7 +75,7 @@ class BCDriverStatus;
* @Abstrakte Basisklasse für alle CAN-Bus Treiber.
* Das Bionx CAN-Bus System kann auf verschiedenen Wegen
* 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
* findet sich in der Unterklasse 'BCDriverTinyCan'.
@@ -90,6 +90,9 @@ class BCDriver : public QObject
public:
// Die möglichen Zustände beim Laden
// des CAN-Bus Treibers.
enum class DriverState
{
NotPresent,
@@ -97,17 +100,22 @@ public:
Loaded,
Initialized,
Opened, // bis hierher: dll vorhanden, Treiber geladen
Ready // hier: devices connectable
DeviceReady // hier: devices connectable
};
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 );
virtual ~BCDriver() = default;
DriverState getState() const;
virtual uint32_t 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 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:
@@ -132,8 +140,8 @@ public:
explicit BCDriverDummy( QObject* parent = nullptr );
uint32_t readRawByte( uint32_t deviceID, uint8_t registerID ) const override;
void writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const 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:

View File

@@ -35,7 +35,7 @@
#include <bcdrivertinycan.h>
#include <can_drv.h>
#include <expected>
@@ -57,16 +57,15 @@ void BCDriverTinyCan::onStartDriver()
void BCDriverTinyCan::loadDriver()
{
using Result=std::expected<DriverState,QString>;
auto callLoadDriver = []() -> Result
auto callLoadDriver = []() -> DriverStateResult
{
if( ::LoadDriver( NULL ) < 0 )
return std::unexpected(QString("Driver Error: 'LoadDriver'"));
return DriverState::Loaded;
};
auto callInitDriver = [](DriverState state) -> Result
auto callInitDriver = [](DriverState state) -> DriverStateResult
{
Q_UNUSED(state)
if( ::CanInitDriver( NULL ) < 0 )
@@ -74,7 +73,7 @@ void BCDriverTinyCan::loadDriver()
return DriverState::Initialized;
};
auto callOpenDevice = [](DriverState state) -> Result
auto callOpenDevice = [](DriverState state) -> DriverStateResult
{
Q_UNUSED(state)
if( ::CanDeviceOpen( 0, NULL ) < 0 )
@@ -122,27 +121,27 @@ BCDriver::DriverState BCDriverTinyCan::connectDriver()
// Console already in slave mode. good!
if( readRawByte( console, slaveFlag ) )
return DriverState::Ready;
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 ... " );
uint32_t isSlave = 0;
TransmitResult isSlave = 0;
do
{
writeRawByte( console, slaveFlag, 1 );
isSlave = readRawByte( console, slaveFlag );
isSlave = readRawByte( console, slaveFlag );
bc::delay_millis( 200 );
} while( retry-- && !isSlave );
} while( retry-- && !(*isSlave) );
bc::delay_millis( 500 ); // give the Console some time to settle
//if( !isSlave )
//emit statusHint( QString("putting Console in slave mode ") + (isSlave ? "done" : "failed") );
// 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)
throw BCException( "readRawValue error: driver not loaded." );
//TransmitResult
qDebug() << " --- DriverState: " << _driverState;
/*
Nicht hier!
if( getState() != DriverState::DeviceReady)
//throw BCException( "readRawValue error: driver not loaded." );
return std::nullopt;
*/
::TCanMsg msg;
// msg verpacken
@@ -192,7 +197,7 @@ uint32_t BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) c
bc::delay_millis( cTIMEOUT_MS );
if( timeOuts == -1 )
throw BCException( "readRawValue error: could not send value" );
return std::unexpected(QString("readRawValue error: could not send value" ));
retry:
@@ -203,7 +208,7 @@ retry:
bc::delay_millis( cTIMEOUT_MS );
if( timeOuts == -1 )
throw BCException( "getValue error: no response from node" );
return std::unexpected(QString("getValue error: no response from node" ));
// message empfangen
int err = ::CanReceive( 0, &msg, 1 );
@@ -222,22 +227,23 @@ retry:
goto retry;
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::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." );
*/
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
return;
::TCanMsg msg;
int timeout_count = cTIMEOUT_COUNT;
@@ -256,7 +262,8 @@ void BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID ,uint8
bc::delay_millis( cTIMEOUT_MS );
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 );
virtual ~BCDriverTinyCan() = default;
uint32_t readRawByte ( uint32_t deviceID, uint8_t registerID ) const override;
void writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
TransmitResult readRawByte ( uint32_t deviceID, uint8_t registerID ) const override;
TransmitResult writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
QString getNodeName( unsigned char id );
public slots:
void onStartDriver() override;

View File

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

View File

@@ -95,6 +95,7 @@ class ThemeSwitchButton : public QPushButton
Q_OBJECT
public:
explicit ThemeSwitchButton(QWidget *parent = nullptr)
: QPushButton(parent), m_isDarkMode(true)
{
@@ -103,9 +104,9 @@ public:
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"(
// 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;
@@ -113,7 +114,7 @@ public:
}
QPushButton:hover {
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( _canDriver->getState() != BCDriver::DriverState::Ready )
if( _canDriver->getState() != BCDriver::DriverState::DeviceReady )
_canDriver->onStartDriver();
// __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)
{
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
{
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();
}
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
{

View File

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

View File

@@ -66,8 +66,8 @@ class BCAbstractTransmitter
public:
virtual uint32_t readRawByte( uint32_t deviceID, uint8_t registerID ) const = 0;
virtual void writeRawByte( uint32_t deviceID, uint8_t registerID , uint8_t value_ ) const = 0;
virtual uint8_t readByte ( uint32_t deviceID, uint8_t registerID ) 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
{
uint32_t result = transmitter.readRawByte( deviceID, registerID );
uint8_t result = transmitter.readByte( deviceID, registerID );
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)),
// hi byte
uint32_t result = transmitter.readRawByte( deviceID, registerID ) << 8;
uint8_t result = transmitter.readByte( deviceID, registerID ) << 8;
// low byte, use followup register: +1
result += transmitter.readRawByte( deviceID, registerID+1 );
result += transmitter.readByte( deviceID, registerID+1 );
return formatValue( result );
}