M3KTE_TERM/M3KTE_TERM/m3kte.cpp

1947 lines
95 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 "m3kte.h"
#include "ui_m3kte.h"
#include "settingsdialog.h"
#include "writeregistermodel.h"
#include <QModbusTcpClient>
#include <QModbusRtuSerialMaster>
#include <QStandardItemModel>
#include <QStatusBar>
#include <QUrl>
#include <QScrollBar>
#include <QTableWidget>
#include <QPointer>
#include <QDebug>
#include <QProcess>
#include <QCoreApplication>
QWidget* init(QWidget *parent)
{
return new M3KTE(parent);
}
//1024 768
//Ширина колбы - уже
M3KTE::M3KTE(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::M3KTE)
{
ui->setupUi(this);
//Массив указателей на индикаторы напряжения топливных элементов
{
int i = 0;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_1;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_2;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_3;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_4;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_5;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_6;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_7;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_8;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_9;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_10;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_11;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_12;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_13;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_14;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_15;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_16;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_17;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_18;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_19;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_20;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_21;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_22;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_23;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_24;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_25;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_26;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_27;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_28;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_29;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_30;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_31;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_32;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_33;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_34;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_35;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_36;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_37;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_38;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_39;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_40;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_41;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_42;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_43;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_44;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_45;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_46;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_47;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_48;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_49;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_50;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_51;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_52;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_53;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_54;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_55;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_56;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_57;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_58;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_59;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_60;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_61;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_62;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_63;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_64;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_65;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_66;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_67;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_68;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_69;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_70;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_71;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_72;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_73;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_74;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_75;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_76;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_77;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_78;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_79;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_80;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_81;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_82;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_83;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_84;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_85;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_86;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_87;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_88;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_89;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_90;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_91;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_92;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_93;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_94;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_95;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_96;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_97;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_98;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_99;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_100;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_101;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_102;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_103;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_104;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_105;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_106;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_107;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_108;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_109;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_110;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_111;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_112;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_113;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_114;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_115;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_116;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_117;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_118;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_119;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_120;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_121;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_122;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_123;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_124;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_125;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_126;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_127;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_128;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_129;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_130;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_131;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_132;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_133;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_134;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_135;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_136;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_137;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_138;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_139;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_140;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_141;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_142;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_143;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_144;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_145;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_146;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_147;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_148;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_149;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_150;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_151;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_152;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_153;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_154;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_155;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_156;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_157;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_158;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_159;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_160;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_161;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_162;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_163;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_164;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_165;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_166;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_167;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_168;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_169;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_170;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_171;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_172;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_173;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_174;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_175;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_176;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_177;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_178;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_179;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_180;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_181;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_182;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_183;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_184;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_185;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_186;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_187;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_188;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_189;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_190;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_191;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_192;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_193;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_194;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_195;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_196;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_197;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_198;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_199;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_200;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_201;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_202;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_203;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_204;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_205;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_206;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_207;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_208;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_209;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_210;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_211;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_212;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_213;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_214;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_215;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_216;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_217;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_218;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_219;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_220;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_221;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_222;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_223;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_224;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_225;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_226;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_227;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_228;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_229;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_230;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_231;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_232;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_233;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_234;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_235;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_236;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_237;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_238;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_239;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_240;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_241;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_242;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_243;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_244;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_245;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_246;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_247;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_248;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_249;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_250;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_251;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_252;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_253;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_254;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_255;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_256;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_257;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_258;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_259;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_260;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_261;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_262;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_263;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_264;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_265;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_266;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_267;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_268;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_269;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_270;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_271;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_272;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_273;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_274;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_275;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_276;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_277;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_278;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_279;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_280;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_281;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_282;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_283;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_284;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_285;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_286;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_287;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_288;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_289;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_290;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_291;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_292;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_293;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_294;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_295;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_296;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_297;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_298;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_299;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_300;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_301;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_302;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_303;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_304;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_305;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_306;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_307;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_308;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_309;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_310;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_311;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_312;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_313;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_314;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_315;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_316;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_317;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_318;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_319;
m_ProgressBar[i++] = ui->FuelCellVoltageBar_320;
}
m_settingsDialog = new SettingsDialog(this);
ui->writeTable->addItem(tr("Exceptions"), QModbusDataUnit::Coils);
ui->writeTable->addItem(tr("Warnings"), QModbusDataUnit::HoldingRegisters);
ui->writeTable->addItem(tr("Accidents"), QModbusDataUnit::HoldingRegisters);
for(int i = 0; i < 4; i++) {
Boards[i].ModbusModelCoil = new WriteRegisterModel(this, 85 - (i/4*20), false);
Boards[i].ModbusModelCoil->setStartAddress(0);
Boards[i].ModbusModelCoil->setNumberOfValues(QString::number(85-(i/4*20)));
Boards[i].ModbusModelHoldingReg = new WriteRegisterModel(this, (85 - (i/4*20))*2, true);
Boards[i].ModbusModelHoldingReg->setStartAddress(0);
Boards[i].ModbusModelHoldingReg->setNumberOfValues(QString::number(85-(i/4*20)));
}
m_deviceSettingsDialog = new DeviceSettingsDialog(this);
m_regMultipleSettings = new MultipleSettings(this);
modbusDevice = new QModbusRtuSerialMaster(this);
m_lineRinger = new LineRinger();
Boards[0].boardScanners = new QTimer();
Boards[1].boardScanners = new QTimer();
Boards[2].boardScanners = new QTimer();
Boards[3].boardScanners = new QTimer();
Boards[0].boardScanners->setSingleShot(true);
Boards[1].boardScanners->setSingleShot(true);
Boards[2].boardScanners->setSingleShot(true);
Boards[3].boardScanners->setSingleShot(true);
connect(Boards[0].boardScanners, &QTimer::timeout, this, [this]() {
boardScan(0);
});
connect(Boards[1].boardScanners, &QTimer::timeout, this, [this]() {
boardScan(1);
});
connect(Boards[2].boardScanners, &QTimer::timeout, this, [this]() {
boardScan(2);
});
connect(Boards[3].boardScanners, &QTimer::timeout, this, [this]() {
boardScan(3);
});
{
Boards[0].adr = 1;
Boards[1].adr = 2;
Boards[2].adr = 3;
Boards[3].adr = 4;
}
ui->M3kteRegSettings->setEnabled(false);
ui->BSM_Warning->setEnabled(false);
ui->BSM_Accident->setEnabled(false);
ui->BSM_WorkInProgress->setEnabled(false);
initActions();
ui->BST_On->setCheckable(false);
ui->BST_Off->setChecked(true);
ui->boardSelectBox->setCurrentIndex(0);
ui->writeTable->setCurrentIndex(0);
changeTable(0, 0);
{
Boards_Fields[0] = ui->FCBoardBox;
Boards_Fields[1] = ui->FCBoardBox_2;
Boards_Fields[2] = ui->FCBoardBox_3;
Boards_Fields[3] = ui->FCBoardBox_4;
}
{
Boards[0].timerStatus = ui->timeStatus_1;
Boards[1].timerStatus = ui->timeStatus_2;
Boards[2].timerStatus = ui->timeStatus_3;
Boards[3].timerStatus = ui->timeStatus_4;
}
{
Boards[0].timerData = ui->timeData_1;
Boards[1].timerData = ui->timeData_2;
Boards[2].timerData = ui->timeData_3;
Boards[3].timerData = ui->timeData_4;
}
{
Boards[0].localError = ui->localErrorEdit_1;
Boards[1].localError = ui->localErrorEdit_2;
Boards[2].localError = ui->localErrorEdit_3;
Boards[3].localError = ui->localErrorEdit_4;
}
{
Boards[0].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_1;
Boards[1].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_2;
Boards[2].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_3;
Boards[3].localState[LOCAL_STATE_POLL] = ui->localPollChkBox_4;
Boards[0].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_1;
Boards[1].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_2;
Boards[2].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_3;
Boards[3].localState[LOCAL_STATE_WARN] = ui->localWarnChkBox_4;
Boards[0].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_1;
Boards[1].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_2;
Boards[2].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_3;
Boards[3].localState[LOCAL_STATE_ERR] = ui->localErrChkBox_4;
}
{ // не кликабельные чекбоксы и радиобоксы
for(int i = 0; i < 4; i++)
{
connect(Boards[i].localState[LOCAL_STATE_POLL], &QCheckBox::clicked,
this, [i, this](bool checked) {
m_deviceSettingsDialog->sendPollCommand(i, checked);
});
Boards[i].localState[LOCAL_STATE_WARN]->setAttribute(Qt::WA_TransparentForMouseEvents, true);
Boards[i].localState[LOCAL_STATE_ERR]->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
ui->BSM_Warning->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BSM_Accident->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BSM_WorkInProgress->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BST_On->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->BST_Off->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
for(int i = 0; i < 4; i++) {
statusM3KTE.Warnings[i] = false;
statusM3KTE.Accidents[i] = false;
Boards_Fields[i]->setEnabled(false);
Boards[i].timerData->setText(" ");
Boards[i].timerStatus->setText(" ");;
Boards[i].localError->setText(" ");;
}
for(int i = 0; i < 5; i++) {
ui->writeValueTable->resizeColumnToContents(i);
}
QBrush tb(Qt::transparent); // Transparent brush, solid pattern
for(int i = 0; i < 320; i++) {
m_ProgressBar[i]->setTextVisible(true);
m_ProgressBar[i]->setMinimumSize(25, 25);
m_ProgressBar[i]->setMaximumSize(25, 25);
m_ProgressBar[i]->resize(25, 25);
m_ProgressBar[i]->setAlignment(Qt::AlignCenter);
m_ProgressBar[i]->setFormat(QString("%1").arg((i%85+1)));
m_ProgressBar[i]->setValue(3);
QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} ";
m_ProgressBar[i]->setStyleSheet(style_fc_off);
ThePhantomMenace[i] = new QPushButton(m_ProgressBar[i]);
ThePhantomMenace[i]->setFlat(true);
ThePhantomMenace[i]->setPalette(QPalette(tb, tb, tb, tb, tb, tb, tb, tb, tb));
connect(ThePhantomMenace[i], &QPushButton::clicked, this, [this, i]() {
selectPositionOnTree(i);
});
}
connect(m_deviceSettingsDialog, &DeviceSettingsDialog::parityChanged, this, &M3KTE::onParityUpdate);
connect(m_deviceSettingsDialog, &DeviceSettingsDialog::speedChanged, this, &M3KTE::onSpeedUpdate);
loggerTable = new QTableWidget(ui->loggerWidget);
ui->loggerWidget->layout()->addWidget(loggerTable);
loggerTable->setColumnCount(5);
QStringList headers;
headers << "Время" << "Плата" << "Тип ошибки" << "Счётчик" << "Примечание";
loggerTable->setHorizontalHeaderLabels(headers);
loggerTable->setSortingEnabled(true);
loggerTable->setAutoScroll(true);
}
M3KTE::~M3KTE()
{
if(modbusDevice->state() == QModbusDevice::ConnectedState) {
onConnectClicked();
}
delete ui;
}
void M3KTE::initActions()
{
ui->ConnectionMenuConnect->setEnabled(true);
ui->ConnectionMenuDisconnect->setEnabled(false);
ui->ConnectionMenuSettings->setEnabled(true);
connect(ui->ConnectionMenuConnect, &QAction::triggered,
this, &M3KTE::onConnectClicked);
connect(ui->ConnectionMenuDisconnect, &QAction::triggered,
this, &M3KTE::onConnectClicked);
connect(ui->readButton, &QPushButton::clicked,
this, &M3KTE::onReadButtonClicked);
connect(ui->writeButton, &QPushButton::clicked,
this, &M3KTE::onWriteButtonClicked);
connect(ui->clearLoggerBtn, &QPushButton::clicked,
this, &M3KTE::clearLogger);
connect(ui->boardSelectBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &M3KTE::onSelectedBoardChanged);
connect(ui->writeTable, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &M3KTE::onWriteTableChanged);
connect(ui->LineCall, &QAction::triggered, m_lineRinger, &QWidget::show);
connect(ui->M3kteRegSettings, &QAction::triggered, m_regMultipleSettings, &QDialog::show);
connect(m_regMultipleSettings, &MultipleSettings::write, this, &M3KTE::slotmultipleRegWrite);
connect(m_regMultipleSettings, &MultipleSettings::writeAndSend, this, &M3KTE::slotmultipleRegWriteAndSend);
connect(ui->ConnectionMenuSettings, &QAction::triggered, m_settingsDialog, &QDialog::show);
connect(ui->M3kteMenuSettings, &QAction::triggered, m_deviceSettingsDialog, &QDialog::show);
}
void M3KTE::logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description)
{
unsigned newRow = loggerTable->rowCount();
loggerTable->insertRow(newRow);
loggerTable->setItem(newRow, 0, new QTableWidgetItem(QTime::currentTime().toString("HH:mm:ss")));
loggerTable->setItem(newRow, 1, new QTableWidgetItem(errorPlace));
loggerTable->setItem(newRow, 2, new QTableWidgetItem(errorString));
loggerTable->setItem(newRow, 3, new QTableWidgetItem(QString::number(errorCount)));
loggerTable->setItem(newRow, 4, new QTableWidgetItem(description));
loggerTable->resizeColumnsToContents();
if(!loggerTable->verticalScrollBar()->isSliderDown())
loggerTable->verticalScrollBar()->setSliderPosition(loggerTable->verticalScrollBar()->maximum());
}
void M3KTE::clearLogger()
{
// Проверяем, что таблица инициализирована
if (!loggerTable) {
return;
}
// Отключаем обновление UI для повышения производительности
loggerTable->setUpdatesEnabled(false);
// Очищаем все строки таблицы
loggerTable->setRowCount(0);
// Включаем обновление UI
loggerTable->setUpdatesEnabled(true);
}
void M3KTE::onConnectClicked()
{
if(!modbusDevice)
return;
statusBar()->clearMessage();
if(modbusDevice->state() != QModbusDevice::ConnectedState) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
m_settingsDialog->settings().portName);
#if QT_CONFIG(modbus_serialport)
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
m_settingsDialog->settings().parity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingsDialog->settings().baud);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
m_settingsDialog->settings().dataBits);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
m_settingsDialog->settings().stopBits);
#endif
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries);
if(!modbusDevice->connectDevice()) {
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
} else {
ui->ConnectionMenuConnect->setEnabled(false);
ui->ConnectionMenuDisconnect->setEnabled(true);
if(pingNetworkDevices()) { //Опрос устройств
unsigned tmp_adr[4];
bool ActiveDevices[4];
for(int i = 0; i < 4; i++) {
tmp_adr[i] = Boards[i].adr;
ActiveDevices[i] = Boards[i].isActive;
}
ui->M3kteRegSettings->setEnabled(true);
m_deviceSettingsDialog->updateSettingsAfterConnection(m_settingsDialog->settings().baud, m_settingsDialog->settings().parity, tmp_adr, ActiveDevices);
ui->boardSelectBox->setCurrentIndex(0);
ui->writeTable->setCurrentIndex(0);
changeTable(0, 0);
ui->M3kteMenuSettings->setEnabled(true);
ui->M3kteRegSettings->setEnabled(true);
ui->BST_Off->setCheckable(false);
ui->BST_Off->setChecked(false);
ui->BST_On->setCheckable(true);
ui->BST_On->setChecked(true);
ui->BSM_Warning->setEnabled(true);
ui->BSM_Accident->setEnabled(true);
ui->BSM_WorkInProgress->setEnabled(true);
ui->BSM_WorkInProgress->setChecked(true);
}
}
} else {
QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} ";
for(int i = 0; i < 4; i++) {
Boards[i].boardScanners->stop();
Boards_Fields[i]->setEnabled(false);
Boards[i].isActive=false;
for(int j = 0; j < (85 - (i/3*20)); j++) {
Boards[i].coil[j] = false;
Boards[i].ModbusModelCoil->m_coils[j]=0;
Boards[i].ModbusModelHoldingReg->m_currentU[j]=0;
Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j] = 0;
Boards[i].ModbusModelHoldingReg->m_holdingRegisters[j + (85 - (i/3*20))] = 0;
}
Boards_Fields[i]->setTitle(QString("Плата №%1").arg(i+1));
Boards[i].timerData->setText(" ");;
Boards[i].timerStatus->setText(" ");;
Boards[i].localError->setText(" ");;
}
for(int i = 0; i < 320; i++) {
m_ProgressBar[i]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85)));
m_ProgressBar[i]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(i/85+1), QString::number(i%85)));
m_ProgressBar[i]->setValue(3);
m_ProgressBar[i]->setStyleSheet(style_fc_off);
}
modbusDevice->disconnectDevice();
ui->M3kteMenuSettings->setEnabled(false);
ui->M3kteRegSettings->setEnabled(false);
ui->ConnectionMenuConnect->setEnabled(true);
ui->ConnectionMenuDisconnect->setEnabled(false);
ui->BST_Off->setCheckable(true);
ui->BST_Off->setChecked(true);
ui->BST_On->setCheckable(false);
ui->BST_On->setChecked(false);
ui->BSM_Warning->setChecked(false);
ui->BSM_Accident->setChecked(false);
ui->BSM_WorkInProgress->setChecked(false);
ui->BSM_Warning->setEnabled(false);
ui->BSM_Accident->setEnabled(false);
ui->BSM_WorkInProgress->setEnabled(false);
ui->M3kteRegSettings->setEnabled(false);
m_deviceSettingsDialog->onDisconnect();
}
}
void M3KTE::onReadButtonClicked()
{
if(!modbusDevice)
return;
statusBar()->clearMessage();
if(auto *reply = modbusDevice->sendReadRequest(readRequest(), Boards[ui->boardSelectBox->currentIndex()].adr)) {
if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &M3KTE::onReadReady);
else
delete reply; // broadcast replies return immediately
} else {
statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000);
}
}
void M3KTE::onReadReady()
{
auto reply = qobject_cast<QModbusReply *>(sender());
if(!reply)
return;
int Adr = 255;
for(int i = 0; i < 4; i++) {
if(Boards[i].isActive && Boards[i].adr==reply->serverAddress()) {
Adr = i;
break;
}
}
if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
for(int i = 0, total = int(unit.valueCount()); i < total; ++i) {
if(unit.registerType() == QModbusDataUnit::Coils) {
Boards[Adr].coil[i + unit.startAddress()] = unit.value(i);
if(unit.value(i)==1)
Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Checked, Qt::CheckStateRole);
else
Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Unchecked, Qt::CheckStateRole);
} else if(unit.registerType() == QModbusDataUnit::HoldingRegisters) {
Boards[Adr].HR[i + unit.startAddress()] = unit.value(i);
Boards[Adr].ModbusModelHoldingReg->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 16), Qt::EditRole);
}
}
switch(unit.registerType()) {
case QModbusDataUnit::Coils:
Boards[Adr].ModbusModelCoil->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 2),
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 2));
break;
case QModbusDataUnit::HoldingRegisters:
Boards[Adr].ModbusModelHoldingReg->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 3),
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 3));
break;
default:
break;
}
} else if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()).
arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
reply->errorString(), ++Boards[Adr].error_RX,
QString::number(reply->rawResult().exceptionCode()));
} else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).
arg(reply->error(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
reply->errorString(), ++Boards[Adr].error_RX,
QString::number(reply->error(), 16));
}
reply->deleteLater();
}
void M3KTE::onWriteButtonClicked()
{
if(!modbusDevice)
return;
statusBar()->clearMessage();
QModbusDataUnit writeUnit = writeRequest();
QModbusDataUnit::RegisterType table = writeUnit.registerType();
for(int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) {
if(table == QModbusDataUnit::Coils)
{
Boards[ui->boardSelectBox->currentIndex()].coil[i+writeUnit.startAddress()] =
Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()];
writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelCoil->m_coils[i + writeUnit.startAddress()]);
} else {
Boards[ui->boardSelectBox->currentIndex()].HR[i+writeUnit.startAddress()] =
Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i+writeUnit.startAddress()];
writeUnit.setValue(i, Boards[ui->boardSelectBox->currentIndex()].ModbusModelHoldingReg->m_holdingRegisters[i + writeUnit.startAddress()]);
}
}
if(auto *reply = modbusDevice->sendWriteRequest(writeUnit, Boards[ui->boardSelectBox->currentIndex()].adr)) {
if(!reply->isFinished()) {
unsigned tmp_id = ui->boardSelectBox->currentIndex();
connect(reply, &QModbusReply::finished, this, [this, reply, tmp_id]() {
if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
5000);
logError(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr),
reply->errorString(), ++Boards[tmp_id].error_TX,
QString::number(reply->rawResult().exceptionCode(), 16));
} else if(reply->error() != QModbusDevice::NoError) {
statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(tmp_id+1).arg(Boards[tmp_id].adr),
reply->errorString(), ++Boards[tmp_id].error_TX,
QString::number(reply->error()));
}
reply->deleteLater();
});
} else {
// broadcast replies return immediately
reply->deleteLater();
}
} else {
statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
logError(tr("Терминал"), modbusDevice->errorString(), 0, "");
}
}
void M3KTE::onSelectedBoardChanged(int index)
{
changeTable(index, ui->writeTable->currentIndex());
}
void M3KTE::onWriteTableChanged(int index)
{
changeTable(ui->boardSelectBox->currentIndex(), index);
}
void M3KTE::changeTable(int board, int tabletype)
{
if(tabletype==0) {
ui->writeValueTable->setModel(Boards[board].ModbusModelCoil);
int i = 0;
for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false);
}
ui->writeValueTable->hideColumn(3);
ui->writeValueTable->showColumn(2);
} else {
ui->writeValueTable->setModel(Boards[board].ModbusModelHoldingReg);
if(tabletype==1) {
Boards[board].ModbusModelHoldingReg->setStartAddress(0);
int i = 0;
for(;i<Boards[board].ModbusModelHoldingReg->rowCount()/2;i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false);
}
for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true);
}
} else {
Boards[board].ModbusModelHoldingReg->setStartAddress(Boards[board].ModbusModelHoldingReg->rowCount()/2);
int i = 0;
for(;i<Boards[board].ModbusModelHoldingReg->rowCount()/2;i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), true);
}
for(;i<Boards[board].ModbusModelHoldingReg->rowCount();i++) {
ui->writeValueTable->setRowHidden(i, ui->writeValueTable->model()->index(i, 0).parent(), false);
}
}
ui->writeValueTable->hideColumn(2);
ui->writeValueTable->showColumn(3);
}
for(int i = 0; i < 5; i++) {
ui->writeValueTable->resizeColumnToContents(i);
}
}
QModbusDataUnit M3KTE::readRequest() const
{
const auto table =
static_cast<QModbusDataUnit::RegisterType>(ui->writeTable->currentData().toInt());
int startAddress = 85 * (ui->writeTable->currentIndex()/2);
Q_ASSERT(startAddress >= 0 && startAddress < 340);
quint16 numberOfEntries = qMin((ushort)(85 - (ui->boardSelectBox->currentIndex()/3*20)), quint16(340 - startAddress));
return QModbusDataUnit(table, startAddress, numberOfEntries);
}
QModbusDataUnit M3KTE::writeRequest() const
{
const auto table =
static_cast<QModbusDataUnit::RegisterType>(ui->writeTable->currentData().toInt());
int startAddress = 85 * (ui->writeTable->currentIndex()/2);
Q_ASSERT(startAddress >= 0 && startAddress < 340);
quint16 numberOfEntries = qMin((ushort)(85 - (ui->boardSelectBox->currentIndex()/3*20)), quint16(340 - startAddress));
return QModbusDataUnit(table, startAddress, numberOfEntries);
}
bool M3KTE::event(QEvent *event)
{
if(event->type() == QEvent::User) {
BoardIdHasBeenChanged* _event = static_cast<BoardIdHasBeenChanged*>(event);
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 172, 1);
_unit->setValue(0, _event->BoardNewID());
Boards[_event->BoardNum()]._tmp_adr = _event->BoardNewID();
if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[_event->BoardNum()].adr)) {
if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [reply, this, _event, _unit]() {
if(reply->error()==QModbusDevice::TimeoutError) {
if(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[_event->BoardNum()]._tmp_adr)) {
if(!subreply->isFinished()) {
connect(subreply, &QModbusReply::finished, this, [subreply, this, _event]() {
checkAdrChange(subreply, _event->BoardNum());
});
} else {
logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
subreply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [1]");
reply->deleteLater();
delete subreply; // broadcast replies return immediately
}
} else {
logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [2]");
reply->deleteLater();
}
} else {
logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [3]");
reply->deleteLater();
}
});
else {
logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
reply->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [4]");
reply->deleteLater();
delete reply;
}
} else {
logError(tr("Плата %1 (ID %2)").arg(_event->BoardNum()+1).arg(Boards[_event->BoardNum()].adr),
modbusDevice->errorString(), ++Boards[_event->BoardNum()].error_adr_change,
"Не удалось изменить адрес устройства. [5]");
reply->deleteLater();
}
m_deviceSettingsDialog->show();
return true;
} else if(event->type() == (QEvent::Type)1001) {
pollStatusChange* _event = static_cast<pollStatusChange*>(event);
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 170, 1);
_unit->setValue(0, _event->Status());
if(auto *reply = modbusDevice->sendWriteRequest(*_unit, Boards[_event->BoardID()].adr)) {
if(!reply->isFinished())
connect(reply, &QModbusReply::finished, this, [reply, this, _event]() {
if(reply->error()!=QModbusDevice::NoError) {
logError(tr("Плата %1 (ID %2)").arg(_event->BoardID()+1).arg(Boards[_event->BoardID()].adr),
reply->errorString(), ++Boards[_event->BoardID()].error_cmd_change, "");
reply->deleteLater();
}
});
} else {
logError(tr("Плата %1 (ID %2)").arg(_event->BoardID()+1).arg(Boards[_event->BoardID()].adr),
modbusDevice->errorString(), ++Boards[_event->BoardID()].error_cmd_change, "");
reply->deleteLater();
}
return true;
}
return QWidget::event(event);
}
void M3KTE::checkAdrChange(QModbusReply *reply, unsigned boardNum)
{
if(!reply) {
logError(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr),
modbusDevice->errorString(), ++Boards[boardNum].error_adr_change,
"Не удалось проверить изменение адреса устройства.");
reply->deleteLater();
return;
}
if(reply->error() == QModbusDevice::NoError) {
//OK
Boards[boardNum].adr = Boards[boardNum]._tmp_adr;
reply->deleteLater();
} else {
logError(tr("Плата %1 (ID %2)").arg(boardNum+1).arg(Boards[boardNum].adr),
reply->errorString(), ++Boards[boardNum].error_adr_change,
"Ошибка при подтверждении изменения адреса устройства.");
reply->deleteLater();
}
}
void M3KTE::checkBoards()
{
QModbusDataUnit unitCheck(QModbusDataUnit::InputRegisters, 85, 1);
// Используем shared pointers вместо ссылок на стековые переменные
auto totalActiveBoards = QSharedPointer<int>::create(0);
auto confirmedBoards = QSharedPointer<int>::create(0);
auto pendingBoards = QSharedPointer<QSet<int>>::create();
for(int i = 0; i < 4; ++i) {
if(!Boards[i].isActive)
continue;
(*totalActiveBoards)++;
int slaveAddress = Boards[i].adr;
QModbusReply *reply = modbusDevice->sendReadRequest(unitCheck, slaveAddress);
if(!reply) {
revertToOldSpeedAndRestart();
return;
}
pendingBoards->insert(slaveAddress);
connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAddress, totalActiveBoards, confirmedBoards, pendingBoards]() {
if(reply->error() == QModbusDevice::NoError) {
(*confirmedBoards)++;
} else {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAddress),
reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при подтверждении изменения скорости обмена.");
}
pendingBoards->remove(slaveAddress);
reply->deleteLater();
if(pendingBoards->isEmpty()) {
if(*confirmedBoards != *totalActiveBoards) {
emit errorAtCheckBoards();
} else {
emit successAtCheckBoards();
}
}
});
}
// Если нет ни одной активной платы — сразу запускаем сканирование
if(*totalActiveBoards == 0) {
emit errorAtCheckBoards();
}
}
void M3KTE::onSpeedUpdate()
{
stopScanBoard();
modbusDevice->setTimeout(500);
unsigned tmp_speed = 0;
switch(m_deviceSettingsDialog->currentSpeed()) {
case 0: tmp_speed = 9600; break;
case 1: tmp_speed = 14400; break;
case 2: tmp_speed = 19200; break;
case 3: tmp_speed = 31250; break;
case 4: tmp_speed = 38400; break;
case 5: tmp_speed = 56000; break;
case 6: tmp_speed = 57600; break;
case 7: tmp_speed = 115200; break;
}
if(tmp_speed == 0) {
logError(tr("Программная ошибка"), "Неожиданное значение скорости", 0,
"Ошибка при изменении скорости обмена.");
beginScanBoards();
return;
}
// Используем shared pointers вместо ссылок на стековые переменные
auto totalActiveBoards = QSharedPointer<int>::create(0);
auto confirmedBoards = QSharedPointer<int>::create(0);
auto pendingBoards = QSharedPointer<QSet<int>>::create();
auto newSpeed = tmp_speed; // копируем для захвата
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 173, 1);
unit.setValue(0, m_deviceSettingsDialog->currentSpeed());
// Лямбда для обработки результата
auto processResult = [this, totalActiveBoards, confirmedBoards, newSpeed]() {
if(*confirmedBoards != *totalActiveBoards) {
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
revertToOldSpeedAndRestart();
beginScanBoards();
} else {
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, newSpeed);
modbusDevice->connectDevice();
// Используем QPointer для безопасного доступа к this
QPointer<M3KTE> safeThis(this);
connect(this, &M3KTE::errorAtCheckBoards, this, [safeThis]() {
if (!safeThis) return;
safeThis->disconnect(safeThis, &M3KTE::errorAtCheckBoards, safeThis, nullptr);
safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime);
safeThis->revertToOldSpeedAndRestart();
safeThis->beginScanBoards();
});
connect(this, &M3KTE::successAtCheckBoards, this, [safeThis]() {
if (!safeThis) return;
safeThis->disconnect(safeThis, &M3KTE::successAtCheckBoards, safeThis, nullptr);
safeThis->m_settingsDialog->UpdateBaud(safeThis->m_deviceSettingsDialog->currentSpeed());
safeThis->modbusDevice->setTimeout(safeThis->m_settingsDialog->settings().responseTime);
safeThis->beginScanBoards();
});
checkBoards();
}
};
for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive)
continue;
int slaveAdress = Boards[i].adr;
auto *reply = modbusDevice->sendWriteRequest(unit, slaveAdress);
if(reply) {
(*totalActiveBoards)++;
pendingBoards->insert(slaveAdress);
// Захватываем shared pointers по значению - это безопасно
connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() {
if(reply->error() == QModbusDevice::TimeoutError) {
(*confirmedBoards)++;
} else if (reply->error() == QModbusDevice::NoError) {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
tr("Неожиданный ответ."), ++Boards[i].error_baud_change,
"Ошибка при изменении скорости обмена.");
} else {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при изменении скорости обмена.");
}
pendingBoards->remove(slaveAdress);
reply->deleteLater();
if(pendingBoards->isEmpty()) {
processResult();
}
});
}
}
}
// Вспомогательная функция восстановления старой скорости
void M3KTE::revertToOldSpeedAndRestart()
{
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingsDialog->curBaud());
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
modbusDevice->connectDevice();
}
void M3KTE::onParityUpdate()
{
stopScanBoard();
modbusDevice->setTimeout(500);
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 174, 1);
switch(m_deviceSettingsDialog->currentParity()) {
case 0: //Нет контроля
unit.setValue(0, 0x000);
break;
case 1: //Четный
unit.setValue(0, 0x0400);
break;
case 2: //Нечетный
unit.setValue(0, 0x0600);
break;
}
// Используем shared pointers вместо ссылок на стековые переменные
auto totalActiveBoards = QSharedPointer<int>::create(0);
auto confirmedBoards = QSharedPointer<int>::create(0);
auto pendingBoards = QSharedPointer<QSet<int>>::create();
auto oldParity = m_settingsDialog->curParity(); // сохраняем старую четность для отката
auto newParity = m_deviceSettingsDialog->currentParity();
// Лямбда для обработки результата
auto processResult = [this, totalActiveBoards, confirmedBoards, oldParity, newParity]() {
if(*confirmedBoards != *totalActiveBoards) {
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards();
} else {
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, newParity);
modbusDevice->connectDevice();
auto errorHandler = [this, oldParity]() {
disconnect(this, &M3KTE::errorAtCheckBoards, this, nullptr);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, oldParity);
modbusDevice->connectDevice();
beginScanBoards();
};
auto successHandler = [this, newParity]() {
disconnect(this, &M3KTE::successAtCheckBoards, this, nullptr);
m_settingsDialog->UpdateParity(newParity);
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
beginScanBoards();
};
connect(this, &M3KTE::errorAtCheckBoards, this, errorHandler);
connect(this, &M3KTE::successAtCheckBoards, this, successHandler);
checkBoards();
}
};
for(int i = 0; i < 4; i++) {
if(!Boards[i].isActive)
continue;
int slaveAdress = Boards[i].adr;
auto *reply = modbusDevice->sendWriteRequest(unit, slaveAdress);
if(reply) {
(*totalActiveBoards)++;
pendingBoards->insert(slaveAdress);
connect(reply, &QModbusReply::finished, this,
[this, i, reply, slaveAdress, totalActiveBoards, confirmedBoards, pendingBoards, processResult]() {
if(reply->error() == QModbusDevice::TimeoutError) {
(*confirmedBoards)++;
} else if (reply->error() == QModbusDevice::NoError) {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
tr("Неожиданный ответ."), ++Boards[i].error_baud_change,
"Ошибка при изменении чётности.");
} else {
logError(tr("Плата %1 (ID %2)").arg(i+1).arg(slaveAdress),
reply->errorString(), ++Boards[i].error_baud_change,
"Ошибка при изменении чётности.");
}
pendingBoards->remove(slaveAdress);
reply->deleteLater();
if(pendingBoards->isEmpty()) {
processResult();
}
});
}
}
}
bool M3KTE::pingNetworkDevices()
{
CurrentConnectedDevice = 0;
int tmp_adr = 1;
bool isRun = false;
bool *tmp_isRun = &isRun;
auto bar = new QProgressDialog(this);
connect(bar, &QProgressDialog::canceled, this, [tmp_isRun]() {
*tmp_isRun = true;
});
bar->setLabelText(tr("Поиск плат... Текущий адрес: %1").arg(tmp_adr));
bar->setCancelButton(nullptr);
bar->setRange(0, 4);
bar->setMinimumDuration(100);
bar->setValue(CurrentConnectedDevice);
modbusDevice->setNumberOfRetries(0);
QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404"));
QModbusRequest requestOfBoardID(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0401"));
for(CurrentConnectedDevice=0; CurrentConnectedDevice<4;) {
modbusDevice->setTimeout(1000);
auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr);
//Запрос типа устройства.
if(reply == nullptr) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
while(!reply->isFinished()) {
if(isRun && CurrentConnectedDevice < 1) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(isRun) {
break;
}
QCoreApplication::processEvents();
}
if(isRun && CurrentConnectedDevice < 1) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(isRun) {
break;
} else if(!isRun) {
//Нужна проверка типа устройства
if(reply->error()==QModbusDevice::NoError) {
QModbusResponse resp = reply->rawResult();
QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH));
if(result == QString("KTE")) {
modbusDevice->setTimeout(1000);
auto *subreply = modbusDevice->sendRawRequest(requestOfBoardID, tmp_adr);
while(!subreply->isFinished()) {
if(isRun && CurrentConnectedDevice < 1) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(isRun) {
break;
}
QCoreApplication::processEvents();
}
int plata_ind = 0;
if(subreply->rawResult().data().size() >= MODBUS_REQUEST_PROTOCOL_INFO_LENGTH) // ответ принят
plata_ind = subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH); // парс ответа
if(plata_ind == 0) // если номер = 0 повторяем всё еще раз
{
qDebug() << "Reqest plata_ind again for address " << tmp_adr;
subreply = modbusDevice->sendRawRequest(requestOfBoardID, tmp_adr);
while(!subreply->isFinished()) {
if(isRun && CurrentConnectedDevice < 1) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(isRun) {
break;
}
QCoreApplication::processEvents();
}
plata_ind = subreply->rawResult().data().at(MODBUS_REQUEST_PROTOCOL_INFO_LENGTH);
}
if(plata_ind == 0)
{
QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Не удалось получить порядковый номер платы по адресу %1").arg(tmp_adr));
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
int board_ind = plata_ind-1;
if(isRun && CurrentConnectedDevice < 1) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(isRun) {
break;
} else {
statusBar()->showMessage(tr("Плата %1 найдена по адресу %2.").arg(board_ind).arg(tmp_adr),
m_settingsDialog->settings().responseTime);
if(Boards[board_ind].isActive) {
QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Платы по адресам %1 и %2 имеют одинаковый порядковый номер %3").arg(Boards[board_ind].adr).arg(tmp_adr).arg(plata_ind));
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
CurrentConnectedDevice++;
Boards[board_ind].adr = Boards[board_ind]._tmp_adr = tmp_adr;
Boards[board_ind].isActive = true;
bar->setValue(CurrentConnectedDevice);
}
}
}
}
tmp_adr++;
bar->setLabelText(tr("Поиск плат... Текущий адрес: %1").arg(tmp_adr));
if(tmp_adr>=247 && (CurrentConnectedDevice<1)) {
//ERROR
//OUT OF RANGE
QMessageBox::warning(this, "Ошибка при сканировании сети.",
QString("Выход за пределы допустимых адресов. Найдено %1 плат.").arg(CurrentConnectedDevice));
bar->setValue(4);
bar->close();
bar->deleteLater();
onConnectClicked();
return false;
} else if(tmp_adr>=247) {
break;
}
}
isRun=false;
QMessageBox::warning(this, "Сканирование сети завершено.", tr("Найдено плат: %1 из 4.").arg(CurrentConnectedDevice));
if(isRun) {
QMessageBox::warning(this, "Ошибка при получении текущих настроек.", QString("Прерывание по запросу пользователя."));
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
bar->setLabelText(tr("Считывание текущих настроек..."));
bar->setRange(0, CurrentConnectedDevice*3);
QModbusDataUnit* _unit_settings[3];
_unit_settings[0] = new QModbusDataUnit(QModbusDataUnit::Coils, 0, 85);
_unit_settings[1] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 0, 85);
_unit_settings[2] = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 85, 85);
for(int i = 0; i < 4; i++) {
if(Boards[i].isActive) {
Boards_Fields[i]->setEnabled(true);
for(int j = 0; j < 3; j++) {
bar->setValue(i*3+j);
if(isRun) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
auto *reply = modbusDevice->sendReadRequest(*_unit_settings[j], Boards[i].adr);
if(!reply) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
while(!reply->isFinished()) {
if(isRun) {
QMessageBox::warning(this, "Ошибка при получении текущих настроек.",
QString("Прерывание по запросу пользователя."));
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
QCoreApplication::processEvents();
}
if(reply->error()==QModbusDevice::NoError) {
applySettingsFromScan(reply);
} else {
QMessageBox::warning(this, "Ошибка при получении текущих настроек.",
QString("Таймаут при опросе устройства %1 по адресу %2").arg(i+1).arg(Boards[i].adr));
bar->setValue(CurrentConnectedDevice*3);
bar->close();
bar->deleteLater();
onConnectClicked();
return false;
}
}
Boards_Fields[i]->setTitle(QString("Плата №%1 (ID %2)").arg(i+1).arg(Boards[i].adr));
}
}
modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries);
beginScanBoards();
bar->deleteLater();
return true;
}
void M3KTE::beginScanBoards()
{
for(int i = 0; i < 4; i++) {
if(Boards[i].isActive) {
m_deviceSettingsDialog->initPollForBoard(i, Boards[i].adr);
boardScan(i);
}
}
return;
}
void M3KTE::boardScan(unsigned boardID)
{
if (!modbusDevice) {
return;
}
statusBar()->clearMessage();
QModbusDataUnit statusUnit(QModbusDataUnit::InputRegisters, 85, 1);
if (auto *reply = modbusDevice->sendReadRequest(statusUnit, Boards[boardID].adr)) {
Boards[boardID].timerToStatusResponse.start();
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, boardID, reply]() {
if(!Boards[boardID].isActive)
return;
// Обработка ответа статуса
Boards[boardID].timerStatus->setText(QString("Status: %1 ms").arg(Boards[boardID].timerToStatusResponse.elapsed()));
if (reply->error() == QModbusDevice::NoError) {
statusreg StatusReg;
StatusReg.AllReg = reply->result().value(0);
// Запрос полных данных
QModbusDataUnit dataUnit(QModbusDataUnit::InputRegisters, 0, 85);
if (auto *dataReply = modbusDevice->sendReadRequest(dataUnit, Boards[boardID].adr)) {
Boards[boardID].timerToDataResponse.start();
if (!dataReply->isFinished()) {
connect(dataReply, &QModbusReply::finished, this, [this, boardID, dataReply, StatusReg]() {
if(!Boards[boardID].isActive)
return;
Boards[boardID].timerData->setText(QString("Data: %1 ms").arg(Boards[boardID].timerToDataResponse.elapsed()));
displayResultOfScan(dataReply, boardID, StatusReg.AllReg);
dataReply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
});
} else {
// Мгновенно завершенный запрос данных
Boards[boardID].timerToDataResponse.elapsed();
// shouldLog для dataReply должен определяться здесь, но используем тот же принцип
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
dataReply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
} else {
// Ошибка отправки запроса данных
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
} else {
// Ошибка в ответе статуса
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_TX, "");
}
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
reply->deleteLater();
});
} else {
// Мгновенно завершенный запрос статуса
Boards[boardID].timerToStatusResponse.elapsed();
// Для мгновенно завершенных запросов определяем shouldLog здесь
if (Boards[boardID].isActive && !(reply->error() == QModbusDevice::ReplyAbortedError)) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
reply->deleteLater();
unsigned timerInterval = m_deviceSettingsDialog->currentBoardTimer(boardID);
Boards[boardID].boardScanners->start(timerInterval);
}
} else {
// Ошибка отправки запроса статуса
if (Boards[boardID].isActive) {
logError(tr("Плата %1 (ID %2)").arg(boardID + 1).arg(Boards[boardID].adr),
modbusDevice->errorString(), ++Boards[boardID].error_TX, "");
}
}
}
void M3KTE::displayResultOfScan(QModbusReply *reply, int boardID, int status)
{
if(!reply)
return;
if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
bool W_Flag = false;
bool A_Flag = false;
if(unit.startAddress() != 0 || unit.valueCount() != 85) {
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
"Ошибка при приёме.", ++Boards[boardID].error_RX,
tr("Принятый ответ: Стартовый адрес %1, Количество элементов %2").arg(unit.startAddress()).arg(unit.valueCount()));
reply->deleteLater();
return;
}
statusreg StatusReg;
StatusReg.AllReg = status;
// Обрабатываем статус MZKT
QString statusText;
int state = StatusReg.ParsingReg.mzkte_status;
int numb_err = StatusReg.ParsingReg.mzkte_error;
if (state == 0) {
statusText = "Ok";
} else if (state == 1) {
statusText = "Non-Critical";
} else if (state == 2) {
statusText = "Critical";
}
if (state) {
switch (numb_err) {
case 1:
statusText += QString(" (Err 5 VD)");
break;
case 2:
statusText += QString(" (Err 5 VA)");
break;
case 3:
statusText += QString(" (Err 5 Vsci)");
break;
case 4:
statusText += QString(" (Err 24 V)");
break;
case 5:
statusText += QString(" (Hardfault)");
break;
case 6:
statusText += QString(" (ADC Error)");
break;
case 7:
statusText += QString(" (UART Error)");
break;
case 8:
statusText += QString(" (Measure Error)");
break;
default:
statusText += QString(" (Program Err %1)").arg(numb_err - 4);
break;
}
}
Boards[boardID].localError->setText(statusText);
Boards[boardID].localState[LOCAL_STATE_POLL]->setChecked(StatusReg.ParsingReg.poll_allowed);
Boards[boardID].localState[LOCAL_STATE_WARN]->setChecked(StatusReg.ParsingReg.warning);
Boards[boardID].localState[LOCAL_STATE_ERR]->setChecked(StatusReg.ParsingReg.accident);
QString W_Adr;
QString A_Adr;
for(int i = unit.startAddress(), total = int(unit.valueCount()); i < total; ++i) {
if(Boards[boardID].coil[i]==true) {
int j = 0;
if(Boards[boardID].HR[i+85] > unit.value(i)) {
j = 1;
if(j != m_ProgressBar[i+boardID*85]->value()) {
A_Adr += tr("ТЭ%1 ").arg(i);
Boards[boardID].error_A++;
}
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Аварийный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
A_Flag = true;
} else if(Boards[boardID].HR[i] > unit.value(i)) {
j = 2;
if(j != m_ProgressBar[i+boardID*85]->value()) {
W_Adr += tr("ТЭ%1 ").arg(i);
Boards[boardID].error_W++;
}
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Предупредительный уровень напряжения.").arg(QString::number(boardID+1), QString::number(i%85)));
W_Flag = true;
} else {
j = 3;
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Уровень напряжения в норме.").arg(QString::number(boardID+1), QString::number(i%85)));
}
m_ProgressBar[i+boardID*85]->setValue(j);
QString style_fc = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(j*50-50) + ", 255, 255, 100%);} ";
m_ProgressBar[i+boardID*85]->setStyleSheet(style_fc);
} else {
m_ProgressBar[i+boardID*85]->setValue(3);
m_ProgressBar[i+boardID*85]->setStatusTip(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85)));
m_ProgressBar[i+boardID*85]->setWhatsThis(QString("П%1 ТЭ%2: Топливный Элемент не учитывается.").arg(QString::number(boardID+1), QString::number(i%85)));
QString style_fc_off = "QProgressBar {border: 2px solid black; font: bold 10px} QProgressBar::chunk {background: hsva(" + QString::number(30) + ", 30, 30, 30%);} ";
m_ProgressBar[i+boardID*85]->setStyleSheet(style_fc_off);
}
Boards[boardID].ModbusModelCoil->set_currentU(unit.value(i), i);
Boards[boardID].ModbusModelHoldingReg->set_currentU(unit.value(i), i);
}
Boards[boardID].ModbusModelCoil->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 2),
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 2));
Boards[boardID].ModbusModelHoldingReg->dataChanged(ui->writeValueTable->model()->index(unit.startAddress(), 3),
ui->writeValueTable->model()->index(unit.startAddress() + unit.valueCount() -1, 3));
if(A_Flag && !A_Adr.isEmpty()) {
statusM3KTE.Accidents[boardID] = true;
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
"Авария", Boards[boardID].error_A, A_Adr);
} else
statusM3KTE.Accidents[boardID] = false;
if(W_Flag && !W_Adr.isEmpty()) {
statusM3KTE.Warnings[boardID] = true;
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
"Предупреждение", Boards[boardID].error_W, W_Adr);
} else
statusM3KTE.Warnings[boardID] = false;
ui->BSM_Warning->setChecked(false);
ui->BSM_Accident->setChecked(false);
ui->BSM_WorkInProgress->setChecked(true);
for(int i = 0; i < 4; i++) {
if(statusM3KTE.Accidents[i]) {
ui->BSM_WorkInProgress->setChecked(false);
ui->BSM_Warning->setChecked(false);
ui->BSM_Accident->setChecked(true);
break;
}
if(statusM3KTE.Warnings[i]) {
ui->BSM_WorkInProgress->setChecked(false);
ui->BSM_Accident->setChecked(false);
ui->BSM_Warning->setChecked(true);
}
}
} else if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_RX,
QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16));
} else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(boardID+1).arg(Boards[boardID].adr),
reply->errorString(), ++Boards[boardID].error_RX,
QString::number(reply->error(), 16));
}
reply->deleteLater();
}
void M3KTE::applySettingsFromScan(QModbusReply *reply)
{
int Adr = 255;
for(int i = 0; i < 4; i++) {
if(Boards[i].adr==reply->serverAddress() &&Boards[i].isActive) {
Adr = i;
break;
}
}
if(reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
for(int i = 0, total = int(unit.valueCount()); i < (total); ++i) {
if(unit.registerType() == QModbusDataUnit::Coils) {
Boards[Adr].coil[i + unit.startAddress()] = unit.value(i);
if(unit.value(i)==1) {
Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Checked, Qt::CheckStateRole);
} else {
Boards[Adr].ModbusModelCoil->setData(ui->writeValueTable->model()->index(i + unit.startAddress(), 2), Qt::Unchecked, Qt::CheckStateRole);
}
} else if(unit.registerType() == QModbusDataUnit::HoldingRegisters) {
Boards[Adr].HR[i + unit.startAddress()] = unit.value(i);
Boards[Adr].ModbusModelHoldingReg->setData(Boards[Adr].ModbusModelHoldingReg->index(i + unit.startAddress(), 3), QString::number(unit.value(i), 16), Qt::EditRole);
}
}
} else if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
reply->errorString(), ++Boards[Adr].error_RX,
QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16));
} else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
reply->errorString(), ++Boards[Adr].error_RX,
QString::number(reply->error(), 16));
}
reply->deleteLater();
}
void M3KTE::slotmultipleRegWrite()
{
if(!modbusDevice)
return;
multipleRegWrite();
}
void M3KTE::slotmultipleRegWriteAndSend()
{
if(!modbusDevice)
return;
multipleRegWrite();
multipleRegSend();
}
void M3KTE::multipleRegSend()
{
QModbusDataUnit *unit_tx = nullptr;
if(m_regMultipleSettings->getTypeReg()) {
unit_tx = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, m_regMultipleSettings->getStartAdr(), m_regMultipleSettings->getCountReg());
} else {
unit_tx = new QModbusDataUnit(QModbusDataUnit::Coils, m_regMultipleSettings->getStartAdr(), m_regMultipleSettings->getCountReg());
}
for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) {
unit_tx->setValue(i, m_regMultipleSettings->getNewValue());
if(m_regMultipleSettings->getTypeReg()) {
Boards[m_regMultipleSettings->getBoardId()].HR[i+m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue();
} else {
Boards[m_regMultipleSettings->getBoardId()].coil[i+m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue();
}
}
if(auto *reply = modbusDevice->sendWriteRequest(*unit_tx, Boards[m_regMultipleSettings->getBoardId()].adr)) {
unsigned Adr = m_regMultipleSettings->getBoardId();
if(!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, reply, Adr]() {
if(reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
reply->errorString(), ++Boards[Adr].error_TX,
QString("Mobus exception: 0x%1").arg(reply->rawResult().exceptionCode(), -1, 16));
} else if(reply->error() != QModbusDevice::NoError) {
statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
logError(tr("Плата %1 (ID %2)").arg(Adr+1).arg(Boards[Adr].adr),
reply->errorString(), ++Boards[Adr].error_TX,
QString::number(reply->error(), 16));
}
reply->deleteLater();
});
} else {
// broadcast replies return immediately
reply->deleteLater();
}
} else {
statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
}
}
void M3KTE::multipleRegWrite()
{
for(unsigned i = 0; i < m_regMultipleSettings->getCountReg(); i++) {
if(m_regMultipleSettings->getTypeReg()) {
Boards[m_regMultipleSettings->getBoardId()].ModbusModelHoldingReg->m_holdingRegisters[i+m_regMultipleSettings->getStartAdr()] = m_regMultipleSettings->getNewValue();
} else {
Boards[m_regMultipleSettings->getBoardId()].ModbusModelCoil->m_coils[i+m_regMultipleSettings->getStartAdr()] = (bool)m_regMultipleSettings->getNewValue();
}
}
}
void M3KTE::selectPositionOnTree(unsigned int index)
{
ui->boardSelectBox->setCurrentIndex(index/85);
QModelIndex selected = ui->writeValueTable->model()->index(index%85, 0);
ui->writeValueTable->selectionModel()->select(selected, QItemSelectionModel::ClearAndSelect |QItemSelectionModel::Rows);
ui->writeValueTable->scrollTo(selected);
}
bool M3KTE::autoBaudRateScan()
{
unsigned countOfDeviceOnLine = 0;
QString resultOfScan;
QVector<unsigned> KTE[8];
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
m_settingsDialog->settings().portName);
#if QT_CONFIG(modbus_serialport)
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
m_settingsDialog->settings().parity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
m_settingsDialog->settings().dataBits);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
m_settingsDialog->settings().stopBits);
#endif
modbusDevice->setTimeout(50);
modbusDevice->setNumberOfRetries(0);
uint m_baud[] = {9600, 14400, 19200, 31250, 38400, 56000, 57600, 115200};
bool isRun = false;
bool *tmp_isRun = &isRun;
auto bar = new QProgressDialog(this);
connect(bar, &QProgressDialog::canceled, this, [tmp_isRun]() {
*tmp_isRun = true;
});
bar->setCancelButton(nullptr);
bar->setRange(0, 8);
bar->setMinimumDuration(100);
bar->setValue(0);
QModbusRequest requestOfDeviceType(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0404"));
for(int i = 0; i < 8; i++) {
bar->setValue(i);
bar->setLabelText(tr("Поиск плат... Текущая скорость: %1").arg(m_baud[i]));
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]);
if(!modbusDevice->connectDevice()) {
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
}
for(int tmp_adr = 1; tmp_adr < 248; tmp_adr++) {
auto *reply = modbusDevice->sendRawRequest(requestOfDeviceType, tmp_adr);
//Запрос типа устройства.
if(reply == nullptr) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
while(!reply->isFinished()) {
if(isRun) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
QCoreApplication::processEvents();
}
if(isRun) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
} else if(!isRun) {
//Нужна проверка типа устройства
if(reply->error()==QModbusDevice::NoError) {
QModbusResponse resp = reply->rawResult();
QString result = QString(resp.data().remove(0, MODBUS_REQUEST_PROTOCOL_INFO_LENGTH));
if(result == QString("KTE")) {
countOfDeviceOnLine++;
KTE[i].append(tmp_adr);
}
}
}
}
if(countOfDeviceOnLine>0)
resultOfScan += QString("%1 плат M3KTE работают на скорости %2.\n").arg(countOfDeviceOnLine).arg(m_baud[i]);
countOfDeviceOnLine = 0;
modbusDevice->disconnectDevice();
}
if(m_scanBoard->exec()==QDialog::Accepted) {
if(m_scanBoard->getCheckState()==Qt::Checked) {
for(int i = 0; i < 8; i++) {
for(int j = 0; j < KTE[i].size(); j++) {
for(int l = i; l < 8; l++) {
if(KTE[l].indexOf(KTE[i].at(j))==-1) {
QMessageBox::warning(this, "Error",
QString("Несколько устройств по адресу %1, работающих на скоростях %2 и %3.").arg(KTE[i].at(j)).arg(m_baud[i]).arg(m_baud[l]));
return false;
}
}
}
}
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 173, 1);
_unit->setValue(0, m_scanBoard->getBaud());
for(int i = 0; i < 8; i++) {
bar->setValue(i);
bar->setLabelText(tr("Синхронизация плат на скорости %1").arg(m_baud[i]));
for(int j = 0; j < KTE[i].size(); j++) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baud[i]);
if(!modbusDevice->connectDevice()) {
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
}
auto *reply = modbusDevice->sendWriteRequest(*_unit, KTE[i].at(j));
if(!reply) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
while(!reply->isFinished()) {
if(isRun) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
QCoreApplication::processEvents();
}
if(reply->error()==QModbusDevice::TimeoutError) {
modbusDevice->disconnectDevice();
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingsDialog->UpdateBaud(m_scanBoard->getBaud()));
modbusDevice->connectDevice();
QModbusDataUnit* _unit = new QModbusDataUnit(QModbusDataUnit::InputRegisters, 85, 1);
if(auto *subreply = modbusDevice->sendReadRequest(*_unit, Boards[i].adr)) {
while(!subreply->isFinished()) {
if(isRun) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
QCoreApplication::processEvents();
}
if(subreply->error()!=QModbusDevice::NoError) {
onConnectClicked();
bar->close();
bar->deleteLater();
return false;
}
}
} else if(reply->error()!=QModbusDevice::NoError) {
return false;
}
modbusDevice->disconnectDevice();
}
}
}
return true;
}
else
return false;
}
void M3KTE::stopScanBoard()
{
for(int i = 0; i < 4; i++) {
Boards[i].boardScanners->stop();
}
return;
}