Compare commits
4 Commits
try-smart-
...
56ab0fbc0f
| Author | SHA1 | Date | |
|---|---|---|---|
| 56ab0fbc0f | |||
| 61bf3b2cec | |||
| c5dc84179b | |||
| 6032abb35c |
@@ -36,7 +36,6 @@ SOURCES += \
|
|||||||
bctransmitter.cpp \
|
bctransmitter.cpp \
|
||||||
bcvalue.cpp \
|
bcvalue.cpp \
|
||||||
bcvaluemodel.cpp \
|
bcvaluemodel.cpp \
|
||||||
bcvaluetype.cpp \
|
|
||||||
bcxmlloader.cpp \
|
bcxmlloader.cpp \
|
||||||
lib/can_drv_win.c \
|
lib/can_drv_win.c \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
@@ -52,7 +51,6 @@ HEADERS += \
|
|||||||
bctransmitter.h \
|
bctransmitter.h \
|
||||||
bcvalue.h \
|
bcvalue.h \
|
||||||
bcvaluemodel.h \
|
bcvaluemodel.h \
|
||||||
bcvaluetype.h \
|
|
||||||
bcxmlloader.h
|
bcxmlloader.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
|||||||
7
bc.h
7
bc.h
@@ -773,15 +773,16 @@ namespace BCTags
|
|||||||
inline constexpr auto Device = "Device"_L1;
|
inline constexpr auto Device = "Device"_L1;
|
||||||
inline constexpr auto ID = "ID"_L1;
|
inline constexpr auto ID = "ID"_L1;
|
||||||
inline constexpr auto Label = "Label"_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 Default = "Default"_L1;
|
||||||
|
|
||||||
inline constexpr auto Current = "Current"_L1;
|
inline constexpr auto Current = "Current"_L1;
|
||||||
inline constexpr auto Enabled = "Enabled"_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 Min = "Min"_L1;
|
||||||
inline constexpr auto Max = "Max"_L1;
|
inline constexpr auto Max = "Max"_L1;
|
||||||
inline constexpr auto Factor = "Factor"_L1;
|
inline constexpr auto Factor = "Factor"_L1;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // BC_H
|
#endif // BC_H
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
#include <bcvalue.h>
|
#include <bcvalue.h>
|
||||||
#include <bcvaluetype.h>
|
|
||||||
/*
|
/*
|
||||||
int32_t CanInitDriver(char *options);
|
int32_t CanInitDriver(char *options);
|
||||||
void CanDownDriver(void);
|
void CanDownDriver(void);
|
||||||
|
|||||||
@@ -34,9 +34,11 @@
|
|||||||
#define BCMAINWINDOW_H
|
#define BCMAINWINDOW_H
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
#include <ui_bcmainwindow.h>
|
#include <ui_bcmainwindow.h>
|
||||||
#include <bcxmlloader.h>
|
#include <bcxmlloader.h>
|
||||||
|
#include <bctransmitter.h>
|
||||||
|
|
||||||
class BCDeviceView;
|
class BCDeviceView;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "bcvaluetype.h"
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
@@ -121,7 +120,7 @@ void BCTransmitter::processValue()
|
|||||||
// Value ist 'under construction'
|
// Value ist 'under construction'
|
||||||
//emit valueUpdated( value.deviceID, value.indexRow, BCValue::State::Locked );
|
//emit valueUpdated( value.deviceID, value.indexRow, BCValue::State::Locked );
|
||||||
|
|
||||||
const BCValueType& valueType = *value.valueType;
|
|
||||||
uint32_t devID = static_cast<uint32_t>(value.deviceID);
|
uint32_t devID = static_cast<uint32_t>(value.deviceID);
|
||||||
uint8_t regID = static_cast<uint8_t> (value.registerID);
|
uint8_t regID = static_cast<uint8_t> (value.registerID);
|
||||||
|
|
||||||
@@ -138,19 +137,17 @@ void BCTransmitter::processValue()
|
|||||||
|
|
||||||
else if( value.state.testFlag( BCValue::State::ReadMe ) )
|
else if( value.state.testFlag( BCValue::State::ReadMe ) )
|
||||||
{
|
{
|
||||||
|
|
||||||
// wir sind hier im anderen thread! nicht einfach so reinschreiben, nur lesen
|
// 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() )
|
if( result.has_value() )
|
||||||
{
|
{
|
||||||
newVisibleValue = valueType.formatValue( result.value() );
|
newVisibleValue = value.formatValue( result.value() );
|
||||||
newState = BCValue::State::InSync;
|
newState = BCValue::State::InSync;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newState = BCValue::State::Failed;
|
newState = BCValue::State::Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit valueUpdated( value.deviceID, value.indexRow, newState, newVisibleValue );
|
emit valueUpdated( value.deviceID, value.indexRow, newState, newVisibleValue );
|
||||||
@@ -164,30 +161,30 @@ void BCTransmitter::processValue()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
TransmitResult BCTransmitter::readByteValue( uint32_t deviceID, uint8_t registerID )
|
||||||
* @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
|
|
||||||
{
|
{
|
||||||
|
qDebug() << " --- YES: Read ByteValue: " << registerID;
|
||||||
|
// Wir lesen nur ein Byte und gut.
|
||||||
return _canDriver->readRawByte( deviceID, registerID );
|
return _canDriver->readRawByte( deviceID, registerID );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
TransmitResult BCTransmitter::readWordValue( uint32_t deviceID, uint8_t 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
|
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include <bcvalue.h>
|
#include <bcvalue.h>
|
||||||
#include <bcvaluetype.h>
|
|
||||||
#include <bcdrivertinycan.h>
|
#include <bcdrivertinycan.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +52,7 @@
|
|||||||
* implementiert sein und liest/schreibt Byteweise auf den Bus.
|
* implementiert sein und liest/schreibt Byteweise auf den Bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BCTransmitter : public QObject, public BCAbstractTransmitter
|
class BCTransmitter : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -61,8 +60,8 @@ public:
|
|||||||
|
|
||||||
explicit BCTransmitter(QObject *parent = nullptr);
|
explicit BCTransmitter(QObject *parent = nullptr);
|
||||||
|
|
||||||
TransmitResult readByte( uint32_t deviceID, uint8_t registerID ) const override;
|
//TransmitResult readByte( uint32_t deviceID, uint8_t registerID ) const override;
|
||||||
TransmitResult writeByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
|
//TransmitResult writeByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
@@ -77,8 +76,11 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void readRawValueX ( const BCValue& value ) const;
|
TransmitResult readByteValue( uint32_t deviceID, uint8_t registerID );
|
||||||
void writeRawValueX( const BCValue& value ) const;
|
TransmitResult readWordValue( uint32_t deviceID, uint8_t registerID );
|
||||||
|
//TransmitResult writeByteValue( uint32_t deviceID, uint8_t registerID );
|
||||||
|
//TransmitResult writeWordValue( uint32_t deviceID, uint8_t registerID );
|
||||||
|
|
||||||
|
|
||||||
using BCDataQueue = QQueue<BCValuePtrConst>;
|
using BCDataQueue = QQueue<BCValuePtrConst>;
|
||||||
|
|
||||||
|
|||||||
51
bcvalue.cpp
51
bcvalue.cpp
@@ -33,16 +33,61 @@
|
|||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
|
|
||||||
#include <bcvalue.h>
|
#include <bcvalue.h>
|
||||||
#include <bcvaluetype.h>
|
|
||||||
|
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
|
|
||||||
|
|
||||||
BCValue::BCValue(const BCValueType* valueType_, BCDevice::ID deviceID_, BC::ID registerID_)
|
BCValue::BCValue( BCDevice::ID deviceID_, BC::ID registerID_)
|
||||||
: valueType{valueType_}, deviceID{deviceID_}, registerID{registerID_}
|
: deviceID{deviceID_}, registerID{registerID_}
|
||||||
{
|
{
|
||||||
visibleValue = "--";
|
visibleValue = "--";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QString BCValue::formatValue( uint32_t value ) const
|
||||||
|
{
|
||||||
|
if( factor == 1 )
|
||||||
|
return QString::number( value );
|
||||||
|
|
||||||
|
double result = value * factor;
|
||||||
|
return QString::number(result, 'f', 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// ----
|
||||||
|
|||||||
96
bcvalue.h
96
bcvalue.h
@@ -38,6 +38,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <bc.h>
|
#include <bc.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -57,14 +58,30 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 )>;
|
||||||
|
|
||||||
|
|
||||||
struct BCValueType;
|
|
||||||
|
|
||||||
class BCValue
|
class BCValue
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Aus dem Type ergibt sich
|
||||||
|
// später der Editor
|
||||||
|
enum class ValueType : uint8_t
|
||||||
|
{
|
||||||
|
Plain,
|
||||||
|
Bool,
|
||||||
|
Number,
|
||||||
|
Float
|
||||||
|
};
|
||||||
|
|
||||||
enum class State : uint8_t
|
enum class State : uint8_t
|
||||||
{
|
{
|
||||||
NoState = 0x00,
|
NoState = 0x00,
|
||||||
@@ -78,16 +95,22 @@ public:
|
|||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(States, State )
|
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};
|
QString formatValue( uint32_t value ) const;
|
||||||
const BCValueType* valueType{};
|
|
||||||
|
mutable States state{BCValue::State::ReadOnly};
|
||||||
BCDevice::ID deviceID{BCDevice::ID::Invalid};
|
BCDevice::ID deviceID{BCDevice::ID::Invalid};
|
||||||
BC::ID registerID{BC::ID::Invalid};
|
BC::ID registerID{BC::ID::Invalid};
|
||||||
|
ValueType valueType{ValueType::Plain};
|
||||||
int indexRow{-1};
|
int indexRow{-1};
|
||||||
QString label;
|
QString label;
|
||||||
mutable QString visibleValue;
|
mutable QString visibleValue;
|
||||||
|
bool isWord{false};
|
||||||
|
QString unitLabel;
|
||||||
|
double factor{1};
|
||||||
|
OptDouble min;
|
||||||
|
OptDouble max;
|
||||||
};
|
};
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BCValue::States)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(BCValue::States)
|
||||||
|
|
||||||
@@ -103,72 +126,9 @@ using BCValueList = QList<BCValuePtr>;
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(const 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)
|
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
|
#endif // BCVALUE_H
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <bcvaluemodel.h>
|
#include <bcvaluemodel.h>
|
||||||
#include <bcvaluetype.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Konstruktor, ohne Besonderheiten
|
* @brief Konstruktor, ohne Besonderheiten
|
||||||
@@ -144,17 +144,17 @@ QVariant BCValueModel::data(const QModelIndex& index, int role) const
|
|||||||
if (wrongRole || !index.isValid() || row >= _valueList.size() )
|
if (wrongRole || !index.isValid() || row >= _valueList.size() )
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
BCValuePtr value = _valueList.at( row );
|
const BCValue& value = *(_valueList.at( row ).get());
|
||||||
|
|
||||||
if( col == 0 )
|
if( col == 0 )
|
||||||
return value->label;
|
return value.label;
|
||||||
|
|
||||||
if( col == 1)
|
if( col == 1)
|
||||||
{
|
{
|
||||||
if( role == Qt::DisplayRole )
|
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();
|
return QVariant();
|
||||||
|
|||||||
183
bcvaluetype.cpp
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
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
|
|
||||||
118
bcxmlloader.cpp
118
bcxmlloader.cpp
@@ -32,28 +32,20 @@
|
|||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QTableView>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QStatusBar>
|
#include <QMetaEnum>
|
||||||
#include <QApplication>
|
#include <QHash>
|
||||||
#include <QElapsedTimer>
|
|
||||||
|
|
||||||
#include <bcxmlloader.h>
|
#include <bcxmlloader.h>
|
||||||
#include <bcvaluetype.h>
|
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BCXmlLoader::BCXmlLoader(QObject *parent)
|
BCXmlLoader::BCXmlLoader(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
//qRegisterMetaType<BCValue*>("BCValue*");
|
//qRegisterMetaType<BCValue*>("BCValue*");
|
||||||
//qRegisterMetaType<BCValue*>();
|
//qRegisterMetaType<BCValue*>();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -156,17 +148,22 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
|||||||
if( _xml.attributes().hasAttribute(BCTags::ID) )
|
if( _xml.attributes().hasAttribute(BCTags::ID) )
|
||||||
{
|
{
|
||||||
//qDebug() << " --- found: " << _xml.name() << " : " << _xml.attributes().value(BCTags::ID);
|
//qDebug() << " --- found: " << _xml.name() << " : " << _xml.attributes().value(BCTags::ID);
|
||||||
QString id = _xml.attributes().value(BCTags::ID).toString();
|
|
||||||
// füllen des Parameter packs
|
// 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(),
|
.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
|
// 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)
|
if(newValue)
|
||||||
{
|
{
|
||||||
// wir merken uns gleich den index in der Werteliste
|
// 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 )
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
static QHash<QString,BCValue::ValueType> s_valueTypes
|
||||||
auto setIfExists = [&]( QStringView source, optDouble& target )
|
{
|
||||||
|
{ "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() )
|
if( !source.isEmpty() )
|
||||||
{
|
{
|
||||||
@@ -199,9 +203,6 @@ std::optional<BCValuePtr> BCXmlLoader::makeDataValue( BCDevice::ID deviceID, con
|
|||||||
target = testVal;
|
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
|
// geht nicht auf qt6.8 von debian trixie
|
||||||
//std::optional<quint64> IDVal = s_bcValueEnum.keyToValue64( params.ID.toLatin1().constData() );
|
//std::optional<quint64> IDVal = s_bcValueEnum.keyToValue64( params.ID.toLatin1().constData() );
|
||||||
bool ok;
|
bool ok;
|
||||||
|
static QMetaEnum s_bcValueEnum{QMetaEnum::fromType<BC::ID>()};
|
||||||
int IDVal = s_bcValueEnum.keyToValue( params.ID.toLatin1().constData(), &ok );
|
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( IDVal.has_value() )
|
||||||
if( ok )
|
if( ok )
|
||||||
{
|
{
|
||||||
auto valueType = BCValueType::fetchValueType(params.UnitType);
|
BCValuePtr newValuePtr = std::make_shared<BCValue>( deviceID, static_cast<BC::ID>(IDVal) );
|
||||||
if( valueType.has_value() )
|
BCValue& newValue = *newValuePtr.get();
|
||||||
{
|
|
||||||
BCValuePtr newValue = std::make_shared<BCValue>( *valueType, deviceID, static_cast<BC::ID>(IDVal) );
|
|
||||||
|
|
||||||
/*
|
|
||||||
setIfExists( params.Factor, newValue.factor );
|
setIfExists( params.Factor, newValue.factor );
|
||||||
setIfExists( params.Min, newValue.min );
|
setIfExists( params.Min, newValue.min );
|
||||||
setIfExists( params.Max, newValue.max );
|
setIfExists( params.Max, newValue.max );
|
||||||
|
setIfExists( params.IsWord, newValue.isWord );
|
||||||
|
|
||||||
|
newValue.label = params.Label;
|
||||||
|
newValue.label = 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;
|
||||||
*/
|
*/
|
||||||
newValue->label = params.Label;
|
|
||||||
qDebug() << " --- created: " << params.Label;
|
qDebug() << " --- created: " << params.Label;
|
||||||
|
|
||||||
return std::optional<BCValuePtr>( newValue );
|
return std::optional<BCValuePtr>( newValuePtr );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
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);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,15 +33,9 @@
|
|||||||
#ifndef BCXMLLOADER_H
|
#ifndef BCXMLLOADER_H
|
||||||
#define BCXMLLOADER_H
|
#define BCXMLLOADER_H
|
||||||
|
|
||||||
#include <QHash>
|
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
#include <QXmlStreamWriter>
|
|
||||||
#include <QMetaEnum>
|
|
||||||
|
|
||||||
#include <QThread>
|
#include <bcvalue.h>
|
||||||
#include <bcvaluemodel.h>
|
|
||||||
|
|
||||||
#include <bctransmitter.h>
|
|
||||||
|
|
||||||
|
|
||||||
class BCXmlLoader : public QObject
|
class BCXmlLoader : public QObject
|
||||||
@@ -55,8 +49,7 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void loadXmlBikeData( const QString& fileName );
|
void loadXmlBikeData( const QString& fileName );;
|
||||||
void saveBikeData();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
@@ -64,16 +57,21 @@ signals:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
struct BCDataParams
|
struct BCValueParams
|
||||||
{
|
{
|
||||||
QString ID;
|
QString ID;
|
||||||
QString Label;
|
QString Label;
|
||||||
QString UnitType;
|
QString UnitLabel;
|
||||||
|
QString Factor;
|
||||||
|
QString Min;
|
||||||
|
QString Max;
|
||||||
|
QString IsWord;
|
||||||
|
QString ValueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
void loadXmlBikeDeviceData( BCDevice::ID deviceID );
|
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;
|
QXmlStreamReader _xml;
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,56 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
QString ID;
|
||||||
|
QString Label;
|
||||||
|
QString UnitLabel;
|
||||||
|
QString Factor;
|
||||||
|
QString Min;
|
||||||
|
QString Max;
|
||||||
|
QString IsWord;
|
||||||
|
QString ValueType;
|
||||||
|
-->
|
||||||
<Bike name='franken-wheeler'>
|
<Bike name='franken-wheeler'>
|
||||||
|
|
||||||
<Device Type="Console">
|
<Device Type="Console">
|
||||||
<Value ID='Cons_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
<Value ID='Cons_Rev_Hw' Label='Hardware Version' />
|
||||||
<Value ID='Cons_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
<Value ID='Cons_Rev_Sw' Label='Software Version' />
|
||||||
<Value ID='Cons_Sn_Product_Hi' Label='Product Number' ReadOnly='true' UnitType='Word'/>
|
<Value ID='Cons_Sn_Product_Hi' Label='Product Number' IsWord='1'/>
|
||||||
<Value ID='Cons_Sn_Oem_Hi' Label='OEM Number' ReadOnly='true' UnitType='Word' />
|
<Value ID='Cons_Sn_Oem_Hi' Label='OEM Number' IsWord='1' />
|
||||||
|
|
||||||
<Value ID='Cons_Assist_Initlevel' Label='Assistance Init Level' ReadOnly='false' UnitType='AssInit'/>
|
<Value ID='Cons_Assist_Initlevel' Label='Assistance Init Level' Min='0' Max='4'/>
|
||||||
<Value ID='Cons_Assist_Level_1' Label='Assistance Level 1' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
<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' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
<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' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
<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' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
<Value ID='Cons_Assist_Level_4' Label='Assistance Level 4' Factor='1.5625' UnitLabel='%' Min='0' Max='400' />
|
||||||
|
|
||||||
<Value ID='Cons_Assist_Maxspeed_Flag' Label='Max Limit Enabled' ReadOnly='false' UnitType='Byte' />
|
<Value ID='Cons_Assist_Maxspeed_Flag' Label='Max Limit Enabled' ValueType='bool' />
|
||||||
<Value ID='Cons_Assist_Maxspeed_Hi' Label='Max Speed Limit' ReadOnly='false' UnitType='Kmh' Factor='0.1'/>
|
<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' ReadOnly='true' UnitType='Byte' />
|
<Value ID='Cons_Assist_Minspeed_Flag' Label='Min Limit Enabled' ValueType='bool' />
|
||||||
<Value ID='Cons_Assist_Minspeed' Label='Min Speed Limit' ReadOnly='true' UnitType='Kmh'/>
|
<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' ReadOnly='true' UnitType='Byte'/>
|
<Value ID='Cons_Throttle_Maxspeed_Flag' Label='Throttle Limit Enabled' ValueType='bool'/>
|
||||||
<Value ID='Cons_Throttle_Maxspeed_Hi' Label='Throttle Speed Limit' ReadOnly='true' UnitType='kmh' Factor='0.1'/>
|
<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' ReadOnly='true' UnitType='mm' />
|
<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' ReadOnly='true' UnitType='Percent' Factor='1.5625' />
|
<Value ID='Cons_Assist_Mountain_Cap' Label='Mountain Cap' UnitLabel='%' Factor='1.5625' />
|
||||||
</Device>
|
</Device>
|
||||||
|
|
||||||
<Device Type="Motor">
|
<Device Type="Motor">
|
||||||
<Value ID='Motor_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
<Value ID='Motor_Rev_Hw' Label='Hardware Version' />
|
||||||
<Value ID='Motor_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
<Value ID='Motor_Rev_Sw' Label='Software Version' />
|
||||||
<Value ID='Motor_Status_Temperature' Label='Motor Temperature' ReadOnly='true' UnitType='Degree'/>
|
<Value ID='Motor_Sn_Item_Hi' Label='Motor Part Number' IsWord='1'/>
|
||||||
<Value ID='Motor_Assist_Maxspeed' Label='Motor max. Speed' ReadOnly='true' UnitType='Kmh' />
|
<Value ID='Motor_Sn_Item_Hi' Label='Motor Serial Number' IsWord='1' />
|
||||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Part Number' ReadOnly='true' UnitType='Word'/>
|
<Value ID='Motor_Status_Temperature' Label='Motor Temperature' UnitLabel='°C' />
|
||||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Serial Number' ReadOnly='true' UnitType='Word' />
|
<Value ID='Motor_Assist_Maxspeed' Label='Motor max. Speed' Reader='Kmh' />
|
||||||
<Value ID='Motor_Geometry_Circ_Hi' Label='Motor Gemetry' ReadOnly='true' UnitType='Mm' />
|
|
||||||
|
<Value ID='Motor_Geometry_Circ_Hi' Label='Wheel Circumference' IsWord='1' UnitLabel='mm' Min='0' Max='2300' Factor='1.5625' />
|
||||||
</Device>
|
</Device>
|
||||||
|
|
||||||
<Device Type="Battery">
|
<Device Type="Battery">
|
||||||
<Value ID='Battery_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
<Value ID='Battery_Rev_Hw' Label='Hardware Version' />
|
||||||
<Value ID='Battery_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
<Value ID='Battery_Rev_Sw' Label='Software Version' />
|
||||||
</Device>
|
</Device>
|
||||||
|
|
||||||
</Bike>
|
</Bike>
|
||||||
@@ -57,106 +68,104 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Value ID='Cons_Stat_Dist_Hi' Label='' ReadOnly='true' UnitType='mm' Factor='0.1' />
|
<Value ID='Cons_Stat_Dist_Hi' Label='' Reader='mm' Factor='0.1' />
|
||||||
<Value ID='Cons_Stat_Dist_Lo' Label='' ReadOnly='true' UnitType='mm'/>
|
<Value ID='Cons_Stat_Dist_Lo' Label='' Reader='mm'/>
|
||||||
<Value ID='Cons_Stat_Avgspeed_Hi' Label='' ReadOnly='true' UnitType='mm' Factor='0.1' />
|
<Value ID='Cons_Stat_Avgspeed_Hi' Label='' Reader='mm' Factor='0.1' />
|
||||||
<Value ID='Cons_Stat_Avgspeed_Lo' Label='' ReadOnly='true' UnitType='mm'/>
|
<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_Hihi' Label='' Factor='0.1' />
|
||||||
<Value ID='Cons_Stat_Odo_Hilo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Stat_Odo_Hilo' Label='' />
|
||||||
<Value ID='Cons_Stat_Odomoter_Lohi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Stat_Odomoter_Lohi' Label='' />
|
||||||
<Value ID='Cons_Stat_Odo_Lolo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Stat_Odo_Lolo' Label='' />
|
||||||
|
|
||||||
<Value ID='Cons_Preference_Nip_Hihi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Nip_Hihi' Label='' />
|
||||||
<Value ID='Cons_Preference_Nip_Hilo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Nip_Hilo' Label='' />
|
||||||
<Value ID='Cons_Preference_Nip_Lohi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Nip_Lohi' Label='' />
|
||||||
<Value ID='Cons_Preference_Nip_Lolo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Nip_Lolo' Label='' />
|
||||||
<Value ID='Cons_Throttle_Calibrated' Label='' ReadOnly='true' />
|
<Value ID='Cons_Throttle_Calibrated' Label='' />
|
||||||
<Value ID='Cons_Stat_Chrono_Second' Label='' ReadOnly='true' />
|
<Value ID='Cons_Stat_Chrono_Second' Label='' />
|
||||||
<Value ID='Cons_Stat_Chrono_Minute' Label='' ReadOnly='true' />
|
<Value ID='Cons_Stat_Chrono_Minute' Label='' />
|
||||||
<Value ID='Cons_Stat_Chrono_Hour' Label='' ReadOnly='true' />
|
<Value ID='Cons_Stat_Chrono_Hour' Label='' />
|
||||||
<Value ID='Cons_Preference_Lcd_Contrast' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Lcd_Contrast' Label='' />
|
||||||
<Value ID='Cons_Sn_Location' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Location' Label='' />
|
||||||
<Value ID='Cons_Sn_Year' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Year' Label='' />
|
||||||
<Value ID='Cons_Sn_Month' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Month' Label='' />
|
||||||
<Value ID='Cons_Sn_Day' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Day' Label='' />
|
||||||
|
|
||||||
<Value ID='Cons_Sn_Pn_Hi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Pn_Hi' Label='' />
|
||||||
<Value ID='Cons_Sn_Pn_Lo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Pn_Lo' Label='' />
|
||||||
<Value ID='Cons_Sn_Item_Hi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Item_Hi' Label='' />
|
||||||
<Value ID='Cons_Sn_Item_Lo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Item_Lo' Label='' />
|
||||||
|
|
||||||
<Value ID='Cons_Assist_Gauge_Joint' Label='' ReadOnly='true' Min='0' Max='11' />
|
<Value ID='Cons_Assist_Gauge_Joint' Label='' Min='0' Max='11' />
|
||||||
<Value ID='Cons_Throttle_Min_Hi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Throttle_Min_Hi' Label='' />
|
||||||
<Value ID='Cons_Throttle_Min_Lo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Throttle_Min_Lo' Label='' />
|
||||||
<Value ID='Cons_Throttle_Max_Hi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Throttle_Max_Hi' Label='' />
|
||||||
<Value ID='Cons_Throttle_Max_Lo' Label='' ReadOnly='true' />
|
<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='' Min='0' Max='64' Factor='1.5625'/>
|
||||||
|
<Value ID='Cons_Preference_Trip_To_Empty_Flag' 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_Preference_Display_Units' Default='1' />
|
<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_Flag' Default='1' />
|
||||||
<Value ID='Cons_Assist_Brake_Polarity' Label='' ReadOnly='true' />
|
<Value ID='Cons_Assist_Brake_Polarity' Label='' />
|
||||||
<Value ID='Cons_Assist_Gauge_Filter' Label='' ReadOnly='true' Min='0' Max='8' />
|
<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_Gauge_Gain' Label='' 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_A' Label='' 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_Assist_Gain_B' Label='' Min='0.1' Max='25.0' Factor='0.1' />
|
||||||
<Value ID='Cons_Sn_Type' Label='' ReadOnly='true' />
|
<Value ID='Cons_Sn_Type' Label='' />
|
||||||
<Value ID='Cons_Preference_Region' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Region' Label='' />
|
||||||
<Value ID='Cons_Preference_Configbit_0' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Configbit_0' Label='' />
|
||||||
<Value ID='Cons_Throttle_Enabled_Boost_Display' Label='' ReadOnly='true' />
|
<Value ID='Cons_Throttle_Enabled_Boost_Display' Label='' />
|
||||||
<Value ID='Cons_Assist_Autoregen_Flag' Label='' ReadOnly='true' />
|
<Value ID='Cons_Assist_Autoregen_Flag' Label='' />
|
||||||
|
|
||||||
<Value ID='Cons_Rev_Sub' Label='' ReadOnly='true' />
|
<Value ID='Cons_Rev_Sub' Label='' />
|
||||||
<Value ID='Cons_Preference_Light_Button_Mode' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Light_Button_Mode' Label='' />
|
||||||
<Value ID='Cons_Preference_Expertmode' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Expertmode' Label='' />
|
||||||
|
|
||||||
|
|
||||||
<Value ID='Cons_Preference_Codes_Hihi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codes_Hihi' Label='' />
|
||||||
<Value ID='Cons_Preference_Codes_Hilo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codes_Hilo' Label='' />
|
||||||
<Value ID='Cons_Preference_Codes_Lohi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codes_Lohi' Label='' />
|
||||||
<Value ID='Cons_Preference_Codes_Lolo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codes_Lolo' Label='' />
|
||||||
<Value ID='Cons_Preference_Codesrw_Hihi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codesrw_Hihi' Label='' />
|
||||||
<Value ID='Cons_Preference_Codesrw_Hilo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codesrw_Hilo' Label='' />
|
||||||
<Value ID='Cons_Preference_Codesrw_Lohi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codesrw_Lohi' Label='' />
|
||||||
<Value ID='Cons_Preference_Codesrw_Lolo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Codesrw_Lolo' Label='' />
|
||||||
<Value ID='Cons_Preference_Throttle_Mode' Label='' ReadOnly='true' />
|
<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_Throttle_Boost_Triggerlevel' Label='' Min='1.5' Max='50.0' Factor='1.5625' />
|
||||||
<Value ID='Cons_Preference_Flip_Side' Label='' ReadOnly='true' />
|
<Value ID='Cons_Preference_Flip_Side' Label='' />
|
||||||
<Value ID='Cons_Config_Testmode' Label='' ReadOnly='true' />
|
<Value ID='Cons_Config_Testmode' Label='' />
|
||||||
<Value ID='Cons_Config_Testmode_Hw14' Label='' ReadOnly='true' />
|
<Value ID='Cons_Config_Testmode_Hw14' Label='' />
|
||||||
|
|
||||||
<Value ID='Cons_Config_Last_Mode' Label='' ReadOnly='true' />
|
<Value ID='Cons_Config_Last_Mode' Label='' />
|
||||||
<Value ID='Cons_Assist_Speedgain' Label='' ReadOnly='true' Factor='0.1' />
|
<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_On' Label='' />
|
||||||
<Value ID='Cons_Config_Last_Mode_Off' Label='' ReadOnly='true' />
|
<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_Hi' Label='' />
|
||||||
<Value ID='Cons_Throttle_Raw_Lo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Throttle_Raw_Lo' Label='' />
|
||||||
<Value ID='Cons_Throttle_Position' Label='' ReadOnly='true' Factor='1.5625'/>
|
<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_3' Label='' Factor='1.5625'/>
|
||||||
<Value ID='Cons_Assist_Level_Rekuperation_4' Label='' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
<Value ID='Cons_Assist_Level_Rekuperation_4' Label='' Factor='1.5625'/>
|
||||||
<Value ID='Cons_Config_Service_Timestamp_Hi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Config_Service_Timestamp_Hi' Label='' />
|
||||||
<Value ID='Cons_Config_Service_Zimestamp_Lo' Label='' ReadOnly='true' />
|
<Value ID='Cons_Config_Service_Zimestamp_Lo' Label='' />
|
||||||
<Value ID='Cons_Config_Service_Distance_Hi' Label='' ReadOnly='true' />
|
<Value ID='Cons_Config_Service_Distance_Hi' Label='' />
|
||||||
<Value ID='Cons_Config_Service_Distance_Lo' Label='' ReadOnly='true' />
|
<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_1' Label='' Factor='1.5625'/>
|
||||||
<Value ID='Cons_Assist_Level_Rekuperation_2' Label='' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
<Value ID='Cons_Assist_Level_Rekuperation_2' Label='' Factor='1.5625'/>
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|||||||
Reference in New Issue
Block a user