diff --git a/AdaptiveBrightness/sensor_driver.cpp b/AdaptiveBrightness/sensor_driver.cpp index a13e5e6..9c80c41 100644 --- a/AdaptiveBrightness/sensor_driver.cpp +++ b/AdaptiveBrightness/sensor_driver.cpp @@ -9,11 +9,6 @@ #include "log_tr.hpp" -SensorDriver::Sensor::Sensor(const QString& serialPortName) : m_serialPortName(serialPortName) -{ - qInfo(ltr("Creating sensor on serial port %1").arg(m_serialPortName)); -} - SensorDriver::Sensor::~Sensor() { qDebug(ltr("Destroying sensor on serial port %1").arg(m_serialPortName)); @@ -43,6 +38,95 @@ std::vector SensorDriver::Sensor::readValues() const return parseReadResponse(response); } +SensorDriver::Sensor::Sensor(const QString& serialPortName) : m_serialPortName(serialPortName) +{ + qInfo(ltr("Creating sensor on serial port %1").arg(m_serialPortName)); +} + +bool SensorDriver::Sensor::isValidSensor() const +{ + const auto versionCmd = QByteArray(VERSION_CMD.data(), static_cast(VERSION_CMD.size())); + + QByteArray response; + + if(!getSensorCommandResponse(m_serialPortName, versionCmd, response)) { + if(!response.isEmpty()) { + qCritical(ltr("Only read \"%1\" from serial port %2").arg(QString(response)).arg(m_serialPortName)); + } + return false; + } + + const auto version = parseVersionResponse(response); + return version == "AdaptiveBrightness v1.2"; +} + +bool SensorDriver::Sensor::getSensorCommandResponse(const QString& serialPortName, QByteArray command, QByteArray& response) const +{ + QSerialPort serialPort; + serialPort.setPortName(serialPortName); + serialPort.setBaudRate(115200); + + if(!serialPort.open(QIODevice::ReadWrite)) { + qCritical(ltr("Unable to open serial port %1, error code: %2").arg(serialPortName).arg(serialPort.errorString())); + return false; + } + + qDebug(ltr("Sending \"%1\" command to serial port %2").arg(QString(command)).arg(serialPortName)); + + command.prepend("\r\n"); + command.append("\r\n"); + + const auto bytesWritten = serialPort.write(command); + + if(bytesWritten == -1) { + qCritical(ltr("Failed to write data to serial port %1, error code: %2").arg(serialPortName).arg(serialPort.errorString())); + return false; + } + else if(bytesWritten != command.size()) { + qCritical(ltr("Only %1/%2 bytes written to serial port %3, error: %4") + .arg(bytesWritten) + .arg(command.size()) + .arg(serialPortName) + .arg(serialPort.errorString())); + return false; + } + else if(!serialPort.waitForBytesWritten(100)) { + qCritical(ltr("Writing operation timed out for serial port %1, error: %2").arg(serialPortName).arg(serialPort.errorString())); + return false; + } + + while(serialPort.waitForReadyRead(100)) { + const auto newData = serialPort.readAll(); + qDebug(ltr("Read additional %1 bytes from serial port %2").arg(newData.size()).arg(serialPortName)); + response.append(newData); + } + + if(serialPort.error() == QSerialPort::ReadError) { + qCritical(ltr("Failed to read from serial port %1, error: %2").arg(serialPortName).arg(serialPort.errorString())); + return false; + } + else if(serialPort.error() == QSerialPort::TimeoutError && response.isEmpty()) { + qCritical(ltr("No data was read from serial port %1, error: %2").arg(serialPortName).arg(serialPort.errorString())); + return false; + } + + return true; +} + +std::string SensorDriver::Sensor::parseVersionResponse(const QByteArray& response) const +{ + const auto versionRegex = std::regex("[a-zA-Z]+ v[0-9]\\.[0-9]"); + const auto strResponse = response.toStdString(); + std::smatch versionMatch; + + if(std::regex_search(strResponse, versionMatch, versionRegex)) { + qDebug(ltr("Found version match: '%1'").arg(QString().fromStdString(versionMatch[0].str()))); + return versionMatch[0]; + } + + return {}; +} + std::pair SensorDriver::Sensor::parseRangeResponse(const QByteArray& response) const { const auto rangeRegex = std::regex("([0-9]+),([0-9]+)"); @@ -95,94 +179,11 @@ std::vector SensorDriver::enumerateSensors() const for(const auto& portInfo: portsInfo) { qDebug(ltr("Checking port %1").arg(portInfo.portName())); - if(isValidSensor(portInfo.portName())) { - sensors.emplace_back(portInfo.portName()); + auto sensor = Sensor(portInfo.portName()); + if(sensor.isValidSensor()) { + sensors.push_back(sensor); } } return std::move(sensors); } - -bool SensorDriver::getSensorCommandResponse(const QString& serialPortName, QByteArray command, QByteArray& response) -{ - QSerialPort serialPort; - serialPort.setPortName(serialPortName); - serialPort.setBaudRate(115200); - - if(!serialPort.open(QIODevice::ReadWrite)) { - qCritical(ltr("Unable to open serial port %1, error code: %2").arg(serialPortName).arg(serialPort.errorString())); - return false; - } - - qDebug(ltr("Sending \"%1\" command to serial port %2").arg(QString(command)).arg(serialPortName)); - - command.prepend("\r\n"); - command.append("\r\n"); - - const auto bytesWritten = serialPort.write(command); - - if(bytesWritten == -1) { - qCritical(ltr("Failed to write data to serial port %1, error code: %2").arg(serialPortName).arg(serialPort.errorString())); - return false; - } - else if(bytesWritten != command.size()) { - qCritical(ltr("Only %1/%2 bytes written to serial port %3, error: %4") - .arg(bytesWritten) - .arg(command.size()) - .arg(serialPortName) - .arg(serialPort.errorString())); - return false; - } - else if(!serialPort.waitForBytesWritten(100)) { - qCritical(ltr("Writing operation timed out for serial port %1, error: %2").arg(serialPortName).arg(serialPort.errorString())); - return false; - } - - while(serialPort.waitForReadyRead(100)) { - const auto newData = serialPort.readAll(); - qDebug(ltr("Read additional %1 bytes from serial port %2").arg(newData.size()).arg(serialPortName)); - response.append(newData); - } - - if(serialPort.error() == QSerialPort::ReadError) { - qCritical(ltr("Failed to read from serial port %1, error: %2").arg(serialPortName).arg(serialPort.errorString())); - return false; - } - else if(serialPort.error() == QSerialPort::TimeoutError && response.isEmpty()) { - qCritical(ltr("No data was read from serial port %1, error: %2").arg(serialPortName).arg(serialPort.errorString())); - return false; - } - - return true; -} - -bool SensorDriver::isValidSensor(const QString& serialPortName) const -{ - const auto versionCmd = QByteArray(VERSION_CMD.data(), static_cast(VERSION_CMD.size())); - - QByteArray response; - - if(!getSensorCommandResponse(serialPortName, versionCmd, response)) { - if(!response.isEmpty()) { - qCritical(ltr("Only read \"%1\" from serial port %2").arg(QString(response)).arg(serialPortName)); - } - return false; - } - - const auto version = parseVersionResponse(response); - return version == "AdaptiveBrightness v1.2"; -} - -std::string SensorDriver::parseVersionResponse(const QByteArray& response) const -{ - const auto versionRegex = std::regex("[a-zA-Z]+ v[0-9]\\.[0-9]"); - const auto strResponse = response.toStdString(); - std::smatch versionMatch; - - if(std::regex_search(strResponse, versionMatch, versionRegex)) { - qDebug(ltr("Found version match: '%1'").arg(QString().fromStdString(versionMatch[0].str()))); - return versionMatch[0]; - } - - return {}; -} diff --git a/AdaptiveBrightness/sensor_driver.hpp b/AdaptiveBrightness/sensor_driver.hpp index 0015ca9..87d5e88 100644 --- a/AdaptiveBrightness/sensor_driver.hpp +++ b/AdaptiveBrightness/sensor_driver.hpp @@ -10,15 +10,27 @@ class SensorDriver { class Sensor { public: - Sensor(const QString& serialPortName); ~Sensor(); std::pair readRange() const; std::vector readValues() const; private: + friend SensorDriver; + + Sensor(const QString& serialPortName); + + static constexpr auto VERSION_CMD = std::string_view{"version"}; + static constexpr auto RANGE_CMD = std::string_view{"range"}; + static constexpr auto READ_CMD = std::string_view{"read csv"}; + QString m_serialPortName; + bool isValidSensor() const; + + bool getSensorCommandResponse(const QString& serialPortName, QByteArray command, QByteArray& response) const; + + std::string parseVersionResponse(const QByteArray& response) const; std::pair parseRangeResponse(const QByteArray& response) const; std::vector parseReadResponse(const QByteArray& response) const; }; @@ -30,11 +42,4 @@ class SensorDriver { std::vector enumerateSensors() const; private: - static constexpr auto VERSION_CMD = std::string_view{"version"}; - static constexpr auto RANGE_CMD = std::string_view{"range"}; - static constexpr auto READ_CMD = std::string_view{"read csv"}; - - static bool getSensorCommandResponse(const QString& serialPortName, QByteArray command, QByteArray& response); - bool isValidSensor(const QString& serialPortName) const; - std::string parseVersionResponse(const QByteArray& response) const; };