/*************************************************************************** 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 @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 #include #include BCTransmitter::BCTransmitter(QObject *parent) : QObject(parent), _isBusy(false) { } void BCTransmitter::onToggleConnectionState( bool connect ) { if( connect ) { if( _canDriver.getState() != BCDriver::DriverState::Ready ) _canDriver.onStartDriver(); // fix! uint32_t hwVersion = _canDriver.readRawByte( (uint32_t)BCDevice::ID::Console, (uint8_t)BC::ID::Cons_Rev_Hw); if(!hwVersion) { qDebug() << "Console not responding"; } else { /* swVersion = getValue(CONSOLE, CONSOLE_REF_SW); printf( "Console information:" _NL " hardware version ........: %02d" _NL " software version ........: %02d" _NL " assistance level ........: %d" _NL, hwVersion, swVersion, getValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL) ); if (!gNoSerialNumbers) printf( " part number .............: %05d" _NL " item number .............: %05d" _NL _NL, ((getValue(CONSOLE, CONSOLE_SN_PN_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_PN_LO)), ((getValue(CONSOLE, CONSOLE_SN_ITEM_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_ITEM_LO)) ); */ } qDebug() << " ---HAIL to the kings: " << hwVersion; } } void BCTransmitter::enqueueValueOp(BC::OpID opID, const BCValue* value) { QMutexLocker locker(&_mutex); _valueQueue.enqueue( value ); // wir wollen nicht den ganzen Value verschicken, erstrecht // wollen wir den Value in verschiedenen Threads gleichzeitig // in die Hand nehmen, also hantieren wir nur mit den Inidizes. // Trigger processing im Event-Loop des Worker Threads // invokeMethod mit QueuedConnection entkoppelt den Aufruf, // damit enqueueValueOp sofort zurückkehrt (non-blocking für den Aufrufer). //QMetaObject::invokeMethod(this, "processValueOp", Qt::QueuedConnection); QMetaObject::invokeMethod(this, [this, opID]() { this->processValueOp(opID); }, Qt::QueuedConnection ); } void BCTransmitter::processValueOp( BC::OpID opID ) { if (_isBusy) return; _isBusy = true; while (true) { const BCValue* currentValue{}; { QMutexLocker locker(&_mutex); if (_valueQueue.isEmpty()) { _isBusy = false; break; // Schleife verlassen, warten auf neue Events } currentValue =_valueQueue.dequeue(); } // Mutex wird hier freigegeben! WICHTIG: Execute ohne Lock! try { // Abkürzung const BCValue& val = *currentValue; // Value ist 'under construction' //emit valueUpdated( val.deviceID, val.indexRow, BC::State::Locked ); if( opID == BC::OpID::ReadValue ) { QString result = currentValue->readRawValueX( *this ); emit valueUpdated( val.deviceID, val.indexRow, BC::State::InSync, result ); } else if( opID == BC::OpID::WriteValue ) { currentValue->writeRawValueX( *this ); } } catch (...) { qDebug() << " --- OUCH!"; } //emit valueStateChanged(cmd.id, true); //emit valueStateChanged(0, true); } } uint32_t BCTransmitter::readRawByte( uint32_t deviceID, uint8_t registerID ) const { uint32_t result{}; try { result = _canDriver.readRawByte( deviceID, registerID ); } catch ( BCException& exception ) { qDebug() << " -- OUCH: read exception: " << exception.what(); } return result; } void BCTransmitter::writeRawByte( uint32_t deviceID, uint8_t registerID , uint8_t value ) const { try { _canDriver.writeRawByte( deviceID, registerID, value ); } catch ( BCException& exception ) { qDebug() << " -- OUCH: write exception: " << exception.what(); } }