#include "unioncom.h" #include "ui_unioncom.h" #include "ProjectSettings.h" #include #include "QDialogButtonBox" QWidget* init(QWidget *parent) { return new UnionCOM(parent); } ////////////// //Оглавление// ////////////// /* Прототипы статичных функций - строка №51 Callback функции - строка №83 Инициализация программы - строка №223 Очистка логгера от сообщений - строка №349 Включение и отключение Modbus - строка №369 Настройки подключения в зависимости от типа - строка №408 Подключение устройства или com-порта - строка №478 Отключение устройства или com-порта - строка №687 Приём данных - строка №794 Загрузка файла - строка №1487 Базовые функции отправки данных - строка №1647 Отправка команды из строки - строка №1765 Отправка пакета байтов, задаваемых на форме в HEX - строка №1970 Отправка файла - строка №2187 Работа с макросами - строка №2428 */ UnionCOM *com_target; CanUsb *wCan = nullptr; USettingsRS *wRS = nullptr; union_modbus *ModbusMaster = nullptr; union_modbus_slave *ModbusSlave = nullptr; unsigned div_up(unsigned x, unsigned y) {return (x - 1) / y + 1;} /////////////////////////////// //Прототипы статичных функций// /////////////////////////////// static void turnOnSendFile(); static void turnOnCMDTX(); static void turnOnCMDHEXTX(); static void turnOnMcrsTX(int index); static void stepToStartMCRS1(); static void stepToStartMCRS2(); static void stepToStartMCRS3(); static void stepToStartMCRS4(); static void stepToStartMCRS5(); static void stepToStartMCRS6(); static void stepToStartMCRS7(); static void stepToStartMCRS8(); static void stepToStartMCRS9(); static void stepToStartMCRS10(); static void stepToStartMCRS11(); static void stepToStartMCRS12(); static void stepToStartMCRS13(); static void stepToStartMCRS14(); static void stepToStartMCRS15(); void (*funcptr[])(){stepToStartMCRS1, stepToStartMCRS2, stepToStartMCRS3, stepToStartMCRS4, stepToStartMCRS5, stepToStartMCRS6, stepToStartMCRS7, stepToStartMCRS8, stepToStartMCRS9, stepToStartMCRS10, stepToStartMCRS11, stepToStartMCRS12, stepToStartMCRS13, stepToStartMCRS14, stepToStartMCRS15}; static void canReaderThread(UnionCOM* obj); //////////////////// //Callback функции// //////////////////// //Callback функция из библиотеки SlCan, обрабатывающая изменения состояния устройства slcan. static void __stdcall Device_Callback(HSLCAN cbDevice, DWORD dwIndex, DWORD dwOperation, PVOID pContext, DWORD dwContextSize) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Изменение состояния устройства slcan."); qDebug() << msg; //dwIndex - номер устройства в списке устройств. if(dwIndex!=0) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] dwIndex = %1.").arg(dwIndex); qDebug() << msg; } //pContext - указатель на контекст устройства. if(pContext!=nullptr) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] pContext = %1.").arg((long long int)pContext); qDebug() << msg; } //dwContextSize - размер контекста устройства в байтах. if(dwContextSize!=0) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] dwContextSize = %1.").arg(dwContextSize); qDebug() << msg; } static bool DevOp_Close; //Пополнение в списке доступных для работы устройств. if(dwOperation == SLCAN_DEVOP_CREATE) { wCan->Refresh(); if(wCan->GetCount()==0) { com_target->gotors(); } } //Открытие устройства для работы. else if(dwOperation == SLCAN_DEVOP_OPEN) { com_target->Connect_Notification(); } //Закрытие устройства для работы в нормальных условиях. else if(dwOperation == SLCAN_DEVOP_CLOSE) { com_target->Disconnect_Notification(); //Флаг необходим, т.к. после отключения Callback функция сработает повторно с операцией SLCAN_DEVOP_DESTROYHANDLE. DevOp_Close=1; } //Закрытие (в том числе - аварийное) устройства. else if(dwOperation == SLCAN_DEVOP_DESTROYHANDLE) { if(com_target->device == cbDevice) { //Очистка буффера отправляемых фреймов SlCan_DevicePurge(com_target->device, SLCAN_PURGE_TX_ABORT|SLCAN_PURGE_TX_CLEAR); SlCan_DeviceClose(com_target->device); com_target->AfterDisconnection(); if(DevOp_Close==0) { //Уведомление о аварийном отключении устройства. com_target->Emergency_Disconnect_Notification(); } DevOp_Close=0; } //Обновление списка устройств. wCan->Refresh(); if(wCan->GetCount()==0) { com_target->gotors(); } } //Выбывание устройства из списка доступных устройств. else if(dwOperation == SLCAN_DEVOP_DESTROY) { wCan->Refresh(); if(wCan->GetCount()==0) { com_target->gotors(); } } } ///Callback функция изменения состояния списка устройств slcan. static void __stdcall DeviceList_Callback(HSLCAN cbDevice, DWORD dwIndex, PVOID pContext, DWORD dwContextSize) { //cbDevice - ссылнка на устройство //Если параметр равен 0xFFFFFFFF, то это означает, что список устройств изменился. if((unsigned long long int)cbDevice==0xffffffff) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Изменение состояние списка устройств slcan."); qDebug() << msg; } //Если параметр не равен 0xFFFFFFFF, то это означает, //что вновь подключенное устройство уже добавлено //в спиок и с ним можно работать, например, //открыть и передавать и принимать фреймы. else { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] cbDevice = %1.").arg((unsigned long long int)cbDevice); qDebug() << msg; } //dwIndex - номер устройства в списке устройств. //Может принимать значение 0xFFFFFFFF. if(dwIndex!=0) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] dwIndex = %1.").arg(dwIndex); qDebug() << msg; } //pContext - указатель на контекст устройства. if(pContext!=nullptr) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] pContext = %1.").arg((long long int)pContext); qDebug() << msg; } //dwContextSize - размер контекста устройства в байтах. if(dwContextSize!=0) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] dwContextSize = %1.").arg(dwContextSize); qDebug() << msg; } //Обновление списка доступных устройств. wCan->Refresh(); if(wCan->GetCount()==0) { com_target->gotors(); } } static const int THREAD_COUNT = QThread::idealThreadCount(); /////////////////////////// //Инициализация программы// /////////////////////////// UnionCOM::UnionCOM(QWidget *parent) : QWidget(parent), ui(new Ui::UnionCOM) { ui->setupUi(this); com_target=this; Init(); } UnionCOM::~UnionCOM() { if(ui->buttonDisconnect->isEnabled()) { on_buttonDisconnect_clicked(); } delete ui; } void UnionCOM::Init() { m_serial = new QSerialPort(this); SettingWidget(); AfterDisconnection(); ui->widgetsModbus->hide(); //HEX поля для ввода байтов. { HEXByteField[0] = ui->HEXByte_0; HEXByteField[1] = ui->HEXByte_1; HEXByteField[2] = ui->HEXByte_2; HEXByteField[3] = ui->HEXByte_3; HEXByteField[4] = ui->HEXByte_4; HEXByteField[5] = ui->HEXByte_5; HEXByteField[6] = ui->HEXByte_6; HEXByteField[7] = ui->HEXByte_7; } //Кнопки макросов. { McrsButtons[0] = ui->buttonMacros_01; McrsButtons[1] = ui->buttonMacros_02; McrsButtons[2] = ui->buttonMacros_03; McrsButtons[3] = ui->buttonMacros_04; McrsButtons[4] = ui->buttonMacros_05; McrsButtons[5] = ui->buttonMacros_06; McrsButtons[6] = ui->buttonMacros_07; McrsButtons[7] = ui->buttonMacros_08; McrsButtons[8] = ui->buttonMacros_09; McrsButtons[9] = ui->buttonMacros_10; McrsButtons[10] = ui->buttonMacros_11; McrsButtons[11] = ui->buttonMacros_12; McrsButtons[12] = ui->buttonMacros_13; McrsButtons[13] = ui->buttonMacros_14; McrsButtons[14] = ui->buttonMacros_15; } //Кнопки остановки переодической отправки макросов. { McrsStopButtons[0] = ui->buttonStopMacros_01; McrsStopButtons[1] = ui->buttonStopMacros_02; McrsStopButtons[2] = ui->buttonStopMacros_03; McrsStopButtons[3] = ui->buttonStopMacros_04; McrsStopButtons[4] = ui->buttonStopMacros_05; McrsStopButtons[5] = ui->buttonStopMacros_06; McrsStopButtons[6] = ui->buttonStopMacros_07; McrsStopButtons[7] = ui->buttonStopMacros_08; McrsStopButtons[8] = ui->buttonStopMacros_09; McrsStopButtons[9] = ui->buttonStopMacros_10; McrsStopButtons[10] = ui->buttonStopMacros_11; McrsStopButtons[11] = ui->buttonStopMacros_12; McrsStopButtons[12] = ui->buttonStopMacros_13; McrsStopButtons[13] = ui->buttonStopMacros_14; McrsStopButtons[14] = ui->buttonStopMacros_15; } //Стартовые значения макросов. { for(int i = 0; i < 15; i++) { //Имя макроса по умолчанию - название кнопки. "М" + номер макроса. MacrosMain[i].Name = McrsButtons[i]->text(); //Поле макроса MacrosMain[i].Mcrs.clear(); //Макрос задаётся в HEX или символами. По умолчанию - символы. MacrosMain[i].IsHEX = Qt::Unchecked; MacrosMain[i].DLC = 8; //Отправляется ли макрос раз в N период. По умолчанию - нет. MacrosMain[i].IsPeriod = Qt::Unchecked; //Количество отправок за одну передачу. По умолчанию - 1. MacrosMain[i].Count = 1; //Период в мс. По умолчанию - 1. MacrosMain[i].Period = 1; } } //Выключаются кнопки макросов при запуске приложения. { for(int i = 0; i < 15; i++) { McrsStopButtons[i]->setEnabled(FALSE); notTimeToStopPeriodMcrs[i]=FALSE; } } //Создаются таймеры для периодических макросов. { for(int index = 0; index < 15; index++) { McrsPeriodTransfer[index] = new QTimer(this); McrsPeriodTransfer[index]->setSingleShot(TRUE); connect(McrsPeriodTransfer[index], &QTimer::timeout, this, funcptr[index]); } } ui->groupRXErrors->hide(); ui->groupTXErrors->hide(); tableInit(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Инициализация завершена."); qDebug()<cboxTypeConnection->setCurrentIndex(1); } //////////////////////////////// //Очистка логгера от сообщений// //////////////////////////////// void UnionCOM::appendToLogger(QString msgToLogger) { ui->logger->append(msgToLogger); } void UnionCOM::on_buttonClearLogger_clicked() { ui->logger->clear(); RxCanModel->removeRows(0, RxCanModel->rowCount()); RxCanRequesterModel->removeRows(0, RxCanRequesterModel->rowCount()); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Очистка логгера."; counterOfLoggerMSG=0; qDebug() << msg; } ///////////////////////////////// //Включение и отключение Modbus// ///////////////////////////////// void UnionCOM::on_checkModbusEnabled_stateChanged(int arg1) { if(ui->checkModbusEnabled->checkState()==Qt::Checked) { ui->verticalSpacerModbus->changeSize(0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); ui->widgetsModbus->show(); ModbusMaster = new union_modbus(nullptr); ModbusSlave = new union_modbus_slave(nullptr); ui->widgetsModbus->addTab(ModbusMaster, "Master"); ui->widgetsModbus->addTab(ModbusSlave, "Slave"); } else { if(ModbusMaster!=nullptr) { ModbusMaster->close(); ModbusMaster->~union_modbus(); ModbusMaster = nullptr; } if(ModbusSlave!=nullptr) { ModbusSlave->close(); ModbusSlave->~union_modbus_slave(); ModbusSlave = nullptr; } ui->verticalSpacerModbus->changeSize(0, 50, QSizePolicy::Expanding, QSizePolicy::Expanding); ui->widgetsModbus->hide(); } } ///////////////////////// //Настройки подключения// //в зависимости от типа// ///////////////////////// //QT-слот, срабатывающий при изменении типа подключения. void UnionCOM::on_cboxTypeConnection_currentIndexChanged(int index) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Изменение типа подключения. Текущий тип: "); switch (index) { case 0: msg += "CAN."; break; case 1: msg += "RS."; break; } qDebug() << msg; SettingWidget(); } void UnionCOM::SettingWidget() { switch (ui->cboxTypeConnection->currentIndex()) { case 0: //CAN //Если перед этим было открыто окно настроек для RS - оно закрывается. { if (wRS) { wRS->close(); delete wRS; wRS=nullptr; } //Загрузка библиотеки и настраивание callback функций. SlCan_Load(Device_Callback, DeviceList_Callback); //Создание окна настроек CAN. wCan = new CanUsb(ui->widget); if(wCan->GetCount()==0) { ui->cboxTypeConnection->setCurrentIndex(1); } else { //Отображение окна wCan->show(); } break; } case 1: //RS //Если перед этим было открыто окно настроек для CAN - оно закрывается. Освобождается библиотека. { if (wCan) { SlCan_Free(FALSE); wCan->close(); delete wCan; wCan=nullptr; } } //Создание окна настроек RS. wRS = new USettingsRS(ui->widget); //Отображение окна. wRS->show(); break; } } ////////////////////////// //Подключение устройства// // или com-порта // ////////////////////////// QString UnionCOM::errors_RS(int ConnectionError) { QString error_msg = QString::number(ConnectionError, 10); error_msg += ": "; switch (ConnectionError) { case 0: error_msg += "No error occurred."; break; case 1: error_msg += "An error occurred while attempting to open an non-existing device."; break; case 2: error_msg += "An error occurred while attempting to open an already opened device by another process or a user not having enough permission and credentials to open."; break; case 3: error_msg += "An error occurred while attempting to open an already opened device in this object."; break; case 4: error_msg += "Parity error detected by the hardware while reading data. This value is obsolete. We strongly advise against using it in new code."; break; case 5: error_msg += "Framing error detected by the hardware while reading data. This value is obsolete. We strongly advise against using it in new code."; break; case 6: error_msg += "Break condition detected by the hardware on the input line. This value is obsolete. We strongly advise against using it in new code."; break; case 7: error_msg += "An I/O error occurred while writing the data."; break; case 8: error_msg += "An I/O error occurred while reading the data."; break; case 9: error_msg += "An I/O error occurred when a resource becomes unavailable, e.g. when the device is unexpectedly removed from the system."; break; case 10: error_msg += "The requested device operation is not supported or prohibited by the running operating system."; break; case 11: error_msg += "An unidentified error occurred."; break; case 12: error_msg += "A timeout error occurred."; break; case 13: error_msg += "This error occurs when an operation is executed that can only be successfully performed if the device is open."; break; } return error_msg; } //QT-слот, обрабатывающий подключение устройства/порта в зависимости от выбранного типа подключения. void UnionCOM::on_buttonConnect_clicked() { switch (ui->cboxTypeConnection->currentIndex()) { case 0: //CAN openCAN(); break; case 1: //RS openSerialPort(); break; } } //Функция открытия устройства CAN. void UnionCOM::openCAN() { //Если было подключено устройство - отключаем. SlCan_DeviceClose(device); //Получаем ссылку на новое устройство. device = wCan->GetDevice(); //Получаем настройки устройства и сообщений. int indx = wCan->GetBR(); //Получаем режим устройства. SLCAN_MODE = wCan->GetMode(); br.BRP = 0x8000 + indx; ID = wCan->GetID(); //Попытка открыть устройство. if(SlCan_DeviceOpen(device)) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Настройка устройства CAN."; qDebug() << msg; //Настройка устройства. //Устройство переходит в режим настройки. SlCan_DeviceSetMode(device, SLCAN_MODE_CONFIG); //Настройка битрейта. SlCan_DeviceSetBitRate(device, &br); //Настройка уровня генерации событий. SlCan_DeviceSetEventLevel(device, SLCAN_EVT_LEVEL_ERRORS); // SlCan_DeviceSetStartTimeStamp(device, 0); SlCan_DeviceSetTimeStampPeriod(device, 1); //Устройство возвращается к работе. SlCan_DeviceSetMode(device, SLCAN_MODE); //Настройка сообщения. outMsg.ID = ID; outMsg.Info = SLCAN_MES_INFO_EXT; outMsg.DataCount = 8; //Перевод режима работы приложения с этапа настройки на этап работы с выбранным устройством. AfterConnection(); timeFromRXErrorClear = new QTimer(); timeFromTXErrorClear = new QTimer(); connect(timeFromRXErrorClear, SIGNAL(timeout()), this, SLOT(rxErrorTimer_anotherSec())); connect(timeFromTXErrorClear, SIGNAL(timeout()), this, SLOT(txErrorTimer_anotherSec())); ui->spinRXErrorCount->setValue(0); ui->spinTXErrorCount->setValue(0); timeFromRXErrorClear->start(1000); timeFromTXErrorClear->start(1000); TimeToStopCANRead = FALSE; QtConcurrent::run(canReaderThread, this); ui->groupRXErrors->show(); ui->groupTXErrors->show(); } else { //Ошибка при открытии. QMessageBox msgBox; msgBox.setText("Не удалось подключиться к устройству."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); ui->logger->setTextColor(Qt::red); msg += QString("[SYS] Не удалось подключиться к устройству."); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; } } //Открытие порта RS. void UnionCOM::openSerialPort() { wRS->device_connect(); //Настройки порта: m_serial->setPortName(wRS->m_currentSettings.name); m_serial->setBaudRate(wRS->m_currentSettings.baudRate); m_serial->setDataBits(wRS->m_currentSettings.dataBits); m_serial->setParity(wRS->m_currentSettings.parity); m_serial->setStopBits(wRS->m_currentSettings.stopBits); m_serial->setFlowControl(wRS->m_currentSettings.flowControl); //Попытка открыть порт. if (m_serial->open(QIODevice::ReadWrite)) { //Успешно QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Устройство подключено."); ui->logger->setTextColor(Qt::blue); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; //Включается функция приёма сообщений. connect(m_serial, &QSerialPort::readyRead, this, &UnionCOM::readData); AfterConnection(); } else { //Ошибка при открытии. QMessageBox msgBox; msgBox.setText("Не удалось подключиться к устройству."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); ui->logger->setTextColor(Qt::red); msg += QString("[SYS] Не удалось подключиться к устройству. Error №%1").arg(errors_RS(m_serial->error())); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; } } //Уведомление о подключении устройства. void UnionCOM::Connect_Notification() { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Устройство подключено."); ui->logger->setTextColor(Qt::blue); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; } //Перевод приложения в режим работы с устройством. void UnionCOM::AfterConnection() { switch (ui->cboxTypeConnection->currentIndex()) { case 0: //CAN { wCan->AfterConnection(); if(wCan->GetMode()!=SLCAN_MODE_LISTENONLY) { ui->TXgridFrame->setEnabled(TRUE); } break; } case 1: //RS { wRS->AfterConnection(); ui->TXgridFrame->setEnabled(TRUE); break; } } ui->cboxTypeConnection->setEnabled(FALSE); ui->buttonConnect->setEnabled(FALSE); ui->buttonDisconnect->setEnabled(TRUE); } ///////////////////////// //Отключение устройства// // или com-порта // ///////////////////////// //QT-слот обработчик отключения от устройства/порта. void UnionCOM::on_buttonDisconnect_clicked() { for(int i = 0; i < 15; i++) { if(MacrosMain[i].IsPeriod==Qt::Checked) stopMcrs(i+1); } switch (ui->cboxTypeConnection->currentIndex()) { case 0: { //CAN //Очистка буффера отправляемых сообщений. ui->groupRXErrors->hide(); ui->spinRXErrorCount->setValue(0); ui->groupTXErrors->hide(); ui->spinTXErrorCount->setValue(0); timeFromRXErrorClear->stop(); timeFromTXErrorClear->stop(); QTime time(0, 0, 0); ui->timeEditRX->setTime(time); ui->timeEditTX->setTime(time); //SlCan_DevicePurge(device, SLCAN_PURGE_TX_ABORT|SLCAN_PURGE_TX_CLEAR|SLCAN_PURGE_RX_ABORT|SLCAN_PURGE_RX_CLEAR); stopCANReadThread(); //Отключение устройства. SlCan_DeviceClose(device); break; } case 1: { //RS //Отключается функция приёма сообщений. disconnect(m_serial, &QSerialPort::readyRead, this, &UnionCOM::readData); //Если устройство открыто - отключение. if (m_serial->isOpen()) m_serial->close(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Устройство отключено."); ui->logger->setTextColor(Qt::blue); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; break; } } AfterDisconnection(); } //Уведомление о отключении устройства. void UnionCOM::Disconnect_Notification() { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Устройство отключено."); ui->logger->setTextColor(Qt::blue); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; } //Уведомление о аварийном отключении устройства. void UnionCOM::Emergency_Disconnect_Notification() { ui->logger->setTextColor(Qt::red); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Устройство аварийно завершило работу."); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; ui->groupRXErrors->hide(); ui->spinRXErrorCount->setValue(0); ui->groupTXErrors->hide(); ui->spinTXErrorCount->setValue(0); timeFromRXErrorClear->stop(); timeFromTXErrorClear->stop(); QTime time(0, 0, 0); ui->timeEditRX->setTime(time); ui->timeEditTX->setTime(time); } //Перевод приложения в режим настройки и выбора подключения. void UnionCOM::AfterDisconnection() { switch (ui->cboxTypeConnection->currentIndex()) { case 0: //CAN { wCan->AfterDisconnection(); break; } case 1: //RS { wRS->AfterDisconnection(); break; } } ui->cboxTypeConnection->setEnabled(TRUE); ui->buttonConnect->setEnabled(TRUE); ui->buttonDisconnect->setEnabled(FALSE); ui->TXgridFrame->setEnabled(FALSE); } //////////////// //Приём данных// //////////////// void UnionCOM::deleteTopLine() { QTextCursor cursor = ui->logger->textCursor(); cursor.movePosition(QTextCursor::Start); cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, 0); cursor.select(QTextCursor::LineUnderCursor); cursor.removeSelectedText(); cursor.deleteChar(); } void UnionCOM::rxErrorTimer_clear() { QTime time(0, 0, 0); ui->timeEditRX->setTime(time); timeFromRXErrorClear->start(1000); } void UnionCOM::txErrorTimer_clear() { QTime time(0, 0, 0); ui->timeEditTX->setTime(time); timeFromTXErrorClear->start(1000); } void UnionCOM::rxErrorTimer_anotherSec() { QTime time = ui->timeEditRX->time().addSecs(1); ui->timeEditRX->setTime(time); } void UnionCOM::txErrorTimer_anotherSec() { QTime time = ui->timeEditTX->time().addSecs(1); ui->timeEditTX->setTime(time); } static void canReaderThread(UnionCOM* obj) { obj->canReadingInThread = TRUE; obj->TimeToReadEvents(); } //QString timeInterval(const QString& from, const QString& to, const QString& format = "hh:mm:ss:ms") //{ // QDateTime fromDt = QDateTime::fromString(from, format); // QDateTime toDt = QDateTime::fromString(to, format); // if (fromDt.isValid() && toDt.isValid()) { // QDateTime interval = QDateTime::fromMSecsSinceEpoch(toDt.toMSecsSinceEpoch() - fromDt.toMSecsSinceEpoch()); // return interval.toString(format); // } // return QString(); //} bool UnionCOM::event(QEvent* event) { if (event->type() == QEvent::User) { if(counterOfLoggerMSG>=500) { deleteTopLine(); } else { counterOfLoggerMSG++; } MyEvent* postedEvent = static_cast(event); switch (postedEvent->msgType()) { case NORMAL_MSG_TO_LOGGER: ui->logger->setTextColor(Qt::black); break; case WARNING_TO_LOGGER: ui->logger->setTextColor(Qt::red); break; case GHOST_TO_LOGGER: ui->logger->setTextColor(Qt::gray); break; case TX_ERROR_EVENT: ui->spinTXErrorCount->stepUp(); postedEvent->~MyEvent(); event->~QEvent(); return true; case RX_ERROR_EVENT: ui->spinRXErrorCount->stepUp(); postedEvent->~MyEvent(); event->~QEvent(); return true; } ui->logger->append(postedEvent->message()); ui->logger->setTextColor(Qt::black); postedEvent->~MyEvent(); event->~QEvent(); return true; } if(event->type() == RxCanEvent::EventType) { int i; RxCanEvent* postedEvent = static_cast(event); unsigned long long periodtmp = postedEvent->time_stamp(); QTime Period(0, 0, 0); for(i = 0; i < RxCanModel->rowCount(); i++) { if(RxCanModel->item(i, RX_CAN_GROUP_TABLE_ID_COLUMN)->text().toUInt(nullptr, 16)==postedEvent->msg().ID) { PSLCAN_TIMESTAMP per_tmp = new SLCAN_TIMESTAMP(); per_tmp->Value = periodtmp - RxCanModel->item(i, RX_CAN_GROUP_TABLE_TMPS)->text().toULongLong(nullptr, 10); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_PERIOD_COLUMN, //(QStringLiteral("%1").arg(postedEvent->msg().ID, 8, 16, QLatin1Char('0') new QStandardItem(QString("%1:%2:%3.%4.%5").arg(QString::number(microsecondToHours(per_tmp->Value)), QStringLiteral("%1").arg(microsecondToMinutes(per_tmp->Value), 2, 10, QLatin1Char('0')), QStringLiteral("%1").arg(microsecondToSeconds(per_tmp->Value), 2, 10, QLatin1Char('0')), QStringLiteral("%1").arg(microsecondToMilliseconds(per_tmp->Value), 3, 10, QLatin1Char('0')), QStringLiteral("%1").arg(per_tmp->Value%1000, 3, 10, QLatin1Char('0'))))); delete per_tmp; // Period = Period.addMSecs((QTime::fromString(RxCanModel->item(i, RX_CAN_GROUP_TABLE_TIME_COLUMN)->text(), "hh:mm:ss.zzz")).msecsTo(postedEvent->time())); // RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_PERIOD_COLUMN, // new QStandardItem(Period.toString("hh:mm:ss.zzz"))); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_TMPS, new QStandardItem(QString::number(periodtmp))); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_TIME_COLUMN, new QStandardItem(postedEvent->time().toString("hh:mm:ss.zzz"))); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_COUNT_COLUMN, new QStandardItem(QString::number(RxCanModel->item(i, RX_CAN_GROUP_TABLE_COUNT_COLUMN)->text().toInt(nullptr, 10)+1, 10))); QStandardItem *E_Standard = new QStandardItem(true); E_Standard->setCheckable(true); if(postedEvent->msg().Info&0b1) { E_Standard->setCheckState(Qt::Checked); } else { E_Standard->setCheckState(Qt::Unchecked); } RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_E_COLUMN, E_Standard); QStandardItem *R_Standard = new QStandardItem(true); R_Standard->setCheckable(true); if(postedEvent->msg().Info&0b10) { R_Standard->setCheckState(Qt::Checked); } else { R_Standard->setCheckState(Qt::Unchecked); } RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_R_COLUMN, R_Standard); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_DLC_COLUMN, new QStandardItem(QString::number(postedEvent->msg().DataCount, 10))); QString Data; for (int j = 0; (j < postedEvent->msg().DataCount)&&!(postedEvent->msg().Info&0b10); j++) { Data += QStringLiteral("%1").arg(postedEvent->msg().Data[j], 2, 16, QLatin1Char('0')); if((j+1)msg().DataCount) Data += " "; } RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_DATA_COLUMN, new QStandardItem(Data.toUpper())); break; } } if(i>=RxCanModel->rowCount()) { RxCanModel->insertRow(i); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_ID_COLUMN, new QStandardItem(QStringLiteral("%1").arg(postedEvent->msg().ID, 8, 16, QLatin1Char('0')).toUpper())); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_TIME_COLUMN, new QStandardItem(postedEvent->time().toString("hh:mm:ss.zzz"))); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_TMPS, new QStandardItem(QString::number(periodtmp))); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_COUNT_COLUMN, new QStandardItem("1")); QStandardItem *E_Standard = new QStandardItem(true); E_Standard->setCheckable(true); if(postedEvent->msg().Info&0b1) { E_Standard->setCheckState(Qt::Checked); } else { E_Standard->setCheckState(Qt::Unchecked); } RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_E_COLUMN, E_Standard); QStandardItem *R_Standard = new QStandardItem(true); R_Standard->setCheckable(true); if(postedEvent->msg().Info&0b10) { R_Standard->setCheckState(Qt::Checked); } else { R_Standard->setCheckState(Qt::Unchecked); } RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_R_COLUMN, R_Standard); RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_DLC_COLUMN, new QStandardItem(QString::number(postedEvent->msg().DataCount, 10))); QString Data; for (int j = 0; (j < postedEvent->msg().DataCount)&&!(postedEvent->msg().Info&0b10); j++) { Data += QStringLiteral("%1").arg(postedEvent->msg().Data[j], 2, 16, QLatin1Char('0')); if((j+1)msg().DataCount) Data += " "; } RxCanModel->setItem(i, RX_CAN_GROUP_TABLE_DATA_COLUMN, new QStandardItem(Data.toUpper())); Data.clear(); } for(i = 0; i < RxCanRequesterModel->rowCount(); i++) { if(RxCanRequesterModel->item(i, RX_CAN_REQUESTER_GROUP_TABLE_ID_COLUMN)->text().toUInt(nullptr, 16)==postedEvent->msg().ID) { // Period = Period.addMSecs((QTime::fromString(RxCanRequesterModel->item(i, RX_CAN_REQUESTER_GROUP_TABLE_TIME_COLUMN)->text(), "hh:mm:ss.zzz")).msecsTo(postedEvent->time())); // RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_PERIOD_COLUMN, // new QStandardItem(Period.toString("hh:mm:ss.zzz"))); PSLCAN_TIMESTAMP per_tmp = new SLCAN_TIMESTAMP(); per_tmp->Value = periodtmp - RxCanRequesterModel->item(i, RX_CAN_REQUESTER_GROUP_TABLE_TMPS)->text().toULongLong(nullptr, 10); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_PERIOD_COLUMN, new QStandardItem(QString("%1:%2:%3.%4.%5").arg(QString::number(microsecondToHours(per_tmp->Value)), QStringLiteral("%1").arg(microsecondToMinutes(per_tmp->Value), 2, 10, QLatin1Char('0')), QStringLiteral("%1").arg(microsecondToSeconds(per_tmp->Value), 2, 10, QLatin1Char('0')), QStringLiteral("%1").arg(microsecondToMilliseconds(per_tmp->Value), 3, 10, QLatin1Char('0')), QStringLiteral("%1").arg(per_tmp->Value%1000, 3, 10, QLatin1Char('0'))))); delete per_tmp; RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_TMPS, new QStandardItem(QString::number(periodtmp))); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_TIME_COLUMN, new QStandardItem(postedEvent->time().toString("hh:mm:ss.zzz"))); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_COUNT_COLUMN, new QStandardItem(QString::number(RxCanRequesterModel->item(i, RX_CAN_REQUESTER_GROUP_TABLE_COUNT_COLUMN)->text().toInt(nullptr, 10)+1, 10))); QStandardItem *E_Requester = new QStandardItem(true); E_Requester->setCheckable(true); if(postedEvent->msg().Info&0b1) { E_Requester->setCheckState(Qt::Checked); } else { E_Requester->setCheckState(Qt::Unchecked); } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_E_COLUMN, E_Requester); QStandardItem *R_Requester = new QStandardItem(true); R_Requester->setCheckable(true); if(postedEvent->msg().Info&0b10) { R_Requester->setCheckState(Qt::Checked); } else { R_Requester->setCheckState(Qt::Unchecked); } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_R_COLUMN, R_Requester); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_DLC_COLUMN, new QStandardItem(QString::number(postedEvent->msg().DataCount, 10))); QString Data; for (int j = 0; (j < postedEvent->msg().DataCount)&&!(postedEvent->msg().Info&0b10); j++) { Data += QStringLiteral("%1").arg(postedEvent->msg().Data[j], 2, 16, QLatin1Char('0')); if((j+1)msg().DataCount) Data += " "; } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_DATA_COLUMN, new QStandardItem(Data.toUpper())); break; } } if(i>=RxCanRequesterModel->rowCount()) { RxCanRequesterModel->insertRow(i); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_TMPS, new QStandardItem(QString::number(periodtmp))); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_ID_COLUMN, new QStandardItem(QStringLiteral("%1").arg(postedEvent->msg().ID, 8, 16, QLatin1Char('0')).toUpper())); QStandardItem *RxCanRoute = new QStandardItem(true); RxCanRoute->setCheckable(true); Requester_ID eID; eID.ID_All = postedEvent->msg().ID; QString datatype; switch (eID.Standard.DataType) { case 0: datatype = "Широковещательные"; break; case 1: datatype = "Дискретные"; break; case 2: datatype = "Аналоговые"; break; case 3: datatype = "Modbus Coil"; break; case 4: datatype = "Modbus Discrete"; break; case 5: datatype = "Modbus Holding"; break; case 6: datatype = "Modbus Input"; break; case 7: datatype = "Ошибки"; break; case 0xF: datatype = "Пульс"; break; default: datatype = "Unknown"; break; } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_DATATYPE, new QStandardItem(datatype)); datatype.clear(); datatype.~QString(); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_SENSORID, new QStandardItem(QString::number(eID.Standard.SensorID, 16).toUpper())); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_DEVICE, new QStandardItem(QString::number(eID.Standard.Device, 16).toUpper())); QString sensortype; switch (eID.Standard.DataType) { case 0: switch (eID.Standard.SensorType) { case 0: sensortype = "Статус"; break; case 1: sensortype = "Запрос на вкл/выкл"; break; case 2: sensortype = "Рестарт устройств"; break; case 3: sensortype = "Установка времени"; break;} break; case 1: switch (eID.Standard.SensorType) { case 0: sensortype = "Аварии"; break; case 1: sensortype = "Предупреждения"; break; case 2: sensortype = "Управляющие сигналы"; break; case 3: sensortype = "Флаги"; break; case 4: sensortype = "Рестарт устройства"; break; case 5: sensortype = "Изменение режима работы устройства"; break; case 6: sensortype = "Запрос перечня п-мтров на устройство"; break;} break; case 2: switch (eID.Standard.SensorType) { case 0: sensortype = "Универсальный запрос"; break; case 1: sensortype = "Уставки"; break; case 2: sensortype = "Напряжение"; break; case 3: sensortype = "Ток"; break; case 4: sensortype = "Температура"; break;} break; case 3: case 4: case 5: case 6: sensortype = QString::number(eID.Modbus.CountReg, 10); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_SENSORID, new QStandardItem(QString::number(eID.Modbus.CountReg, 16).toUpper())); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_DEVICE, new QStandardItem(QString::number(eID.Modbus.Device, 16).toUpper())); break; default: break; } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_SENSORTYPE, new QStandardItem(sensortype)); if(eID.Standard.Route) { RxCanRoute->setCheckState(Qt::Checked); } else { RxCanRoute->setCheckState(Qt::Unchecked); } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_ROUTE, RxCanRoute); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_TIME_COLUMN, new QStandardItem(postedEvent->time().toString("hh:mm:ss.zzz"))); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_COUNT_COLUMN, new QStandardItem("1")); QStandardItem *E_Requester = new QStandardItem(true); E_Requester->setCheckable(true); if(postedEvent->msg().Info&0b1) { E_Requester->setCheckState(Qt::Checked); } else { E_Requester->setCheckState(Qt::Unchecked); } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_E_COLUMN, E_Requester); QStandardItem *R_Requester = new QStandardItem(true); R_Requester->setCheckable(true); if(postedEvent->msg().Info&0b10) { R_Requester->setCheckState(Qt::Checked); } else { R_Requester->setCheckState(Qt::Unchecked); } QString Data; RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_R_COLUMN, R_Requester); RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_DLC_COLUMN, new QStandardItem(QString::number(postedEvent->msg().DataCount, 10))); for (int j = 0; (j < postedEvent->msg().DataCount)&&!(postedEvent->msg().Info&0b10); j++) { Data += QStringLiteral("%1").arg(postedEvent->msg().Data[j], 2, 16, QLatin1Char('0')); if((j+1)msg().DataCount) Data += " "; } RxCanRequesterModel->setItem(i, RX_CAN_REQUESTER_GROUP_TABLE_DATA_COLUMN, new QStandardItem(Data.toUpper())); } ui->loggertable->resizeColumnsToContents(); if(ui->requestBox->checkState()==Qt::Checked) { ui->loggertable->setColumnHidden(RX_CAN_GROUP_TABLE_TMPS, false); ui->loggertable->setColumnHidden(RX_CAN_REQUESTER_GROUP_TABLE_TMPS, true); } else { ui->loggertable->setColumnHidden(RX_CAN_GROUP_TABLE_TMPS, true); ui->loggertable->setColumnHidden(RX_CAN_REQUESTER_GROUP_TABLE_TMPS, false); } postedEvent->~RxCanEvent(); event->~QEvent(); return true; } return QWidget::event(event); } void UnionCOM::stopCANReadThread() { TimeToStopCANRead = TRUE; } //Функция чтения сообщений (доступна при работе по RS). void UnionCOM::readData() { //Если идёт загрузка файла, то запускается/обновляется таймер, //а полученные данные записываются в буффер. if(UsartFileLoading) { TransferEndTimer->start(5000); const QByteArray data = m_serial->readAll(); BufferForLoadFile += QString(data); } //Стандартный приём. else { const QByteArray data = m_serial->readAll(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[RX]"; //Вывод полученного сообщения доступен в двух вариантах: символы и HEX код. if(ui->checkRXHEX->checkState()!=Qt::Checked) { msg += " "; msg += data; } else { msg += "[HEX] "; for(int i = 0; ilogger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; } } //Функция обработки событий и приёма сообщений по CAN. void UnionCOM::TimeToReadEvents() { do{ SlCan_DeviceReadEvents(device, 0, inputEvents, FRAMES, &cntrInput); for(unsigned i = 0; i < cntrInput; i++) { switch(inputEvents[i].EventType) { case 0: //Принят CAN фрейм. { PSLCAN_TIMESTAMP per_t = new SLCAN_TIMESTAMP(); SlCan_DeviceGetTimeStamp(device, per_t); RxCanEvent* rxCanEvent = new RxCanEvent(inputEvents[i].Msg, QTime::currentTime(), per_t->Value); QCoreApplication::postEvent(this, rxCanEvent); delete per_t; if(ui->checkPushMsgToLogger->checkState()==Qt::Checked) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[RX]"); if(ui->checkRXHEX->checkState()==Qt::Checked) { msg += QString("[HEX]"); } msg += QString(" "); if(ui->checkRXHEX->checkState()!=Qt::Checked) { msg += QString::fromLocal8Bit((char*)inputEvents[i].Msg.Data, inputEvents[i].Msg.DataCount); } else { for(int j = 0; j < inputEvents[i].Msg.DataCount; j++) { msg += QString::number((int)inputEvents[i].Msg.Data[j], 16); msg += " "; } } MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); msg.clear(); } break; } case 1: //Начата передача CAN. { if(ui->checkEchoMode->checkState()==Qt::Checked) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[TX]"); if(ui->checkRXHEX->checkState()==Qt::Checked) { msg += QString("[HEX]"); } msg += QString(" "); if(ui->checkRXHEX->checkState()==Qt::Checked) { for (int k = 0; k < inputEvents[i].Msg.DataCount; k++) { msg += QString::number(inputEvents[i].Msg.Data[k], 16); msg += " "; } } else { msg += QString::fromLocal8Bit((char*)inputEvents[i].Msg.Data, inputEvents[i].Msg.DataCount); } MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; } break; } case 2: //Передача CAN фрейма успешно завершена. { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Передача успешно завершена."); MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; break; } case 3: //Передача CAN фрейма отменена. { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Передача CAN фрейма отменена."); MyEvent* myEvent = new MyEvent(msg, WARNING_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; break; } case 4: //Изменилось состояние CAN контроллера. { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Изменилось состояние CAN контроллера."); MyEvent* myEvent = new MyEvent(msg, GHOST_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; break; } case 5: //Изменилось значение одного из счётчика ошибок. { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Счётчик(-и) ошибок устройства изменился(-ись). RX: %1. TX: %2.").arg(QString::number(inputEvents[i].ErrCountRx), QString::number(inputEvents[i].ErrCountTx)); MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); break; } case 6: //Произошла ошибка шины CAN. { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Произошла ошибка шины CAN."); MyEvent* myEvent = new MyEvent(msg, WARNING_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += " BUSMODE: "; switch(inputEvents[i].BusMode) { case SLCAN_BUS_STATE_ERROR_ACTIVE: msg += "SLCAN_BUS_STATE_ERROR_ACTIVE."; break; case SLCAN_BUS_STATE_ERROR_ACTIVE_WARN: msg += "SLCAN_BUS_STATE_ERROR_ACTIVE_WARN."; break; case SLCAN_BUS_STATE_ERROR_PASSIVE: msg += "SLCAN_BUS_STATE_ERROR_PASSIVE."; break; case SLCAN_BUS_STATE_BUSOFF: msg += "SLCAN_BUS_STATE_BUSOFF."; break; } msg += QString(tr(" ErrCountRX: %1.").arg(inputEvents[i].ErrCountRx)); msg += QString(tr(" ErrCountTX: %1.").arg(inputEvents[i].ErrCountTx)); switch(inputEvents[i].ErrType) { case SLCAN_EVT_ERR_TYPE_BIT: msg += " SLCAN_EVT_ERR_TYPE_BIT."; break; case SLCAN_EVT_ERR_TYPE_FORM: msg += " SLCAN_EVT_ERR_TYPE_FORM."; break; case SLCAN_EVT_ERR_TYPE_STUFF: msg += " SLCAN_EVT_ERR_TYPE_STUFF."; break; case SLCAN_EVT_ERR_TYPE_OTHER: msg += " SLCAN_EVT_ERR_TYPE_OTHER."; break; } switch (inputEvents[i].ErrDir) { case SLCAN_EVT_ERR_DIR_TX: msg += " SLCAN_EVT_ERR_DIR_TX."; break; case SLCAN_EVT_ERR_DIR_RX: msg += " SLCAN_EVT_ERR_DIR_RX."; MyEvent* myEvent = new MyEvent(NULL, RX_ERROR_EVENT); QCoreApplication::postEvent(this, myEvent); break; } switch (inputEvents[i].ErrFrame){ case SLCAN_EVT_ERR_FRAME_SOF: msg += " SLCAN_EVT_ERR_FRAME_SOF."; break; case SLCAN_EVT_ERR_FRAME_ID28_ID21: msg += " SLCAN_EVT_ERR_FRAME_ID28_ID21."; break; case SLCAN_EVT_ERR_FRAME_ID20_ID18: msg += " SLCAN_EVT_ERR_FRAME_ID20_ID18."; break; case SLCAN_EVT_ERR_FRAME_SRTR: msg += " SLCAN_EVT_ERR_FRAME_SRTR."; break; case SLCAN_EVT_ERR_FRAME_IDE: msg += " SLCAN_EVT_ERR_FRAME_IDE."; break; case SLCAN_EVT_ERR_FRAME_ID17_ID13: msg += " SLCAN_EVT_ERR_FRAME_ID17_ID13."; break; case SLCAN_EVT_ERR_FRAME_ID12_ID5: msg += " SLCAN_EVT_ERR_FRAME_ID12_ID5."; break; case SLCAN_EVT_ERR_FRAME_ID4_ID0: msg += " SLCAN_EVT_ERR_FRAME_ID4_ID0."; break; case SLCAN_EVT_ERR_FRAME_RTR: msg += " SLCAN_EVT_ERR_FRAME_RTR."; break; case SLCAN_EVT_ERR_FRAME_RSRV0: msg += " SLCAN_EVT_ERR_FRAME_RSRV0."; break; case SLCAN_EVT_ERR_FRAME_RSRV1: msg += " SLCAN_EVT_ERR_FRAME_RSRV1."; break; case SLCAN_EVT_ERR_FRAME_DLC: msg += " SLCAN_EVT_ERR_FRAME_DLC."; break; case SLCAN_EVT_ERR_FRAME_DATA: msg += " SLCAN_EVT_ERR_FRAME_DATA."; break; case SLCAN_EVT_ERR_FRAME_CRC_SEQ: msg += " SLCAN_EVT_ERR_FRAME_CRC_SEQ."; break; case SLCAN_EVT_ERR_FRAME_CRC_DEL: msg += " SLCAN_EVT_ERR_FRAME_CRC_DEL."; break; case SLCAN_EVT_ERR_FRAME_ACK_SLOT: msg += " SLCAN_EVT_ERR_FRAME_ACK_SLOT."; break; case SLCAN_EVT_ERR_FRAME_ACK_DEL: msg += " SLCAN_EVT_ERR_FRAME_ACK_DEL."; break; case SLCAN_EVT_ERR_FRAME_EOF: msg += " SLCAN_EVT_ERR_FRAME_EOF."; break; case SLCAN_EVT_ERR_FRAME_INTER: msg += " SLCAN_EVT_ERR_FRAME_INTER."; break; case SLCAN_EVT_ERR_FRAME_AER_FLAG: msg += " SLCAN_EVT_ERR_FRAME_AER_FLAG."; break; case SLCAN_EVT_ERR_FRAME_PER_FLAG: msg += " SLCAN_EVT_ERR_FRAME_PER_FLAG."; break; case SLCAN_EVT_ERR_FRAME_TDB: msg += " SLCAN_EVT_ERR_FRAME_TDB."; break; case SLCAN_EVT_ERR_FRAME_ERR_DEL: msg += " SLCAN_EVT_ERR_FRAME_ERR_DEL."; break; case SLCAN_EVT_ERR_FRAME_OVER_FLAG: msg += " SLCAN_EVT_ERR_FRAME_OVER_FLAG."; break; } qDebug() << msg; break; } case 7: //Произошла ошибка арбитража. { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Произошла ошибка арбитража."); MyEvent* myEvent = new MyEvent(msg, WARNING_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; break; } } } }while(!TimeToStopCANRead); canReadingInThread = FALSE; } ////////////////// //Загрузка файла// ////////////////// //QT-слот для выгрузки файла. void UnionCOM::on_buttonLoadFile_clicked() { switch (ui->cboxTypeConnection->currentIndex()) { case 0: //CAN { SlCan_DevicePurge(device, SLCAN_PURGE_TX_ABORT|SLCAN_PURGE_TX_CLEAR|SLCAN_PURGE_RX_ABORT|SLCAN_PURGE_RX_CLEAR); stopCANReadThread(); fileName = QFileDialog::getSaveFileName(this, "Save File", "/home/", "Bin Files (*.bin);;All files (*.*)"); if(fileName.isEmpty()) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Отмена выгрузки файла."); qDebug()<logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; for(DWORD i = 0; i < cntrInput; i++) { for(int j = 0; j < inputMsg[i].DataCount; j++) { int Current = i*8+j; vuffalo[Current] = inputMsg[i].Data[j]; } } file.write(vuffalo); vuffalo.clear(); QCoreApplication::processEvents(); }while(cntrInput==FRAMES); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][RX] Файл выгружен в:"); qDebug()<logger->setTextColor(Qt::black); ui->logger->append(msg); file.close(); } else { QMessageBox msgBox; msgBox.setText("Не удалось выгрузить файл."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Не удалось выгрузить файл."; qDebug() << msg; return; } SlCan_DeviceSetMode(device, SLCAN_MODE_CONFIG); SlCan_DeviceSetBitRate(device, &br); SlCan_DeviceSetEventLevel(device, SLCAN_EVT_LEVEL_ERRORS); SlCan_DeviceSetMode(device, SLCAN_MODE); TimeToStopCANRead = FALSE; QtConcurrent::run(canReaderThread, this); break; } case 1: //RS { fileName = QFileDialog::getSaveFileName(this, "Save File", "/home/", "Bin Files (*.bin);;All files (*.*)"); if(fileName.isEmpty()) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Отмена выгрузки файла."); qDebug()<setSingleShot(TRUE); connect(TransferEndTimer, &QTimer::timeout, this, &UnionCOM::EndOfUSARTLoadFile); UsartFileLoading = 1; break; } } } //Функция, которая вызывается через 5 секунд после окончания передачи. Производится запись полученных байтов в файл. void UnionCOM::EndOfUSARTLoadFile() { UsartFileLoading=0; if(BufferForLoadFile.isEmpty()) { QMessageBox msgBox; msgBox.setText("Время ожидания вышло. Не удалось выгрузить файл."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Время ожидания вышло. Не удалось выгрузить файл."; qDebug() << msg; return; } QFile file(fileName); fileName.clear(); QByteArray Buffer; Buffer.resize(BufferForLoadFile.size()); if(file.open(QFile::WriteOnly)) { Buffer = BufferForLoadFile.toUtf8(); file.write(Buffer); file.close(); BufferForLoadFile.clear(); TransferEndTimer->~QTimer(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][RX] Файл выгружен в:"); qDebug()<logger->setTextColor(Qt::black); ui->logger->append(msg); } else { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Ошибка выгрузки файла: Не удалось создать и/или открыть файл.").arg(cntrInput); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug()<BusMode) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Передача прервана. Устройство находится в состоянии "; switch(DeviceState->BusMode) { //CAN контроллер находится в состоянии ERROR ACTIVE. //Значение одного из счетчиков ошибок больше или равно 96. case SLCAN_BUS_STATE_ERROR_ACTIVE_WARN: msg += "ERROR ACTIVE."; break; //CAN контроллер находится в состоянии ERROR PASSIVE //Значение одного из счетчиков ошибок больше 127. case SLCAN_BUS_STATE_ERROR_PASSIVE: msg += "ERROR PASSIVE."; break; //CAN контроллер находится в состоянии BUS OFF. //Контроллер переходит в это состояние //при превышеии счетчика ошибок передачи значения 256. case SLCAN_BUS_STATE_BUSOFF: msg += "BUS OFF."; break; } MyEvent* myEvent = new MyEvent(msg, WARNING_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; //Очистка буфера устройства. SlCan_DevicePurge(device, SLCAN_PURGE_TX_ABORT|SLCAN_PURGE_TX_CLEAR); do{ SlCan_DeviceReadEvents(device, 0, inputEvents, FRAMES, &cntrInput); }while(cntrInput==FRAMES); } } //Функция отправки сообщения по CAN. BYTE UnionCOM::writeMSG() { BYTE WriteStatus; //Попытка отправить сообщение. if(SlCan_DeviceWriteMessages(device, &outMsg, 1, &WriteStatus)) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz][TX]"); //Если при отправке сообщения возникла ошибка, то происходит вывод ошибки в логгер. if(WriteStatus){ TX_error_counter+=8; ui->spinTXErrorCount->setValue(ui->spinTXErrorCount->value()+1); switch (WriteStatus) { case SLCAN_TX_STATUS_TIMEOUT: msg += " Сообщения не переданы. Передача прервана из-за таймаута."; break; case SLCAN_TX_STATUS_BUSOFF: msg += " Сообщения не переданы. " "Передача прервана из-за ошибок на шине CAN и перехода CAN контроллера устройства в режим BUS OFF."; break; case SLCAN_TX_STATUS_ABORT: msg += " Сообщения не переданы. Передача прервана внешней командой."; break; case SLCAN_TX_STATUS_NOT_ENA: msg += " Сообщения не переданы. Передача запрещена."; break; case SLCAN_TX_STATUS_ERROR_ONE_SHOT: msg += " Сообщение передавалось в режиме ONE SHOT и произошла ошибка."; break; case SLCAN_TX_STATUS_INVALID_MODE: msg += " Сообщения не переданы. Режим устройства не поддерживает передачу."; break; case SLCAN_TX_STATUS_UNKNOWN: msg += " Сообщения не переданы. Ошибка не известна."; break; } MyEvent* myEvent = new MyEvent(msg, WARNING_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; } //Если передача прошла успешна, снижается счётчик ошибок. else { if(TX_error_counter>0) TX_error_counter--; } //Считывается текущее состояние устройства. SlCan_DeviceGetState(device, &DeviceState); //Если устройство не находится в нормальном режиме работы или кол-во ошибок при отправке превышает порог, то обрабатывается ошибка устройства. if(DeviceState.BusMode!=SLCAN_BUS_STATE_ERROR_ACTIVE && WriteStatus) { Device_Error(&DeviceState); return 0x07; } //Выводится статус отправки сообщения. 0 - успех, остальное - ошибки. return WriteStatus; } return 0x07; } //Функция очистки буффера сообщения по CAN. void UnionCOM::clearMSG() { for(BYTE& byte: outMsg.Data){ byte = 0; } QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Очистка буффера сообщения по CAN."); qDebug() << msg; } ////////////////////////////// //Отправка команды из строки// ////////////////////////////// //QT-слот для обработки отправления //сообщения(-ий) из командной строки. void UnionCOM::on_buttonSendCMD_clicked() { isTxIdle_CMD(); } void UnionCOM::isTxIdle_CMD() { if(isIdle) { //Вызов функции отправки. startCMDTX(); } else { //Подключение функции отправки к сигналу о завершении. QDialog *stopCurrentTX = new QDialog; stopCurrentTX->setWindowTitle("Прервать текущую передачу?"); stopCurrentTX->setMinimumSize(260, 50); stopCurrentTX->setMaximumSize(260, 50); QVBoxLayout *layoutCTX = new QVBoxLayout(stopCurrentTX); stopCurrentTX->setLayout(layoutCTX); QDialogButtonBox *yesOrNo = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, stopCurrentTX); layoutCTX->addWidget(yesOrNo); connect(yesOrNo, &QDialogButtonBox::accepted, stopCurrentTX, &QDialog::accept); connect(yesOrNo, &QDialogButtonBox::rejected, stopCurrentTX, &QDialog::reject); stopCurrentTX->exec(); if(stopCurrentTX->result()==QDialog::Accepted) { connect(this, SIGNAL(isTxFinished()), this, SLOT(stepToStartCMDTX)); userTXInterruption = TRUE; } delete stopCurrentTX; } } void UnionCOM::stepToStartCMDTX() { if(userTXInterruption) { disconnect(this, SIGNAL(isTxFinished), this, SLOT(stepToStartCMDTX)); userTXInterruption=FALSE; } startCMDTX(); } void UnionCOM::startCMDTX() { switch (ui->cboxTypeConnection->currentIndex()) { case 0: { QtConcurrent::run(turnOnCMDTX); break; } case 1: { sendCMD_RS(); break; } } } static void turnOnCMDTX() { com_target->sendCMD_CAN(); } void UnionCOM::sendCMD_CAN() { isIdle=FALSE; //Считывается текст на отправку. QString tx_data = ui->lineMSG->text(); //Если информации для отправки нет - проходит сигнал и выход из функции. if(tx_data.size()==0) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Пустое поле ввода."); MyEvent* myEvent = new MyEvent(msg, WARNING_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; isIdle=TRUE; emit isTxFinished(); return; } //Уведомление о начале передачи. QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; //CAN int i; //Перевод из QString Unicod в Ascii. QByteArray buffer = tx_data.toLocal8Bit(); BYTE MSG_Status; //Из строки символов формируются сообщения и отправляются. for(i = 0; i<(tx_data.size()/8); i+=8) { outMsg.Data[0] = buffer[i]; outMsg.Data[1] = buffer[i+1]; outMsg.Data[2] = buffer[i+2]; outMsg.Data[3] = buffer[i+3]; outMsg.Data[4] = buffer[i+4]; outMsg.Data[5] = buffer[i+5]; outMsg.Data[6] = buffer[i+6]; outMsg.Data[7] = buffer[i+7]; //Попытка отправить сообщение. do { MSG_Status = writeMSG(); //Если передать сообщение не удаётся, то происходит отмена отправки. if (MSG_Status == 0x07 || userTXInterruption) { clearMSG(); isIdle=TRUE; emit isTxFinished(); return; } } while(MSG_Status); //Очистка буффера сообщения. clearMSG(); } //Если остались символы, передаём их. if(i!=tx_data.size()) { int j; //Формируется сообщение из оставшихся символов. for(j = 0; (j+i)lineMSG->text(); //Если информации для отправки нет - проходит сигнал и выход из функции. if(tx_data.size()==0) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Пустое поле ввода."); ui->logger->setTextColor(Qt::red); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; isIdle=TRUE; emit isTxFinished(); return; } //Уведомление о начале передачи. QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; m_serial->write(tx_data.toUtf8(), tx_data.size()); m_serial->waitForBytesWritten(); if(ui->checkEchoMode->checkState()==Qt::Checked) { msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[TX] "); msg += tx_data; ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; } msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Передача успешно завершена."); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; isIdle=TRUE; emit isTxFinished(); } ///////////////////////////// // Отправка пакета байтов, // //задаваемых на форме в HEX// ///////////////////////////// //Функция для отслеживания кол-ва отправляемых байт в команде. void UnionCOM::on_boxDataCount_currentIndexChanged(int index) { if(ui->checkHEXRTR->checkState()==Qt::Checked) { return; } index--; for(int i = 0; i < 8; i++) { if(i > (index)) { HEXByteField[i]->setEnabled(FALSE); } else { HEXByteField[i]->setEnabled(TRUE); } } QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Количество байтов для отправки изменилось. Текущее количество: %1.").arg(index+1); qDebug()<setWindowTitle("Прервать текущую передачу?"); stopCurrentTX->setMinimumSize(260, 50); stopCurrentTX->setMaximumSize(260, 50); QVBoxLayout *layoutCTX = new QVBoxLayout(stopCurrentTX); stopCurrentTX->setLayout(layoutCTX); QDialogButtonBox *yesOrNo = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, stopCurrentTX); layoutCTX->addWidget(yesOrNo); connect(yesOrNo, &QDialogButtonBox::accepted, stopCurrentTX, &QDialog::accept); connect(yesOrNo, &QDialogButtonBox::rejected, stopCurrentTX, &QDialog::reject); stopCurrentTX->exec(); if(stopCurrentTX->result()==QDialog::Accepted) { connect(this, SIGNAL(isTxFinished), this, SLOT(stepToStartCMDHEXTX)); userTXInterruption=TRUE; } delete stopCurrentTX; } } void UnionCOM::stepToStartCMDHEXTX() { if(userTXInterruption) { disconnect(this, SIGNAL(isTxFinished), this, SLOT(stepToStartCMDHEXTX)); userTXInterruption=FALSE; } startCMDHEXTX(); } void UnionCOM::startCMDHEXTX() { switch (ui->cboxTypeConnection->currentIndex()) { case 0: { QtConcurrent::run(turnOnCMDHEXTX); break; } case 1: { sendCMD_RS(); break; } } } static void turnOnCMDHEXTX() { com_target->sendCMDHEX_CAN(); } void UnionCOM::sendCMDHEX_CAN() { isIdle=FALSE; int SizeOfHEXCMD = ui->boxDataCount->currentIndex(); char tx_data[SizeOfHEXCMD]; for(int i = 0; i < SizeOfHEXCMD; i++) { tx_data[i] = (BYTE)HEXByteField[i]->text().toInt(nullptr, 16); } QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; //CAN BYTE MSG_Status; DWORD oldID = outMsg.ID; outMsg.ID = ui->lineHEXID->text().toInt(nullptr, 16); BYTE oldInfo = outMsg.Info; if(ui->checkHEXEID->checkState()==Qt::Checked) { outMsg.Info = oldInfo|0b1; } else { outMsg.Info = oldInfo&0b11111110; } if(ui->checkHEXRTR->checkState()==Qt::Checked) { outMsg.Info = outMsg.Info|0b10; short oldDataCount = outMsg.DataCount; outMsg.DataCount=SizeOfHEXCMD; do { MSG_Status = writeMSG(); if (MSG_Status == 0x07 || userTXInterruption) { clearMSG(); outMsg.DataCount = oldDataCount; outMsg.ID = oldID; outMsg.Info = oldInfo; isIdle=TRUE; emit isTxFinished(); return; } } while(MSG_Status); clearMSG(); outMsg.DataCount = oldDataCount; outMsg.ID = oldID; outMsg.Info = oldInfo; isIdle=TRUE; emit isTxFinished(); return; } else { outMsg.Info = outMsg.Info&0b11111101; } outMsg.DataCount=SizeOfHEXCMD; for(int i = 0; i < SizeOfHEXCMD; i++) { outMsg.Data[i] = tx_data[i]; } do { MSG_Status = writeMSG(); if (MSG_Status == 0x07 || userTXInterruption) { clearMSG(); outMsg.DataCount = 8; outMsg.ID = oldID; outMsg.Info = oldInfo; isIdle=TRUE; emit isTxFinished(); return; } } while(MSG_Status); clearMSG(); outMsg.DataCount = 8; outMsg.ID = oldID; outMsg.Info = oldInfo; isIdle=TRUE; emit isTxFinished(); } void UnionCOM::sendCMDHEX_RS() { isIdle=FALSE; int SizeOfHEXCMD = ui->boxDataCount->currentIndex(); char tx_data[SizeOfHEXCMD]; for(int i = 0; i < SizeOfHEXCMD; i++) { tx_data[i] = (BYTE)HEXByteField[i]->text().toInt(nullptr, 16); } QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; if(ui->checkEchoMode->checkState()==Qt::Checked) { msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[TX][HEX]"); for(int i = 0; i < SizeOfHEXCMD; i++) { msg += QString::number(tx_data[i], 16); msg += " "; } ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; } m_serial->write(tx_data, SizeOfHEXCMD); msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Передача успешно завершена."); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; isIdle=TRUE; emit isTxFinished(); } ////////////////// //Отправка файла// ////////////////// //QT-слот для отправки файла. void UnionCOM::on_buttonSendFile_clicked() { isTxIdle_FILE(); } void UnionCOM::isTxIdle_FILE() { if(isIdle) { //Вызов функции отправки. startSendFile(); } else { QDialog *stopCurrentTX = new QDialog; stopCurrentTX->setWindowTitle("Прервать текущую передачу?"); stopCurrentTX->setMinimumSize(260, 50); stopCurrentTX->setMaximumSize(260, 50); QVBoxLayout *layoutCTX = new QVBoxLayout(stopCurrentTX); stopCurrentTX->setLayout(layoutCTX); QDialogButtonBox *yesOrNo = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, stopCurrentTX); layoutCTX->addWidget(yesOrNo); connect(yesOrNo, &QDialogButtonBox::accepted, stopCurrentTX, &QDialog::accept); connect(yesOrNo, &QDialogButtonBox::rejected, stopCurrentTX, &QDialog::reject); stopCurrentTX->exec(); if(stopCurrentTX->result()==QDialog::Accepted) { connect(this, SIGNAL(isTxFinished()), this, SLOT(stepToStartSendFile)); userTXInterruption = TRUE; } delete stopCurrentTX; } } void UnionCOM::stepToStartSendFile() { if(userTXInterruption) { disconnect(this, SIGNAL(isTxFinished), this, SLOT(stepToStartSendFile)); userTXInterruption=FALSE; } startSendFile(); } void UnionCOM::startSendFile() { isIdle=FALSE; //Открывается окно выбора файла. fileName = QFileDialog::getOpenFileName(this, "Open File", "/home/", "Bin Files (*.bin);;All files (*.*)"); //Если произошла отмена выбора, то срабатывают оповещение и выход из функции. if(fileName.isEmpty()) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Отмена отправки файла."); qDebug()<cboxTypeConnection->currentIndex()) { case 0: { QtConcurrent::run(turnOnSendFile); break; } case 1: { sendFile_RS(); break; } } } static void turnOnSendFile() { com_target->sendFile_CAN(); } //Функция отправки файла. void UnionCOM::sendFile_CAN() { isIdle=FALSE; QFile *file = new QFile(fileName); fileName.clear(); //Если открытие успешно: if(file->open(QIODevice::ReadOnly)) { //Уведомление о начале передачи. QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; //Считывается файл в массив байтов. QByteArray data; data = file->readAll(); file->close(); //Отправка байтов в зависимости от выбранного типа подключения. Counter_of_suc_transmit=0; TX_error_counter=0; BYTE MSG_Status; unsigned short CurrentByte=0; //Формирование пакета и его отправка. for(int i=0; i~MyEvent(); myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; } else { QMessageBox msgBox; msgBox.setText("Не удалось отправить файл."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Не удалось отправить файл."; qDebug() << msg; isIdle=TRUE; emit isTxFinished(); return; } QThread::usleep(5000); isIdle=TRUE; emit isTxFinished(); } void UnionCOM::sendFile_RS() { isIdle=FALSE; QFile *file = new QFile(fileName); fileName.clear(); if(file->open(QIODevice::ReadOnly)) { //Уведомление о начале передачи. QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; //Считывается файл в массив байтов. QByteArray data; data = file->readAll(); file->close(); //Отправка файла с получением кол-ва переданных байт. int WrittenBytes = m_serial->write(data); //Если передано не всё, то выводится сообщение об ошибке. if (WrittenBytes!=data.size()) { msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Ошибка передачи. Передано: %1. Всего: %2").arg(WrittenBytes).arg(data.size()); ui->logger->setTextColor(Qt::red); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; } //Если всё прошло успешно, то выводится уведомление об отправке. else { msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Успешно передано %1 (в байтах).").arg(WrittenBytes); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; } } else { QMessageBox msgBox; msgBox.setText("Не удалось отправить файл."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Не удалось отправить файл."; qDebug() << msg; delete file; isIdle=TRUE; emit isTxFinished(); return; } delete file; isIdle=TRUE; emit isTxFinished(); } ////////////////////// //Работа с макросами// ////////////////////// //Настройка макросов. void UnionCOM::on_buttonSetMcrs_clicked() { for(int i = 0; i < 15; i++) { MacrosMain[i].Name = McrsButtons[i]->text(); } QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Открыто окно изменения макросов."); qDebug()<SetStart(arrEID, arrID, arrRTR, arrIsHEX, arrDLC, arrName, arrMcrs, arrCount, arrIsPeriod, arrPeriod); mcrs_w->exec(); if(mcrs_w->IsOK) { for (int i = 0; i < 15; i++) { MacrosMain[i].EID = arrEID[i]; MacrosMain[i].ID = arrID[i]; MacrosMain[i].RTR = arrRTR[i]; MacrosMain[i].IsHEX = arrIsHEX[i]; MacrosMain[i].DLC = arrDLC[i]; MacrosMain[i].Name = arrName[i]; MacrosMain[i].Mcrs = arrMcrs[i]; MacrosMain[i].Count = arrCount[i]; MacrosMain[i].IsPeriod = arrIsPeriod[i]; MacrosMain[i].Period = arrPeriod[i]; //Смена имени на кнопках. if(!MacrosMain[i].Name.isEmpty()) { McrsButtons[i]->setText(MacrosMain[i].Name); } } msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Макросы были изменены."); qDebug()<~MacrosSetting(); } //Сохранить текущий набор макросов в файл. void UnionCOM::on_buttonSaveMcrsKit_clicked() { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Сохранение макросов."); qDebug()<setText(MacrosMain[i].Name); } } } else { QMessageBox msgBox; msgBox.setText("Нет доступа."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Не удалось загрузить макросы: Нет доступа."; qDebug() << msg; return; } } //Функция для проверки файла сохранения наборов макросов. bool UnionCOM::CheckFile(qint64 StatusOfRead, char *buffer, qint64 MaxByteToRead) { if(StatusOfRead<=0 || (StatusOfRead==(MaxByteToRead+1) && buffer[MaxByteToRead]!='\n')) { QMessageBox msgBox; msgBox.setText("Файл повреждён."); msgBox.exec(); QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += "[SYS] Не удалось загрузить макросы: Файл повреждён."; qDebug() << msg; return TRUE; } return FALSE; } //Макросы. void UnionCOM::isTxIdle_MCRS(int index) { com_target->notTimeToStopPeriodMcrs[index-1] = TRUE; if(isIdle) { //Вызов функции отправки. startMCRSTX(index); } else { //Подключение функции отправки к сигналу о завершении. QDialog *stopCurrentTX = new QDialog; stopCurrentTX->setWindowTitle("Прервать текущую передачу?"); stopCurrentTX->setMinimumSize(260, 50); stopCurrentTX->setMaximumSize(260, 50); QVBoxLayout *layoutCTX = new QVBoxLayout(stopCurrentTX); stopCurrentTX->setLayout(layoutCTX); QDialogButtonBox *yesOrNo = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, stopCurrentTX); layoutCTX->addWidget(yesOrNo); connect(yesOrNo, &QDialogButtonBox::accepted, stopCurrentTX, &QDialog::accept); connect(yesOrNo, &QDialogButtonBox::rejected, stopCurrentTX, &QDialog::reject); stopCurrentTX->exec(); if(stopCurrentTX->result()==QDialog::Accepted) { connect(this, &UnionCOM::isTxFinished, funcptr[index]); userTXInterruption=TRUE; if(McrsPeriodTransfer[index-1]) { stopMcrs(index); } } stopCurrentTX->~QDialog(); } } void UnionCOM::startMCRSTX(int index) { index--; if(userTXInterruption) { disconnect(this, SIGNAL(isTxFinished), this, (char*)funcptr[index]); userTXInterruption=FALSE; } switch (ui->cboxTypeConnection->currentIndex()) { case 0: { turnOnMcrsTX(index); break; } case 1: { pushMcrs_RS(index); break; } } //Если макрос имеет свойство периодичности, то запускается таймер, //который повторит отправку макроса через заданный период. if(MacrosMain[index].IsPeriod==Qt::Checked && notTimeToStopPeriodMcrs[index]) { McrsStopButtons[index]->setEnabled(TRUE); McrsPeriodTransfer[index]->start(MacrosMain[index].Period); } } static void turnOnMcrsTX(int index) { com_target->pushMcrs_CAN(index); } static void stepToStartMCRS1() { com_target->startMCRSTX(1); } static void stepToStartMCRS2() { com_target->startMCRSTX(2); } static void stepToStartMCRS3() { com_target->startMCRSTX(3); } static void stepToStartMCRS4() { com_target->startMCRSTX(4); } static void stepToStartMCRS5() { com_target->startMCRSTX(5); } static void stepToStartMCRS6() { com_target->startMCRSTX(6); } static void stepToStartMCRS7() { com_target->startMCRSTX(7); } static void stepToStartMCRS8() { com_target->startMCRSTX(8); } static void stepToStartMCRS9() { com_target->startMCRSTX(9); } static void stepToStartMCRS10() { com_target->startMCRSTX(10); } static void stepToStartMCRS11() { com_target->startMCRSTX(11); } static void stepToStartMCRS12() { com_target->startMCRSTX(12); } static void stepToStartMCRS13() { com_target->startMCRSTX(13); } static void stepToStartMCRS14() { com_target->startMCRSTX(14); } static void stepToStartMCRS15() { com_target->startMCRSTX(15); } //Отправка макроса. void UnionCOM::pushMcrs_CAN(int index) { if(!notTimeToStopPeriodMcrs[index]) { emit isTxFinished(); return; } isIdle=FALSE; if(MacrosMain[index].Mcrs.size()==0 && MacrosMain[index].RTR!=Qt::Checked) { QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS] Макрос не задан."); MyEvent* myEvent = new MyEvent(msg, WARNING_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; isIdle=TRUE; emit isTxFinished(); return; } QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); MyEvent* myEvent = new MyEvent(msg, NORMAL_MSG_TO_LOGGER); QCoreApplication::postEvent(this, myEvent); qDebug() << msg; BYTE MSG_Status; DWORD oldID = outMsg.ID; outMsg.ID = MacrosMain[index].ID; BYTE oldInfo = outMsg.Info; if(MacrosMain[index].EID==Qt::Checked) { outMsg.Info = oldInfo|0b1; } else { outMsg.Info = oldInfo&0b11111110; } if(MacrosMain[index].RTR==Qt::Checked) { outMsg.Info = outMsg.Info|0b10; short oldDataCount = outMsg.DataCount; outMsg.DataCount=MacrosMain[index].DLC; do { MSG_Status = writeMSG(); if (MSG_Status == 0x07 || userTXInterruption) { if(MacrosMain[index].IsPeriod==Qt::Checked) stopMcrs(index+1); clearMSG(); outMsg.DataCount = oldDataCount; outMsg.ID = oldID; outMsg.Info = oldInfo; isIdle=TRUE; emit isTxFinished(); return; } } while(MSG_Status); clearMSG(); outMsg.DataCount = oldDataCount; outMsg.ID = oldID; outMsg.Info = oldInfo; isIdle=TRUE; emit isTxFinished(); return; } else { outMsg.Info = outMsg.Info&0b11111101; } QByteArray buffer; if(MacrosMain[index].IsHEX) { QString oldMcrs = MacrosMain[index].Mcrs; MacrosMain[index].Mcrs = MacrosMain[index].Mcrs.replace(" ", ""); if(MacrosMain[index].Mcrs.size()%2) { MacrosMain[index].Mcrs = "0" + MacrosMain[index].Mcrs; } QString Subbuff; for(int i = 0; i < MacrosMain[index].Mcrs.size()-1; i+=2) { Subbuff = MacrosMain[index].Mcrs[i]; Subbuff += MacrosMain[index].Mcrs[i+1]; buffer += Subbuff.toInt(nullptr, 16); } MacrosMain[index].Mcrs = oldMcrs; } else { buffer += MacrosMain[index].Mcrs.toLocal8Bit(); } //CAN for(int TX_Counter = 0; TX_Counterlogger->setTextColor(Qt::red); ui->logger->append(msg); ui->logger->setTextColor(Qt::black); qDebug() << msg; isIdle=TRUE; emit isTxFinished(); return; } QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Начало передачи."); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; QByteArray buffer; if(MacrosMain[index].IsHEX) { QString Subbuff; for(int i = 0; i < MacrosMain[index].Mcrs.size()-1; i+=2) { Subbuff = MacrosMain[index].Mcrs[i]; Subbuff += MacrosMain[index].Mcrs[i+1]; buffer += Subbuff.toInt(nullptr, 16); } } else { buffer += MacrosMain[index].Mcrs; } for(int TX_Counter = 0; TX_Counterwrite(buffer, buffer.size()); if(ui->checkEchoMode->checkState()==Qt::Checked) { msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[TX] "); msg += buffer; ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; } } msg = QTime::currentTime().toString("[hh:mm:ss.zzz]"); msg += QString("[SYS][TX] Передача успешно завершена."); ui->logger->setTextColor(Qt::black); ui->logger->append(msg); qDebug() << msg; isIdle=TRUE; emit isTxFinished(); } //Остановка переодического макроса. void UnionCOM::stopMcrs(int index) { index--; McrsPeriodTransfer[index]->stop(); notTimeToStopPeriodMcrs[index]=FALSE; McrsStopButtons[index]->setEnabled(FALSE); } void UnionCOM::on_buttonRXErrorCountErase_clicked() { ui->spinRXErrorCount->setValue(0); rxErrorTimer_clear(); } void UnionCOM::on_buttonTXErrorCountErase_clicked() { ui->spinTXErrorCount->setValue(0); txErrorTimer_clear(); } void UnionCOM::on_buttonCRC_clicked() { CRC16 *crc_widget = new CRC16(nullptr); crc_widget->setWindowTitle("CRC Calc"); crc_widget->show(); } void UnionCOM::on_checkHEXRTR_stateChanged(int arg1) { bool flag; if(ui->checkHEXRTR->checkState()==Qt::Checked) { flag = false; } else { flag = true; } for(int i = 0; i < 8; i++) { if(flag && (ui->boxDataCount->currentIndex()>=(i+1))) { HEXByteField[i]->setEnabled(flag); } else { HEXByteField[i]->setEnabled(false); } } } void UnionCOM::on_checkHEXEID_stateChanged(int arg1) { if(ui->checkHEXEID->checkState()==Qt::Checked) { ui->lineHEXID->setInputMask(">HHHHHHHH"); } else { ui->lineHEXID->setInputMask(">HHH"); } } void UnionCOM::on_lineHEXID_textChanged(const QString &arg1) { QString buffer = QString::number(ui->lineHEXID->text().toUInt(nullptr, 16), 10); int pos = 0; unsigned long long maxRange; if(ui->checkHEXEID->checkState()==Qt::Checked) { maxRange = 0x1FFFFFFF; } else { maxRange = 0x7FF; } if((unsigned long long)buffer.toUInt(nullptr, 10) > (unsigned long long) maxRange) { ui->lineHEXID->setStyleSheet("border: 1px solid red"); ui->lineHEXID->setToolTip(QString("Valid ID: 0 - 0x%1").arg(QString::number(maxRange, 16).toUpper())); ui->buttonSendCMDHex->setEnabled(false); } else { ui->lineHEXID->setStyleSheet(""); ui->lineHEXID->setToolTip(QString()); ui->buttonSendCMDHex->setEnabled(true); } } #include "canidcalc.h" void UnionCOM::on_pushButton_clicked() { CanIdCalc *CAN_ID_Calc = new CanIdCalc(nullptr); CAN_ID_Calc->setWindowTitle("CAN ID Calc"); CAN_ID_Calc->show(); } void UnionCOM::tableInit() { ui->loggertable->setSortingEnabled(true); RxCanModel = new QStandardItemModel(0, 9); { RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_COUNT_COLUMN, Qt::Horizontal, "Count"); RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_TIME_COLUMN, Qt::Horizontal, "Time, h:m:s.ms"); RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_PERIOD_COLUMN, Qt::Horizontal, "Period, h:m:s.ms.us"); RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_ID_COLUMN, Qt::Horizontal, "ID (hex)"); RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_E_COLUMN, Qt::Horizontal, "E"); RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_R_COLUMN, Qt::Horizontal, "R"); RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_DLC_COLUMN, Qt::Horizontal, "DLC"); RxCanModel->setHeaderData(RX_CAN_GROUP_TABLE_DATA_COLUMN, Qt::Horizontal, "Data (hex)"); } RxCanRequesterModel = new QStandardItemModel(0, 14); { RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_COUNT_COLUMN, Qt::Horizontal, "Count"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_TIME_COLUMN, Qt::Horizontal, "Time, h:m:s.ms"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_PERIOD_COLUMN, Qt::Horizontal, "Period, h:m:s.ms.us"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_ID_COLUMN, Qt::Horizontal, "ID (hex)"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_ROUTE, Qt::Horizontal, "Route"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_DATATYPE, Qt::Horizontal, "DataType"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_SENSORTYPE, Qt::Horizontal, "SensorType"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_SENSORID, Qt::Horizontal, "SensorID"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_DEVICE, Qt::Horizontal, "Device"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_E_COLUMN, Qt::Horizontal, "E"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_R_COLUMN, Qt::Horizontal, "R"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_DLC_COLUMN, Qt::Horizontal, "DLC"); RxCanRequesterModel->setHeaderData(RX_CAN_REQUESTER_GROUP_TABLE_DATA_COLUMN, Qt::Horizontal, "Data (hex)"); } if(ui->requestBox->checkState()==Qt::Checked) { ui->loggertable->setModel(RxCanRequesterModel); ui->loggertable->setColumnHidden(RX_CAN_GROUP_TABLE_TMPS, false); ui->loggertable->setColumnHidden(RX_CAN_REQUESTER_GROUP_TABLE_TMPS, true); } else { ui->loggertable->setModel(RxCanModel); ui->loggertable->setColumnHidden(RX_CAN_GROUP_TABLE_TMPS, true); ui->loggertable->setColumnHidden(RX_CAN_REQUESTER_GROUP_TABLE_TMPS, false); } } void UnionCOM::on_requestBox_stateChanged(int arg1) { switch (arg1) { case Qt::Unchecked: ui->loggertable->setModel(RxCanModel); ui->loggertable->setColumnHidden(RX_CAN_GROUP_TABLE_TMPS, true); ui->loggertable->setColumnHidden(RX_CAN_REQUESTER_GROUP_TABLE_TMPS, false); break; case Qt::Checked: ui->loggertable->setModel(RxCanRequesterModel); ui->loggertable->setColumnHidden(RX_CAN_GROUP_TABLE_TMPS, false); ui->loggertable->setColumnHidden(RX_CAN_REQUESTER_GROUP_TABLE_TMPS, true); break; } ui->loggertable->resizeColumnsToContents(); }