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
360 lines
12 KiB
#include "electrocardiograph_tester.hpp"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "logger.hpp"
|
|
#include "zexception.hpp"
|
|
using namespace iflytop;
|
|
|
|
#define TAG "ElectrocardiographTester"
|
|
|
|
/*******************************************************************************
|
|
* UTILS_BEGIN *
|
|
*******************************************************************************/
|
|
|
|
static bool isHeader(uint8_t *data, uint8_t *headerType) {
|
|
if (data[0] == 0x5A && data[1] == 0xA5) {
|
|
*headerType = 1;
|
|
return true;
|
|
}
|
|
|
|
if (data[0] == 0x4A && data[1] == 0xA4) {
|
|
*headerType = 2;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool isTail(uint8_t headerType, uint8_t *data) {
|
|
if (headerType == 1 && data[0] == 0x5B && data[1] == 0xB5) {
|
|
return true;
|
|
}
|
|
|
|
if (headerType == 2 && data[0] == 0x4B && data[1] == 0xB4) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/*******************************************************************************
|
|
* UTILS_END *
|
|
*******************************************************************************/
|
|
ElectrocardiographTester *ElectrocardiographTester::ins() {
|
|
static ElectrocardiographTester *ins = nullptr;
|
|
if (ins == nullptr) {
|
|
ins = new ElectrocardiographTester();
|
|
}
|
|
return ins;
|
|
}
|
|
void ElectrocardiographTester::initialize(IDataChannel *channel) { //
|
|
m_channel = channel;
|
|
m_channel->regRxListener([this](uint8_t *data, size_t len) {
|
|
{
|
|
// ZLOGI(TAG, "rx: %s", zhex2str(data, len).c_str());
|
|
lock_guard<mutex> lock(lock_);
|
|
if (len + m_rxlen > sizeof(m_rxcache)) {
|
|
m_rxlen = 0;
|
|
}
|
|
memcpy(m_rxcache + m_rxlen, data, len);
|
|
m_rxlen += len;
|
|
}
|
|
});
|
|
m_thread.reset(new thread([this]() {
|
|
while (true) {
|
|
this_thread::sleep_for(chrono::milliseconds(2));
|
|
|
|
{
|
|
lock_guard<mutex> lock(lock_);
|
|
// 1.找头部
|
|
int32_t headerpos = -1;
|
|
uint8_t headerType = 0;
|
|
for (int32_t i = 0; i < m_rxlen - 1; i++) {
|
|
if (isHeader(m_rxcache + i, &headerType)) {
|
|
headerpos = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (headerpos == -1) {
|
|
continue;
|
|
}
|
|
|
|
// 2.找尾
|
|
int32_t tailpos = -1;
|
|
for (int32_t i = headerpos + 2; i < m_rxlen - 1; i++) {
|
|
if (isTail(headerType, m_rxcache + i)) {
|
|
tailpos = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (tailpos == -1) {
|
|
continue;
|
|
}
|
|
|
|
// 3.处理数据
|
|
|
|
int32_t datalen = tailpos - headerpos + 2;
|
|
uint8_t *packet = &m_rxcache[headerpos];
|
|
|
|
if (packet[0] == 0x5A && packet[1] == 0xA5) {
|
|
processCh3RxData(packet, datalen);
|
|
} else if (packet[0] == 0x4B && packet[1] == 0xB4) {
|
|
processCh4RxData(packet, datalen);
|
|
} else {
|
|
ZLOGI(TAG, "unknow packet: %s", zhex2str(packet, datalen).c_str());
|
|
}
|
|
|
|
// 4. 移除已经处理的数据
|
|
int32_t leftlen = m_rxlen - tailpos - 2;
|
|
if (leftlen > 0) {
|
|
memmove(m_rxcache, m_rxcache + tailpos + 2, leftlen);
|
|
}
|
|
m_rxlen = leftlen;
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
// m_on_raw_data_cb
|
|
void ElectrocardiographTester::regReportCB(on_report_t cb) { m_on_report = cb; }
|
|
void ElectrocardiographTester::regCh4CheckSumPacketReport(on_ch4_check_sum_packet_report_t cb) { m_on_ch4_check_sum_packet_report = cb; }
|
|
|
|
void ElectrocardiographTester::regRawDataCB(on_raw_data_t cb) { m_on_raw_data_cb = cb; }
|
|
|
|
typedef struct {
|
|
uint32_t rxcnt;
|
|
uint32_t m_rx_sum_cnt;
|
|
} block_data_rx_state_t;
|
|
|
|
void ElectrocardiographTester::processCh4RxData(uint8_t *rx, int32_t rxlen) {
|
|
block_data_rx_state_t *block_data_rx_state = (block_data_rx_state_t *)&rx[2];
|
|
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);
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::processCh3RxData(uint8_t *rx, int32_t rxlen) {
|
|
ify_hrs_packet_t *rxcmd = (ify_hrs_packet_t *)&rx[2];
|
|
if (rxcmd->frame_type == kifyhrs_pt_cmd_receipt || rxcmd->frame_type == kifyhrs_pt_error_receipt) {
|
|
if (rxcmd->frame_index == m_rxReceiptContext.waittingIndex) {
|
|
lock_guard<mutex> lock(m_rxReceiptContext_lock);
|
|
m_rxReceiptContext.receiptIsReady = true;
|
|
m_rxReceiptContext.receiptLen = rxlen;
|
|
memcpy(m_rxReceiptContext.receipt, &rx[2], rxlen - 2);
|
|
} else {
|
|
ZLOGE(TAG, "Rx index not match, %s", zhex2str(rx, rxlen).c_str());
|
|
return;
|
|
}
|
|
} else if (rxcmd->frame_type == kifyhrs_pt_report) {
|
|
processRxReportPacket(rxcmd, rxlen);
|
|
}
|
|
}
|
|
void ElectrocardiographTester::processRxReportPacket(ify_hrs_packet_t *rx, int32_t rxlen) {
|
|
if (m_on_report == nullptr) {
|
|
return;
|
|
}
|
|
if (m_on_raw_data_cb) m_on_raw_data_cb(kcmd_report, (uint8_t *)rx, rxlen);
|
|
m_on_report(rx, rxlen);
|
|
}
|
|
|
|
void ElectrocardiographTester::sendCmd(ify_hrs_packet_t *tx, int32_t txlen, ify_hrs_packet_t *rx, int32_t *rxlen, int32_t overtime) {
|
|
if (m_channel == nullptr || m_channel->isOpen() == false) {
|
|
throw zexception(kifyhrs_ecode_channle_is_close, "channel is not open");
|
|
}
|
|
|
|
uint8_t txindex = m_txindex++;
|
|
|
|
ify_hrs_packet_t *txcmd = (ify_hrs_packet_t *)tx;
|
|
txcmd->frame_index = txindex;
|
|
txcmd->frame_type = kifyhrs_pt_cmd;
|
|
|
|
{
|
|
lock_guard<mutex> lock(m_rxReceiptContext_lock);
|
|
m_rxReceiptContext.waittingIndex = txindex;
|
|
m_rxReceiptContext.waittingForReceipt = true;
|
|
m_rxReceiptContext.receiptIsReady = false;
|
|
m_rxReceiptContext.receiptLen = 0;
|
|
}
|
|
|
|
if (m_on_raw_data_cb) m_on_raw_data_cb(kcmd_cmd, (uint8_t *)tx, txlen);
|
|
|
|
m_channel->send((uint8_t *)tx, txlen);
|
|
bool rxreceipt = false;
|
|
|
|
for (int32_t i = 0; i < overtime; i++) {
|
|
{
|
|
lock_guard<mutex> lock(m_rxReceiptContext_lock);
|
|
/**
|
|
* @brief 接收到回执
|
|
*/
|
|
if (m_rxReceiptContext.receiptIsReady) {
|
|
memcpy(rx, m_rxReceiptContext.receipt, m_rxReceiptContext.receiptLen);
|
|
*rxlen = m_rxReceiptContext.receiptLen;
|
|
rxreceipt = true;
|
|
if (m_on_raw_data_cb) m_on_raw_data_cb(kcmd_receipt, (uint8_t *)rx, *rxlen);
|
|
break;
|
|
}
|
|
}
|
|
this_thread::sleep_for(chrono::milliseconds(1));
|
|
}
|
|
|
|
if (!rxreceipt) {
|
|
throw zexception(kifyhrs_ecode_overtime, "overtime");
|
|
}
|
|
|
|
ify_hrs_packet_t *rxcmd = (ify_hrs_packet_t *)rx;
|
|
if (rxcmd->frame_type == kifyhrs_pt_error_receipt) {
|
|
error_receipt_t *receipt = (error_receipt_t *)rxcmd->data;
|
|
throw zexception(receipt->errorcode, "ecode");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::readDeviceVersion(device_version_info_receipt_t *version) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_read_device_version;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
|
|
device_version_info_receipt_t *receipt = (device_version_info_receipt_t *)m_rxcmd->data;
|
|
memcpy(version, receipt, sizeof(device_version_info_receipt_t));
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::readSensorInfo(sensor_info_receipt_t *sensor) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_read_sensor_info;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
|
|
sensor_info_receipt_t *receipt = (sensor_info_receipt_t *)m_rxcmd->data;
|
|
memcpy(sensor, receipt, sizeof(sensor_info_receipt_t));
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::readDeviceState(device_state_receipt_t *state) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_read_device_state;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
|
|
device_state_receipt_t *receipt = (device_state_receipt_t *)m_rxcmd->data;
|
|
memcpy(state, receipt, sizeof(device_state_receipt_t));
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::readTime(read_time_receipt_t *time) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_read_time;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
|
|
read_time_receipt_t *receipt = (read_time_receipt_t *)m_rxcmd->data;
|
|
memcpy(time, receipt, sizeof(read_time_receipt_t));
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::syncTime(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
sync_time_cmd_t *cmd = (sync_time_cmd_t *)m_txcmd->data;
|
|
cmd->year = year;
|
|
cmd->month = month;
|
|
cmd->day = day;
|
|
cmd->hour = hour;
|
|
cmd->minute = minute;
|
|
cmd->second = second;
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_sync_time;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(sync_time_cmd_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::startCapture() {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_start_capture;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::stopCapture() {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_stop_capture;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::startRealtimeReport() {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_start_realtime_report;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::stopRealtimeReport() {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_stop_realtime_report;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::readRecordsInfo(int32_t recordoff, read_record_info_receipt_t *recordinfo) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_read_records_info;
|
|
read_record_info_cmd_t *cmd = (read_record_info_cmd_t *)m_txcmd->data;
|
|
cmd->record_index = recordoff;
|
|
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(read_record_info_cmd_t), m_rxcmd, &m_rxsize, 100);
|
|
|
|
read_record_info_receipt_t *receipt = (read_record_info_receipt_t *)m_rxcmd->data;
|
|
memcpy(recordinfo, receipt, sizeof(read_record_info_receipt_t));
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::delRecord(uint8_t *recordId) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
del_record_cmd_t *cmd = (del_record_cmd_t *)m_txcmd->data;
|
|
memcpy(cmd->record_id, recordId, 6);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_del_record;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(del_record_cmd_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
void ElectrocardiographTester::startUploadRecord(uint8_t *recordId) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
start_upload_record_cmd_t *cmd = (start_upload_record_cmd_t *)m_txcmd->data;
|
|
memcpy(cmd->record_id, recordId, 6);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_start_upload_record;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t) + sizeof(start_upload_record_cmd_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::stopUploadRecord() {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_stop_upload_record;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::readSn(string &sn) {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_read_sn;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
|
|
read_sn_receipt_t *receipt = (read_sn_receipt_t *)m_rxcmd->data;
|
|
sn = string((char *)receipt->sn, 14);
|
|
return;
|
|
}
|
|
|
|
void ElectrocardiographTester::reset() {
|
|
lock_guard<mutex> lock(m_tx_lock);
|
|
|
|
m_txcmd->cmd = ify_hrs_cmd_reset;
|
|
sendCmd(m_txcmd, sizeof(ify_hrs_packet_t), m_rxcmd, &m_rxsize, 100);
|
|
return;
|
|
}
|