Skip to content

Commit 3203720

Browse files
refactor(simulator): extract HostSerialBackend interface
Phase 1 of pluggable host serial backends. Introduces an abstract HostSerialBackend QObject interface and extracts the existing QSerialPort handling into a QSerialPortBackend implementation. HostSerialConnector becomes a thin per-port owner of a backend pointer. Per-port encoding and baudrate are cached on the connector so they survive backend swaps and reconnects. Error reporting moves out of the connector: backends emit errorOccurred, the connector forwards via a backendError signal, and SimulatorMainWindow shows the message box. No behaviour change. Sets up the next phase, which adds a QLocalSocketBackend so user scripts can stand in for hardware on simulator aux ports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f31e364 commit 3203720

7 files changed

Lines changed: 296 additions & 63 deletions

companion/src/simulation/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ set(${PROJECT_NAME}_NAMES
2020
widgets/radiowidget
2121
widgets/virtualjoystickwidget
2222
serialportsdialog
23+
hostserialbackend_serialport
2324
hostserialconnector
2425
simulateduiwidgetGeneric
2526
wasmsimulatorinterface
@@ -36,6 +37,7 @@ AddHeadersSources()
3637

3738
set(${PROJECT_NAME}_HDRS
3839
${${PROJECT_NAME}_HDRS}
40+
hostserialbackend.h
3941
radiouiaction.h
4042
widgets/buttonswidget.h
4143
widgets/radiofaderwidget.h
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (C) EdgeTX
3+
*
4+
* Based on code named
5+
* opentx - https://github.com/opentx/opentx
6+
* th9x - http://code.google.com/p/th9x
7+
* er9x - http://code.google.com/p/er9x
8+
* gruvin9x - http://code.google.com/p/gruvin9x
9+
*
10+
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11+
*
12+
* This program is free software; you can redistribute it and/or modify
13+
* it under the terms of the GNU General Public License version 2 as
14+
* published by the Free Software Foundation.
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*/
21+
22+
#pragma once
23+
24+
#include <QByteArray>
25+
#include <QObject>
26+
#include <QString>
27+
28+
// Abstract host-side transport for a simulator aux serial port.
29+
//
30+
// The simulator firmware sees a generic byte stream; on the host side
31+
// the bytes can come from a real QSerialPort device, a local socket,
32+
// or any other source. Each backend implementation hides the
33+
// transport details behind this interface so HostSerialConnector can
34+
// stay transport-agnostic.
35+
//
36+
// Backends are owned by HostSerialConnector and live on the same
37+
// thread as the connector. Implementations should emit dataReceived
38+
// for incoming bytes and errorOccurred (with a user-facing message)
39+
// when something goes wrong opening or operating the transport.
40+
class HostSerialBackend : public QObject
41+
{
42+
Q_OBJECT
43+
44+
public:
45+
explicit HostSerialBackend(QObject * parent = nullptr) : QObject(parent) {}
46+
~HostSerialBackend() override = default;
47+
48+
virtual bool open() = 0;
49+
virtual void close() = 0;
50+
virtual bool isOpen() const = 0;
51+
52+
virtual void write(const QByteArray & data) = 0;
53+
54+
// No-ops for transports without a notion of bit-level encoding /
55+
// baudrate (e.g. local sockets). Serial backends override these.
56+
virtual void setBaudrate(quint32 /*baudrate*/) {}
57+
virtual void setEncoding(quint8 /*encoding*/) {}
58+
59+
// Human-readable identifier (port name, socket path, ...) shown
60+
// in dialogs and log output.
61+
virtual QString displayName() const = 0;
62+
63+
signals:
64+
void dataReceived(const QByteArray & data);
65+
void errorOccurred(const QString & message);
66+
};
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (C) EdgeTX
3+
*
4+
* Based on code named
5+
* opentx - https://github.com/opentx/opentx
6+
* th9x - http://code.google.com/p/th9x
7+
* er9x - http://code.google.com/p/er9x
8+
* gruvin9x - http://code.google.com/p/gruvin9x
9+
*
10+
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11+
*
12+
* This program is free software; you can redistribute it and/or modify
13+
* it under the terms of the GNU General Public License version 2 as
14+
* published by the Free Software Foundation.
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*/
21+
22+
#include "hostserialbackend_serialport.h"
23+
24+
#include "simulatorinterface.h"
25+
26+
#include <QtDebug>
27+
28+
QSerialPortBackend::QSerialPortBackend(const QString & portName, QObject * parent)
29+
: HostSerialBackend(parent),
30+
port(new QSerialPort(portName, this))
31+
{
32+
connect(port, &QSerialPort::readyRead, this, [this]() {
33+
emit dataReceived(port->readAll());
34+
});
35+
}
36+
37+
QSerialPortBackend::~QSerialPortBackend()
38+
{
39+
if (port->isOpen())
40+
port->close();
41+
}
42+
43+
bool QSerialPortBackend::open()
44+
{
45+
if (port->open(QIODevice::ReadWrite)) {
46+
qDebug() << "Opened host serial" << port->portName();
47+
return true;
48+
}
49+
emit errorOccurred(port->errorString());
50+
return false;
51+
}
52+
53+
void QSerialPortBackend::close()
54+
{
55+
port->close();
56+
}
57+
58+
bool QSerialPortBackend::isOpen() const
59+
{
60+
return port->isOpen();
61+
}
62+
63+
void QSerialPortBackend::write(const QByteArray & data)
64+
{
65+
port->write(data);
66+
}
67+
68+
void QSerialPortBackend::setBaudrate(quint32 baudrate)
69+
{
70+
if (!port->setBaudRate(baudrate))
71+
qDebug() << "Failed to set baudrate";
72+
}
73+
74+
void QSerialPortBackend::setEncoding(quint8 encoding)
75+
{
76+
switch (encoding) {
77+
case SERIAL_ENCODING_8N1:
78+
port->setDataBits(QSerialPort::Data8);
79+
port->setParity(QSerialPort::NoParity);
80+
port->setStopBits(QSerialPort::OneStop);
81+
break;
82+
case SERIAL_ENCODING_8E2:
83+
port->setDataBits(QSerialPort::Data8);
84+
port->setParity(QSerialPort::EvenParity);
85+
port->setStopBits(QSerialPort::TwoStop);
86+
break;
87+
default:
88+
// QSerialPort can't do SERIAL_ENCODING_PXX1_PWM
89+
break;
90+
}
91+
}
92+
93+
QString QSerialPortBackend::displayName() const
94+
{
95+
return port->portName();
96+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) EdgeTX
3+
*
4+
* Based on code named
5+
* opentx - https://github.com/opentx/opentx
6+
* th9x - http://code.google.com/p/th9x
7+
* er9x - http://code.google.com/p/er9x
8+
* gruvin9x - http://code.google.com/p/gruvin9x
9+
*
10+
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11+
*
12+
* This program is free software; you can redistribute it and/or modify
13+
* it under the terms of the GNU General Public License version 2 as
14+
* published by the Free Software Foundation.
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*/
21+
22+
#pragma once
23+
24+
#include "hostserialbackend.h"
25+
26+
#include <QSerialPort>
27+
28+
// HostSerialBackend implementation backed by a real QSerialPort
29+
// device (USB-serial adapter, native UART, ...). Mirrors the original
30+
// HostSerialConnector behaviour 1:1.
31+
class QSerialPortBackend : public HostSerialBackend
32+
{
33+
Q_OBJECT
34+
35+
public:
36+
QSerialPortBackend(const QString & portName, QObject * parent = nullptr);
37+
~QSerialPortBackend() override;
38+
39+
bool open() override;
40+
void close() override;
41+
bool isOpen() const override;
42+
43+
void write(const QByteArray & data) override;
44+
45+
void setBaudrate(quint32 baudrate) override;
46+
void setEncoding(quint8 encoding) override;
47+
48+
QString displayName() const override;
49+
50+
private:
51+
QSerialPort * port;
52+
};

0 commit comments

Comments
 (0)