switch rs232 provider to completly async transfer (#255)

This commit is contained in:
redPanther 2016-09-25 22:20:01 +02:00 committed by GitHub
parent f146894799
commit d1e165a753
2 changed files with 72 additions and 30 deletions

View File

@ -13,9 +13,15 @@ ProviderRs232::ProviderRs232(const Json::Value &deviceConfig)
: _rs232Port(this) : _rs232Port(this)
, _blockedForDelay(false) , _blockedForDelay(false)
, _stateChanged(true) , _stateChanged(true)
, _bytesToWrite(0)
, _bytesWritten(0)
, _frameDropCounter(0)
, _lastError(QSerialPort::NoError)
{ {
setConfig(deviceConfig); setConfig(deviceConfig);
connect(&_rs232Port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(error(QSerialPort::SerialPortError))); connect(&_rs232Port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(error(QSerialPort::SerialPortError)));
connect(&_rs232Port, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64)));
connect(&_rs232Port, SIGNAL(readyRead()), this, SLOT(readyRead()));
} }
bool ProviderRs232::setConfig(const Json::Value &deviceConfig) bool ProviderRs232::setConfig(const Json::Value &deviceConfig)
@ -28,12 +34,33 @@ bool ProviderRs232::setConfig(const Json::Value &deviceConfig)
return true; return true;
} }
void ProviderRs232::bytesWritten(qint64 bytes)
{
_bytesWritten += bytes;
if (_bytesWritten >= _bytesToWrite)
{
_bytesToWrite = 0;
_blockedForDelay = false;
}
}
void ProviderRs232::readyRead()
{
QByteArray data = _rs232Port.readAll();
Debug(_log, "received %d bytes data", data.size());
}
void ProviderRs232::error(QSerialPort::SerialPortError error) void ProviderRs232::error(QSerialPort::SerialPortError error)
{ {
if ( error != QSerialPort::NoError ) if ( error != QSerialPort::NoError )
{ {
switch (error) if (_lastError != error)
{ {
_lastError = error;
switch (error)
{
case QSerialPort::DeviceNotFoundError: case QSerialPort::DeviceNotFoundError:
Error(_log, "An error occurred while attempting to open an non-existing device."); break; Error(_log, "An error occurred while attempting to open an non-existing device."); break;
case QSerialPort::PermissionError: case QSerialPort::PermissionError:
@ -43,11 +70,11 @@ void ProviderRs232::error(QSerialPort::SerialPortError error)
case QSerialPort::NotOpenError: case QSerialPort::NotOpenError:
Error(_log, "This error occurs when an operation is executed that can only be successfully performed if the device is open."); break; Error(_log, "This error occurs when an operation is executed that can only be successfully performed if the device is open."); break;
case QSerialPort::ParityError: case QSerialPort::ParityError:
Error(_log, "Parity error detected by the hardware while reading data. This value is obsolete. We strongly advise against using it in new code."); break; Error(_log, "Parity error detected by the hardware while reading data."); break;
case QSerialPort::FramingError: case QSerialPort::FramingError:
Error(_log, "Framing error detected by the hardware while reading data. This value is obsolete. We strongly advise against using it in new code."); break; Error(_log, "Framing error detected by the hardware while reading data."); break;
case QSerialPort::BreakConditionError: case QSerialPort::BreakConditionError:
Error(_log, "Break condition detected by the hardware on the input line. This value is obsolete. We strongly advise against using it in new code."); break; Error(_log, "Break condition detected by the hardware on the input line."); break;
case QSerialPort::WriteError: case QSerialPort::WriteError:
Error(_log, "An I/O error occurred while writing the data."); break; Error(_log, "An I/O error occurred while writing the data."); break;
case QSerialPort::ReadError: case QSerialPort::ReadError:
@ -59,8 +86,10 @@ void ProviderRs232::error(QSerialPort::SerialPortError error)
case QSerialPort::TimeoutError: case QSerialPort::TimeoutError:
Error(_log, "A timeout error occurred."); break; Error(_log, "A timeout error occurred."); break;
default: Error(_log,"An unidentified error occurred. (%d)", error); default: Error(_log,"An unidentified error occurred. (%d)", error);
}
_rs232Port.clearError();
closeDevice();
} }
_rs232Port.clearError();
} }
} }
@ -84,15 +113,15 @@ int ProviderRs232::open()
Info(_log, "Opening UART: %s", _deviceName.c_str()); Info(_log, "Opening UART: %s", _deviceName.c_str());
_rs232Port.setPortName(_deviceName.c_str()); _rs232Port.setPortName(_deviceName.c_str());
return tryOpen() ? 0 : -1; return tryOpen(_delayAfterConnect_ms) ? 0 : -1;
} }
bool ProviderRs232::tryOpen() bool ProviderRs232::tryOpen(const int delayAfterConnect_ms)
{ {
if ( ! _rs232Port.isOpen() ) if ( ! _rs232Port.isOpen() )
{ {
if ( ! _rs232Port.open(QIODevice::WriteOnly) ) if ( ! _rs232Port.open(QIODevice::ReadWrite) )
{ {
if ( _stateChanged ) if ( _stateChanged )
{ {
@ -105,46 +134,52 @@ bool ProviderRs232::tryOpen()
_stateChanged = true; _stateChanged = true;
} }
if (_delayAfterConnect_ms > 0) if (delayAfterConnect_ms > 0)
{ {
_blockedForDelay = true; _blockedForDelay = true;
QTimer::singleShot(_delayAfterConnect_ms, this, SLOT(unblockAfterDelay())); QTimer::singleShot(delayAfterConnect_ms, this, SLOT(unblockAfterDelay()));
Debug(_log, "Device blocked for %d ms", _delayAfterConnect_ms); Debug(_log, "Device blocked for %d ms", delayAfterConnect_ms);
} }
return _rs232Port.isOpen(); return _rs232Port.isOpen();
} }
int ProviderRs232::writeBytes(const unsigned size, const uint8_t * data) int ProviderRs232::writeBytes(const qint64 size, const uint8_t * data)
{ {
if (_blockedForDelay) if (! _blockedForDelay)
{ {
return 0; if (!_rs232Port.isOpen())
} {
return tryOpen(3000) ? 0 : -1;
}
if (!_rs232Port.isOpen()) if (_frameDropCounter > 0)
{
Debug(_log, "%d frames dropped", _frameDropCounter);
}
_frameDropCounter = 0;
_blockedForDelay = true;
_bytesToWrite = size;
qint64 bytesWritten = _rs232Port.write(reinterpret_cast<const char*>(data), size);
if (bytesWritten == -1 || bytesWritten != size)
{
Warning(_log,"failed writing data");
QTimer::singleShot(500, this, SLOT(unblockAfterDelay()));
return -1;
}
QTimer::singleShot(5000, this, SLOT(unblockAfterDelay()));
}
else
{ {
_delayAfterConnect_ms = 3000; _frameDropCounter++;
return tryOpen() ? 0 : -1;
} }
_rs232Port.flush();
qint64 result = _rs232Port.write(reinterpret_cast<const char*>(data), size);
if ( result < 0 || result != size)
{
return -1;
}
Debug(_log, "write %d ", result);
_rs232Port.flush();
return 0; return 0;
} }
void ProviderRs232::unblockAfterDelay() void ProviderRs232::unblockAfterDelay()
{ {
Debug(_log, "Device unblocked");
_blockedForDelay = false; _blockedForDelay = false;
} }

View File

@ -49,7 +49,7 @@ protected:
* *
* @return Zero on succes else negative * @return Zero on succes else negative
*/ */
int writeBytes(const unsigned size, const uint8_t *data); int writeBytes(const qint64 size, const uint8_t *data);
void closeDevice(); void closeDevice();
@ -57,10 +57,12 @@ private slots:
/// Unblock the device after a connection delay /// Unblock the device after a connection delay
void unblockAfterDelay(); void unblockAfterDelay();
void error(QSerialPort::SerialPortError error); void error(QSerialPort::SerialPortError error);
void bytesWritten(qint64 bytes);
void readyRead();
private: private:
// tries to open device if not opened // tries to open device if not opened
bool tryOpen(); bool tryOpen(const int delayAfterConnect_ms);
/// The name of the output device /// The name of the output device
std::string _deviceName; std::string _deviceName;
@ -77,4 +79,9 @@ private:
bool _blockedForDelay; bool _blockedForDelay;
bool _stateChanged; bool _stateChanged;
qint64 _bytesToWrite;
qint64 _bytesWritten;
qint64 _frameDropCounter;
QSerialPort::SerialPortError _lastError;
}; };