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.

360 lines
12 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 year ago
1 year ago
1 year ago
  1. #include "electrocardiograph_tester.hpp"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "logger.hpp"
  5. #include "zexception.hpp"
  6. using namespace iflytop;
  7. #define TAG "ElectrocardiographTester"
  8. /*******************************************************************************
  9. * UTILS_BEGIN *
  10. *******************************************************************************/
  11. static bool isHeader(uint8_t *data, uint8_t *headerType) {
  12. if (data[0] == 0x5A && data[1] == 0xA5) {
  13. *headerType = 1;
  14. return true;
  15. }
  16. if (data[0] == 0x4A && data[1] == 0xA4) {
  17. *headerType = 2;
  18. return true;
  19. }
  20. return false;
  21. }
  22. static bool isTail(uint8_t headerType, uint8_t *data) {
  23. if (headerType == 1 && data[0] == 0x5B && data[1] == 0xB5) {
  24. return true;
  25. }
  26. if (headerType == 2 && data[0] == 0x4B && data[1] == 0xB4) {
  27. return true;
  28. }
  29. return false;
  30. }
  31. /*******************************************************************************
  32. * UTILS_END *
  33. *******************************************************************************/
  34. ElectrocardiographTester *ElectrocardiographTester::ins() {
  35. static ElectrocardiographTester *ins = nullptr;
  36. if (ins == nullptr) {
  37. ins = new ElectrocardiographTester();
  38. }
  39. return ins;
  40. }
  41. void ElectrocardiographTester::initialize(IDataChannel *channel) { //
  42. m_channel = channel;
  43. m_channel->regRxListener([this](uint8_t *data, size_t len) {
  44. {
  45. // ZLOGI(TAG, "rx: %s", zhex2str(data, len).c_str());
  46. lock_guard<mutex> lock(lock_);
  47. if (len + m_rxlen > sizeof(m_rxcache)) {
  48. m_rxlen = 0;
  49. }
  50. memcpy(m_rxcache + m_rxlen, data, len);
  51. m_rxlen += len;
  52. }
  53. });
  54. m_thread.reset(new thread([this]() {
  55. while (true) {
  56. this_thread::sleep_for(chrono::milliseconds(2));
  57. {
  58. lock_guard<mutex> lock(lock_);
  59. // 1.找头部
  60. int32_t headerpos = -1;
  61. uint8_t headerType = 0;
  62. for (int32_t i = 0; i < m_rxlen - 1; i++) {
  63. if (isHeader(m_rxcache + i, &headerType)) {
  64. headerpos = i;
  65. break;
  66. }
  67. }
  68. if (headerpos == -1) {
  69. continue;
  70. }
  71. // 2.找尾
  72. int32_t tailpos = -1;
  73. for (int32_t i = headerpos + 2; i < m_rxlen - 1; i++) {
  74. if (isTail(headerType, m_rxcache + i)) {
  75. tailpos = i;
  76. break;
  77. }
  78. }
  79. if (tailpos == -1) {
  80. continue;
  81. }
  82. // 3.处理数据
  83. int32_t datalen = tailpos - headerpos + 2;
  84. uint8_t *packet = &m_rxcache[headerpos];
  85. if (packet[0] == 0x5A && packet[1] == 0xA5) {
  86. processCh3RxData(packet, datalen);
  87. } else if (packet[0] == 0x4B && packet[1] == 0xB4) {
  88. processCh4RxData(packet, datalen);
  89. } else {
  90. ZLOGI(TAG, "unknow packet: %s", zhex2str(packet, datalen).c_str());
  91. }
  92. // 4. 移除已经处理的数据
  93. int32_t leftlen = m_rxlen - tailpos - 2;
  94. if (leftlen > 0) {
  95. memmove(m_rxcache, m_rxcache + tailpos + 2, leftlen);
  96. }
  97. m_rxlen = leftlen;
  98. }
  99. }
  100. }));
  101. }
  102. // m_on_raw_data_cb
  103. void ElectrocardiographTester::regReportCB(on_report_t cb) { m_on_report = cb; }
  104. void ElectrocardiographTester::regCh4CheckSumPacketReport(on_ch4_check_sum_packet_report_t cb) { m_on_ch4_check_sum_packet_report = cb; }
  105. void ElectrocardiographTester::regRawDataCB(on_raw_data_t cb) { m_on_raw_data_cb = cb; }
  106. typedef struct {
  107. uint32_t rxcnt;
  108. uint32_t m_rx_sum_cnt;
  109. } block_data_rx_state_t;
  110. void ElectrocardiographTester::processCh4RxData(uint8_t *rx, int32_t rxlen) {
  111. block_data_rx_state_t *block_data_rx_state = (block_data_rx_state_t *)&rx[2];
  112. if (m_on_ch4_check_sum_packet_report) m_on_ch4_check_sum_packet_report(block_data_rx_state->rxcnt, block_data_rx_state->m_rx_sum_cnt);
  113. return;
  114. }
  115. void ElectrocardiographTester::processCh3RxData(uint8_t *rx, int32_t rxlen) {
  116. ify_hrs_packet_t *rxcmd = (ify_hrs_packet_t *)&rx[2];
  117. if (rxcmd->frame_type == kifyhrs_pt_cmd_receipt || rxcmd->frame_type == kifyhrs_pt_error_receipt) {
  118. if (rxcmd->frame_index == m_rxReceiptContext.waittingIndex) {
  119. lock_guard<mutex> lock(m_rxReceiptContext_lock);
  120. m_rxReceiptContext.receiptIsReady = true;
  121. m_rxReceiptContext.receiptLen = rxlen;
  122. memcpy(m_rxReceiptContext.receipt, &rx[2], rxlen - 2);
  123. } else {
  124. ZLOGE(TAG, "Rx index not match, %s", zhex2str(rx, rxlen).c_str());
  125. return;
  126. }
  127. } else if (rxcmd->frame_type == kifyhrs_pt_report) {
  128. processRxReportPacket(rxcmd, rxlen);
  129. }
  130. }
  131. void ElectrocardiographTester::processRxReportPacket(ify_hrs_packet_t *rx, int32_t rxlen) {
  132. if (m_on_report == nullptr) {
  133. return;
  134. }
  135. if (m_on_raw_data_cb) m_on_raw_data_cb(kcmd_report, (uint8_t *)rx, rxlen);
  136. m_on_report(rx, rxlen);
  137. }
  138. void ElectrocardiographTester::sendCmd(ify_hrs_packet_t *tx, int32_t txlen, ify_hrs_packet_t *rx, int32_t *rxlen, int32_t overtime) {
  139. if (m_channel == nullptr || m_channel->isOpen() == false) {
  140. throw zexception(kifyhrs_ecode_channle_is_close, "channel is not open");
  141. }
  142. uint8_t txindex = m_txindex++;
  143. ify_hrs_packet_t *txcmd = (ify_hrs_packet_t *)tx;
  144. txcmd->frame_index = txindex;
  145. txcmd->frame_type = kifyhrs_pt_cmd;
  146. {
  147. lock_guard<mutex> lock(m_rxReceiptContext_lock);
  148. m_rxReceiptContext.waittingIndex = txindex;
  149. m_rxReceiptContext.waittingForReceipt = true;
  150. m_rxReceiptContext.receiptIsReady = false;
  151. m_rxReceiptContext.receiptLen = 0;
  152. }
  153. if (m_on_raw_data_cb) m_on_raw_data_cb(kcmd_cmd, (uint8_t *)tx, txlen);
  154. m_channel->send((uint8_t *)tx, txlen);
  155. bool rxreceipt = false;
  156. for (int32_t i = 0; i < overtime; i++) {
  157. {
  158. lock_guard<mutex> lock(m_rxReceiptContext_lock);
  159. /**
  160. * @brief
  161. */
  162. if (m_rxReceiptContext.receiptIsReady) {
  163. memcpy(rx, m_rxReceiptContext.receipt, m_rxReceiptContext.receiptLen);
  164. *rxlen = m_rxReceiptContext.receiptLen;
  165. rxreceipt = true;
  166. if (m_on_raw_data_cb) m_on_raw_data_cb(kcmd_receipt, (uint8_t *)rx, *rxlen);
  167. break;
  168. }
  169. }
  170. this_thread::sleep_for(chrono::milliseconds(1));
  171. }
  172. if (!rxreceipt) {
  173. throw zexception(kifyhrs_ecode_overtime, "overtime");
  174. }
  175. ify_hrs_packet_t *rxcmd = (ify_hrs_packet_t *)rx;
  176. if (rxcmd->frame_type == kifyhrs_pt_error_receipt) {
  177. error_receipt_t *receipt = (error_receipt_t *)rxcmd->data;
  178. throw zexception(receipt->errorcode, "ecode");
  179. }
  180. return;
  181. }
  182. void ElectrocardiographTester::readDeviceVersion(device_version_info_receipt_t *version) {
  183. lock_guard<mutex> lock(m_tx_lock);
  184. m_txcmd->cmd = ify_hrs_cmd_read_device_version;
  185. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  186. device_version_info_receipt_t *receipt = (device_version_info_receipt_t *)m_rxcmd->data;
  187. memcpy(version, receipt, sizeof(device_version_info_receipt_t));
  188. return;
  189. }
  190. void ElectrocardiographTester::readSensorInfo(sensor_info_receipt_t *sensor) {
  191. lock_guard<mutex> lock(m_tx_lock);
  192. m_txcmd->cmd = ify_hrs_cmd_read_sensor_info;
  193. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  194. sensor_info_receipt_t *receipt = (sensor_info_receipt_t *)m_rxcmd->data;
  195. memcpy(sensor, receipt, sizeof(sensor_info_receipt_t));
  196. return;
  197. }
  198. void ElectrocardiographTester::readDeviceState(device_state_receipt_t *state) {
  199. lock_guard<mutex> lock(m_tx_lock);
  200. m_txcmd->cmd = ify_hrs_cmd_read_device_state;
  201. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  202. device_state_receipt_t *receipt = (device_state_receipt_t *)m_rxcmd->data;
  203. memcpy(state, receipt, sizeof(device_state_receipt_t));
  204. return;
  205. }
  206. void ElectrocardiographTester::readTime(read_time_receipt_t *time) {
  207. lock_guard<mutex> lock(m_tx_lock);
  208. m_txcmd->cmd = ify_hrs_cmd_read_time;
  209. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  210. read_time_receipt_t *receipt = (read_time_receipt_t *)m_rxcmd->data;
  211. memcpy(time, receipt, sizeof(read_time_receipt_t));
  212. return;
  213. }
  214. void ElectrocardiographTester::syncTime(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
  215. lock_guard<mutex> lock(m_tx_lock);
  216. sync_time_cmd_t *cmd = (sync_time_cmd_t *)m_txcmd->data;
  217. cmd->year = year;
  218. cmd->month = month;
  219. cmd->day = day;
  220. cmd->hour = hour;
  221. cmd->minute = minute;
  222. cmd->second = second;
  223. m_txcmd->cmd = ify_hrs_cmd_sync_time;
  224. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(sync_time_cmd_t), m_rxcmd, &m_rxsize, 100);
  225. return;
  226. }
  227. void ElectrocardiographTester::startCapture() {
  228. lock_guard<mutex> lock(m_tx_lock);
  229. m_txcmd->cmd = ify_hrs_cmd_start_capture;
  230. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  231. return;
  232. }
  233. void ElectrocardiographTester::stopCapture() {
  234. lock_guard<mutex> lock(m_tx_lock);
  235. m_txcmd->cmd = ify_hrs_cmd_stop_capture;
  236. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  237. return;
  238. }
  239. void ElectrocardiographTester::startRealtimeReport() {
  240. lock_guard<mutex> lock(m_tx_lock);
  241. m_txcmd->cmd = ify_hrs_cmd_start_realtime_report;
  242. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  243. return;
  244. }
  245. void ElectrocardiographTester::stopRealtimeReport() {
  246. lock_guard<mutex> lock(m_tx_lock);
  247. m_txcmd->cmd = ify_hrs_cmd_stop_realtime_report;
  248. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  249. return;
  250. }
  251. void ElectrocardiographTester::readRecordsInfo(int32_t recordoff, read_record_info_receipt_t *recordinfo) {
  252. lock_guard<mutex> lock(m_tx_lock);
  253. m_txcmd->cmd = ify_hrs_cmd_read_records_info;
  254. read_record_info_cmd_t *cmd = (read_record_info_cmd_t *)m_txcmd->data;
  255. cmd->record_index = recordoff;
  256. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(read_record_info_cmd_t), m_rxcmd, &m_rxsize, 100);
  257. read_record_info_receipt_t *receipt = (read_record_info_receipt_t *)m_rxcmd->data;
  258. memcpy(recordinfo, receipt, sizeof(read_record_info_receipt_t));
  259. return;
  260. }
  261. void ElectrocardiographTester::delRecord(uint8_t *recordId) {
  262. lock_guard<mutex> lock(m_tx_lock);
  263. del_record_cmd_t *cmd = (del_record_cmd_t *)m_txcmd->data;
  264. memcpy(cmd->record_id, recordId, 6);
  265. m_txcmd->cmd = ify_hrs_cmd_del_record;
  266. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(del_record_cmd_t), m_rxcmd, &m_rxsize, 100);
  267. return;
  268. }
  269. void ElectrocardiographTester::startUploadRecord(uint8_t *recordId) {
  270. lock_guard<mutex> lock(m_tx_lock);
  271. start_upload_record_cmd_t *cmd = (start_upload_record_cmd_t *)m_txcmd->data;
  272. memcpy(cmd->record_id, recordId, 6);
  273. m_txcmd->cmd = ify_hrs_cmd_start_upload_record;
  274. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(start_upload_record_cmd_t), m_rxcmd, &m_rxsize, 100);
  275. return;
  276. }
  277. void ElectrocardiographTester::stopUploadRecord() {
  278. lock_guard<mutex> lock(m_tx_lock);
  279. m_txcmd->cmd = ify_hrs_cmd_stop_upload_record;
  280. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  281. return;
  282. }
  283. void ElectrocardiographTester::readSn(string &sn) {
  284. lock_guard<mutex> lock(m_tx_lock);
  285. m_txcmd->cmd = ify_hrs_cmd_read_sn;
  286. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  287. read_sn_receipt_t *receipt = (read_sn_receipt_t *)m_rxcmd->data;
  288. sn = string((char *)receipt->sn, 14);
  289. return;
  290. }
  291. void ElectrocardiographTester::reset() {
  292. lock_guard<mutex> lock(m_tx_lock);
  293. m_txcmd->cmd = ify_hrs_cmd_reset;
  294. sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
  295. return;
  296. }