From fe6859977c88a8a4e9b9f29333fb2a4a43903081 Mon Sep 17 00:00:00 2001 From: nymea Date: Tue, 14 May 2019 12:17:32 +0200 Subject: [PATCH 1/3] fixed segfault and device discovery --- .../devicepluginserialportcommander.cpp | 174 +++++++++++------- .../devicepluginserialportcommander.h | 11 +- .../devicepluginserialportcommander.json | 12 +- 3 files changed, 123 insertions(+), 74 deletions(-) diff --git a/serialportcommander/devicepluginserialportcommander.cpp b/serialportcommander/devicepluginserialportcommander.cpp index 20d7fed2..51382fb5 100644 --- a/serialportcommander/devicepluginserialportcommander.cpp +++ b/serialportcommander/devicepluginserialportcommander.cpp @@ -46,61 +46,62 @@ DevicePluginSerialPortCommander::DevicePluginSerialPortCommander() DeviceManager::DeviceSetupStatus DevicePluginSerialPortCommander::setupDevice(Device *device) { + if(!m_reconnectTimer) { + m_reconnectTimer = new QTimer(this); + m_reconnectTimer->setSingleShot(true); + m_reconnectTimer->setInterval(5000); + + connect(m_reconnectTimer, &QTimer::timeout, this, &DevicePluginSerialPortCommander::onReconnectTimer); + } + if (device->deviceClassId() == serialPortCommanderDeviceClassId) { QString interface = device->paramValue(serialPortCommanderDeviceSerialPortParamTypeId).toString(); + QSerialPort *serialPort = new QSerialPort(interface, this); + if(!serialPort) + return DeviceManager::DeviceSetupStatusFailure; - if (!m_usedInterfaces.contains(interface)) { + serialPort->setBaudRate(device->paramValue(serialPortCommanderDeviceBaudRateParamTypeId).toInt()); + serialPort->setDataBits(QSerialPort::DataBits(device->paramValue(serialPortCommanderDeviceDataBitsParamTypeId).toInt())); - 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); + 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(); + serialPort->deleteLater(); return DeviceManager::DeviceSetupStatusFailure; } - return DeviceManager::DeviceSetupStatusSuccess; + + 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))); + m_serialPorts.insert(device, serialPort); + device->setStateValue(serialPortCommanderConnectedStateTypeId, true); } - return DeviceManager::DeviceSetupStatusFailure; + return DeviceManager::DeviceSetupStatusSuccess; } @@ -110,20 +111,21 @@ DeviceManager::DeviceError DevicePluginSerialPortCommander::discoverDevices(cons // Create the list of available serial interfaces QList 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); + foreach(QSerialPortInfo port, QSerialPortInfo::availablePorts()) { + + qCDebug(dcSerialPortCommander()) << "Found serial port:" << port.portName(); + QString description = port.manufacturer() + " " + port.description(); + DeviceDescriptor deviceDescriptor(deviceClassId, port.portName(), description); + ParamList parameters; + foreach (Device *existingDevice, myDevices()) { + if (existingDevice->paramValue(serialPortCommanderDeviceSerialPortParamTypeId).toString() == port.portName()) { + deviceDescriptor.setDeviceId(existingDevice->id()); + break; + } } + parameters.append(Param(serialPortCommanderDeviceSerialPortParamTypeId, port.portName())); + deviceDescriptor.setParams(parameters); + deviceDescriptors.append(deviceDescriptor); } emit devicesDiscovered(deviceClassId, deviceDescriptors); return DeviceManager::DeviceErrorAsync; @@ -137,8 +139,10 @@ DeviceManager::DeviceError DevicePluginSerialPortCommander::executeAction(Device if (action.actionTypeId() == serialPortCommanderTriggerActionTypeId) { QSerialPort *serialPort = m_serialPorts.value(device); - serialPort->write(action.param(serialPortCommanderTriggerActionOutputDataParamTypeId).value().toByteArray()); - + qint64 size = serialPort->write(action.param(serialPortCommanderTriggerActionOutputDataParamTypeId).value().toByteArray()); + if(size != action.param(serialPortCommanderTriggerActionOutputDataParamTypeId).value().toByteArray().length()) { + return DeviceManager::DeviceErrorHardwareFailure; + } return DeviceManager::DeviceErrorNoError; } return DeviceManager::DeviceErrorActionTypeNotFound; @@ -151,10 +155,19 @@ 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(); + if (serialPort) { + if (serialPort->isOpen()){ + serialPort->flush(); + serialPort->close(); + } + serialPort->deleteLater(); + } + } + + if (myDevices().empty()) { + m_reconnectTimer->stop(); + m_reconnectTimer->deleteLater(); } } @@ -165,7 +178,7 @@ void DevicePluginSerialPortCommander::onReadyRead() QByteArray data; while (!serialPort->atEnd()) { - data = serialPort->read(100); + data.append(serialPort->read(100)); } qDebug(dcSerialPortCommander()) << "Message received" << data; @@ -176,9 +189,17 @@ void DevicePluginSerialPortCommander::onReadyRead() emitEvent(event); } -void DevicePluginSerialPortCommander::onSerialError(QSerialPort::SerialPortError error) +void DevicePluginSerialPortCommander::onSerialError(const QSerialPort::SerialPortError &error) { - qCWarning(dcSerialPortCommander) << "Serial Port error happened:" << error; + QSerialPort *serialPort = static_cast(sender()); + Device *device = m_serialPorts.key(serialPort); + + if (error != QSerialPort::NoError && serialPort->isOpen()) { + qCCritical(dcSerialPortCommander()) << "Serial port error:" << error << serialPort->errorString(); + m_reconnectTimer->start(); + serialPort->close(); + device->setStateValue(serialPortCommanderConnectedStateTypeId, false); + } } void DevicePluginSerialPortCommander::onBaudRateChanged(qint32 baudRate, QSerialPort::Direction direction) @@ -217,3 +238,20 @@ void DevicePluginSerialPortCommander::onFlowControlChanged(QSerialPort::FlowCont device->setParamValue(serialPortCommanderDeviceFlowControlParamTypeId, flowControl); } +void DevicePluginSerialPortCommander::onReconnectTimer() +{ + foreach(Device *device, myDevices()) { + if (!device->stateValue(serialPortCommanderConnectedStateTypeId).toBool()) { + QSerialPort *serialPort = m_serialPorts.value(device); + if (serialPort) { + if (serialPort->open(QSerialPort::ReadWrite)) { + device->setStateValue(serialPortCommanderConnectedStateTypeId, true); + } else { + device->setStateValue(serialPortCommanderConnectedStateTypeId, false); + m_reconnectTimer->start(); + } + } + } + } +} + diff --git a/serialportcommander/devicepluginserialportcommander.h b/serialportcommander/devicepluginserialportcommander.h index d1e2b45e..08a796ce 100644 --- a/serialportcommander/devicepluginserialportcommander.h +++ b/serialportcommander/devicepluginserialportcommander.h @@ -25,6 +25,8 @@ #include "plugin/deviceplugin.h" #include "devicemanager.h" +#include + #include #include @@ -40,23 +42,22 @@ public: DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; void deviceRemoved(Device *device) override; - DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms); + DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; private: + QTimer *m_reconnectTimer = nullptr; QHash m_serialPorts; - QList m_usedInterfaces; private slots: void onReadyRead(); - void onSerialError(QSerialPort::SerialPortError error); + void onSerialError(const 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: + void onReconnectTimer(); }; diff --git a/serialportcommander/devicepluginserialportcommander.json b/serialportcommander/devicepluginserialportcommander.json index 7f2c2aa0..0fc2cd64 100644 --- a/serialportcommander/devicepluginserialportcommander.json +++ b/serialportcommander/devicepluginserialportcommander.json @@ -14,7 +14,7 @@ "name": "serialPortCommander", "displayName": "Serial port commander", "createMethods": ["user", "discovery"], - "interfaces": ["outputtrigger", "inputtrigger"], + "interfaces": ["connectable", "outputtrigger", "inputtrigger"], "paramTypes": [ { "id": "ed49f7d8-ab18-4c37-9b80-1004b75dcb91", @@ -74,6 +74,16 @@ "defaultValue": "No Parity" } ], + "stateTypes": [ + { + "id": "e308259d-9180-4880-a0bf-1734b52de9ac", + "name": "connected", + "displayName": "connected", + "displayNameEvent": "connected changed", + "defaultValue": false, + "type": "bool" + } + ], "actionTypes": [ { "id": "0b22c4d1-f5f6-4a93-aa93-660d27bf8f71", From 921bf87fd29eb215be30b75ca86a3fe31c95c1a3 Mon Sep 17 00:00:00 2001 From: nymea Date: Tue, 14 May 2019 12:32:21 +0200 Subject: [PATCH 2/3] fixed onBaudrateChanged signal --- serialportcommander/devicepluginserialportcommander.cpp | 4 ++-- serialportcommander/devicepluginserialportcommander.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/serialportcommander/devicepluginserialportcommander.cpp b/serialportcommander/devicepluginserialportcommander.cpp index 51382fb5..bff5e691 100644 --- a/serialportcommander/devicepluginserialportcommander.cpp +++ b/serialportcommander/devicepluginserialportcommander.cpp @@ -93,7 +93,7 @@ DeviceManager::DeviceSetupStatus DevicePluginSerialPortCommander::setupDevice(De 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(baudRateChanged(qint32, QSerialPort::Directions)), this, SLOT(onBaudRateChanged(qint32, QSerialPort::Directions))); 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))); @@ -202,7 +202,7 @@ void DevicePluginSerialPortCommander::onSerialError(const QSerialPort::SerialPor } } -void DevicePluginSerialPortCommander::onBaudRateChanged(qint32 baudRate, QSerialPort::Direction direction) +void DevicePluginSerialPortCommander::onBaudRateChanged(qint32 baudRate, QSerialPort::Directions direction) { Q_UNUSED(direction) QSerialPort *serialPort = static_cast(sender()); diff --git a/serialportcommander/devicepluginserialportcommander.h b/serialportcommander/devicepluginserialportcommander.h index 08a796ce..302ab647 100644 --- a/serialportcommander/devicepluginserialportcommander.h +++ b/serialportcommander/devicepluginserialportcommander.h @@ -52,7 +52,7 @@ private: private slots: void onReadyRead(); void onSerialError(const QSerialPort::SerialPortError &error); - void onBaudRateChanged(qint32 baudRate, QSerialPort::Direction direction); + void onBaudRateChanged(qint32 baudRate, QSerialPort::Directions direction); void onParityChanged(QSerialPort::Parity parity); void onDataBitsChanged(QSerialPort::DataBits dataBits); void onStopBitsChanged(QSerialPort::StopBits stopBits); From d3f00a9f5ee619511b10f3ab0539487c2fe0951e Mon Sep 17 00:00:00 2001 From: nymea Date: Mon, 20 May 2019 10:51:04 +0200 Subject: [PATCH 3/3] refurbished the serialport commander --- .../devicepluginserialportcommander.cpp | 57 ++++++++++--------- .../devicepluginserialportcommander.h | 5 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/serialportcommander/devicepluginserialportcommander.cpp b/serialportcommander/devicepluginserialportcommander.cpp index bff5e691..6f203946 100644 --- a/serialportcommander/devicepluginserialportcommander.cpp +++ b/serialportcommander/devicepluginserialportcommander.cpp @@ -44,6 +44,34 @@ DevicePluginSerialPortCommander::DevicePluginSerialPortCommander() { } + +DeviceManager::DeviceError DevicePluginSerialPortCommander::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) +{ + Q_UNUSED(params) + // Create the list of available serial interfaces + QList deviceDescriptors; + + foreach(QSerialPortInfo port, QSerialPortInfo::availablePorts()) { + + qCDebug(dcSerialPortCommander()) << "Found serial port:" << port.portName(); + QString description = port.manufacturer() + " " + port.description(); + DeviceDescriptor deviceDescriptor(deviceClassId, port.portName(), description); + ParamList parameters; + foreach (Device *existingDevice, myDevices()) { + if (existingDevice->paramValue(serialPortCommanderDeviceSerialPortParamTypeId).toString() == port.portName()) { + deviceDescriptor.setDeviceId(existingDevice->id()); + break; + } + } + parameters.append(Param(serialPortCommanderDeviceSerialPortParamTypeId, port.portName())); + deviceDescriptor.setParams(parameters); + deviceDescriptors.append(deviceDescriptor); + } + emit devicesDiscovered(deviceClassId, deviceDescriptors); + return DeviceManager::DeviceErrorAsync; +} + + DeviceManager::DeviceSetupStatus DevicePluginSerialPortCommander::setupDevice(Device *device) { if(!m_reconnectTimer) { @@ -105,33 +133,6 @@ DeviceManager::DeviceSetupStatus DevicePluginSerialPortCommander::setupDevice(De } -DeviceManager::DeviceError DevicePluginSerialPortCommander::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) -{ - Q_UNUSED(params) - // Create the list of available serial interfaces - QList deviceDescriptors; - - foreach(QSerialPortInfo port, QSerialPortInfo::availablePorts()) { - - qCDebug(dcSerialPortCommander()) << "Found serial port:" << port.portName(); - QString description = port.manufacturer() + " " + port.description(); - DeviceDescriptor deviceDescriptor(deviceClassId, port.portName(), description); - ParamList parameters; - foreach (Device *existingDevice, myDevices()) { - if (existingDevice->paramValue(serialPortCommanderDeviceSerialPortParamTypeId).toString() == port.portName()) { - deviceDescriptor.setDeviceId(existingDevice->id()); - break; - } - } - parameters.append(Param(serialPortCommanderDeviceSerialPortParamTypeId, port.portName())); - deviceDescriptor.setParams(parameters); - deviceDescriptors.append(deviceDescriptor); - } - emit devicesDiscovered(deviceClassId, deviceDescriptors); - return DeviceManager::DeviceErrorAsync; -} - - DeviceManager::DeviceError DevicePluginSerialPortCommander::executeAction(Device *device, const Action &action) { if (device->deviceClassId() == serialPortCommanderDeviceClassId ) { @@ -189,7 +190,7 @@ void DevicePluginSerialPortCommander::onReadyRead() emitEvent(event); } -void DevicePluginSerialPortCommander::onSerialError(const QSerialPort::SerialPortError &error) +void DevicePluginSerialPortCommander::onSerialError(QSerialPort::SerialPortError error) { QSerialPort *serialPort = static_cast(sender()); Device *device = m_serialPorts.key(serialPort); diff --git a/serialportcommander/devicepluginserialportcommander.h b/serialportcommander/devicepluginserialportcommander.h index 302ab647..44d69ecf 100644 --- a/serialportcommander/devicepluginserialportcommander.h +++ b/serialportcommander/devicepluginserialportcommander.h @@ -25,8 +25,8 @@ #include "plugin/deviceplugin.h" #include "devicemanager.h" -#include +#include #include #include @@ -51,14 +51,13 @@ private: private slots: void onReadyRead(); - void onSerialError(const QSerialPort::SerialPortError &error); + void onSerialError(QSerialPort::SerialPortError error); void onBaudRateChanged(qint32 baudRate, QSerialPort::Directions direction); void onParityChanged(QSerialPort::Parity parity); void onDataBitsChanged(QSerialPort::DataBits dataBits); void onStopBitsChanged(QSerialPort::StopBits stopBits); void onFlowControlChanged(QSerialPort::FlowControl flowControl); void onReconnectTimer(); - }; #endif // DEVICEPLUGINSERIALPORTCOMMANDER_H