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.

456 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 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() > 1000) {
  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() > 1000) {
  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() > 1000) {
  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("[upload end ] checksum: 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) { //
  218. blockDataUploadPreviewShow("RXCNT %d CHECKSUM 0x%08x", rxcnt, report_packet_checksum);
  219. });
  220. ElectrocardiographTester::ins()->regRawDataCB([this](raw_data_type_t type, uint8_t *hex, uint32_t hexlen) {
  221. if (type == kcmd_cmd) {
  222. rawDataPreviewShow("[CMD ] %s", zhex2str(hex, hexlen).c_str());
  223. } else if (type == kcmd_receipt) {
  224. rawDataPreviewShow("[RECEIPT] %s", zhex2str(hex, hexlen).c_str());
  225. } else if (type == kcmd_report) {
  226. rawDataPreviewShow("[REPORT ] %s", zhex2str(hex, hexlen).c_str());
  227. } else if (type == kcmd_ch4_data) {
  228. // rawDataPreviewShow("[CH4 ] %s", zhex2str(hex, hexlen).c_str());
  229. }
  230. });
  231. }
  232. void MainWindow::processException(zexception &e) { instructionPreviewShow("%s:%s", e.what(), hrs_ecode2str((ify_hrs_error_code_t)e.ecode())); }
  233. void MainWindow::on_readDeviceVersion_clicked() {
  234. instructionPreviewClear();
  235. try {
  236. device_version_info_receipt_t version;
  237. ElectrocardiographTester::ins()->readDeviceVersion(&version);
  238. instructionPreviewShow("-------------- version ----------------");
  239. instructionPreviewShow(" blestack_version: %d", version.blestack_version);
  240. instructionPreviewShow(" bootloader_version: %d", version.bootloader_version);
  241. instructionPreviewShow(" firmware_version: %d", version.firmware_version);
  242. instructionPreviewShow(" hardware_version: %d", version.hardware_version);
  243. } catch (zexception &exception) {
  244. processException(exception);
  245. }
  246. }
  247. void MainWindow::on_readDeviceState_clicked() {
  248. instructionPreviewClear();
  249. try {
  250. device_state_receipt_t state;
  251. ElectrocardiographTester::ins()->readDeviceState(&state);
  252. instructionPreviewShow("-------------- state ----------------");
  253. instructionPreviewShow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
  254. instructionPreviewShow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
  255. instructionPreviewShow(" sampling_state: %d", state.device_state0.sampling_state);
  256. instructionPreviewShow(" report_state: %d", state.device_state0.report_state);
  257. instructionPreviewShow(" low_battery: %d", state.device_state0.low_battery);
  258. instructionPreviewShow(" full_storge: %d", state.device_state0.full_storge);
  259. instructionPreviewShow(" holder: %d", state.device_state0.holder);
  260. instructionPreviewShow(" powerlevel: %d", state.powerlevel);
  261. instructionPreviewShow(" storage_item_num: %d", state.storage_item_num);
  262. } catch (zexception &exception) {
  263. processException(exception);
  264. }
  265. }
  266. void MainWindow::on_readTime_clicked() {
  267. instructionPreviewClear();
  268. try {
  269. read_time_receipt_t time;
  270. ElectrocardiographTester::ins()->readTime(&time);
  271. instructionPreviewShow("-------------- time ----------------");
  272. instructionPreviewShow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
  273. } catch (zexception &exception) {
  274. processException(exception);
  275. }
  276. }
  277. void MainWindow::on_syncTime_clicked() {
  278. instructionPreviewClear();
  279. try {
  280. // 获取系统时间
  281. QDateTime now = QDateTime::currentDateTime();
  282. ElectrocardiographTester::ins()->syncTime(now.date().year() - 2000, now.date().month(), now.date().day(), now.time().hour(), now.time().minute(), now.time().second());
  283. instructionPreviewShow("sync time success!");
  284. } catch (zexception &exception) {
  285. processException(exception);
  286. }
  287. }
  288. std::string zhex2time(const uint8_t *hex, size_t len) {
  289. std::string str;
  290. if (len < 6) return str;
  291. str.append(fmt("%d/%d/%d %2d:%2d:%2d", hex[0] + 2000, hex[1], hex[2], hex[3], hex[4], hex[5]));
  292. return str;
  293. }
  294. void MainWindow::on_readAllRecords_clicked() {
  295. // 读取当前有多少条记录
  296. instructionPreviewClear();
  297. try {
  298. device_state_receipt_t state;
  299. ElectrocardiographTester::ins()->readDeviceState(&state);
  300. instructionPreviewShow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
  301. for (int32_t i = 0; i < state.storage_item_num; i++) {
  302. read_record_info_receipt_t record;
  303. ElectrocardiographTester::ins()->readRecordsInfo(i, &record);
  304. 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);
  305. }
  306. } catch (zexception &exception) {
  307. processException(exception);
  308. }
  309. }
  310. void MainWindow::on_startUploadRecord_clicked() {
  311. instructionPreviewClear();
  312. int reportIndex = ui->startUploadRecord_p0->toPlainText().toInt();
  313. try {
  314. read_record_info_receipt_t record;
  315. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  316. ElectrocardiographTester::ins()->startUploadRecord(record.record_id);
  317. instructionPreviewShow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
  318. } catch (zexception &exception) {
  319. processException(exception);
  320. }
  321. }
  322. void MainWindow::on_readSensorInfo_clicked() {
  323. instructionPreviewClear();
  324. try {
  325. sensor_info_receipt_t sensor;
  326. ElectrocardiographTester::ins()->readSensorInfo(&sensor);
  327. instructionPreviewShow("-------------- sensor ----------------");
  328. instructionPreviewShow(" sensor_num: %d", sensor.sensor_num);
  329. instructionPreviewShow(" sensor_precision: %d", sensor.sensor_precision);
  330. instructionPreviewShow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
  331. instructionPreviewShow(" sensor0_pos: %d", sensor.sensor0_pos);
  332. instructionPreviewShow(" sensor1_pos: %d", sensor.sensor1_pos);
  333. instructionPreviewShow(" sensor2_pos: %d", sensor.sensor2_pos);
  334. } catch (zexception &exception) {
  335. processException(exception);
  336. }
  337. }
  338. void MainWindow::on_readSN_clicked() {
  339. instructionPreviewClear();
  340. try {
  341. string sn;
  342. ElectrocardiographTester::ins()->readSn(sn);
  343. instructionPreviewShow("-------------- sn ----------------");
  344. instructionPreviewShow(" sn: %s", sn.c_str());
  345. } catch (zexception &exception) {
  346. processException(exception);
  347. }
  348. }
  349. void MainWindow::on_stopUploadRecord_clicked() {
  350. instructionPreviewClear();
  351. try {
  352. ElectrocardiographTester::ins()->stopUploadRecord();
  353. instructionPreviewShow("stop upload record success");
  354. } catch (zexception &exception) {
  355. processException(exception);
  356. }
  357. }
  358. void MainWindow::on_delRecord_clicked() {
  359. instructionPreviewClear();
  360. int reportIndex = ui->delRecord_p0->toPlainText().toInt();
  361. try {
  362. read_record_info_receipt_t record;
  363. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  364. ElectrocardiographTester::ins()->delRecord(record.record_id);
  365. instructionPreviewShow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
  366. } catch (zexception &exception) {
  367. processException(exception);
  368. }
  369. }
  370. void MainWindow::on_startCapture_clicked() {
  371. instructionPreviewClear();
  372. try {
  373. ElectrocardiographTester::ins()->startCapture();
  374. instructionPreviewShow("start capture success");
  375. } catch (zexception &exception) {
  376. processException(exception);
  377. }
  378. }
  379. void MainWindow::on_stopCapture_clicked() {
  380. instructionPreviewClear();
  381. try {
  382. ElectrocardiographTester::ins()->stopCapture();
  383. instructionPreviewShow("stop capture success");
  384. } catch (zexception &exception) {
  385. processException(exception);
  386. }
  387. }
  388. void MainWindow::on_startRealtimeReport_clicked() {
  389. instructionPreviewClear();
  390. try {
  391. ElectrocardiographTester::ins()->startRealtimeReport();
  392. instructionPreviewShow("start realtime report success");
  393. } catch (zexception &exception) {
  394. processException(exception);
  395. }
  396. }
  397. void MainWindow::on_stopRealtimeReport_clicked() {
  398. instructionPreviewClear();
  399. try {
  400. ElectrocardiographTester::ins()->stopRealtimeReport();
  401. instructionPreviewShow("stop realtime report success");
  402. } catch (zexception &exception) {
  403. processException(exception);
  404. }
  405. }
  406. void MainWindow::on_clearPreview_clicked() {
  407. ui->reportPreview->document()->clear();
  408. ui->uploadDataPreview->document()->clear();
  409. ui->rawDataPreview->document()->clear();
  410. ui->instructionPreview->document()->clear();
  411. }