AdvancedControllerRemoteCPP/lib/controllerlink.h

85 lines
3.3 KiB
C++

// controllerlink.h - one controller for a GUI application: a RemoteClient in its own thread,
// the results as Qt signals (delivered in the thread of the ControllerLink object, normally
// the GUI thread). One ControllerLink per serial port.
//
// After open() the link detects the controller (PING, then ID), polls the keyboard leds
// (LEDS, 5 times a second) and executes the command lines given to send() one after the
// other (stop-and-wait). Link state:
// Closed - the port is closed
// NoLink - the port is open, the controller does not answer (detection repeated every 2 s)
// Link - connected
// 3 requests in a row without an answer = link lost: lost(), state NoLink, detection again.
// When the port fails (e.g. the USB adapter was unplugged) the link closes: error(), closed().
//
// Example
// auto *link = new AdvCtrl::ControllerLink(this);
// connect(link, &AdvCtrl::ControllerLink::stateChanged, this, &MyWidget::showLinkState);
// connect(link, &AdvCtrl::ControllerLink::reply, this,
// [](const QString &command, const QString &result) { qDebug() << command << result; });
// link->open("/dev/ttyUSB0");
// link->send("CAM 2");
// link->send("BR 12");
#ifndef ADVCTRL_CONTROLLERLINK_H
#define ADVCTRL_CONTROLLERLINK_H
#include "remoteclient.h"
#include <QObject>
#include <QString>
namespace AdvCtrl {
class LinkThread;
class ControllerLink : public QObject
{
Q_OBJECT
public:
enum State { Closed, NoLink, Link };
Q_ENUM(State)
static constexpr int LedsPeriodMs = 200; // LEDS polling
static constexpr int DetectRetryMs = 2000; // detection retry while not detected
static constexpr int LostAfter = 3; // requests in a row without an answer -> link lost
explicit ControllerLink(QObject *parent = nullptr);
~ControllerLink() override; // stops the thread and closes the port
State state() const;
QString portName() const; // port of the running link, "" when closed
public slots:
void open(const QString &portName, int baudRate = RemoteClient::DefaultBaudRate);
void close(); // closed() follows when the port is released
void send(const QString &commandLine); // the result comes as reply(commandLine, result)
signals:
void stateChanged(AdvCtrl::ControllerLink::State state);
void detected(const QString &firmware, const QString &cameras, const QString &uid);
void notDetected(); // a detection attempt failed (retried every 2 s)
void lost(); // 3 requests in a row without an answer
void leds(quint32 mask); // keyboard leds, bit order = RemoteClient::LedNames
// result: "OK[ data]", "ERR <code> <text>" or "!! <why there is no reply>"
void reply(const QString &commandLine, const QString &result);
void error(const QString &message);
void closed();
private:
friend class LinkThread;
void setState(State state);
void handleDetected(const QString &firmware, const QString &cameras, const QString &uid);
void handleNotDetected();
void handleLost();
void handleClosed();
LinkThread *m_thread = nullptr;
State m_state = Closed;
QString m_portName;
};
} // namespace AdvCtrl
#endif // ADVCTRL_CONTROLLERLINK_H