UnionComDLL/unioncom.cpp

3281 lines
123 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "unioncom.h"
#include "ui_unioncom.h"
#include "ProjectSettings.h"
#include <QSerialPort>
#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()<<msg;
}
void UnionCOM::gotors()
{
ui->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<MyEvent*>(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<RxCanEvent*>(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)<postedEvent->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)<postedEvent->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)<postedEvent->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)<postedEvent->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; i<data.size(); i++)
{
msg += (QString::number((byte)data[i], 16)).toUpper();
msg += " ";
}
}
ui->logger->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()<<msg;
return;
}
SlCan_DeviceSetMode(device, SLCAN_MODE_CONFIG);
SlCan_DeviceSetBitRate(device, &br);
SlCan_DeviceSetEventLevel(device, SLCAN_EVT_LEVEL_RX_MSG);
SlCan_DeviceSetMode(device, SLCAN_MODE);
SlCan_DevicePurge(device, SLCAN_PURGE_RX_CLEAR);
clearMSG();
QFile file(fileName);
fileName.clear();
bool FirstRX = false;
if(file.open(QFile::WriteOnly))
{
QString bufferToFile;
QByteArray vuffalo;
do{
cntrInput=0;
if(FirstRX)
SlCan_DeviceReadMessages(device, READDELAY, inputMsg, FRAMES, &cntrInput);
else
{
SlCan_DeviceReadMessages(device, READDELAY, inputMsg, FRAMES, &cntrInput);
if(cntrInput==0)
{
QMessageBox msgBox;
msgBox.setText("Время ожидания вышло. Не удалось выгрузить файл.");
msgBox.exec();
QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += "[SYS] Время ожидания вышло. Не удалось выгрузить файл.";
qDebug() << msg;
return;
}
FirstRX=TRUE;
}
QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS][RX] Принято пакетов: %1").arg(cntrInput);
ui->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()<<msg;
qDebug()<<file.fileName();
msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS][RX] Файл выгружен.");
ui->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()<<msg;
return;
}
TransferEndTimer = new QTimer(this);
TransferEndTimer->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()<<msg;
qDebug()<<file.fileName();
msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS][RX] Файл выгружен.");
ui->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()<<msg;
}
}
///////////////////
//Базовые функции//
//отправки данных//
///////////////////
//Функция обработки ошибки при передаче.
void UnionCOM::Device_Error(PSLCAN_STATE DeviceState)
{
//Если состояние устройства отличается от нормы:
if(DeviceState->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)<tx_data.size(); j++)
{
outMsg.Data[j]=buffer[j+i];
}
//Задаётся количество оставшихся символов.
outMsg.DataCount = j;
//Попытка отправить сообщение.
do {
MSG_Status = writeMSG();
//Если передать сообщение не удаётся, то происходит отмена отправки.
if (MSG_Status == 0x07 || userTXInterruption)
{
outMsg.DataCount = 8;
clearMSG();
isIdle=TRUE;
emit isTxFinished();
return;
}
} while(MSG_Status);
//Очистка буффера сообщения.
clearMSG();
//Возвращение к стандартному количеству байт для отправки.
outMsg.DataCount = 8;
}
isIdle=TRUE;
emit isTxFinished();
}
void UnionCOM::sendCMD_RS()
{
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] Пустое поле ввода.");
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()<<msg;
}
//QT-Слот для отправки 8 байт в HEX формате введённых в поля на форме.
void UnionCOM::on_buttonSendCMDHex_clicked()
{
isTxIdle_CMDHEX();
}
void UnionCOM::isTxIdle_CMDHEX()
{
if(isIdle)
{
//Вызов функции отправки
startCMDHEXTX();
}
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(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()<<msg;
isIdle=TRUE;
emit isTxFinished();
return;
}
switch(ui->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<data.size(); i++)
{
outMsg.Data[CurrentByte]=data[i];
if(CurrentByte==7)
{
CurrentByte=0;
do {
MSG_Status = writeMSG();
//Если при передаче произошла неизвестная ошибка - передача прерывается.
if (MSG_Status == 0x07 || userTXInterruption)
{
//Мб нужна какая-то "пустая" передача для завершения?
clearMSG();
QThread::usleep(5000);
isIdle=TRUE;
emit isTxFinished();
return;
}
} while(MSG_Status);
clearMSG();
}
else
{
CurrentByte++;
}
//Функция для продолжения корректной работы остального
//приложения во время выполнения трудоёмкой операции.
}
//Если после отправок пактов по 8 байт что-то осталось.
if(CurrentByte!=0)
{
outMsg.DataCount=CurrentByte;
do {
MSG_Status = writeMSG();
if (MSG_Status == 0x07)
{
outMsg.DataCount=8;
clearMSG();
QThread::usleep(5000);
isIdle=TRUE;
emit isTxFinished();
return;
}
} while(MSG_Status);
clearMSG();
}
//Возврат к стандартному количеству байт для отправки.
outMsg.DataCount=8;
//Оповещение об успешной передаче файла.
msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS][TX] Всего пакетов: %1. Успешно передано: %2. Ошибок передачи: %3."
).arg(div_up(data.size(), 8)).arg(Counter_of_suc_transmit).arg(TX_error_counter);
myEvent->~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()<<msg;
MacrosSetting *mcrs_w = new MacrosSetting();
Qt::CheckState arrEID[15];
DWORD arrID[15];
Qt::CheckState arrRTR[15];
Qt::CheckState arrIsHEX[15];
int arrDLC[15];
QString arrName[15];
QString arrMcrs[15];
int arrCount[15];
Qt::CheckState arrIsPeriod[15];
int arrPeriod[15];
//Ввод стартовых значений.
for (int i = 0; i < 15; i++)
{
arrEID[i] = MacrosMain[i].EID;
arrID[i] = MacrosMain[i].ID;
arrRTR[i] = MacrosMain[i].RTR;
arrIsHEX[i] = MacrosMain[i].IsHEX;
arrDLC[i] = MacrosMain[i].DLC;
arrName[i] = MacrosMain[i].Name;
arrMcrs[i] = MacrosMain[i].Mcrs;
arrCount[i] = MacrosMain[i].Count;
arrIsPeriod[i] = MacrosMain[i].IsPeriod;
arrPeriod[i] = MacrosMain[i].Period;
}
mcrs_w->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()<<msg;
}
else
{
msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS] Отмена изменений макросов.");
qDebug()<<msg;
}
mcrs_w->~MacrosSetting();
}
//Сохранить текущий набор макросов в файл.
void UnionCOM::on_buttonSaveMcrsKit_clicked()
{
QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS] Сохранение макросов.");
qDebug()<<msg;
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()<<msg;
return;
}
QFile file(fileName);
fileName.clear();
QByteArray buffer;
if(file.open(QFile::WriteOnly))
{
for(int i = 0; i < 15; i++)
{
buffer += MacrosMain[i].EID;
buffer += '\n';
buffer += QString::number(MacrosMain[i].ID, 16);
buffer += '\n';
buffer += MacrosMain[i].RTR;
buffer += '\n';
buffer += MacrosMain[i].IsHEX;
buffer += '\n';
buffer += QString::number(MacrosMain[i].DLC, 10);
buffer += '\n';
buffer += MacrosMain[i].Name;
buffer += '\n';
buffer += MacrosMain[i].Mcrs;
buffer += '\n';
buffer += QString::number(MacrosMain[i].Count, 10);
buffer += '\n';
buffer += MacrosMain[i].IsPeriod;
buffer += '\n';
buffer += QString::number(MacrosMain[i].Period, 10);
buffer += '\n';
file.write(buffer, buffer.size());
buffer.clear();
}
file.close();
QMessageBox msgBox;
msgBox.setText("Файл сохранён.");
msgBox.exec();
QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += "[SYS] Макросы сохранены в файл:";
qDebug() << msg;
qDebug() << file.fileName();
}
else
{
QMessageBox msgBox;
msgBox.setText("Нет доступа.");
msgBox.exec();
QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += "[SYS] Не удалось сохранить макросы: Нет доступа.";
qDebug() << msg;
return;
}
}
//Загрузить набор макросов из файла.
void UnionCOM::on_buttonLoadMcrsKit_clicked()
{
QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS] Загрузка макросов.");
qDebug()<<msg;
fileName = QFileDialog::getOpenFileName(this, "Open File", "/home/", "Bin Files (*.bin);;All files (*.*)");
if(fileName.isEmpty())
{
msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS] Отмена загрузки макросов.");
qDebug()<<msg;
return;
}
QFile file(fileName);
fileName.clear();
char buffer[MAX_MACROS_SIZE+1];
qint64 StatusOfRead;
mcrs_kit ReadMacrosKit[15];
if(file.open(QIODevice::ReadOnly))
{
for(int i = 0; i < 15; i++)
{
//EID Flag
StatusOfRead = file.readLine(buffer, MAX_MACROS_EID_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_EID_SIZE))
{
return;
}
ReadMacrosKit[i].EID = (Qt::CheckState)buffer[0];
//ID
StatusOfRead = file.readLine(buffer, MAX_MACROS_ID_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_ID_SIZE))
{
return;
}
QString subbuffer;
for(int j = 0; j < StatusOfRead-1; j++)
{
subbuffer += QString(buffer[j]);
}
ReadMacrosKit[i].ID = subbuffer.toInt(nullptr, 16);
subbuffer.clear();
//RTR Flag
StatusOfRead = file.readLine(buffer, MAX_MACROS_RTR_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_RTR_SIZE))
{
return;
}
ReadMacrosKit[i].RTR = (Qt::CheckState)buffer[0];
//Считывание значения HEX флага в макросе.
StatusOfRead = file.readLine(buffer, MAX_MACROS_HEX_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_HEX_SIZE))
{
return;
}
ReadMacrosKit[i].IsHEX = (Qt::CheckState)buffer[0];
//Считывание имени макроса.
StatusOfRead = file.readLine(buffer, MAX_MACROS_NAME_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_NAME_SIZE))
{
return;
}
StatusOfRead = file.readLine(buffer, MAX_DLC_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_DLC_SIZE))
{
return;
}
for(int j = 0; j < StatusOfRead-1; j++)
{
subbuffer += QString(buffer[j]);
}
ReadMacrosKit[i].DLC = subbuffer.toInt(nullptr, 10);
subbuffer.clear();
for(int j = 0; j < StatusOfRead-1; j++)
{
ReadMacrosKit[i].Name += QString(buffer[j]);
}
//Считывание макроса.
StatusOfRead = file.readLine(buffer, MAX_MACROS_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_SIZE))
{
return;
}
for(int j = 0; j < StatusOfRead-1; j++)
{
ReadMacrosKit[i].Mcrs += QString(buffer[j]);
}
//Считывание количества отправок.
StatusOfRead = file.readLine(buffer, MAX_MACROS_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_SIZE))
{
return;
}
for(int j = 0; j < StatusOfRead-1; j++)
{
subbuffer += QString(buffer[j]);
}
ReadMacrosKit[i].Count = subbuffer.toInt(nullptr, 10);
subbuffer.clear();
//Считывание значение флага периода.
StatusOfRead = file.readLine(buffer, MAX_MACROS_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_SIZE))
{
return;
}
ReadMacrosKit[i].IsPeriod = (Qt::CheckState)buffer[0];
//Считывание периода.
StatusOfRead = file.readLine(buffer, MAX_MACROS_SIZE+2);
if(CheckFile(StatusOfRead, buffer, MAX_MACROS_SIZE))
{
return;
}
for(int j = 0; j < StatusOfRead-1; j++)
{
subbuffer += QString(buffer[j]);
}
ReadMacrosKit[i].Period = subbuffer.toInt(nullptr, 10);
subbuffer.clear();
}
QString msg = QTime::currentTime().toString("[hh:mm:ss.zzz]");
msg += QString("[SYS] Загрузка набора макросов из файла:");
qDebug()<<msg;
qDebug() << file.fileName();
file.close();
//Если считывание файла прошло успешно - загрузка сохранённого набора макросов.
for(int i = 0; i < 15; i++)
{
MacrosMain[i].EID = ReadMacrosKit[i].EID;
MacrosMain[i].ID = ReadMacrosKit[i].ID;
MacrosMain[i].RTR = ReadMacrosKit[i].RTR;
MacrosMain[i].IsHEX = ReadMacrosKit[i].IsHEX;
MacrosMain[i].DLC = ReadMacrosKit[i].DLC;
MacrosMain[i].Name = ReadMacrosKit[i].Name;
MacrosMain[i].Mcrs = ReadMacrosKit[i].Mcrs;
MacrosMain[i].Count = ReadMacrosKit[i].Count;
MacrosMain[i].IsPeriod = ReadMacrosKit[i].IsPeriod;
MacrosMain[i].Period = ReadMacrosKit[i].Period;
if(!MacrosMain[i].Name.isEmpty())
{
McrsButtons[i]->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_Counter<MacrosMain[index].Count; TX_Counter++)
{
int i;
for(i = 0; i<(buffer.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)
{
if(MacrosMain[index].IsPeriod==Qt::Checked)
stopMcrs(index+1);
clearMSG();
outMsg.ID = oldID;
outMsg.Info = oldInfo;
isIdle=TRUE;
emit isTxFinished();
return;
}
} while(MSG_Status);
clearMSG();
}
//Если остались символы, передаём их.
if(i!=buffer.size())
{
int j;
for(j = 0; (j+i)<buffer.size(); j++)
{
outMsg.Data[j]=buffer[j+i];
}
outMsg.DataCount = j;
do {
MSG_Status = writeMSG();
if (MSG_Status == 0x07 || userTXInterruption)
{
if(MacrosMain[index].IsPeriod==Qt::Checked)
stopMcrs(index+1);
clearMSG();
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::pushMcrs_RS(int index)
{
isIdle=FALSE;
if(MacrosMain[index].Mcrs.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;
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_Counter<MacrosMain[index].Count; TX_Counter++)
{
m_serial->write(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();
}