Add arduino and abstract transport

This commit is contained in:
Simon Stürz 2021-11-14 13:40:06 +01:00 committed by Michael Zanetti
parent 1852044ef1
commit f7872915d0
12 changed files with 739 additions and 82 deletions

View File

@ -37,70 +37,104 @@
#include "network/zeroconf/zeroconfservicebrowser.h"
#include "network/zeroconf/zeroconfserviceentry.h"
#include "owlettcptransport.h"
#include "owletserialtransport.h"
#include <QColor>
#include <QTimer>
static QHash<ThingClassId, ParamTypeId> idParamTypeMap = {
{ digitalOutputThingClassId, digitalOutputThingOwletIdParamTypeId },
{ digitalInputThingClassId, digitalInputThingOwletIdParamTypeId },
{ ws2812ThingClassId, ws2812ThingOwletIdParamTypeId }
};
IntegrationPluginOwlet::IntegrationPluginOwlet()
{
}
void IntegrationPluginOwlet::init()
{
m_owletIdParamTypeMap.insert(digitalOutputThingClassId, digitalOutputThingOwletIdParamTypeId);
m_owletIdParamTypeMap.insert(digitalInputThingClassId, digitalInputThingOwletIdParamTypeId);
m_owletIdParamTypeMap.insert(ws2812ThingClassId, ws2812ThingOwletIdParamTypeId);
m_owletSerialPortParamTypeMap.insert(arduinoMiniProThingClassId, arduinoMiniProThingSerialPortParamTypeId);
m_zeroConfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_nymea-owlet._tcp");
}
void IntegrationPluginOwlet::discoverThings(ThingDiscoveryInfo *info)
{
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
qCDebug(dcOwlet()) << "Found owlet:" << entry;
ThingDescriptor descriptor(info->thingClassId(), entry.name(), entry.txt("platform"));
descriptor.setParams(ParamList() << Param(idParamTypeMap.value(info->thingClassId()), entry.txt("id")));
foreach (Thing *existingThing, myThings().filterByParam(idParamTypeMap.value(info->thingClassId()), entry.txt("id"))) {
descriptor.setThingId(existingThing->id());
break;
if (info->thingClassId() == arduinoMiniProThingClassId) {
// Discover serial ports for arduino bords
foreach(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
qCDebug(dcOwlet()) << "Found serial port" << port.systemLocation();
QString description = port.systemLocation() + " " + port.manufacturer() + " " + port.description();
ThingDescriptor thingDescriptor(info->thingClassId(), "Owlet Arduino Pro Mini", description);
ParamList parameters;
foreach (Thing *existingThing, myThings()) {
if (existingThing->paramValue(m_owletSerialPortParamTypeMap.value(info->thingClassId())).toString() == port.systemLocation()) {
thingDescriptor.setThingId(existingThing->id());
break;
}
}
parameters.append(Param(m_owletSerialPortParamTypeMap.value(info->thingClassId()), port.systemLocation()));
thingDescriptor.setParams(parameters);
info->addThingDescriptor(thingDescriptor);
}
info->addThingDescriptor(descriptor);
info->finish(Thing::ThingErrorNoError);
} else {
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
qCDebug(dcOwlet()) << "Found owlet:" << entry;
ThingDescriptor descriptor(info->thingClassId(), entry.name(), entry.txt("platform"));
descriptor.setParams(ParamList() << Param(m_owletIdParamTypeMap.value(info->thingClassId()), entry.txt("id")));
foreach (Thing *existingThing, myThings().filterByParam(m_owletIdParamTypeMap.value(info->thingClassId()), entry.txt("id"))) {
descriptor.setThingId(existingThing->id());
break;
}
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
}
info->finish(Thing::ThingErrorNoError);
}
void IntegrationPluginOwlet::setupThing(ThingSetupInfo *info)
{
Thing *thing = info->thing();
OwletTransport *transport = nullptr;
QHostAddress ip;
int port = 5555;
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
if (entry.txt("id") == info->thing()->paramValue(idParamTypeMap.value(info->thing()->thingClassId()))) {
ip = entry.hostAddress();
port = entry.port();
break;
if (thing->thingClassId() != arduinoMiniProThingClassId) {
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
if (entry.txt("id") == info->thing()->paramValue(m_owletIdParamTypeMap.value(info->thing()->thingClassId()))) {
ip = entry.hostAddress();
port = entry.port();
break;
}
}
}
// Try cached ip
if (ip.isNull()) {
pluginStorage()->beginGroup(thing->id().toString());
ip = QHostAddress(pluginStorage()->value("cachedIP").toString());
pluginStorage()->endGroup();
// Try cached ip
if (ip.isNull()) {
pluginStorage()->beginGroup(thing->id().toString());
ip = QHostAddress(pluginStorage()->value("cachedIP").toString());
pluginStorage()->endGroup();
}
if (ip.isNull()) {
qCWarning(dcOwlet()) << "Can't find owlet in the local network.";
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
transport = new OwletTcpTransport(ip, port, this);
} else if (thing->thingClassId() == arduinoMiniProThingClassId) {
QString serialPort = thing->paramValue(arduinoMiniProThingSerialPortParamTypeId).toString();
qCDebug(dcOwlet()) << "Setup arduino mini pro owlet on" << serialPort;
transport = new OwletSerialTransport(serialPort, 115200, this);
}
if (ip.isNull()) {
qCWarning(dcOwlet()) << "Can't find owlet in the local network.";
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
OwletClient *client = new OwletClient(this);
OwletClient *client = new OwletClient(transport, this);
connect(client, &OwletClient::connected, info, [=](){
qCDebug(dcOwlet()) << "Connected to owleet";
qCDebug(dcOwlet()) << "Connected to owlet";
m_clients.insert(thing, client);
if (thing->thingClassId() == digitalOutputThingClassId) {
@ -127,15 +161,31 @@ void IntegrationPluginOwlet::setupThing(ThingSetupInfo *info)
info->finish(Thing::ThingErrorNoError);
});
connect(client, &OwletClient::error, info, [=](){
info->finish(Thing::ThingErrorHardwareFailure);
});
connect(client, &OwletClient::connected, thing, [=](){
thing->setStateValue("connected", true);
pluginStorage()->beginGroup(thing->id().toString());
pluginStorage()->setValue("cachedIP", ip.toString());
pluginStorage()->endGroup();
// FIXME: find a better way
if (thing->thingClassId() != arduinoMiniProThingClassId) {
pluginStorage()->beginGroup(thing->id().toString());
pluginStorage()->setValue("cachedIP", ip.toString());
pluginStorage()->endGroup();
}
qCDebug(dcOwlet()) << "Sending get platform information request...";
int id = client->sendCommand("Platform.GetInformation");
connect(client, &OwletClient::replyReceived, thing, [=](int commandId, const QVariantMap &params){
if (id != commandId)
return;
qCDebug(dcOwlet()) << "Reply from owlet platform information:" << params;
});
});
connect(client, &OwletClient::disconnected, thing, [=](){
thing->setStateValue("connected", false);
});
@ -170,7 +220,7 @@ void IntegrationPluginOwlet::setupThing(ThingSetupInfo *info)
}
});
client->connectToHost(ip, port);
client->transport()->connectTransport();
}

View File

@ -56,8 +56,9 @@ public:
private:
ZeroConfServiceBrowser *m_zeroConfBrowser = nullptr;
QHash<Thing*, OwletClient*> m_clients;
QHash<Thing *, OwletClient *> m_clients;
QHash<ThingClassId, ParamTypeId> m_owletIdParamTypeMap;
QHash<ThingClassId, ParamTypeId> m_owletSerialPortParamTypeMap;
};
#endif // INTEGRATIONPLUGINOWLET_H

View File

@ -219,6 +219,286 @@
"writable": true
}
]
},
{
"id": "22f216f4-9715-48f9-ab76-f7d7436d49c9",
"name": "arduinoMiniPro",
"displayName": "Arduino Pro Mini Owlet",
"createMethods": ["user", "discovery"],
"interfaces": ["gateway", "connectable"],
"paramTypes": [
{
"id": "589715a6-aaf7-4ffb-9c34-015ac22d527e",
"name": "serialPort",
"displayName": "Serial port",
"type": "QString",
"inputType": "TextLine",
"defaultValue": "/dev/ttyS0"
},
{
"id": "d9643551-883a-4e33-89a8-6e2e1211eb22",
"name": "resetGpio",
"displayName": "Reset GPIO",
"type": "uint",
"defaultValue": 18
}
],
"settingsTypes": [
{
"id": "82a8d0f5-3b42-4138-ae65-8554e19b73e5",
"name": "pin2",
"displayName": "Pin 2",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Interrupt"
],
"defaultValue": "None"
},
{
"id": "3953ad67-69a6-4b5f-8a91-f913d75d7d2f",
"name": "pin3",
"displayName": "Pin 3",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"PWM",
"Interrupt"
],
"defaultValue": "None"
},
{
"id": "cee570df-1669-49df-9eb6-6c28c9cb7aec",
"name": "pin4",
"displayName": "Pin 4",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output"
],
"defaultValue": "None"
},
{
"id": "ec366d87-cfdb-4c7e-a23e-20cb8e99b1f5",
"name": "pin5",
"displayName": "Pin 5",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"PWM"
],
"defaultValue": "None"
},
{
"id": "40354097-c5e5-4d13-b94c-72cb7a97cf71",
"name": "pin6",
"displayName": "Pin 6",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"PWM"
],
"defaultValue": "None"
},
{
"id": "22e5320f-2f34-4fd5-8699-1e4ddf96a8c8",
"name": "pin7",
"displayName": "Pin 7",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output"
],
"defaultValue": "None"
},
{
"id": "9b7b159c-9da1-4811-80e1-835d7743bebc",
"name": "pin8",
"displayName": "Pin 8",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output"
],
"defaultValue": "None"
},
{
"id": "0d4aa38d-7607-4361-b8c7-cc5c28e17bb8",
"name": "pin9",
"displayName": "Pin 9",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"PWM"
],
"defaultValue": "None"
},
{
"id": "d18e6ac5-3bf7-47ac-8b5b-70a9ef8394d5",
"name": "pin10",
"displayName": "Pin 10",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"PWM"
],
"defaultValue": "None"
},
{
"id": "f0afb81c-dcd4-4d50-84a7-0ed6739c4011",
"name": "pin11",
"displayName": "Pin 11",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"PWM"
],
"defaultValue": "None"
},
{
"id": "c62ab191-40ab-4d20-8130-a6b37801b984",
"name": "pin12",
"displayName": "Pin 12",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output"
],
"defaultValue": "None"
},
{
"id": "4522ce36-ba6f-46b0-a54b-410a93065b34",
"name": "pin13",
"displayName": "Pin 13 (LED)",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output"
],
"defaultValue": "None"
},
{
"id": "d6cf8433-acef-4312-836b-b34be6592e22",
"name": "pinA1",
"displayName": "Pin A1",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Analog Input"
],
"defaultValue": "None"
},
{
"id": "e22fd058-8eab-4450-a2ef-2f85c347602c",
"name": "pinA2",
"displayName": "Pin A2",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Analog Input"
],
"defaultValue": "None"
},
{
"id": "1702602e-6c05-4dea-b0ff-89af8ec63a88",
"name": "pinA3",
"displayName": "Pin A3",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Analog Input"
],
"defaultValue": "None"
},
{
"id": "02b5022f-8892-4e9d-b11e-6fd8a9d4616f",
"name": "pinA4",
"displayName": "Pin A4",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Analog Input"
],
"defaultValue": "None"
},
{
"id": "704e2a48-b1f4-400e-a378-d7e546f2083d",
"name": "pinA5",
"displayName": "Pin A5",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Analog Input"
],
"defaultValue": "None"
},
{
"id": "69c85170-9447-4a01-acd2-926fbe03489f",
"name": "pinA6",
"displayName": "Pin A6",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Analog Input"
],
"defaultValue": "None"
},
{
"id": "3ad3b667-b51f-4deb-b5d3-8cad1e0fdbba",
"name": "pinA7",
"displayName": "Pin A7",
"type": "QString",
"allowedValues": [
"None",
"Input",
"Output",
"Analog Input"
],
"defaultValue": "None"
}
],
"stateTypes": [
{
"id": "9a7d9a6a-f131-4f18-bfc0-956c2dba9329",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
}
]
}
]
}

View File

@ -1,13 +1,19 @@
include(../plugins.pri)
QT += network
QT += network serialport
SOURCES += \
integrationpluginowlet.cpp \
owletclient.cpp
owletclient.cpp \
owletserialtransport.cpp \
owlettcptransport.cpp \
owlettransport.cpp
HEADERS += \
integrationpluginowlet.h \
owletclient.h
owletclient.h \
owletserialtransport.h \
owlettcptransport.h \
owlettransport.h

View File

@ -1,49 +1,33 @@
#include "owletclient.h"
#include "owlettransport.h"
#include "extern-plugininfo.h"
#include <QJsonDocument>
#include <QTimer>
OwletClient::OwletClient(QObject *parent) : QObject(parent)
OwletClient::OwletClient(OwletTransport *transport, QObject *parent) :
QObject(parent),
m_transport(transport)
{
connect(m_transport, &OwletTransport::dataReceived, this, &OwletClient::dataReceived);
connect(m_transport, &OwletTransport::error, this, &OwletClient::error);
connect(m_transport, &OwletTransport::connectedChanged, this, [=](bool isConnected){
if (isConnected) {
emit connected();
} else {
emit disconnected();
}
});
}
void OwletClient::connectToHost(const QHostAddress &address, int port)
OwletTransport *OwletClient::transport() const
{
if (m_socket) {
m_socket->abort();
m_socket->deleteLater();
}
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::connected, this, [this](){
emit connected();
});
connect(m_socket, &QTcpSocket::disconnected, this, [this, address, port](){
qCDebug(dcOwlet()) << "Disconnected from owleet";
emit disconnected();
QTimer::singleShot(1000, this, [=]{
connectToHost(address, port);
});
});
typedef void (QTcpSocket:: *errorSignal)(QAbstractSocket::SocketError);
connect(m_socket, static_cast<errorSignal>(&QTcpSocket::error), this, [this](){
qCDebug(dcOwlet()) << "Error in owlet communication";
emit error();
});
connect(m_socket, &QTcpSocket::readyRead, this, [this](){
dataReceived(m_socket->readAll());
});
m_socket->connectToHost(address, port);
return m_transport;
}
int OwletClient::sendCommand(const QString &method, const QVariantMap &params)
{
if (!m_socket) {
if (!m_transport->connected()) {
qCWarning(dcOwlet()) << "Not connected to owlet. Not sending command.";
return -1;
}
@ -54,7 +38,7 @@ int OwletClient::sendCommand(const QString &method, const QVariantMap &params)
packet.insert("id", id);
packet.insert("method", method);
packet.insert("params", params);
m_socket->write(QJsonDocument::fromVariant(packet).toJson(QJsonDocument::Compact));
m_transport->sendData(QJsonDocument::fromVariant(packet).toJson(QJsonDocument::Compact));
return id;
}

View File

@ -5,15 +5,17 @@
#include <QHostAddress>
#include <QTcpSocket>
class OwletTransport;
class OwletClient : public QObject
{
Q_OBJECT
public:
explicit OwletClient(QObject *parent = nullptr);
explicit OwletClient(OwletTransport *transport, QObject *parent = nullptr);
void connectToHost(const QHostAddress &address, int port);
OwletTransport *transport() const;
int sendCommand(const QString &method, const QVariantMap &params);
int sendCommand(const QString &method, const QVariantMap &params = QVariantMap());
signals:
void connected();
@ -27,7 +29,7 @@ private slots:
void dataReceived(const QByteArray &data);
private:
QTcpSocket *m_socket = nullptr;
OwletTransport *m_transport = nullptr;
int m_commandId = 0;
QByteArray m_receiveBuffer;

View File

@ -0,0 +1,168 @@
#include "owletserialtransport.h"
#include "owlettransport.h"
#include "extern-plugininfo.h"
#include <QDataStream>
OwletSerialTransport::OwletSerialTransport(const QString &serialPortName, uint baudrate, QObject *parent) :
OwletTransport(parent),
m_serialPortName(serialPortName),
m_baudrate(baudrate)
{
qRegisterMetaType<QSerialPort::SerialPortError>();
m_serialPort = new QSerialPort(this);
m_serialPort->setPortName(serialPortName);
m_serialPort->setBaudRate(115200);
m_serialPort->setDataBits(QSerialPort::DataBits::Data8);
m_serialPort->setParity(QSerialPort::Parity::NoParity);
m_serialPort->setStopBits(QSerialPort::StopBits::OneStop);
m_serialPort->setFlowControl(QSerialPort::FlowControl::NoFlowControl);
connect(m_serialPort, &QSerialPort::readyRead, this, &OwletSerialTransport::onReadyRead);
connect(m_serialPort, &QSerialPort::errorOccurred, this, [=](QSerialPort::SerialPortError serialPortError){
if (serialPortError != QSerialPort::NoError) {
qCWarning(dcOwlet()) << "Serial port error occured" << serialPortError << m_serialPort->errorString();
emit error();
m_reconnectTimer->start();
if (m_serialPort->isOpen()) {
m_serialPort->close();
}
emit connectedChanged(false);
}
});
m_reconnectTimer = new QTimer(this);
m_reconnectTimer->setInterval(5000);
m_reconnectTimer->setSingleShot(false);
connect(m_reconnectTimer, &QTimer::timeout, this, [=](){
if (m_serialPort->isOpen()) {
m_reconnectTimer->stop();
return;
} else {
connectTransport();
}
});
}
bool OwletSerialTransport::connected() const
{
return m_serialPort->isOpen();
}
void OwletSerialTransport::sendData(const QByteArray &data)
{
// Stream bytes using SLIP
QByteArray message;
QDataStream stream(&message, QIODevice::WriteOnly);
stream << static_cast<quint8>(SlipProtocolEnd);
for (int i = 0; i < data.length(); i++) {
quint8 dataByte = data.at(i);
switch (dataByte) {
case SlipProtocolEnd:
stream << static_cast<quint8>(SlipProtocolEsc);
stream << static_cast<quint8>(SlipProtocolTransposedEnd);
break;
case SlipProtocolEsc:
stream << static_cast<quint8>(SlipProtocolEsc);
stream << static_cast<quint8>(SlipProtocolTransposedEsc);
break;
default:
stream << dataByte;
break;
}
}
stream << static_cast<quint8>(SlipProtocolEnd);
qCDebug(dcOwlet()) << "UART -->" << qUtf8Printable(data) << message.toHex();
m_serialPort->write(message);
m_serialPort->flush();
}
void OwletSerialTransport::connectTransport()
{
if (m_serialPort->isOpen())
return;
qCDebug(dcOwlet()) << "Connecting to" << m_serialPortName;
bool serialPortFound = false;
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
if (serialPortInfo.systemLocation() == m_serialPortName) {
serialPortFound = true;
break;
}
}
// Prevent repeating warnings...
if (!serialPortFound) {
if (!m_reconnectTimer->isActive()) {
m_reconnectTimer->start();
}
return;
}
if (!m_serialPort->open(QIODevice::ReadWrite)) {
qCWarning(dcOwlet()) << "Could not open serial port on" << m_serialPortName << m_serialPort->errorString();
m_reconnectTimer->start();
return;
}
m_reconnectTimer->stop();
emit connectedChanged(true);
}
void OwletSerialTransport::disconnectTransport()
{
if (m_serialPort->isOpen()) {
m_serialPort->close();
emit connectedChanged(false);
}
}
void OwletSerialTransport::onReadyRead()
{
QByteArray data = m_serialPort->readAll();
qCDebug(dcOwlet()) << "UART <-- raw:" << data.toHex() << qUtf8Printable(data);
for (int i = 0; i < data.length(); i++) {
quint8 receivedByte = data.at(i);
if (m_protocolEscaping) {
switch (receivedByte) {
case SlipProtocolTransposedEnd:
m_buffer.append(static_cast<quint8>(SlipProtocolEnd));
m_protocolEscaping = false;
break;
case SlipProtocolTransposedEsc:
m_buffer.append(static_cast<quint8>(SlipProtocolEsc));
m_protocolEscaping = false;
break;
default:
// SLIP protocol violation...received escape, but it is not an escaped byte
break;
}
}
switch (receivedByte) {
case SlipProtocolEnd:
// We are done with this package, process it and reset the buffer
if (!m_buffer.isEmpty() && m_buffer.length() >= 3) {
qCDebug(dcOwlet()) << "UART <--" << m_buffer.toHex() << qUtf8Printable(m_buffer);
emit dataReceived(m_buffer);
}
m_buffer.clear();
m_protocolEscaping = false;
break;
case SlipProtocolEsc:
// The next byte will be escaped, lets wait for it
m_protocolEscaping = true;
break;
default:
// Nothing special, just add to buffer
m_buffer.append(receivedByte);
break;
}
}
}

View File

@ -0,0 +1,45 @@
#ifndef OWLETSERIALTRANSPORT_H
#define OWLETSERIALTRANSPORT_H
#include <QObject>
#include <QTimer>
#include <QSerialPort>
#include <QSerialPortInfo>
#include "owlettransport.h"
class OwletSerialTransport : public OwletTransport
{
Q_OBJECT
public:
explicit OwletSerialTransport(const QString &serialPortName, uint baudrate, QObject *parent = nullptr);
bool connected() const override;
void sendData(const QByteArray &data) override;
public slots:
void connectTransport() override;
void disconnectTransport() override;
private slots:
void onReadyRead();
private:
enum SlipProtocol {
SlipProtocolEnd = 0xC0,
SlipProtocolEsc = 0xDB,
SlipProtocolTransposedEnd = 0xDC,
SlipProtocolTransposedEsc = 0xDD
};
QSerialPort *m_serialPort = nullptr;
QTimer *m_reconnectTimer = nullptr;
QString m_serialPortName;
uint m_baudrate;
QByteArray m_buffer;
bool m_protocolEscaping = false;
};
#endif // OWLETSERIALTRANSPORT_H

View File

@ -0,0 +1,51 @@
#include "owlettcptransport.h"
#include "extern-plugininfo.h"
#include <QTimer>
OwletTcpTransport::OwletTcpTransport(const QHostAddress &hostAddress, quint16 port, QObject *parent) :
OwletTransport(parent),
m_socket(new QTcpSocket(this)),
m_hostAddress(hostAddress),
m_port(port)
{
connect(m_socket, &QTcpSocket::connected, this, [=](){
emit connectedChanged(true);
});
connect(m_socket, &QTcpSocket::disconnected, this, [=](){
qCDebug(dcOwlet()) << "TCP transport: Disconnected from owlet" << QString("%1:%2").arg(m_hostAddress.toString()).arg(m_port);
emit connectedChanged(false);
QTimer::singleShot(1000, this, &OwletTcpTransport::connectTransport);
});
typedef void (QTcpSocket:: *errorSignal)(QAbstractSocket::SocketError);
connect(m_socket, static_cast<errorSignal>(&QTcpSocket::error), this, [this](){
qCDebug(dcOwlet()) << "TCP transport: Error in owlet communication" << m_socket->errorString();
emit error();
});
connect(m_socket, &QTcpSocket::readyRead, this, [this](){
emit dataReceived(m_socket->readAll());
});
}
bool OwletTcpTransport::connected() const
{
return m_socket->state() == QAbstractSocket::ConnectedState;
}
void OwletTcpTransport::sendData(const QByteArray &data)
{
m_socket->write(data);
}
void OwletTcpTransport::connectTransport()
{
qCDebug(dcOwlet()) << "Connecting to" << m_hostAddress << m_port;
m_socket->connectToHost(m_hostAddress, m_port);
}
void OwletTcpTransport::disconnectTransport()
{
m_socket->close();
}

30
owlet/owlettcptransport.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef OWLETTCPTRANSPORT_H
#define OWLETTCPTRANSPORT_H
#include <QObject>
#include <QHostAddress>
#include <QTcpSocket>
#include "owlettransport.h"
class OwletTcpTransport : public OwletTransport
{
Q_OBJECT
public:
explicit OwletTcpTransport(const QHostAddress &hostAddress, quint16 port, QObject *parent = nullptr);
bool connected() const override;
void sendData(const QByteArray &data) override;
public slots:
void connectTransport() override;
void disconnectTransport() override;
private:
QTcpSocket *m_socket = nullptr;
QHostAddress m_hostAddress;
quint16 m_port;
};
#endif // OWLETTCPTRANSPORT_H

11
owlet/owlettransport.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "owlettransport.h"
OwletTransport::OwletTransport(QObject *parent) : QObject(parent)
{
}
bool OwletTransport::connected() const
{
return m_connected;
}

29
owlet/owlettransport.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef OWLETTRANSPORT_H
#define OWLETTRANSPORT_H
#include <QObject>
class OwletTransport : public QObject
{
Q_OBJECT
public:
explicit OwletTransport(QObject *parent = nullptr);
virtual bool connected() const;
virtual void sendData(const QByteArray &data) = 0;
public slots:
virtual void connectTransport() = 0;
virtual void disconnectTransport() = 0;
signals:
void connectedChanged(bool connected);
void dataReceived(const QByteArray &data);
void error();
protected:
bool m_connected;
};
#endif // OWLETTRANSPORT_H