diff --git a/bcdriver.cpp b/bcdriver.cpp index c9a1b4a..d99f458 100644 --- a/bcdriver.cpp +++ b/bcdriver.cpp @@ -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(QRandomGenerator::global()->bounded(256)); + Q_UNUSED(deviceID) + Q_UNUSED(registerID) + qDebug() << " --- DriverState: " << _driverState; + uint8_t myRandomByte = static_cast(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; } diff --git a/bcdriver.h b/bcdriver.h index b696bdc..1406989 100644 --- a/bcdriver.h +++ b/bcdriver.h @@ -34,7 +34,7 @@ #define BCDRIVER_H #include - +#include #include /* @@ -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; + // Enthält den gelesenen Wert oder einen Fehlerstring + using TransmitResult = std::expected; + 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: diff --git a/bcdrivertinycan.cpp b/bcdrivertinycan.cpp index 7f2d0bf..490de1c 100644 --- a/bcdrivertinycan.cpp +++ b/bcdrivertinycan.cpp @@ -35,7 +35,7 @@ #include #include -#include + @@ -57,16 +57,15 @@ void BCDriverTinyCan::onStartDriver() void BCDriverTinyCan::loadDriver() { - using Result=std::expected; - 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: @@ -202,8 +207,8 @@ retry: while( timeOuts-- && !::CanReceiveGetCount( 0 ) ) bc::delay_millis( cTIMEOUT_MS ); - if( timeOuts == -1 ) - throw BCException( "getValue error: no response from node" ); + if( timeOuts == -1 ) + 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' } diff --git a/bcdrivertinycan.h b/bcdrivertinycan.h index 05c85ae..543c731 100644 --- a/bcdrivertinycan.h +++ b/bcdrivertinycan.h @@ -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; diff --git a/bcmainwindow.cpp b/bcmainwindow.cpp index 924fe98..bb04bce 100644 --- a/bcmainwindow.cpp +++ b/bcmainwindow.cpp @@ -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"); qRegisterMetaType>("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); diff --git a/bcmainwindow.h b/bcmainwindow.h index ba4cf0f..3aadbfb 100644 --- a/bcmainwindow.h +++ b/bcmainwindow.h @@ -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; } )"); diff --git a/bctransmitter.cpp b/bctransmitter.cpp index e1d850f..588e935 100644 --- a/bctransmitter.cpp +++ b/bctransmitter.cpp @@ -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 { diff --git a/bctransmitter.h b/bctransmitter.h index 2c8f7cf..258122f 100644 --- a/bctransmitter.h +++ b/bctransmitter.h @@ -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: diff --git a/bcvalue.h b/bcvalue.h index 310cced..1db18f6 100644 --- a/bcvalue.h +++ b/bcvalue.h @@ -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; }; diff --git a/bcvaluetype.cpp b/bcvaluetype.cpp index 759b739..173feb8 100644 --- a/bcvaluetype.cpp +++ b/bcvaluetype.cpp @@ -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 ); }