You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

448 lines
19 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #include "mainwindow.h"
  2. #include <QDateTime>
  3. #include <QMessageBox>
  4. #include <QtConcurrent>
  5. #include <QtCore/QVariant>
  6. #include <QtSerialPort/QSerialPort>
  7. #include <QtSerialPort/QSerialPortInfo>
  8. #include <QtWidgets/QLineEdit>
  9. #include "./ui_mainwindow.h"
  10. #include "iflytop_canbus/iflytop_canbus_master.hpp"
  11. #include "logger.hpp"
  12. #include "qt_serial_datachannel.hpp"
  13. #include "reglist.hpp"
  14. #include "zexception.hpp"
  15. #include "zui/z_function_list_box.hpp"
  16. #include "zui/zq_vtab_page.hpp"
  17. //
  18. #include <thread>
  19. #include "zui/zui.hpp"
  20. using namespace std;
  21. using namespace iflytop;
  22. static MainWindow *m_mainWindow;
  23. static QTDataChannel G_QTDataChannel;
  24. static int PublicState_DeviceIDVal = 0;
  25. QT_REQUIRE_CONFIG(groupbox);
  26. #define TAG "MainWindow"
  27. static const char *fmt(const char *fmt, ...) {
  28. va_list args;
  29. va_start(args, fmt);
  30. static char buf[1024] = {0};
  31. vsnprintf(buf, sizeof(buf), fmt, args);
  32. va_end(args);
  33. return buf;
  34. }
  35. void MainWindow::log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) {}
  36. void MainWindow::doinui_slot(QFunction func) {
  37. if (func.get()) func.get()();
  38. }
  39. /***********************************************************************************************************************
  40. * PreviewShow *
  41. ***********************************************************************************************************************/
  42. void MainWindow::ishow(QString text) {
  43. QString info;
  44. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  45. info.append(" |");
  46. info.append(text);
  47. emit doinui_signal(QFunction([this, info]() { ui->instructionPreview->append(info); }));
  48. }
  49. void MainWindow::reportPreviewShow(QString text) {
  50. QString info;
  51. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  52. info.append(text);
  53. emit doinui_signal(QFunction([this, info]() {
  54. if (ui->reportPreview->document()->lineCount() > 1000) {
  55. ui->reportPreview->document()->clear();
  56. }
  57. ui->reportPreview->append(info);
  58. }));
  59. }
  60. void MainWindow::exceptionUploadPreviewShow(QString text) {
  61. QString info;
  62. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  63. info.append(text);
  64. emit doinui_signal(QFunction([this, info]() {
  65. if (ui->uploadDataPreview->document()->lineCount() > 1000) {
  66. ui->uploadDataPreview->document()->clear();
  67. }
  68. ui->uploadDataPreview->append(info);
  69. }));
  70. }
  71. void MainWindow::rawDataPreviewShow(QString text) {
  72. QString info;
  73. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
  74. info.append(text);
  75. emit doinui_signal(QFunction([this, info]() {
  76. if (ui->rawDataPreview->document()->lineCount() > 1000) {
  77. ui->rawDataPreview->document()->clear();
  78. }
  79. ui->rawDataPreview->append(info);
  80. }));
  81. }
  82. void MainWindow::instructionPreviewClear() {
  83. doinui_signal(QFunction([this]() { ui->instructionPreview->clear(); }));
  84. }
  85. #pragma pack(push, 1)
  86. typedef struct {
  87. uint16_t header;
  88. int16_t wave1;
  89. int16_t wave2;
  90. int16_t wave3;
  91. int16_t wave4;
  92. int16_t wave5;
  93. uint8_t check;
  94. uint16_t tail;
  95. } Wave_t;
  96. #pragma pack(pop)
  97. /***********************************************************************************************************************
  98. * UI相关构造 *
  99. ***********************************************************************************************************************/
  100. void MainWindow::constructBaseUI() {
  101. /**
  102. * @brief UI
  103. */
  104. {
  105. const auto infos = QSerialPortInfo::availablePorts();
  106. for (const QSerialPortInfo &info : infos) {
  107. ui->serialPortCB->addItem(info.portName());
  108. }
  109. }
  110. ui->serialBaudrateCB->addItem("9600");
  111. ui->serialBaudrateCB->addItem("14400");
  112. ui->serialBaudrateCB->addItem("19200");
  113. ui->serialBaudrateCB->addItem("38400");
  114. ui->serialBaudrateCB->addItem("57600");
  115. ui->serialBaudrateCB->addItem("115200");
  116. ui->serialBaudrateCB->addItem("460800");
  117. ui->serialBaudrateCB->addItem("500000");
  118. ui->serialBaudrateCB->addItem("2000000");
  119. ui->serialBaudrateCB->setCurrentIndex(8);
  120. connect(ui->serialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  121. ui->serialPortCB->clear();
  122. const auto infos = QSerialPortInfo::availablePorts();
  123. for (const QSerialPortInfo &info : infos) {
  124. ui->serialPortCB->addItem(info.portName());
  125. }
  126. });
  127. connect(ui->serialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  128. // 打开串口
  129. if (ui->serialOpenKey->text() == "打开") {
  130. G_QTDataChannel.setPortName(ui->serialPortCB->currentText().toStdString());
  131. G_QTDataChannel.setBaudRate(ui->serialBaudrateCB->currentText().toInt());
  132. G_QTDataChannel.setDataBits(QSerialPort::Data8);
  133. G_QTDataChannel.setParity(QSerialPort::NoParity);
  134. G_QTDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  135. G_QTDataChannel.setStopBits(QSerialPort::OneStop);
  136. /**
  137. * @brief
  138. */
  139. if (!G_QTDataChannel.open()) {
  140. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  141. return;
  142. }
  143. ui->serialOpenKey->setText("关闭");
  144. // 下拉菜单控件使能
  145. ui->serialBaudrateCB->setEnabled(false);
  146. ui->serialPortCB->setEnabled(false);
  147. ui->serialPortRefreshKey->setEnabled(false);
  148. IflytopCanbusMaster::ins()->updateChannelConfig();
  149. } else {
  150. G_QTDataChannel.close();
  151. ui->serialOpenKey->setText("打开");
  152. ui->serialBaudrateCB->setEnabled(true);
  153. ui->serialPortCB->setEnabled(true);
  154. ui->serialPortRefreshKey->setEnabled(true);
  155. }
  156. });
  157. }
  158. void MainWindow::displayInfo(bool suc, QString info) {}
  159. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  160. /**
  161. * @brief QT初始化
  162. */
  163. ui->setupUi(this);
  164. m_mainWindow = this;
  165. qRegisterMetaType<int32_t>("int32_t");
  166. qRegisterMetaType<uint32_t>("uint32_t");
  167. qRegisterMetaType<float>("float");
  168. qRegisterMetaType<function<void()>>("function<void()>");
  169. qRegisterMetaType<QFunction>("QFunction");
  170. connect(this, SIGNAL(doinui_signal(QFunction)), this, SLOT(doinui_slot(QFunction)));
  171. ZQUI::ins()->initialize();
  172. ZQUI::ins()->setexceptionUploadPreviewShow([this](QString text) { exceptionUploadPreviewShow(text); });
  173. ZQUI::ins()->setishow([this](QString text) { ishow(text); });
  174. ZQUI::ins()->setReportPreviewShow([this](QString text) { reportPreviewShow(text); });
  175. ZQUI::ins()->setRawDataPreviewShow([this](QString text) { rawDataPreviewShow(text); });
  176. ZQUI::ins()->setInstructionPreviewClear([this]() { instructionPreviewClear(); });
  177. /**
  178. * @brief
  179. */
  180. constructBaseUI();
  181. constructAppUI();
  182. /**
  183. * @brief
  184. */
  185. G_QTDataChannel.init();
  186. IflytopCanbusMaster::ins()->initialize(&G_QTDataChannel);
  187. IflytopCanbusMaster::ins()->regOnRawData([this](packet_type_t type, uint8_t from, uint8_t to, uint8_t *hex, uint32_t hexlen) {
  188. if (type == kcmd) {
  189. zcanbus_packet_t *frame = (zcanbus_packet_t *)hex;
  190. ZQUI::ins()->rawDataPreviewShow("[CMD ] [%d->%d],%s", from, to, zhex2str(hex, hexlen).c_str()); //
  191. } else if (type == kerror_receipt) {
  192. ZQUI::ins()->rawDataPreviewShow("[E-RECEIPT] [%d->%d],%s", from, to, zhex2str(hex, hexlen).c_str()); //
  193. } else if (type == kreceipt) {
  194. ZQUI::ins()->rawDataPreviewShow("[RECEIPT ] [%d->%d],%s", from, to, zhex2str(hex, hexlen).c_str()); //
  195. } else if (type == kreport) {
  196. ZQUI::ins()->rawDataPreviewShow("[REPORT ] [%d->%d],%s", from, to, zhex2str(hex, hexlen).c_str()); //
  197. }
  198. processReportPacket(type, from, to, hex, hexlen);
  199. });
  200. }
  201. MainWindow::~MainWindow() { delete ui; }
  202. void MainWindow::processException(const zexception &e) { //
  203. ZQUI::ins()->ishow("%s", e.what());
  204. }
  205. int32_t MainWindow::getDeviceId() { return PublicState_DeviceIDVal; }
  206. /***********************************************************************************************************************
  207. * *
  208. ***********************************************************************************************************************/
  209. void MainWindow::constructPumpControlUI(ZQFunctionListBox *box, int targetDeviceId) {
  210. // ZQFunctionListBox *box = new ZQFunctionListBox(tab, "泵机指令", 4);
  211. box->newFunc("pump_rotate", {"subid", "rpm"}, [this, targetDeviceId](int argn, const char **args) { //
  212. IflytopCanbusMaster::ins()->pump_rotate(targetDeviceId, atoi(args[0]), atoi(args[1]));
  213. });
  214. box->newFunc("pump_stop", {"subid"}, [this, targetDeviceId](int argn, const char **args) { //
  215. IflytopCanbusMaster::ins()->pump_stop(targetDeviceId, atoi(args[0]));
  216. });
  217. box->newFunc("pump_set_ihold_irun_idelay", {"subid", "ihold", "irun", "idelay"}, [this, targetDeviceId](int argn, const char **args) { //
  218. IflytopCanbusMaster::ins()->pump_set_ihold_irun_idelay(targetDeviceId, atoi(args[0]), atoi(args[1]), atoi(args[2]), atoi(args[3]));
  219. });
  220. box->newFunc("pump_set_acc", {"subid", "acc"}, [this, targetDeviceId](int argn, const char **args) { //
  221. IflytopCanbusMaster::ins()->pump_set_acc(targetDeviceId, atoi(args[0]), atoi(args[1]));
  222. });
  223. box->newFunc("pump_set_subic_reg", {"subid", "regadd", "val"}, [this, targetDeviceId](int argn, const char **args) { //
  224. IflytopCanbusMaster::ins()->pump_set_subic_reg(targetDeviceId, atoi(args[0]), atoi(args[1]), atoi(args[2]));
  225. });
  226. box->newFunc("pump_get_subic_reg", {"subid", "regadd"}, [this, targetDeviceId](int argn, const char **args) { //
  227. int val = IflytopCanbusMaster::ins()->pump_get_subic_reg(targetDeviceId, atoi(args[0]), atoi(args[1]));
  228. ZQUI::ins()->ishow("val:%x", val);
  229. });
  230. box->newFunc("pump_get_subic_reg", {"subid", "regadd"}, [this, targetDeviceId](int argn, const char **args) { //
  231. int val = IflytopCanbusMaster::ins()->pump_get_subic_reg(targetDeviceId, atoi(args[0]), atoi(args[1]));
  232. ZQUI::ins()->ishow("val:%x", val);
  233. });
  234. }
  235. /***********************************************************************************************************************
  236. * *
  237. ***********************************************************************************************************************/
  238. void MainWindow::constructCommonOperationTab() {
  239. ZQVTabPage *tab = new ZQVTabPage(ui->buttonTabWidget, "通用接口");
  240. // static
  241. {
  242. ZQFunctionListBox *box = new ZQFunctionListBox(tab, "通用方法", 4);
  243. box->newFunc("读板卡信息", {"id"}, [this](int argn, const char **args) { //
  244. ack_read_board_info_data_t ack = IflytopCanbusMaster::ins()->readboardinfo(atoi(args[0]));
  245. ZQUI::ins()->ishow("boardType :%s(%d)", BoardTypeToString(ack.boardType), ack.boardType);
  246. ZQUI::ins()->ishow("projectId :%s(%d)", ProjectIDToString(ack.projectId), ack.projectId);
  247. ZQUI::ins()->ishow("protcol_version :%d", ack.protcol_version);
  248. ZQUI::ins()->ishow("software_version :%d", ack.software_version);
  249. ZQUI::ins()->ishow("hardware_version :%d", ack.hardware_version);
  250. });
  251. box->newFunc("读内存信息", {"id"}, [this](int argn, const char **args) { //
  252. ack_sysinfo_t ack = IflytopCanbusMaster::ins()->readsysinfo(atoi(args[0]));
  253. ask_taskinfo_t task[20];
  254. for (int i = 0; i < ack.taskNum; i++) {
  255. task[i] = IflytopCanbusMaster::ins()->readtaskinfo(atoi(args[0]), i);
  256. }
  257. ZQUI::ins()->ishow("=========================== sys info ===========================");
  258. ZQUI::ins()->ishow("total_heap_size :%d", ack.total_heap_size);
  259. ZQUI::ins()->ishow("free_heap_size :%d", ack.free_heap_size);
  260. ZQUI::ins()->ishow("sysHasRun :%d", ack.sysHasRun);
  261. ZQUI::ins()->ishow("=");
  262. ZQUI::ins()->ishow("=========================== task info ===========================");
  263. ZQUI::ins()->ishow("taskoff name state stackRemainSize priority");
  264. for (int i = 0; i < ack.taskNum; i++) {
  265. ZQUI::ins()->ishow("%d %10s %c %d %d", i, task[i].taskName, task[i].state, task[i].stackRemindSize, task[i].priority);
  266. }
  267. ZQUI::ins()->ishow("=");
  268. });
  269. box->newFunc("PingAllBoard", {}, [this](int argn, const char **args) { //
  270. IflytopCanbusMaster::ins()->pingAllBoard();
  271. });
  272. box->newFunc("clear_reset_flag", {"id"}, [this](int argn, const char **args) { //
  273. IflytopCanbusMaster::ins()->clear_reset_flag(atoi(args[0]));
  274. });
  275. }
  276. }
  277. /***********************************************************************************************************************
  278. * *
  279. ***********************************************************************************************************************/
  280. void MainWindow::constructDrawBarDisinfectionBoxTab() { //
  281. ZQVTabPage *tab = new ZQVTabPage(ui->buttonTabWidget, "消毒拉杆箱");
  282. {
  283. ZQFunctionListBox *minpowerboard_box = new ZQFunctionListBox(tab, "液路板", 4);
  284. {
  285. /**
  286. * @brief
  287. */
  288. constructPumpControlUI(minpowerboard_box, kFixBoardId_LiquidCtrl);
  289. }
  290. {
  291. // 喷液MINI真空泵
  292. minpowerboard_box->newFunc("喷液MINI真空泵控制", {"onoff"}, [this](int argn, const char **args) { //
  293. IflytopCanbusMaster::ins()->sl_mini_ac_ctrl(kFixBoardId_LiquidCtrl, atoi(args[0]));
  294. });
  295. // 气密性测试MINI真空泵
  296. minpowerboard_box->newFunc("气密性测试MINI真空泵", {"onoff"}, [this](int argn, const char **args) { //
  297. IflytopCanbusMaster::ins()->atta_mini_air_compressor_ctrl(kFixBoardId_LiquidCtrl, atoi(args[0]));
  298. });
  299. // 压力传感器总线
  300. minpowerboard_box->newFunc("压力传感器总线-读数据", {"subid"}, [this](int argn, const char **args) { //
  301. int32_t val = IflytopCanbusMaster::ins()->pressure_sensor_bus_read_data( //
  302. kFixBoardId_LiquidCtrl, atoi(args[0]));
  303. ZQUI::ins()->ishow("val:%d", val);
  304. });
  305. minpowerboard_box->newFunc("压力传感器总线-设置上报周期", {"periodms"}, [this](int argn, const char **args) { //
  306. IflytopCanbusMaster::ins()->pressure_sensor_bus_set_report_period_ms( //
  307. kFixBoardId_LiquidCtrl, atoi(args[0]));
  308. });
  309. }
  310. }
  311. }
  312. void MainWindow::construct_largeSpaceDisinfectionTab() {
  313. //
  314. int targetId = kFixBoardId_LiquidCtrl;
  315. ZQVTabPage *tab = new ZQVTabPage(ui->buttonTabWidget, "大空间消毒机");
  316. {
  317. ZQFunctionListBox *minpowerboard_box = new ZQFunctionListBox(tab, "液路板", 4);
  318. constructPumpControlUI(minpowerboard_box, targetId); // 泵机控制接口
  319. minpowerboard_box->newFunc("压力传感器总线-读数据", {"subid"}, //
  320. [this, targetId](int argn, const char **args) {
  321. int32_t val = IflytopCanbusMaster::ins()->pressure_sensor_bus_read_data(targetId, atoi(args[0]));
  322. ZQUI::ins()->ishow("val:%d", val);
  323. });
  324. minpowerboard_box->newFunc("压力传感器总线-设置上报周期", {"periodms"}, //
  325. [this, targetId](int argn, const char **args) { IflytopCanbusMaster::ins()->pressure_sensor_bus_set_report_period_ms(targetId, atoi(args[0])); });
  326. minpowerboard_box->newFunc("报警灯控制", {"r", "g", "b", "w"}, //
  327. [this, targetId](int argn, const char **args) { IflytopCanbusMaster::ins()->triple_warning_light_ctl(targetId, atoi(args[0]), atoi(args[1]), atoi(args[2]), atoi(args[3])); });
  328. minpowerboard_box->newFunc("读取-蒸发桶水浸传感器-状态", {}, //
  329. [this, targetId](int argn, const char **args) {
  330. int state = IflytopCanbusMaster::ins()->evaporation_bin_water_sensor_read_state(targetId);
  331. ZQUI::ins()->ishow("state:%d", state);
  332. });
  333. minpowerboard_box->newFunc("读取-设备底部水浸传感器-状态", {}, //
  334. [this, targetId](int argn, const char **args) {
  335. int state = IflytopCanbusMaster::ins()->device_bottom_water_sensor_read_state(targetId);
  336. ZQUI::ins()->ishow("state:%d", state);
  337. });
  338. }
  339. }
  340. void MainWindow::constructAppUI() {
  341. //
  342. constructCommonOperationTab();
  343. constructDrawBarDisinfectionBoxTab();
  344. construct_largeSpaceDisinfectionTab();
  345. }
  346. void MainWindow::processReportPacket(packet_type_t type, uint8_t from, uint8_t to, uint8_t *hex, uint32_t hexlen) {
  347. if (type != kreport) {
  348. return;
  349. }
  350. zcanbus_packet_t *frame = (zcanbus_packet_t *)hex;
  351. if (frame->function_id == kreport_heatpacket_pong) {
  352. report_heatpacket_data_t *ack = (report_heatpacket_data_t *)frame->params;
  353. ZQUI::ins()->rshow("[Heat ][FROM:%03d] HeatIndex:%x ToardType:%s flag:%x", from, ack->heartIndex, BoardTypeToString(ack->boardType), ack->flag);
  354. }
  355. //
  356. else if (frame->function_id == kreport_exception_error) {
  357. report_exeception_data_t *ack = (report_exeception_data_t *)frame->params;
  358. ZQUI::ins()->eshow("[Exception][FROM:%03d] subid:%x ecode:%s", from, ack->subid, ErrorCodeToString(ack->ecode));
  359. }
  360. //
  361. else if (frame->function_id == kreport_pressure_data) {
  362. report_pressure_data_t *ack = (report_pressure_data_t *)frame->params;
  363. QString info;
  364. info.append(fmt("[Pressure][FROM:%03d](%d)", from, ack->sensorDataNum));
  365. for (int i = 0; i < ack->sensorDataNum; i++) {
  366. info.append(fmt(" %d:%d,", ack->data[i].subid, ack->data[i].pressureVal));
  367. }
  368. ZQUI::ins()->rshow(info.toStdString().c_str());
  369. }
  370. //
  371. else if (frame->function_id == kreport_h2o2_sensor_data) {
  372. report_h2o2_data_t *ack = (report_h2o2_data_t *)frame->params;
  373. QString info;
  374. info.append(fmt("[H2O2 ][FROM:%03d] suid:%d,err:%d h2o2:%d (x10ppm),humid:%d (x10),temp:%d (x10),saturation:%d (x10)", //
  375. from, ack->subid, ack->sensor_error, ack->h2o2, ack->humid, ack->temp, ack->saturation));
  376. ZQUI::ins()->rshow(info.toStdString().c_str());
  377. }
  378. //
  379. else if (frame->function_id == kreport_evaporation_bin_water_sensor) {
  380. report_water_sensor_state_t *ack = (report_water_sensor_state_t *)frame->params;
  381. ZQUI::ins()->rshow("[蒸发仓内水浸][FROM:%03d] (%d)", from, ack->state);
  382. }
  383. //
  384. else if (frame->function_id == kreport_device_bottom_water_sensor) {
  385. report_water_sensor_state_t *ack = (report_water_sensor_state_t *)frame->params;
  386. ZQUI::ins()->rshow("[设备底部水浸][FROM:%03d] (%d)", from, ack->state);
  387. }
  388. }
  389. void MainWindow::on_PublicState_ConfirmKey_clicked() { PublicState_DeviceIDVal = ui->PublicState_DeviceID->toPlainText().toInt(); }
  390. void MainWindow::on_clearPreview_clicked() {
  391. // ZQUI()->
  392. }