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.

446 lines
14 KiB

2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years 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 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 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 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 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 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 "zexception.hpp"
  14. using namespace std;
  15. using namespace iflytop;
  16. using namespace zcr;
  17. typedef enum {
  18. kone_lead_ecg,
  19. kthree_lead_ecg,
  20. } device_type_t;
  21. static MainWindow *m_mainWindow;
  22. static QTDataChannel G_QTDataChannel;
  23. static QTDataChannel G_WaveDataChannel;
  24. QT_REQUIRE_CONFIG(groupbox);
  25. #define TAG "MainWindow"
  26. static const char *fmt(const char *fmt, ...) {
  27. va_list args;
  28. va_start(args, fmt);
  29. static char buf[1024] = {0};
  30. vsnprintf(buf, sizeof(buf), fmt, args);
  31. va_end(args);
  32. return buf;
  33. }
  34. void MainWindow::log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) {}
  35. void MainWindow::doinui_slot(QFunction func) {
  36. if (func.get()) func.get()();
  37. }
  38. /***********************************************************************************************************************
  39. * PreviewShow *
  40. ***********************************************************************************************************************/
  41. void MainWindow::instructionPreviewShow(const char *fmt, ...) {
  42. va_list args;
  43. va_start(args, fmt);
  44. char buf[1024] = {0};
  45. vsnprintf(buf, sizeof(buf), fmt, args);
  46. va_end(args);
  47. QString text(buf);
  48. QString info;
  49. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  50. info.append(" |");
  51. info.append(text);
  52. emit doinui_signal(QFunction([this, info]() { ui->instructionPreview->append(info); }));
  53. }
  54. void MainWindow::instructionPreviewClear() { ui->instructionPreview->document()->clear(); }
  55. void MainWindow::reportPreviewShow(const char *fmt, ...) {
  56. va_list args;
  57. va_start(args, fmt);
  58. char buf[1024] = {0};
  59. vsnprintf(buf, sizeof(buf), fmt, args);
  60. va_end(args);
  61. QString text(buf);
  62. QString info;
  63. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  64. info.append(text);
  65. emit doinui_signal(QFunction([this, info]() {
  66. if (ui->reportPreview->document()->lineCount() > 1000) {
  67. ui->reportPreview->document()->clear();
  68. }
  69. ui->reportPreview->append(info);
  70. }));
  71. }
  72. void MainWindow::blockDataUploadPreviewShow(const char *fmt, ...) {
  73. va_list args;
  74. va_start(args, fmt);
  75. char buf[1024] = {0};
  76. vsnprintf(buf, sizeof(buf), fmt, args);
  77. va_end(args);
  78. QString text(buf);
  79. QString info;
  80. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  81. info.append(text);
  82. emit doinui_signal(QFunction([this, info]() {
  83. if (ui->uploadDataPreview->document()->lineCount() > 1000) {
  84. ui->uploadDataPreview->document()->clear();
  85. }
  86. ui->uploadDataPreview->append(info);
  87. }));
  88. }
  89. void MainWindow::rawDataPreviewShow(const char *fmt, ...) {
  90. va_list args;
  91. va_start(args, fmt);
  92. char buf[1024] = {0};
  93. vsnprintf(buf, sizeof(buf), fmt, args);
  94. va_end(args);
  95. QString text(buf);
  96. QString info;
  97. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
  98. info.append(text);
  99. emit doinui_signal(QFunction([this, info]() {
  100. if (ui->rawDataPreview->document()->lineCount() > 1000) {
  101. ui->rawDataPreview->document()->clear();
  102. }
  103. ui->rawDataPreview->append(info);
  104. }));
  105. }
  106. // uploadDataPreview
  107. #pragma pack(push, 1)
  108. typedef struct {
  109. uint16_t header;
  110. int16_t wave1;
  111. int16_t wave2;
  112. int16_t wave3;
  113. int16_t wave4;
  114. int16_t wave5;
  115. uint8_t check;
  116. uint16_t tail;
  117. } Wave_t;
  118. #pragma pack(pop)
  119. void MainWindow::displayWave(int16_t wave1, int16_t wave2, int16_t wave3) {
  120. // 1. 生成波形数据
  121. Wave_t wave;
  122. wave.header = 0xAAAA;
  123. wave.wave1 = wave1;
  124. wave.wave2 = wave2;
  125. wave.wave3 = wave3;
  126. wave.wave4 = 0;
  127. wave.wave5 = 0;
  128. wave.tail = 0x5555;
  129. wave.check = 0;
  130. uint8_t check = 0;
  131. for (size_t i = 2; i < sizeof(wave) - 2; i++) {
  132. check += ((uint8_t *)&wave)[i];
  133. }
  134. wave.check = check;
  135. // 2. 发送波形数据
  136. G_WaveDataChannel.send((uint8_t *)&wave, sizeof(wave));
  137. }
  138. /***********************************************************************************************************************
  139. * UI相关构造 *
  140. ***********************************************************************************************************************/
  141. void MainWindow::constructBaseUI() {
  142. /**
  143. * @brief UI
  144. */
  145. {
  146. const auto infos = QSerialPortInfo::availablePorts();
  147. for (const QSerialPortInfo &info : infos) {
  148. ui->serialPortCB->addItem(info.portName());
  149. }
  150. }
  151. ui->serialBaudrateCB->addItem("9600");
  152. ui->serialBaudrateCB->addItem("14400");
  153. ui->serialBaudrateCB->addItem("19200");
  154. ui->serialBaudrateCB->addItem("38400");
  155. ui->serialBaudrateCB->addItem("57600");
  156. ui->serialBaudrateCB->addItem("115200");
  157. ui->serialBaudrateCB->addItem("460800");
  158. ui->serialBaudrateCB->addItem("500000");
  159. ui->serialBaudrateCB->addItem("2000000");
  160. ui->serialBaudrateCB->setCurrentIndex(6);
  161. connect(ui->serialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  162. ui->serialPortCB->clear();
  163. const auto infos = QSerialPortInfo::availablePorts();
  164. for (const QSerialPortInfo &info : infos) {
  165. ui->serialPortCB->addItem(info.portName());
  166. }
  167. });
  168. connect(ui->serialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  169. // 打开串口
  170. if (ui->serialOpenKey->text() == "打开") {
  171. G_QTDataChannel.setPortName(ui->serialPortCB->currentText().toStdString());
  172. G_QTDataChannel.setBaudRate(ui->serialBaudrateCB->currentText().toInt());
  173. G_QTDataChannel.setDataBits(QSerialPort::Data8);
  174. G_QTDataChannel.setParity(QSerialPort::NoParity);
  175. G_QTDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  176. G_QTDataChannel.setStopBits(QSerialPort::OneStop);
  177. /**
  178. * @brief
  179. */
  180. if (!G_QTDataChannel.open()) {
  181. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  182. return;
  183. }
  184. ui->serialOpenKey->setText("关闭");
  185. // 下拉菜单控件使能
  186. ui->serialBaudrateCB->setEnabled(false);
  187. ui->serialPortCB->setEnabled(false);
  188. ui->serialPortRefreshKey->setEnabled(false);
  189. IflytopCanbusMaster::ins()->updateChannelConfig();
  190. } else {
  191. G_QTDataChannel.close();
  192. ui->serialOpenKey->setText("打开");
  193. ui->serialBaudrateCB->setEnabled(true);
  194. ui->serialPortCB->setEnabled(true);
  195. ui->serialPortRefreshKey->setEnabled(true);
  196. }
  197. });
  198. /**
  199. * @brief UI
  200. */
  201. {
  202. const auto infos = QSerialPortInfo::availablePorts();
  203. for (const QSerialPortInfo &info : infos) {
  204. ui->waveSerialPortCB->addItem(info.portName());
  205. }
  206. }
  207. ui->waveSerialBaudrateCB->addItem("9600");
  208. ui->waveSerialBaudrateCB->addItem("14400");
  209. ui->waveSerialBaudrateCB->addItem("19200");
  210. ui->waveSerialBaudrateCB->addItem("38400");
  211. ui->waveSerialBaudrateCB->addItem("57600");
  212. ui->waveSerialBaudrateCB->addItem("115200");
  213. ui->waveSerialBaudrateCB->addItem("460800");
  214. ui->waveSerialBaudrateCB->addItem("500000");
  215. ui->waveSerialBaudrateCB->addItem("2000000");
  216. // ui->waveSerialBaudrateCB->addItems
  217. ui->waveSerialBaudrateCB->setCurrentIndex(6);
  218. connect(ui->waveSerialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  219. ui->waveSerialPortCB->clear();
  220. const auto infos = QSerialPortInfo::availablePorts();
  221. for (const QSerialPortInfo &info : infos) {
  222. ui->waveSerialPortCB->addItem(info.portName());
  223. }
  224. });
  225. connect(ui->waveSerialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  226. // 打开串口
  227. if (ui->waveSerialOpenKey->text() == "打开") {
  228. G_WaveDataChannel.setPortName(ui->waveSerialPortCB->currentText().toStdString());
  229. G_WaveDataChannel.setBaudRate(ui->waveSerialBaudrateCB->currentText().toInt());
  230. G_WaveDataChannel.setDataBits(QSerialPort::Data8);
  231. G_WaveDataChannel.setParity(QSerialPort::NoParity);
  232. G_WaveDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  233. G_WaveDataChannel.setStopBits(QSerialPort::OneStop);
  234. if (!G_WaveDataChannel.open()) {
  235. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  236. return;
  237. }
  238. ui->waveSerialOpenKey->setText("关闭");
  239. // 下拉菜单控件使能
  240. ui->waveSerialBaudrateCB->setEnabled(false);
  241. ui->waveSerialPortCB->setEnabled(false);
  242. ui->waveSerialPortRefreshKey->setEnabled(false);
  243. } else {
  244. G_WaveDataChannel.close();
  245. ui->waveSerialOpenKey->setText("打开");
  246. ui->waveSerialBaudrateCB->setEnabled(true);
  247. ui->waveSerialPortCB->setEnabled(true);
  248. ui->waveSerialPortRefreshKey->setEnabled(true);
  249. }
  250. });
  251. }
  252. void MainWindow::displayInfo(bool suc, QString info) {}
  253. /***********************************************************************************************************************
  254. * *
  255. ***********************************************************************************************************************/
  256. /**
  257. * @brief
  258. *
  259. * +TAB---------------------------------+
  260. * |---BOX---------------------------|
  261. * | |Button|Param|Param| |
  262. * | |Button|Param|Param| |
  263. * | |Button|Param|Param| |
  264. * |---------------------------------|
  265. * |---BOX---------------------------|
  266. * | |Button|Param|Param| |
  267. * | |Button|Param|Param| |
  268. * | |Button|Param|Param| |
  269. * |---------------------------------|
  270. *
  271. *
  272. */
  273. QWidget *MainWindow::allocNewTab(QString zh_name) {
  274. QWidget *newtab = new QWidget();
  275. QVBoxLayout *verticalLayout = new QVBoxLayout(newtab); // 设置布局
  276. newtab->setLayout(verticalLayout);
  277. // 添加Tab
  278. ui->buttonTabWidget->insertTab(0,newtab, QString());
  279. ui->buttonTabWidget->setTabText(ui->buttonTabWidget->indexOf(newtab), zh_name);
  280. return newtab;
  281. }
  282. void MainWindow::endAllocNewTab(QWidget *tab) {
  283. QVBoxLayout *layout = qobject_cast<QVBoxLayout *>(tab->layout());
  284. layout->addItem(new QSpacerItem(20, 445, QSizePolicy::Minimum, QSizePolicy::Expanding));
  285. }
  286. QGroupBox *MainWindow::allocNewBox(QWidget *tab, QString zh_name, int column) {
  287. QVBoxLayout *tablayout = qobject_cast<QVBoxLayout *>(tab->layout());
  288. QGroupBox *groupBox = new QGroupBox(tab); // 创建BOX
  289. QGridLayout *gridLayout = new QGridLayout(groupBox); // 创建布局
  290. groupBox->setLayout(gridLayout); // 设置布局
  291. gridLayout->setColumnMinimumWidth(column, column);
  292. tablayout->addWidget(groupBox);
  293. return groupBox;
  294. }
  295. void MainWindow::endAllocNewBox(QGroupBox *box) { //
  296. QGridLayout *layout = qobject_cast<QGridLayout *>(box->layout());
  297. QSpacerItem *verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
  298. layout->addItem(verticalSpacer, layout->rowCount(), 0, 1, 1);
  299. }
  300. void MainWindow::addNewButtonStyle1(QWidget *box, QString zh_name, QStringList params, std::function<void(int argn, const char **args)> onButtonClick) { //
  301. QGridLayout *layout = qobject_cast<QGridLayout *>(box->layout());
  302. int rowcnt = layout->rowCount();
  303. QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
  304. sizePolicy.setHorizontalStretch(1);
  305. sizePolicy.setVerticalStretch(0);
  306. QPushButton *button = new QPushButton(box);
  307. button->setText(zh_name);
  308. button->setMinimumHeight(30);
  309. button->setSizePolicy(sizePolicy);
  310. layout->addWidget(button, rowcnt, 0, 1, 1);
  311. QList<QLineEdit *> lineEdits;
  312. for (int i = 0; i < params.size(); i++) {
  313. QLineEdit *lineEdit = new QLineEdit(box);
  314. lineEdit->setMinimumHeight(30);
  315. // lineEdit->sizePolicy().setHorizontalStretch(1);
  316. lineEdit->setSizePolicy(sizePolicy);
  317. lineEdit->setPlaceholderText(params[i]);
  318. lineEdits.push_back(lineEdit);
  319. layout->addWidget(lineEdit, rowcnt, i + 1, 1, 1);
  320. }
  321. connect(button, &QPushButton::clicked, this, [onButtonClick, lineEdits, this]() {
  322. vector<string> params;
  323. for (int i = 0; i < lineEdits.size(); i++) {
  324. params.push_back(lineEdits[i]->text().toStdString());
  325. }
  326. char *args[params.size()];
  327. for (int i = 0; i < params.size(); i++) {
  328. args[i] = (char *)params[i].c_str();
  329. }
  330. try {
  331. onButtonClick(params.size(), (const char **)args);
  332. } catch (const std::zexception &e) {
  333. processException(e);
  334. }
  335. });
  336. }
  337. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  338. /**
  339. * @brief QT初始化
  340. */
  341. ui->setupUi(this);
  342. m_mainWindow = this;
  343. qRegisterMetaType<int32_t>("int32_t");
  344. qRegisterMetaType<uint32_t>("uint32_t");
  345. qRegisterMetaType<float>("float");
  346. qRegisterMetaType<function<void()>>("function<void()>");
  347. qRegisterMetaType<QFunction>("QFunction");
  348. connect(this, SIGNAL(doinui_signal(QFunction)), this, SLOT(doinui_slot(QFunction)));
  349. /**
  350. * @brief
  351. */
  352. constructBaseUI();
  353. constructAppUI();
  354. /**
  355. * @brief
  356. */
  357. G_QTDataChannel.init();
  358. G_WaveDataChannel.init();
  359. IflytopCanbusMaster::ins()->initialize(&G_QTDataChannel);
  360. IflytopCanbusMaster::ins()->regOnRawData([this](raw_data_type_t type, uint8_t *hex, uint32_t hexlen) {
  361. if (type == kcmd_cmd) {
  362. rawDataPreviewShow("[CMD ] %s", zhex2str(hex, hexlen).c_str());
  363. } else if (type == kcmd_receipt) {
  364. rawDataPreviewShow("[RECEIPT] %s", zhex2str(hex, hexlen).c_str());
  365. } else if (type == kcmd_report) {
  366. rawDataPreviewShow("[REPORT ] %s", zhex2str(hex, hexlen).c_str());
  367. }
  368. });
  369. }
  370. MainWindow::~MainWindow() { delete ui; }
  371. void MainWindow::processException(const zexception &e) { //
  372. instructionPreviewShow("%s", e.what());
  373. }
  374. void MainWindow::constructAppUI() {
  375. {
  376. QWidget *tab = allocNewTab("模块操作");
  377. {
  378. QGroupBox *box = allocNewBox(tab, "模块基础操作", 4);
  379. addNewButtonStyle1(box, "扫描模块", {"deviceId"}, [](int argn, const char **args) { //
  380. IflytopCanbusMaster::ins()->callcmd(atoi(args[0]), kmodule_ping);
  381. });
  382. endAllocNewBox(box);
  383. }
  384. endAllocNewTab(tab);
  385. }
  386. }