diff --git a/udpcommander/devicepluginudpcommander.cpp b/udpcommander/devicepluginudpcommander.cpp index 3ac4064e..51f97f65 100644 --- a/udpcommander/devicepluginudpcommander.cpp +++ b/udpcommander/devicepluginudpcommander.cpp @@ -1,6 +1,7 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright (C) 2015 Simon Stürz * + * Copyright (C) 2015-2018 Simon Stürz * + * Copyright (C) 2017 Bernhard Trinnes * * * * This file is part of nymea. * * * @@ -69,41 +70,72 @@ DevicePluginUdpCommander::DevicePluginUdpCommander() DeviceManager::DeviceSetupStatus DevicePluginUdpCommander::setupDevice(Device *device) { - // check port - bool portOk = false; - int port = device->paramValue(commanderPortParamTypeId).toInt(&portOk); - if (!portOk || port <= 0 || port > 65535) { - qCWarning(dcUdpCommander) << device->name() << ": invalid port:" << device->paramValue(commanderPortParamTypeId).toString() << "."; - return DeviceManager::DeviceSetupStatusFailure; + qCDebug(dcUdpCommander()) << "Setup device" << device->name() << device->params(); + + if (device->deviceClassId() == udpReceiverDeviceClassId) { + QUdpSocket *udpSocket = new QUdpSocket(this); + int port = device->paramValue(udpReceiverPortParamTypeId).toInt(); + if (!udpSocket->bind(QHostAddress::Any, port, QUdpSocket::ShareAddress)) { + qCWarning(dcUdpCommander()) << device->name() << "cannot bind to port" << port; + delete udpSocket; + return DeviceManager::DeviceSetupStatusFailure; + } + + connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); + m_receiverList.insert(udpSocket, device); + + return DeviceManager::DeviceSetupStatusSuccess; + } else if (device->deviceClassId() == udpCommanderDeviceClassId) { + QUdpSocket *udpSocket = new QUdpSocket(this); + m_commanderList.insert(udpSocket, device); + return DeviceManager::DeviceSetupStatusSuccess; } - QUdpSocket *udpSocket = new QUdpSocket(this); + return DeviceManager::DeviceSetupStatusFailure; +} - if (!udpSocket->bind(QHostAddress::Any, port)) { - qCWarning(dcUdpCommander) << device->name() << "can't bind to port" << port << "."; - delete udpSocket; - return DeviceManager::DeviceSetupStatusFailure; + +DeviceManager::DeviceError DevicePluginUdpCommander::executeAction(Device *device, const Action &action) { + + if (device->deviceClassId() == udpCommanderDeviceClassId) { + if (action.actionTypeId() == udpCommanderOutputDataActionTypeId) { + QUdpSocket *udpSocket = m_commanderList.key(device); + int port = device->paramValue(udpCommanderPortParamTypeId).toInt(); + QHostAddress address = QHostAddress(device->paramValue(udpCommanderAddressParamTypeId).toString()); + QByteArray data = action.param(udpCommanderDataParamTypeId).value().toByteArray(); + qDebug(dcUdpCommander()) << "Send UDP datagram:" << data << "address:" << address.toIPv4Address() << "port:" << port; + udpSocket->writeDatagram(data, address, port); + + return DeviceManager::DeviceErrorNoError; + } + return DeviceManager::DeviceErrorActionTypeNotFound; } - - connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); - m_commanderList.insert(udpSocket, device); - - return DeviceManager::DeviceSetupStatusSuccess; + return DeviceManager::DeviceErrorDeviceClassNotFound; } void DevicePluginUdpCommander::deviceRemoved(Device *device) { - QUdpSocket *socket = m_commanderList.key(device); - m_commanderList.remove(socket); + if (device->deviceClassId() == udpReceiverDeviceClassId) { + QUdpSocket *socket = m_receiverList.key(device); + m_receiverList.remove(socket); + socket->close(); + socket->deleteLater(); - socket->close(); - socket->deleteLater(); + } else if (device->deviceClassId() == udpCommanderDeviceClassId) { + QUdpSocket *socket = m_commanderList.key(device); + m_commanderList.remove(socket); + socket->close(); + socket->deleteLater(); + } } void DevicePluginUdpCommander::readPendingDatagrams() { - QUdpSocket *socket= qobject_cast(sender()); - Device *device = m_commanderList.value(socket); + QUdpSocket *socket= static_cast(sender()); + Device *device = m_receiverList.value(socket); + + if (!device) + return; QByteArray datagram; QHostAddress sender; @@ -114,10 +146,14 @@ void DevicePluginUdpCommander::readPendingDatagrams() socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); } - if (datagram == device->paramValue(commanderCommandParamTypeId).toByteArray() || - datagram == device->paramValue(commanderCommandParamTypeId).toByteArray() + "\n") { - qCDebug(dcUdpCommander) << device->name() << " got command from" << sender.toString() << senderPort; - emit emitEvent(Event(commanderCommandReceivedEventTypeId, device->id())); + device->setStateValue(udpReceiverInputDataStateTypeId, datagram); + + if (datagram == device->paramValue(udpReceiverCommandParamTypeId).toByteArray() || + datagram == device->paramValue(udpReceiverCommandParamTypeId).toByteArray() + "\n") { + qCDebug(dcUdpCommander()) << device->name() << "got command from" << sender.toString() << senderPort; + emit emitEvent(Event(udpReceiverCommandReceivedEventTypeId, device->id())); + + // Send response for verification socket->writeDatagram("OK\n", sender, senderPort); } } diff --git a/udpcommander/devicepluginudpcommander.h b/udpcommander/devicepluginudpcommander.h index 01c56c55..f5c9f9e3 100644 --- a/udpcommander/devicepluginudpcommander.h +++ b/udpcommander/devicepluginudpcommander.h @@ -1,6 +1,7 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright (C) 2015 Simon Stürz * + * Copyright (C) 2015-2018 Simon Stürz * + * Copyright (C) 2017 Bernhard Trinnes * * * * This file is part of nymea. * * * @@ -41,7 +42,10 @@ public: DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; void deviceRemoved(Device *device) override; + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; + private: + QHash m_receiverList; QHash m_commanderList; private slots: diff --git a/udpcommander/devicepluginudpcommander.json b/udpcommander/devicepluginudpcommander.json index e3824887..c9d2a0a5 100644 --- a/udpcommander/devicepluginudpcommander.json +++ b/udpcommander/devicepluginudpcommander.json @@ -10,34 +10,86 @@ "deviceClasses": [ { "id": "6ecd5a8d-595a-4520-85e3-dcc9679edf66", - "displayName": "UDP Commander", - "name": "commander", + "displayName": "UDP Receiver", + "name": "udpReceiver", "deviceIcon": "Network", - "basicTags": [ - "Service", - "Sensor" - ], + "basicTags": ["Service", "Sensor"], "createMethods": ["user"], "paramTypes": [ { "id": "1843adcb-e377-44d1-8d70-ab4f9eeb32ec", "name": "port", - "displayName": "port", - "type": "int" + "displayName": "Port", + "type": "int", + "minValue": 0, + "maxValue": 65535, + "defaultValue": 4242 }, { "id": "d0f29961-1624-4b91-a0e8-9b1cc86c44c7", "name": "command", - "displayName": "command", + "displayName": "Command", "type": "QString", - "inputType": "TextLine" + "defaultValue": "Hello" + } + ], + "stateTypes":[ + { + "id": "065a1a0a-d324-4ae6-a461-bef8143e8795", + "name": "inputData", + "displayName": "Received data", + "displayNameEvent": "Received data changed", + "type": "QString", + "defaultValue": "" } ], "eventTypes": [ { "id": "5fecbba3-ffbb-456b-872c-a2f571c681cb", "name": "commandReceived", - "displayName": "command received" + "displayName": "Command received" + } + ] + }, + { + "id": "31b00639-8904-4522-84ed-54c46a54c63c", + "name": "udpCommander", + "displayName": "UDP Commander", + "deviceIcon": "Network", + "basicTags": ["Service", "Sensor"], + "createMethods": ["user"], + "paramTypes": [ + { + "id": "eb204dfe-11f8-413f-8b68-8bffef3f9a7f", + "name": "port", + "displayName": "Port", + "type": "int", + "minValue": 0, + "maxValue": 65535, + "defaultValue": 4242 + }, + { + "id": "ea1be9fc-9a9b-44ba-a28d-e021aef4f046", + "name": "address", + "displayName": "Address", + "type": "QString", + "inputType": "IPv4Address", + "defaultValue": "127.0.0.1" + } + ], + "actionTypes": [ + { + "id": "6bc52462-b192-46a4-a6df-92cc5a479c89", + "name": "outputData", + "displayName": "Send data", + "paramTypes": [ + { + "id": "6604c852-6b24-4707-b8e5-1ddd8032efcc", + "name": "data", + "displayName": "Data", + "type": "QString" + } + ] } ] }