Merge PR #143: TcpCommander: Fixed input and output device class
commit
78bbf7f35b
|
|
@ -1,3 +1,34 @@
|
|||
# TCP commander
|
||||
|
||||
This plugin is a generic approach to allow sending and receiving custom TCP packages in a network.
|
||||
This plugin is a generic approach to allow sending and receiving custom TCP packages.
|
||||
|
||||
> Note: This plugin is ment to be combined with a rule.
|
||||
|
||||
## TCP output
|
||||
|
||||
The TCP output opens a TCP connection to the given host IPv4 address and port everytime the output trigger gets activated. As soon
|
||||
as the command has been executed the socket will close again. The connected state is only stated as connected
|
||||
as long as the connection is active.
|
||||
|
||||
## TCP input
|
||||
|
||||
The TCP input creates a TCP server on the given port.
|
||||
|
||||
Be aware that only a single connection can be established simultaneously. The connected state is active as long as
|
||||
a client is connected. It is up to the client to deside how long the connection stays active.
|
||||
|
||||
## Example
|
||||
|
||||
If you create a TCP Input on port 2323 and with the command `"Light 1 ON"`, following command will trigger an event in nymea and allows you to connect this event with a rule.
|
||||
|
||||
> Note: In this example nymea is running on `localhost`
|
||||
|
||||
$ echo "Light 1 ON" | nc localhost 2323
|
||||
OK
|
||||
|
||||
If you create a TCP output on port 2324 and IP address 127.0.0.1, send in nymea the command `"Light 1 is ON"` and Netcat (nc) will receive and display your command.
|
||||
|
||||
> Note: the command is running on `localhost`
|
||||
|
||||
$ while :; do nc -l -p 2324; sleep 1; done
|
||||
Light 1 is ON
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2017 Bernhard Trinnes <bernhard.trinnes@guh.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
|
|
@ -26,14 +26,27 @@ DevicePluginTcpCommander::DevicePluginTcpCommander()
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
Device::DeviceSetupStatus DevicePluginTcpCommander::setupDevice(Device *device)
|
||||
{
|
||||
if (device->deviceClassId() == tcpOutputDeviceClassId) {
|
||||
QTcpSocket *tcpSocket = new QTcpSocket(this);
|
||||
|
||||
quint16 port = device->paramValue(tcpOutputDevicePortParamTypeId).toUInt();
|
||||
QHostAddress address= QHostAddress(device->paramValue(tcpOutputDeviceIpv4addressParamTypeId).toString());
|
||||
TcpSocket *tcpSocket = new TcpSocket(address, port, this);
|
||||
m_tcpSockets.insert(tcpSocket, device);
|
||||
connect(tcpSocket, &QTcpSocket::connected, this, &DevicePluginTcpCommander::onTcpSocketConnected);
|
||||
connect(tcpSocket, &QTcpSocket::disconnected, this, &DevicePluginTcpCommander::onTcpSocketDisconnected);
|
||||
connect(tcpSocket, &QTcpSocket::bytesWritten, this, &DevicePluginTcpCommander::onTcpSocketBytesWritten);
|
||||
connect(tcpSocket, &TcpSocket::connectionChanged, this, &DevicePluginTcpCommander::onTcpSocketConnectionChanged);
|
||||
connect(tcpSocket, &TcpSocket::commandSent, this, &DevicePluginTcpCommander::onTcpSocketCommandSent);
|
||||
connect(tcpSocket, &TcpSocket::connectionTestFinished, this, [this, device] (bool status) {
|
||||
|
||||
if (status) {
|
||||
emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess);
|
||||
} else {
|
||||
emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure);
|
||||
}
|
||||
});
|
||||
tcpSocket->connectionTest();
|
||||
// Test the socket, if a socket can be established the setup process was successfull
|
||||
return Device::DeviceSetupStatusAsync;
|
||||
}
|
||||
|
||||
|
|
@ -43,8 +56,8 @@ Device::DeviceSetupStatus DevicePluginTcpCommander::setupDevice(Device *device)
|
|||
|
||||
if (tcpServer->isValid()) {
|
||||
m_tcpServer.insert(tcpServer, device);
|
||||
connect(tcpServer, &TcpServer::connected, this, &DevicePluginTcpCommander::onTcpServerConnected);
|
||||
connect(tcpServer, &TcpServer::disconnected, this, &DevicePluginTcpCommander::onTcpServerDisconnected);
|
||||
connect(tcpServer, &TcpServer::connectionChanged, this, &DevicePluginTcpCommander::onTcpServerConnectionChanged);
|
||||
connect(tcpServer, &TcpServer::commandReceived, this, &DevicePluginTcpCommander::onTcpServerCommandReceived);
|
||||
return Device::DeviceSetupStatusSuccess;
|
||||
} else {
|
||||
tcpServer->deleteLater();
|
||||
|
|
@ -60,11 +73,11 @@ Device::DeviceError DevicePluginTcpCommander::executeAction(Device *device, cons
|
|||
if (device->deviceClassId() == tcpOutputDeviceClassId) {
|
||||
|
||||
if (action.actionTypeId() == tcpOutputTriggerActionTypeId) {
|
||||
int port = device->paramValue(tcpOutputDevicePortParamTypeId).toInt();
|
||||
QHostAddress address= QHostAddress(device->paramValue(tcpOutputDeviceIpv4addressParamTypeId).toString());
|
||||
QTcpSocket *tcpSocket = m_tcpSockets.key(device);
|
||||
tcpSocket->connectToHost(address, port);
|
||||
return Device::DeviceErrorNoError;
|
||||
TcpSocket *tcpSocket = m_tcpSockets.key(device);
|
||||
QByteArray data = action.param(tcpOutputTriggerActionOutputDataAreaParamTypeId).value().toByteArray();
|
||||
tcpSocket->sendCommand(data);
|
||||
m_pendingActions.insert(action.id(), device->id());
|
||||
return Device::DeviceErrorAsync;
|
||||
}
|
||||
return Device::DeviceErrorActionTypeNotFound;
|
||||
}
|
||||
|
|
@ -76,11 +89,11 @@ void DevicePluginTcpCommander::deviceRemoved(Device *device)
|
|||
{
|
||||
if(device->deviceClassId() == tcpOutputDeviceClassId){
|
||||
|
||||
QTcpSocket *tcpSocket = m_tcpSockets.key(device);
|
||||
TcpSocket *tcpSocket = m_tcpSockets.key(device);
|
||||
m_tcpSockets.remove(tcpSocket);
|
||||
tcpSocket->deleteLater();
|
||||
|
||||
}else if(device->deviceClassId() == tcpInputDeviceClassId){
|
||||
} else if(device->deviceClassId() == tcpInputDeviceClassId){
|
||||
|
||||
TcpServer *tcpServer = m_tcpServer.key(device);
|
||||
m_tcpServer.remove(tcpServer);
|
||||
|
|
@ -89,105 +102,49 @@ void DevicePluginTcpCommander::deviceRemoved(Device *device)
|
|||
}
|
||||
|
||||
|
||||
void DevicePluginTcpCommander::onTcpSocketConnected()
|
||||
void DevicePluginTcpCommander::onTcpSocketConnectionChanged(bool connected)
|
||||
{
|
||||
QTcpSocket *tcpSocket = static_cast<QTcpSocket *>(sender());
|
||||
TcpSocket *tcpSocket = static_cast<TcpSocket *>(sender());
|
||||
Device *device = m_tcpSockets.value(tcpSocket);
|
||||
if (device->deviceClassId() == tcpOutputDeviceClassId) {
|
||||
if (!device->setupComplete()) {
|
||||
qDebug(dcTCPCommander()) << device->name() << "Setup finished" ;
|
||||
emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess);
|
||||
} else {
|
||||
QByteArray data = device->paramValue(tcpOutputTriggerActionOutputDataAreaParamTypeId).toByteArray();
|
||||
tcpSocket->write(data);
|
||||
}
|
||||
device->setStateValue(tcpOutputConnectedStateTypeId, true);
|
||||
}
|
||||
if (device->deviceClassId() == tcpInputDeviceClassId) {
|
||||
if (!device->setupComplete()) {
|
||||
qDebug(dcTCPCommander()) << device->name() << "Setup finished" ;
|
||||
emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess);
|
||||
}
|
||||
device->setStateValue(tcpInputConnectedStateTypeId, true);
|
||||
device->setStateValue(tcpOutputConnectedStateTypeId, connected);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DevicePluginTcpCommander::onTcpSocketDisconnected()
|
||||
void DevicePluginTcpCommander::onTcpSocketCommandSent(bool successfull)
|
||||
{
|
||||
QTcpSocket *tcpSocket = static_cast<QTcpSocket *>(sender());
|
||||
TcpSocket *tcpSocket = static_cast<TcpSocket *>(sender());
|
||||
Device *device = m_tcpSockets.value(tcpSocket);
|
||||
if (device->deviceClassId() == tcpInputDeviceClassId) {
|
||||
device->setStateValue(tcpInputConnectedStateTypeId, false);
|
||||
} else if (device->deviceClassId() == tcpOutputDeviceClassId) {
|
||||
device->setStateValue(tcpOutputConnectedStateTypeId, false);
|
||||
|
||||
ActionId action = m_pendingActions.key(device->id());
|
||||
m_pendingActions.remove(action);
|
||||
if (successfull) {
|
||||
emit actionExecutionFinished(action, Device::DeviceErrorNoError);
|
||||
} else {
|
||||
emit actionExecutionFinished(action, Device::DeviceErrorHardwareNotAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DevicePluginTcpCommander::onTcpSocketBytesWritten()
|
||||
{
|
||||
QTcpSocket *tcpSocket = static_cast<QTcpSocket *>(sender());
|
||||
tcpSocket->close();
|
||||
}
|
||||
|
||||
void DevicePluginTcpCommander::onTcpServerConnected()
|
||||
void DevicePluginTcpCommander::onTcpServerConnectionChanged(bool connected)
|
||||
{
|
||||
TcpServer *tcpServer = static_cast<TcpServer *>(sender());
|
||||
Device *device = m_tcpServer.value(tcpServer);
|
||||
qDebug(dcTCPCommander()) << device->name() << "Tcp Server Client connected" ;
|
||||
if (device->deviceClassId() == tcpInputDeviceClassId) {
|
||||
device->setStateValue(tcpInputConnectedStateTypeId, true);
|
||||
} else if (device->deviceClassId() == tcpOutputDeviceClassId) {
|
||||
device->setStateValue(tcpOutputConnectedStateTypeId, true);
|
||||
}
|
||||
|
||||
connect(tcpServer, &TcpServer::textMessageReceived, this, &DevicePluginTcpCommander::onTcpServerTextMessageReceived);
|
||||
//send signal device Setup was successful
|
||||
}
|
||||
|
||||
|
||||
void DevicePluginTcpCommander::onTcpServerDisconnected()
|
||||
{
|
||||
TcpServer *tcpServer = static_cast<TcpServer *>(sender());
|
||||
Device *device = m_tcpServer.value(tcpServer);
|
||||
qDebug(dcTCPCommander()) << device->name() << "Tcp Server Client disconnected" ;
|
||||
if (device->deviceClassId() == tcpInputDeviceClassId) {
|
||||
device->setStateValue(tcpInputConnectedStateTypeId, false);
|
||||
} else if (device->deviceClassId() == tcpOutputDeviceClassId) {
|
||||
device->setStateValue(tcpOutputConnectedStateTypeId, false);
|
||||
device->setStateValue(tcpInputConnectedStateTypeId, connected);
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginTcpCommander::onTcpServerTextMessageReceived(QByteArray data)
|
||||
void DevicePluginTcpCommander::onTcpServerCommandReceived(QByteArray data)
|
||||
{
|
||||
TcpServer *tcpServer = static_cast<TcpServer *>(sender());
|
||||
Device *device = m_tcpServer.value(tcpServer);
|
||||
qDebug(dcTCPCommander()) << device->name() << "Message received" << data;
|
||||
device->setStateValue(tcpInputDataReceivedStateTypeId, data);
|
||||
|
||||
if (device->paramValue(tcpInputDeviceComparisionParamTypeId).toString() == "Is exactly") {
|
||||
qDebug(dcTCPCommander()) << "is exactly";
|
||||
if (data == device->paramValue(tcpInputDeviceInputDataParamTypeId)) {
|
||||
qDebug(dcTCPCommander()) << "comparison successful";
|
||||
emitEvent(Event(tcpInputTriggeredEventTypeId, device->id()));
|
||||
}
|
||||
|
||||
} else if (device->paramValue(tcpInputDeviceComparisionParamTypeId).toString() == "Contains") {
|
||||
if (data.contains(device->paramValue(tcpInputDeviceInputDataParamTypeId).toByteArray())) {
|
||||
emitEvent(Event(tcpInputTriggeredEventTypeId, device->id()));
|
||||
}
|
||||
|
||||
} else if (device->paramValue(tcpInputDeviceComparisionParamTypeId) == "Contains not") {
|
||||
if (!data.contains(device->paramValue(tcpInputDeviceInputDataParamTypeId).toByteArray()))
|
||||
emitEvent(Event(tcpInputTriggeredEventTypeId, device->id()));
|
||||
|
||||
} else if (device->paramValue(tcpInputDeviceComparisionParamTypeId) == "Starts with") {
|
||||
if (data.startsWith(device->paramValue(tcpInputDeviceInputDataParamTypeId).toByteArray()))
|
||||
emitEvent(Event(tcpInputTriggeredEventTypeId, device->id()));
|
||||
|
||||
} else if (device->paramValue(tcpInputDeviceComparisionParamTypeId) == "Ends with") {
|
||||
if (data.endsWith(device->paramValue(tcpInputDeviceInputDataParamTypeId).toByteArray()))
|
||||
emitEvent(Event(tcpInputTriggeredEventTypeId, device->id()));
|
||||
}
|
||||
Event event = Event(tcpInputTriggeredEventTypeId, device->id());
|
||||
ParamList params;
|
||||
params.append(Param(tcpInputTriggeredEventDataParamTypeId, data));
|
||||
event.setParams(params);
|
||||
emitEvent(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2017 Bernhard Trinnes <bernhard.trinnes@guh.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "devices/deviceplugin.h"
|
||||
#include "tcpserver.h"
|
||||
#include "tcpsocket.h"
|
||||
|
||||
class DevicePluginTcpCommander : public DevicePlugin
|
||||
{
|
||||
|
|
@ -41,18 +42,16 @@ public:
|
|||
Device::DeviceError executeAction(Device *device, const Action &action) override;
|
||||
|
||||
private:
|
||||
QHash<QTcpSocket *, Device *> m_tcpSockets;
|
||||
QHash<TcpSocket *, Device *> m_tcpSockets;
|
||||
QHash<TcpServer *, Device *> m_tcpServer;
|
||||
QHash<ActionId, DeviceId> m_pendingActions;
|
||||
|
||||
private slots:
|
||||
void onTcpSocketConnected();
|
||||
void onTcpSocketDisconnected();
|
||||
void onTcpSocketBytesWritten();
|
||||
|
||||
void onTcpServerConnected();
|
||||
void onTcpServerDisconnected();
|
||||
void onTcpServerTextMessageReceived(QByteArray message);
|
||||
void onTcpSocketConnectionChanged(bool connected);
|
||||
void onTcpSocketCommandSent(bool successfulle);
|
||||
|
||||
void onTcpServerConnectionChanged(bool connected);
|
||||
void onTcpServerCommandReceived(QByteArray message);
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINTCPCOMMANDER_H
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
"id": "741b7b0a-0c9c-4c93-be99-0d0bcf5a4643",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "tcpCommander",
|
||||
"displayName": "TCP Commander",
|
||||
"id": "9181278e-7812-4a3e-a9ce-f00f3f8b8afd",
|
||||
"name": "nymea",
|
||||
"displayName": "nymea",
|
||||
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"id": "c67d059f-694f-47cb-8e1d-9e3e6d014c1a",
|
||||
|
|
@ -35,10 +35,10 @@
|
|||
{
|
||||
"id": "725b541a-9e0c-4634-81eb-e415c0b8f025",
|
||||
"name": "connected",
|
||||
"displayName": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"displayNameEvent": "connection status changed"
|
||||
"displayNameEvent": "Connection status changed"
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
|
|
@ -71,53 +71,23 @@
|
|||
"displayName": "Port",
|
||||
"type": "int",
|
||||
"defaultValue": "22"
|
||||
},
|
||||
{
|
||||
"id": "d99f55c7-0e14-45ee-b0f0-33f2d1d2e674",
|
||||
"name": "comparision",
|
||||
"displayName": "Data Comparison",
|
||||
"type": "QString",
|
||||
"allowedValues": [
|
||||
"Is exactly",
|
||||
"Contains",
|
||||
"Contains not",
|
||||
"Starts with",
|
||||
"Ends with"
|
||||
],
|
||||
"defaultValue": "Exactly"
|
||||
},
|
||||
{
|
||||
"id": "23051bdf-3f50-41fa-abde-bc4fe0bcc4fc",
|
||||
"name": "inputData",
|
||||
"displayName": "Command",
|
||||
"type": "QString",
|
||||
"inputType": "TextArea",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "a2eb1619-261c-45ee-9587-6b5994633ad0",
|
||||
"name": "connected",
|
||||
"displayName": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"displayNameEvent": "connection status changed"
|
||||
},
|
||||
{
|
||||
"id": "b98fdacc-59d7-41c4-b790-1fdca50dfb22",
|
||||
"name": "dataReceived",
|
||||
"displayName": "Data Received",
|
||||
"type": "QString",
|
||||
"defaultValue": "",
|
||||
"displayNameEvent": "Data received"
|
||||
"displayNameEvent": "Connection status changed"
|
||||
}
|
||||
],
|
||||
"eventTypes": [
|
||||
{
|
||||
"id": "6d7c6df6-cb61-4d9e-b0d7-37c43911ca4b",
|
||||
"name": "triggered",
|
||||
"displayName": "Command Received",
|
||||
"displayName": "Data recieved",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "97d7ee8c-d9db-40b4-9855-4ceecd64c411",
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ TARGET = $$qtLibraryTarget(nymea_deviceplugintcpcommander)
|
|||
SOURCES += \
|
||||
deviceplugintcpcommander.cpp \
|
||||
tcpserver.cpp \
|
||||
tcpsocket.cpp
|
||||
|
||||
HEADERS += \
|
||||
deviceplugintcpcommander.h \
|
||||
tcpserver.h \
|
||||
|
||||
tcpsocket.h
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2017 Bernhard Trinnes <bernhard.trinnes@guh.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
|
|
@ -23,28 +23,27 @@
|
|||
#include <QNetworkInterface>
|
||||
|
||||
|
||||
TcpServer::TcpServer(const QHostAddress address, const int &port, QObject *parent) :
|
||||
TcpServer::TcpServer(const QHostAddress address, const quint16 &port, QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_tcpServer = new QTcpServer(this);
|
||||
connect(m_tcpServer, &QTcpServer::newConnection, this, &TcpServer::newConnection);
|
||||
qDebug(dcTCPCommander()) << "TCP Server on Port: " << port << "Address: " << address.toString();
|
||||
if (!m_tcpServer->listen(address, port)) {
|
||||
qDebug(dcTCPCommander()) << "Unable to start the server: " << m_tcpServer->errorString();
|
||||
qWarning(dcTCPCommander()) << "Unable to start the server: " << m_tcpServer->errorString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TcpServer::TcpServer(const int &port, QObject *parent) :
|
||||
TcpServer::TcpServer(const quint16 &port, QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
|
||||
m_tcpServer = new QTcpServer(this);
|
||||
connect(m_tcpServer, &QTcpServer::newConnection, this, &TcpServer::newConnection);
|
||||
qDebug(dcTCPCommander()) << "TCP Server on Port: " << port;
|
||||
if (!m_tcpServer->listen(QHostAddress::Any, port)) {
|
||||
qDebug(dcTCPCommander()) << "Unable to start the server: " << m_tcpServer->errorString();
|
||||
qWarning(dcTCPCommander()) << "Unable to start the server: " << m_tcpServer->errorString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -72,14 +71,13 @@ void TcpServer::newConnection()
|
|||
{
|
||||
qDebug(dcTCPCommander()) << "TCP Server new Connection request";
|
||||
m_socket = m_tcpServer->nextPendingConnection();
|
||||
m_socket->write("Hello client");
|
||||
m_socket->flush();
|
||||
|
||||
emit connected();
|
||||
emit connectionChanged(true);
|
||||
connect(m_socket, &QTcpSocket::disconnected, this, &TcpServer::onDisconnected);
|
||||
connect(m_socket, &QTcpSocket::readyRead, this, &TcpServer::readData);
|
||||
// Note: error signal will be interpreted as function, not as signal in C++11
|
||||
//connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -89,13 +87,18 @@ void TcpServer::onDisconnected()
|
|||
disconnect(m_socket, &QTcpSocket::disconnected, this, &TcpServer::onDisconnected);
|
||||
disconnect(m_socket, &QTcpSocket::readyRead, this, &TcpServer::readData);
|
||||
m_socket->deleteLater();
|
||||
emit disconnected();
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
|
||||
void TcpServer::readData()
|
||||
{
|
||||
QByteArray data = m_socket->readAll();
|
||||
qDebug(dcTCPCommander()) << "TCP Server data received: " << data;
|
||||
emit textMessageReceived(data);
|
||||
|
||||
m_socket->write("OK\n");
|
||||
emit commandReceived(data);
|
||||
}
|
||||
|
||||
void TcpServer::onError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qWarning(dcTCPCommander()) << "Socket Error" << m_socket->errorString() << error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2017 Bernhard Trinnes <bernhard.trinnes@guh.io> *
|
||||
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
|
|
@ -29,8 +29,8 @@ class TcpServer : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TcpServer(const QHostAddress address, const int &port, QObject *parent);
|
||||
explicit TcpServer(const int &port, QObject *parent = 0);
|
||||
explicit TcpServer(const QHostAddress address, const quint16 &port, QObject *parent = nullptr);
|
||||
explicit TcpServer(const quint16 &port, QObject *parent = nullptr);
|
||||
~TcpServer();
|
||||
|
||||
bool isValid();
|
||||
|
|
@ -42,19 +42,19 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
QTcpServer *m_tcpServer;
|
||||
QTcpSocket *m_socket;
|
||||
QTcpServer *m_tcpServer = nullptr;
|
||||
QTcpSocket *m_socket = nullptr;
|
||||
|
||||
signals:
|
||||
void newPendingConnection();
|
||||
void textMessageReceived(QByteArray message);
|
||||
void connected();
|
||||
void disconnected();
|
||||
void commandReceived(QByteArray message);
|
||||
void connectionChanged(bool connected);
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void newConnection();
|
||||
void onDisconnected();
|
||||
void readData();
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
};
|
||||
|
||||
#endif // TCPSERVER_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
#include "tcpsocket.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
TcpSocket::TcpSocket(const QHostAddress address, const quint16 &port, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_port(port),
|
||||
m_address(address)
|
||||
{
|
||||
m_tcpSocket = new QTcpSocket(this);
|
||||
connect(m_tcpSocket, &QTcpSocket::connected, this, &TcpSocket::onConnected);
|
||||
connect(m_tcpSocket, &QTcpSocket::disconnected, this, &TcpSocket::onDisconnected);
|
||||
connect(m_tcpSocket, &QTcpSocket::bytesWritten, this, &TcpSocket::onBytesWritten);
|
||||
connect(m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onTcpSocketError(QAbstractSocket::SocketError)));
|
||||
}
|
||||
|
||||
void TcpSocket::sendCommand(QByteArray command)
|
||||
{
|
||||
if (m_pendingCommands.isEmpty()) {
|
||||
m_pendingCommands.append(command);
|
||||
m_tcpSocket->abort();
|
||||
m_tcpSocket->connectToHost(m_address, m_port);
|
||||
} else {
|
||||
m_pendingCommands.append(command);
|
||||
}
|
||||
}
|
||||
|
||||
void TcpSocket::connectionTest()
|
||||
{
|
||||
QTcpSocket *testSocket = new QTcpSocket(this);
|
||||
connect(testSocket, &QTcpSocket::connected, this,[this, testSocket] {
|
||||
emit connectionTestFinished(true);
|
||||
testSocket->deleteLater();
|
||||
});
|
||||
connect(testSocket, static_cast<void (QTcpSocket::*) (QAbstractSocket::SocketError)>(&QTcpSocket::error), this, [this, testSocket] {
|
||||
emit connectionTestFinished(false);
|
||||
testSocket->deleteLater();
|
||||
});
|
||||
testSocket->connectToHost(m_address, m_port);
|
||||
}
|
||||
|
||||
void TcpSocket::onConnected()
|
||||
{
|
||||
qDebug(dcTCPCommander()) << "Socket connected" ;
|
||||
if (!m_pendingCommands.isEmpty()) {
|
||||
QByteArray data = m_pendingCommands.takeLast();
|
||||
qDebug(dcTCPCommander()) << "Writing data:" << data;
|
||||
m_tcpSocket->write(data + "\n");
|
||||
} else {
|
||||
m_tcpSocket->disconnectFromHost();
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
}
|
||||
|
||||
void TcpSocket::onDisconnected()
|
||||
{
|
||||
qDebug(dcTCPCommander()) << "Socket disconnected" ;
|
||||
emit connectionChanged(false);
|
||||
}
|
||||
|
||||
|
||||
void TcpSocket::onBytesWritten()
|
||||
{
|
||||
emit commandSent(true);
|
||||
if (!m_pendingCommands.isEmpty()){
|
||||
m_tcpSocket->write(m_pendingCommands.takeFirst());
|
||||
} else {
|
||||
m_tcpSocket->close();
|
||||
}
|
||||
}
|
||||
|
||||
void TcpSocket::onError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qWarning(dcTCPCommander()) << "Socket Error" << m_tcpSocket->errorString();
|
||||
|
||||
switch (error) {
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
break;
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
break;
|
||||
case QAbstractSocket::ConnectionRefusedError:
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
emit commandSent(false);
|
||||
emit connectionChanged(false);
|
||||
|
||||
m_pendingCommands.clear(); //undefined socket state needs to clear command buffer.
|
||||
|
||||
if (m_tcpSocket->isOpen()) {
|
||||
m_tcpSocket->disconnectFromHost();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef TCPSOCKET_H
|
||||
#define TCPSOCKET_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
|
||||
class TcpSocket : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TcpSocket(const QHostAddress address, const quint16 &port, QObject *parent = nullptr);
|
||||
void sendCommand(QByteArray command);
|
||||
|
||||
void connectionTest();
|
||||
|
||||
private:
|
||||
QTcpSocket *m_tcpSocket = nullptr;
|
||||
|
||||
quint16 m_port;
|
||||
QHostAddress m_address;
|
||||
|
||||
QList<QByteArray> m_pendingCommands;
|
||||
|
||||
signals:
|
||||
void connectionChanged(bool connected);
|
||||
void commandSent(bool successfull);
|
||||
void connectionTestFinished(bool successfull);
|
||||
|
||||
private slots:
|
||||
|
||||
void onConnected();
|
||||
void onDisconnected();
|
||||
void onBytesWritten();
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
|
||||
};
|
||||
|
||||
#endif // TCPSOCKET_H
|
||||
Loading…
Reference in New Issue