/* * ┌─────────────────────────────────────────────────────────────┐ * │┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐│ * ││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" #include /** * @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, rt_uint8_t (*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, rt_uint8_t *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 rt_uint8_t *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 {*} 打包后数据总长度 */ rt_uint8_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); LOG_I("ROW = %d",row); // rt_uint8_t packdata[row][200]; // 打包后数据 rt_uint8_t tlen[row]; // 打包后数据各维长度 // static rt_uint8_t index = 0; // rt_uint8_t in[len]; // memcpy(in,din,len); cfg->fallpiece[0]=row; rt_uint8_t tmplen = 0; size_t var=0; for (rt_uint8_t index = 0; index< row;index++) { // rt_uint8_t tmplen = w; // 当前待打包数据的长度 tmplen = (len - var) > w ? w : (len - var); // 判断最后一包数据的长度 cfg->fcurpiece[0] = index+1; rt_uint8_t col = packMsg(cfg, din+var, tmplen, dout[index]); arrlen[index] = col; // index++; var += w; LOG_D("index/row-var-tmplen"); LOG_D("%5d/%3d-%3d-%6d",index,row,var,tmplen); LOG_HEX("per msg",27,dout[index],col); // LOG_D("--------"); 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 */ rt_uint8_t pack_File(const char *fin, rt_uint8_t flag, const rt_uint8_t (*dout)[200], rt_uint8_t *arrLen) { static 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 rt_uint8_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_NULL ; buffer = rt_malloc(file_size); if (buffer == RT_NULL) { LOG_E("No memory for read %s.",fin); return 0; } 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)); len = packMsgs(&cfg, buffer, file_size, flen, dout, arrLen); 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."); } // LOG_D("%p--%p",dout,arrLen); return len; } static char d[40][200]; static char s[40]; // static rt_uint8_t *buffer = RT_NULL; // static MSG cfg; static int pf_thread_entry(void* parameter) { char *f = (char *) parameter; // static char d[5][200]; // static char s[5]; rt_uint8_t *buffer = RT_NULL; static MSG cfg; static rt_uint8_t len=0; // len = pack_File(f, 0, d, s); #define DEMO #ifdef DEMO { // rt_memset(&cfg, 0, sizeof(MSG)); // 分配空间 rt_uint8_t rst = packInit(&cfg, f, 0); 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; static size_t flen = 150; // 每包数据初始长度,最大不超过 FRAME_DATA_LEN_MAX // rt_uint8_t len = 0; fd_in = open(f, O_RDONLY, 0); if (fd_in < 0) { LOG_E("open the input file : %s error!\n", f); 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); // static rt_uint8_t *buffer = RT_NULL; buffer = rt_malloc(file_size); if (buffer == RT_NULL) { LOG_E("No memory for read %s.", f); return 0; } read(fd_in, buffer, file_size); // LOG_HEX() close(fd_in); // 粗略调整每包大小 if (file_size > (size_t)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("flen is %d",flen); // s[0] = packMsg(&cfg, buffer, flen, d[0]); len = packMsgs(&cfg, buffer, file_size, flen, d, s); 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."); } } #endif rt_kprintf("len is %d\n", len); if (len) { for (size_t var = 0; var < len; var++) { LOG_D("i = %d",var); LOG_HEX("d", 27, d[var], s[var]); } LOG_I("Done."); } return RT_EOK; } static int 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 * 20, 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"); } return 0; } #include MSH_CMD_EXPORT(pmsg, 打包文件。); void pwTT_thread_entry(void *parameter) { // LOG_I("--%s--",parameter); if (parameter == NULL) { int f = rt_pin_read(TT_EN); rt_pin_write(TT_EN, !f); LOG_I("set TT %s",!f?"ON":"OFF"); } else { rt_bool_t flag = (rt_bool_t)parameter; rt_pin_write(TT_EN, flag); LOG_I("set TT %s",flag?"ON":"OFF"); } } static int swTT(int argc, char **argv) { int f = NULL;//不带参数时argv[1]为NULL if (argc == 2) { f = atoi(argv[1]); } /* 创建线程 */ rt_thread_t thread = rt_thread_create("sw_TT", pwTT_thread_entry, (void *) f, 1024 * 1, 25, 10); /* 创建成功则启动线程 */ if (thread != RT_NULL) { rt_thread_startup(thread); } else { LOG_E("thread 'sw_TT' create failure."); return RT_ERROR; } } MSH_CMD_EXPORT(swTT, 切换TT电源。不带参切换电源状态,支持参数);