File indexing completed on 2024-05-12 04:41:10

0001 /* AtCore KDE Libary for 3D Printers
0002     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0003     SPDX-FileCopyrightText: 2016-2018 Patrick José Pereira <patrickjp@kde.org>
0004     SPDX-FileCopyrightText: 2016-2018 Chris Rizzitello <rizzitello@kde.org>
0005     SPDX-FileCopyrightText: 2016, 2018 Tomaz Canabrava <tcanabrava@kde.org>
0006     SPDX-FileCopyrightText: 2018 Leandro Santiago <leandrosansilva@gmail.com>
0007 */
0008 
0009 #include <QLoggingCategory>
0010 
0011 #include "seriallayer.h"
0012 
0013 Q_LOGGING_CATEGORY(SERIAL_LAYER, "org.kde.atelier.core.serialLayer")
0014 
0015 /**
0016  * @brief The SerialLayerPrivate class
0017  */
0018 struct SerialLayer::SerialLayerPrivate {
0019     /** _lastError: the last reported error */
0020     QSerialPort::SerialPortError _lastError = QSerialPort::NoError;
0021     /** New Line String */
0022     static const QByteArray _newLine;
0023     /** New Line Return String */
0024     static const QByteArray _newLineReturn;
0025     /** _rawData: the raw serial data */
0026     QByteArray _rawData;
0027     /** _rByteCommand: received Messages */
0028     QVector<QByteArray> _rByteCommands;
0029     /** Return String */
0030     static const QByteArray _return;
0031     /** _sByteCommand: sent Messages */
0032     QVector<QByteArray> _sByteCommands;
0033     /** _serialOpened: is Serial port opened */
0034     bool _serialOpened = false;
0035     /** List of valid Baud Rates */
0036     static const QStringList _validBaudRates;
0037 };
0038 
0039 const QByteArray SerialLayer::SerialLayerPrivate::_newLine = QByteArray("\n");
0040 const QByteArray SerialLayer::SerialLayerPrivate::_newLineReturn = QByteArray("\n\r");
0041 const QByteArray SerialLayer::SerialLayerPrivate::_return = QByteArray("\r");
0042 const QStringList SerialLayer::SerialLayerPrivate::_validBaudRates = {QStringLiteral("9600"),
0043                                                                       QStringLiteral("14400"),
0044                                                                       QStringLiteral("19200"),
0045                                                                       QStringLiteral("28800"),
0046                                                                       QStringLiteral("38400"),
0047                                                                       QStringLiteral("57600"),
0048                                                                       QStringLiteral("76800"),
0049                                                                       QStringLiteral("115200"),
0050                                                                       QStringLiteral("230400"),
0051                                                                       QStringLiteral("250000"),
0052                                                                       QStringLiteral("500000"),
0053                                                                       QStringLiteral("1000000")};
0054 
0055 SerialLayer::SerialLayer(const QString &port, int32_t baud, QObject *parent)
0056     : QSerialPort(parent)
0057     , d(new SerialLayerPrivate())
0058 {
0059     setPortName(port);
0060     setBaudRate(baud);
0061     if (open(QIODevice::ReadWrite)) {
0062         d->_serialOpened = true;
0063         connect(this, &QSerialPort::readyRead, this, &SerialLayer::readAllData);
0064         connect(this, &QSerialPort::errorOccurred, this, &SerialLayer::handleError);
0065     }
0066 }
0067 
0068 SerialLayer::~SerialLayer()
0069 {
0070     delete d;
0071 };
0072 
0073 void SerialLayer::readAllData()
0074 {
0075     d->_rawData.append(readAll());
0076 
0077     // Remove any \r in the string, then split by \n.
0078     // This removes any trailing \r or \n from the commands
0079     // Proper line endings are added when the command is pushed.
0080     d->_rawData = d->_rawData.replace(d->_return, QByteArray());
0081 
0082     QList<QByteArray> tempList = d->_rawData.split(d->_newLine.at(0));
0083     for (auto i = tempList.begin(); i != tempList.end(); ++i) {
0084         // Get finished line to _byteCommands
0085         if (i < tempList.end() - 1) {
0086             d->_rByteCommands.append(*i);
0087             Q_EMIT receivedCommand(*i);
0088         } else {
0089             d->_rawData.clear();
0090             d->_rawData.append(*i);
0091         }
0092     }
0093 }
0094 
0095 void SerialLayer::pushCommand(const QByteArray &comm, const QByteArray &term)
0096 {
0097     if (!isOpen()) {
0098         qCDebug(SERIAL_LAYER) << "Serial not connected !";
0099         return;
0100     }
0101     QByteArray tmp = comm + term;
0102     write(tmp);
0103     Q_EMIT pushedCommand(tmp);
0104 }
0105 
0106 void SerialLayer::pushCommand(const QByteArray &comm)
0107 {
0108     pushCommand(comm, d->_newLineReturn);
0109 }
0110 
0111 void SerialLayer::add(const QByteArray &comm, const QByteArray &term)
0112 {
0113     QByteArray tmp = comm + term;
0114     d->_sByteCommands.append(tmp);
0115 }
0116 
0117 void SerialLayer::add(const QByteArray &comm)
0118 {
0119     add(comm, d->_newLineReturn);
0120 }
0121 
0122 void SerialLayer::push()
0123 {
0124     if (!isOpen()) {
0125         qCDebug(SERIAL_LAYER) << "Serial not connected !";
0126         return;
0127     }
0128     for (const auto &comm : qAsConst(d->_sByteCommands)) {
0129         write(comm);
0130         Q_EMIT pushedCommand(comm);
0131     }
0132     d->_sByteCommands.clear();
0133 }
0134 
0135 bool SerialLayer::commandAvailable() const
0136 {
0137     return !d->_rByteCommands.isEmpty();
0138 }
0139 
0140 QStringList SerialLayer::validBaudRates() const
0141 {
0142     return d->_validBaudRates;
0143 }
0144 
0145 void SerialLayer::handleError(QSerialPort::SerialPortError error)
0146 {
0147     if (d->_lastError == error) {
0148         return;
0149     }
0150 
0151     d->_lastError = error;
0152     Q_EMIT serialError(error);
0153 }