Compare commits
29 Commits
6032abb35c
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
| e5f7ba569a | |||
| a57b45e21a | |||
| 1a2d815634 | |||
| 6c15d99119 | |||
| c21bb2cf4e | |||
| 5c52b1e936 | |||
| 731566e7d1 | |||
| ae0ac5317d | |||
| 5d1e66f5fa | |||
|
|
e0b1e90f6c | ||
| 0f167a5e32 | |||
| aef6c641d1 | |||
| c63e9fa428 | |||
| 4f92e37400 | |||
| e16f02a165 | |||
| 57e6c69a15 | |||
| eb21eccb23 | |||
| 2474d3394c | |||
| 4f1af0f4ae | |||
| 3e9c1cc20b | |||
| e118fa4a20 | |||
| 2c9e9be6b3 | |||
| c36e9053c4 | |||
| 193579e798 | |||
| 3a132bb584 | |||
| 68680db6b4 | |||
| 56ab0fbc0f | |||
| 61bf3b2cec | |||
| c5dc84179b |
17
.gitignore
vendored
@@ -3,3 +3,20 @@ build/
|
||||
bcvalue.cpp.autosave
|
||||
.qtcreator/BionxControl.pro.user
|
||||
.user
|
||||
|
||||
# Objektdateien ignorieren
|
||||
*.o
|
||||
|
||||
.qtc_clangd/
|
||||
|
||||
# Von Qt generierte MOC-Dateien (Meta-Object Compiler) ignorieren
|
||||
moc_*
|
||||
|
||||
# Von Qt generierte Ressourcen-Dateien ignorieren
|
||||
qrc_*
|
||||
|
||||
BionxControl
|
||||
Makefile
|
||||
ui_*
|
||||
|
||||
.qmake.stash
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
QT += core gui
|
||||
QT += core gui svg
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
@@ -10,13 +10,30 @@ QMAKE_CXXFLAGS += -std=c++23
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
INCLUDEPATH += . lib
|
||||
INCLUDEPATH += . libwin
|
||||
|
||||
linux {
|
||||
#LIBS += -lpigpio -lpigpiod_if2 -lrt
|
||||
# FIXME SOURCES +=
|
||||
linux:contains(QT_ARCH, arm.*)
|
||||
{
|
||||
message("Konfiguration für Raspberry Pi (ARM) erkannt.")
|
||||
|
||||
# 1. Header-Dateien (z.B. für bcm2835.h oder eigene Treiber)
|
||||
#INCLUDEPATH += /usr/local/include \
|
||||
# /home/pi/my_custom_drivers/include
|
||||
|
||||
# not used at the moment
|
||||
# 2. Bibliotheken linken
|
||||
# -L sagt dem Linker WO er suchen soll
|
||||
# -l sagt dem Linker WAS er nehmen soll (z.B. libwiringPi.so -> -lwiringPi)
|
||||
#LIBS += -L/usr/lib \
|
||||
# -lmhstcan
|
||||
|
||||
|
||||
# Optional: Spezielle Compiler-Flags für den Pi (Optimierung)
|
||||
#QMAKE_CXXFLAGS += -O3
|
||||
}
|
||||
|
||||
li
|
||||
|
||||
windows
|
||||
{
|
||||
#LIBS += -L$$PWD/can_api -lmhstcan -lAdvapi32
|
||||
@@ -27,18 +44,20 @@ windows
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
aalegacy.cpp \
|
||||
bc.cpp \
|
||||
bcanimateddelegate.cpp \
|
||||
bcdeviceview.cpp \
|
||||
bcdriver.cpp \
|
||||
bcdrivertinycan.cpp \
|
||||
bclegacy.cpp \
|
||||
bcguihelpers.cpp \
|
||||
bcsliderstyle.cpp \
|
||||
bctransmitter.cpp \
|
||||
bcvalue.cpp \
|
||||
bcvaluemodel.cpp \
|
||||
bcvaluetype.cpp \
|
||||
bcxmlloader.cpp \
|
||||
lib/can_drv_win.c \
|
||||
libwin/can_drv_win.c \
|
||||
libwin/mhs_can_drv.c \
|
||||
main.cpp \
|
||||
bcmainwindow.cpp
|
||||
|
||||
@@ -48,11 +67,12 @@ HEADERS += \
|
||||
bcdeviceview.h \
|
||||
bcdriver.h \
|
||||
bcdrivertinycan.h \
|
||||
bcguihelpers.h \
|
||||
bcmainwindow.h \
|
||||
bcsliderstyle.h \
|
||||
bctransmitter.h \
|
||||
bcvalue.h \
|
||||
bcvaluemodel.h \
|
||||
bcvaluetype.h \
|
||||
bcxmlloader.h
|
||||
|
||||
FORMS += \
|
||||
|
||||
@@ -185,102 +185,7 @@ double gSetSpeedLimit = -1, gSetMinSpeedLimit = -1, gSetThrottleSpeedLimit = -1;
|
||||
#define BATTERY 3
|
||||
#define BIB 4
|
||||
|
||||
/*
|
||||
class ThemeSwitchButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ThemeSwitchButton(QWidget *parent = nullptr)
|
||||
: QPushButton(parent), m_isDarkMode(true)
|
||||
{
|
||||
// 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
setFixedSize(32, 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"(
|
||||
QPushButton {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 14pt;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
|
||||
border-radius: 4px;
|
||||
}
|
||||
)");
|
||||
|
||||
// 2. Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
||||
updateIcon();
|
||||
|
||||
// 3. Klick verbinden
|
||||
connect(this, &QPushButton::clicked, this, &ThemeSwitchButton::toggle);
|
||||
}
|
||||
|
||||
signals:
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
void toggle() {
|
||||
m_isDarkMode = !m_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(m_isDarkMode);
|
||||
}
|
||||
|
||||
private:
|
||||
void updateIcon() {
|
||||
// Logik:
|
||||
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
||||
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
||||
setText(m_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(m_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode");
|
||||
}
|
||||
|
||||
bool m_isDarkMode;
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
setWindowTitle("Fluent Theme Switcher");
|
||||
resize(800, 600);
|
||||
|
||||
// --- STATUSBAR SETUP ---
|
||||
QStatusBar *statBar = statusBar();
|
||||
|
||||
// Optional: Normale Nachricht links
|
||||
statBar->showMessage("Ready");
|
||||
|
||||
// 1. Unseren Switcher erstellen
|
||||
ThemeSwitchButton *themeBtn = new ThemeSwitchButton(this);
|
||||
|
||||
// 2. WICHTIG: Rechts hinzufügen
|
||||
statBar->addPermanentWidget(themeBtn);
|
||||
|
||||
// 3. Signal verbinden: Button klick -> Theme ändern
|
||||
connect(themeBtn, &ThemeSwitchButton::themeChanged, this, [this](bool isDark){
|
||||
if (isDark) {
|
||||
applyFluentDarkTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Dark Mode Activated", 3000);
|
||||
} else {
|
||||
applyFluentLightTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Light Mode Activated", 3000);
|
||||
}
|
||||
});
|
||||
|
||||
// Initiale Anwendung (Dark Mode)
|
||||
applyFluentDarkTheme(*qApp);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
char *getNodeName(unsigned char id)
|
||||
{
|
||||
@@ -727,24 +632,30 @@ int xmain(int argc, char **argv)
|
||||
CanSetMode(0, OP_CAN_START, CAN_CMD_ALL_CLEAR);
|
||||
CanGetDeviceStatus(0, &status);
|
||||
|
||||
if (status.DrvStatus >= DRV_STATUS_CAN_OPEN) {
|
||||
if (status.CanStatus == CAN_STATUS_BUS_OFF) {
|
||||
if (status.DrvStatus >= DRV_STATUS_CAN_OPEN)
|
||||
{
|
||||
if (status.CanStatus == CAN_STATUS_BUS_OFF)
|
||||
{
|
||||
printf("CAN Status BusOff" _NL);
|
||||
CanSetMode(0, OP_CAN_RESET, CAN_CMD_NONE);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("error: could not open device" _NL);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
|
||||
if (consoleInSlaveMode) {
|
||||
|
||||
if (consoleInSlaveMode)
|
||||
{
|
||||
printf("console already in salve mode. good!" _NL _NL);
|
||||
} else {
|
||||
if (gConsoleSetSlaveMode) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gConsoleSetSlaveMode)
|
||||
{
|
||||
int retry = 20;
|
||||
|
||||
printf("putting console in salve mode ... ");
|
||||
@@ -756,16 +667,21 @@ int xmain(int argc, char **argv)
|
||||
|
||||
doSleep(500); // give the console some time to settle
|
||||
printf("%s" _NL _NL, consoleInSlaveMode ? "done" : "failed");
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("console not in slave mode" _NL _NL);
|
||||
}
|
||||
}
|
||||
|
||||
if (gAssistInitLevel != -1) {
|
||||
if (gAssistInitLevel != -1)
|
||||
{
|
||||
printf("setting initial assistance level to %d" _NL, gAssistInitLevel);
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL, gAssistInitLevel);
|
||||
}
|
||||
|
||||
if (gSetSpeedLimit > 0) {
|
||||
if (gSetSpeedLimit > 0)
|
||||
{
|
||||
printf("set speed limit to %0.2f km/h" _NL, gSetSpeedLimit);
|
||||
setSpeedLimit(gSetSpeedLimit);
|
||||
doShutdown = 1;
|
||||
2
bc.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
9
bc.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -773,15 +773,16 @@ namespace BCTags
|
||||
inline constexpr auto Device = "Device"_L1;
|
||||
inline constexpr auto ID = "ID"_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 Current = "Current"_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 Max = "Max"_L1;
|
||||
inline constexpr auto Factor = "Factor"_L1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // BC_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -181,54 +181,31 @@ QSize BCAnimatedDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
|
||||
void BCAnimatedDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
// 1. Standard-Zeichnen (Text, Hintergrund, Selection) durchführen
|
||||
// Standard-Zeichnen (Text, Hintergrund, Selection) durchführen
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
//QPen pen(QColor(255, 165, 0)); // Orange
|
||||
|
||||
/*
|
||||
if (index.row() == _highlightedRow && _opacity > 0.0)
|
||||
{
|
||||
painter->save();
|
||||
|
||||
qDebug() << " --- is highlight: " << index.row();
|
||||
|
||||
QColor highlightColor( 0xFF9800 );
|
||||
highlightColor.setAlphaF(_opacity);
|
||||
|
||||
QPen pen(highlightColor, 3);
|
||||
painter->setPen(pen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawRoundedRect(option.rect.adjusted(2, 2, -2, -2), 8, 8);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
int row = index.row();
|
||||
if (index.column() == 1 )
|
||||
int col = index.column();
|
||||
|
||||
switch (col)
|
||||
{
|
||||
case 1:
|
||||
|
||||
if( m_rowOpacities.contains(row))
|
||||
{
|
||||
paintHighlightRow(painter,option,index);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
if( row>-1 && row <= _valueList.size() )
|
||||
paintSliderIndicator(painter,option,index);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
qreal opacity = m_rowOpacities.value(row);
|
||||
if (opacity > 0.01)
|
||||
{
|
||||
painter->save();
|
||||
painter->setOpacity(opacity);
|
||||
painter->fillRect(option.rect, QColor(255, 140, 0, 120));
|
||||
painter->restore();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void BCAnimatedDelegate::paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
painter->save();
|
||||
@@ -239,33 +216,70 @@ void BCAnimatedDelegate::paintHighlightRow(QPainter* painter, const QStyleOption
|
||||
// Margin von 4px
|
||||
QRect itemRect = option.rect.adjusted(3, 3, -3, -3);
|
||||
|
||||
// Border von 2px berücksichtigen (nach innen)
|
||||
//QRect contentRect = itemRect.adjusted(2, 2, -2, -2);
|
||||
// painter->fillRect(contentRect,Qt::green);
|
||||
/*
|
||||
// Hintergrund (weiß)
|
||||
painter->setBrush(Qt::white);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRoundedRect(itemRect, 8, 8);
|
||||
*/
|
||||
// Border (2px solid #2196F3)
|
||||
QPen borderPen( Qt::red, 1);
|
||||
painter->setPen(borderPen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawRoundedRect(itemRect, 2, 2);
|
||||
|
||||
// Padding von 8px für den Content
|
||||
//QRect textRect = contentRect.adjusted(8, 8, -8, -8);
|
||||
|
||||
/*
|
||||
// Text zeichnen
|
||||
painter->setPen(Qt::black); // oder option.palette.color(QPalette::Text)
|
||||
QString text = index.data(Qt::DisplayRole).toString();
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
*/
|
||||
painter->restore();
|
||||
|
||||
}
|
||||
|
||||
void BCAnimatedDelegate::paintSliderIndicator(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
const BCValue& valueX = *(_valueList[ index.row()].get());
|
||||
int value = 50;index.model()->data(index, Qt::DisplayRole).toInt();
|
||||
|
||||
// Hintergrund
|
||||
if (option.state & QStyle::State_Selected)
|
||||
{
|
||||
painter->fillRect(option.rect, option.palette.highlight());
|
||||
}
|
||||
else if (index.row() % 2 == 1)
|
||||
{
|
||||
painter->fillRect(option.rect, QColor(0xFAFAFA));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->fillRect(option.rect, Qt::white);
|
||||
}
|
||||
|
||||
// Text und kleiner Slider-Indikator zeichnen
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
//QRect textRect = option.rect.adjusted(8, 0, -120, 0);
|
||||
|
||||
QRect barRect = option.rect.adjusted
|
||||
(
|
||||
8,
|
||||
option.rect.height() / 2 - 2,
|
||||
-8,
|
||||
-option.rect.height() / 2 + 2
|
||||
);
|
||||
|
||||
//QRect barRect = option.rect;
|
||||
// Text
|
||||
//painter->setPen(option.state & QStyle::State_Selected ? option.palette.highlightedText().color() : Qt::black);
|
||||
//painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft,
|
||||
// QString::number(value));
|
||||
|
||||
// Mini Progress Bar
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(QColor(0xE0E0E0));
|
||||
painter->drawRoundedRect(barRect, 2, 2);
|
||||
|
||||
QRect fillRect = barRect;
|
||||
fillRect.setWidth(barRect.width() * value / 100);
|
||||
painter->setBrush(QColor(0x0078D4));
|
||||
painter->drawRoundedRect(fillRect, 2, 2);
|
||||
|
||||
painter->restore();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void BCAnimatedDelegate::onHighlightRow(int row)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -61,21 +61,6 @@ public:
|
||||
QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex& index) const override;
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
|
||||
|
||||
/*
|
||||
qreal highlightOpacity() const
|
||||
{
|
||||
return _opacity;
|
||||
}
|
||||
|
||||
void setHighlightOpacity(qreal opacity)
|
||||
{
|
||||
_opacity = opacity;
|
||||
//qDebug() << " --- opa: " << opacity;
|
||||
// __fix! unsinn!
|
||||
emit viewUpdateNeeded();
|
||||
}
|
||||
*/
|
||||
|
||||
void clearAllHighlights();
|
||||
|
||||
public slots:
|
||||
@@ -91,13 +76,11 @@ private:
|
||||
|
||||
void updateRow(int row);
|
||||
void paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
void paintSliderIndicator(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
|
||||
const BCValueList& _valueList;
|
||||
QTableView* _view{};
|
||||
|
||||
//int _highlightedRow{-1};
|
||||
//qreal _opacity{1.0};
|
||||
|
||||
QPropertyAnimation* _animation{};
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -30,6 +30,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
#include <bcdeviceview.h>
|
||||
#include <bcanimateddelegate.h>
|
||||
|
||||
@@ -44,7 +46,6 @@ BCDeviceView::BCDeviceView(QWidget *parent)
|
||||
// __fix! ziemlich wildes ge-pointere, hier
|
||||
_itemDelegate = new BCAnimatedDelegate( _valueModel.getValueList(), this);
|
||||
setItemDelegate( _itemDelegate );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +61,9 @@ BCDevice::ID BCDeviceView::getDeviceID() const
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gibt eine Referenz auf der ValueList zurück.
|
||||
*/
|
||||
|
||||
const BCValueList& BCDeviceView::getValueListX()
|
||||
{
|
||||
@@ -68,8 +71,10 @@ const BCValueList& BCDeviceView::getValueListX()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// __FIX ist das ok so?
|
||||
/**
|
||||
* @brief SLOT, der aufgerufen wird, wenn die ValueList vom XML-Lader fertig geladen wurde.
|
||||
* Die DeviceView nimmt die ValueList dann in Besitz.
|
||||
*/
|
||||
void BCDeviceView::onValueListReady( BCDevice::ID deviceID, BCValueList valueList )
|
||||
{
|
||||
qDebug() << " --- onValueListReady: " << deviceID << ": " << valueList.size();
|
||||
@@ -77,11 +82,28 @@ void BCDeviceView::onValueListReady( BCDevice::ID deviceID, BCValueList valueLis
|
||||
_valueModel.takeValueList( valueList );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief SLOT, der aufgerufen wird, wenn ein Value geändert wurde. Gibt dem ItemDelegate Bescheid.
|
||||
*/
|
||||
|
||||
void BCDeviceView::onValueUpdated(int index, BCValue::State state, const QString& newVisibleValue )
|
||||
{
|
||||
_valueModel.onValueUpdated( index, state, newVisibleValue);
|
||||
_itemDelegate->onHighlightRow( index );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BCDeviceView::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
// Zuerst die Basisklasse aufrufen (Wichtig für Layouts!)
|
||||
QWidget::resizeEvent(event);
|
||||
|
||||
// Berechnung: 40% der aktuellen Breite
|
||||
// Tipp: viewport()->width() ist genauer als width(), da es Scrollbars rausrechnet!
|
||||
int totalWidth = viewport()->width();
|
||||
int col0Width = static_cast<int>(totalWidth * 0.60);
|
||||
|
||||
// Setzen der Breite
|
||||
horizontalHeader()->resizeSection(0, col0Width);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -64,6 +64,8 @@ public slots:
|
||||
|
||||
protected:
|
||||
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
BCDevice::ID _devideID{BCDevice::ID::Invalid};
|
||||
BCValueModel _valueModel;
|
||||
BCAnimatedDelegate* _itemDelegate{};
|
||||
|
||||
50
bcdriver.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -36,12 +36,9 @@
|
||||
#include <bcdriver.h>
|
||||
|
||||
|
||||
|
||||
BCDriver::BCDriver(QObject* parent )
|
||||
: QObject{ parent }
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Gibt den Treiberstatus zurück.
|
||||
*/
|
||||
|
||||
BCDriver::DriverState BCDriver::getDriverState() const
|
||||
{
|
||||
@@ -59,48 +56,20 @@ BCDriver::DriverState BCDriver::getDriverState() const
|
||||
* aber die Console noch nicht eingeschaltet war.
|
||||
*/
|
||||
|
||||
void BCDriverDummy::onStartDriver()
|
||||
BCDriver::DriverStateResult BCDriverDummy::loadAndStartDriver()
|
||||
{
|
||||
_driverState = DriverState::DeviceReady;
|
||||
emit driverStateChanged( DriverState::DeviceReady, "Driver Ready." );
|
||||
return _driverState;
|
||||
}
|
||||
// __Fix
|
||||
/*
|
||||
try
|
||||
{
|
||||
|
||||
// erstmal die Dll Laden: State::sIdle -> State::sLoaded
|
||||
if( _driverState == DriverState::NotPresent)
|
||||
_driverState = loadAndInitDriver();
|
||||
|
||||
emit stateChanged( _driverState );
|
||||
|
||||
}
|
||||
catch( std::exception& except )
|
||||
{
|
||||
//::CanDownDriver();
|
||||
//::UnloadAndInitDriver();
|
||||
|
||||
emit statusHint( except.what() );
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief BCDriverDummy::BCDriverDummy
|
||||
* @param parent
|
||||
* @brief Gibt ein Zufallsbyte zurück.
|
||||
*/
|
||||
|
||||
BCDriverDummy::BCDriverDummy( QObject* parent )
|
||||
: BCDriver(parent)
|
||||
{
|
||||
}
|
||||
|
||||
TransmitResult BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID ) const
|
||||
{
|
||||
Q_UNUSED(deviceID)
|
||||
@@ -110,6 +79,11 @@ TransmitResult BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID
|
||||
return myRandomByte;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Simuliert erfolgreiches scheiben. Tut nix.
|
||||
*/
|
||||
|
||||
TransmitResult BCDriverDummy::writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const
|
||||
{
|
||||
Q_UNUSED(deviceID)
|
||||
|
||||
60
bcdriver.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -36,37 +36,7 @@
|
||||
#include <QObject>
|
||||
#include <expected>
|
||||
#include <bcvalue.h>
|
||||
#include <bcvaluetype.h>
|
||||
/*
|
||||
int32_t CanInitDriver(char *options);
|
||||
void CanDownDriver(void);
|
||||
int32_t CanSetOptions(char *options);
|
||||
int32_t CanDeviceOpen(uint32_t index, char *parameter);
|
||||
int32_t CanDeviceClose(uint32_t index);
|
||||
|
||||
int32_t CanSetMode(uint32_t index, unsigned char can_op_mode, uint16_t can_command);
|
||||
|
||||
int32_t CanTransmit(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
void CanTransmitClear(uint32_t index);
|
||||
uint32_t CanTransmitGetCount(uint32_t index);
|
||||
int32_t CanTransmitSet(uint32_t index, uint16_t cmd, uint32_t time);
|
||||
int32_t CanReceive(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
void CanReceiveClear(uint32_t index);
|
||||
uint32_t CanReceiveGetCount(uint32_t index);
|
||||
|
||||
int32_t CanSetSpeed(uint32_t index, uint16_t speed);
|
||||
int32_t CanSetSpeedUser(uint32_t index, uint32_t value);
|
||||
char* CanDrvInfo(void);
|
||||
char* CanDrvHwInfo(uint32_t index);
|
||||
int32_t CanSetFilter(uint32_t index, struct TMsgFilter *msg_filter);
|
||||
int32_t CanGetDeviceStatus(uint32_t index, struct TDeviceStatus *status);
|
||||
void CanSetPnPEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, int32_t status));
|
||||
void CanSetStatusEventCallback(void (DRV_CALLBACK_TYPE *event) (uint32_t index, struct TDeviceStatus *device_status) );
|
||||
void CanSetRxEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, struct TCanMsg *msg, int32_t count) );
|
||||
|
||||
void CanSetEvents( uint16_t events );
|
||||
uint32_t CanEventStatus(void);
|
||||
*/
|
||||
|
||||
struct CBCItem;
|
||||
class BCDriverStatus;
|
||||
@@ -84,16 +54,16 @@ class BCDriverStatus;
|
||||
*/
|
||||
|
||||
|
||||
class BCDriver : public QObject
|
||||
class BCDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
|
||||
// Die möglichen Zustände beim Laden
|
||||
// des CAN-Bus Treibers.
|
||||
|
||||
enum class DriverState
|
||||
enum class DriverState : uint8_t
|
||||
{
|
||||
NotPresent,
|
||||
Error,
|
||||
@@ -107,9 +77,11 @@ public:
|
||||
// Enthält den Treiberzustand oder einen Fehlerstring
|
||||
using DriverStateResult = std::expected<DriverState,QString>;
|
||||
|
||||
explicit BCDriver( QObject* parent = nullptr );
|
||||
explicit BCDriver() = default;
|
||||
virtual ~BCDriver() = default;
|
||||
|
||||
virtual BCDriver::DriverStateResult loadAndStartDriver() = 0;
|
||||
|
||||
// Gibt den aktuelle Zustand des Treibers zurück. Der DriverState
|
||||
// muss auf DeviceReady stehen, um Werte lesen & schreiben zu können.
|
||||
// Dazu muss das Bionx-System eingeschaltet sein.
|
||||
@@ -122,14 +94,6 @@ public:
|
||||
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:
|
||||
|
||||
virtual void onStartDriver() = 0;
|
||||
|
||||
signals:
|
||||
|
||||
void driverStateChanged( DriverState state, const QString& message="" ) const;
|
||||
|
||||
protected:
|
||||
|
||||
DriverState _driverState{DriverState::NotPresent};
|
||||
@@ -137,20 +101,22 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class BCDriverDummy : public BCDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCDriverDummy( QObject* parent = nullptr );
|
||||
BCDriver::DriverStateResult loadAndStartDriver() 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:
|
||||
|
||||
virtual void onStartDriver() override;
|
||||
};
|
||||
|
||||
#endif // BCDRIVER_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -36,44 +36,98 @@
|
||||
#include <can_drv.h>
|
||||
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
// Unter Windows steht der Treibername in der registry
|
||||
static const char* cMHS_DRIVERNAME = NULL;
|
||||
#elif defined(Q_OS_LINUX)
|
||||
// Unter linux(artigen) muss der Treibername explizit mit übergeben werden
|
||||
static const char* cMHS_DRIVERNAME = "libmhstcan.so";
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
// TinyCan C-Api
|
||||
// -------------
|
||||
|
||||
BCDriverTinyCan::BCDriverTinyCan( QObject* parent )
|
||||
: BCDriver(parent )
|
||||
int32_t CanInitDriver(char *options);
|
||||
void CanDownDriver(void);
|
||||
int32_t CanSetOptions(char *options);
|
||||
int32_t CanDeviceOpen(uint32_t index, char *parameter);
|
||||
int32_t CanDeviceClose(uint32_t index);
|
||||
|
||||
int32_t CanSetMode(uint32_t index, unsigned char can_op_mode, uint16_t can_command);
|
||||
|
||||
int32_t CanTransmit(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
void CanTransmitClear(uint32_t index);
|
||||
uint32_t CanTransmitGetCount(uint32_t index);
|
||||
int32_t CanTransmitSet(uint32_t index, uint16_t cmd, uint32_t time);
|
||||
int32_t CanReceive(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
void CanReceiveClear(uint32_t index);
|
||||
uint32_t CanReceiveGetCount(uint32_t index);
|
||||
|
||||
int32_t CanSetSpeed(uint32_t index, uint16_t speed);
|
||||
int32_t CanSetSpeedUser(uint32_t index, uint32_t value);
|
||||
char* CanDrvInfo(void);
|
||||
char* CanDrvHwInfo(uint32_t index);
|
||||
int32_t CanSetFilter(uint32_t index, struct TMsgFilter *msg_filter);
|
||||
int32_t CanGetDeviceStatus(uint32_t index, struct TDeviceStatus *status);
|
||||
void CanSetPnPEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, int32_t status));
|
||||
void CanSetStatusEventCallback(void (DRV_CALLBACK_TYPE *event) (uint32_t index, struct TDeviceStatus *device_status) );
|
||||
void CanSetRxEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, struct TCanMsg *msg, int32_t count) );
|
||||
|
||||
void CanSetEvents( uint16_t events );
|
||||
uint32_t CanEventStatus(void);
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Destruktor. Entlädt den CAN-Bus Treiber wieder.
|
||||
*/
|
||||
|
||||
BCDriverTinyCan::~BCDriverTinyCan()
|
||||
{
|
||||
|
||||
resetDriver();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BCDriverTinyCan::loadAndStartDriver
|
||||
* @return
|
||||
*/
|
||||
|
||||
void BCDriverTinyCan::onStartDriver()
|
||||
BCDriver::DriverStateResult BCDriverTinyCan::loadAndStartDriver()
|
||||
{
|
||||
DriverStateResult result;
|
||||
if( _driverState < DriverState::Opened)
|
||||
loadDriver();
|
||||
result = loadDriver();
|
||||
if( _driverState == DriverState::Opened)
|
||||
_driverState = connectDriver();
|
||||
result = setConsoleSlaveMode();
|
||||
return result;
|
||||
}
|
||||
|
||||
void BCDriverTinyCan::loadDriver()
|
||||
{
|
||||
/**
|
||||
* @brief BCDriverTinyCan::loadDriver
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
auto callLoadDriver = []() -> DriverStateResult
|
||||
BCDriver::DriverStateResult BCDriverTinyCan::loadDriver()
|
||||
{
|
||||
if( ::LoadDriver( NULL ) < 0 )
|
||||
auto callLoadDriver = [&]() -> DriverStateResult
|
||||
{
|
||||
if( ::LoadDriver( cMHS_DRIVERNAME ) < 0 )
|
||||
return std::unexpected(QString("Driver Error: 'LoadDriver'"));
|
||||
return DriverState::Loaded;
|
||||
_driverState = DriverState::Loaded;
|
||||
return _driverState;
|
||||
};
|
||||
|
||||
auto callInitDriver = [](DriverState state) -> DriverStateResult
|
||||
auto callInitDriver = [&](DriverState state) -> DriverStateResult
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
if( ::CanInitDriver( NULL ) < 0 )
|
||||
return std::unexpected(QString("Driver Error: 'InitDriver'"));
|
||||
return DriverState::Initialized;
|
||||
_driverState = DriverState::Initialized;
|
||||
return _driverState;
|
||||
};
|
||||
|
||||
auto callOpenDevice = [](DriverState state) -> DriverStateResult
|
||||
auto callOpenDevice = [&](DriverState state) -> DriverStateResult
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
if( ::CanDeviceOpen( 0, NULL ) < 0 )
|
||||
@@ -93,41 +147,58 @@ void BCDriverTinyCan::loadDriver()
|
||||
::CanSetMode( 0, OP_CAN_RESET, CAN_CMD_NONE );
|
||||
return std::unexpected(QString("Driver Error: CAN Status 'BusOff'" ));
|
||||
}
|
||||
return DriverState::Opened;
|
||||
_driverState = DriverState::Opened;
|
||||
return _driverState;
|
||||
};
|
||||
|
||||
|
||||
// #1. erstmal komplett zurücksetzen
|
||||
resetDriver();
|
||||
// #2. Treiber laden, initialisieren und
|
||||
// mit dem tinyCan Interface verbinden.
|
||||
auto newDriverState = callLoadDriver()
|
||||
.and_then( callInitDriver )
|
||||
.and_then( callOpenDevice );
|
||||
|
||||
_driverState = DriverState::Error;
|
||||
QString message("Driver Ready.");
|
||||
// in Fehlerfall ist der Errorstring gesetzt,
|
||||
// der interne _driverstate ist
|
||||
// irgendwo unter DriverState::Opened
|
||||
return newDriverState;
|
||||
|
||||
if(newDriverState)
|
||||
_driverState = *newDriverState;
|
||||
else
|
||||
message = newDriverState.error();
|
||||
|
||||
emit driverStateChanged( _driverState, message );
|
||||
}
|
||||
|
||||
// __fix
|
||||
BCDriver::DriverState BCDriverTinyCan::connectDriver()
|
||||
|
||||
/**
|
||||
* @brief Um mit dem Bionx eBike reden zu können, müssen wir
|
||||
* die Console in den Slave-Mode setzen.
|
||||
* @return Fehlerstring oder DriverState::DeviceReady
|
||||
*/
|
||||
|
||||
BCDriver::DriverStateResult BCDriverTinyCan::setConsoleSlaveMode()
|
||||
{
|
||||
|
||||
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
|
||||
uint8_t slaveFlag = static_cast<uint8_t> (BC::ID::Cons_Status_Slave);
|
||||
|
||||
qDebug() << "XXX BCDriverTinyCan::Driver Init: putting Console in slave mode ... ";
|
||||
|
||||
// Console already in slave mode. good!
|
||||
if( readRawByte( console, slaveFlag ) )
|
||||
TransmitResult isSlave = 0;
|
||||
// Already slave?
|
||||
isSlave = readRawByte( console, slaveFlag );
|
||||
if( isSlave.has_value() )
|
||||
{
|
||||
qDebug() << "Console responded: " << isSlave.value();
|
||||
if( isSlave.value() == 1 )
|
||||
{
|
||||
qDebug() << "Console already in slave mode. good!";
|
||||
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 ... " );
|
||||
TransmitResult isSlave = 0;
|
||||
|
||||
do
|
||||
{
|
||||
writeRawByte( console, slaveFlag, 1 );
|
||||
@@ -145,19 +216,15 @@ BCDriver::DriverState BCDriverTinyCan::connectDriver()
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
try
|
||||
void BCDriverTinyCan::resetDriver()
|
||||
{
|
||||
initBCDevice::ID::Console();
|
||||
}
|
||||
|
||||
catch( std::exception& except )
|
||||
if( _driverState > DriverState::NotPresent )
|
||||
{
|
||||
::CanDownDriver();
|
||||
::UnloadDriver();
|
||||
_driverState = DriverState::NotPresent;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@@ -170,17 +237,75 @@ BCDriver::DriverState BCDriverTinyCan::connectDriver()
|
||||
TransmitResult BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) const
|
||||
{
|
||||
|
||||
qDebug() << " --- CAN Read Byte: Device: "<< deviceID << " register: " << registerID << " TRY! ";
|
||||
|
||||
struct TCanMsg msg;
|
||||
int err, retry = 20;
|
||||
int timeout = 80;
|
||||
|
||||
unsigned char receipient = (unsigned char) deviceID;
|
||||
unsigned char reg = (unsigned char) registerID;
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = receipient;
|
||||
msg.MsgLen = 2;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = reg;
|
||||
|
||||
CanTransmit(0, &msg, 1);
|
||||
|
||||
while(timeout-- && CanTransmitGetCount(0))
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if (timeout == -1)
|
||||
qDebug() << "error: could not send value to node ";
|
||||
|
||||
retry:
|
||||
|
||||
timeout = 80;
|
||||
while(timeout-- && !CanReceiveGetCount(0))
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if (timeout == -1)
|
||||
{
|
||||
qDebug() << "error: no response from node";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((err = CanReceive(0, &msg, 1)) > 0)
|
||||
{
|
||||
qDebug() << " retry: " << retry << " BIB:" << BC::ID::ID_Bib << " msg.Id: " << msg.Id << " msg.MsgLen: " << msg.MsgLen << " msg.MsgData[1]: " << msg.MsgData[1] << " reg: " << reg;
|
||||
if (--retry && (msg.Id != (uint32_t)BC::ID::ID_Bib|| msg.MsgLen != 4 || msg.MsgData[1] != reg))
|
||||
goto retry;
|
||||
|
||||
if (!retry)
|
||||
{
|
||||
qDebug() << "XXX error: no response from node: " << err;
|
||||
return 0;
|
||||
}
|
||||
qDebug() << " --- CAN Read Byte: Device: "<< deviceID << " register: " << registerID << " BYTE: " << (uint32_t) msg.MsgData[3];
|
||||
return (unsigned int) msg.MsgData[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Error:" <<err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
//TransmitResult
|
||||
qDebug() << " --- BCDriverTinyCan::readRawByte DriverState: " << getDriverState();
|
||||
|
||||
if( getDriverState() != DriverState::DeviceReady)
|
||||
if( _driverState <DriverState::Opened )
|
||||
return std::unexpected(QString("readRawValue error: driver not loaded." ) );
|
||||
|
||||
unsigned char receipient = (unsigned char ) deviceID;
|
||||
::TCanMsg msg;
|
||||
|
||||
// msg verpacken
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = deviceID;
|
||||
msg.Id = receipient;//deviceID;
|
||||
msg.MsgLen = 2;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = registerID;
|
||||
@@ -212,15 +337,15 @@ retry:
|
||||
|
||||
// message empfangen
|
||||
int err = ::CanReceive( 0, &msg, 1 );
|
||||
qDebug() << "HÄÄ ?" << err << "reg: "<< registerID <<" timeOuts: " << timeOuts;
|
||||
//qDebug() << "HÄÄ ?" << err << "reg: "<< registerID <<" timeOuts: " << timeOuts;
|
||||
|
||||
if( err < 0 )
|
||||
//throw BCException( "getValue error: could not receive value" );
|
||||
qDebug( "getValue error: could not receive value" );
|
||||
|
||||
qDebug() << "HÄÄ 2" <<msg.Id;
|
||||
qDebug() << "HÄÄ 2" <<msg.MsgLen;
|
||||
qDebug() << "HÄÄ 2" <<msg.MsgData[1];
|
||||
//qDebug() << "HÄÄ 2" <<msg.Id;
|
||||
//qDebug() << "HÄÄ 2" <<msg.MsgLen;
|
||||
//qDebug() << "HÄÄ 2" <<msg.MsgData[1];
|
||||
|
||||
//if( err > 0 )
|
||||
if( --retries && ( msg.Id != BIB || msg.MsgLen != 4 || msg.MsgData[1] != registerID ) )
|
||||
@@ -229,8 +354,9 @@ retry:
|
||||
if( !timeOuts )
|
||||
return std::unexpected(QString("CAN response errror: timeout" ));
|
||||
|
||||
qDebug() << " --- CAN Read Byte: " << (uint32_t) msg.MsgData[3] << " Device:: "<< deviceID << " register: " << registerID;
|
||||
return (uint32_t) msg.MsgData[3];
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -238,14 +364,15 @@ retry:
|
||||
TransmitResult BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const
|
||||
{
|
||||
|
||||
if( getDriverState() != DriverState::DeviceReady)
|
||||
return std::unexpected(QString("writeRawValue error: driver not loaded." ) );
|
||||
if( _driverState <DriverState::Opened )
|
||||
return std::unexpected(QString("readRawValue error: driver not loaded." ) );
|
||||
|
||||
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
|
||||
|
||||
::TCanMsg msg;
|
||||
int timeout_count = cTIMEOUT_COUNT;
|
||||
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = deviceID;
|
||||
msg.MsgLen = 4;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -37,39 +37,27 @@
|
||||
|
||||
class BCDriverTinyCan : public BCDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCDriverTinyCan( QObject* parent=nullptr );
|
||||
virtual ~BCDriverTinyCan() = default;
|
||||
virtual ~BCDriverTinyCan();
|
||||
|
||||
BCDriver::DriverStateResult loadAndStartDriver() override;
|
||||
void resetDriver();
|
||||
|
||||
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:
|
||||
private:
|
||||
|
||||
void onStartDriver() override;
|
||||
|
||||
protected:
|
||||
|
||||
void loadDriver();
|
||||
DriverState connectDriver();
|
||||
|
||||
//const char* CBCDLL_LIN = "libmhstcan.so";
|
||||
//const char* CBCDLL_WIN = "mhstcan.dll";
|
||||
BCDriver::DriverStateResult loadDriver();
|
||||
BCDriver::DriverStateResult setConsoleSlaveMode();
|
||||
|
||||
static constexpr int cRetries = 5;
|
||||
static constexpr int cTimeOuts = 20;
|
||||
static constexpr int cTIMEOUT_MS = 10; // 10ms
|
||||
static constexpr int cTIMEOUT_COUNT = 10;
|
||||
|
||||
//const unsigned int BATTERY = 0x010;
|
||||
//const unsigned int MOTOR = 0x020;
|
||||
const unsigned int BIB = 0x048;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // BCDRIVERTINYCAN_H
|
||||
|
||||
250
bcguihelpers.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 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 <bcguihelpers.h>
|
||||
|
||||
|
||||
BCThemeSwitchButton::BCThemeSwitchButton(QWidget *parent )
|
||||
: QPushButton(parent)
|
||||
{
|
||||
// Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
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"(
|
||||
BCThemeSwitchButton
|
||||
{
|
||||
border: none;
|
||||
background-color: green;
|
||||
font-size: 11pt;
|
||||
}
|
||||
BCThemeSwitchButton:Hover
|
||||
{
|
||||
background-color: rgba(128, 128, 128, 30);
|
||||
border-radius: 24px;
|
||||
}
|
||||
)");
|
||||
|
||||
// Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
||||
updateIcon();
|
||||
|
||||
connect(this, &QPushButton::clicked, this, &BCThemeSwitchButton::toggleMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Setzt den DarkMode
|
||||
*/
|
||||
|
||||
void BCThemeSwitchButton::setDarkMode( bool isDark )
|
||||
{
|
||||
_isDarkMode = !isDark;
|
||||
toggleMode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Schaltet den akutellen Mode um.
|
||||
*/
|
||||
|
||||
void BCThemeSwitchButton::toggleMode()
|
||||
{
|
||||
_isDarkMode = !_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(_isDarkMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Icon & Tooltip anpassen
|
||||
*/
|
||||
|
||||
void BCThemeSwitchButton::updateIcon()
|
||||
{
|
||||
// Logik:
|
||||
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
||||
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
||||
setText(_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(_isDarkMode ? "Zum LightMode wechseln" : "Zum DarkMode wechseln");
|
||||
}
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* @brief Hilfswidget: Zeigt den DriverState als Icon an.
|
||||
*/
|
||||
|
||||
BCDriverStateWidget::BCDriverStateWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(10, 2, 10, 2);
|
||||
//layout->setSpacing(8);
|
||||
|
||||
_led = new QLabel(this);
|
||||
_led->setFixedSize(12, 12);
|
||||
|
||||
layout->addWidget(_led);
|
||||
|
||||
// Startzustand
|
||||
onDriverStateChanged(BCDriver::DriverState::NotPresent, "Not Present");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void BCDriverStateWidget::onDriverStateChanged(BCDriver::DriverState state, const QString& customMessage)
|
||||
{
|
||||
_state = state;
|
||||
qDebug() << " --- StateWidget: " << state << " - " << customMessage;
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
/*
|
||||
void BCDriverStateWidget::updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString labelColor;
|
||||
QString toolTipText;
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;#FF5F1F; #FF8C00;<- das isses #FF6700";
|
||||
labelColor = "#FFFFFF"; // Weiß (Hervorgehoben)
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
labelColor = "#FF99A4"; // Ein helleres Rot für Text, damit es auf Dunkel lesbar ist
|
||||
toolTipText = "Kritischer Fehler bei der Verbindung!";
|
||||
break;
|
||||
|
||||
default:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
labelColor = "#9E9E9E"; // Ausgegrauter Text
|
||||
toolTipText = "System ist offline.";
|
||||
break;
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
|
||||
// Textfarbe setzen
|
||||
_label->setStyleSheet(QString("color: %1; font-weight: %2;")
|
||||
.arg(labelColor)
|
||||
.arg(_state == BCDriver::DriverState::DeviceReady ? "bold" : "normal"));
|
||||
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
*/
|
||||
|
||||
void BCDriverStateWidget::updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString toolTipText;
|
||||
/*
|
||||
NotPresent,
|
||||
Error,
|
||||
Loaded,
|
||||
Initialized,
|
||||
Opened, // bis hierher: dll vorhanden, Treiber geladen
|
||||
DeviceReady
|
||||
*/
|
||||
switch (_state)
|
||||
{
|
||||
case BCDriver::DriverState::NotPresent:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
toolTipText = "Treiber nicht geladen.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
toolTipText = "Fehler beim Laden des Treibers.";
|
||||
break;
|
||||
|
||||
// hier: dll vorhanden, Treiber geladen
|
||||
case BCDriver::DriverState::Loaded:
|
||||
case BCDriver::DriverState::Initialized:
|
||||
case BCDriver::DriverState::Opened:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #FF8C00; border: 1px solid #A80000;";
|
||||
toolTipText = "Fehler beim Laden des Treibers.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;";
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
|
||||
/*
|
||||
// Textfarbe setzen
|
||||
_setStyleSheet(QString("color: %1; font-weight: %2;")
|
||||
.arg(labelColor)
|
||||
.arg(_state == BCDriver::DriverState::DeviceReady ? "bold" : "normal"));
|
||||
*/
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
|
||||
void BCDriverStateWidget::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
emit clicked();
|
||||
}
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
|
||||
113
bcguihelpers.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 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 BCGUIHELPERS_H
|
||||
#define BCGUIHELPERS_H
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include <bcdriver.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Einfaches Buttonwidget, um zwischen Dark- und Lightmode
|
||||
* zu wechseln
|
||||
*/
|
||||
|
||||
class BCThemeSwitchButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCThemeSwitchButton(QWidget *parent = nullptr);
|
||||
void setDarkMode( bool isDark );
|
||||
|
||||
signals:
|
||||
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
|
||||
void toggleMode();
|
||||
|
||||
private:
|
||||
|
||||
void updateIcon();
|
||||
|
||||
bool _isDarkMode{false};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* @brief Einfaches Widget, um den Zustand des TinyCan Native
|
||||
* Drivers anzuzeigen.
|
||||
*/
|
||||
|
||||
class BCDriverStateWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCDriverStateWidget(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void onDriverStateChanged(BCDriver::DriverState state, const QString& customMessage = QString());
|
||||
|
||||
signals:
|
||||
|
||||
void clicked();
|
||||
|
||||
protected:
|
||||
|
||||
void updateStyle();
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
|
||||
QLabel* _led;
|
||||
BCDriver::DriverState _state;
|
||||
|
||||
};
|
||||
|
||||
#endif // BCGUIHELPERS_H
|
||||
122
bcmainwindow.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -29,14 +29,14 @@
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include "qassert.h"
|
||||
#include <bcmainwindow.h>
|
||||
#include <bcanimateddelegate.h>
|
||||
#include <ui_bcmainwindow.h>
|
||||
|
||||
#include <bcguihelpers.h>
|
||||
|
||||
/**
|
||||
* @brief Das Mainwindow erzeugen
|
||||
@@ -52,8 +52,6 @@ BCMainWindow::BCMainWindow(QWidget *parent)
|
||||
|
||||
setupUi(this);
|
||||
|
||||
// den pimp-my-ride-button schalten wir vorerst aus.
|
||||
_pimpButton->hide();
|
||||
|
||||
// Wir schreiben den 'initMainWindow()' Aufruf mit Hilfe des
|
||||
// timers in die Event-Queue, damit er erst ausgeführt wird,
|
||||
@@ -111,13 +109,11 @@ void BCMainWindow::initMainWindow()
|
||||
_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 );
|
||||
configureAction(_consoleButton, _consoleAction, BCDevice::ID::Console );
|
||||
configureAction(_batteryButton, _batteryAction, BCDevice::ID::Battery );
|
||||
//configureAction(_pimpButton, _pimpAction, BCDevice::ID::Pimp );
|
||||
|
||||
/*
|
||||
bool m_isDarkMode = false;
|
||||
@@ -141,57 +137,109 @@ void BCMainWindow::initMainWindow()
|
||||
|
||||
fitzeButton->setStyleSheet(style);
|
||||
*/
|
||||
|
||||
initStatusBar();
|
||||
|
||||
// besser: model::emit dataChanged
|
||||
// also: emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, ValueRole});
|
||||
connect( _connectButton, &QToolButton::clicked, &_transmitter, &BCTransmitter::onToggleConnectionState );
|
||||
connect( _connectButton, &QToolButton::clicked, &_transmitter, &BCTransmitter::onToggleDriverConnection );
|
||||
connect( _syncButton, &QToolButton::clicked, this, &BCMainWindow::onSyncDeviceView );
|
||||
connect( _exitButton, &QToolButton::clicked, qApp, &QCoreApplication::quit );
|
||||
|
||||
connect( &_transmitter, &BCTransmitter::valueUpdated, this, &BCMainWindow::onValueUpdated );
|
||||
|
||||
|
||||
_transmitter.moveToThread(&_worker);
|
||||
|
||||
connect(this, &BCMainWindow::requestValueUpdate, &_transmitter, &BCTransmitter::enqueueValue);
|
||||
connect( this, &BCMainWindow::requestValueUpdate, &_transmitter, &BCTransmitter::onUpdateValue);
|
||||
connect( &_worker, &QThread::finished, &_transmitter, &QObject::deleteLater);
|
||||
connect( &_transmitter, &BCTransmitter::driverStateChanged, this, &BCMainWindow::onDriverStateChanged );
|
||||
|
||||
// transmitter starten
|
||||
_transmitter.moveToThread(&_worker);
|
||||
_worker.start();
|
||||
|
||||
// die Daten des eBikes laden
|
||||
_dataManager.loadXmlBikeData(":/bikeinfo.xml"_L1);
|
||||
//_consoleAction->trigger();
|
||||
_batteryAction->trigger();
|
||||
_consoleAction->trigger();
|
||||
//_batteryAction->trigger();
|
||||
|
||||
// Dummy sync beim starten
|
||||
|
||||
QTimer::singleShot(1000, this, [this]()
|
||||
{
|
||||
onSyncDeviceView();
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
// 2. Bild für den Zustand UNCHECKED (Off) hinzufügen
|
||||
// Das ist das Symbol, wenn NICHT verbunden ist (z.B. ein Stecker)
|
||||
connectIcon.addFile(":/icons/plug_disconnected.svg", QSize(), QIcon::Normal, QIcon::Off);
|
||||
|
||||
// 3. Bild für den Zustand CHECKED (On) hinzufügen
|
||||
// Das ist das Symbol, wenn verbunden IST (z.B. Stecker in Dose)
|
||||
connectIcon.addFile(":/icons/plug_connected.svg", QSize(), QIcon::Normal, QIcon::On);
|
||||
*/
|
||||
|
||||
void BCMainWindow::initStatusBar()
|
||||
{
|
||||
// __fix
|
||||
QStatusBar *statBar = statusBar();
|
||||
|
||||
// Optional: Normale Nachricht links
|
||||
BCDriverStateWidget* conState = new BCDriverStateWidget(this);
|
||||
connect( &_transmitter, &BCTransmitter::driverStateChanged, conState, &BCDriverStateWidget::onDriverStateChanged );
|
||||
connect( conState, &BCDriverStateWidget::clicked, _connectAction, &QAction::trigger );
|
||||
|
||||
statBar->addPermanentWidget(conState);
|
||||
conState->installEventFilter(this);
|
||||
|
||||
BCThemeSwitchButton* themeBtn = new BCThemeSwitchButton(this);
|
||||
statBar->addPermanentWidget(themeBtn);
|
||||
connect(themeBtn, &BCThemeSwitchButton::themeChanged, this, [this](bool isDark)
|
||||
{
|
||||
|
||||
QString message = isDark ? "Dark Mode Activated" : "Light Mode Activated";
|
||||
statusBar()->showMessage( message, 3000);
|
||||
setApplicationStyleSheet( isDark ? ":claude_dark_mode.qss"_L1 : ":claude_light_mode.qss"_L1 );
|
||||
});
|
||||
|
||||
// Wir starten im light mode
|
||||
//themeBtn->setDarkMode( false );
|
||||
|
||||
statBar->showMessage("Ready");
|
||||
|
||||
// 1. Unseren Switcher erstellen
|
||||
ThemeSwitchButton *themeBtn = new ThemeSwitchButton(this);
|
||||
setApplicationStyleSheet(":bionxcontrol.qss"_L1);
|
||||
|
||||
// 2. WICHTIG: Rechts hinzufügen
|
||||
statBar->addPermanentWidget(themeBtn);
|
||||
}
|
||||
|
||||
// 3. Signal verbinden: Button klick -> Theme ändern
|
||||
connect(themeBtn, &ThemeSwitchButton::themeChanged, this, [this](bool isDark){
|
||||
if (isDark)
|
||||
/*
|
||||
bool BCMainWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
//applyFluentDarkTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Dark Mode Activated", 3000);
|
||||
if (obj == myWidget && event->type() == QEvent::MouseButtonRelease) {
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
if (mouseEvent->button() == Qt::LeftButton) {
|
||||
myAction->trigger();
|
||||
return true; // Event wurde verarbeitet
|
||||
}
|
||||
else
|
||||
}
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Setzt das Stylesheet, hier: Dark- oder Lightmode
|
||||
* @param path Der Pfad zuum Stylesheet
|
||||
* @return
|
||||
*/
|
||||
|
||||
bool BCMainWindow::setApplicationStyleSheet( QAnyStringView path )
|
||||
{
|
||||
//applyFluentLightTheme(*qApp); // Funktion von vorhin
|
||||
statusBar()->showMessage("Light Mode Activated", 3000);
|
||||
QFile styleFile( path.toString() );
|
||||
if (styleFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QString style = styleFile.readAll();
|
||||
qApp->setStyleSheet(style);
|
||||
styleFile.close();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
qWarning() << "Konnte Stylesheet nicht laden:" << styleFile.errorString();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +253,10 @@ void BCMainWindow::setHeaderLabel( const QString& headerText)
|
||||
_headerLabel->setText( " BionxControl: " + headerText );
|
||||
}
|
||||
|
||||
void BCMainWindow::onShowMessage( const QString& message, int timeOut )
|
||||
{
|
||||
_statusbar->showMessage( message, timeOut );
|
||||
}
|
||||
|
||||
void BCMainWindow::autoConnect()
|
||||
{
|
||||
@@ -216,6 +268,7 @@ void BCMainWindow::autoConnect()
|
||||
void BCMainWindow::onDriverStateChanged( BCDriver::DriverState state, const QString& message )
|
||||
{
|
||||
qDebug() << " --- on DriverStatusChanged: " << state << ":" << message;
|
||||
_statusbar->showMessage( message, 8000 );
|
||||
}
|
||||
|
||||
void BCMainWindow::onShowDevicePanel( BCDevice::ID deviceID )
|
||||
@@ -271,11 +324,14 @@ void BCMainWindow::onSyncDeviceView()
|
||||
|
||||
for( const BCValuePtr& value : currentList )
|
||||
{
|
||||
qDebug() << " --- begin sync of value: " << value->label;
|
||||
qDebug() << " --- begin sync of value: " << QThread::currentThreadId() << " : " << value->label;
|
||||
// wir setzen auf 'lesen'
|
||||
value->state.setFlag( BCValue::State::ReadMe );
|
||||
// statt '_transmitter.enqueueValueCommand( value )' entkoppeln
|
||||
// wir das eleganter über emit requestValueUpdate()
|
||||
|
||||
// statt '_transmitter.onUpdateValue( value )' müssen wir hier
|
||||
// über emit requestValueUpdate() zur Thread sysnchronisation
|
||||
// entkoppeln,
|
||||
|
||||
emit requestValueUpdate( value);
|
||||
|
||||
}
|
||||
|
||||
177
bcmainwindow.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -34,9 +34,11 @@
|
||||
#define BCMAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QThread>
|
||||
|
||||
#include <ui_bcmainwindow.h>
|
||||
#include <bcxmlloader.h>
|
||||
#include <bctransmitter.h>
|
||||
|
||||
class BCDeviceView;
|
||||
|
||||
@@ -58,10 +60,12 @@ public slots:
|
||||
void onConnectButtonToggled(bool active );
|
||||
void onDriverStateChanged( BCDriver::DriverState state, const QString& message="" );
|
||||
|
||||
// Slots für Rückmeldungen vom Runner
|
||||
// Slots für Rückmeldungen vom Transmitter
|
||||
void onValueUpdated( BCDevice::ID deviceID, int index, BCValue::State state, const QString& newValue="" );
|
||||
void onSyncDeviceView();
|
||||
|
||||
void onShowMessage( const QString& message, int timeOut=3000);
|
||||
|
||||
signals:
|
||||
|
||||
// Internes Signal, um Daten an den Worker Thread zu senden
|
||||
@@ -69,10 +73,13 @@ signals:
|
||||
|
||||
protected:
|
||||
|
||||
bool setApplicationStyleSheet( QAnyStringView path );
|
||||
void initMainWindow();
|
||||
void initStatusBar();
|
||||
void autoConnect();
|
||||
|
||||
//bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
BCXmlLoader _dataManager;
|
||||
|
||||
// Wir brauchen eine Verbindung zwischen den Views
|
||||
@@ -90,170 +97,4 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ThemeSwitchButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ThemeSwitchButton(QWidget *parent = nullptr)
|
||||
: QPushButton(parent), m_isDarkMode(true)
|
||||
{
|
||||
// 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
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"(
|
||||
QPushButton {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 11pt;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
|
||||
border-radius: 24px;
|
||||
}
|
||||
)");
|
||||
|
||||
// 2. Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
||||
updateIcon();
|
||||
|
||||
// 3. Klick verbinden
|
||||
connect(this, &QPushButton::clicked, this, &ThemeSwitchButton::toggle);
|
||||
}
|
||||
|
||||
signals:
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
void toggle() {
|
||||
m_isDarkMode = !m_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(m_isDarkMode);
|
||||
}
|
||||
|
||||
private:
|
||||
void updateIcon() {
|
||||
// Logik:
|
||||
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
||||
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
||||
setText(m_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(m_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode");
|
||||
}
|
||||
|
||||
bool m_isDarkMode;
|
||||
};
|
||||
|
||||
|
||||
class BCConnectionWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Definition der 3 Zustände
|
||||
enum class State
|
||||
{
|
||||
Disconnected, // Grau: Offline / Standby
|
||||
Connected, // Grün: Alles OK
|
||||
Error // Rot: Fehler / Timeout / Abbruch
|
||||
};
|
||||
Q_ENUM(State) // Damit Qt das Enum kennt (optional, gut für Debugging)
|
||||
|
||||
explicit BCConnectionWidget(QWidget *parent = nullptr)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(10, 2, 10, 2);
|
||||
layout->setSpacing(8);
|
||||
|
||||
// 1. Die LED
|
||||
m_led = new QLabel(this);
|
||||
m_led->setFixedSize(12, 12);
|
||||
|
||||
// 2. Der Text
|
||||
m_label = new QLabel(this);
|
||||
m_label->setStyleSheet("font-weight: 500;"); // Medium weight
|
||||
|
||||
layout->addWidget(m_led);
|
||||
layout->addWidget(m_label);
|
||||
|
||||
// Startzustand
|
||||
setState(State::Disconnected, "Offline");
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void setState(State state, const QString &customMessage = QString())
|
||||
{
|
||||
m_state = state;
|
||||
|
||||
// Standard-Texte, falls keine Nachricht übergeben wurde
|
||||
QString text = customMessage;
|
||||
if (text.isEmpty()) {
|
||||
switch (state) {
|
||||
case State::Connected: text = "Online"; break;
|
||||
case State::Disconnected: text = "Not Connected"; break;
|
||||
case State::Error: text = "Connection Error"; break;
|
||||
}
|
||||
}
|
||||
m_label->setText(text);
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString labelColor;
|
||||
QString toolTipText;
|
||||
|
||||
switch (m_state) {
|
||||
case State::Connected:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;#FF5F1F; #FF8C00;<- das isses #FF6700";
|
||||
labelColor = "#FFFFFF"; // Weiß (Hervorgehoben)
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
|
||||
case State::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
labelColor = "#FF99A4"; // Ein helleres Rot für Text, damit es auf Dunkel lesbar ist
|
||||
toolTipText = "Kritischer Fehler bei der Verbindung!";
|
||||
break;
|
||||
|
||||
case State::Disconnected:
|
||||
default:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
labelColor = "#9E9E9E"; // Ausgegrauter Text
|
||||
toolTipText = "System ist offline.";
|
||||
break;
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
m_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
|
||||
// Textfarbe setzen
|
||||
m_label->setStyleSheet(QString("color: %1; font-weight: %2;")
|
||||
.arg(labelColor)
|
||||
.arg(m_state == State::Connected ? "bold" : "normal"));
|
||||
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
|
||||
QLabel *m_led;
|
||||
QLabel *m_label;
|
||||
State m_state;
|
||||
};
|
||||
|
||||
#endif // BCMAINWINDOW_H
|
||||
|
||||
187
bcmainwindow.ui
@@ -19,6 +19,9 @@
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="_centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
@@ -68,9 +71,15 @@
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">_buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
@@ -90,9 +99,15 @@
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">_buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
@@ -112,31 +127,18 @@
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_pimpButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">_buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -154,25 +156,79 @@
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_syncButton">
|
||||
<property name="text">
|
||||
<string>Sync</string>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="_connectButton">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<normaloff>:/sync_yellow.svg</normaloff>:/sync_yellow.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fitzeButton">
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_connectButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fitze</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<normaloff>:/connect.svg</normaloff>:/connect.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_exitButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<normaloff>:/exit_red.svg</normaloff>:/exit_red.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -194,7 +250,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="BCDeviceView" name="_consolePanel">
|
||||
<property name="frameShape">
|
||||
@@ -283,35 +339,6 @@
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="BCDeviceView" name="_pimpPanel">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::PenStyle::NoPen</enum>
|
||||
</property>
|
||||
<property name="BCHeaderLabel" stdset="0">
|
||||
<string>Pimp my Ride ...</string>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -319,21 +346,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="_statusbar"/>
|
||||
<action name="_pimpAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:restart.png</normaloff>:restart.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>pimp</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Pimp my Ride</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_motorAction">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
@@ -343,7 +355,7 @@
|
||||
<string>motor</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show motor settings</string>
|
||||
<string>Motoreinstellungen anzeigen und bearbeiten</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_batteryAction">
|
||||
@@ -355,7 +367,7 @@
|
||||
<string>battery</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show battery settings</string>
|
||||
<string>Batterieeinstellungen anzeigen und bearbeiten</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_consoleAction">
|
||||
@@ -367,31 +379,19 @@
|
||||
<string>console</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show console settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_exitAction">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:exit.png</normaloff>:exit.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Exit</string>
|
||||
<string>Konseleneinstellungen anzeigen und bearbeiten</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_connectAction">
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/connected.png</normaloff>:/connected.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>connect</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>connect to bike</string>
|
||||
<string>TinyCAN native Treiber laden</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::TextHeuristicRole</enum>
|
||||
@@ -409,4 +409,7 @@
|
||||
<include location="bionxcontrol.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="_buttonGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
||||
34
bcsliderstyle.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 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 <bcsliderstyle.h>
|
||||
|
||||
269
bcsliderstyle.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 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 BCSLIDERSTYLE_H
|
||||
#define BCSLIDERSTYLE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QTableView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHeaderView>
|
||||
|
||||
#include <QSlider>
|
||||
#include <QPainter>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QPushButton>
|
||||
#include <QLineEdit>
|
||||
#include <QSlider>
|
||||
#include <QCheckBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QProxyStyle>
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionSlider>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
|
||||
// Fluent Design Slider Style
|
||||
class FluentSliderStyle : public QProxyStyle
|
||||
{
|
||||
public:
|
||||
|
||||
FluentSliderStyle()
|
||||
: QProxyStyle()
|
||||
{}
|
||||
|
||||
// Wichtig: Genug Platz für Handle reservieren
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override
|
||||
{
|
||||
switch (metric)
|
||||
{
|
||||
case PM_SliderThickness:
|
||||
return 32; // Höhe für horizontalen Slider
|
||||
case PM_SliderLength:
|
||||
return 20; // Handle-Größe
|
||||
case PM_SliderControlThickness:
|
||||
return 20;
|
||||
case PM_SliderSpaceAvailable:
|
||||
if (option)
|
||||
{
|
||||
if (const QStyleOptionSlider* sliderOpt = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
||||
if (sliderOpt->orientation == Qt::Horizontal) {
|
||||
return sliderOpt->rect.width() - 20;
|
||||
} else {
|
||||
return sliderOpt->rect.height() - 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
|
||||
default:
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
}
|
||||
|
||||
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt,SubControl sc, const QWidget* widget) const override
|
||||
{
|
||||
if (cc == CC_Slider) {
|
||||
if (const QStyleOptionSlider* slider = qstyleoption_cast<const QStyleOptionSlider*>(opt)) {
|
||||
QRect rect = slider->rect;
|
||||
int handleSize = 20;
|
||||
|
||||
if (sc == SC_SliderHandle) {
|
||||
// Handle Position korrekt berechnen
|
||||
if (slider->orientation == Qt::Horizontal) {
|
||||
int range = slider->maximum - slider->minimum;
|
||||
int pos = slider->sliderPosition - slider->minimum;
|
||||
int pixelRange = rect.width() - handleSize;
|
||||
int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0;
|
||||
|
||||
return QRect(rect.x() + pixelPos,
|
||||
rect.center().y() - handleSize / 2,
|
||||
handleSize, handleSize);
|
||||
} else {
|
||||
int range = slider->maximum - slider->minimum;
|
||||
int pos = slider->sliderPosition - slider->minimum;
|
||||
int pixelRange = rect.height() - handleSize;
|
||||
int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0;
|
||||
|
||||
return QRect(rect.center().x() - handleSize / 2,
|
||||
rect.bottom() - pixelPos - handleSize,
|
||||
handleSize, handleSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return QProxyStyle::subControlRect(cc, opt, sc, widget);
|
||||
}
|
||||
|
||||
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override
|
||||
{
|
||||
if (control == CC_Slider)
|
||||
{
|
||||
if (const QStyleOptionSlider* slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// Fluent Colors
|
||||
QColor accentColor(0, 120, 212); // #0078D4
|
||||
QColor inactiveColor(138, 136, 134); // #8A8886
|
||||
QColor bgColor(255, 255, 255); // White background
|
||||
|
||||
if (slider->orientation == Qt::Horizontal) {
|
||||
drawHorizontalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor);
|
||||
} else {
|
||||
drawVerticalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void drawHorizontalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider,
|
||||
const QColor& activeColor, const QColor& inactiveColor,
|
||||
const QColor& bgColor) const {
|
||||
QRect groove = slider->rect;
|
||||
QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr);
|
||||
|
||||
int grooveHeight = 4;
|
||||
// Track sollte im Widget-Zentrum sein, nicht im groove-Zentrum
|
||||
int grooveY = slider->rect.center().y() - grooveHeight / 2;
|
||||
|
||||
// Full background track
|
||||
QRect fullTrack(groove.left(), grooveY, groove.width(), grooveHeight);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(inactiveColor.lighter(150));
|
||||
painter->drawRoundedRect(fullTrack, grooveHeight / 2, grooveHeight / 2);
|
||||
|
||||
// Active track (filled portion)
|
||||
int activeWidth = handle.center().x() - groove.left();
|
||||
QRect activeTrack(groove.left(), grooveY, activeWidth, grooveHeight);
|
||||
painter->setBrush(activeColor);
|
||||
painter->drawRoundedRect(activeTrack, grooveHeight / 2, grooveHeight / 2);
|
||||
|
||||
// Handle (Thumb) - Fluent style is more subtle
|
||||
int handleSize = 20;
|
||||
QRect thumbRect(handle.center().x() - handleSize / 2,
|
||||
handle.center().y() - handleSize / 2,
|
||||
handleSize, handleSize);
|
||||
|
||||
// Hover effect - subtle glow
|
||||
if (slider->state & State_MouseOver) {
|
||||
painter->setBrush(QColor(activeColor.red(), activeColor.green(),
|
||||
activeColor.blue(), 30));
|
||||
int glowSize = 32;
|
||||
QRect glow(handle.center().x() - glowSize / 2,
|
||||
handle.center().y() - glowSize / 2,
|
||||
glowSize, glowSize);
|
||||
painter->drawEllipse(glow);
|
||||
}
|
||||
|
||||
// Thumb
|
||||
painter->setBrush(bgColor);
|
||||
painter->setPen(QPen(activeColor, 2));
|
||||
painter->drawEllipse(thumbRect);
|
||||
|
||||
// Inner circle for pressed state
|
||||
if (slider->state & State_Sunken) {
|
||||
int innerSize = 8;
|
||||
QRect inner(handle.center().x() - innerSize / 2,
|
||||
handle.center().y() - innerSize / 2,
|
||||
innerSize, innerSize);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(activeColor);
|
||||
painter->drawEllipse(inner);
|
||||
}
|
||||
}
|
||||
|
||||
void drawVerticalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider,
|
||||
const QColor& activeColor, const QColor& inactiveColor,
|
||||
const QColor& bgColor) const {
|
||||
QRect groove = slider->rect;
|
||||
QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr);
|
||||
|
||||
int grooveWidth = 4;
|
||||
// Track sollte im Widget-Zentrum sein
|
||||
int grooveX = slider->rect.center().x() - grooveWidth / 2;
|
||||
|
||||
// Full background track
|
||||
QRect fullTrack(grooveX, groove.top(), grooveWidth, groove.height());
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(inactiveColor.lighter(150));
|
||||
painter->drawRoundedRect(fullTrack, grooveWidth / 2, grooveWidth / 2);
|
||||
|
||||
// Active track
|
||||
int activeHeight = groove.bottom() - handle.center().y();
|
||||
QRect activeTrack(grooveX, handle.center().y(), grooveWidth, activeHeight);
|
||||
painter->setBrush(activeColor);
|
||||
painter->drawRoundedRect(activeTrack, grooveWidth / 2, grooveWidth / 2);
|
||||
|
||||
// Handle
|
||||
int handleSize = 20;
|
||||
QRect thumbRect(handle.center().x() - handleSize / 2,
|
||||
handle.center().y() - handleSize / 2,
|
||||
handleSize, handleSize);
|
||||
|
||||
if (slider->state & State_MouseOver) {
|
||||
painter->setBrush(QColor(activeColor.red(), activeColor.green(),
|
||||
activeColor.blue(), 30));
|
||||
int glowSize = 32;
|
||||
QRect glow(handle.center().x() - glowSize / 2,
|
||||
handle.center().y() - glowSize / 2,
|
||||
glowSize, glowSize);
|
||||
painter->drawEllipse(glow);
|
||||
}
|
||||
|
||||
painter->setBrush(bgColor);
|
||||
painter->setPen(QPen(activeColor, 2));
|
||||
painter->drawEllipse(thumbRect);
|
||||
|
||||
if (slider->state & State_Sunken) {
|
||||
int innerSize = 8;
|
||||
QRect inner(handle.center().x() - innerSize / 2,
|
||||
handle.center().y() - innerSize / 2,
|
||||
innerSize, innerSize);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(activeColor);
|
||||
painter->drawEllipse(inner);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // BCSLIDERSTYLE_H
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -30,98 +30,125 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "bcvaluetype.h"
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <bctransmitter.h>
|
||||
|
||||
/**
|
||||
* @brief Kosntruktion. Aktiviert erstmal den Dummy-Driver.
|
||||
*/
|
||||
|
||||
BCTransmitter::BCTransmitter(QObject *parent)
|
||||
: QObject(parent), _isBusy(false)
|
||||
: QObject(parent)//, _isBusy(false)
|
||||
{
|
||||
//_canDriver = new BCDriverTinyCan{this};
|
||||
_canDriver = new BCDriverDummy{this};
|
||||
// forward driver state
|
||||
connect( _canDriver, &BCDriver::driverStateChanged, this, &BCTransmitter::driverStateChanged );
|
||||
_canDriver = &_dummyDriver;
|
||||
}
|
||||
|
||||
|
||||
void BCTransmitter::onToggleConnectionState( bool connect )
|
||||
/**
|
||||
* @brief Steuert die Verbindung mit dem 'echten' CAN-Bus Treiber.
|
||||
* @param connect true: Vesuche den CAN-Bus Treiber zu laden und zu verbinden
|
||||
* false: Disconnect & Cleanup
|
||||
*/
|
||||
|
||||
void BCTransmitter::onToggleDriverConnection( bool connect )
|
||||
{
|
||||
if( connect )
|
||||
{
|
||||
if( _canDriver->getDriverState() != BCDriver::DriverState::DeviceReady )
|
||||
_canDriver->onStartDriver();
|
||||
|
||||
// __fix!
|
||||
TransmitResult hwVersion = _canDriver->readRawByte( (uint32_t)BCDevice::ID::Console, (uint8_t)BC::ID::Cons_Rev_Hw);
|
||||
if(!hwVersion)
|
||||
{
|
||||
qDebug() << "Console not responding";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
qDebug() << " ---HAIL to the kings: " << hwVersion.value();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BCTransmitter::enqueueValue( BCValuePtrConst value)
|
||||
{
|
||||
// Hier sind wir noch in GUI Thread
|
||||
QMutexLocker locker(&_mutex);
|
||||
_valueQueue.enqueue( value );
|
||||
|
||||
// wir wollen nicht den ganzen Value verschicken, erstrecht
|
||||
// wollen wir nicht 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 enqueueValue sofort zurückkehrt (non-blocking für den Aufrufer).
|
||||
|
||||
QMetaObject::invokeMethod(this, "processValue", Qt::QueuedConnection);
|
||||
qDebug() << " --- onToggleDriverConnection: " << connect;
|
||||
emit driverStateChanged(BCDriver::DriverState::Initialized, "BUSY!");
|
||||
bc::delay_millis(350);
|
||||
// kill all pending stuff
|
||||
QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
|
||||
// FIX! Ende der current op abwarten!
|
||||
BCDriver::DriverState state = connect ? BCDriver::DriverState::DeviceReady : BCDriver::DriverState::NotPresent;
|
||||
const QString& message = connect ? "Trying to connect" : " FAILED";
|
||||
emit driverStateChanged(state, message);
|
||||
return;
|
||||
|
||||
/*
|
||||
QMetaObject::invokeMethod(this, [this]()
|
||||
{
|
||||
processValue();
|
||||
}, Qt::QueuedConnection );
|
||||
// Hier sind wir noch in GUI Thread
|
||||
QMutexLocker locker(&_mutex);
|
||||
// weitere operation stoppen
|
||||
_isBusy = true;
|
||||
connect ? connectCanDriver() : disconnectCanDriver();
|
||||
_isBusy = false;
|
||||
*/
|
||||
}
|
||||
|
||||
void BCTransmitter::processValue()
|
||||
|
||||
void BCTransmitter::onStartNativeDriver()
|
||||
{
|
||||
|
||||
if (_isBusy)
|
||||
return;
|
||||
|
||||
_isBusy = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
BCValuePtrConst valuePtr{};
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
if (_valueQueue.isEmpty())
|
||||
{
|
||||
_isBusy = false;
|
||||
break; // Schleife verlassen, warten auf neue Events
|
||||
}
|
||||
valuePtr =_valueQueue.dequeue();
|
||||
} // Mutex wird hier freigegeben! WICHTIG: Execute ohne Lock!
|
||||
|
||||
void BCTransmitter::connectCanDriver()
|
||||
{
|
||||
// hier gehts nur um den echten Treiber
|
||||
|
||||
// Treiber laden und/oder starten:
|
||||
BCDriver::DriverStateResult result; //(defaults to 'NotPresent')
|
||||
if( _tinyCanDriver.getDriverState() != BCDriver::DriverState::DeviceReady )
|
||||
result = _tinyCanDriver.loadAndStartDriver();
|
||||
|
||||
QString message("FitzeFatze!");
|
||||
// hat geklappt
|
||||
if( _tinyCanDriver.getDriverState() >= BCDriver::DriverState::Opened )
|
||||
{
|
||||
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
|
||||
uint8_t hwRev = static_cast<uint8_t> (BC::ID::Cons_Rev_Hw);
|
||||
|
||||
TransmitResult hwVersion = _tinyCanDriver.readRawByte( console, hwRev);
|
||||
if( hwVersion.has_value() )
|
||||
{
|
||||
message = " ---- HAIL to the king!";
|
||||
qDebug() << message;
|
||||
// swap driver
|
||||
_canDriver = &_tinyCanDriver;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Console not responding";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
message = result.error();
|
||||
}
|
||||
emit driverStateChanged( _tinyCanDriver.getDriverState(), message );
|
||||
}
|
||||
|
||||
void BCTransmitter::disconnectCanDriver()
|
||||
{
|
||||
_tinyCanDriver.resetDriver();
|
||||
_canDriver = &_dummyDriver;
|
||||
emit driverStateChanged( _tinyCanDriver.getDriverState(), "Disconnected" );
|
||||
}
|
||||
|
||||
|
||||
void BCTransmitter::onUpdateValue( BCValuePtrConst valuePtr)
|
||||
{
|
||||
|
||||
// wir stellen hier auf die harte Tour sicher, das onUpdateValue
|
||||
// nicht aus dem Parent-Thread direkt sondern über die EventQueue aufgerufen wurde.
|
||||
|
||||
Q_ASSERT(QThread::currentThread() == this->thread());
|
||||
|
||||
// Wir arbeiten hier ohne besondere Threadsynchronisation, mutexed o.ä: Die
|
||||
// entkoppelung und serialisierung passiert bereits durch die Qt-Eventqueue.
|
||||
// Das klappt aber nur in der hier gewählten Konstellation mit einer Parent-Thread
|
||||
// und einem Worker.
|
||||
|
||||
// Kosmetik
|
||||
const BCValue& value = *(valuePtr.get());
|
||||
|
||||
qDebug() << "------- DE.-.QUEUE: " << QThread::currentThreadId() << ": " << value.label;
|
||||
|
||||
// Value ist 'under construction'
|
||||
//emit valueUpdated( value.deviceID, value.indexRow, BCValue::State::Locked );
|
||||
|
||||
const BCValueType& valueType = *value.valueType;
|
||||
|
||||
uint32_t devID = static_cast<uint32_t>(value.deviceID);
|
||||
uint8_t regID = static_cast<uint8_t> (value.registerID);
|
||||
|
||||
@@ -138,56 +165,56 @@ void BCTransmitter::processValue()
|
||||
|
||||
else if( value.state.testFlag( BCValue::State::ReadMe ) )
|
||||
{
|
||||
|
||||
// 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() )
|
||||
{
|
||||
newVisibleValue = valueType.formatValue( result.value() );
|
||||
// quark! das gehört hier nicht hin!
|
||||
newVisibleValue = value.formatValues( result.value() );
|
||||
newState = BCValue::State::InSync;
|
||||
}
|
||||
else
|
||||
{
|
||||
newState = BCValue::State::Failed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
emit valueUpdated( value.deviceID, value.indexRow, newState, newVisibleValue );
|
||||
|
||||
// __fix
|
||||
bc::processEventsFor(50);
|
||||
//bc::processEventsFor(150);
|
||||
bc::delay_millis(50);
|
||||
|
||||
|
||||
//emit valueStateChanged(cmd.id, true);
|
||||
//emit valueStateChanged(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
void BCTransmitter::onProcessValue()
|
||||
{}
|
||||
|
||||
/**
|
||||
* @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
|
||||
TransmitResult BCTransmitter::readByteValue( uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
//qDebug() << " --- YES: Read ByteValue: " << registerID;
|
||||
// Wir lesen nur ein Byte und gut.
|
||||
return _canDriver->readRawByte( deviceID, 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
|
||||
TransmitResult BCTransmitter::readWordValue( uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <atomic>
|
||||
|
||||
#include <bcvalue.h>
|
||||
#include <bcvaluetype.h>
|
||||
#include <bcdrivertinycan.h>
|
||||
|
||||
/**
|
||||
@@ -53,7 +52,7 @@
|
||||
* implementiert sein und liest/schreibt Byteweise auf den Bus.
|
||||
*/
|
||||
|
||||
class BCTransmitter : public QObject, public BCAbstractTransmitter
|
||||
class BCTransmitter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -61,14 +60,12 @@ public:
|
||||
|
||||
explicit BCTransmitter(QObject *parent = nullptr);
|
||||
|
||||
TransmitResult readByte( uint32_t deviceID, uint8_t registerID ) const override;
|
||||
TransmitResult writeByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const override;
|
||||
|
||||
public slots:
|
||||
|
||||
void onToggleConnectionState( bool connect );
|
||||
void enqueueValue(BCValuePtrConst value );
|
||||
void processValue();
|
||||
void onToggleDriverConnection( bool connect );
|
||||
void onUpdateValue(BCValuePtrConst valuePtr );
|
||||
void onProcessValue();
|
||||
void onStartNativeDriver();
|
||||
|
||||
signals:
|
||||
|
||||
@@ -77,17 +74,22 @@ signals:
|
||||
|
||||
private:
|
||||
|
||||
void readRawValueX ( const BCValue& value ) const;
|
||||
void writeRawValueX( const BCValue& value ) const;
|
||||
void connectCanDriver();
|
||||
void disconnectCanDriver();
|
||||
|
||||
using BCDataQueue = QQueue<BCValuePtrConst>;
|
||||
TransmitResult readByteValue( uint32_t deviceID, uint8_t registerID );
|
||||
TransmitResult readWordValue( uint32_t deviceID, uint8_t registerID );
|
||||
|
||||
BCDataQueue _valueQueue;
|
||||
QMutex _mutex;
|
||||
std::atomic<bool> _isBusy{ false };
|
||||
//using BCDataQueue = QQueue<BCValuePtrConst>;
|
||||
|
||||
// __fix! set two
|
||||
//BCDataQueue _valueQueue;
|
||||
//QMutex _mutex;
|
||||
//std::atomic<bool> _isBusy{ false };
|
||||
|
||||
// __fix!
|
||||
BCDriver* _canDriver{};
|
||||
BCDriverTinyCan _tinyCanDriver{};
|
||||
BCDriverDummy _dummyDriver{};
|
||||
|
||||
};
|
||||
|
||||
|
||||
26
bcvalue.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -33,16 +33,34 @@
|
||||
#include <QMetaEnum>
|
||||
|
||||
#include <bcvalue.h>
|
||||
#include <bcvaluetype.h>
|
||||
|
||||
|
||||
///-------------------------------
|
||||
|
||||
|
||||
BCValue::BCValue(const BCValueType* valueType_, BCDevice::ID deviceID_, BC::ID registerID_)
|
||||
: valueType{valueType_}, deviceID{deviceID_}, registerID{registerID_}
|
||||
BCValue::BCValue( BCDevice::ID deviceID_, BC::ID registerID_)
|
||||
: deviceID{deviceID_}, registerID{registerID_}
|
||||
{
|
||||
visibleValue = "--";
|
||||
}
|
||||
|
||||
QString BCValue::formatValues( uint32_t value ) const
|
||||
{
|
||||
if( factor == 1 )
|
||||
return QString::number( value );
|
||||
|
||||
double result = value * factor;
|
||||
return QString::number(result, 'f', 2);
|
||||
}
|
||||
|
||||
void BCValue::dumpValue() const
|
||||
{
|
||||
|
||||
qDebug() << "DeviceID: " << deviceID << " Register: " << registerID << " state:" " << state << " << " label: " << label;
|
||||
qDebug() << "visibleValue: " << visibleValue << " min: " << min << " max: " << max << " factor: " << factor << " ValueType: " << (char)valueType << " ";
|
||||
qDebug() << "indexRow: " << indexRow << " isWord: " << isWord;
|
||||
qDebug();
|
||||
|
||||
}
|
||||
|
||||
/// ----
|
||||
|
||||
100
bcvalue.h
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
|
||||
#include <expected>
|
||||
#include <bc.h>
|
||||
|
||||
|
||||
@@ -55,16 +56,28 @@
|
||||
-
|
||||
*/
|
||||
|
||||
using OptDouble = std::optional<double>;
|
||||
|
||||
|
||||
|
||||
struct BCValueType;
|
||||
// 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 )>;
|
||||
|
||||
class BCValue
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Aus dem Type ergibt sich
|
||||
// später der Editor
|
||||
enum class ValueType : uint8_t
|
||||
{
|
||||
Plain,
|
||||
Bool,
|
||||
Number,
|
||||
Float
|
||||
};
|
||||
|
||||
enum class State : uint8_t
|
||||
{
|
||||
NoState = 0x00,
|
||||
@@ -78,16 +91,24 @@ public:
|
||||
};
|
||||
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};
|
||||
const BCValueType* valueType{};
|
||||
QString formatValues( uint32_t value ) const;
|
||||
void dumpValue() const;
|
||||
|
||||
mutable States state{BCValue::State::ReadOnly};
|
||||
BCDevice::ID deviceID{BCDevice::ID::Invalid};
|
||||
BC::ID registerID{BC::ID::Invalid};
|
||||
ValueType valueType{ValueType::Plain};
|
||||
int indexRow{-1};
|
||||
QString label;
|
||||
mutable QString visibleValue;
|
||||
|
||||
mutable double rawValue;
|
||||
bool isWord{false};
|
||||
QString unitLabel;
|
||||
double factor{1};
|
||||
OptDouble min;
|
||||
OptDouble max;
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BCValue::States)
|
||||
|
||||
@@ -103,72 +124,9 @@ using BCValueList = QList<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)
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
#include <bcvaluemodel.h>
|
||||
#include <bcvaluetype.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Konstruktor, ohne Besonderheiten
|
||||
@@ -83,16 +83,25 @@ void BCValueModel::takeValueList(BCValueList& newValueList)
|
||||
|
||||
void BCValueModel::onValueUpdated( int row, BCValue::State state, const QString& newVisisbleValue )
|
||||
{
|
||||
qDebug() << " BCValueModel::onValueUpdated update: " << newVisisbleValue;
|
||||
if( row > -1 && row < _valueList.size() )
|
||||
{
|
||||
BCValuePtr value = _valueList[row];
|
||||
const BCValue& value = *(_valueList[row].get());
|
||||
QModelIndex idx = index(row,1);
|
||||
value->state = state;
|
||||
if( !newVisisbleValue.isEmpty() && newVisisbleValue != value->visibleValue )
|
||||
|
||||
//qDebug();
|
||||
//qDebug() << " --- OLD:"<< newVisisbleValue;
|
||||
//value.dumpValue();
|
||||
|
||||
value.state = state;
|
||||
|
||||
if( !newVisisbleValue.isEmpty() && newVisisbleValue != value.visibleValue )
|
||||
{
|
||||
value->visibleValue = newVisisbleValue;
|
||||
value.visibleValue = newVisisbleValue;
|
||||
}
|
||||
|
||||
//qDebug() << " --- NEW: " << newVisisbleValue;
|
||||
//value.dumpValue();
|
||||
|
||||
// wir schicken auf jeden fall einen update request
|
||||
emit dataChanged(idx, idx, {Qt::DisplayRole, Qt::EditRole});
|
||||
}
|
||||
@@ -123,7 +132,7 @@ int BCValueModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,17 +153,17 @@ QVariant BCValueModel::data(const QModelIndex& index, int role) const
|
||||
if (wrongRole || !index.isValid() || row >= _valueList.size() )
|
||||
return QVariant();
|
||||
|
||||
BCValuePtr value = _valueList.at( row );
|
||||
const BCValue& value = *(_valueList.at( row ).get());
|
||||
|
||||
if( col == 0 )
|
||||
return value->label;
|
||||
return value.label;
|
||||
|
||||
if( col == 1)
|
||||
{
|
||||
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();
|
||||
@@ -182,7 +191,8 @@ Das Model Gibt hier, unabhängig von der DataRole, immer das
|
||||
|
||||
Qt::ItemFlags BCValueModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
// die label spalte lässt sich nicht editieren
|
||||
if (!index.isValid() || index.column() == 0 )
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
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
@@ -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
|
||||
151
bcxmlloader.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -32,28 +32,20 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QTableView>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include <QStatusBar>
|
||||
#include <QApplication>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMetaEnum>
|
||||
#include <QHash>
|
||||
|
||||
#include <bcxmlloader.h>
|
||||
#include <bcvaluetype.h>
|
||||
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
|
||||
|
||||
BCXmlLoader::BCXmlLoader(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
//qRegisterMetaType<BCValue*>("BCValue*");
|
||||
//qRegisterMetaType<BCValue*>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -67,11 +59,7 @@ void BCXmlLoader::loadXmlBikeData( const QString& fileName )
|
||||
}
|
||||
qDebug().noquote() << parts.join(" ");
|
||||
};
|
||||
/*
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "XML öffnen", "", "XML Files (*.xml)");
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
*/
|
||||
|
||||
|
||||
QMetaEnum bcDeviceEnum{QMetaEnum::fromType<BCDevice::ID>()};
|
||||
|
||||
@@ -100,7 +88,7 @@ void BCXmlLoader::loadXmlBikeData( const QString& fileName )
|
||||
if (token == QXmlStreamReader::StartElement)
|
||||
{
|
||||
QString deviceType = _xml.attributes().value("Type"_L1).toString();
|
||||
printAttrs (_xml);
|
||||
//printAttrs (_xml);
|
||||
// Wir wollen die Device-ID aus dem XML Tag ermitteln
|
||||
const char* deviceKey = _xml.attributes().value("Type"_L1).toLatin1().constData();
|
||||
bool ok;
|
||||
@@ -117,22 +105,13 @@ void BCXmlLoader::loadXmlBikeData( const QString& fileName )
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (xml.hasError())
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Parsing Fehler", xml.errorString());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->setDevices(parsedValues);
|
||||
}
|
||||
/**
|
||||
* @brief Lädt deie Daten des BionX eBikes
|
||||
* @param deviceID
|
||||
*/
|
||||
|
||||
// create & add new model to the model map
|
||||
|
||||
}
|
||||
|
||||
void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
{
|
||||
auto printAttrs = [](const QXmlStreamReader& xml)
|
||||
@@ -146,7 +125,7 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
|
||||
printAttrs (_xml);
|
||||
Q_ASSERT(_xml.isStartElement() && _xml.name() == "Device"_L1);
|
||||
qDebug() << " XXX ---------------";
|
||||
|
||||
|
||||
// temporäre Wertliste für neues Device
|
||||
BCValueList currentValues;
|
||||
@@ -156,17 +135,22 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
if( _xml.attributes().hasAttribute(BCTags::ID) )
|
||||
{
|
||||
//qDebug() << " --- found: " << _xml.name() << " : " << _xml.attributes().value(BCTags::ID);
|
||||
QString id = _xml.attributes().value(BCTags::ID).toString();
|
||||
|
||||
// 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(),
|
||||
.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
|
||||
std::optional<BCValuePtr> newValue = makeDataValue( deviceID, params );
|
||||
std::optional<BCValuePtr> newValue = makeValue( deviceID, params );
|
||||
if(newValue)
|
||||
{
|
||||
// wir merken uns gleich den index in der Werteliste
|
||||
@@ -185,11 +169,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 )
|
||||
{
|
||||
|
||||
/*
|
||||
auto setIfExists = [&]( QStringView source, optDouble& target )
|
||||
static QHash<QString,BCValue::ValueType> s_valueTypes
|
||||
{
|
||||
{ "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() )
|
||||
{
|
||||
@@ -199,9 +190,6 @@ std::optional<BCValuePtr> BCXmlLoader::makeDataValue( BCDevice::ID deviceID, con
|
||||
target = testVal;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
static QMetaEnum s_bcValueEnum{QMetaEnum::fromType<BC::ID>()};
|
||||
|
||||
|
||||
/*
|
||||
@@ -214,70 +202,47 @@ std::optional<BCValuePtr> BCXmlLoader::makeDataValue( BCDevice::ID deviceID, con
|
||||
// geht nicht auf qt6.8 von debian trixie
|
||||
//std::optional<quint64> IDVal = s_bcValueEnum.keyToValue64( params.ID.toLatin1().constData() );
|
||||
bool ok;
|
||||
static QMetaEnum s_bcValueEnum{QMetaEnum::fromType<BC::ID>()};
|
||||
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( ok )
|
||||
{
|
||||
auto valueType = BCValueType::fetchValueType(params.UnitType);
|
||||
if( valueType.has_value() )
|
||||
{
|
||||
BCValuePtr newValue = std::make_shared<BCValue>( *valueType, deviceID, static_cast<BC::ID>(IDVal) );
|
||||
BCValuePtr newValuePtr = std::make_shared<BCValue>( deviceID, static_cast<BC::ID>(IDVal) );
|
||||
BCValue& newValue = *newValuePtr.get();
|
||||
|
||||
/*
|
||||
setIfExists( params.Factor, newValue.factor );
|
||||
setIfExists( params.Min, newValue.min );
|
||||
setIfExists( params.Max, newValue.max );
|
||||
*/
|
||||
newValue->label = params.Label;
|
||||
qDebug() << " --- created: " << params.Label;
|
||||
setIfExists( params.IsWord, newValue.isWord );
|
||||
|
||||
return std::optional<BCValuePtr>( newValue );
|
||||
}
|
||||
newValue.label = params.Label;
|
||||
newValue.unitLabel = 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;
|
||||
*/
|
||||
|
||||
qDebug() << " --- created: " << params.Label;
|
||||
newValue.dumpValue();
|
||||
|
||||
return std::optional<BCValuePtr>( newValuePtr );
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -33,15 +33,9 @@
|
||||
#ifndef BCXMLLOADER_H
|
||||
#define BCXMLLOADER_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QMetaEnum>
|
||||
|
||||
#include <QThread>
|
||||
#include <bcvaluemodel.h>
|
||||
|
||||
#include <bctransmitter.h>
|
||||
#include <bcvalue.h>
|
||||
|
||||
|
||||
class BCXmlLoader : public QObject
|
||||
@@ -55,8 +49,7 @@ public:
|
||||
|
||||
public slots:
|
||||
|
||||
void loadXmlBikeData( const QString& fileName );
|
||||
void saveBikeData();
|
||||
void loadXmlBikeData( const QString& fileName );;
|
||||
|
||||
signals:
|
||||
|
||||
@@ -64,16 +57,21 @@ signals:
|
||||
|
||||
protected:
|
||||
|
||||
struct BCDataParams
|
||||
struct BCValueParams
|
||||
{
|
||||
QString ID;
|
||||
QString Label;
|
||||
QString UnitType;
|
||||
QString UnitLabel;
|
||||
QString Factor;
|
||||
QString Min;
|
||||
QString Max;
|
||||
QString IsWord;
|
||||
QString ValueType;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
<file alias="bionx_akku.png">resources/bionx_akku.png</file>
|
||||
<file alias="bionx_console.png">resources/bionx_console.png</file>
|
||||
<file alias="bionx_motor.png">resources/bionx_motor.png</file>
|
||||
<file alias="exit.png">resources/exit.png</file>
|
||||
<file alias="important.png">resources/important.png</file>
|
||||
<file alias="restart.png">resources/restart.png</file>
|
||||
<file alias="splash.png">resources/splash.png</file>
|
||||
<file alias="connect.png">resources/connect.png</file>
|
||||
<file alias="connected.png">resources/connected.png</file>
|
||||
<file alias="disconnected.png">resources/disconnected.png</file>
|
||||
<file alias="connect.svg">resources/connect.svg</file>
|
||||
<file alias="exit.svg">resources/exit.svg</file>
|
||||
<file alias="exit_red.svg">resources/exit_red.svg</file>
|
||||
<file alias="sync_green.svg">resources/sync_green.svg</file>
|
||||
<file alias="sync_yellow.svg">resources/sync_yellow.svg</file>
|
||||
<file alias="connect_white.svg">resources/connect_white.svg</file>
|
||||
<file alias="sync.svg">resources/sync.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
#ifndef __CAN_DRV_H__
|
||||
#define __CAN_DRV_H__
|
||||
|
||||
#include "can_drv_config.h"
|
||||
#include "can_types.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
// ****** Windows
|
||||
#include <windows.h>
|
||||
#define DRV_CALLBACK_TYPE __stdcall
|
||||
#else
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#define DRV_CALLBACK_TYPE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* Define Makros */
|
||||
/***************************************************************/
|
||||
|
||||
// CAN <20>bertragungsgeschwindigkeit
|
||||
#define CAN_10K_BIT 10 // 10 kBit/s
|
||||
#define CAN_20K_BIT 20 // 20 kBit/s
|
||||
#define CAN_50K_BIT 50 // 50 kBit/s
|
||||
#define CAN_100K_BIT 100 // 100 kBit/s
|
||||
#define CAN_125K_BIT 125 // 125 kBit/s
|
||||
#define CAN_250K_BIT 250 // 250 kBit/s
|
||||
#define CAN_500K_BIT 500 // 500 kBit/s
|
||||
#define CAN_800K_BIT 800 // 800 kBit/s
|
||||
#define CAN_1M_BIT 1000 // 1 MBit/s
|
||||
#define CAN_1M5_BIT 1500 // 1,5 MBit/s
|
||||
#define CAN_2M_BIT 2000 // 2 MBit/s
|
||||
#define CAN_3M_BIT 3000 // 3 MBit/s
|
||||
#define CAN_4M_BIT 4000 // 4 MBit/s
|
||||
|
||||
// Time Stamp Mode
|
||||
#define TIME_STAMP_OFF 0 // keine Time-Stamps
|
||||
#define TIME_STAMP_SOFT 1 // Software Time-Stamps
|
||||
#define TIME_STAMP_HW_UNIX 2 // Hardware Time-Stamps, UNIX-Format
|
||||
#define TIME_STAMP_HW 3 // Hardware Time-Stamps
|
||||
#define TIME_STAMP_HW_SW_UNIX 4 // Hardware Time-Stamps verwenden wenn verf<72>gbar,
|
||||
// ansonsten Software Time-Stamps
|
||||
// Ab Treiber Version 4.08!
|
||||
|
||||
// CAN Bus Mode
|
||||
#define OP_CAN_NO_CHANGE 0 // Aktuellen Zustand nicht <20>ndern
|
||||
#define OP_CAN_START 1 // Startet den CAN-Bus
|
||||
#define OP_CAN_STOP 2 // Stopt den CAN-Bus
|
||||
#define OP_CAN_RESET 3 // Reset CAN Controller (BusOff l<>schen)
|
||||
#define OP_CAN_START_LOM 4 // Startet den CAN-Bus im Silent Mode (Listen Only Mode)
|
||||
#define OP_CAN_START_NO_RETRANS 5 // Startet den CAN-Bus im Automatic Retransmission disable Mode
|
||||
#define OP_CAN_ECU_FLASH_MODE 6 // Start im ECU Flash Mode
|
||||
|
||||
#define CAN_CMD_NONE 0x0000
|
||||
#define CAN_CMD_RXD_OVERRUN_CLEAR 0x0001
|
||||
#define CAN_CMD_RXD_FIFOS_CLEAR 0x0002
|
||||
#define CAN_CMD_TXD_OVERRUN_CLEAR 0x0004
|
||||
#define CAN_CMD_TXD_FIFOS_CLEAR 0x0008
|
||||
#define CAN_CMD_HW_FILTER_CLEAR 0x0010
|
||||
#define CAN_CMD_SW_FILTER_CLEAR 0x0020
|
||||
#define CAN_CMD_TXD_PUFFERS_CLEAR 0x0040
|
||||
// <*> neu
|
||||
#define CAN_CMD_START_DATA_TRANSFER 0x1000
|
||||
#define CAN_CMD_CANCEL_DATA_TRANSFER 0x2000
|
||||
#define CAN_CMD_START_TEST 0xE000
|
||||
#define CAN_CMD_STOP_TEST 0xF000
|
||||
|
||||
#define CAN_CMD_FIFOS_CLEAR 0x000F
|
||||
#define CAN_CMD_ALL_CLEAR 0x0FFF
|
||||
|
||||
|
||||
// DrvStatus
|
||||
#define DRV_NOT_LOAD 0 // Die Treiber DLL wurde noch nicht geladen
|
||||
#define DRV_STATUS_NOT_INIT 1 // Treiber noch nicht Initialisiert (Funktion "CanInitDrv" noch nicht aufgerufen)
|
||||
#define DRV_STATUS_INIT 2 // Treiber erfolgrich Initialisiert
|
||||
#define DRV_STATUS_PORT_NOT_OPEN 3 // Die Schnittstelle wurde nicht ge<67>ffnet
|
||||
#define DRV_STATUS_PORT_OPEN 4 // Die Schnittstelle wurde ge<67>ffnet
|
||||
#define DRV_STATUS_DEVICE_FOUND 5 // Verbindung zur Hardware wurde Hergestellt
|
||||
#define DRV_STATUS_CAN_OPEN 6 // Device wurde ge<67>ffnet und erfolgreich Initialisiert
|
||||
#define DRV_STATUS_CAN_RUN_TX 7 // CAN Bus RUN nur Transmitter (wird nicht verwendet !)
|
||||
#define DRV_STATUS_CAN_RUN 8 // CAN Bus RUN
|
||||
|
||||
// CanStatus
|
||||
#define CAN_STATUS_OK 0 // CAN-Controller: Ok
|
||||
#define CAN_STATUS_ERROR 1 // CAN-Controller: CAN Error
|
||||
#define CAN_STATUS_WARNING 2 // CAN-Controller: Error warning
|
||||
#define CAN_STATUS_PASSIV 3 // CAN-Controller: Error passiv
|
||||
#define CAN_STATUS_BUS_OFF 4 // CAN-Controller: Bus Off
|
||||
#define CAN_STATUS_UNBEKANNT 5 // CAN-Controller: Status Unbekannt
|
||||
|
||||
// Neu f<>r Low-Speed CAN, TJA1055 Fehler
|
||||
#define BUS_FAILURE 0x10
|
||||
|
||||
// Fifo Status
|
||||
#define FIFO_OK 0 // Fifo-Status: Ok
|
||||
#define FIFO_HW_OVERRUN 1 // Fifo-Status: Hardware Fifo <20>berlauf
|
||||
#define FIFO_SW_OVERRUN 2 // Fifo-Status: Software Fifo <20>berlauf
|
||||
#define FIFO_HW_SW_OVERRUN 3 // Fifo-Status: Hardware & Software Fifo <20>berlauf
|
||||
#define FIFO_STATUS_UNBEKANNT 4 // Fifo-Status: Unbekannt
|
||||
|
||||
// Makros f<>r SetEvent
|
||||
#define EVENT_ENABLE_PNP_CHANGE 0x0001
|
||||
#define EVENT_ENABLE_STATUS_CHANGE 0x0002
|
||||
#define EVENT_ENABLE_RX_FILTER_MESSAGES 0x0004
|
||||
#define EVENT_ENABLE_RX_MESSAGES 0x0008
|
||||
#define EVENT_ENABLE_ALL 0x00FF
|
||||
|
||||
#define EVENT_DISABLE_PNP_CHANGE 0x0100
|
||||
#define EVENT_DISABLE_STATUS_CHANGE 0x0200
|
||||
#define EVENT_DISABLE_RX_FILTER_MESSAGES 0x0400
|
||||
#define EVENT_DISABLE_RX_MESSAGES 0x0800
|
||||
#define EVENT_DISABLE_ALL 0xFF00
|
||||
|
||||
// <*> Neu
|
||||
#define TCAN_LOG_FLAG_MESSAGE 0x00000001
|
||||
#define TCAN_LOG_FLAG_STATUS 0x00000002
|
||||
#define TCAN_LOG_FLAG_RX_MSG 0x00000004
|
||||
#define TCAN_LOG_FLAG_TX_MSG 0x00000008
|
||||
#define TCAN_LOG_FLAG_API_CALL 0x00000010
|
||||
#define TCAN_LOG_API_CALL_RX 0x00000020
|
||||
#define TCAN_LOG_API_CALL_TX 0x00000040
|
||||
#define TCAN_LOG_API_CALL_STATUS 0x00000080
|
||||
#define TCAN_LOG_FLAG_ERROR 0x00000100
|
||||
#define TCAN_LOG_FLAG_WARN 0x00000200
|
||||
#define TCAN_LOG_FLAG_ERR_MSG 0x00000400
|
||||
#define TCAN_LOG_FLAG_OV_MSG 0x00000800
|
||||
#define TCAN_LOG_USB 0x00008000 // <*> neu
|
||||
#define TCAN_LOG_FLAG_DEBUG 0x08000000
|
||||
#define TCAN_LOG_FLAG_WITH_TIME 0x40000000
|
||||
#define TCAN_LOG_FLAG_DISABLE_SYNC 0x80000000
|
||||
|
||||
/***************************************************************/
|
||||
/* Typen */
|
||||
/***************************************************************/
|
||||
|
||||
/******************************************/
|
||||
/* Device Status */
|
||||
/******************************************/
|
||||
#pragma pack(push, 1)
|
||||
struct TDeviceStatus
|
||||
{
|
||||
int32_t DrvStatus; // Treiber Status (Device close / Device open / CAN Bus RUN)
|
||||
unsigned char CanStatus; // Status des CAN Controllers (Ok / ... / Error passiv / Bus off)
|
||||
unsigned char FifoStatus; // Fifo Status (Ok / ... / Hard. u. Soft. FIFO <20>berlauf)
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#ifdef CAN_API_TRUE_FUNC
|
||||
|
||||
int32_t CanInitDriver(char *options);
|
||||
void CanDownDriver(void);
|
||||
int32_t CanSetOptions(char *options);
|
||||
int32_t CanDeviceOpen(uint32_t index, char *parameter);
|
||||
int32_t CanDeviceClose(uint32_t index);
|
||||
|
||||
int32_t CanSetMode(uint32_t index, unsigned char can_op_mode, uint16_t can_command);
|
||||
|
||||
int32_t CanTransmit(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
void CanTransmitClear(uint32_t index);
|
||||
uint32_t CanTransmitGetCount(uint32_t index);
|
||||
int32_t CanTransmitSet(uint32_t index, uint16_t cmd, uint32_t time);
|
||||
int32_t CanReceive(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
void CanReceiveClear(uint32_t index);
|
||||
uint32_t CanReceiveGetCount(uint32_t index);
|
||||
|
||||
int32_t CanSetSpeed(uint32_t index, uint16_t speed);
|
||||
int32_t CanSetSpeedUser(uint32_t index, uint32_t value);
|
||||
char *CanDrvInfo(void);
|
||||
char *CanDrvHwInfo(uint32_t index);
|
||||
int32_t CanSetFilter(uint32_t index, struct TMsgFilter *msg_filter);
|
||||
int32_t CanGetDeviceStatus(uint32_t index, struct TDeviceStatus *status);
|
||||
void CanSetPnPEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, int32_t status));
|
||||
void CanSetStatusEventCallback(void (DRV_CALLBACK_TYPE *event)
|
||||
(uint32_t index, struct TDeviceStatus *device_status));
|
||||
void CanSetRxEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index,
|
||||
struct TCanMsg *msg, int32_t count));
|
||||
|
||||
void CanSetEvents(uint16_t events);
|
||||
uint32_t CanEventStatus(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !(defined(CAN_API_TRUE_FUNC)) || defined(CAN_DRV_INCLUDE)
|
||||
/***************************************************************/
|
||||
/* Funktionstypen */
|
||||
/***************************************************************/
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanInitDriver)(char *options);
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanDownDriver)(void);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanSetOptions)(char *options);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanDeviceOpen)(uint32_t index, char *parameter);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanDeviceClose)(uint32_t index);
|
||||
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanSetMode)(uint32_t index, unsigned char can_op_mode,
|
||||
uint16_t can_command);
|
||||
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanTransmit)(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanTransmitClear)(uint32_t index);
|
||||
typedef uint32_t (DRV_CALLBACK_TYPE *TCanTransmitGetCount)(uint32_t index);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanTransmitSet)(uint32_t index, uint16_t cmd, uint32_t time);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanReceive)(uint32_t index, struct TCanMsg *msg, int32_t count);
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanReceiveClear)(uint32_t index);
|
||||
typedef uint32_t (DRV_CALLBACK_TYPE *TCanReceiveGetCount)(uint32_t index);
|
||||
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanSetSpeed)(uint32_t index, uint16_t speed);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanSetSpeedUser)(uint32_t index, uint32_t value);
|
||||
typedef char * (DRV_CALLBACK_TYPE *TCanDrvInfo)(void);
|
||||
typedef char * (DRV_CALLBACK_TYPE *TCanDrvHwInfo)(uint32_t index);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanSetFilter)(uint32_t index, struct TMsgFilter *msg_filter);
|
||||
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanGetDeviceStatus)(uint32_t index, struct TDeviceStatus *status);
|
||||
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanSetPnPEventCallback)(void (DRV_CALLBACK_TYPE *event)
|
||||
(uint32_t index, int32_t status));
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanSetStatusEventCallback)(void (DRV_CALLBACK_TYPE *event)
|
||||
(uint32_t index, struct TDeviceStatus *device_status));
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanSetRxEventCallback)(void (DRV_CALLBACK_TYPE *event)
|
||||
(uint32_t index, struct TCanMsg *msg, int32_t count));
|
||||
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanSetEvents)(uint16_t events);
|
||||
typedef uint32_t (DRV_CALLBACK_TYPE *TCanEventStatus)(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef CAN_API_TRUE_FUNC
|
||||
/***************************************************************/
|
||||
/* Tiny-CAN API Funktionen */
|
||||
/***************************************************************/
|
||||
|
||||
extern TCanInitDriver CanInitDriver;
|
||||
extern TCanDownDriver CanDownDriver;
|
||||
extern TCanSetOptions CanSetOptions;
|
||||
extern TCanDeviceOpen CanDeviceOpen;
|
||||
extern TCanDeviceClose CanDeviceClose;
|
||||
|
||||
extern TCanSetMode CanSetMode;
|
||||
|
||||
extern TCanTransmit CanTransmit;
|
||||
extern TCanTransmitClear CanTransmitClear;
|
||||
extern TCanTransmitGetCount CanTransmitGetCount;
|
||||
extern TCanTransmitSet CanTransmitSet;
|
||||
extern TCanReceive CanReceive;
|
||||
extern TCanReceiveClear CanReceiveClear;
|
||||
extern TCanReceiveGetCount CanReceiveGetCount;
|
||||
|
||||
extern TCanSetSpeed CanSetSpeed;
|
||||
extern TCanSetSpeedUser CanSetSpeedUser;
|
||||
|
||||
extern TCanDrvInfo CanDrvInfo;
|
||||
extern TCanDrvHwInfo CanDrvHwInfo;
|
||||
extern TCanSetFilter CanSetFilter;
|
||||
|
||||
extern TCanGetDeviceStatus CanGetDeviceStatus;
|
||||
|
||||
extern TCanSetPnPEventCallback CanSetPnPEventCallback;
|
||||
extern TCanSetStatusEventCallback CanSetStatusEventCallback;
|
||||
extern TCanSetRxEventCallback CanSetRxEventCallback;
|
||||
|
||||
extern TCanSetEvents CanSetEvents;
|
||||
extern TCanEventStatus CanEventStatus;
|
||||
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* Funktionen Treiber laden/entladen */
|
||||
/***************************************************************/
|
||||
int32_t LoadDriver(const char *file_name);
|
||||
void UnloadDriver(void);
|
||||
|
||||
#include "can_drv_ex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef __CAN_DRV_CONFIG_H__
|
||||
#define __CAN_DRV_CONFIG_H__
|
||||
|
||||
#ifndef STRICT_CAN_FD_SUPPORT
|
||||
//#define STRICT_CAN_FD_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifndef CAN_API_TRUE_FUNC
|
||||
#define CAN_API_TRUE_FUNC
|
||||
#endif
|
||||
|
||||
#ifndef DRV_REF_LOCKING
|
||||
#define DRV_REF_LOCKING
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,420 +0,0 @@
|
||||
#ifndef __CAN_DRV_EX_H__
|
||||
#define __CAN_DRV_EX_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ERR_NO_CAN_DRIVER_LOAD -1000000
|
||||
|
||||
|
||||
#define DEV_LIST_SHOW_TCAN_ONLY 0x01
|
||||
#define DEV_LIST_SHOW_UNCONNECT 0x02
|
||||
|
||||
/***************************************************************/
|
||||
/* Define Makros */
|
||||
/***************************************************************/
|
||||
#define CAN_FEATURE_LOM 0x0001 // Silent Mode (LOM = Listen only Mode)
|
||||
#define CAN_FEATURE_ARD 0x0002 // Automatic Retransmission disable
|
||||
#define CAN_FEATURE_TX_ACK 0x0004 // TX ACK (Gesendete Nachrichten best<73>tigen)
|
||||
#define CAN_FEATURE_ERROR_MSGS 0x0008 // Error Messages Support
|
||||
#define CAN_FEATURE_FD_HARDWARE 0x0010 // CAN-FD Hardware
|
||||
#define CAN_FEATURE_FIFO_OV_MODE 0x0020 // FIFO OV Mode (Auto Clear, OV CAN Messages)
|
||||
#define CAN_FEATURE_ECU_FLASH 0x0040 // Hardware beschleunigung f<>r ISO-TP ECU-Flash programmierung
|
||||
#define CAN_FEATURE_CAN_TEST 0x4000 // Tiny-CAN Tester Firmware
|
||||
#define CAN_FEATURE_HW_TIMESTAMP 0x8000 // Hardware Time Stamp
|
||||
|
||||
// (V)alue (T)ype
|
||||
#define VT_BYTE 0x01
|
||||
#define VT_UBYTE 0x02
|
||||
#define VT_WORD 0x03
|
||||
#define VT_UWORD 0x04
|
||||
#define VT_LONG 0x05
|
||||
#define VT_ULONG 0x06
|
||||
|
||||
#define VT_BYTE_ARRAY 0x07
|
||||
#define VT_UBYTE_ARRAY 0x08
|
||||
#define VT_WORD_ARRAY 0x09
|
||||
#define VT_UWORD_ARRAY 0x0A
|
||||
#define VT_LONG_ARRAY 0x0B
|
||||
#define VT_ULONG_ARRAY 0x0C
|
||||
|
||||
#define VT_BYTE_RANGE_ARRAY 0x0D
|
||||
#define VT_UBYTE_RANGE_ARRAY 0x0E
|
||||
#define VT_WORD_RANGE_ARRAY 0x0F
|
||||
#define VT_UWORD_RANGE_ARRAY 0x10
|
||||
#define VT_LONG_RANGE_ARRAY 0x11
|
||||
#define VT_ULONG_RANGE_ARRAY 0x12
|
||||
|
||||
#define VT_HBYTE 0x40
|
||||
#define VT_HWORD 0x41
|
||||
#define VT_HLONG 0x42
|
||||
|
||||
#define VT_STREAM 0x80
|
||||
#define VT_STRING 0x81
|
||||
#define VT_POINTER 0x82
|
||||
#define VT_REVISION 0x83
|
||||
#define VT_DATE 0x84
|
||||
|
||||
// MHS (EV)ent (S)ource
|
||||
#define MHS_EVS_STATUS 1
|
||||
#define MHS_EVS_PNP 2
|
||||
#define MHS_EVS_OBJECT 3
|
||||
|
||||
#define MHS_EVS_DIN 4
|
||||
#define MHS_EVS_ENC 5
|
||||
#define MHS_EVS_KEY 6
|
||||
|
||||
|
||||
#define MHS_TERMINATE 0x80000000
|
||||
|
||||
|
||||
// <*> neu
|
||||
#define CAN_DATA_ST_IDLE 0
|
||||
#define CAN_DATA_ST_RUN 1
|
||||
#define CAN_DATA_ST_FINISH 2
|
||||
#define CAN_DATA_ST_ERR_ACK_TIMEOUT -1
|
||||
#define CAN_DATA_ST_ERR_NACK -2
|
||||
#define CAN_DATA_ST_ERR_OVERFLOW -3
|
||||
#define CAN_DATA_ST_ERR_ISOTP -4
|
||||
|
||||
// ISO-TP Flags
|
||||
#define CAN_DATA_ISOTP_29BIT_ID 0x01
|
||||
#define CAN_DATA_ISOTP_EXTEND_ADDR 0x02
|
||||
#define CAN_DATA_ISOTP_TX_PADDING 0x04
|
||||
#define CAN_DATA_ISOTP_LISTEN_MODE 0x08
|
||||
|
||||
|
||||
// <*> neu
|
||||
#define TCAN_INFO_KEY_HW_SNR 0x00000000 // Hardware Snr
|
||||
#define TCAN_INFO_KEY_HW_ID_STR 0x00000001 // Hardware ID String
|
||||
#define TCAN_INFO_KEY_HW_BIOS_STR 0x00000002 // Bios ID String
|
||||
#define TCAN_INFO_KEY_HW_REVISION 0x00000003 // Hardware Revision
|
||||
#define TCAN_INFO_KEY_HW_DATE 0x00000004 // Fertigungsdatum
|
||||
#define TCAN_INFO_KEY_HW_VARIANT_STR 0x00000005 // Hardware Variante
|
||||
|
||||
#define TCAN_INFO_KEY_HW_CAN_COUNT 0x00008000 // Anzahl CAN Interfaces
|
||||
#define TCAN_INFO_KEY_HW_CAN_DRV 0x00008010 // Treiber
|
||||
#define TCAN_INFO_KEY_HW_CAN_OPTO 0x00008020 // Opto
|
||||
#define TCAN_INFO_KEY_HW_CAN_TERM 0x00008030 // Term
|
||||
#define TCAN_INFO_KEY_HW_CAN_HS 0x00008040 // HighSpeed
|
||||
#define TCAN_INFO_KEY_HW_I2C_CNT 0x00008100 // Anzahl I2C Interfaces
|
||||
#define TCAN_INFO_KEY_HW_SPI_CNT 0x00008200 // Anzahl SPI Interfaces
|
||||
|
||||
#define TCAN_INFO_KEY_FW_ID 0x00001000 // ID
|
||||
#define TCAN_INFO_KEY_FW_ID_STR 0x00001001 // ID String
|
||||
#define TCAN_INFO_KEY_FW_VERSION 0x00001002 // Version
|
||||
#define TCAN_INFO_KEY_FW_VERSION_STR 0x00001003 // Version String
|
||||
#define TCAN_INFO_KEY_FW_AUTOR 0x00001004 // Autor
|
||||
#define TCAN_INFO_KEY_FW_OPTIOS 0x00001005 // Optionen
|
||||
#define TCAN_INFO_KEY_FW_SNR 0x00001006 // Snr
|
||||
|
||||
#define TCAN_INFO_KEY_FW_CAN_FLAGS 0x00008001 // CAN Features Flags
|
||||
#define TCAN_INFO_KEY_FW_CAN_FLAGS2 0x00008002 // CAN Features Flags2 // <*>
|
||||
#define TCAN_INFO_KEY_FW_CAN_CLOCK1 0x00008003
|
||||
#define TCAN_INFO_KEY_FW_CAN_CLOCK2 0x00008004
|
||||
#define TCAN_INFO_KEY_FW_CAN_CLOCK3 0x00008005
|
||||
#define TCAN_INFO_KEY_FW_CAN_CLOCK4 0x00008006
|
||||
#define TCAN_INFO_KEY_FW_CAN_CLOCK5 0x00008007
|
||||
#define TCAN_INFO_KEY_FW_CAN_CLOCK6 0x00008008
|
||||
#define TCAN_INFO_KEY_FW_PUFFER_CNT 0x00008050 // Anzahl Interval Puffer
|
||||
#define TCAN_INFO_KEY_FW_FILTER_CNT 0x00008060 // Anzahl Filter
|
||||
|
||||
#define TCAN_INFO_KEY_OPEN_INDEX 0x01000001
|
||||
#define TCAN_INFO_KEY_HARDWARE_ID 0x01000002
|
||||
#define TCAN_INFO_KEY_HARDWARE 0x01000003
|
||||
#define TCAN_INFO_KEY_VENDOR 0x01000004
|
||||
|
||||
#define TCAN_INFO_KEY_DEVICE_NAME 0x01000005
|
||||
#define TCAN_INFO_KEY_SERIAL_NUMBER 0x01000006
|
||||
|
||||
#define TCAN_INFO_KEY_CAN_FEATURES 0x01000007
|
||||
#define TCAN_INFO_KEY_CAN_CHANNELS 0x01000008
|
||||
#define TCAN_INFO_KEY_RX_FILTER_CNT 0x01000009
|
||||
#define TCAN_INFO_KEY_TX_BUFFER_CNT 0x0100000A
|
||||
#define TCAN_INFO_KEY_CAN_CLOCKS 0x0100000B
|
||||
#define TCAN_INFO_KEY_CAN_CLOCK1 0x0100000C
|
||||
#define TCAN_INFO_KEY_CAN_CLOCK2 0x0100000D
|
||||
#define TCAN_INFO_KEY_CAN_CLOCK3 0x0100000E
|
||||
#define TCAN_INFO_KEY_CAN_CLOCK4 0x0100000F
|
||||
#define TCAN_INFO_KEY_CAN_CLOCK5 0x01000010
|
||||
#define TCAN_INFO_KEY_CAN_CLOCK6 0x01000011
|
||||
|
||||
|
||||
#define TCAN_INFO_KEY_API_VERSION 0x02000001
|
||||
#define TCAN_INFO_KEY_DLL 0x02000002
|
||||
#define TCAN_INFO_KEY_CFG_APP 0x02000003
|
||||
|
||||
/***************************************************************/
|
||||
/* Typen */
|
||||
/***************************************************************/
|
||||
#pragma pack(push, 1)
|
||||
struct TModulFeatures
|
||||
{
|
||||
uint32_t CanClock; // Clock-Frequenz des CAN-Controllers, muss nicht mit
|
||||
// der Clock-Frequenz des Mikrocontrollers <20>bereinstimmen
|
||||
uint32_t Flags; // Unterst<73>tzte Features des Moduls:
|
||||
// Bit 0 -> Silent Mode (LOM = Listen only Mode)
|
||||
// 1 -> Automatic Retransmission disable
|
||||
// 2 -> TX ACK (Gesendete Nachrichten best<73>tigen)
|
||||
// 15 -> Hardware Time Stamp
|
||||
uint32_t CanChannelsCount; // Anzahl der CAN Schnittstellen, reserviert f<>r
|
||||
// zuk<75>nftige Module mit mehr als einer Schnittstelle
|
||||
uint32_t HwRxFilterCount; // Anzahl der zur Verf<72>gung stehenden Receive-Filter
|
||||
uint32_t HwTxPufferCount; // Anzahl der zur Verf<72>gung stehenden Transmit Puffer mit Timer
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanDevicesList
|
||||
{
|
||||
uint32_t TCanIdx; // Ist das Device ge<67>ffnet ist der Wert auf dem Device-Index
|
||||
// gesetzt, ansonsten ist der Wert auf "INDEX_INVALID" gesetzt.
|
||||
uint32_t HwId; // Ein 32 Bit Schl<68>ssel der die Hardware eindeutig Identifiziert.
|
||||
// Manche Module m<>ssen erst ge<67>ffnet werden damit dieser Wert
|
||||
// gesetzt wird
|
||||
char DeviceName[255]; // Nur Linux: entspricht den Device Namen des USB-Devices,
|
||||
// z.B. /dev/ttyUSB0
|
||||
char SerialNumber[16]; // Seriennummer des Moduls
|
||||
char Description[64]; // Modul Bezeichnung, z.B. "Tiny-CAN IV-XL",
|
||||
// muss in den USB-Controller programmiert sein,
|
||||
// was zur Zeit nur bei den Modulen Tiny-CAN II-XL,
|
||||
// IV-XL u. M1 der Fall ist.
|
||||
struct TModulFeatures ModulFeatures; // Unterst<73>tzte Features des Moduls, nur g<>ltig
|
||||
// wenn HwId > 0
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanDeviceInfo
|
||||
{
|
||||
uint32_t HwId; // Ein 32 Bit Schl<68>ssel der die Hardware eindeutig Identifiziert.
|
||||
uint32_t FirmwareVersion; // Version der Firmware des Tiny-CAN Moduls
|
||||
uint32_t FirmwareInfo; // Informationen zum Stand der Firmware Version
|
||||
// 0 = Unbekannt
|
||||
// 1 = Firmware veraltet, Device kann nicht ge<67>ffnet werden
|
||||
// 2 = Firmware veraltet, Funktionsumfang eingeschr<68>nkt
|
||||
// 3 = Firmware veraltet, keine Einschr<68>nkungen
|
||||
// 4 = Firmware auf Stand
|
||||
// 5 = Firmware neuer als Erwartet
|
||||
char SerialNumber[16]; // Seriennummer des Moduls
|
||||
char Description[64]; // Modul Bezeichnung, z.B. "Tiny-CAN IV-XL"
|
||||
struct TModulFeatures ModulFeatures; // Unterst<73>tzte Features des Moduls
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanInfoVar // <*> ge<67>ndert von TInfoVar in TCanInfoVar
|
||||
{
|
||||
uint32_t Key; // Variablen Schl<68>ssel
|
||||
uint32_t Type; // Variablen Type
|
||||
uint32_t Size; // (Max)Gr<47><72>e der Variable in Byte
|
||||
char Data[255]; // Wert der Variable
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanInfoVarList
|
||||
{
|
||||
uint32_t Size;
|
||||
struct TCanInfoVar *List;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct _TMhsEvent TMhsEvent;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct _TMhsEvent
|
||||
{
|
||||
volatile uint32_t Events;
|
||||
volatile uint32_t EventsMask;
|
||||
volatile int32_t Waiting;
|
||||
#ifdef __WIN32__
|
||||
// ****** Windows
|
||||
uint32_t WinEventCount;
|
||||
HANDLE WinEvent[3];
|
||||
CRITICAL_SECTION EventLock;
|
||||
#else
|
||||
// ****** Linux
|
||||
pthread_cond_t Cond;
|
||||
pthread_mutex_t Mutex;
|
||||
#endif
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/***************************************************************/
|
||||
/* Callback Funktionstypen */
|
||||
/***************************************************************/
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanGetDataBlockCB)(uint8_t *tx_data, uint16_t tx_limit, void *user_data);
|
||||
|
||||
#ifdef CAN_API_TRUE_FUNC
|
||||
|
||||
int32_t CanExGetDeviceCount(int32_t flags);
|
||||
int32_t CanExGetDeviceList(struct TCanDevicesList **devices_list, int32_t flags);
|
||||
int32_t CanExGetDeviceListPerform(int32_t flags);
|
||||
int32_t CanExGetDeviceListGet(struct TCanDevicesList *item);
|
||||
|
||||
int32_t CanExGetDeviceInfo(uint32_t index, struct TCanDeviceInfo *device_info,
|
||||
struct TCanInfoVar **hw_info, uint32_t *hw_info_size);
|
||||
int32_t CanExGetDeviceInfoPerform(uint32_t index, struct TCanDeviceInfo *device_info);
|
||||
int32_t CanExGetDeviceInfoGet(struct TCanInfoVar *item);
|
||||
void CanExDataFree(void **data);
|
||||
int32_t CanExCreateDevice(uint32_t *index, char *options);
|
||||
int32_t CanExDestroyDevice(uint32_t *index);
|
||||
int32_t CanExCreateFifo(uint32_t index, uint32_t size, TMhsEvent *event_obj, uint32_t event, uint32_t channels);
|
||||
int32_t CanExBindFifo(uint32_t fifo_index, uint32_t device_index, uint32_t bind);
|
||||
TMhsEvent *CanExCreateEvent(void);
|
||||
int32_t CanExSetObjEvent(uint32_t index, uint32_t source, TMhsEvent *event_obj, uint32_t event);
|
||||
void CanExSetEvent(TMhsEvent *event_obj, uint32_t event);
|
||||
void CanExSetEventAll(uint32_t event);
|
||||
void CanExResetEvent(TMhsEvent *event_obj, uint32_t event);
|
||||
uint32_t CanExWaitForEvent(TMhsEvent *event_obj, uint32_t timeout);
|
||||
int32_t CanExInitDriver(char *options);
|
||||
int32_t CanExSetOptions(uint32_t index, char *options);
|
||||
int32_t CanExSetAsByte(uint32_t index, const char *name, char value);
|
||||
int32_t CanExSetAsWord(uint32_t index, const char *name, int16_t value);
|
||||
int32_t CanExSetAsLong(uint32_t index, const char *name, int32_t value);
|
||||
int32_t CanExSetAsUByte(uint32_t index, const char *name, unsigned char value);
|
||||
int32_t CanExSetAsUWord(uint32_t index, const char *name, uint16_t value);
|
||||
int32_t CanExSetAsULong(uint32_t index, const char *name, uint32_t value);
|
||||
int32_t CanExSetAsString(uint32_t index, const char *name, char *value);
|
||||
int32_t CanExGetAsByte(uint32_t index, const char *name, char *value);
|
||||
int32_t CanExGetAsWord(uint32_t index, const char *name, int16_t *value);
|
||||
int32_t CanExGetAsLong(uint32_t index, const char *name, int32_t *value);
|
||||
int32_t CanExGetAsUByte(uint32_t index, const char *name, unsigned char *value);
|
||||
int32_t CanExGetAsUWord(uint32_t index, const char *name, uint16_t *value);
|
||||
int32_t CanExGetAsULong(uint32_t index, const char *name, uint32_t *value);
|
||||
int32_t CanExGetAsString(uint32_t index, const char *name, char **str);
|
||||
int32_t CanExGetAsStringCopy(uint32_t index, const char *name, char *dest, uint32_t *dest_size);
|
||||
// **** CAN-FD
|
||||
int32_t CanFdTransmit(uint32_t index, struct TCanFdMsg *fd_msg, int32_t count);
|
||||
int32_t CanFdReceive(uint32_t index, struct TCanFdMsg *fd_msg, int32_t count);
|
||||
// *** <*> neu
|
||||
int32_t CanExSetAsData(uint32_t index, const char *name, void *data, uint32_t size);
|
||||
int32_t CanExSetDataPtr(uint32_t index, const char *name, void *data_ptr, uint32_t size);
|
||||
int32_t CanExSetDataBlockCB(uint32_t index, TCanGetDataBlockCB func, void *user_data);
|
||||
|
||||
int32_t CanExGetInfoList(uint32_t dev_idx, const char *name, struct TCanInfoVarList **devices_info, int32_t flags); // <*> neu
|
||||
int32_t CanExGetInfoListPerform(uint32_t dev_idx, const char *name, int32_t flags);
|
||||
int32_t CanExGetInfoListGet(uint32_t list_idx, struct TCanInfoVar *item);
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined(CAN_API_TRUE_FUNC)) || defined(CAN_DRV_INCLUDE)
|
||||
|
||||
/***************************************************************/
|
||||
/* Funktionstypen */
|
||||
/***************************************************************/
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetDeviceCount)(int32_t flags);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetDeviceList)(struct TCanDevicesList **devices_list, int32_t flags);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetDeviceListPerform)(int32_t flags);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetDeviceListGet)(struct TCanDevicesList *item);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetDeviceInfo)(uint32_t index, struct TCanDeviceInfo *device_info,
|
||||
struct TCanInfoVar **hw_info, uint32_t *hw_info_size);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetDeviceInfoPerform)(uint32_t index, struct TCanDeviceInfo *device_info);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetDeviceInfoGet)(struct TCanInfoVar *item);
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanExDataFree)(void **data);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExCreateDevice)(uint32_t *index, char *options);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExDestroyDevice)(uint32_t *index);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExCreateFifo)(uint32_t index, uint32_t size, TMhsEvent *event_obj,
|
||||
uint32_t event, uint32_t channels);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExBindFifo)(uint32_t fifo_index, uint32_t device_index,
|
||||
uint32_t bind);
|
||||
typedef TMhsEvent * (DRV_CALLBACK_TYPE *TCanExCreateEvent)(void);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetObjEvent)(uint32_t index, uint32_t source, TMhsEvent *event_obj, uint32_t event);
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanExSetEvent)(TMhsEvent *event_obj, uint32_t event);
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanExSetEventAll)(uint32_t event);
|
||||
typedef void (DRV_CALLBACK_TYPE *TCanExResetEvent)(TMhsEvent *event_obj, uint32_t event);
|
||||
typedef uint32_t (DRV_CALLBACK_TYPE *TCanExWaitForEvent)(TMhsEvent *event_obj, uint32_t timeout);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExInitDriver)(char *options);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetOptions)(uint32_t index, const char *options);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsByte)(uint32_t index, const char *name, char value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsWord)(uint32_t index, const char *name, int16_t value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsLong)(uint32_t index, const char *name, int32_t value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsUByte)(uint32_t index, const char *name, unsigned char value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsUWord)(uint32_t index, const char *name, uint16_t value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsULong)(uint32_t index, const char *name, uint32_t value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsString)(uint32_t index, const char *name, char *value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsByte)(uint32_t index, const char *name, char *value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsWord)(uint32_t index, const char *name, int16_t *value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsLong)(uint32_t index, const char *name, int32_t *value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsUByte)(uint32_t index, const char *name, unsigned char *value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsUWord)(uint32_t index, const char *name, uint16_t *value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsULong)(uint32_t index, const char *name, uint32_t *value);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsString)(uint32_t index, const char *name, char **str);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetAsStringCopy)(uint32_t index, const char *name, char *dest, uint32_t *dest_size);
|
||||
// ****** CAN-FD
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanFdTransmit)(uint32_t index, struct TCanFdMsg *fd_msg, int32_t count);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanFdReceive)(uint32_t index, struct TCanFdMsg *fd_msg, int32_t count);
|
||||
// ***** <*>
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetAsData)(uint32_t index, const char *name, void *data, uint32_t size);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetDataPtr)(uint32_t index, const char *name, void *data_ptr, uint32_t size);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExSetDataBlockCB)(uint32_t index, TCanGetDataBlockCB func, void *user_data);
|
||||
// ***** <*> neu 2
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetInfoList)(uint32_t dev_idx, const char *name, struct TCanInfoVarList **devices_info, int32_t flags); // <*> neu
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetInfoListPerform)(uint32_t dev_idx, const char *name, int32_t flags);
|
||||
typedef int32_t (DRV_CALLBACK_TYPE *TCanExGetInfoListGet)(uint32_t list_idx, struct TCanInfoVar *item);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CAN_API_TRUE_FUNC
|
||||
/***************************************************************/
|
||||
/* Tiny-CAN API Funktionen */
|
||||
/***************************************************************/
|
||||
extern TCanExGetDeviceCount CanExGetDeviceCount;
|
||||
extern TCanExGetDeviceList CanExGetDeviceList;
|
||||
extern TCanExGetDeviceListPerform CanExGetDeviceListPerform;
|
||||
extern TCanExGetDeviceListGet CanExGetDeviceListGet;
|
||||
extern TCanExGetDeviceInfo CanExGetDeviceInfo;
|
||||
extern TCanExGetDeviceInfoPerform CanExGetDeviceInfoPerform;
|
||||
extern TCanExGetDeviceInfoGet CanExGetDeviceInfoGet;
|
||||
extern TCanExDataFree CanExDataFree;
|
||||
extern TCanExCreateDevice CanExCreateDevice;
|
||||
extern TCanExDestroyDevice CanExDestroyDevice;
|
||||
extern TCanExCreateFifo CanExCreateFifo;
|
||||
extern TCanExBindFifo CanExBindFifo;
|
||||
extern TCanExCreateEvent CanExCreateEvent;
|
||||
extern TCanExSetObjEvent CanExSetObjEvent;
|
||||
extern TCanExSetEvent CanExSetEvent;
|
||||
extern TCanExSetEventAll CanExSetEventAll;
|
||||
extern TCanExResetEvent CanExResetEvent;
|
||||
extern TCanExWaitForEvent CanExWaitForEvent;
|
||||
extern TCanExInitDriver CanExInitDriver;
|
||||
extern TCanExSetOptions CanExSetOptions;
|
||||
extern TCanExSetAsByte CanExSetAsByte;
|
||||
extern TCanExSetAsWord CanExSetAsWord;
|
||||
extern TCanExSetAsLong CanExSetAsLong;
|
||||
extern TCanExSetAsUByte CanExSetAsUByte;
|
||||
extern TCanExSetAsUWord CanExSetAsUWord;
|
||||
extern TCanExSetAsULong CanExSetAsULong;
|
||||
extern TCanExSetAsString CanExSetAsString;
|
||||
extern TCanExGetAsByte CanExGetAsByte;
|
||||
extern TCanExGetAsWord CanExGetAsWord;
|
||||
extern TCanExGetAsLong CanExGetAsLong;
|
||||
extern TCanExGetAsUByte CanExGetAsUByte;
|
||||
extern TCanExGetAsUWord CanExGetAsUWord;
|
||||
extern TCanExGetAsULong CanExGetAsULong;
|
||||
extern TCanExGetAsString CanExGetAsString;
|
||||
extern TCanExGetAsStringCopy CanExGetAsStringCopy;
|
||||
|
||||
// ****** CAN-FD
|
||||
extern TCanFdTransmit CanFdTransmit;
|
||||
extern TCanFdReceive CanFdReceive;
|
||||
// **** <*> neu
|
||||
extern TCanExSetAsData CanExSetAsData;
|
||||
extern TCanExSetDataPtr CanExSetDataPtr;
|
||||
extern TCanExSetDataBlockCB CanExSetDataBlockCB;
|
||||
|
||||
extern TCanExGetInfoList CanExGetInfoList;
|
||||
extern TCanExGetInfoListPerform CanExGetInfoListPerform;
|
||||
extern TCanExGetInfoListGet CanExGetInfoListGet;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,385 +0,0 @@
|
||||
#ifndef __CAN_TYPES_H__
|
||||
#define __CAN_TYPES_H__
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#ifndef __WIN32__
|
||||
#define __WIN32__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
// Windows
|
||||
#if !defined(WINVER)
|
||||
#define WINVER 0x0500
|
||||
#endif
|
||||
#if !defined(_WIN32_IE)
|
||||
#define _WIN32_IE 0x0501
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1900)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
#endif
|
||||
#else
|
||||
// Linux & Mac
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef M_FORCE_INLINE
|
||||
#define M_FORCE_INLINE static __inline__ __attribute__((__always_inline__,__gnu_inline__))
|
||||
//inline __attribute__((always_inline)) <*>
|
||||
#endif
|
||||
#else
|
||||
#ifndef M_FORCE_INLINE
|
||||
#define M_FORCE_INLINE static __forceinline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define INDEX_INVALID 0xFFFFFFFF
|
||||
|
||||
#define INDEX_FIFO_PUFFER_MASK 0x0000FFFF
|
||||
#define INDEX_SOFT_FLAG 0x02000000
|
||||
// #define INDEX_RXD_TXT_FLAG 0x01000000 <*>
|
||||
#define INDEX_TXT_FLAG 0x01000000
|
||||
#define INDEX_CAN_KANAL_MASK 0x000F0000
|
||||
#define INDEX_CAN_DEVICE_MASK 0x00F00000
|
||||
|
||||
#define INDEX_FIFO_VIRTUAL 0x80000000
|
||||
#define INDEX_USER_MASK 0xFC000000
|
||||
|
||||
#define INDEX_CAN_KANAL_A 0x00000000
|
||||
#define INDEX_CAN_KANAL_B 0x00010000
|
||||
|
||||
/***************************************************************/
|
||||
/* Typen */
|
||||
/***************************************************************/
|
||||
|
||||
/******************************************/
|
||||
/* CAN Message Type */
|
||||
/******************************************/
|
||||
#define MsgFlags Flags.Long
|
||||
#define MsgLen Flags.Flag.Len
|
||||
#define MsgRTR Flags.Flag.RTR
|
||||
#define MsgEFF Flags.Flag.EFF
|
||||
#define MsgTxD Flags.Flag.TxD
|
||||
#define MsgErr Flags.Flag.Error
|
||||
#define MsgSource Flags.Flag.Source
|
||||
#define MsgFilHit Flags.Flag.FilHit
|
||||
#define MsgOV Flags.Flag.OV
|
||||
#define MsgData Data.Bytes
|
||||
|
||||
/*
|
||||
Byte
|
||||
|
||||
0 -> LEC Last Error Code
|
||||
1 = Stuff Error More than 5 equal bits in a sequence have occurred in a part of a
|
||||
received message where this is not allowed.
|
||||
2 = Form Error A fixed format part of a received frame has the wrong format.
|
||||
3 = AckError The message this CAN Core transmitted was not acknowledged by another node.
|
||||
4 = Bit1Error During the transmission of a message (with the exception of the
|
||||
arbitration field), the device wanted to send a recessive level (bit of logical
|
||||
value '1'), but the monitored busvalue was dominant.
|
||||
5 = Bit0Error During the transmission of a message (or acknowledge bit or active error
|
||||
flag, or overload flag), the device wanted to send a dominant level (data or
|
||||
identifier bit logical value '0'), but the monitored Bus value was recessive.
|
||||
During busoff recovery this status is set each time a sequence of 11 recessive bits
|
||||
has been monitored. This enables the CPU to monitor the proceeding of the busoff
|
||||
recovery sequence (indicating the bus is not stuck at dominant level or continuously
|
||||
disturbed).
|
||||
6 = CRCError The CRC check sum was incorrect in the message received, the CRC received
|
||||
for an incoming message does not match with the calculated CRC for the received data.
|
||||
1 -> Bus Status (Bit 0 - 3)
|
||||
0 = Ok
|
||||
1 = Error Warning
|
||||
2 = Error Passiv
|
||||
3 = Bus Off
|
||||
Bus-Failure -> Bit4
|
||||
2 -> Receive Error Counter
|
||||
3 -> Transmit Error Counter
|
||||
|
||||
<*> Neu
|
||||
OV -> FIFO Overflow Frame
|
||||
|
||||
Byte 0
|
||||
0 -> Source
|
||||
1 = CAN Controller
|
||||
2 = CAN Hardware
|
||||
3 = API
|
||||
1,2 -> Messages Lost <*> muss noch implementiert werden
|
||||
|
||||
*/
|
||||
|
||||
struct TCanFlagsBits
|
||||
{
|
||||
unsigned Len:4; // DLC -> Datenl<6E>nge 0 - 8 Byte
|
||||
unsigned TxD:1; // TxD -> 1 = Tx CAN Nachricht, 0 = Rx CAN Nachricht
|
||||
// Eine Erfolgreich versendete Nachricht wird als Best<73>tigung
|
||||
// ins Empfangsfifo zur<75>ckgeschrieben
|
||||
// Nicht alle Module unterst<73>tzen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned Error:1; // Error -> 1 = CAN Bus Fehler Nachricht
|
||||
// Nicht alle Module unterst<73>tzen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned RTR:1; // Remote Transmition Request bit -> Kennzeichnet eine RTR Nachricht
|
||||
unsigned EFF:1; // Extended Frame Format bit -> 1 = 29 Bit Id's, 0 = 11 Bit Id's
|
||||
unsigned Source:8; // Quelle der Nachricht (Device)
|
||||
// Neu
|
||||
unsigned FilHit:1; // FilHit -> 1 = Filter Hit
|
||||
unsigned OV:1; // <*> Neu FIFO Overflow
|
||||
unsigned Res1:1;
|
||||
unsigned Res3:1;
|
||||
unsigned Res4:4;
|
||||
unsigned Res5:8;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union TCanFlags
|
||||
{
|
||||
struct TCanFlagsBits Flag;
|
||||
uint32_t Long;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union TCanData
|
||||
{
|
||||
char Chars[8];
|
||||
unsigned char Bytes[8];
|
||||
uint16_t Words[4];
|
||||
uint32_t Longs[2];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TTime
|
||||
{
|
||||
uint32_t Sec;
|
||||
uint32_t USec;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanMsg
|
||||
{
|
||||
uint32_t Id;
|
||||
union TCanFlags Flags;
|
||||
union TCanData Data;
|
||||
struct TTime Time;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* CAN FD */
|
||||
/******************************************/
|
||||
#define MsgFD Flags.Flag.FD // FD Format
|
||||
#define MsgBRS Flags.Flag.BRS // Bit Rate Switch
|
||||
|
||||
struct TCanFdFlagsBits
|
||||
{
|
||||
unsigned Source:8; // Quelle der Nachricht (Device)
|
||||
unsigned Len:8; // DLC -> Datenl<6E>nge 0 - 8 Byte
|
||||
|
||||
unsigned TxD:1; // TxD -> 1 = Tx CAN Nachricht, 0 = Rx CAN Nachricht
|
||||
// Eine Erfolgreich versendete Nachricht wird als Best<73>tigung
|
||||
// ins Empfangsfifo zur<75>ckgeschrieben
|
||||
// Nicht alle Module unterst<73>tzen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned Error:1; // Error -> 1 = CAN Bus Fehler Nachricht
|
||||
// Nicht alle Module unterst<73>tzen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned RTR:1; // Remote Transmition Request bit -> Kennzeichnet eine RTR Nachricht
|
||||
unsigned EFF:1; // Extended Frame Format bit -> 1 = 29 Bit Id's, 0 = 11 Bit Id's
|
||||
unsigned FD:1; // CAN-FD Frame
|
||||
unsigned BRS:1; // Bit Rate Switch
|
||||
unsigned Res0:1;
|
||||
unsigned OV:1; // <*> Neu FIFO Overflow
|
||||
|
||||
unsigned Res2:1;
|
||||
unsigned Res3:1;
|
||||
unsigned Res4:1;
|
||||
unsigned Res5:1;
|
||||
unsigned Res6:1;
|
||||
unsigned Res7:1;
|
||||
unsigned Res8:1;
|
||||
unsigned FilHit:1; // FilHit -> 1 = Filter Hit
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union TCanFdFlags
|
||||
{
|
||||
struct TCanFdFlagsBits Flag;
|
||||
uint32_t Long;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union TCanFdData
|
||||
{
|
||||
char Chars[64];
|
||||
unsigned char Bytes[64];
|
||||
uint16_t Words[32];
|
||||
uint32_t Longs[16];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanFdMsg
|
||||
{
|
||||
uint32_t Id;
|
||||
union TCanFdFlags Flags;
|
||||
union TCanFdData Data;
|
||||
struct TTime Time;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* CAN Message Filter Type */
|
||||
/******************************************/
|
||||
#define FilFlags Flags.Long
|
||||
#define FilRTR Flags.Flag.RTR
|
||||
#define FilEFF Flags.Flag.EFF
|
||||
#define FilMode Flags.Flag.Mode
|
||||
#define FilIdMode Flags.Flag.IdMode
|
||||
#define FilEnable Flags.Flag.Enable
|
||||
|
||||
// * = Reserviert, zur Zeit noch unbenutzt
|
||||
|
||||
struct TMsgFilterFlagsBits
|
||||
{
|
||||
// 1. Byte
|
||||
unsigned Len:4; // * Dlc
|
||||
unsigned Res:2; // Reserviert
|
||||
unsigned RTR:1; // Remote Transmition Request
|
||||
unsigned EFF:1; // Extended Frame Format
|
||||
// 2. Byte
|
||||
unsigned IdMode:2; // 0 = Maske & Code
|
||||
// 1 = Start & Stop
|
||||
// 2 = Single Id
|
||||
unsigned DLCCheck:1; // *
|
||||
unsigned DataCheck:1; // *
|
||||
unsigned Res1:4;
|
||||
// 3. Byte
|
||||
unsigned Res2:8;
|
||||
// 4. Byte
|
||||
unsigned Type:4; // 0 = Single Puffer
|
||||
unsigned Res3:2;
|
||||
unsigned Mode:1; // 0 = Message entfernen
|
||||
// 1 = Message nicht entfernen
|
||||
unsigned Enable:1; // 0 = Filter sperren
|
||||
// 1 = Filter freigeben
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union TMsgFilterFlags
|
||||
{
|
||||
struct TMsgFilterFlagsBits Flag;
|
||||
uint32_t Long;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TMsgFilter
|
||||
{ // IdMode -> Maske & Code | Start & Stop | Single Id
|
||||
// --------------------------+--------------+-----------
|
||||
uint32_t Maske; // Filter-Id -> Maske | Stop |
|
||||
uint32_t Code; // Filter-Id -> Code | Start | Id
|
||||
union TMsgFilterFlags Flags;
|
||||
union TCanData Data; // *
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct TCanIndexSource
|
||||
{
|
||||
// 1. u. 2 Byte
|
||||
unsigned SubIndex:16;
|
||||
// 3. Byte
|
||||
unsigned Source:8;
|
||||
// 4. Byte
|
||||
unsigned TxD:1;
|
||||
unsigned Soft:1;
|
||||
unsigned User:5;
|
||||
unsigned Virtual:1;
|
||||
};
|
||||
|
||||
struct TCanIndexBits
|
||||
{
|
||||
// 1. u. 2 Byte
|
||||
unsigned SubIndex:16;
|
||||
// 3. Byte
|
||||
unsigned Channel:4;
|
||||
unsigned Device:4;
|
||||
// 4. Byte
|
||||
unsigned TxD:1;
|
||||
unsigned Soft:1;
|
||||
unsigned User:5;
|
||||
unsigned Virtual:1;
|
||||
};
|
||||
|
||||
union TCanIndex
|
||||
{
|
||||
struct TCanIndexBits Item;
|
||||
struct TCanIndexSource SrcItem;
|
||||
uint32_t Long;
|
||||
};
|
||||
|
||||
|
||||
|
||||
M_FORCE_INLINE void CanFdToCan(struct TCanMsg *dst, const struct TCanFdMsg *src)
|
||||
{
|
||||
uint8_t len;
|
||||
|
||||
dst->Id = src->Id;
|
||||
len = src->MsgLen;
|
||||
dst->MsgFlags = (src->MsgFlags >> 12) & 0x000000F0;
|
||||
if (len > 8)
|
||||
len = 8;
|
||||
dst->MsgLen = len;
|
||||
dst->MsgSource = src->MsgSource;
|
||||
dst->MsgFilHit = src->MsgFilHit;
|
||||
dst->Data.Longs[0] = src->Data.Longs[0];
|
||||
dst->Data.Longs[1] = src->Data.Longs[1];
|
||||
dst->Time.Sec = src->Time.Sec;
|
||||
dst->Time.USec = src->Time.USec;
|
||||
}
|
||||
|
||||
|
||||
M_FORCE_INLINE void CanToCanFd(struct TCanFdMsg *dst, const struct TCanMsg *src)
|
||||
{
|
||||
dst->Id = src->Id;
|
||||
dst->MsgFlags = (src->MsgFlags << 12) & 0x000F0000;
|
||||
dst->MsgLen = src->MsgLen;
|
||||
dst->MsgSource = src->MsgSource;
|
||||
dst->MsgFilHit = src->MsgFilHit;
|
||||
dst->Data.Longs[0] = src->Data.Longs[0];
|
||||
dst->Data.Longs[1] = src->Data.Longs[1];
|
||||
dst->Time.Sec = src->Time.Sec;
|
||||
dst->Time.USec = src->Time.USec;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
|
||||
Sehr geehrte Frau Spaag,
|
||||
|
||||
Aktuell bin ich als Softwareentwickler im Bereich C++/Qt fest angestellt, suche jedoch
|
||||
nach neuen Entwicklungsmöglichkeiten.
|
||||
|
||||
Ihre Stellenanzeige hat mich sofort angesprochen, denn das beschriebene Anforderungsprofil
|
||||
harmonisiert sehr gut mit meiner derzeitigen Tätigkeit im Bereich Datenvisualisierung und
|
||||
|
||||
blub
|
||||
|
||||
Ich freu mich wie woschd und verbeibe mit freundlichen Grüßen
|
||||
|
||||
Christoph Holzheuer
|
||||
|
||||
|
||||
// ----------
|
||||
|
||||
znode<T> ist eine header-only Klasse in modern c++ für generische Baumstrukturen
|
||||
In der derzeitigen Ausführung dient sie mit Hilfe des pugixml Parser zur Verwaltung
|
||||
von XML Daten innerhalb des xtree-Projekts.
|
||||
|
||||
Die Knoten sind std::c++, die Verwaltung der Attribs ist drangeebrt und somit variable.
|
||||
|
||||
Besonderheit ist die Übergabe das String types als template parameter: In Xtree instanzierung durch QString,
|
||||
andere durch std::string bzw. std::w_string ohne Dependencies zur Qt-Lib eingehen zu müssen.
|
||||
bridge-code
|
||||
|
||||
// ----------
|
||||
|
Before Width: | Height: | Size: 46 KiB |
94
doc/Install.on.pi.txt
Normal file
@@ -0,0 +1,94 @@
|
||||
Nachinstallieren:
|
||||
|
||||
Qt6
|
||||
|
||||
...
|
||||
|
||||
|
||||
IconFont:
|
||||
|
||||
|
||||
sudo apt install fonts-noto-color-emoji
|
||||
|
||||
|
||||
UpdateDB:
|
||||
|
||||
...
|
||||
|
||||
paket modemmanager stört:
|
||||
|
||||
apt list --installed modemmanager
|
||||
dpkg -s modemmanager
|
||||
|
||||
systemctl status ModemManager
|
||||
sudo systemctl stop ModemManager
|
||||
sudo systemctl disable ModemManager
|
||||
sudo apt purge modemmanager
|
||||
|
||||
// ---
|
||||
|
||||
sudo apt install \
|
||||
qt6-declarative-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
qt6-l10n-tools \
|
||||
qt6-scxml-dev \
|
||||
qt6-serialport-dev \
|
||||
qt6-serialbus-dev \
|
||||
qt6-connectivity-dev \
|
||||
qt6-sensors-dev \
|
||||
qt6-websockets-dev \
|
||||
qt6-webchannel-dev \
|
||||
qt6-svg-dev \
|
||||
qt6-multimedia-dev \
|
||||
qt6-charts-dev \
|
||||
qt6-wayland \
|
||||
qml6-module-qtquick-controls \
|
||||
qml6-module-qtquick-layouts \
|
||||
qml6-module-qtquick-templates \
|
||||
qml6-module-qtquick-window \
|
||||
qml6-module-qtqml-workerscript \
|
||||
qml6-module-qtcharts \
|
||||
qml6-module-qt-labs-platform \
|
||||
libqt6sql6-mysql libqt6sql6-psql libqt6sql6-sqlite \
|
||||
libqt6opengl6-dev
|
||||
|
||||
sudo apt update
|
||||
sudo apt install \
|
||||
qtcreator \
|
||||
qtcreator-doc \
|
||||
cmake \
|
||||
ninja-build \
|
||||
gdb \
|
||||
clang \
|
||||
clang-format
|
||||
|
||||
|
||||
https://github.com/MHS-Elektronik/OBD-Display
|
||||
|
||||
sudo chgrp pi /opt
|
||||
sudo chmod -R 775 /opt
|
||||
cd /opt
|
||||
mv /home/pi/tiny_can_raspberry_790.tar.gz .
|
||||
tar -xzvf tiny_can_raspberry_790.tar.gz
|
||||
rm tiny_can_raspberry_790.tar.gz
|
||||
|
||||
sudo apt install fonts-open-sans
|
||||
|
||||
|
||||
RANT
|
||||
|
||||
--- STRUKTUR
|
||||
|
||||
Denglish -> Comments, Bezeichnungen 'aligned', 'given'
|
||||
Weltsprache, mag ja sein,
|
||||
|
||||
Schlimmer: Doku & Bücher -> c++, qt, OO nicht verstanden
|
||||
|
||||
includes_ pfade hartcodiert statt im Makefile -> Kunstfehler
|
||||
Projecte willkürlich verstreut
|
||||
|
||||
Respektlose Schlampigkeit: copy & paste: es werden sogar die Artefakte des MKS mitkopiert ->
|
||||
---
|
||||
|
||||
---
|
||||
@@ -1,45 +0,0 @@
|
||||
Challenges
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
@@ -1,17 +0,0 @@
|
||||
/*******************************************************************************/
|
||||
/* Interface zur Tiny-CAN API */
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* Beschreibung : Laden einer Treiber Lib */
|
||||
/* */
|
||||
/* Version : 2.10 */
|
||||
/* Datei Name : can_drv_win.c */
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* Datum : 18.09.15 */
|
||||
/* Copyright : (C) 2011 - 2015 by MHS-Elektronik GmbH & Co. KG, Germany */
|
||||
/* www.mhs-elektronik.de */
|
||||
/* Autor : Demlehner Klaus, info@mhs-elektronik.de */
|
||||
/*******************************************************************************/
|
||||
#include "mhs_can_drv.c"
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*******************************************************************************/
|
||||
/* Interface zur Tiny-CAN API */
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* Beschreibung : Laden einer Treiber DLL */
|
||||
/* */
|
||||
/* Version : 2.10 */
|
||||
/* Datei Name : can_drv_win.c */
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* Datum : 18.09.15 */
|
||||
/* Copyright : (C) 2011 - 2015 by MHS-Elektronik GmbH & Co. KG, Germany */
|
||||
/* www.mhs-elektronik.de */
|
||||
/* Autor : Demlehner Klaus, info@mhs-elektronik.de */
|
||||
/*******************************************************************************/
|
||||
#include "mhs_can_drv.c"
|
||||
|
||||
|
||||
|
||||
19
main.cpp
@@ -1,7 +1,7 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
Copyright © 2025 christoph holzheuer
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
@@ -39,31 +39,14 @@
|
||||
|
||||
#include <bcmainwindow.h>
|
||||
|
||||
#include <expected>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
|
||||
bool setApplicationStyleSheet( QAnyStringView path )
|
||||
{
|
||||
QFile styleFile( path.toString() );
|
||||
if (styleFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QString style = styleFile.readAll();
|
||||
qApp->setStyleSheet(style);
|
||||
styleFile.close();
|
||||
return true;
|
||||
}
|
||||
qWarning() << "Konnte Stylesheet nicht laden:" << styleFile.errorString();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QApplication app(argc, argv);
|
||||
//setApplicationStyleSheet( ":/claude_light_mode.qss"_L1 );
|
||||
/*
|
||||
app.setStyleSheet(R"(
|
||||
QWidget {
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -3,43 +3,48 @@
|
||||
<Bike name='franken-wheeler'>
|
||||
|
||||
<Device Type="Console">
|
||||
<Value ID='Cons_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Cons_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Cons_Sn_Product_Hi' Label='Product Number' ReadOnly='true' UnitType='Word'/>
|
||||
<Value ID='Cons_Sn_Oem_Hi' Label='OEM Number' ReadOnly='true' UnitType='Word' />
|
||||
<Value ID='Cons_Rev_Hw' Label='Hardware Version' />
|
||||
<Value ID='Cons_Rev_Sw' Label='Software Version' />
|
||||
|
||||
<Value ID='Cons_Assist_Initlevel' Label='Assistance Init Level' ReadOnly='false' UnitType='AssInit'/>
|
||||
<Value ID='Cons_Assist_Level_1' Label='Assistance Level 1' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_2' Label='Assistance Level 2' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_3' Label='Assistance Level 3' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_4' Label='Assistance Level 4' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Sn_Product_Hi' Label='Product Number' IsWord='1'/>
|
||||
<Value ID='Cons_Sn_Oem_Hi' Label='OEM Number' IsWord='1' />
|
||||
|
||||
<Value ID='Cons_Assist_Maxspeed_Flag' Label='Max Limit Enabled' ReadOnly='false' UnitType='Byte' />
|
||||
<Value ID='Cons_Assist_Maxspeed_Hi' Label='Max Speed Limit' ReadOnly='false' UnitType='Kmh' Factor='0.1'/>
|
||||
<Value ID='Cons_Assist_Initlevel' Label='Assistance Init Level' Min='0' Max='4'/>
|
||||
|
||||
<Value ID='Cons_Assist_Minspeed_Flag' Label='Min Limit Enabled' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Cons_Assist_Minspeed' Label='Min Speed Limit' ReadOnly='true' UnitType='Kmh'/>
|
||||
|
||||
<Value ID='Cons_Throttle_Maxspeed_Flag' Label='Throttle Limit Enabled' ReadOnly='true' UnitType='Byte'/>
|
||||
<Value ID='Cons_Throttle_Maxspeed_Hi' Label='Throttle Speed Limit' ReadOnly='true' UnitType='kmh' Factor='0.1'/>
|
||||
<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' Factor='1.5625' UnitLabel='%' Min='0' Max='400' />
|
||||
<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' Factor='1.5625' UnitLabel='%' Min='0' Max='400' />
|
||||
|
||||
<Value ID='Cons_Geometry_Circ_Hi' Label='Wheel Circumference' ReadOnly='true' UnitType='mm' />
|
||||
<Value ID='Cons_Assist_Mountain_Cap' Label='Mountain Cap' ReadOnly='true' UnitType='Percent' Factor='1.5625' />
|
||||
<Value ID='Cons_Assist_Maxspeed_Flag' Label='Max Limit Enabled' ValueType='bool' />
|
||||
<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' ValueType='bool' />
|
||||
<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' ValueType='bool'/>
|
||||
<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' IsWord='1' UnitLabel='mm' Min='0' Max='2300' Factor='1.5625' />
|
||||
<Value ID='Cons_Assist_Mountain_Cap' Label='Mountain Cap' UnitLabel='%' Factor='1.5625' />
|
||||
</Device>
|
||||
|
||||
|
||||
<Device Type="Motor">
|
||||
<Value ID='Motor_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Motor_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Motor_Status_Temperature' Label='Motor Temperature' ReadOnly='true' UnitType='Degree'/>
|
||||
<Value ID='Motor_Assist_Maxspeed' Label='Motor max. Speed' ReadOnly='true' UnitType='Kmh' />
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Part Number' ReadOnly='true' UnitType='Word'/>
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Serial Number' ReadOnly='true' UnitType='Word' />
|
||||
<Value ID='Motor_Geometry_Circ_Hi' Label='Motor Gemetry' ReadOnly='true' UnitType='Mm' />
|
||||
<Value ID='Motor_Rev_Hw' Label='Hardware Version' />
|
||||
<Value ID='Motor_Rev_Sw' Label='Software Version' />
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Part Number' IsWord='1'/>
|
||||
<Value ID='Motor_Sn_Item_Hi' Label='Motor Serial Number' IsWord='1' />
|
||||
<Value ID='Motor_Status_Temperature' Label='Motor Temperature' UnitLabel='°C' />
|
||||
<Value ID='Motor_Assist_Maxspeed' Label='Motor max. Speed' Reader='Kmh' />
|
||||
|
||||
<Value ID='Motor_Geometry_Circ_Hi' Label='Wheel Circumference' IsWord='1' UnitLabel='mm' Min='0' Max='2300' Factor='1.5625' />
|
||||
</Device>
|
||||
|
||||
<Device Type="Battery">
|
||||
<Value ID='Battery_Rev_Hw' Label='Hardware Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Battery_Rev_Sw' Label='Software Version' ReadOnly='true' UnitType='Byte' />
|
||||
<Value ID='Battery_Rev_Hw' Label='Hardware Version' />
|
||||
<Value ID='Battery_Rev_Sw' Label='Software Version' />
|
||||
</Device>
|
||||
|
||||
</Bike>
|
||||
@@ -57,106 +62,104 @@
|
||||
|
||||
|
||||
|
||||
<Value ID='Cons_Stat_Dist_Hi' Label='' ReadOnly='true' UnitType='mm' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Dist_Lo' Label='' ReadOnly='true' UnitType='mm'/>
|
||||
<Value ID='Cons_Stat_Avgspeed_Hi' Label='' ReadOnly='true' UnitType='mm' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Avgspeed_Lo' Label='' ReadOnly='true' UnitType='mm'/>
|
||||
<Value ID='Cons_Stat_Dist_Hi' Label='' Reader='mm' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Dist_Lo' Label='' Reader='mm'/>
|
||||
<Value ID='Cons_Stat_Avgspeed_Hi' Label='' Reader='mm' Factor='0.1' />
|
||||
<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_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Odomoter_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Odo_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Odo_Hihi' Label='' Factor='0.1' />
|
||||
<Value ID='Cons_Stat_Odo_Hilo' Label='' />
|
||||
<Value ID='Cons_Stat_Odomoter_Lohi' Label='' />
|
||||
<Value ID='Cons_Stat_Odo_Lolo' Label='' />
|
||||
|
||||
<Value ID='Cons_Preference_Nip_Hihi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Calibrated' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Chrono_Second' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Chrono_Minute' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Stat_Chrono_Hour' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Lcd_Contrast' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Location' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Year' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Month' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Day' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Nip_Hihi' Label='' />
|
||||
<Value ID='Cons_Preference_Nip_Hilo' Label='' />
|
||||
<Value ID='Cons_Preference_Nip_Lohi' Label='' />
|
||||
<Value ID='Cons_Preference_Nip_Lolo' Label='' />
|
||||
<Value ID='Cons_Throttle_Calibrated' Label='' />
|
||||
<Value ID='Cons_Stat_Chrono_Second' Label='' />
|
||||
<Value ID='Cons_Stat_Chrono_Minute' Label='' />
|
||||
<Value ID='Cons_Stat_Chrono_Hour' Label='' />
|
||||
<Value ID='Cons_Preference_Lcd_Contrast' Label='' />
|
||||
<Value ID='Cons_Sn_Location' Label='' />
|
||||
<Value ID='Cons_Sn_Year' Label='' />
|
||||
<Value ID='Cons_Sn_Month' Label='' />
|
||||
<Value ID='Cons_Sn_Day' Label='' />
|
||||
|
||||
<Value ID='Cons_Sn_Pn_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Pn_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Item_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Item_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Sn_Pn_Hi' Label='' />
|
||||
<Value ID='Cons_Sn_Pn_Lo' Label='' />
|
||||
<Value ID='Cons_Sn_Item_Hi' Label='' />
|
||||
<Value ID='Cons_Sn_Item_Lo' Label='' />
|
||||
|
||||
<Value ID='Cons_Assist_Gauge_Joint' Label='' ReadOnly='true' Min='0' Max='11' />
|
||||
<Value ID='Cons_Throttle_Min_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Min_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Max_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Max_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Gauge_Joint' Label='' Min='0' Max='11' />
|
||||
<Value ID='Cons_Throttle_Min_Hi' Label='' />
|
||||
<Value ID='Cons_Throttle_Min_Lo' Label='' />
|
||||
<Value ID='Cons_Throttle_Max_Hi' Label='' />
|
||||
<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='' 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_Assist_Brake_Level' Label='' Min='0' Max='64' Factor='1.5625'/>
|
||||
<Value ID='Cons_Preference_Trip_To_Empty_Flag' Label='' />
|
||||
<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_Polarity' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Gauge_Filter' Label='' ReadOnly='true' Min='0' Max='8' />
|
||||
<Value ID='Cons_Assist_Brake_Polarity' Label='' />
|
||||
<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_Gain_A' Label='' ReadOnly='true' 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_Sn_Type' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Region' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Configbit_0' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Enabled_Boost_Display' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Autoregen_Flag' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Gauge_Gain' Label='' 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='' Min='0.1' Max='25.0' Factor='0.1' />
|
||||
<Value ID='Cons_Sn_Type' Label='' />
|
||||
<Value ID='Cons_Preference_Region' Label='' />
|
||||
<Value ID='Cons_Preference_Configbit_0' Label='' />
|
||||
<Value ID='Cons_Throttle_Enabled_Boost_Display' Label='' />
|
||||
<Value ID='Cons_Assist_Autoregen_Flag' Label='' />
|
||||
|
||||
<Value ID='Cons_Rev_Sub' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Light_Button_Mode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Expertmode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Rev_Sub' Label='' />
|
||||
<Value ID='Cons_Preference_Light_Button_Mode' Label='' />
|
||||
<Value ID='Cons_Preference_Expertmode' Label='' />
|
||||
|
||||
|
||||
<Value ID='Cons_Preference_Codes_Hihi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hihi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hilo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lohi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lolo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Throttle_Mode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Preference_Codes_Hihi' Label='' />
|
||||
<Value ID='Cons_Preference_Codes_Hilo' Label='' />
|
||||
<Value ID='Cons_Preference_Codes_Lohi' Label='' />
|
||||
<Value ID='Cons_Preference_Codes_Lolo' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hihi' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Hilo' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lohi' Label='' />
|
||||
<Value ID='Cons_Preference_Codesrw_Lolo' Label='' />
|
||||
<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_Preference_Flip_Side' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Testmode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Testmode_Hw14' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Boost_Triggerlevel' Label='' Min='1.5' Max='50.0' Factor='1.5625' />
|
||||
<Value ID='Cons_Preference_Flip_Side' Label='' />
|
||||
<Value ID='Cons_Config_Testmode' Label='' />
|
||||
<Value ID='Cons_Config_Testmode_Hw14' Label='' />
|
||||
|
||||
<Value ID='Cons_Config_Last_Mode' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Speedgain' Label='' ReadOnly='true' Factor='0.1' />
|
||||
<Value ID='Cons_Config_Last_Mode' Label='' />
|
||||
<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_Off' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Last_Mode_On' Label='' />
|
||||
<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_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Throttle_Position' Label='' ReadOnly='true' Factor='1.5625'/>
|
||||
<Value ID='Cons_Throttle_Raw_Hi' Label='' />
|
||||
<Value ID='Cons_Throttle_Raw_Lo' Label='' />
|
||||
<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_4' Label='' ReadOnly='true' UnitType='Percent' Factor='1.5625'/>
|
||||
<Value ID='Cons_Config_Service_Timestamp_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Service_Zimestamp_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Service_Distance_Hi' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Config_Service_Distance_Lo' Label='' ReadOnly='true' />
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_3' Label='' Factor='1.5625'/>
|
||||
<Value ID='Cons_Assist_Level_Rekuperation_4' Label='' Factor='1.5625'/>
|
||||
<Value ID='Cons_Config_Service_Timestamp_Hi' Label='' />
|
||||
<Value ID='Cons_Config_Service_Zimestamp_Lo' Label='' />
|
||||
<Value ID='Cons_Config_Service_Distance_Hi' Label='' />
|
||||
<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_2' 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='' Factor='1.5625'/>
|
||||
|
||||
-->
|
||||
|
||||
@@ -3,118 +3,165 @@
|
||||
/* Alle QWidgets bekommen diesen Font */
|
||||
QWidget
|
||||
{
|
||||
font-size: 14px;
|
||||
font-family: Segoe UI, sans-serif;
|
||||
font-family: "Calibri", "Carlito", "Open Sans", sans-serif;
|
||||
font-size: 10pt;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
/*
|
||||
QMainWindow
|
||||
|
||||
QLabel#_headerLabel
|
||||
{
|
||||
background-color: #272727;
|
||||
font-size: 14pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*
|
||||
QToolButton
|
||||
{
|
||||
background-color: white;
|
||||
color: #201F1E;
|
||||
border: 1px solid #8A8886;
|
||||
border-radius: 4px;
|
||||
|
||||
|
||||
min-width: 64px;
|
||||
max-width: 64px;
|
||||
min-height: 64px;
|
||||
max-height: 64px;
|
||||
|
||||
}
|
||||
|
||||
QToolButton:hover
|
||||
{
|
||||
background-color: #F3F2F1;
|
||||
border: 1px solid #323130;
|
||||
}
|
||||
|
||||
QToolButton:pressed
|
||||
{
|
||||
background-color: #EDEBE9;
|
||||
border: 1px solid #201F1E;
|
||||
}
|
||||
|
||||
QToolButton:disabled
|
||||
{
|
||||
background-color: #F3F2F1;
|
||||
color: #A19F9D;
|
||||
border: 1px solid #EDEBE9;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Spezifisches Styling für Buttons */
|
||||
QPushButton
|
||||
/* === QToolButton === */
|
||||
QToolButton
|
||||
{
|
||||
background-color: #0078d7;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
color: #000000;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
|
||||
min-width: 64px;
|
||||
max-width: 64px;
|
||||
min-height: 64px;
|
||||
max-height: 64px;
|
||||
}
|
||||
|
||||
QPushButton:hover
|
||||
QToolButton:hover
|
||||
{
|
||||
background-color: #1084e3;
|
||||
background-color: #F9F9F9;
|
||||
border: 1px solid #DDDDDD;
|
||||
}
|
||||
|
||||
QPushButton:pressed
|
||||
QToolButton:pressed
|
||||
{
|
||||
background-color: #005a9e;
|
||||
background-color: #E0E0E0;
|
||||
}
|
||||
|
||||
/* Normal */
|
||||
QToolButton {
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
QToolButton:checked
|
||||
{
|
||||
background-color: green;/*#0078D4;*/
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QToolButton:disabled
|
||||
{
|
||||
color: #A19F9D;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* === QTableView & QTableWidget === */
|
||||
|
||||
QTableView, QTableWidget
|
||||
{
|
||||
background-color: #FFFFFF;
|
||||
color: #000000;
|
||||
gridline-color: #E1DFDD;
|
||||
border: 1px solid #E1DFDD;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
selection-background-color: #0078D4;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
QToolButton:hover {
|
||||
background-color: #E3F2FD;
|
||||
border: 1px solid #2196F3;
|
||||
}
|
||||
|
||||
/* Pressed/Clicked */
|
||||
QToolButton:pressed {
|
||||
background-color: #BBDEFB;
|
||||
}
|
||||
|
||||
/* Checked (bei checkable buttons) */
|
||||
QToolButton:checked {
|
||||
background-color: #2196F3;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Checked + Hover */
|
||||
QToolButton:checked:hover {
|
||||
background-color: #1976D2;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
QToolButton:disabled {
|
||||
color: #BDBDBD;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/*
|
||||
QTableView
|
||||
{
|
||||
background-color: #404142;
|
||||
border-radius: 8px;
|
||||
outline: none;
|
||||
show-decoration-selected: 0;
|
||||
}
|
||||
|
||||
QTableView::item
|
||||
{
|
||||
border: 2px solid #2196F3;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
margin: 4px;
|
||||
background-color: white;
|
||||
}
|
||||
*/
|
||||
|
||||
QTableView::item:hover
|
||||
{
|
||||
border-color: #FF9800;
|
||||
background-color: #fff8f0;
|
||||
background-color: #e8f4f8;
|
||||
}
|
||||
|
||||
QTableView::item:selected
|
||||
{
|
||||
border-color: #F44336; /* Roter Rahmen */
|
||||
background-color: #ffebee;
|
||||
|
||||
QScrollBar::handle:horizontal {
|
||||
background-color: #C8C6C4;
|
||||
min-width: 40px;
|
||||
border-radius: 6px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
QTableView::item:selected:hover
|
||||
{
|
||||
border-color: #FF9800;
|
||||
background-color: #ffe0b2;
|
||||
QScrollBar::handle:horizontal:hover {
|
||||
background-color: #A19F9D;
|
||||
}
|
||||
*/
|
||||
|
||||
QTableView::item:focus
|
||||
{
|
||||
/*
|
||||
// outline: none; Entfernt das Focus-Rectangle
|
||||
// border-color: green;
|
||||
// background-color: #ffe0b2;
|
||||
*/
|
||||
border: 2px solid gray;
|
||||
border-style: inset;
|
||||
background-color: white;
|
||||
color: black;
|
||||
QScrollBar::handle:horizontal:pressed {
|
||||
background-color: #8A8886;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal,
|
||||
QScrollBar::sub-line:horizontal {
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
QScrollBar::add-page:horizontal,
|
||||
QScrollBar::sub-page:horizontal {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QScrollBar:vertical {
|
||||
background-color: transparent;
|
||||
width: 12px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
background-color: #C8C6C4;
|
||||
min-height: 40px;
|
||||
border-radius: 6px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:hover {
|
||||
background-color: #A19F9D;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:pressed {
|
||||
background-color: #8A8886;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical,
|
||||
QScrollBar::sub-line:vertical {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
QScrollBar::add-page:vertical,
|
||||
QScrollBar::sub-page:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 7.3 KiB |
1
resources/connect.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.25 4a.75.75 0 0 1 .743.648L9 4.75v2.773l1.874 2.815a.75.75 0 0 1 .117.306l.009.11v4.496a.75.75 0 0 1-.649.743L10.25 16H8.996v3.254a.75.75 0 0 1-1.492.101l-.007-.101L7.496 16 5.5 15.999v3.258a.75.75 0 0 1-1.493.101l-.006-.101L4 15.999 2.75 16a.75.75 0 0 1-.742-.648l-.007-.102v-4.496a.75.75 0 0 1 .071-.32l.055-.096 1.874-2.815V4.75a.75.75 0 0 1 1.493-.102l.007.102v3a.75.75 0 0 1-.072.32l-.054.096-1.874 2.815V14.5H9.5v-3.52L7.625 8.167a.75.75 0 0 1-.117-.306L7.5 7.75v-3A.75.75 0 0 1 8.25 4Zm7.004.001h4.496a.75.75 0 0 1 .743.649l.007.101L20.499 8h.75a.75.75 0 0 1 .744.648L22 8.75v4.496c0 .111-.025.22-.072.32l-.054.096L20 16.477v2.773a.75.75 0 0 1-1.494.102l-.006-.102v-3c0-.11.024-.22.071-.32l.054-.096L20.5 13.02V9.5h-5.998v3.52l1.874 2.814a.749.749 0 0 1 .118.306l.008.11v3a.75.75 0 0 1-1.493.102l-.007-.102v-2.773l-1.874-2.815a.75.75 0 0 1-.118-.306l-.008-.11V8.75a.75.75 0 0 1 .648-.743L13.752 8h.752V4.751a.75.75 0 0 1 .649-.743l.101-.007h4.496-4.496ZM19 5.501h-2.996V8h2.995V5.501Z" fill="#000000"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
resources/connect_white.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="48" height="48" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.25 4a.75.75 0 0 1 .743.648L9 4.75v2.773l1.874 2.815a.75.75 0 0 1 .117.306l.009.11v4.496a.75.75 0 0 1-.649.743L10.25 16H8.996v3.254a.75.75 0 0 1-1.492.101l-.007-.101L7.496 16 5.5 15.999v3.258a.75.75 0 0 1-1.493.101l-.006-.101L4 15.999 2.75 16a.75.75 0 0 1-.742-.648l-.007-.102v-4.496a.75.75 0 0 1 .071-.32l.055-.096 1.874-2.815V4.75a.75.75 0 0 1 1.493-.102l.007.102v3a.75.75 0 0 1-.072.32l-.054.096-1.874 2.815V14.5H9.5v-3.52L7.625 8.167a.75.75 0 0 1-.117-.306L7.5 7.75v-3A.75.75 0 0 1 8.25 4Zm7.004.001h4.496a.75.75 0 0 1 .743.649l.007.101L20.499 8h.75a.75.75 0 0 1 .744.648L22 8.75v4.496c0 .111-.025.22-.072.32l-.054.096L20 16.477v2.773a.75.75 0 0 1-1.494.102l-.006-.102v-3c0-.11.024-.22.071-.32l.054-.096L20.5 13.02V9.5h-5.998v3.52l1.874 2.814a.749.749 0 0 1 .118.306l.008.11v3a.75.75 0 0 1-1.493.102l-.007-.102v-2.773l-1.874-2.815a.75.75 0 0 1-.118-.306l-.008-.11V8.75a.75.75 0 0 1 .648-.743L13.752 8h.752V4.751a.75.75 0 0 1 .649-.743l.101-.007h4.496-4.496ZM19 5.501h-2.996V8h2.995V5.501Z" fill="#DDE6E8"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 16 KiB |
1
resources/exit.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2Zm0 1.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Zm3.446 4.897.084.073a.75.75 0 0 1 .073.976l-.073.084L13.061 12l2.47 2.47a.75.75 0 0 1 .072.976l-.073.084a.75.75 0 0 1-.976.073l-.084-.073L12 13.061l-2.47 2.47a.75.75 0 0 1-.976.072l-.084-.073a.75.75 0 0 1-.073-.976l.073-.084L10.939 12l-2.47-2.47a.75.75 0 0 1-.072-.976l.073-.084a.75.75 0 0 1 .976-.073l.084.073L12 10.939l2.47-2.47a.75.75 0 0 1 .976-.072Z" fill="#000000"/></svg>
|
||||
|
After Width: | Height: | Size: 599 B |