From: SnickerSun Date: Thu, 16 May 2024 12:32:51 +0000 (+0800) Subject: 重构ble通讯协议接收代码,增加 ota文件接收,实现ota升级能力 X-Git-Tag: release_V1.2.70_20241020_135402~1115^2~1 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=refs%2Fchanges%2F174%2Ftarget%2F1;p=mirrors%2FFD230.git 重构ble通讯协议接收代码,增加 ota文件接收,实现ota升级能力 --- diff --git a/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.c b/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.c index 675585cfd..a6c7ce191 100644 --- a/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.c +++ b/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.c @@ -39,7 +39,7 @@ extern "C" { #include "errcode.h" #include "bletest.h" - +#include "custom_utils.h" #define DEBUG_TEST (0) #define CRC_CHECK_ERR 0 //crc校验失败 #define JSON_CHECK_OK 1 //json解析成功 @@ -221,10 +221,12 @@ void cameram_data(void)//拍照发送数据 调用这个接口即可 } bool bigDataBufState=false;//大数据传输状态 -static bool Check_CRC(uint8_t *data,uint16_t len,uint8_t crcvalue)//计算20byte的的校验位 +/** + * 计算crc时的求和函数,可以递归,从而实现多段数据的组合计算 +*/ +static uint8_t calculate_lrc(uint8_t *data,uint16_t len,uint8_t _lrcValue) { - uint8_t crcbuf = 0; - uint8_t lrcValue = 0x00; + uint8_t lrcValue = _lrcValue; if(data == NULL) { return false; @@ -234,11 +236,33 @@ static bool Check_CRC(uint8_t *data,uint16_t len,uint8_t crcvalue)//计算20byte lrcValue =lrcValue+ data[i]; // printf("%02x ",data[i]); } - //"{\"pn\":\"iPhone\",\"tp\":1}"; - + return lrcValue; +} + +/*** + * 根据求和后的数据计算crc 值 +*/ +static uint8_t get_crc_from_lrc(uint8_t lrcValue) +{ + uint8_t crcbuf = 0; crcbuf = lrcValue%256; crcbuf = 256-crcbuf; crcbuf = crcbuf%256; + return crcbuf; +} + +static bool Check_CRC(uint8_t *data,uint16_t len,uint8_t crcvalue)//计算20byte的的校验位 +{ + uint8_t crcbuf = 0; + uint8_t lrcValue = 0x00; + if(data == NULL) + { + return false; + } + lrcValue = calculate_lrc(data,len,0x00); + + crcbuf = get_crc_from_lrc(lrcValue); + WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "Check_CRC ret:0x%x len:%d\r\n",crcbuf,len); if(crcbuf == crcvalue) @@ -256,38 +280,20 @@ static uint8_t Calculate_CRC(uint8_t *data,uint16_t len)//计算20byte { uint8_t crcbuf = 0; uint8_t lrcValue = 0x00; - for(uint16_t i = 17; i < len; i++) - { - lrcValue =lrcValue+ data[i]; - } - // printf("Calculate_CRC:%x,len:%d",lrcValue,len); - crcbuf = lrcValue%256; - crcbuf = 256-crcbuf; - crcbuf = crcbuf%256; + lrcValue = calculate_lrc(data+17,len-17,0x00); + crcbuf = get_crc_from_lrc(lrcValue); return crcbuf; } -static uint8_t cal_sum(uint8_t *data,uint16_t len)//计算20byte -{ - uint8_t lrcValue = 0x00; - for(uint16_t i = 0; i < len; i++) - { - lrcValue =lrcValue+ data[i]; - } - return lrcValue; -} + static uint8_t Calculate_CRC_Big(uint8_t *data,uint16_t len)//计算20byte { uint8_t crcbuf = 0; uint8_t lrcValue = 0x00; - for(uint16_t i = 0; i < len; i++) - { - lrcValue =lrcValue+ data[i]; - } - crcbuf = lrcValue%256; - crcbuf = 256-crcbuf; - crcbuf = crcbuf%256; + lrcValue = calculate_lrc(data,len,0x00); + crcbuf = get_crc_from_lrc(lrcValue); return crcbuf; } + static cJSON *cjson_json_tmp = NULL; //发送ble数据 errcode_t sendBleData(uint8_t *buf,uint16_t len) @@ -347,6 +353,73 @@ void send_big_data(uint8_t flag, char *data, int datalen, int total, uint32_t Pa ym_free(buf); // 释放内存空间 } + + + + + + +uint32_t packdataLen = 0; +uint32_t totalDataLen = 0; +uint8_t totalpack = 0; +uint8_t cmd_data[17]; +uint8_t *recvData; +#include "los_memory.h" + + +#if USE_PROTOCOL_EN_DE_BY_SNICKER +#define MAX_BLE_MSG_PACKAGE_LEN (1024*5) //包缓存最大5k +#define BLE_MSG_TMP_FILE_NAME "/user/userdata/ble_tmp_buf_%04X" +typedef struct +{ + int handle; + int data_len ; + int totalDataLen; + int buffer_to_file; //1 buffer to file , 0 buffer to ram + int decode_type; //1 with header , 2 no header + FILE *tmpfilehandle;// 如果buffer to file , 则在此保存handle + msg_header_t cmd_header; + uint8_t *data;//if buffer_to_file is 1, than data is the filename , else data is the ram buffer. + uint8_t crcvalue; + uint8_t lrcvalue; //计算crc用的临时变量 + uint32_t last_timestamp;// last package receive time + uint8_t receive_file_flag;//1 接收文件 0 不接收文件 + file_recv_stat_t file_recv_stat; +} ble_read_data; + +#define MAX_HANDLE_NUM 10 +//LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus) +//根据特征值分开组合读取的数据,并处理 +static ble_read_data handle_l[MAX_HANDLE_NUM]={0}; + +errcode_t cancel_recv_file(ble_read_data *buffer_handle); + + +#else + +typedef struct +{ + uint8_t *data; + int handle; + int data_len ; + int totalDataLen; + uint8_t cmd_data[17]; + uint8_t crcvalue; +} ble_read_data; + +#define MAX_HANDLE_NUM 10 +//LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus) +//根据特征值分开组合读取的数据,并处理 +static ble_read_data handle_l[MAX_HANDLE_NUM]={0}; + +#endif + + + + + + + //发送训练状态[app发起的运动] void sendtraningstatedata(uint8_t state ,uint16_t time) { @@ -1883,9 +1956,7 @@ void GetWeatherCmd(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *totalData,ui void getUserInfo(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *totalData,uint8_t crcvalue)// { - // 用户数据同步死机,暂时跳过 by Snicker - return; - + // 用户数据同步死机, uint8_t value[19]; memset(value,0,19); uint32_t tmp = 1; @@ -2488,7 +2559,11 @@ static void GetSwitchMessCmd(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *to } } //撤销当前文件传输 1 OTA 2MP3 3表盘 3天气 5闹钟 +#if USE_PROTOCOL_EN_DE_BY_SNICKER +static void RemoveFileCmd(ble_read_data *buffer_handle,uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *totaldata,uint8_t crcvalue) +#else static void RemoveFileCmd(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *totaldata,uint8_t crcvalue) +#endif { uint8_t value[19]; memset(value,0,19); @@ -2508,6 +2583,10 @@ static void RemoveFileCmd(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *total value[17] = 1; // value[18] = Calculate_CRC(value,18); sendBleData(value,19); + + #if USE_PROTOCOL_EN_DE_BY_SNICKER + cancel_recv_file(buffer_handle); + #endif }else { value[17] = 0; @@ -3913,10 +3992,14 @@ len 就是data的长度 *totaldata:总的数据内容 包含包头和校验预览做接口是用 如果要计算totaldata的长度直接是len+17+1 就是加上包头和校验和 crcvalue;数据的校验和 不包含包头和校验和的计算结果 */ +#if USE_PROTOCOL_EN_DE_BY_SNICKER +void type2AE3Data(ble_read_data *buffer_handle,uint8_t *cmd_buf ,uint8_t *data,uint16_t datalen,uint8_t *totaldata,uint8_t crcvalue) +#else void type2AE3Data(uint8_t *cmd_buf ,uint8_t *data,uint16_t datalen,uint8_t *totaldata,uint8_t crcvalue) +#endif { uint16_t cmd = cmd_buf[1]*256+cmd_buf[2]; - printf("typeHexOneData:0x%x\r\n",cmd); + printf("typeHexOneData:0x%04X\r\n",cmd); // uint8_t typeID = cmd_buf[2]; switch (cmd) { @@ -3945,10 +4028,12 @@ void type2AE3Data(uint8_t *cmd_buf ,uint8_t *data,uint16_t datalen,uint8_t *tota GetSwitchMessCmd(cmd,data,datalen,totaldata,crcvalue); break; case REVOKE_CURR_FILE_TRANS_CMD://撤销文件传输 - RemoveFileCmd(cmd,data,datalen,totaldata,crcvalue); + #if USE_PROTOCOL_EN_DE_BY_SNICKER + RemoveFileCmd(buffer_handle,cmd,data,datalen,totaldata,crcvalue); + #endif break; case GET_SPECIF_TYPE_FILE_CMD://获取指定类型文件目录 - RemoveFileCmd(cmd,data,datalen,totaldata,crcvalue); + GetFileTypeCmd(data,datalen); // break; case DELETE_SPECIF_TYPE_FILE_CMD://删除指定类型的所有文件 DeleteFileTypeCmd(cmd,data,datalen,totaldata,crcvalue); @@ -4431,29 +4516,6 @@ void getPhoneInfo_test(void) } -//长数据解析 -void bleLongRecvData(uint8_t *data, uint16_t data_size,uint8_t *buf_cmd,uint8_t *totalData,uint8_t crcvalue)//buf_cmd 指令前17个字节数据 -{ - uint8_t type=buf_cmd[1]; - printf("type:%d %d data_size:%d data:%x crcvalue:%x\r\n",buf_cmd[0],type,data_size,data,crcvalue); - switch (type) - { - case 0x02://获取手机信息 - type2AE4Data(buf_cmd,data,data_size,totalData,crcvalue); - break; - case 0x01: - type2AE3Data(buf_cmd,data,data_size,totalData,crcvalue); - break; - case 0x03:// - type2AE1Data(buf_cmd,data,data_size,totalData,crcvalue); - break; - case 0x04: - type2AE0Data(buf_cmd,data,data_size,totalData,crcvalue); - break; - default: - break; - } -} bool creatMessageDir(void)//创建消息文件夹 { struct stat info; @@ -4729,10 +4791,101 @@ void type2AE1Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *total } } -static ota_file_struct_t g_ota_file_stat={0}; +void bleRecvANCSData(uint8_t *data, uint16_t data_size,uint8_t *buf_cmd,uint8_t *totalData,uint8_t crcvalue)//buf_cmd 指令前17个字节数据 +{ + uint8_t type = buf_cmd[1]; + printf("type:%d %d data_size:%d data:%d crcvalue:%x\r\n",buf_cmd[0],type,data_size,data[0],crcvalue); + switch (type) + { + case 0x03:// + type2AE1Data(buf_cmd,data,data_size,totalData,crcvalue); + break; + default: + break; + } +} + -errcode_t ota_json_file_save(uint8_t *data,uint16_t datalen) +#if USE_PROTOCOL_EN_DE_BY_SNICKER + + +/** + * less than 20bytes msg reply +*/ +errcode_t ble_reply_msgarr(uint8_t msg_cmdtype,uint8_t msg_cmdid,uint8_t *replydata,uint16_t replydata_len) { + + //发送校验失败 + + if (replydata_len > 20) + { + printf("datalen is larger than 20, please send with other api !\n"); + return ERRCODE_FAIL; + } + uint16_t replybuflen=sizeof(msg_header_t)+replydata_len+1; + uint8_t *replybuf=malloc(replybuflen); + if(replybuf != NULL) + { + msg_header_t *reply_cmd_header=(msg_header_t*)replybuf; + reply_cmd_header->direction = MSG_DIRECTION_SEND; + reply_cmd_header->cmdtype =msg_cmdtype; + reply_cmd_header->cmdid = msg_cmdid; + reply_cmd_header->package_count = 1; + reply_cmd_header->package_index = 1; + reply_cmd_header->package_len = replydata_len; + reply_cmd_header->total_data_len = replydata_len; + memcpy_s(replybuf+sizeof(msg_header_t),replydata_len,replydata,replydata_len); + uint8_t crc_value = Calculate_CRC( replybuf, replybuflen - 1); + replybuf[ replybuflen - 1 ] = crc_value ; //CRC + errcode_t ret = sendBleData(replybuf,replybuflen); + printf("ble_reply_msgarr cmdtype %02X cmdid %02X package %d/%d , len %d,total len %d , data[0] %02X crc %02X\n", + reply_cmd_header->cmdtype, + reply_cmd_header->cmdid, + reply_cmd_header->package_index, + reply_cmd_header->package_count, + reply_cmd_header->package_len, + reply_cmd_header->total_data_len, + (replybuf+sizeof(msg_header_t))[0], + crc_value + ); + free(replybuf); + return ret; + }else{ + return ERRCODE_MALLOC; + } +} + +errcode_t ble_reply_cmdarr(uint16_t msg_cmd,uint8_t *replydata,uint16_t replydata_len) +{ + + uint8_t cmdtype = (uint8_t)((msg_cmd&0xFF00)>>8); + uint8_t cmdid = (uint8_t)(msg_cmd&0x00FF); + + return ble_reply_msgarr(cmdtype,cmdid,replydata,replydata_len); + +} +errcode_t ble_reply_cmd(uint16_t msg_cmd,uint8_t replydata) +{ + uint8_t cmdtype = (uint8_t)((msg_cmd&0xFF00)>>8); + uint8_t cmdid = (uint8_t)(msg_cmd&0x00FF); + printf("msg_cmd %04X cmdtype %02X cmdid %02X\n",msg_cmd,cmdtype,cmdid); + return ble_reply_msg(cmdtype,cmdid,replydata); +} +errcode_t ble_reply_msg(uint8_t msg_cmdtype,uint8_t msg_cmdid,uint8_t replydata) +{ + return ble_reply_msgarr(msg_cmdtype,msg_cmdid,&replydata,1); +} + + + + + + +errcode_t decode_ota_json(ble_read_data *buffer_handle) +{ + + uint8_t *data = buffer_handle->data+sizeof(msg_header_t); + uint16_t datalen = buffer_handle->totalDataLen; printf("ota_json_file_save %s\n",data); /** @@ -4757,67 +4910,114 @@ errcode_t ota_json_file_save(uint8_t *data,uint16_t datalen) cJSON* ota_type_json = cJSON_GetObjectItem(root, "type"); if(ota_type_json != NULL && cJSON_IsNumber(ota_type_json)) { - g_ota_file_stat.ota_type = ota_type_json->valueint; + buffer_handle->file_recv_stat.file_type = ota_type_json->valueint; } cJSON* ota_name_json = cJSON_GetObjectItem(root, "name"); if ( ota_name_json != NULL && cJSON_IsString(ota_name_json)) { - g_ota_file_stat.ota_name = ota_name_json->valuestring; + buffer_handle->file_recv_stat.file_name = ota_name_json->valuestring; } cJSON* ota_size_json = cJSON_GetObjectItem(root, "size"); if(ota_size_json != NULL && cJSON_IsNumber(ota_size_json)) { - g_ota_file_stat.ota_size = ota_size_json->valueint; + buffer_handle->file_recv_stat.file_size = ota_size_json->valueint; } cJSON* ota_major_json = cJSON_GetObjectItem(root, "major"); if(ota_major_json != NULL && cJSON_IsNumber(ota_major_json)) { - g_ota_file_stat.ota_major = ota_major_json->valueint; + buffer_handle->file_recv_stat.ota_major = ota_major_json->valueint; } cJSON* ota_mid_json = cJSON_GetObjectItem(root, "mid"); if(ota_mid_json != NULL && cJSON_IsNumber(ota_mid_json)) { - g_ota_file_stat.ota_mid = ota_mid_json->valueint; + buffer_handle->file_recv_stat.ota_mid = ota_mid_json->valueint; } cJSON* ota_minor_json = cJSON_GetObjectItem(root, "minor"); if(ota_minor_json != NULL && cJSON_IsNumber(ota_minor_json)) { - g_ota_file_stat.ota_minor = ota_minor_json->valueint; + buffer_handle->file_recv_stat.ota_minor = ota_minor_json->valueint; } cJSON* ota_isforced_json = cJSON_GetObjectItem(root, "isForced"); if(ota_isforced_json != NULL && cJSON_IsNumber(ota_isforced_json)) { - g_ota_file_stat.ota_isforced = ota_isforced_json->valueint; + buffer_handle->file_recv_stat.ota_isforced = ota_isforced_json->valueint; } cJSON_Delete(root); printf(" ota_type= %d, ota_name=%s, ota_size=%d, ota_major=%d, ota_mid=%d, ota_minor=%d, ota_isforced=%d \n", - g_ota_file_stat.ota_type, - g_ota_file_stat.ota_name, - g_ota_file_stat.ota_size, - g_ota_file_stat.ota_major, - g_ota_file_stat.ota_mid, - g_ota_file_stat.ota_minor, - g_ota_file_stat.ota_isforced + buffer_handle->file_recv_stat.file_type, + buffer_handle->file_recv_stat.file_name, + buffer_handle->file_recv_stat.file_size, + buffer_handle->file_recv_stat.ota_major, + buffer_handle->file_recv_stat.ota_mid, + buffer_handle->file_recv_stat.ota_minor, + buffer_handle->file_recv_stat.ota_isforced ); + buffer_handle->file_recv_stat.received_size = 0; + buffer_handle->file_recv_stat.lrcvalue = 0; + buffer_handle->receive_file_flag = 1; + return ERRCODE_SUCC; + }else{ + buffer_handle->receive_file_flag = 0; + return ERRCODE_FAIL; + } +} +void decode_file_checksum(ble_read_data *buffer_handle) +{ + + uint8_t msg_crc = get_crc_from_lrc(buffer_handle->lrcvalue); + if (msg_crc == buffer_handle->crcvalue) + { + uint8_t file_crc = get_crc_from_lrc(buffer_handle->file_recv_stat.lrcvalue); + uint8_t crc_recv = buffer_handle->data[sizeof(msg_header_t)]; + if (file_crc == crc_recv) + { + ble_reply_cmd(FILE_CHECKSUM_RECV_CMD,1); + do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_TYPE_STARTOTA,NULL,0); + }else{ + ble_reply_cmd(FILE_CHECKSUM_RECV_CMD,2); + } + }else{ + ble_reply_cmd(FILE_CHECKSUM_RECV_CMD,0); } - return ERRCODE_SUCC; + } -void type2AE0Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *totalData,uint8_t crcvalue) +void type2AE0Data(ble_read_data *buffer_handle) { - uint16_t typeID = buf_cmd[1]*256 +buf_cmd[2]; - printf("type2AE0Data typeID:0x%x datalen %d\r\n",typeID,datalen); - bool checkcrc = Check_CRC(data,datalen,crcvalue); + uint16_t typeID = buffer_handle->cmd_header.cmdtype*256 + buffer_handle->cmd_header.cmdid; + printf("type2AE0Data typeID:0x%x datalen %d\r\n",typeID,buffer_handle->totalDataLen); + bool checkcrc = (get_crc_from_lrc(buffer_handle->lrcvalue) == buffer_handle->crcvalue); if( checkcrc == true ) { switch (typeID) //ID { case OTA_FILE_RECV_CMD:// - ota_json_file_save( data, datalen); + { + if (decode_ota_json( buffer_handle) == ERRCODE_SUCC) + { + ble_reply_cmd(OTA_FILE_RECV_CMD,1); + }else{ + ble_reply_cmd(OTA_FILE_RECV_CMD,2); + } + } + break; + case MP3_FILE_RECV_CMD: + + break; + case DIAL_FILE_RECV_CMD: + break; + case FILE_CHECKSUM_RECV_CMD: + decode_file_checksum(buffer_handle); + break; + case EPO_DATA_RECV_CMD: break; + case SINGLE_DIAL_FILE_RECV_CMD: + break; + default: + break; } }else{ @@ -4825,45 +5025,8 @@ void type2AE0Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *total } } -void bleRecvANCSData(uint8_t *data, uint16_t data_size,uint8_t *buf_cmd,uint8_t *totalData,uint8_t crcvalue)//buf_cmd 指令前17个字节数据 -{ - uint8_t type = buf_cmd[1]; - printf("type:%d %d data_size:%d data:%d crcvalue:%x\r\n",buf_cmd[0],type,data_size,data[0],crcvalue); - switch (type) - { - case 0x03:// - type2AE1Data(buf_cmd,data,data_size,totalData,crcvalue); - break; - default: - break; - } -} - -uint32_t packdataLen = 0; -uint32_t totalDataLen = 0; -uint8_t totalpack = 0; -uint8_t cmd_data[17]; -uint8_t *recvData; -#include "los_memory.h" -#if USE_PROTOCOL_EN_DE_BY_SNICKER -#define MAX_BLE_MSG_PACKAGE_LEN (1024*5) //包缓存最大5k -typedef struct -{ - uint8_t *data; - int handle; - int data_len ; - int totalDataLen; - msg_header_t cmd_header; - uint8_t crcvalue; -} ble_read_data; - -#define MAX_HANDLE_NUM 10 -//LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus) -//根据特征值分开组合读取的数据,并处理 -static ble_read_data handle_l[MAX_HANDLE_NUM]={0}; - void dumpHeader(msg_header_t *msgheader) { printf("dumpHeader(%d) direction %02X, type %02X, id %02X, package_count %d, total_data_len %d,package_index %d , package_len %d\n", @@ -4878,7 +5041,148 @@ void dumpHeader(msg_header_t *msgheader) ); } +errcode_t check_header(msg_header_t *header ) +{ + if( (header->direction == MSG_DIRECTION_RECV) + && (header->cmdtype > 0 && header->cmdtype <= 6 ) + && (header->cmdid > 0 && header->cmdid <= 0x50 ) + ) + { + // 这个是合理的值,可以当做header来处理 + dumpHeader(header); + return ERRCODE_SUCC; + }else{ + //非header + // printf("not first package , no header!\n"); + return ERRCODE_FAIL; + } +} +errcode_t cancel_recv_file(ble_read_data *buffer_handle) +{ + + buffer_handle->receive_file_flag = 0; + + if (buffer_handle->file_recv_stat.recv_file_stat != 2) //已经下载完毕的文件,没有必要cancel了。 + { + + if (buffer_handle->file_recv_stat.file!=NULL) + { + fclose(buffer_handle->file_recv_stat.file); + buffer_handle->file_recv_stat.file = NULL; + } + buffer_handle->file_recv_stat.recv_file_stat = -1; + ble_reply_cmd(FILE_RECV_REPLY_STAT_CMD,0);//接收失败 + } + return ERRCODE_SUCC; +} +errcode_t handle_recv_file(ble_read_data *buffer_handle,uint8_t *data, uint16_t event_size) +{ + + if( event_size == 0 || data == NULL ) return ERRCODE_FAIL; + + + printf("handle_recv_file %d\n",event_size); + + //第一帧要创建文件 + if(buffer_handle->file_recv_stat.recv_file_stat <= 0 && buffer_handle->file_recv_stat.file == NULL) + { + buffer_handle->file_recv_stat.lrcvalue = 0; + if (buffer_handle->file_recv_stat.file_type == 1) + { + buffer_handle->file_recv_stat.file = fopen("/update/update.fwpkg","w+"); + printf("create file /update/update.fwpkg %X\n",buffer_handle->file_recv_stat.file); + }else{ + buffer_handle->file_recv_stat.file = fopen(buffer_handle->file_recv_stat.file_name,"w+"); + printf("create file %s %X\n",buffer_handle->file_recv_stat.file_name,buffer_handle->file_recv_stat.file); + } + if (buffer_handle->file_recv_stat.file == NULL) + { + return ERRCODE_FAIL; + } + buffer_handle->file_recv_stat.recv_file_stat = 1; + } + + if (buffer_handle->file_recv_stat.file == NULL) + { + return ERRCODE_FAIL; + } + //写入文件 + size_t writtensize = fwrite(data,1,event_size,buffer_handle->file_recv_stat.file); + if(writtensize == event_size) + { + buffer_handle->file_recv_stat.lrcvalue = calculate_lrc(data,event_size,buffer_handle->file_recv_stat.lrcvalue); + buffer_handle->file_recv_stat.received_size += event_size; + printf("handle_recv_file received_size %d\n",buffer_handle->file_recv_stat.received_size); + + }else{ + printf("handle_recv_file write file failed! ret %d != %d\n",writtensize,event_size); + return ERRCODE_FAIL; + } + + //检查文件是否写完 + if(buffer_handle->file_recv_stat.file_size == buffer_handle->file_recv_stat.received_size ) + { + if (buffer_handle->file_recv_stat.file!=NULL) + { + fclose(buffer_handle->file_recv_stat.file); + buffer_handle->file_recv_stat.file = NULL; + } + buffer_handle->file_recv_stat.recv_file_stat = 2; + buffer_handle->receive_file_flag = 0; + printf("handle_recv_file received success \n"); + ble_reply_cmd(FILE_RECV_REPLY_STAT_CMD,1);//接收成功 + } + + return ERRCODE_SUCC; +} + +//长数据解析 +void bleLongRecvData(ble_read_data *buffer_handle,uint8_t *data, uint16_t data_size,uint8_t *buf_cmd,uint8_t *totalData,uint8_t crcvalue)//buf_cmd 指令前17个字节数据 +{ + uint8_t type=buf_cmd[1]; + printf("type:%d %d data_size:%d data:%x crcvalue:%x\r\n", + buffer_handle->cmd_header.cmdtype, + buffer_handle->cmd_header.cmdid, + data_size, + data, + crcvalue); + switch (type) + { + case 0x02://获取手机信息 + type2AE4Data(buf_cmd,data,data_size,totalData,crcvalue); + break; + case 0x01: + type2AE3Data(buffer_handle,buf_cmd,data,data_size,totalData,crcvalue); + break; + case 0x03:// + type2AE1Data(buf_cmd,data,data_size,totalData,crcvalue); + break; + case 0x04: + type2AE0Data(buffer_handle); + break; + default: + break; + } +} + + +/// @brief 解码收到的msg +/// @param buffer_handle +/// @return +static errcode_t handle_ble_msg(ble_read_data *buffer_handle) +{ + + if(buffer_handle->buffer_to_file == 0) + { + bleLongRecvData(buffer_handle,buffer_handle->data+sizeof(msg_header_t),buffer_handle->totalDataLen,(uint8_t*)(&buffer_handle->cmd_header),NULL,buffer_handle->crcvalue); + + }else{ + //处理缓存成文件的 + printf("handle ble msg file buffer! not implement\n"); + } + return ERRCODE_SUCC; +} /***** * 组包函数 * 组包校验完成,在分发给对应的handler去解码协议。 @@ -4887,58 +5191,179 @@ void dumpHeader(msg_header_t *msgheader) errcode_t combine_data_internal(ble_read_data *buffer_handle,uint8_t *totalData, uint16_t event_size) { - msg_header_t *header = (msg_header_t*)totalData; - dumpHeader(header); - buffer_handle->cmd_header.direction = header->direction; - buffer_handle->cmd_header.cmdtype = header->cmdtype; - buffer_handle->cmd_header.cmdid = header->cmdid; - buffer_handle->cmd_header.package_count = header->package_count; - buffer_handle->cmd_header.total_data_len = header->total_data_len; - buffer_handle->cmd_header.package_len = header->package_len; - buffer_handle->cmd_header.package_index = header->package_index; - //第一帧 - if (buffer_handle->cmd_header.package_index == 1) + if(buffer_handle->receive_file_flag == 1) { + //接收文件 + return handle_recv_file(buffer_handle,totalData,event_size); + } + msg_header_t *header = (msg_header_t*)totalData; + //第一帧 + if (event_size > sizeof(msg_header_t) && check_header(header) == ERRCODE_SUCC ) + { + buffer_handle->cmd_header.direction = header->direction; + buffer_handle->cmd_header.cmdtype = header->cmdtype; + buffer_handle->cmd_header.cmdid = header->cmdid; + buffer_handle->cmd_header.package_count = header->package_count; + buffer_handle->cmd_header.total_data_len = header->total_data_len; + buffer_handle->cmd_header.package_len = header->package_len; + buffer_handle->cmd_header.package_index = header->package_index; //如果有历史数据,没有被清空,可能是历史错误数据,则清空内存。 if (buffer_handle->data!=NULL && buffer_handle->data_len > 0) { free(buffer_handle->data); buffer_handle->data = NULL; - buffer_handle->data_len = 0; } + if (buffer_handle->tmpfilehandle!=NULL && buffer_handle->data_len>0) + { + fclose(buffer_handle->tmpfilehandle); + buffer_handle->tmpfilehandle = NULL; + } + buffer_handle->data_len = 0; + buffer_handle->crcvalue = 0; + buffer_handle->lrcvalue = 0; + buffer_handle->buffer_to_file = 0; + buffer_handle->decode_type = 0; + buffer_handle->tmpfilehandle = NULL; + uint32_t timestamp_ble=0; + uapi_get_timestampe_ms(×tamp_ble); + buffer_handle->last_timestamp = timestamp_ble; buffer_handle->totalDataLen = buffer_handle->cmd_header.total_data_len; if (buffer_handle->totalDataLen > MAX_BLE_MSG_PACKAGE_LEN || buffer_handle->totalDataLen <= 0 ) { printf("package is too lardge (%d) than (%d) or too small !\n",buffer_handle->totalDataLen,MAX_BLE_MSG_PACKAGE_LEN); return ERRCODE_FAIL; } - buffer_handle->data = malloc(buffer_handle->totalDataLen); + if(buffer_handle->totalDataLen+sizeof(msg_header_t)+1 > MAX_BLE_MSG_PACKAGE_LEN) + { + //如果总长度超过限定大小,则写入文件做缓存。 + buffer_handle->buffer_to_file = 1; + int filelen = strlen(BLE_MSG_TMP_FILE_NAME); + buffer_handle->data = malloc(filelen); + if (buffer_handle->data== NULL) + { + return ERRCODE_MALLOC; + } + //生成临时文件名 + sprintf_s((char*)buffer_handle->data,filelen,BLE_MSG_TMP_FILE_NAME,buffer_handle->handle); + buffer_handle->tmpfilehandle = fopen((const char*)buffer_handle->data,"w+"); + printf("create ble protocol tmpfile %s handle %X\n",buffer_handle->data,buffer_handle->tmpfilehandle); + if (buffer_handle->tmpfilehandle != NULL) + { + //写buffer到文件 + size_t ret =fwrite(totalData,1,event_size,buffer_handle->tmpfilehandle); + buffer_handle->lrcvalue = calculate_lrc(totalData+sizeof(msg_header_t),header->package_len,0x00); + printf("write %d to buffer file!\n",ret); + } + buffer_handle->data_len += event_size; + + }else{ + //如果长度在限定大小之内。则写入内存中缓存。 + buffer_handle->buffer_to_file = 0; + buffer_handle->data = malloc(buffer_handle->totalDataLen+sizeof(msg_header_t)+1); + if (buffer_handle->data== NULL) + { + return ERRCODE_MALLOC; + } + //创建缓存开始存储包数据 + if(buffer_handle->cmd_header.package_len >0) + { + memcpy_s(buffer_handle->data,buffer_handle->totalDataLen+sizeof(msg_header_t)+1,totalData,event_size); + buffer_handle->lrcvalue = calculate_lrc(totalData+sizeof(msg_header_t),header->package_len,0x00); + buffer_handle->data_len += event_size; + } + + //单一包 + if(event_size == sizeof(msg_header_t)+buffer_handle->totalDataLen+1) + { + buffer_handle->crcvalue = totalData[event_size-1]; + } + } + + }else{ + //处理第二包以后的数据 + + //经过第一包处理,仍然data==NULL证明第一帧就是错的,要退出解析。 if (buffer_handle->data== NULL) { return ERRCODE_MALLOC; } - } - //经过第一包处理,仍然data==NULL证明第一帧就是错的,要退出解析。 - if (buffer_handle->data== NULL) - { - return ERRCODE_MALLOC; - } - //创建缓存开始存储包数据 - if(buffer_handle->cmd_header.package_len >0) - { - - + //此处是最后一帧 event_size = (buffer_handle->totalDataLen-buffer_handle->data_len) + 1 + if (event_size == (buffer_handle->totalDataLen + sizeof(msg_header_t) + 1 -buffer_handle->data_len )) + { + if(buffer_handle->buffer_to_file == 1) + { + fwrite(totalData,1,event_size,buffer_handle->tmpfilehandle); + + }else{ + memcpy_s(buffer_handle->data+buffer_handle->data_len,buffer_handle->totalDataLen,totalData,event_size); + + } + buffer_handle->lrcvalue = calculate_lrc(totalData,event_size,buffer_handle->lrcvalue); + buffer_handle->data_len += event_size; + }else if (event_size < (buffer_handle->totalDataLen + sizeof(msg_header_t) + 1 - buffer_handle->data_len)) //中间帧 + { + if(buffer_handle->buffer_to_file == 1) + { + fwrite(totalData,1,event_size,buffer_handle->tmpfilehandle); + + }else{ + memcpy_s(buffer_handle->data+buffer_handle->data_len,(buffer_handle->totalDataLen + sizeof(msg_header_t) + 1 - buffer_handle->data_len),totalData,event_size); + + } + buffer_handle->lrcvalue = calculate_lrc(totalData,event_size,buffer_handle->lrcvalue); + buffer_handle->data_len += event_size; + }else{ //异常帧 + printf("error event_size %d , should <= %d\n",event_size, (buffer_handle->totalDataLen + sizeof(msg_header_t) + 1 - buffer_handle->data_len) ); + + } + } //如果包完整接收,进行crc校验 - if(buffer_handle->data_len == buffer_handle->totalDataLen) + if( (buffer_handle->totalDataLen + sizeof(msg_header_t) + 1 ) == buffer_handle->data_len ) { + //我们认为最后一个包,应该不包含其他包,因此其最后一位,应当就是crc值,因此可直接获取crc值 + buffer_handle->crcvalue = buffer_handle->data[buffer_handle->data_len - 1];//获取crc + //最后一位校验位清0,方便字符串处理 + buffer_handle->data[buffer_handle->data_len - 1] = 0; + //缓存到文件的,处理方法会不同因此单独解决 + if(buffer_handle->buffer_to_file == 1) + { + //先关闭临时文件,然后把文件名给协议解析函数即可。 + if (buffer_handle->tmpfilehandle != NULL) + { + fclose(buffer_handle->tmpfilehandle); + buffer_handle->tmpfilehandle=NULL; + } + } + // #define COMMON_CRC_MSG + //通用回复crc校验结果,不是所有指令都一致,暂时取消,在每个指令内部进行回复 + #ifdef COMMON_CRC_MSG + if (get_crc_from_lrc(buffer_handle->lrcvalue) != buffer_handle->crcvalue) + { + //发送校验失败 + ble_reply_msg(buffer_handle->cmd_header.cmdtype,buffer_handle->cmd_header.cmdid,0); + }else + #endif + { + //协议解析指令 + handle_ble_msg(buffer_handle); + } + //所有操作都完成,要释放 data + if(buffer_handle->data != NULL) + { + free(buffer_handle->data); + buffer_handle->data=NULL; + } + } return ERRCODE_SUCC; } + + void bleDataRecv(uint8_t *totalData, uint16_t event_size,uint16_t handle) { @@ -4952,19 +5377,37 @@ void bleDataRecv(uint8_t *totalData, uint16_t event_size,uint16_t handle) return; } printf("bleDataRecv handle:%d\r\n",handle); - + int last_unused_handle_index = -1; + int handle_index_found = -1; for(int i = 0;i=0 && handle_index_found == -1) + { + handle_index_found = last_unused_handle_index; + } + + if(handle_index_found>=0) + { + printf("handle_index_found:index %d addr %X\r\n",handle_index_found,&handle_l[handle_index_found]); + handle_l[handle_index_found].handle = handle; + combine_data_internal(&handle_l[handle_index_found],totalData,event_size); + } + else + printf("no empty handle_l found! skip this msg!\n"); + + } void free_ble_data(void)//以防断开蓝牙没有释放数据类型 @@ -4980,20 +5423,34 @@ void free_ble_data(void)//以防断开蓝牙没有释放数据类型 } #else -typedef struct + + + +//长数据解析 +void bleLongRecvData(uint8_t *data, uint16_t data_size,uint8_t *buf_cmd,uint8_t *totalData,uint8_t crcvalue)//buf_cmd 指令前17个字节数据 { - uint8_t *data; - int handle; - int data_len ; - int totalDataLen; - uint8_t cmd_data[17]; - uint8_t crcvalue; -} ble_read_data; + uint8_t type=buf_cmd[1]; + printf("type:%d %d data_size:%d data:%x crcvalue:%x\r\n",buf_cmd[0],type,data_size,data,crcvalue); + + switch (type) + { + case 0x02://获取手机信息 + type2AE4Data(buf_cmd,data,data_size,totalData,crcvalue); + break; + case 0x01: + type2AE3Data(buf_cmd,data,data_size,totalData,crcvalue); + break; + case 0x03:// + type2AE1Data(buf_cmd,data,data_size,totalData,crcvalue); + break; + case 0x04: + break; + default: + break; + } +} + -#define MAX_HANDLE_NUM 10 -//LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus) -//根据特征值分开组合读取的数据,并处理 -static ble_read_data handle_l[MAX_HANDLE_NUM]={0}; void bleDataRecv(uint8_t *totalData, uint16_t event_size,uint16_t handle) { diff --git a/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.h b/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.h index 7321c58ad..cc5d552fc 100644 --- a/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.h +++ b/code/sdk/application/wearable/service/ble_service/bleservice/bleEvent.h @@ -95,11 +95,15 @@ void cameram_send_data(void); #define FIND_PHONE_CMD 0x0501 //同步睡眠历史数据 -#define USE_PROTOCOL_EN_DE_BY_SNICKER 0 +#define USE_PROTOCOL_EN_DE_BY_SNICKER 1 #if USE_PROTOCOL_EN_DE_BY_SNICKER + + #define MSG_DIRECTION_RECV 0x73 -#define MSG_DIRECTION_SEND 0x71 +#define MSG_DIRECTION_SEND 0x72 + +#define MAX_INTERVAL_MS_BETWEEN_2_CMD 50 // 50ms 在一个分包里,如果多个指令间超过50ms,则认为分包失败 /*******************data structure*************************/ @@ -132,6 +136,12 @@ typedef struct uint8_t crc; //校验位 数据包后最后一位 }msg_data_t; + +errcode_t ble_reply_cmd(uint16_t msg_cmd,uint8_t replydata); +errcode_t ble_reply_cmdarr(uint16_t msg_cmd,uint8_t *replydata,uint16_t replydata_len); +errcode_t ble_reply_msg(uint8_t msg_cmdtype,uint8_t msg_cmdid,uint8_t replydata); +errcode_t ble_reply_msgarr(uint8_t msg_cmdtype,uint8_t msg_cmdid,uint8_t *replydata,uint16_t replydata_len); + #endif #pragma pack(1) typedef struct @@ -537,6 +547,13 @@ typedef struct /****************OTA******************************************/ #define OTA_FILE_RECV_CMD 0x0420 +#define MP3_FILE_RECV_CMD 0x0421 +#define DIAL_FILE_RECV_CMD 0x0422 +#define FILE_CHECKSUM_RECV_CMD 0x0423 +#define SINGLE_DIAL_FILE_RECV_CMD 0x0424 +#define EPO_DATA_RECV_CMD 0x0425 +#define FILE_RECV_REPLY_STAT_CMD 0x0520 + /***********************长指令>20字节****************************************/ /*******************TYPE+ID**********************/ @@ -647,14 +664,20 @@ typedef struct typedef struct { - uint8_t ota_type; - uint32_t ota_size; + uint8_t file_type; //1 ota file , 2 mp3 file , 3 dial file, 7 epo file + uint32_t file_size; uint8_t ota_major; uint8_t ota_mid; uint8_t ota_minor; - uint8_t ota_isforced; - char *ota_name; -}ota_file_struct_t; + uint8_t ota_isforced; + char* file_name; + FILE* file; + uint32_t received_size; + uint8_t lrcvalue;//crc 校验算子 + int recv_file_stat; //0 not start , 1 reciving , -1 error or stop , 2 success +} file_recv_stat_t; + + @@ -662,9 +685,9 @@ typedef struct void revBleOldData(uint8_t *buf, uint16_t event_size,uint16_t handle);//协议接收client下发的数据接口 //02类型的指令数据 -void type2AE3Data(uint8_t *cmd_buf ,uint8_t *data,uint16_t datalen,uint8_t *totaldata,uint8_t crcvalue);//对不同指令ID进行区分 +// void type2AE3Data(uint8_t *cmd_buf ,uint8_t *data,uint16_t datalen,uint8_t *totaldata,uint8_t crcvalue);//对不同指令ID进行区分 void type2AE1Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *totalData,uint8_t crcvalue); -void type2AE0Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *totalData,uint8_t crcvalue); +// void type2AE0Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *totalData,uint8_t crcvalue); void type2AE4Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *totalData,uint8_t crcvalue); void type2AE5Data(uint8_t *buf_cmd,uint8_t *data,uint16_t datalen,uint8_t *totalData,uint8_t crcvalue); diff --git a/code/sdk/drivers/peripheral/utils/custom_cmd_service.c b/code/sdk/drivers/peripheral/utils/custom_cmd_service.c index 41bba1377..ee0be8ca6 100644 --- a/code/sdk/drivers/peripheral/utils/custom_cmd_service.c +++ b/code/sdk/drivers/peripheral/utils/custom_cmd_service.c @@ -125,8 +125,11 @@ static void custom_cmd_service_check_task(void const *arg) UnbindSucessCmd(1);//1确认解绑 uapi_delete_files(); uapi_reboot_device(); - } - break; + } + break; + case CUSTOM_CMD_MSG_TYPE_STARTOTA: + uaip_cmd_update_request(); + break; default: PRINT("Unknown CUSTOM_CMD_MSG cmd 0x%02X \r\n", mail.cmd); break; diff --git a/code/sdk/drivers/peripheral/utils/custom_utils.h b/code/sdk/drivers/peripheral/utils/custom_utils.h index 4fe064a8b..3827aa180 100644 --- a/code/sdk/drivers/peripheral/utils/custom_utils.h +++ b/code/sdk/drivers/peripheral/utils/custom_utils.h @@ -156,6 +156,7 @@ uint32_t uapi_calendar_store_date(void); #define CUSTOM_CMD_MSG_TYPE_CHANGE_CALL_VOLUME 0x03 #define CUSTOM_CMD_MSG_TYPE_REMOVE_CAT1VOTE 0x04 #define CUSTOM_CMD_MSG_TYPE_RESTORE_FACTORY_SETTING 0x05 +#define CUSTOM_CMD_MSG_TYPE_STARTOTA 0x06 errcode_t uapi_custom_cmd_service_init(void); void do_custom_cmd_service_check_msg(int cmd, void *params, int paramlen);