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

#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;
}