Disentangle LedDevice/LinearColorSmoothing, Bug Fixes & Test support (#654)

* Handle Exceptions in main & Pythoninit

* Have SSDPDiscover generic again

* Have SSDPDiscover generic again

* Change Info- to Debug logs as technical service messages

* Nanoleaf - When switched on, ensure UDP mode

* Include SQL Database in Cross-Compile instructions

* Fix Clazy (QT code checker) and clang Warnings

* Stop LedDevice:write for disabled device

* Nanoleaf: Fix uint printfs

* NanoLeaf: Fix indents to tabs

* NanoLeaf - Add debug verbosity switches

* Device switchability support, FileDevice with timestamp support

* Nanoleaf Light Panels now support External Control V2

* Enhance LedDeviceFile by Timestamp + fix readyness

* Stop color stream, if LedDevice disabled

* Nanoleaf - remove switchability

* Fix MultiColorAdjustment, if led-range is greater lednum

* Fix logging

* LedFileDevice/LedDevice - add testing support

* New "Led Test" effect

* LedDeviceFile - Add chrono include + Allow Led rewrites for testing

* Stabilize Effects for LedDevices where latchtime = 0

* Update LedDeviceFile, allow latchtime = 0

* Distangle LinearColorSmoothing and LEDDevice, Fix Effect configuration updates

* Updates LedDeviceFile - Initialize via Open

* Updates LedDeviceNanoleaf - Initialize via Open, Remove throwing exceptions

* Updates ProviderUDP - Remove throwing exceptions

* Framebuffer - Use precise timer

* TestSpi - Align to LedDevice updates

* Pretty Print CrossCompileHowTo as markdown-file

* Ensure that output is only written when LedDevice is ready

* Align APA102 Device to new device staging

* Logger - Remove clang warnings on extra semicolon

* Devices SPI - Align to Device stages and methods

* Fix cppcheck and clang findings

* Add Code-Template for new Devices

* Align devices to stages and methods, clean-up some code

* Allow to reopen LedDevice without restart

* Revert change "Remove Connect (PriorityMuxer::visiblePriorityChanged -> Hyperion::update) due to double writes"

* Remove visiblePriorityChanged from LedDevice to decouple LedDevice from hyperion logic

* Expose LedDevice getLedCount and align signedness
This commit is contained in:
LordGrey
2020-02-10 15:21:58 +01:00
committed by GitHub
parent 1aba51e85c
commit ed5455458b
107 changed files with 2980 additions and 1551 deletions

View File

@@ -5,7 +5,9 @@ LedDeviceAdalight::LedDeviceAdalight(const QJsonObject &deviceConfig)
, _headerSize(6)
, _ligthBerryAPA102Mode(false)
{
_deviceReady = init(deviceConfig);
_devConfig = deviceConfig;
_deviceReady = false;
connect(this,SIGNAL(receivedData(QByteArray)),this,SLOT(receivedData(QByteArray)));
}
@@ -16,7 +18,8 @@ LedDevice* LedDeviceAdalight::construct(const QJsonObject &deviceConfig)
bool LedDeviceAdalight::init(const QJsonObject &deviceConfig)
{
ProviderRs232::init(deviceConfig);
bool isInitOK = ProviderRs232::init(deviceConfig);
_ligthBerryAPA102Mode = deviceConfig["lightberry_apa102_mode"].toBool(false);
// create ledBuffer
@@ -30,7 +33,7 @@ bool LedDeviceAdalight::init(const QJsonObject &deviceConfig)
_ledBuffer.resize(_headerSize + (_ledCount * bytesPerRGBLed) + startFrameSize + endFrameSize, 0x00);
// init constant data values
for (signed iLed=1; iLed<=_ledCount; iLed++)
for (signed iLed=1; iLed<= static_cast<int>( _ledCount); iLed++)
{
_ledBuffer[iLed*4+_headerSize] = 0xFF;
}
@@ -52,14 +55,14 @@ bool LedDeviceAdalight::init(const QJsonObject &deviceConfig)
Debug( _log, "Adalight header for %d leds: %c%c%c 0x%02x 0x%02x 0x%02x", _ledCount,
_ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3], _ledBuffer[4], _ledBuffer[5] );
return true;
return isInitOK;
}
int LedDeviceAdalight::write(const std::vector<ColorRgb> & ledValues)
{
if(_ligthBerryAPA102Mode)
{
for (signed iLed=1; iLed<=_ledCount; iLed++)
for (signed iLed=1; iLed<=static_cast<int>( _ledCount); iLed++)
{
const ColorRgb& rgb = ledValues[iLed-1];
_ledBuffer[iLed*4+7] = rgb.red;

View File

@@ -1,5 +1,6 @@
#pragma once
// hyperion includes
#include "ProviderRs232.h"
///
@@ -15,12 +16,12 @@ public:
///
/// @param deviceConfig json device config
///
LedDeviceAdalight(const QJsonObject &deviceConfig);
explicit LedDeviceAdalight(const QJsonObject &deviceConfig);
/// constructs leddevice
static LedDevice* construct(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig) override;
public slots:
void receivedData(QByteArray data);
@@ -32,7 +33,7 @@ private:
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> & ledValues);
virtual int write(const std::vector<ColorRgb> & ledValues) override;
const short _headerSize;
bool _ligthBerryAPA102Mode;

View File

@@ -4,7 +4,8 @@
LedDeviceAtmo::LedDeviceAtmo(const QJsonObject &deviceConfig)
: ProviderRs232()
{
_deviceReady = init(deviceConfig);
_devConfig = deviceConfig;
_deviceReady = false;
}
LedDevice* LedDeviceAtmo::construct(const QJsonObject &deviceConfig)
@@ -14,21 +15,27 @@ LedDevice* LedDeviceAtmo::construct(const QJsonObject &deviceConfig)
bool LedDeviceAtmo::init(const QJsonObject &deviceConfig)
{
ProviderRs232::init(deviceConfig);
bool isInitOK = ProviderRs232::init(deviceConfig);
if (_ledCount != 5)
if ( isInitOK )
{
Error( _log, "%d channels configured. This should always be 5!", _ledCount);
return 0;
if (_ledCount != 5)
{
//Error( _log, "%d channels configured. This should always be 5!", _ledCount);
QString errortext = QString ("%1 channels configured. This should always be 5!").arg(_ledCount);
this->setInError(errortext);
isInitOK = false;
}
else
{
_ledBuffer.resize(4 + 5*3); // 4-byte header, 5 RGB values
_ledBuffer[0] = 0xFF; // Startbyte
_ledBuffer[1] = 0x00; // StartChannel(Low)
_ledBuffer[2] = 0x00; // StartChannel(High)
_ledBuffer[3] = 0x0F; // Number of Databytes send (always! 15)
}
}
_ledBuffer.resize(4 + 5*3); // 4-byte header, 5 RGB values
_ledBuffer[0] = 0xFF; // Startbyte
_ledBuffer[1] = 0x00; // StartChannel(Low)
_ledBuffer[2] = 0x00; // StartChannel(High)
_ledBuffer[3] = 0x0F; // Number of Databytes send (always! 15)
return true;
return isInitOK;
}
int LedDeviceAtmo::write(const std::vector<ColorRgb> &ledValues)

View File

@@ -1,6 +1,6 @@
#pragma once
// hyperion incluse
// hyperion includes
#include "ProviderRs232.h"
///
@@ -14,12 +14,12 @@ public:
///
/// @param deviceConfig json device config
///
LedDeviceAtmo(const QJsonObject &deviceConfig);
explicit LedDeviceAtmo(const QJsonObject &deviceConfig);
/// constructs leddevice
static LedDevice* construct(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig) override;
private:
///
@@ -28,5 +28,5 @@ private:
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> &ledValues);
virtual int write(const std::vector<ColorRgb> &ledValues) override;
};

View File

@@ -10,44 +10,8 @@ LedDeviceDMX::LedDeviceDMX(const QJsonObject &deviceConfig)
, _dmxLedCount(0)
, _dmxChannelCount(0)
{
_deviceReady = init(deviceConfig);
}
bool LedDeviceDMX::init(const QJsonObject &deviceConfig)
{
ProviderRs232::init(deviceConfig);
QString dmxString = deviceConfig["dmxdevice"].toString("invalid");
if (dmxString == "raw")
{
_dmxDeviceType = 0;
_dmxStart = 1;
_dmxSlotsPerLed = 3;
}
else if (dmxString == "McCrypt")
{
_dmxDeviceType = 1;
_dmxStart = 1;
_dmxSlotsPerLed = 4;
}
else
{
Error(_log, "unknown dmx device type %s", QSTRING_CSTR(dmxString));
}
Debug(_log, "_dmxString \"%s\", _dmxDeviceType %d", QSTRING_CSTR(dmxString), _dmxDeviceType );
_rs232Port.setStopBits(QSerialPort::TwoStop);
_dmxLedCount = qMin(_ledCount, 512/_dmxSlotsPerLed);
_dmxChannelCount = 1 + _dmxSlotsPerLed * _dmxLedCount;
Debug(_log, "_dmxStart %d, _dmxSlotsPerLed %d", _dmxStart, _dmxSlotsPerLed);
Debug(_log, "_ledCount %d, _dmxLedCount %d, _dmxChannelCount %d", _ledCount, _dmxLedCount, _dmxChannelCount);
_ledBuffer.resize(_dmxChannelCount, 0);
_ledBuffer[0] = 0x00; // NULL START code
return true;
_devConfig = deviceConfig;
_deviceReady = false;
}
LedDevice* LedDeviceDMX::construct(const QJsonObject &deviceConfig)
@@ -55,6 +19,48 @@ LedDevice* LedDeviceDMX::construct(const QJsonObject &deviceConfig)
return new LedDeviceDMX(deviceConfig);
}
bool LedDeviceDMX::init(const QJsonObject &deviceConfig)
{
bool isInitOK = ProviderRs232::init(deviceConfig);
if ( isInitOK )
{
QString dmxString = deviceConfig["dmxdevice"].toString("invalid");
if (dmxString == "raw")
{
_dmxDeviceType = 0;
_dmxStart = 1;
_dmxSlotsPerLed = 3;
}
else if (dmxString == "McCrypt")
{
_dmxDeviceType = 1;
_dmxStart = 1;
_dmxSlotsPerLed = 4;
}
else
{
//Error(_log, "unknown dmx device type %s", QSTRING_CSTR(dmxString));
QString errortext = QString ("unknown dmx device type: %1").arg(dmxString);
this->setInError(errortext);
return false;
}
Debug(_log, "_dmxString \"%s\", _dmxDeviceType %d", QSTRING_CSTR(dmxString), _dmxDeviceType );
_rs232Port.setStopBits(QSerialPort::TwoStop);
_dmxLedCount = qMin(static_cast<int>(_ledCount), 512/_dmxSlotsPerLed);
_dmxChannelCount = 1 + _dmxSlotsPerLed * _dmxLedCount;
Debug(_log, "_dmxStart %d, _dmxSlotsPerLed %d", _dmxStart, _dmxSlotsPerLed);
Debug(_log, "_ledCount %d, _dmxLedCount %d, _dmxChannelCount %d", _ledCount, _dmxLedCount, _dmxChannelCount);
_ledBuffer.resize(_dmxChannelCount, 0);
_ledBuffer[0] = 0x00; // NULL START code
}
return isInitOK;
}
int LedDeviceDMX::write(const std::vector<ColorRgb> &ledValues)
{
switch (_dmxDeviceType) {

View File

@@ -1,6 +1,6 @@
#pragma once
// hyperion incluse
// hyperion includes
#include "ProviderRs232.h"
///
@@ -14,12 +14,12 @@ public:
///
/// @param deviceConfig json device config
///
LedDeviceDMX(const QJsonObject &deviceConfig);
explicit LedDeviceDMX(const QJsonObject &deviceConfig);
/// constructs leddevice
static LedDevice* construct(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig) override;
private:
///
@@ -28,7 +28,7 @@ private:
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> &ledValues);
virtual int write(const std::vector<ColorRgb> &ledValues) override;
int _dmxDeviceType = 0;
int _dmxStart = 1;
int _dmxSlotsPerLed = 3;

View File

@@ -4,7 +4,9 @@
LedDeviceKarate::LedDeviceKarate(const QJsonObject &deviceConfig)
: ProviderRs232()
{
_deviceReady = init(deviceConfig);
_devConfig = deviceConfig;
_deviceReady = false;
connect(this,SIGNAL(receivedData(QByteArray)),this,SLOT(receivedData(QByteArray)));
}
@@ -15,23 +17,31 @@ LedDevice* LedDeviceKarate::construct(const QJsonObject &deviceConfig)
bool LedDeviceKarate::init(const QJsonObject &deviceConfig)
{
ProviderRs232::init(deviceConfig);
bool isInitOK = ProviderRs232::init(deviceConfig);
if (_ledCount != 16)
if ( isInitOK )
{
Error( _log, "%d channels configured. This should always be 16!", _ledCount);
return 0;
if (_ledCount != 16)
{
//Error( _log, "%d channels configured. This should always be 16!", _ledCount);
QString errortext = QString ("%1 channels configured. This should always be 16!").arg(_ledCount);
this->setInError(errortext);
isInitOK = false;
}
else
{
_ledBuffer.resize(4 + _ledCount * 3); // 4-byte header, 3 RGB values
_ledBuffer[0] = 0xAA; // Startbyte
_ledBuffer[1] = 0x12; // Send all Channels in Batch
_ledBuffer[2] = 0x00; // Checksum
_ledBuffer[3] = _ledCount * 3; // Number of Databytes send
Debug( _log, "Karatelight header for %d leds: 0x%02x 0x%02x 0x%02x 0x%02x", _ledCount,
_ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3] );
}
}
_ledBuffer.resize(4 + _ledCount * 3); // 4-byte header, 3 RGB values
_ledBuffer[0] = 0xAA; // Startbyte
_ledBuffer[1] = 0x12; // Send all Channels in Batch
_ledBuffer[2] = 0x00; // Checksum
_ledBuffer[3] = _ledCount * 3; // Number of Databytes send
Debug( _log, "Karatelight header for %d leds: 0x%02x 0x%02x 0x%02x 0x%02x", _ledCount,
_ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3] );
return true;
return isInitOK;
}
int LedDeviceKarate::write(const std::vector<ColorRgb> &ledValues)

View File

@@ -1,6 +1,6 @@
#pragma once
// hyperion incluse
// hyperion includes
#include "ProviderRs232.h"
///
@@ -15,12 +15,12 @@ public:
///
/// @param deviceConfig json device config
///
LedDeviceKarate(const QJsonObject &deviceConfig);
explicit LedDeviceKarate(const QJsonObject &deviceConfig);
/// constructs leddevice
static LedDevice* construct(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig) override;
public slots:
void receivedData(QByteArray data);
@@ -32,5 +32,5 @@ private:
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> &ledValues);
virtual int write(const std::vector<ColorRgb> &ledValues) override;
};

View File

@@ -9,7 +9,8 @@ struct FrameSpec
LedDeviceSedu::LedDeviceSedu(const QJsonObject &deviceConfig)
: ProviderRs232()
{
_deviceReady = init(deviceConfig);
_devConfig = deviceConfig;
_deviceReady = false;
}
LedDevice* LedDeviceSedu::construct(const QJsonObject &deviceConfig)
@@ -19,7 +20,7 @@ LedDevice* LedDeviceSedu::construct(const QJsonObject &deviceConfig)
bool LedDeviceSedu::init(const QJsonObject &deviceConfig)
{
ProviderRs232::init(deviceConfig);
bool isInitOK = ProviderRs232::init(deviceConfig);
std::vector<FrameSpec> frameSpecs{{0xA1, 256}, {0xA2, 512}, {0xB0, 768}, {0xB1, 1536}, {0xB2, 3072} };
@@ -38,11 +39,13 @@ bool LedDeviceSedu::init(const QJsonObject &deviceConfig)
if (_ledBuffer.size() == 0)
{
Warning(_log, "More rgb-channels required then available");
return false;
//Warning(_log, "More rgb-channels required then available");
QString errortext = "More rgb-channels required then available";
this->setInError(errortext);
isInitOK = false;
}
return true;
return isInitOK;
}
int LedDeviceSedu::write(const std::vector<ColorRgb> &ledValues)

View File

@@ -1,6 +1,6 @@
#pragma once
// hyperion incluse
// hyperion includes
#include "ProviderRs232.h"
///
@@ -14,12 +14,12 @@ public:
///
/// @param deviceConfig json device config
///
LedDeviceSedu(const QJsonObject &deviceConfig);
explicit LedDeviceSedu(const QJsonObject &deviceConfig);
/// constructs leddevice
static LedDevice* construct(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig) override;
private:
///
@@ -28,5 +28,5 @@ private:
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> &ledValues);
virtual int write(const std::vector<ColorRgb> &ledValues) override;
};

View File

@@ -4,7 +4,8 @@
LedDeviceTpm2::LedDeviceTpm2(const QJsonObject &deviceConfig)
: ProviderRs232()
{
_deviceReady = init(deviceConfig);
_devConfig = deviceConfig;
_deviceReady = false;
}
LedDevice* LedDeviceTpm2::construct(const QJsonObject &deviceConfig)
@@ -14,7 +15,7 @@ LedDevice* LedDeviceTpm2::construct(const QJsonObject &deviceConfig)
bool LedDeviceTpm2::init(const QJsonObject &deviceConfig)
{
ProviderRs232::init(deviceConfig);
bool isInitOK = ProviderRs232::init(deviceConfig);
_ledBuffer.resize(5 + _ledRGBCount);
_ledBuffer[0] = 0xC9; // block-start byte
@@ -23,7 +24,7 @@ bool LedDeviceTpm2::init(const QJsonObject &deviceConfig)
_ledBuffer[3] = _ledRGBCount & 0xFF; // frame size low byte
_ledBuffer.back() = 0x36; // block-end byte
return true;
return isInitOK;
}
int LedDeviceTpm2::write(const std::vector<ColorRgb> &ledValues)

View File

@@ -1,6 +1,6 @@
#pragma once
// hyperion incluse
// hyperion includes
#include "ProviderRs232.h"
///
@@ -14,12 +14,12 @@ public:
///
/// @param deviceConfig json device config
///
LedDeviceTpm2(const QJsonObject &deviceConfig);
explicit LedDeviceTpm2(const QJsonObject &deviceConfig);
/// constructs leddevice
static LedDevice* construct(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig) override;
private:
///
@@ -28,5 +28,5 @@ private:
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> &ledValues);
virtual int write(const std::vector<ColorRgb> &ledValues) override;
};

View File

@@ -27,6 +27,7 @@ ProviderRs232::ProviderRs232()
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()));
_writeTimeout.setInterval(5000);
_writeTimeout.setSingleShot(true);
connect(&_writeTimeout, SIGNAL(timeout()), this, SLOT(writeTimeout()));
@@ -36,7 +37,7 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig)
{
closeDevice();
LedDevice::init(deviceConfig);
bool isInitOK = LedDevice::init(deviceConfig);
_deviceName = deviceConfig["output"].toString("auto");
_enableAutoDeviceName = _deviceName == "auto";
@@ -44,7 +45,16 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig)
_delayAfterConnect_ms = deviceConfig["delayAfterConnect"].toInt(1500);
_preOpenDelay = deviceConfig["delayBeforeConnect"].toInt(1500);
return true;
return isInitOK;
}
void ProviderRs232::close()
{
LedDevice::close();
// LedDevice specific closing activites
closeDevice();
}
QString ProviderRs232::findSerialDevice()
@@ -56,7 +66,6 @@ QString ProviderRs232::findSerialDevice()
{
Info(_log, "found serial device: %s", port.systemLocation().toLocal8Bit().constData());
return port.systemLocation();
break;
}
}
return "";
@@ -122,6 +131,7 @@ void ProviderRs232::error(QSerialPort::SerialPortError error)
_deviceReady = false;
}
_rs232Port.clearError();
this->setInError( "Rs232 SerialPortError, see details in previous log lines!" );
closeDevice();
}
}
@@ -130,7 +140,6 @@ void ProviderRs232::error(QSerialPort::SerialPortError error)
ProviderRs232::~ProviderRs232()
{
disconnect(&_rs232Port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(error(QSerialPort::SerialPortError)));
closeDevice();
}
void ProviderRs232::closeDevice()
@@ -151,9 +160,27 @@ void ProviderRs232::closeDevice()
int ProviderRs232::open()
{
return tryOpen(_delayAfterConnect_ms) ? 0 : -1;
}
int retval = -1;
_deviceReady = false;
// General initialisation and configuration of LedDevice
if ( init(_devConfig) )
{
if ( tryOpen(_delayAfterConnect_ms) )
{
// Everything is OK -> enable device
_deviceReady = true;
setEnable(true);
retval = 0;
}
else
{
this->setInError( "Error opening device!" );
}
}
return retval;
}
bool ProviderRs232::tryOpen(const int delayAfterConnect_ms)
{
@@ -247,16 +274,13 @@ int ProviderRs232::writeBytes(const qint64 size, const uint8_t * data)
void ProviderRs232::writeTimeout()
{
Error(_log, "Timeout on write data to %s", _deviceName.toLocal8Bit().constData());
closeDevice();
//Error(_log, "Timeout on write data to %s", _deviceName.toLocal8Bit().constData());
QString errortext = QString ("Timeout on write data to %1").arg(_deviceName);
setInError( errortext );
close();
}
void ProviderRs232::unblockAfterDelay()
{
_blockedForDelay = false;
}
int ProviderRs232::rewriteLeds()
{
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}

View File

@@ -5,7 +5,7 @@
#include <QTimer>
#include <QString>
// Leddevice includes
// LedDevice includes
#include <leddevice/LedDevice.h>
///
@@ -26,28 +26,33 @@ public:
///
/// @param deviceConfig the json device config
/// @return true if success
virtual bool init(const QJsonObject &deviceConfig);
virtual bool init(const QJsonObject &deviceConfig) override;
///
/// Destructor of the LedDevice; closes the output device if it is open
///
virtual ~ProviderRs232();
virtual ~ProviderRs232() override;
///
/// Opens and configures the output device
///
/// @return Zero on succes else negative
///
int open();
int open() override;
public slots:
///
/// Closes the output device.
/// Includes switching-off the device and stopping refreshes
///
virtual void close() override;
private slots:
/// Write the last data to the leds again
int rewriteLeds();
/// Unblock the device after a connection delay
void writeTimeout();
void unblockAfterDelay();
void error(QSerialPort::SerialPortError error);
void error(QSerialPort::SerialPortError setInError);
void bytesWritten(qint64 bytes);
void readyRead();