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",