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.
 
 
 

366 lines
14 KiB

#include "app_ble_service.h"
#include "../../ify_hrs_protocol/heart_rate_sensor_protocol.h"
#include "app_event.h"
#include "app_event_distribute.h"
#include "app_scheduler.h"
#include "board/board.h"
#include "board/board_battery_state.h"
#include "device_ctrl_service.h"
#include "heart_wave_sample_service.h"
#include "sample_data_manager_service.h"
#include "zble_module.h"
#include "zdatachannel_service.h"
#include "znordic.h"
#include "znordic_device_info_mgr.h"
static uint8_t rxbufcache[256];
static bool is_rxbufcache_used = false; // 接收到的消息是否正在被处理中
static bool m_realtime_report_state = false; // 实时上报状态
static uint8_t m_txbuf[128];
static uint8_t m_reportbuf[128];
static void prvf_process_ble_rx_data(void* p_event_data, uint16_t event_size);
static void process_ble_rx_data(void* p_event_data, uint16_t event_size);
/*******************************************************************************
* 蓝牙服务注册 *
*******************************************************************************/
ZDATACHANNEL_DEF(m_zhrs, 2 /*优先级*/, 1 /*client num*/);
/**
* @brief 蓝牙消息回调
*/
static void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) {
if (p_evt->type != ZDATACHANNEL_EVT_RX_DATA) {
return;
}
// 消息正在被处理中,丢弃新来的消息
if (is_rxbufcache_used) return;
if (p_evt->params.rx_data.length > sizeof(rxbufcache)) return;
memcpy(rxbufcache, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
uint32_t suc = app_sched_event_put(rxbufcache, p_evt->params.rx_data.length, process_ble_rx_data);
if (suc == 0) {
is_rxbufcache_used = true;
}
}
/*******************************************************************************
* UTILS *
*******************************************************************************/
int ble_start_realtime_report() {
m_realtime_report_state = true;
return 0;
}
int ble_stop_realtime_report() {
m_realtime_report_state = false;
return 0;
}
static void send_error_receipt(ify_hrs_packet_t* rxpacket, int32_t errorcode) {
ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)m_txbuf;
error_receipt_t* receipt = (error_receipt_t*)txheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(error_receipt_t);
txheader->cmd = rxpacket->cmd;
txheader->frame_index = rxpacket->frame_index;
txheader->frame_type = kifyhrs_pt_error_receipt;
txheader->frame_type = kifyhrs_pt_error_receipt;
receipt->errorcode = kifyhrs_ecode_cmd_not_support;
zdatachannel_data_send2(m_txbuf, sendlen);
}
static void send_success_receipt(ify_hrs_packet_t* rxpacket, int32_t emptydatasize) {
ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)m_txbuf;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + emptydatasize;
txheader->cmd = rxpacket->cmd;
txheader->frame_index = rxpacket->frame_index;
txheader->frame_type = kifyhrs_pt_cmd_receipt;
zdatachannel_data_send2(m_txbuf, sendlen);
}
static void prvf_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1) {
sensor_drop_event_report_packet_t* reportpacket = (sensor_drop_event_report_packet_t*)m_reportbuf;
reportpacket->cmd = ify_hrs_report_sensor_drop_detect;
reportpacket->frame_index = 0;
reportpacket->frame_type = kifyhrs_pt_report;
reportpacket->drop_state0 = dropstate0;
reportpacket->drop_state1 = dropstate1;
uint16_t sendlen = sizeof(sensor_drop_event_report_packet_t);
zdatachannel_data_send2(m_reportbuf, sendlen);
return;
}
static void prvf_try_report_sample_end_event() {
ify_hrs_packet_t* reportpacket = (ify_hrs_packet_t*)m_reportbuf;
reportpacket->cmd = ify_hrs_report_sample_finish_end;
reportpacket->frame_index = 0;
reportpacket->frame_type = kifyhrs_pt_report;
uint16_t sendlen = sizeof(ify_hrs_packet_t);
zdatachannel_data_send2(m_reportbuf, sendlen);
return;
}
void prvf_report_sample_data(uint32_t frameIndex, uint32_t data, uint32_t data2, uint32_t data3) {
if (!m_realtime_report_state) {
return;
}
heartrate_report_packet_t* reportpacket = (heartrate_report_packet_t*)m_reportbuf;
reportpacket->cmd = ify_hrs_report_heartrate_data;
reportpacket->frame_index = 0;
reportpacket->frame_type = kifyhrs_pt_report;
reportpacket->sample_data_index = frameIndex;
/**
* @brief 第一导联数据
*/
reportpacket->data[0] = (data >> 0) & 0xFF;
reportpacket->data[1] = (data >> 8) & 0xFF;
reportpacket->data[2] = (data >> 16) & 0xFF;
reportpacket->data[3] = 0;
/**
* @brief 第二导联数据
*/
reportpacket->data[4] = (data2 >> 0) & 0xFF;
reportpacket->data[5] = (data2 >> 8) & 0xFF;
reportpacket->data[6] = (data2 >> 16) & 0xFF;
reportpacket->data[7] = 0;
/**
* @brief 第三导联数据
*/
reportpacket->data[8] = (data3 >> 0) & 0xFF;
reportpacket->data[9] = (data3 >> 8) & 0xFF;
reportpacket->data[10] = (data3 >> 16) & 0xFF;
reportpacket->data[11] = 0;
uint16_t sendlen = sizeof(heartrate_report_packet_t) + 4 * 3;
zdatachannel_data_send2(m_reportbuf, sendlen);
return;
}
/*******************************************************************************
* 消息处理 *
*******************************************************************************/
static void process_ble_rx_data(void* p_event_data, uint16_t event_size) { //
prvf_process_ble_rx_data(p_event_data, event_size);
is_rxbufcache_used = false;
}
static void prvf_process_ble_rx_data(void* p_event_data, uint16_t len) {
ify_hrs_packet_t* rxheader = (ify_hrs_packet_t*)p_event_data;
ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)m_txbuf;
ify_hrs_cmd_t cmd = (ify_hrs_cmd_t)rxheader->cmd;
memset(m_txbuf, 0, sizeof(m_txbuf));
ZLOGI("rx:");
NRF_LOG_HEXDUMP_INFO(p_event_data, len);
ZLOGI("rx cmd:%d index:%d datalen:%d", cmd, rxheader->frame_index, len - sizeof(ify_hrs_packet_t));
txheader->cmd = rxheader->cmd;
txheader->frame_index = rxheader->frame_index;
txheader->frame_type = kifyhrs_pt_cmd_receipt;
NRF_LOG_HEXDUMP_INFO(rxheader->data, len - sizeof(ify_hrs_packet_t));
if (cmd == ify_hrs_cmd_read_device_version) {
device_version_info_receipt_t* receipt = (device_version_info_receipt_t*)txheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_version_info_receipt_t);
receipt->blestack_version = device_info_read_blestack_version();
receipt->bootloader_version = device_info_read_bootloader_version();
receipt->firmware_version = device_info_read_firmware_version();
receipt->hardware_version = device_info_read_hardware_version();
zdatachannel_data_send2(m_txbuf, sendlen);
}
else if (cmd == ify_hrs_cmd_read_sensor_info) {
sensor_info_receipt_t* receipt = (sensor_info_receipt_t*)txheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(sensor_info_receipt_t);
receipt->sensor_num = 1;
receipt->sensor_precision = SAMPLE_PRECISION;
receipt->sensor_sample_rate = SAMPLE_RATE / 10;
receipt->sensor0_pos = kifyhrs_sensor_pos_II;
receipt->sensor1_pos = kifyhrs_sensor_pos_V1;
receipt->sensor2_pos = kifyhrs_sensor_pos_V5;
zdatachannel_data_send2(m_txbuf, sendlen);
}
else if (cmd == ify_hrs_cmd_read_device_state) {
device_state_receipt_t* receipt = (device_state_receipt_t*)txheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_state_receipt_t);
receipt->drop_state0 = hwss_get_drop_state0();
receipt->drop_state1 = hwss_get_drop_state1();
receipt->drop_state1 = 0x00;
receipt->device_state0.sampling_state = (DeviceCtrl_now_state() == kdevice_state_sampling);
receipt->device_state0.report_state = m_realtime_report_state;
receipt->device_state0.low_battery = (BoardBattery_get_battery_level() < 20);
receipt->device_state0.full_storge = (SampleDataMgr_storageIsFull());
receipt->device_state1 = 0;
receipt->powerlevel = BoardBattery_get_battery_level();
receipt->storage_item_num = SampleDataMgr_getFileNum();
zdatachannel_data_send2(m_txbuf, sendlen);
}
else if (cmd == ify_hrs_cmd_read_time) {
read_time_receipt_t* receipt = (read_time_receipt_t*)txheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_time_receipt_t);
static ztm_t ztm;
znordic_rtc_gettime(&ztm);
receipt->year = (ztm.tm_year + 1900 - 2000);
receipt->month = ztm.tm_mon + 1;
receipt->day = ztm.tm_mday;
receipt->hour = ztm.tm_hour;
receipt->minute = ztm.tm_min;
receipt->second = ztm.tm_sec;
zdatachannel_data_send2(m_txbuf, sendlen);
}
else if (cmd == ify_hrs_cmd_sync_time) {
sync_time_cmd_t* cmd = (sync_time_cmd_t*)rxheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t);
znordic_rtc_settime(cmd->year + 2000, cmd->month, cmd->day, cmd->hour, cmd->minute, cmd->second);
zdatachannel_data_send2(m_txbuf, sendlen);
}
else if (cmd == ify_hrs_cmd_start_capture) {
hwss_start_capture();
send_success_receipt(rxheader, 0);
}
else if (cmd == ify_hrs_cmd_stop_capture) {
hwss_stop_capture();
send_success_receipt(rxheader, 0);
}
else if (cmd == ify_hrs_cmd_start_realtime_report) {
// unsupport cmd
int ecode = ble_start_realtime_report();
if (ecode == 0) {
send_success_receipt(rxheader, 8); // 凑8个字节,使这个回执的字节长度同上报包长度一致,方便调试
} else {
send_error_receipt(rxheader, ecode);
}
}
else if (cmd == ify_hrs_cmd_stop_realtime_report) {
int ecode = ble_stop_realtime_report();
if (ecode == 0) {
send_success_receipt(rxheader, 0);
} else {
send_error_receipt(rxheader, ecode);
}
}
else if (cmd == ify_hrs_cmd_read_records_info) {
// 指令 10-读取采样记录头部信息
read_record_info_cmd_t* cmd = (read_record_info_cmd_t*)rxheader->data;
read_record_info_receipt_t* receipt = (read_record_info_receipt_t*)txheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_record_info_receipt_t);
uint8_t recordoff = cmd->record_index;
// 采样时不支持
if (hwss_is_capturing()) {
send_error_receipt(rxheader, kifyhrs_ecode_device_busy);
return;
}
sample_data_fileinfo_list_t* recordlist = SampleDataMgr_getFileinfoList();
if (recordoff >= recordlist->count) {
send_error_receipt(rxheader, kifyhrs_ecode_no_record_find);
return;
}
sample_data_fileinfo_t* fileinfo = recordlist->fileinfo[recordoff];
memcpy(receipt->record_id, fileinfo->filename, 6);
receipt->frameNum = fileinfo->size / 2; // 2byte per frame
receipt->dataSize = fileinfo->size;
receipt->sensorNum = 1;
receipt->captureRate = SAMPLE_RATE / 10;
receipt->capturePrecision = SAMPLE_PRECISION;
receipt->compressAlgorithm = 0;
zdatachannel_data_send2(m_txbuf, sendlen);
}
else if (cmd == ify_hrs_cmd_del_record) {
// 指令 11-删除采样记录
del_record_cmd_t* cmd = (del_record_cmd_t*)rxheader->data;
static sample_data_filename_t filename;
memset(&filename, 0, sizeof(filename));
memcpy(&filename, cmd->record_id, sizeof(cmd->record_id));
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support);
}
else if (cmd == ify_hrs_cmd_start_upload_record) {
// 指令 12-上传采集记录
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support);
}
else if (cmd == ify_hrs_cmd_enter_ota) {
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support);
}
else if (cmd == ify_hrs_cmd_read_sn) {
read_sn_receipt_t* receipt = (read_sn_receipt_t*)txheader->data;
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_sn_receipt_t);
device_info_read_sn((sn_t*)&receipt->sn);
zdatachannel_data_send2(m_txbuf, sendlen);
}
else if (cmd == ify_hrs_cmd_reset) {
NVIC_SystemReset();
}
//
else {
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support);
}
}
void AppBleService_onServiceInitCB() {
ZLOGI("init zdatachannel service");
static zdatachannel_init_t zdatachannle_init;
memset(&zdatachannle_init, 0, sizeof(zdatachannle_init));
zdatachannle_init.data_handler = zdatachannel_data_handler;
ZERROR_CHECK(zdatachannel_init(&m_zhrs, &zdatachannle_init));
}
static void app_event_listener(void* p_event_data, uint16_t event_size) { //
app_event_t* event = (app_event_t*)p_event_data;
if (event->eventType == kevent_sensor_drop) {
prvf_try_report_sensor_drop_event(event->val.sensor_drop.drop0, event->val.sensor_drop.drop1);
} else if (event->eventType == kevent_sample_stop_event) {
prvf_try_report_sample_end_event();
} else if (event->eventType == kevent_capture_little_data_block_event) {
// 上报采样数据
if (m_realtime_report_state) {
// 上报采样数据
prvf_report_sample_data(event->val.little_data_block.frameIndex, //
event->val.little_data_block.data[0].data0, //
event->val.little_data_block.data[0].data1, //
event->val.little_data_block.data[0].data2);
}
}
}
void AppBleService_init() { AppEvent_regListener(app_event_listener); }