/* * ┌─────────────────────────────────────────────────────────────┐ * │┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐│ * ││Esc│!1 │@2 │#3 │$4 │%5 │^6 │&7 │*8 │(9 │)0 │_- │+= │|\ │`~ ││ * │├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤│ * ││ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{[ │}] │ BS ││ * │├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤│ * ││ Ctrl │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter ││ * │├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────┬───┤│ * ││ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│Shift │Fn ││ * │└─────┬──┴┬──┴──┬┴───┴───┴───┴───┴───┴──┬┴───┴┬──┴┬─────┴───┘│ * │ │Fn │ Alt │ Space │ Alt │Win│ HHKB │ * │ └───┴─────┴───────────────────────┴─────┴───┘ │ * └─────────────────────────────────────────────────────────────┘ */ /* * @Author: murmur test@test.com * @Date: 2023-05-05 10:07:30 * @LastEditors: murmur test@test.com * @LastEditTime: 2023-05-11 16:34:31 * @FilePath: \TT12-MCU\applications\ttmsg\ttmsg.c * @Description: * * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. */ // #include #define LOG_TAG "ttmsg" #define LOG_LVL LOG_LVL_DBG #include #include "ttmsg.h" /** * @brief 按指定分隔符分割字符串 * * @param str 待分割字符串 * @param deli 分隔符 * @param out 输出字符串数组 * @return size_t 分割后字符串个数 */ #ifdef USE_STRTOK static size_t split(const char *str, const char *deli, char (*out)[STR_LEN_MAX]) { char buf[50]; strcpy(buf, str); // strtok会修改字符串 char *token = strtok(buf, deli); char *rst[STR_LEN_MAX]; size_t i = 0; while (token) { rst[i++] = token; token = strtok(NULL, deli); } // 更新out for (size_t ii = 0; ii < i; ii++) { // out[ii] = id[ii]; strcpy(out[ii], rst[ii]); } return i; } #else // strtok_r版本 static size_t split(const char *str, const char *delim, char (*out)[STR_LEN_MAX]) { char buf[50]; strcpy(buf, str); // strtok会修改字符串 char *token = NULL; char *saveptr = NULL; char *rst[STR_LEN_MAX]; int idx = 0; token = strtok_r(buf, delim, &saveptr); while (token) { LOG_D("---%s---",token); rst[idx++] = token; token = strtok_r(NULL, delim, &saveptr); } // 更新out for (size_t ii = 0; ii < idx; ii++) { // out[ii] = id[ii]; strcpy(out[ii], rst[ii]); } return idx; } #endif /** * @brief 从文件名字符串提取ID * * @param fin 文件名,支持路径 * @param out 提取结果 * @return size_t ID长度 */ static size_t getID(const char *str, unsigned char *out) { char id[10][STR_LEN_MAX] = {}; // 分割路径 size_t len = split(str, "/", id); // 分割后缀 LOG_D("file is %s",id[len-1]); len = split(id[len - 1], ".", id); // 分割时间 LOG_D("file name is %s",id[0]); len = split(id[0], "_", id); unsigned char tmp[len]; for (size_t i = 0; i < len; i++) { unsigned int v = atoi(id[i]); // 去除代表20的2000 if (v > 0xff) { v = v - 2000; } tmp[i] = v; } LOG_HEX("file ID",16,tmp,len); memcpy(out, tmp, len); return len; } /** * @brief 根据配置初始化MSG * @param *tpl MSG结构体 * @param fin 文件名,由时间戳和随机码组成,作为数据包唯一ID * @param flag 参数配置,如信息类型、压缩方式、加密方式等 * @return 成功返回0 */ rt_uint8_t packInit(MSG *tpl, const char *fin, rt_uint8_t flag) { // memset(tpl, 0, sizeof(MSG)); // 分配空间 // 模板 MSG msgs_tpl = { .fstart = {0x88, 0xAA, 0xBB, 0x88}, .fnum = {0x00, 0x01}, .fbak = {0x00, 0x02}, .ftype = { 0x70, 0x21}, .fdlen = {0x00, 0x00}, .ftccid = {0x37, 0x32, 0x32, 0x32}, .fcfg = flag, }; rt_memcpy(tpl, &msgs_tpl, sizeof(MSG)); size_t len = getID(fin, tpl->findex); if (len != 7) { LOG_E("file name %s format error", fin); return RT_ERROR; } return RT_EOK; } /** * @description: 按MSG帧格式拼接din数据后输出到dout * @param *p_msg MSG格式配置文件 * @param {rt_uint8_t} *din 待打包数据 * @param {rt_uint8_t} len 待打包数据长度 * @param {rt_uint8_t} *dout 打包后数据 * @return {*} 打包后数据总长度 */ rt_uint8_t packMsg(MSG *p_msg, rt_uint8_t *din, rt_uint8_t len, rt_uint8_t *dout) { rt_uint8_t fralen = sizeof(MSG) + len; // len of current frame // 计算各字段 p_msg->fdlen[0] = 0; // 单包长度必不会超过0xFF,故高字节始终为0 p_msg->fdlen[1] = fralen - 13; // 总长度-帧头长度 // memcpy(p_msg->findex,id,6); // 将待发数据传入帧数据 rt_memcpy(p_msg->fdata, din, len); // 将打包后帧数据传入buff rt_memcpy(dout, p_msg, fralen); return fralen; } /** * @description: 将din按指定长度w分割,再按MSG帧格式拼接 * @param *cfg MSG格式配置文件 * @param {rt_uint8_t} *din 待打包数据 * @param {rt_uint8_t} len 待打包数据长度 * @param {rt_uint8_t} w 分割长度 * @param {rt_uint8_t} *dout 打包后数据 * @return {*} 打包后数据总长度 */ size_t packMsgs(MSG *cfg, rt_uint8_t *din, size_t len, rt_uint8_t w, rt_uint8_t (*dout)[200], rt_uint8_t *arrlen) { if (!(w > 0)) // 无效长度 { w = len; } rt_uint8_t row = (len / w) + (len % w > 0 ? 1 : 0); // rt_uint8_t packdata[row][200]; // 打包后数据 rt_uint8_t tlen[row]; // 打包后数据各维长度 rt_uint8_t index = 0; // rt_uint8_t in[len]; // memcpy(in,din,len); cfg->fallpiece[0]=row; for (size_t var = 0; var < len;var += w) { size_t tmplen = len - var; // 当前待打包数据的长度 tmplen = tmplen > w ? w : tmplen; // 判断最后一包数据的长度 cfg->fcurpiece[0] = index+1; size_t col = packMsg(cfg, din+var, tmplen, dout[index]); tlen[index] = col; index++; LOG_D("index/row-var-tmplen"); LOG_D("%5d/%3d-%3d-%6d",index,row,var,tmplen); LOG_HEX("per msg",27,dout[index-1],col); LOG_D("--------"); LOG_D("addr is %d",din); rt_thread_mdelay(100); } // for (size_t i = 0; i < row; i++) // { // memcpy(dout[i], packdata[i], tlen[i]); // } memcpy(arrlen, tlen, row); // LOG_D("--addr is %d",din); return row; } size_t demo (uint8_t *din) { size_t s= 1024*10; rt_uint8_t *buf = rt_malloc(s); if (buf!=RT_NULL) { LOG_D("mem ok, addr is %d",buf); LOG_D("addr is %d",rt_memset(buf, 0xab, s)); } else { LOG_E("no mem."); } for (size_t var = 0; var < s; ++ var) { rt_memcpy(buf+var, din+var, 1); } LOG_HEX("buf",16,buf,100); LOG_D("addr is %d",din); if (buf) { rt_free(buf); } return 1; } /** * 将指定文件按帧协议进行切片打包,返回二维数组 * @param *cfg MSG格式配置文件 * @param fin 待打包文件名 * @param flag 配置信息 * @param dout 打包后二维数组 * @param arrlen 打包后二维数组各维数组的长度 * @return */ size_t pack_File(const char *fin, rt_uint8_t flag, char (*dout)[200], char *arrLen) { MSG cfg; rt_memset(&cfg, 0, sizeof(MSG)); // 分配空间 rt_uint8_t rst = packInit(&cfg, fin, flag); if (rst!= RT_EOK) { return 0; } int fd_in = -1; //, fd_out = -1; static size_t file_size = 0; // rt_uint8_t *buffer = RT_NULL; size_t flen = 150; // 每包数据初始长度,最大不超过 FRAME_DATA_LEN_MAX size_t len = 0; fd_in = open(fin, O_RDONLY, 0); if (fd_in < 0) { LOG_E("open the input file : %s error!\n", fin); close(fd_in); return len; } file_size = lseek(fd_in, 0, SEEK_END); LOG_I("file size is %d bytes.",file_size); lseek(fd_in, 0, SEEK_SET); rt_uint8_t *buffer = rt_malloc(file_size); if (buffer == RT_NULL) { LOG_E("No memory for read %s.",fin); return 0; } // rt_uint8_t buffer[file_size]; rt_memset(buffer, 0x00, file_size); read(fd_in, buffer, file_size); close(fd_in); // 粗略调整每包大小 if (file_size > FRAME_DATA_LEN_MAX) { while (file_size % flen < flen / 1.2 && flen < FRAME_DATA_LEN_MAX) // 阈值约83% { flen += 1; } if (file_size % flen < flen / 1.2) { // 到达限制仍不符合要求 flen = 150; while (file_size % flen < flen / 2.5 && flen < FRAME_DATA_LEN_MAX) // 调整阈值为40% { flen += 1; } } } else { flen = file_size; } LOG_I("len of data per pack is %d Bytes.",flen); LOG_I("cnt of packages is %d",(file_size / flen) + (file_size % flen > 0 ? 1 : 0)); // LOG_HEX("BEFORE:",16,buffer,file_size); LOG_D("1-addr is %p",buffer); len = packMsgs(&cfg, buffer, file_size, flen, dout, arrLen); LOG_D("2-addr is %p",buffer); // len = demo(buffer); LOG_D("len is %d",len); LOG_I("file size is %d bytes.",file_size); // LOG_HEX("AFTER:",16,buffer,file_size); LOG_D("addr is %p",buffer); if (fd_in >= 0) { close(fd_in); } if (buffer!=RT_NULL) { LOG_D("try to free buf."); rt_free(buffer); LOG_D("free buf done."); } return len; } void pf_thread_entry(void* parameter) { char *f = (char *) parameter; rt_uint8_t d[50][200]; rt_uint8_t s[50]; size_t len = pack_File(f, 0, d, s); if (len) { LOG_I("Done."); } } void pmsg(int argc, char **argv) { if (argc == 2) { static char c[STR_LEN_MAX]; strcpy(c, argv[1]); /* 创建线程 */ rt_thread_t thread = rt_thread_create("pmsg", pf_thread_entry, (void *) c, 1024 * 30, 25, 10); /* 创建成功则启动线程 */ if (thread != RT_NULL) { rt_thread_startup(thread); // rt_kprintf("done"); } else { LOG_E("thread 'pmsg' create failure."); return RT_ERROR; } } else { rt_kprintf("Usage:\n"); rt_kprintf("pmsg [input_file] pack \"input_file\" \n"); } } #include MSH_CMD_EXPORT(pmsg, 打包文件。);