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.

559 lines
20 KiB

2 years ago
2 years ago
1 year ago
2 years 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
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. #include "mainwindow.h"
  2. #include <QDateTime>
  3. #include <QMessageBox>
  4. #include <QtConcurrent>
  5. #include <QtSerialPort/QSerialPort>
  6. #include <QtSerialPort/QSerialPortInfo>
  7. #include "./ui_mainwindow.h"
  8. #include "electrocardiograph_tester.hpp"
  9. #include "logger.hpp"
  10. #include "qt_serial_datachannel.hpp"
  11. #include "zexception.hpp"
  12. using namespace std;
  13. using namespace iflytop;
  14. typedef enum {
  15. kone_lead_ecg,
  16. kthree_lead_ecg,
  17. } device_type_t;
  18. static MainWindow *m_mainWindow;
  19. static QTDataChannel G_QTDataChannel;
  20. static QTDataChannel G_WaveDataChannel;
  21. static device_type_t m_devicetype;
  22. #define TAG "MainWindow"
  23. static const char *fmt(const char *fmt, ...) {
  24. va_list args;
  25. va_start(args, fmt);
  26. static char buf[1024] = {0};
  27. vsnprintf(buf, sizeof(buf), fmt, args);
  28. va_end(args);
  29. return buf;
  30. }
  31. void MainWindow::log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) {}
  32. void MainWindow::doinui_slot(QFunction func) {
  33. if (func.get()) func.get()();
  34. }
  35. void MainWindow::instructionPreviewShow(const char *fmt, ...) {
  36. va_list args;
  37. va_start(args, fmt);
  38. char buf[1024] = {0};
  39. vsnprintf(buf, sizeof(buf), fmt, args);
  40. va_end(args);
  41. QString text(buf);
  42. QString info;
  43. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  44. info.append(" |");
  45. info.append(text);
  46. emit doinui_signal(QFunction([this, info]() { ui->instructionPreview->append(info); }));
  47. }
  48. void MainWindow::instructionPreviewClear() { ui->instructionPreview->document()->clear(); }
  49. void MainWindow::reportPreviewShow(const char *fmt, ...) {
  50. va_list args;
  51. va_start(args, fmt);
  52. char buf[1024] = {0};
  53. vsnprintf(buf, sizeof(buf), fmt, args);
  54. va_end(args);
  55. QString text(buf);
  56. QString info;
  57. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  58. info.append(text);
  59. emit doinui_signal(QFunction([this, info]() {
  60. if (ui->reportPreview->document()->lineCount() > 1000) {
  61. ui->reportPreview->document()->clear();
  62. }
  63. ui->reportPreview->append(info);
  64. }));
  65. }
  66. void MainWindow::blockDataUploadPreviewShow(const char *fmt, ...) {
  67. va_list args;
  68. va_start(args, fmt);
  69. char buf[1024] = {0};
  70. vsnprintf(buf, sizeof(buf), fmt, args);
  71. va_end(args);
  72. QString text(buf);
  73. QString info;
  74. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  75. info.append(text);
  76. emit doinui_signal(QFunction([this, info]() {
  77. if (ui->uploadDataPreview->document()->lineCount() > 1000) {
  78. ui->uploadDataPreview->document()->clear();
  79. }
  80. ui->uploadDataPreview->append(info);
  81. }));
  82. }
  83. void MainWindow::rawDataPreviewShow(const char *fmt, ...) {
  84. va_list args;
  85. va_start(args, fmt);
  86. char buf[1024] = {0};
  87. vsnprintf(buf, sizeof(buf), fmt, args);
  88. va_end(args);
  89. QString text(buf);
  90. QString info;
  91. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
  92. info.append(text);
  93. emit doinui_signal(QFunction([this, info]() {
  94. if (ui->rawDataPreview->document()->lineCount() > 1000) {
  95. ui->rawDataPreview->document()->clear();
  96. }
  97. ui->rawDataPreview->append(info);
  98. }));
  99. }
  100. // uploadDataPreview
  101. #pragma pack(push, 1)
  102. typedef struct {
  103. uint16_t header;
  104. int16_t wave1;
  105. int16_t wave2;
  106. int16_t wave3;
  107. int16_t wave4;
  108. int16_t wave5;
  109. uint8_t check;
  110. uint16_t tail;
  111. } Wave_t;
  112. #pragma pack(pop)
  113. void MainWindow::displayWave(int16_t wave1, int16_t wave2, int16_t wave3) {
  114. // 1. 生成波形数据
  115. Wave_t wave;
  116. wave.header = 0xAAAA;
  117. wave.wave1 = wave1;
  118. wave.wave2 = wave2;
  119. wave.wave3 = wave3;
  120. wave.wave4 = 0;
  121. wave.wave5 = 0;
  122. wave.tail = 0x5555;
  123. wave.check = 0;
  124. uint8_t check = 0;
  125. for (size_t i = 2; i < sizeof(wave) - 2; i++) {
  126. check += ((uint8_t *)&wave)[i];
  127. }
  128. wave.check = check;
  129. // 2. 发送波形数据
  130. G_WaveDataChannel.send((uint8_t *)&wave, sizeof(wave));
  131. }
  132. void MainWindow::displayInfo(bool suc, QString info) {}
  133. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  134. /*******************************************************************************
  135. * QT初始化 *
  136. *******************************************************************************/
  137. ui->setupUi(this);
  138. m_mainWindow = this;
  139. qRegisterMetaType<int32_t>("int32_t");
  140. qRegisterMetaType<uint32_t>("uint32_t");
  141. qRegisterMetaType<float>("float");
  142. qRegisterMetaType<function<void()>>("function<void()>");
  143. qRegisterMetaType<QFunction>("QFunction");
  144. connect(this, SIGNAL(doinui_signal(QFunction)), this, SLOT(doinui_slot(QFunction)));
  145. // qInstallMessageHandler(log_output);
  146. /*******************************************************************************
  147. * *
  148. *******************************************************************************/
  149. constructUI();
  150. /*******************************************************************************
  151. * *
  152. *******************************************************************************/
  153. G_QTDataChannel.init();
  154. G_WaveDataChannel.init();
  155. ElectrocardiographTester::ins()->initialize(&G_QTDataChannel);
  156. }
  157. MainWindow::~MainWindow() { delete ui; }
  158. /*******************************************************************************
  159. * UI相关构造 *
  160. *******************************************************************************/
  161. void MainWindow::constructUI() {
  162. /*******************************************************************************
  163. * UI *
  164. *******************************************************************************/
  165. {
  166. const auto infos = QSerialPortInfo::availablePorts();
  167. for (const QSerialPortInfo &info : infos) {
  168. ui->serialPortCB->addItem(info.portName());
  169. }
  170. }
  171. ui->serialBaudrateCB->addItem("9600");
  172. ui->serialBaudrateCB->addItem("14400");
  173. ui->serialBaudrateCB->addItem("19200");
  174. ui->serialBaudrateCB->addItem("38400");
  175. ui->serialBaudrateCB->addItem("57600");
  176. ui->serialBaudrateCB->addItem("115200");
  177. ui->serialBaudrateCB->addItem("460800");
  178. ui->serialBaudrateCB->addItem("500000");
  179. ui->serialBaudrateCB->setCurrentIndex(6);
  180. connect(ui->serialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  181. ui->serialPortCB->clear();
  182. const auto infos = QSerialPortInfo::availablePorts();
  183. for (const QSerialPortInfo &info : infos) {
  184. ui->serialPortCB->addItem(info.portName());
  185. }
  186. });
  187. connect(ui->serialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  188. // 打开串口
  189. if (ui->serialOpenKey->text() == "打开") {
  190. G_QTDataChannel.setPortName(ui->serialPortCB->currentText().toStdString());
  191. G_QTDataChannel.setBaudRate(ui->serialBaudrateCB->currentText().toInt());
  192. G_QTDataChannel.setDataBits(QSerialPort::Data8);
  193. G_QTDataChannel.setParity(QSerialPort::NoParity);
  194. G_QTDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  195. G_QTDataChannel.setStopBits(QSerialPort::OneStop);
  196. if (!G_QTDataChannel.open()) {
  197. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  198. return;
  199. }
  200. ui->serialOpenKey->setText("关闭");
  201. // 下拉菜单控件使能
  202. ui->serialBaudrateCB->setEnabled(false);
  203. ui->serialPortCB->setEnabled(false);
  204. ui->serialPortRefreshKey->setEnabled(false);
  205. } else {
  206. G_QTDataChannel.close();
  207. ui->serialOpenKey->setText("打开");
  208. ui->serialBaudrateCB->setEnabled(true);
  209. ui->serialPortCB->setEnabled(true);
  210. ui->serialPortRefreshKey->setEnabled(true);
  211. }
  212. });
  213. /*******************************************************************************
  214. * UI *
  215. *******************************************************************************/
  216. {
  217. const auto infos = QSerialPortInfo::availablePorts();
  218. for (const QSerialPortInfo &info : infos) {
  219. ui->waveSerialPortCB->addItem(info.portName());
  220. }
  221. }
  222. ui->waveSerialBaudrateCB->addItem("9600");
  223. ui->waveSerialBaudrateCB->addItem("14400");
  224. ui->waveSerialBaudrateCB->addItem("19200");
  225. ui->waveSerialBaudrateCB->addItem("38400");
  226. ui->waveSerialBaudrateCB->addItem("57600");
  227. ui->waveSerialBaudrateCB->addItem("115200");
  228. ui->waveSerialBaudrateCB->addItem("460800");
  229. ui->waveSerialBaudrateCB->addItem("500000");
  230. ui->waveSerialBaudrateCB->setCurrentIndex(6);
  231. connect(ui->waveSerialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  232. ui->waveSerialPortCB->clear();
  233. const auto infos = QSerialPortInfo::availablePorts();
  234. for (const QSerialPortInfo &info : infos) {
  235. ui->waveSerialPortCB->addItem(info.portName());
  236. }
  237. });
  238. connect(ui->waveSerialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  239. // 打开串口
  240. if (ui->waveSerialOpenKey->text() == "打开") {
  241. G_WaveDataChannel.setPortName(ui->waveSerialPortCB->currentText().toStdString());
  242. G_WaveDataChannel.setBaudRate(ui->waveSerialBaudrateCB->currentText().toInt());
  243. G_WaveDataChannel.setDataBits(QSerialPort::Data8);
  244. G_WaveDataChannel.setParity(QSerialPort::NoParity);
  245. G_WaveDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  246. G_WaveDataChannel.setStopBits(QSerialPort::OneStop);
  247. if (!G_WaveDataChannel.open()) {
  248. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  249. return;
  250. }
  251. ui->waveSerialOpenKey->setText("关闭");
  252. // 下拉菜单控件使能
  253. ui->waveSerialBaudrateCB->setEnabled(false);
  254. ui->waveSerialPortCB->setEnabled(false);
  255. ui->waveSerialPortRefreshKey->setEnabled(false);
  256. } else {
  257. G_WaveDataChannel.close();
  258. ui->waveSerialOpenKey->setText("打开");
  259. ui->waveSerialBaudrateCB->setEnabled(true);
  260. ui->waveSerialPortCB->setEnabled(true);
  261. ui->waveSerialPortRefreshKey->setEnabled(true);
  262. }
  263. });
  264. // 事件填充
  265. ElectrocardiographTester::ins()->regReportCB([this](bool checkok, ify_hrs_packet_t *report_packet, size_t len) {
  266. int reportType = report_packet->cmd;
  267. switch (reportType) {
  268. case ify_hrs_report_heartrate_data: {
  269. heartrate_report_packet_t *heartrate_report = (heartrate_report_packet_t *)report_packet;
  270. // reportPreviewShow("[preview data ] index %llu", heartrate_report->sample_data_index);
  271. uint16_t header = 0xA55A;
  272. uint16_t tail = 0xB55B;
  273. G_WaveDataChannel.send((uint8_t *)&header, sizeof(header));
  274. G_WaveDataChannel.send((uint8_t *)report_packet, len);
  275. G_WaveDataChannel.send((uint8_t *)&tail, sizeof(tail));
  276. // if (m_devicetype == kone_lead_ecg) {
  277. reportPreviewShow("[preview data ] checksum_ok:%d index %llu", checkok, heartrate_report->sample_data_index);
  278. // } else if (m_devicetype == kthree_lead_ecg) {
  279. // displayWave(heartrate_report->data[0], heartrate_report->data[1], heartrate_report->data[2]);
  280. // }
  281. break;
  282. }
  283. case ify_hrs_report_battery_level: {
  284. reportPreviewShow("[battery_level ]");
  285. break;
  286. }
  287. case ify_hrs_report_low_battey_level: {
  288. reportPreviewShow("[low_battey ]");
  289. break;
  290. }
  291. case ify_hrs_report_sample_finish_end: {
  292. reportPreviewShow("[sample_finish ]");
  293. break;
  294. }
  295. case ify_hrs_report_sensor_drop_detect: {
  296. sensor_drop_event_report_packet_t *sensor_drop_report = (sensor_drop_event_report_packet_t *)report_packet->data;
  297. reportPreviewShow("[sensor_drop ] %s %s", zhex2binary(sensor_drop_report->drop_state0).c_str(), zhex2binary(sensor_drop_report->drop_state1).c_str());
  298. break;
  299. }
  300. case ify_hrs_report_record_upload_end: {
  301. uint32_t checksum = *(uint32_t *)report_packet->data;
  302. reportPreviewShow("[upload end ] checksum: 0x%08x", checksum);
  303. break;
  304. }
  305. default:
  306. break;
  307. }
  308. });
  309. ElectrocardiographTester::ins()->regCh4CheckSumPacketReport([this](uint32_t rxcnt, uint32_t report_packet_checksum) { //
  310. blockDataUploadPreviewShow("RXCNT %d CHECKSUM 0x%08x", rxcnt, report_packet_checksum);
  311. });
  312. ElectrocardiographTester::ins()->regRawDataCB([this](raw_data_type_t type, uint8_t *hex, uint32_t hexlen) {
  313. if (type == kcmd_cmd) {
  314. rawDataPreviewShow("[CMD ] %s", zhex2str(hex, hexlen).c_str());
  315. } else if (type == kcmd_receipt) {
  316. rawDataPreviewShow("[RECEIPT] %s", zhex2str(hex, hexlen).c_str());
  317. } else if (type == kcmd_report) {
  318. rawDataPreviewShow("[REPORT ] %s", zhex2str(hex, hexlen).c_str());
  319. } else if (type == kcmd_ch4_data) {
  320. // rawDataPreviewShow("[CH4 ] %s", zhex2str(hex, hexlen).c_str());
  321. }
  322. });
  323. }
  324. void MainWindow::processException(zexception &e) { instructionPreviewShow("%s:%s", e.what(), hrs_ecode2str((ify_hrs_error_code_t)e.ecode())); }
  325. void MainWindow::on_readDeviceVersion_clicked() {
  326. instructionPreviewClear();
  327. try {
  328. device_version_info_receipt_t version;
  329. ElectrocardiographTester::ins()->readDeviceVersion(&version);
  330. instructionPreviewShow("-------------- version ----------------");
  331. instructionPreviewShow(" blestack_version: %d", version.blestack_version);
  332. instructionPreviewShow(" bootloader_version: %d", version.bootloader_version);
  333. instructionPreviewShow(" firmware_version: %d", version.firmware_version);
  334. instructionPreviewShow(" hardware_version: %d", version.hardware_version);
  335. } catch (zexception &exception) {
  336. processException(exception);
  337. }
  338. }
  339. void MainWindow::on_readDeviceState_clicked() {
  340. instructionPreviewClear();
  341. try {
  342. device_state_receipt_t state;
  343. ElectrocardiographTester::ins()->readDeviceState(&state);
  344. instructionPreviewShow("-------------- state ----------------");
  345. instructionPreviewShow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
  346. instructionPreviewShow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
  347. instructionPreviewShow(" sampling_state: %d", state.device_state0.sampling_state);
  348. instructionPreviewShow(" report_state: %d", state.device_state0.report_state);
  349. instructionPreviewShow(" low_battery: %d", state.device_state0.low_battery);
  350. instructionPreviewShow(" full_storge: %d", state.device_state0.full_storge);
  351. instructionPreviewShow(" holder: %d", state.device_state0.holder);
  352. instructionPreviewShow(" powerlevel: %d", state.powerlevel);
  353. instructionPreviewShow(" storage_item_num: %d", state.storage_item_num);
  354. } catch (zexception &exception) {
  355. processException(exception);
  356. }
  357. }
  358. void MainWindow::on_readTime_clicked() {
  359. instructionPreviewClear();
  360. try {
  361. read_time_receipt_t time;
  362. ElectrocardiographTester::ins()->readTime(&time);
  363. instructionPreviewShow("-------------- time ----------------");
  364. instructionPreviewShow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
  365. } catch (zexception &exception) {
  366. processException(exception);
  367. }
  368. }
  369. void MainWindow::on_syncTime_clicked() {
  370. instructionPreviewClear();
  371. try {
  372. // 获取系统时间
  373. QDateTime now = QDateTime::currentDateTime();
  374. ElectrocardiographTester::ins()->syncTime(now.date().year() - 2000, now.date().month(), now.date().day(), now.time().hour(), now.time().minute(), now.time().second());
  375. instructionPreviewShow("sync time success!");
  376. } catch (zexception &exception) {
  377. processException(exception);
  378. }
  379. }
  380. std::string zhex2time(const uint8_t *hex, size_t len) {
  381. std::string str;
  382. if (len < 6) return str;
  383. str.append(fmt("%d/%d/%d %2d:%2d:%2d", hex[0] + 2000, hex[1], hex[2], hex[3], hex[4], hex[5]));
  384. return str;
  385. }
  386. void MainWindow::on_readAllRecords_clicked() {
  387. // 读取当前有多少条记录
  388. instructionPreviewClear();
  389. try {
  390. device_state_receipt_t state;
  391. ElectrocardiographTester::ins()->readDeviceState(&state);
  392. instructionPreviewShow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
  393. for (int32_t i = 0; i < state.storage_item_num; i++) {
  394. read_record_info_receipt_t record;
  395. ElectrocardiographTester::ins()->readRecordsInfo(i, &record);
  396. instructionPreviewShow("%d %s %8d %8d %8d %8d %8d %8d 0x%08x", i, zhex2time(record.record_id, 6).c_str(), record.frameNum, record.dataSize, record.sensorNum, record.captureRate, record.capturePrecision, record.compressAlgorithm, record.checksum);
  397. }
  398. } catch (zexception &exception) {
  399. processException(exception);
  400. }
  401. }
  402. void MainWindow::on_startUploadRecord_clicked() {
  403. instructionPreviewClear();
  404. int reportIndex = ui->startUploadRecord_p0->toPlainText().toInt();
  405. try {
  406. read_record_info_receipt_t record;
  407. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  408. ElectrocardiographTester::ins()->startUploadRecord(record.record_id);
  409. instructionPreviewShow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
  410. } catch (zexception &exception) {
  411. processException(exception);
  412. }
  413. }
  414. void MainWindow::on_readSensorInfo_clicked() {
  415. instructionPreviewClear();
  416. try {
  417. sensor_info_receipt_t sensor;
  418. ElectrocardiographTester::ins()->readSensorInfo(&sensor);
  419. instructionPreviewShow("-------------- sensor ----------------");
  420. instructionPreviewShow(" sensor_num: %d", sensor.sensor_num);
  421. instructionPreviewShow(" sensor_precision: %d", sensor.sensor_precision);
  422. instructionPreviewShow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
  423. instructionPreviewShow(" sensor0_pos: %d", sensor.sensor0_pos);
  424. instructionPreviewShow(" sensor1_pos: %d", sensor.sensor1_pos);
  425. instructionPreviewShow(" sensor2_pos: %d", sensor.sensor2_pos);
  426. } catch (zexception &exception) {
  427. processException(exception);
  428. }
  429. }
  430. void MainWindow::on_readSN_clicked() {
  431. instructionPreviewClear();
  432. try {
  433. string sn;
  434. ElectrocardiographTester::ins()->readSn(sn);
  435. instructionPreviewShow("-------------- sn ----------------");
  436. instructionPreviewShow(" sn: %s", sn.c_str());
  437. } catch (zexception &exception) {
  438. processException(exception);
  439. }
  440. }
  441. void MainWindow::on_stopUploadRecord_clicked() {
  442. instructionPreviewClear();
  443. try {
  444. ElectrocardiographTester::ins()->stopUploadRecord();
  445. instructionPreviewShow("stop upload record success");
  446. } catch (zexception &exception) {
  447. processException(exception);
  448. }
  449. }
  450. void MainWindow::on_delRecord_clicked() {
  451. instructionPreviewClear();
  452. int reportIndex = ui->delRecord_p0->toPlainText().toInt();
  453. try {
  454. read_record_info_receipt_t record;
  455. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  456. ElectrocardiographTester::ins()->delRecord(record.record_id);
  457. instructionPreviewShow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
  458. } catch (zexception &exception) {
  459. processException(exception);
  460. }
  461. }
  462. void MainWindow::on_startCapture_clicked() {
  463. instructionPreviewClear();
  464. try {
  465. ElectrocardiographTester::ins()->startCapture();
  466. instructionPreviewShow("start capture success");
  467. } catch (zexception &exception) {
  468. processException(exception);
  469. }
  470. }
  471. void MainWindow::on_stopCapture_clicked() {
  472. instructionPreviewClear();
  473. try {
  474. ElectrocardiographTester::ins()->stopCapture();
  475. instructionPreviewShow("stop capture success");
  476. } catch (zexception &exception) {
  477. processException(exception);
  478. }
  479. }
  480. void MainWindow::on_startRealtimeReport_clicked() {
  481. instructionPreviewClear();
  482. try {
  483. ElectrocardiographTester::ins()->startRealtimeReport();
  484. instructionPreviewShow("start realtime report success");
  485. } catch (zexception &exception) {
  486. processException(exception);
  487. }
  488. }
  489. void MainWindow::on_stopRealtimeReport_clicked() {
  490. instructionPreviewClear();
  491. try {
  492. ElectrocardiographTester::ins()->stopRealtimeReport();
  493. instructionPreviewShow("stop realtime report success");
  494. } catch (zexception &exception) {
  495. processException(exception);
  496. }
  497. }
  498. void MainWindow::on_clearPreview_clicked() {
  499. ui->reportPreview->document()->clear();
  500. ui->uploadDataPreview->document()->clear();
  501. ui->rawDataPreview->document()->clear();
  502. ui->instructionPreview->document()->clear();
  503. }