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.

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