/
pi_coder
/
ByteMachine
Обзор
Документация
Войти
/
pi_coder
/
ByteMachine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/nodes/com_writer_node.cpp
526 строк
16 KB
pimenov-and
Перенос функциональности из старого проекта, в основном это описания узлов
19 июл 2026, 20:13
19 июл 2026, 20:13
cb3c51b
Код
Авторство
О чём код?
//////////////////////////////////////////////////////////////// // ByteMachine // Узел для записи в COM-порта //////////////////////////////////////////////////////////////// #include "com_writer_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; //============================================================== // Конструктор с параметрами //============================================================== ComWriterNode::ComWriterNode(QUndoStack *undoStack, QObject *parent) : BaseNode{undoStack, parent} { name_ = nodeNameManager()->addName("comWriter"); Q_ASSERT(!name_.isEmpty()); createInputPin(); ComWriterNode::updateStateInfo(); } //============================================================== // Деструктор //============================================================== ComWriterNode::~ComWriterNode() { closePort(); } //============================================================== // Чтение из XML //============================================================== void ComWriterNode::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 ComWriterNode::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 ComWriterNode::draw(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); drawHighlight(painter, theme); drawSimpleBody(painter, theme); drawInputPins(painter, theme); drawStateArea(painter, theme); drawComment(painter, theme); } //============================================================== // Получение копии узла //============================================================== ShPtrBaseNode ComWriterNode::clone() const { const ShPtrComWriterNode cloneNode = ShPtrComWriterNode::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 ComWriterNode::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 ComWriterNode::openPort() { if (isOpenPort()) { return true; } comPort_.setPortName(portName_); comPort_.setBaudRate(comPortBaudRateToQtBaudRate(baudRate_), QSerialPort::Output); const bool isOpen = comPort_.open(QIODevice::WriteOnly); updateStateInfo(); if (isOpen) { emit sigChangedPortState(true); } return isOpen; } //============================================================== // Закрытие порта //============================================================== void ComWriterNode::closePort() { if (comPort_.isOpen()) { comPort_.close(); updateStateInfo(); emit sigChangedPortState(false); } } //============================================================== // Изменение состояния порта //============================================================== bool ComWriterNode::changeState() { if (isOpenPort()) { closePort(); return true; } else { return openPort(); } } //============================================================== // Получение размера данных //============================================================== size_t ComWriterNode::dataSize() const { if (stateInfo_.isError()) { return 0; } return inputPin_->dataSize(); } //============================================================== // Получение байта данных //============================================================== quint8 ComWriterNode::dataByte(std::size_t index) const { Q_ASSERT_X(index < dataSize(), "Check index", qPrintable(QString{"index: %1, dataSize: %2"}.arg(index).arg(dataSize()))); return inputPin_->dataByte(index); } //============================================================== // Получение блока данных //============================================================== ByteList ComWriterNode::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 inputPin_->dataBlock(index, count); } //============================================================== // Функция вызывается при изменении данных //============================================================== void ComWriterNode::dataChanged() { startHighlightTimer(); updateStateInfo(); if (!stateInfo_.isError() && (dataSize() > 0)) { const ByteList data = dataBlock(0, dataSize()); if (!writeDataToPort(data)) { qDebug() << "Not write to COM-port"; } } } //============================================================== // Получение входных пинов //============================================================== QVector<ShPtrInputPin> ComWriterNode::inputPins() { return QVector<ShPtrInputPin>{inputPin_}; } //============================================================== // Получение входных пинов (константный вариант) //============================================================== QVector<ShPtrConstInputPin> ComWriterNode::inputPins() const { return QVector<ShPtrConstInputPin>{inputPin_}; } //============================================================== // Задание имени порта //============================================================== void ComWriterNode::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 ComWriterNode::resetPortName() { setPortName("Unknown"); } //============================================================== // Задание частоты порта //============================================================== void ComWriterNode::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 ComWriterNode::resetBaudRate() { setBaudRate(ComPortBaudRates::Baud_9600); } //============================================================== // Задание режима пакетов //============================================================== void ComWriterNode::setPacketMode(ComPortPacketModes mode) { Q_UNUSED(mode) } //============================================================== // Сброс режима пакетов //============================================================== void ComWriterNode::resetPacketMode() { setPacketMode(ComPortPacketModes::Raw); } //============================================================== // Функция получения имени свойства для графического // интерфейса по его системному имени //============================================================== QString ComWriterNode::getUiPropertyName(const QString &systemName) { const QMap<QString, QString> map { {"name", tr("Name")}, {"left", tr("Left")}, {"top", tr("Top")}, {"width", tr("Width")}, {"height", tr("Height")}, {"topLeft", tr("Top and left")}, {"size", tr("Size")}, {"comment", tr("Comment")}, {"portName", tr("Port name")}, {"packetMode", tr("Packet mode")}, {"bypass", tr("Bypass")} }; return map.value(systemName, tr("Unknown")); } //============================================================== // Функция перевода //============================================================== void ComWriterNode::retranslate() { updateStateInfo(); } //============================================================== // Создание входного пина //============================================================== void ComWriterNode::createInputPin() { inputPin_ = ShPtrInputPin::create(this, 0); } //============================================================== // Вывод комментариев //============================================================== void ComWriterNode::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 ComWriterNode::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_); } } //============================================================== // Запись данных в порт //============================================================== bool ComWriterNode::writeDataToPort(const ByteList &bytes) { if (!isOpenPort() || (bytes.size() > 256)) { return false; } const QVector<quint8> data(bytes.cbegin(), bytes.cend()); const qint64 count = comPort_.write((const char*)data.data(), data.size()); return count == data.size(); } //============================================================== // Чтение имени порта из XML //============================================================== QString ComWriterNode::readPortNameFromXml(const QDomElement &elem) const { Q_ASSERT(!elem.isNull()); const QString propName = "portName"; Q_UNUSED(propName) return QString{}; } //============================================================== // Запись имени порта в XML //============================================================== void ComWriterNode::writePortNameToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); } //============================================================== // Чтение частоты порта из XML //============================================================== ComPortBaudRates ComWriterNode::readBaudRateFromXml( const QDomElement &elem) const { Q_ASSERT(!elem.isNull()); const QString propName = "baudRate"; Q_UNUSED(propName) return ComPortBaudRates::Baud_9600; } //============================================================== // Чтение режима разбора пакетов из XML //============================================================== ComPortPacketModes ComWriterNode::readPacketModeFromXml( const QDomElement &elem) const { Q_ASSERT(!elem.isNull()); const QString propName = "packetMode"; Q_UNUSED(propName) return ComPortPacketModes::Raw; } //============================================================== // Запись частоты порта в XML //============================================================== void ComWriterNode::writeBaudRateToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); } //============================================================== // Запись режима разбора пакетов из XML //============================================================== void ComWriterNode::writePacketModeToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); }