}
static uint8_t file_count=0;
-
static uint8_t file_index=1;
-
+/*****************************************************************************
+ * 函数功能:统计 TAR_PATH 目录下的文件总数
+ * 全局变量:file_count = 文件总数
+ * file_index = 重置为 1
+ ****************************************************************************/
void get_tar_dir_file_count(void)
{
- char dir_path[128]={0};
- sprintf_s(dir_path,128,"%s",TAR_PATH);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"TAR_PATH %s\r\n",dir_path);
- struct DIR *dir;
- struct dirent *ent;
+ char dir_path[128] = {0};
+ DIR *dir = NULL;
+ struct dirent *ent = NULL;
-
- file_count=0;
+ // 拼接目录路径
+ sprintf_s(dir_path, sizeof(dir_path), "%s", TAR_PATH);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[dir count] path: %s\r\n", dir_path);
+
+ // 初始化计数
+ file_count = 0;
+ file_index = 1;
- if ((dir = opendir(dir_path)) != NULL)
+ // 打开目录
+ dir = opendir(dir_path);
+ if (dir == NULL)
{
- while ((ent = readdir(dir)) != NULL)
- {
- std::string fileName = ent->d_name;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[dir count] opendir failed\r\n");
+ return;
+ }
- if (fileName != "." && fileName != "..")
- {
-
- if (ent->d_type == DT_REG || ent->d_type == DT_UNKNOWN ) // 普通文件
- {
- //if(strstr(fileName.c_str(),".tar"))
- file_count++;
+ // 遍历目录
+ while ((ent = readdir(dir)) != NULL)
+ {
+ std::string file_name = ent->d_name;
- }
- }
- else if (ent->d_type == DT_DIR) // 目录
- {
- continue;
- }
+ // 跳过 . 和 ..
+ if (file_name == "." || file_name == "..")
+ {
+ continue;
+ }
+
+ // 只统计普通文件
+ if (ent->d_type == DT_REG || ent->d_type == DT_UNKNOWN)
+ {
+ file_count++;
}
- closedir(dir);
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"enenenenen \r\n");
}
- file_index=1;
- return;
-}
+ // 关闭目录
+ closedir(dir);
+ dir = NULL;
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[dir count] total files: %d\r\n", file_count);
+}
+/*****************************************************************************
+ * 函数功能:删除指定文件
+ * 参数:tar_path - 文件路径
+ * 返回值:1=成功,0=失败
+ ****************************************************************************/
uint32_t tar_rmove(char *tar_path)
{
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"remove %s\r\n",tar_path);
- if(0==remove(tar_path))
- return 1;
+ if (tar_path == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_rmove] path is NULL\r\n");
+ return 0;
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_rmove] remove file: %s\r\n", tar_path);
+
+ // 删除文件
+ if (remove(tar_path) == 0)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_rmove] remove success\r\n");
+ return 1;
+ }
else
- return 0;
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_rmove] remove failed\r\n");
+ return 0;
+ }
}
-
-char * tar_dir_to_json_buf_malloc_(char* file_name,uint32_t *file_size)
+/*****************************************************************************
+ * 函数功能:读取目录第一个文件 → 拼装成JSON并返回malloc的字符串
+ * 参数:file_name - 输出:文件完整路径
+ * file_size - 输出:文件大小
+ * 返回值:malloc的JSON字符串(需要外部free),NULL=失败
+ ****************************************************************************/
+char *tar_dir_to_json_buf_malloc_(char *file_name, uint32_t *file_size)
{
- char dir_path[256]={0};
- sprintf_s(dir_path,256,"%s",TAR_PATH);
+ // 入参检查
+ if (file_name == NULL || file_size == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_dir] param NULL\r\n");
+ return NULL;
+ }
- cJSON *dataJSON = cJSON_CreateObject();
- cJSON* data_arryJSON = cJSON_CreateArray();
+ char dir_path[256] = {0};
+ sprintf_s(dir_path, sizeof(dir_path), "%s", TAR_PATH);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[tar_dir] open dir: %s\r\n", dir_path);
- struct DIR *dir;
- struct dirent *ent;
-
- if ((dir = opendir(dir_path)) != NULL)
+ cJSON *rootJSON = cJSON_CreateObject();
+ if (rootJSON == NULL)
{
- while ((ent = readdir(dir)) != NULL)
- {
- std::string fileName = ent->d_name;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_dir] create json fail\r\n");
+ return NULL;
+ }
- if (fileName != "." && fileName != "..")
- {
- if (ent->d_type == DT_REG || ent->d_type == DT_UNKNOWN ) // 普通文件
- {
-
- //*file_size=ent->d_reclen;
- char file_path[300]={0};
- sprintf_s(file_path,256,"%s/%s",TAR_PATH,ent->d_name);
-
- FILE * fp = fopen(file_path,"rb+");
- if(fp==NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP," fopen fail %s\r\n",file_path);
- return NULL;
- }
- if (fp != NULL)
- {
- fseek(fp, 0, SEEK_END); // 将文件指针移动到文件末尾
- *file_size = ftell(fp); // 获取当前文件指针位置,即文件大小
- fseek(fp, 0, SEEK_SET); // 将文件指针移回文件开头
- }
- fclose(fp);
+ // 打开目录
+ DIR *dir = opendir(dir_path);
+ if (dir == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_dir] opendir failed\r\n");
+ cJSON_Delete(rootJSON);
+ return NULL;
+ }
+ struct dirent *ent;
+ char *json_str = NULL;
- memcpy(file_name,file_path,strlen(file_path));
- uint8_t crc= Calculate_CRC_file(file_name);
+ // 遍历目录
+ while ((ent = readdir(dir)) != NULL)
+ {
+ std::string fileName = ent->d_name;
- cJSON* itemJSON = cJSON_CreateObject();
+ // 跳过 . 和 ..
+ if (fileName == "." || fileName == "..")
+ continue;
- cJSON_AddNumberToObject(itemJSON,"index",file_index);
- cJSON_AddNumberToObject(itemJSON,"count",file_count);
+ // 只处理普通文件
+ if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN)
+ continue;
- cJSON_AddNumberToObject(itemJSON,"crc",crc);
+ // 拼接文件路径
+ char file_path[300] = {0};
+ sprintf_s(file_path, sizeof(file_path), "%s/%s", TAR_PATH, ent->d_name);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[tar_dir] find file: %s\r\n", file_path);
- cJSON_AddStringToObject(itemJSON,"name",fileName.c_str());
- cJSON_AddNumberToObject(itemJSON,"size",*file_size);
+ // 打开文件获取大小
+ FILE *fp = fopen(file_path, "rb");
+ if (fp == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_dir] fopen failed: %s\r\n", file_path);
+ continue;
+ }
- char *json_format = cJSON_PrintUnformatted(itemJSON);
-
- int pSize = cJSON_GetArraySize(dataJSON);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"文件数据:%s\r\n",json_format);
- cJSON_Delete(dataJSON);
- file_index++;
+ fseek(fp, 0, SEEK_END);
+ *file_size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ fclose(fp);
- return json_format;
+ // 输出文件路径给外部
+ memcpy(file_name, file_path, strlen(file_path));
- //cJSON_AddItemReferenceToArray(data_arryJSON,itemJSON);
+ // 计算CRC
+ uint8_t crc = Calculate_CRC_file(file_name);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[tar_dir] file crc: %d, size: %d\r\n", crc, *file_size);
- }
- else if (ent->d_type == DT_DIR) // 目录
- {
- continue;
- }
+ // 创建JSON
+ cJSON *itemJSON = cJSON_CreateObject();
+ cJSON_AddNumberToObject(itemJSON, "index", file_index);
+ cJSON_AddNumberToObject(itemJSON, "count", file_count);
+ cJSON_AddNumberToObject(itemJSON, "crc", crc);
+ cJSON_AddStringToObject(itemJSON, "name", fileName.c_str());
+ cJSON_AddNumberToObject(itemJSON, "size", *file_size);
- }
+ // 生成JSON字符串
+ json_str = cJSON_PrintUnformatted(itemJSON);
+ cJSON_Delete(itemJSON);
- }
- closedir(dir);
- }
- else
- {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[tar_dir] json: %s\r\n", json_str);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"opendir fail\r\n");
+ // 只取第一个文件就返回(原逻辑)
+ file_index++;
+ break;
}
- cJSON_Delete(dataJSON);
- cJSON_Delete(data_arryJSON);
-
- return NULL;
-}
-
-
-
+ closedir(dir);
+ cJSON_Delete(rootJSON);
+ return json_str;
+}
void add_addressbookToRead(char *data)
{
-
SAFE_CALL(bleInstruct_t.add_addressbookToRead, data);
}
uint8_t vibration=data[5];
uint8_t notify=data[6];
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"设置步数:%d %d %d %d \r\n",targetStep,ringOn,vibration,notify);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"设置步数:%d %d %d %d \r\n",targetStep,ringOn,vibration,notify);
set_goal_stepcount(targetStep);
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[install_dial] 表盘安装流程全部完成,返回成功\n");
return ERRCODE_SUCC;
}
-static char file_name[128]={0};
-static uint32_t file_size=0;
-
-bool Read_tar_file_buf_send_Data(uint16_t pack_size,uint8_t id)
-{
-
- char *data= (char *)malloc(pack_size+1);
- uint16_t read_size=0;
- FILE *fp=fopen(file_name,"rb+");
-
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,"Read_tar_file_buf_send_Data size %d\r\n",file_size);
-
- uint32_t pack=file_size/pack_size+1;
- uint32_t pack_id=1;
- if(fp==NULL)
- {
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,"fopen fail %s\r\n",file_name);
- free(data);
- return false;
- }
-
- do
- {
- memset_s(data,pack_size+1,0,pack_size+1);
- read_size=fread(data,1,pack_size,fp);
- if(read_size!=0)
- {
- ble_data_type type_={0x05,id,file_size,pack,pack_id};
- send_big_data(type_,(char *)data,read_size);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Read_tar_file_buf_send_Data size %d\r\n",read_size);
- }
-
-
- //send_big_data(1,data,read_size,file_size,pack_id,pack,id,5);
- pack_id++;
-
- } while (read_size==pack_size);
- free(data);
- fclose(fp);
- sendbigDataBufState = false;
- return true;
-}
-
void delete_app(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t crcvalue)
{
}
-bool read_dir_send_json()
+static char file_name[128]={0};
+static uint32_t file_size=0;
+/*****************************************************************************
+ * 函数功能:读取目标目录文件列表 → 转为JSON → 通过BLE分包发送
+ * 返回值:true = 成功
+ * false = 失败(内存申请失败/目录为空)
+ ****************************************************************************/
+bool read_dir_send_json(void)
{
-
- char *send_buf=NULL;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"read_dir_send_json xxxxxxxx\r\n");
- memset_s(file_name,128,0,128);
- send_buf=tar_dir_to_json_buf_malloc_(file_name,&file_size);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"read_dir_send_json end\r\n");
- if( send_buf!=NULL)
+ char *send_buf = NULL;
+ uint32_t json_len = 0;
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "read_dir_send_json start\r\n");
+
+ /* 清空文件名缓冲区 */
+ memset_s(file_name, 128, 0, 128);
+
+ /* 将目录内容转为JSON,并申请内存 */
+ send_buf = tar_dir_to_json_buf_malloc_(file_name, &file_size);
+ if (send_buf == NULL)
{
- //send_big_data(1,send_buf,strlen(send_buf),strlen(send_buf),1,1,0x26,0x04);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "tar_dir_to_json_buf_malloc_ failed\r\n");
+ return false;
+ }
- ble_data_type type_={0x04,0x26,strlen(send_buf),1,1};
-
- send_big_data(type_,(char *)send_buf,strlen(send_buf));
+ json_len = strlen(send_buf);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "json len: %d\r\n", json_len);
- free(send_buf);
- return true;
+ /* 配置BLE发送参数 */
+ ble_data_type type_param = {0x04,0x26,json_len,1,1};
+ /* BLE大数据分包发送 */
+ send_big_data(type_param, send_buf, json_len);
+
+ /* 释放内存 */
+ free(send_buf);
+ send_buf = NULL; // 防止野指针
+
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "read_dir_send_json success\r\n");
+ return true;
+}
+/*****************************************************************************
+ * 函数功能:读取目标文件并按分包大小通过BLE大数据发送
+ * 参数:pack_size - 每包数据长度
+ * id - 命令ID
+ * 返回值:true 发送成功
+ * false 打开文件失败
+ ****************************************************************************/
+bool Read_tar_file_buf_send_Data(uint16_t pack_size, uint8_t id)
+{
+ // 申请内存
+ char *data_buf = (char *)malloc(pack_size + 1);
+ if (data_buf == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "malloc failed\r\n");
+ return false;
}
- else
+
+ // 打开文件
+ FILE *fp = fopen(file_name, "rb");
+ if (fp == NULL)
{
- return false;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "fopen failed: %s\r\n", file_name);
+ free(data_buf);
+ return false;
}
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "file_size: %d\r\n", file_size);
+
+ // 计算总包数
+ uint32_t total_pack = file_size / pack_size + 1;
+ uint32_t current_pack = 1;
+ uint16_t read_len = 0;
+
+ // 循环分包读取并发送
+ do
+ {
+ memset_s(data_buf, pack_size + 1, 0, pack_size + 1);
+ read_len = fread(data_buf, 1, pack_size, fp);
+
+ if (read_len > 0)
+ {
+ ble_data_type type_param = { 0x05, id, file_size, total_pack,current_pack};
+ send_big_data(type_param, data_buf, read_len);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "send pack: %d, len: %d\r\n", current_pack, read_len);
+ }
+
+ current_pack++;
+
+ } while (read_len == pack_size);
+
+ // 资源释放
+ fclose(fp);
+ free(data_buf);
+ data_buf = NULL;
+
+ sendbigDataBufState = false;
+
+ return true;
}
// 蓝牙文件传输完成后的校验与结果处理核心函数(指令码2AE6对应文件校验场景)
void type2AE0Data(ble_read_data *buffer_handle)
{
- uint16_t typeID = buffer_handle->cmd_header.cmdtype*256 + buffer_handle->cmd_header.cmdid;
-
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,"type2AE0Data typeID:0x%04X datalen %d\r\n",typeID,buffer_handle->totalDataLen);
-
- bool checkcrc = (get_crc_from_lrc(buffer_handle->lrcvalue) == buffer_handle->crcvalue);
+ // 1. 校验入参
+ if (buffer_handle == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "type2AE0Data: buffer_handle is NULL\r\n");
+ return;
+ }
+
+ // 2. 计算命令类型ID
+ uint16_t typeID = (buffer_handle->cmd_header.cmdtype * 256) + buffer_handle->cmd_header.cmdid;
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "type2AE0Data typeID:0x%04X, datalen:%d\r\n",
+ typeID, buffer_handle->totalDataLen);
+
+ // 3. CRC校验(Android方向直接跳过校验)
+ bool crc_ok = (get_crc_from_lrc(buffer_handle->lrcvalue) == buffer_handle->crcvalue);
+ bool is_android_msg = (buffer_handle->cmd_header.direction == MSG_DIRECTION_RECV_ANDROID);
- uint32_t num;
- if ( (checkcrc == true ) ||
- (buffer_handle->cmd_header.direction == MSG_DIRECTION_RECV_ANDROID))
+ if (!crc_ok && !is_android_msg)
{
- switch (typeID) //ID
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "type2AE0Data CRC failed!\r\n");
+ return;
+ }
+
+ // 4. 根据命令ID分发处理
+ switch (typeID)
+ {
+ case OTA_FILE_RECV_CMD:
{
- case OTA_FILE_RECV_CMD://
- {
- 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:
- {
- if (decode_mp3_json( buffer_handle) == ERRCODE_SUCC)
- {
- ble_reply_cmd(MP3_FILE_RECV_CMD,1);
- }else{
- ble_reply_cmd(MP3_FILE_RECV_CMD,2);
- }
- }
- break;
- case DIAL_FILE_RECV_CMD:
- {
- if (decode_dial_info( buffer_handle) == ERRCODE_SUCC)
- {
-
- //if(ble_dial_uid >=5 &&
- // if(get_dial_num()>=MAX_BLE_EVENT_DIAL_NUM)
- // {
- // ble_reply_cmd(DIAL_FILE_RECV_CMD,3);
+ uint8_t res = decode_ota_json(buffer_handle) ? 2 : 1;
+ ble_reply_cmd(OTA_FILE_RECV_CMD, res);
+ break;
+ }
- // }
- //else
- {
-
- ble_reply_cmd(DIAL_FILE_RECV_CMD,1);
- }
-
- }else{
- ble_reply_cmd(DIAL_FILE_RECV_CMD,2);
- }
- }
- break;
- case FILE_CHECKSUM_RECV_CMD:
- decode_file_checksum(buffer_handle);
- break;
- case SINGLE_DIAL_FILE_RECV_CMD:
- if (decode_single_dial_info(buffer_handle) == ERRCODE_SUCC)
- {
- ble_reply_cmd(SINGLE_DIAL_FILE_RECV_CMD,1);
- } else {
- ble_reply_cmd(SINGLE_DIAL_FILE_RECV_CMD,2);
- }
- break;
- case EPO_DATA_RECV_CMD:
- break;
- case APP_INAUIRE_EXC_FILE_CMD:
- get_tar_dir_file_count();
+ case MP3_FILE_RECV_CMD:
+ {
+ uint8_t res = decode_mp3_json(buffer_handle) ? 2 : 1;
+ ble_reply_cmd(MP3_FILE_RECV_CMD, res);
+ break;
+ }
- if(!read_dir_send_json())
- {
- ble_reply_cmd(APP_INAUIRE_EXC_FILE_CMD,2);
- }
- break;
-
- case APP_START_SEND_EXC_FILE_CMD:
- num=(ble_nus_max_data_len-18);
- if(num>482)num=482;
- if(!Read_tar_file_buf_send_Data(num,0x63))
- {
- ble_reply_cmd(APP_START_SEND_EXC_FILE_CMD,2);
- }
- break;
- case APP_SEND_EXC_FILE_END_CMD:
- if(!tar_rmove(file_name))
- {
- ble_reply_cmd(APP_SEND_EXC_FILE_END_CMD,2);
- }
- if(!read_dir_send_json())
- {
- ble_reply_cmd(APP_SEND_EXC_FILE_END_CMD,2);
- }
+ case DIAL_FILE_RECV_CMD:
+ {
+ if (decode_dial_info(buffer_handle) != ERRCODE_SUCC)
+ {
+ ble_reply_cmd(DIAL_FILE_RECV_CMD, 2);
break;
-
+ }
- default:
- break;
+ // 预留表盘数量判断逻辑
+ ble_reply_cmd(DIAL_FILE_RECV_CMD, 1);
+ break;
}
-
- }else{
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,"type2AE0Data CRC failed!\n");
+
+ case FILE_CHECKSUM_RECV_CMD:
+ decode_file_checksum(buffer_handle);
+ break;
+
+ case SINGLE_DIAL_FILE_RECV_CMD:
+ {
+ uint8_t res = decode_single_dial_info(buffer_handle) ? 2 : 1;
+ ble_reply_cmd(SINGLE_DIAL_FILE_RECV_CMD, res);
+ break;
+ }
+
+ case EPO_DATA_RECV_CMD:
+ // 暂未实现
+ break;
+
+ case APP_INAUIRE_EXC_FILE_CMD:
+ get_tar_dir_file_count();
+ if (!read_dir_send_json())
+ {
+ ble_reply_cmd(APP_INAUIRE_EXC_FILE_CMD, 2);
+ }
+ break;
+
+ case APP_START_SEND_EXC_FILE_CMD:
+ {
+ uint32_t send_len = ble_nus_max_data_len - 18;
+ if (send_len > 482)
+ {
+ send_len = 482;
+ }
+
+ if (!Read_tar_file_buf_send_Data(send_len, 0x63))
+ {
+ ble_reply_cmd(APP_START_SEND_EXC_FILE_CMD, 2);
+ }
+ break;
+ }
+
+ case APP_SEND_EXC_FILE_END_CMD:
+ if (!tar_rmove(file_name) || !read_dir_send_json())
+ {
+ ble_reply_cmd(APP_SEND_EXC_FILE_END_CMD, 2);
+ }
+ break;
+
+ default:
+ break;
}
-
}
//
void type2AE6Data(ble_read_data *buffer_handle,uint8_t *cmd_buf ,uint8_t *data,uint16_t datalen,uint8_t *totaldata,uint8_t crcvalue)