Merge PR #75: New Plugin: Serialport commander

This commit is contained in:
Jenkins 2019-03-06 21:13:46 +01:00
commit f9cfd899bb
7 changed files with 430 additions and 1 deletions

18
debian/control vendored
View File

@ -725,7 +725,7 @@ Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-translations,
Description: nymea.io plugin for remote ssh connection
Description: nymea.io plugin for UniPi devices
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
@ -749,6 +749,21 @@ Description: nymea.io plugin for remote ssh connection
.
This package will install the nymea.io plugin for unipi devices
Package: nymea-plugin-serialportcommander
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
libqt5serialport5,
nymea-plugins-translations,
Description: nymea.io plugin to send and receive strings over a serial port
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for serial ports
Package: nymea-plugins-translations
Section: misc
@ -816,6 +831,7 @@ Depends: nymea-plugin-boblight,
nymea-plugin-mqttclient,
nymea-plugin-remotessh,
nymea-plugin-unipi,
nymea-plugin-serialportcommander,
Replaces: guh-plugins-maker
Description: Plugins for nymea IoT server - Meta package for makers, tinkers and hackers
The nymea daemon is a plugin based IoT (Internet of Things) server. The

View File

@ -0,0 +1 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_devicepluginserialportcommander.so

View File

@ -36,6 +36,7 @@ PLUGIN_DIRS = \
pushbullet \
remotessh \
senic \
serialportcommander \
simulation \
snapd \
tasmota \

View File

@ -0,0 +1,219 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page serialportcommander.html
\title Serial Port Commander
\brief Plug-In to send and receive strings over a serial port.
\ingroup plugins
\ingroup nymea-plugins
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/serialportcommander/devicepluginserialportcommander.json
*/
#include "devicepluginserialportcommander.h"
#include "plugininfo.h"
DevicePluginSerialPortCommander::DevicePluginSerialPortCommander()
{
}
DeviceManager::DeviceSetupStatus DevicePluginSerialPortCommander::setupDevice(Device *device)
{
if (device->deviceClassId() == serialPortCommanderDeviceClassId) {
QString interface = device->paramValue(serialPortCommanderDeviceSerialPortParamTypeId).toString();
if (!m_usedInterfaces.contains(interface)) {
QSerialPort *serialPort = new QSerialPort(interface, this);
if(!serialPort)
return DeviceManager::DeviceSetupStatusFailure;
serialPort->setBaudRate(device->paramValue(serialPortCommanderDeviceBaudRateParamTypeId).toInt());
serialPort->setDataBits(QSerialPort::DataBits(device->paramValue(serialPortCommanderDeviceDataBitsParamTypeId).toInt()));
if (device->paramValue(serialPortCommanderDeviceParityParamTypeId).toString().contains("Even")) {
serialPort->setParity(QSerialPort::Parity::EvenParity );
} else if (device->paramValue(serialPortCommanderDeviceParityParamTypeId).toString().contains("Odd")) {
serialPort->setParity(QSerialPort::Parity::OddParity );
} else if (device->paramValue(serialPortCommanderDeviceParityParamTypeId).toString().contains("Space")) {
serialPort->setParity(QSerialPort::Parity::SpaceParity );
} else if (device->paramValue(serialPortCommanderDeviceParityParamTypeId).toString().contains("Mark")) {
serialPort->setParity(QSerialPort::Parity::MarkParity );
} else {
serialPort->setParity(QSerialPort::Parity::NoParity);
}
serialPort->setStopBits(QSerialPort::StopBits(device->paramValue(serialPortCommanderDeviceStopBitsParamTypeId).toInt()));
if (device->paramValue(serialPortCommanderDeviceFlowControlParamTypeId).toString().contains("Hardware")) {
serialPort->setFlowControl(QSerialPort::FlowControl::HardwareControl);
} else if (device->paramValue(serialPortCommanderDeviceFlowControlParamTypeId).toString().contains("Software")) {
serialPort->setFlowControl(QSerialPort::FlowControl::SoftwareControl);
} else {
serialPort->setFlowControl(QSerialPort::FlowControl::NoFlowControl);
}
if (!serialPort->open(QIODevice::ReadWrite)) {
qCWarning(dcSerialPortCommander()) << "Could not open serial port" << interface << serialPort->errorString();
return DeviceManager::DeviceSetupStatusFailure;
}
connect(serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onSerialError(QSerialPort::SerialPortError)));
connect(serialPort, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(serialPort, SIGNAL(baudRateChanged(qint32, QSerialPort::Direction)), this, SLOT(onBaudRateChanged(qint32, QSerialPort::Direction)));
connect(serialPort, SIGNAL(parityChanged(QSerialPort::Parity)), this, SLOT(onParityChanged(QSerialPort::Parity)));
connect(serialPort, SIGNAL(dataBitsChanged(QSerialPort::DataBits)), this, SLOT(onDataBitsChanged(QSerialPort::DataBits)));
connect(serialPort, SIGNAL(stopBitsChanged(QSerialPort::StopBits)), this, SLOT(onStopBitsChanged(QSerialPort::StopBits)));
connect(serialPort, SIGNAL(flowControlChanged(QSerialPort::FlowControl)), this, SLOT(onFlowControlChanged(QSerialPort::FlowControl)));
qCDebug(dcSerialPortCommander()) << "Setup successfully serial port" << interface;
m_usedInterfaces.append(interface);
m_serialPorts.insert(device, serialPort);
} else {
return DeviceManager::DeviceSetupStatusFailure;
}
return DeviceManager::DeviceSetupStatusSuccess;
}
return DeviceManager::DeviceSetupStatusFailure;
}
DeviceManager::DeviceError DevicePluginSerialPortCommander::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
// Create the list of available serial interfaces
QList<DeviceDescriptor> deviceDescriptors;
Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
if (m_usedInterfaces.contains(port.portName())){
//device already in use
qCDebug(dcSerialPortCommander()) << "Found serial port that is already used:" << port.portName();
} else {
//Serial port is not yet used, create now a new one
qCDebug(dcSerialPortCommander()) << "Found serial port:" << port.portName();
QString description = port.manufacturer() + " " + port.description();
DeviceDescriptor descriptor(deviceClassId, port.portName(), description);
ParamList parameters;
parameters.append(Param(serialPortCommanderDeviceSerialPortParamTypeId, port.portName()));
descriptor.setParams(parameters);
deviceDescriptors.append(descriptor);
}
}
emit devicesDiscovered(deviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceError DevicePluginSerialPortCommander::executeAction(Device *device, const Action &action)
{
if (device->deviceClassId() == serialPortCommanderDeviceClassId ) {
if (action.actionTypeId() == serialPortCommanderTriggerActionTypeId) {
QSerialPort *serialPort = m_serialPorts.value(device);
serialPort->write(action.param(serialPortCommanderTriggerActionOutputDataParamTypeId).value().toByteArray());
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
void DevicePluginSerialPortCommander::deviceRemoved(Device *device)
{
if (device->deviceClassId() == serialPortCommanderDeviceClassId) {
m_usedInterfaces.removeAll(device->paramValue(serialPortCommanderDeviceSerialPortParamTypeId).toString());
QSerialPort *serialPort = m_serialPorts.take(device);
serialPort->close();
serialPort->deleteLater();
}
}
void DevicePluginSerialPortCommander::onReadyRead()
{
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
Device *device = m_serialPorts.key(serialPort);
QByteArray data;
while (!serialPort->atEnd()) {
data = serialPort->read(100);
}
qDebug(dcSerialPortCommander()) << "Message received" << data;
Event event(serialPortCommanderTriggeredEventTypeId, device->id());
ParamList parameters;
parameters.append(Param(serialPortCommanderTriggeredEventInputDataParamTypeId, data));
event.setParams(parameters);
emitEvent(event);
}
void DevicePluginSerialPortCommander::onSerialError(QSerialPort::SerialPortError error)
{
qCWarning(dcSerialPortCommander) << "Serial Port error happened:" << error;
}
void DevicePluginSerialPortCommander::onBaudRateChanged(qint32 baudRate, QSerialPort::Direction direction)
{
Q_UNUSED(direction)
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
Device *device = m_serialPorts.key(serialPort);
device->setParamValue(serialPortCommanderDeviceBaudRateParamTypeId, baudRate);
}
void DevicePluginSerialPortCommander::onParityChanged(QSerialPort::Parity parity)
{
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
Device *device = m_serialPorts.key(serialPort);
device->setParamValue(serialPortCommanderDeviceParityParamTypeId, parity);
}
void DevicePluginSerialPortCommander::onDataBitsChanged(QSerialPort::DataBits dataBits)
{
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
Device *device = m_serialPorts.key(serialPort);
device->setParamValue(serialPortCommanderDeviceDataBitsParamTypeId, dataBits);
}
void DevicePluginSerialPortCommander::onStopBitsChanged(QSerialPort::StopBits stopBits)
{
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
Device *device = m_serialPorts.key(serialPort);
device->setParamValue(serialPortCommanderDeviceStopBitsParamTypeId, stopBits);
}
void DevicePluginSerialPortCommander::onFlowControlChanged(QSerialPort::FlowControl flowControl)
{
QSerialPort *serialPort = static_cast<QSerialPort*>(sender());
Device *device = m_serialPorts.key(serialPort);
device->setParamValue(serialPortCommanderDeviceFlowControlParamTypeId, flowControl);
}

View File

@ -0,0 +1,63 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DEVICEPLUGINSERIALPORTCOMMANDER_H
#define DEVICEPLUGINSERIALPORTCOMMANDER_H
#include "plugin/deviceplugin.h"
#include "devicemanager.h"
#include <QSerialPort>
#include <QSerialPortInfo>
class DevicePluginSerialPortCommander : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginserialportcommander.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginSerialPortCommander();
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params);
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private:
QHash<Device *, QSerialPort *> m_serialPorts;
QList<QString> m_usedInterfaces;
private slots:
void onReadyRead();
void onSerialError(QSerialPort::SerialPortError error);
void onBaudRateChanged(qint32 baudRate, QSerialPort::Direction direction);
void onParityChanged(QSerialPort::Parity parity);
void onDataBitsChanged(QSerialPort::DataBits dataBits);
void onStopBitsChanged(QSerialPort::StopBits stopBits);
void onFlowControlChanged(QSerialPort::FlowControl flowControl);
signals:
};
#endif // DEVICEPLUGINSERIALPORTCOMMANDER_H

View File

@ -0,0 +1,117 @@
{
"displayName": "Serial port commander",
"name": "SerialPortCommander",
"id": "fe93a12e-36f4-4015-8019-26b659817773",
"vendors": [
{
"name": "guh",
"displayName": "guh GmbH",
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
"deviceClasses": [
{
"id": "540566d8-a2a6-4ce2-9a1e-a66a989e6199",
"name": "serialPortCommander",
"displayName": "Serial port commander",
"deviceIcon": "Network",
"createMethods": ["user", "discovery"],
"interfaces": ["outputtrigger", "inputtrigger"],
"basicTags": [
"Device"
],
"paramTypes": [
{
"id": "ed49f7d8-ab18-4c37-9b80-1004b75dcb91",
"name": "serialPort",
"displayName": "Serial port",
"type": "QString",
"inputType": "TextLine",
"defaultValue": "ttyAMA0"
},
{
"id": "45dfc828-f238-4263-89a3-9b35cf5dea39",
"name": "baudRate",
"displayName": "Baud rate",
"type": "int",
"defaultValue": 9600
},
{
"id": "add4f7fb-1be9-4944-a420-3355b20174f9",
"name": "dataBits",
"displayName": "Data bits",
"type": "int",
"defaultValue": 8
},
{
"id": "4ea8bcdf-d4c5-45a4-a54f-f10ac3f08a78",
"name": "stopBits",
"displayName": "Stop bits",
"type": "int",
"defaultValue": 0
},
{
"id": "7e5d197f-0224-4c6f-8e86-0e7c867da5f1",
"name": "flowControl",
"displayName": "Flow control",
"type": "QString",
"inputType": "TextLine",
"allowedValues": [
"No Flow Control",
"Hardware Control",
"Software Control"
],
"defaultValue": "No Flow Control"
},
{
"id": "72de1b08-2a27-49c5-90e0-8788c3ea1da3",
"name": "parity",
"displayName": "Parity",
"type": "QString",
"inputType": "TextLine",
"allowedValues": [
"No Parity",
"Even Parity",
"Odd Parity",
"Space Parity",
"Mark Parity"
],
"defaultValue": "No Parity"
}
],
"actionTypes": [
{
"id": "0b22c4d1-f5f6-4a93-aa93-660d27bf8f71",
"name": "trigger",
"displayName": "Trigger",
"paramTypes": [
{
"id": "a27ecedc-424e-49ce-8956-9dbca2feac02",
"name": "outputData",
"displayName": "Data",
"type": "QString",
"inputType": "TextArea"
}
]
}
],
"eventTypes": [
{
"id": "32087633-616c-45a7-85af-4f1695c22359",
"name": "triggered",
"displayName": "Data received",
"paramTypes": [
{
"id": "b98fdacc-59d7-41c4-b790-1fdca50dfb22",
"name": "inputData",
"displayName": "Received Data",
"type": "QString",
"defaultValue": ""
}
]
}
]
}
]
}
]
}

View File

@ -0,0 +1,12 @@
include(../plugins.pri)
QT += serialport
TARGET = $$qtLibraryTarget(nymea_devicepluginserialportcommander)
SOURCES += \
devicepluginserialportcommander.cpp \
HEADERS += \
devicepluginserialportcommander.h \