/
pi_coder
/
ByteMachine
Обзор
Документация
Войти
/
pi_coder
/
ByteMachine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/nodes/com_reader_node.cpp
542 строки
17 KB
pimenov-and
Перенос функциональности из старого проекта, в основном это описания узлов
19 июл 2026, 20:13
19 июл 2026, 20:13
cb3c51b
Код
Авторство
О чём код?
//////////////////////////////////////////////////////////////// // ByteMachine // Узел для чтения из COM-порта //////////////////////////////////////////////////////////////// #include "com_reader_node.h" #include "node_name_manager.h" #include "undo/undo_change_object_prop_value.h" #include "colors.h" #include <QPainter> #include <QDomDocument> #include <QUndoStack> //============================================================== using std::size_t; //============================================================== // Конструктор с параметрами //============================================================== ComReaderNode::ComReaderNode(QUndoStack *undoStack, QObject *parent) : BaseNode{undoStack, parent} { name_ = nodeNameManager()->addName("comReader"); Q_ASSERT(!name_.isEmpty()); createOutputPin(); setConnections(); ComReaderNode::updateStateInfo(); } //============================================================== // Деструктор //============================================================== ComReaderNode::~ComReaderNode() { closePort(); } //============================================================== // Чтение из XML //============================================================== void ComReaderNode::readFromXml(const QDomElement &elem) { Q_ASSERT(!elem.isNull()); const QString name = readNameFromXml(elem); const qint32 left = readLeftFromXml(elem); const qint32 top = readTopFromXml(elem); const QString portName = readPortNameFromXml(elem); const ComPortBaudRates baudRate = readBaudRateFromXml(elem); const ComPortPacketModes packetMode = readPacketModeFromXml(elem); const QString comment = readCommentFromXml(elem); setName(name); setLeft(left); setTop(top); setPortName(portName); setBaudRate(baudRate); setPacketMode(packetMode); setComment(comment); } //============================================================== // Запись в XML //============================================================== void ComReaderNode::writeToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); writeIdToXml(doc, elem); writeNameToXml(doc, elem); writeLeftToXml(doc, elem); writeTopToXml(doc, elem); writePortNameToXml(doc, elem); writeBaudRateToXml(doc, elem); writePacketModeToXml(doc, elem); writeCommentToXml(doc, elem); } //============================================================== // Рисование узла //============================================================== void ComReaderNode::draw(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); drawHighlight(painter, theme); drawSimpleBody(painter, theme); drawOutputPins(painter, theme); drawStateArea(painter, theme); drawComment(painter, theme); } //============================================================== // Получение копии узла //============================================================== ShPtrBaseNode ComReaderNode::clone() const { const ShPtrComReaderNode cloneNode = ShPtrComReaderNode::create( undoStack(), parent()); cloneNode->setUndo(true); cloneNode->setLeft(left()); cloneNode->setTop(top()); cloneNode->setPortName(portName()); cloneNode->setBaudRate(baudRate()); cloneNode->setPacketMode(packetMode()); cloneNode->setComment(comment()); cloneNode->setUndo(false); return cloneNode; } //============================================================== // Получение текста подсказки //============================================================== QString ComReaderNode::tooltipText() const { QString text{}; text += QString{"%1: \"%2\"\n"}.arg(tr("Name"), name()); text += QString{"%1: %2\n"}.arg(tr("Port name"), portName()); text += QString{"%1: %2\n"}.arg(tr("Baud rate")).arg(comPortBaudRateToInt(baudRate())); text += QString{"%1: %2\n"}.arg(tr("Packet mode"), comPortPacketModeToStrTr(packetMode_)); text += QString{"%1: \"%2\""}.arg(tr("Comment"), comment()); return text; } //============================================================== // Открытие порта //============================================================== bool ComReaderNode::openPort() { if (isOpenPort()) { return true; } comPort_.setPortName(portName_); comPort_.setBaudRate(comPortBaudRateToQtBaudRate(baudRate_), QSerialPort::Input); const bool isOpen = comPort_.open(QIODevice::ReadOnly); updateStateInfo(); if (isOpen) { emit sigChangedPortState(true); } return isOpen; } //============================================================== // Закрытие порта //============================================================== void ComReaderNode::closePort() { if (comPort_.isOpen()) { comPort_.close(); updateStateInfo(); emit sigChangedPortState(false); } } //============================================================== // Изменение состояния порта //============================================================== bool ComReaderNode::changeState() { if (isOpenPort()) { closePort(); return true; } else { return openPort(); } } //============================================================== // Получение размера данных //============================================================== size_t ComReaderNode::dataSize() const { if (stateInfo_.isError()) { return 0; } return buffer_.size(); } //============================================================== // Получение байта данных //============================================================== quint8 ComReaderNode::dataByte(size_t index) const { Q_ASSERT_X(index < dataSize(), "Check index", qPrintable(QString{"index: %1, dataSize: %2"}.arg(index).arg(dataSize()))); return buffer_[index]; } //============================================================== // Получение блока данных //============================================================== ByteList ComReaderNode::dataBlock(size_t index, size_t count) const { Q_ASSERT_X(index + count <= dataSize(), "Check index and count", qPrintable(QString{"Index: %1, Count: %2, DataSize: %3"}.arg(index).arg(count).arg(dataSize()))); return ByteList(buffer_.cbegin() + index, buffer_.cbegin() + index + count); } //============================================================== // Функция вызывается при изменении данных //============================================================== void ComReaderNode::dataChanged() { startHighlightTimer(); updateStateInfo(); outputPin_->dataChanged(); } //============================================================== // Получение выходных пинов //============================================================== QVector<ShPtrOutputPin> ComReaderNode::outputPins() { return QVector<ShPtrOutputPin>{outputPin_}; } //============================================================== // Получение выходных пинов (константный вариант) //============================================================== QVector<ShPtrConstOutputPin> ComReaderNode::outputPins() const { return QVector<ShPtrConstOutputPin>{outputPin_}; } //============================================================== // Задание имени порта //============================================================== void ComReaderNode::setPortName(const QString &portName) { if (portName_ != portName) { const QString oldPortName = portName_; portName_ = portName; const PropValue value{"portName", portName_}; emit sigChangedProp(value); if (!isUndo_) { Q_ASSERT(undoStack_ != nullptr); const auto undoCmd = new UndoChangeObjectPropValue{this, "portName", portName_, oldPortName}; undoStack_->push(undoCmd); } closePort(); startHighlightTimer(); } } //============================================================== // Сброс имени порта //============================================================== void ComReaderNode::resetPortName() { setPortName("Unknown"); } //============================================================== // Задание частоты порта //============================================================== void ComReaderNode::setBaudRate(ComPortBaudRates baud) { if (baudRate_ != baud) { const ComPortBaudRates oldBaud = baudRate_; baudRate_ = baud; const PropValue value{"baudRate", QVariant::fromValue(baudRate_)}; emit sigChangedProp(value); if (!isUndo_) { Q_ASSERT(undoStack_ != nullptr); const auto undoCmd = new UndoChangeObjectPropValue{this, "baudRate", QVariant::fromValue(baudRate_), QVariant::fromValue(oldBaud)}; undoStack_->push(undoCmd); } closePort(); startHighlightTimer(); } } //============================================================== // Сброс частоты порта //============================================================== void ComReaderNode::resetBaudRate() { setBaudRate(ComPortBaudRates::Baud_9600); } //============================================================== // Задание режима пакетов //============================================================== void ComReaderNode::setPacketMode(ComPortPacketModes mode) { Q_UNUSED(mode) } //============================================================== // Сброс режима пакетов //============================================================== void ComReaderNode::resetPacketMode() { setPacketMode(ComPortPacketModes::Raw); } //============================================================== // Функция получения имени свойства для графического // интерфейса по его системному имени //============================================================== QString ComReaderNode::getUiPropertyName(const QString &systemName) { const QMap<QString, QString> map { {"name", "Name"}, {"left", "Left"}, {"top", "Top"}, {"width", "Width"}, {"height", tr("Height")}, {"topLeft", tr("Top and left")}, {"size", tr("Size")}, {"comment", tr("Comment")}, {"portName", tr("Port name")}, {"baudRate", tr("Baud rate")}, {"packetMode", tr("Packet mode")} }; return map.value(systemName, tr("Unknown")); } //============================================================== // Функция перевода //============================================================== void ComReaderNode::retranslate() { updateStateInfo(); } //============================================================== // Функция вызывается при подключении выходного пина //============================================================== void ComReaderNode::slotOutputPinConnectChanged(ConnectStates state, InputPin *pin) { Q_ASSERT(!isUnknown(state)); Q_ASSERT(pin != nullptr); dataChanged(); const int conNodeId = pin->parentNode()->id(); const int conPinIndex = pin->parentNode()->indexOfInputPin(pin); const bool isCon = ::isConnect(state); emit sigChangedConnect(0, conNodeId, conPinIndex, isCon); } //============================================================== // Функция вызывается при появлении данных в COM-порте //============================================================== void ComReaderNode::slotReadyReadData() { const QByteArray data = comPort_.readAll(); buffer_ = ByteList(data.constBegin(), data.constEnd()); dataChanged(); } //============================================================== // Задание соединений //============================================================== void ComReaderNode::setConnections() { connect(&comPort_, &QSerialPort::readyRead, this, &ComReaderNode::slotReadyReadData); } //============================================================== // Создание выходного пина //============================================================== void ComReaderNode::createOutputPin() { outputPin_ = ShPtrOutputPin::create(this, 0); connect(outputPin_.get(), &OutputPin::sigConnectChanged, this, &ComReaderNode::slotOutputPinConnectChanged); } //============================================================== // Вывод комментариев //============================================================== void ComReaderNode::drawComment(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); if (isCommentsVisible()) { QString comments{}; comments += QString{" <<< %1: \"%2\"\n"}.arg(tr("Name"), name()); comments += QString{" %1: %2\n"}.arg(tr("Port name"), portName()); comments += QString{" %1: %2\n"}.arg(tr("Baud rate")).arg(comPortBaudRateToInt(baudRate())); comments += QString{" %1: %2\n"}.arg(tr("Packet mode"), comPortPacketModeToStrTr(packetMode())); comments += QString{" %1: \"%2\"\n"}.arg(tr("Comment"), comment()); #ifdef QT_DEBUG comments += " -\n"; comments += QString{" %1: %2\n"}.arg("Id").arg(id()); #endif // QT_DEBUG const int commentsLeft = right(); const int commentsTop = top() + (headerHeight() - charHeight()) / 2; const int commentsFlags = Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip; const QRect commentsRect{commentsLeft, commentsTop, 0, 0}; painter->setPen(Colors::nodeText(theme)); painter->drawText(commentsRect, commentsFlags, comments); } } //============================================================== // Обновление состояния узла //============================================================== void ComReaderNode::updateStateInfo() { const NodeStateInfo oldStateInfo = stateInfo_; if (!isPortNameModified()) { const QString msg = tr("Port name not valid"); stateInfo_ = NodeStateInfo{NodeStates::Error, msg}; } else if (isUnknown(baudRate())) { const QString msg = tr("Baud rate not valid"); stateInfo_ = NodeStateInfo{NodeStates::Error, msg}; } else if (!isOpenPort()) { const QString msg = tr("Port not open"); stateInfo_ = NodeStateInfo{NodeStates::Error, msg}; } else { stateInfo_ = NodeStateInfo{NodeStates::Success, QString{}}; } if (stateInfo_ != oldStateInfo) { emit sigChangedState(stateInfo_); } } //============================================================== // Чтение имени порта из XML //============================================================== QString ComReaderNode::readPortNameFromXml(const QDomElement &elem) const { Q_ASSERT(!elem.isNull()); const QString propName = "portName"; Q_UNUSED(propName) return QString{}; } //============================================================== // Запись имени порта в XML //============================================================== void ComReaderNode::writePortNameToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); } //============================================================== // Чтение частоты порта из XML //============================================================== ComPortBaudRates ComReaderNode::readBaudRateFromXml( const QDomElement &elem) const { Q_ASSERT(!elem.isNull()); const QString propName = "baudRate"; Q_UNUSED(propName) return ComPortBaudRates::Baud_9600; } //============================================================== // Чтение режима разбора пакетов из XML //============================================================== ComPortPacketModes ComReaderNode::readPacketModeFromXml( const QDomElement &elem) const { Q_ASSERT(!elem.isNull()); const QString propName = "packetMode"; Q_UNUSED(propName) return ComPortPacketModes::Raw; } //============================================================== // Запись частоты порта в XML //============================================================== void ComReaderNode::writeBaudRateToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); } //============================================================== // Запись режима разбора пакетов из XML //============================================================== void ComReaderNode::writePacketModeToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); }