#include #define LOG_TAG "tool" #define LOG_LVL LOG_LVL_DBG #include //#include #include #include /** * 以HEX显示文件内容 */ void hexFile_thread_entry(void* parameter) { int fd_in = -1; int block_size = 0; char *fin = (char *)parameter; fd_in = open(fin, O_RDONLY, 0); if (fd_in < 0) { LOG_E("[hex] open the input file : %s error.", fin); return RT_ERROR; } size_t file_size = lseek(fd_in, 0, SEEK_END); lseek(fd_in, 0, SEEK_SET); rt_uint8_t *buffer = RT_NULL; #define READ_BUFFER_SIZE 512 buffer = (rt_uint8_t *) malloc(READ_BUFFER_SIZE); rt_kprintf("\n------Start------\n"); LOG_D("size = %d bytes.",file_size); for (size_t i = 0; i < file_size; i += READ_BUFFER_SIZE) { if ((file_size - i) < READ_BUFFER_SIZE) { block_size = file_size - i; } else { block_size = READ_BUFFER_SIZE; } rt_memset(buffer, 0x00, READ_BUFFER_SIZE); read(fd_in, buffer, block_size); LOG_HEX("hex_file",27,buffer,block_size); } rt_free(buffer); close(fd_in); rt_kprintf("------Done.------\n"); } void hexFile(int argc, char **argv) { if (argc == 2) { static char f[30]; rt_strcpy(f,argv[1]); /* 创建线程 */ rt_thread_t thread = rt_thread_create("hex_file", hexFile_thread_entry, (void *) f, 1024 * 2, 25, 10); /* 创建成功则启动线程 */ if (thread != RT_NULL) { rt_thread_startup(thread); } else { LOG_E("thread 'hex_file' create failure."); return RT_ERROR; } } } MSH_CMD_EXPORT(hexFile,以HEX方式显示文件内容); int time2Byte(uint8_t * t) { static time_t now; static struct tm *tm, tm_tmp; now = time(RT_NULL); tm = localtime_r(&now, &tm_tmp); srand((unsigned)now); uint8_t rnd=(uint8_t)rand()%99; uint8_t tmp[]={tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,rnd}; memcpy(t,tmp,sizeof(tmp)); return sizeof(tmp); } char *bytes2str(uint8_t *din, size_t count, int radix, char *sep, char *str); /** * 将当前时间转为字符串,格式如 23_08_27_11_44_42_65 * @param str 字符串buffer * @return 字符串长度 */ char *time2Str(char *str) { uint8_t t[10]; size_t len=time2Byte(t); bytes2str(t, len, 10, "_", str); len = strlen(str); str[len]='\0'; return str; } /* * 获取日期,格式如 23_08_27_11 */ char *date2Str(char *str) { uint8_t t[10]; size_t len=time2Byte(t); bytes2str(t, len, 10, "_", str); // len = strlen(str); str[11]='\0'; return str; } void initDataLogPath(char *logfile) { char rootDir[22] = ROOT_PATH_LOG; mkdir(rootDir, 0); char tstmp[30] = ""; char fn[50] = ""; strcat(fn,rootDir); strcat(fn,"20"); strcat(fn,date2Str(tstmp));//以小时为独立文件 fn[strlen(fn)-3]='\0'; strcat(fn,"/"); mkdir(fn, 0); strcat(fn,tstmp); strcat(fn,".log"); strcpy(logfile,fn); } /* * 获得时戳,格式如 2023-08-27 11-44-42-65 */ char *getTimestmp(char *str) { uint8_t t[10]; size_t len=time2Byte(t); str[0]='\0'; strcat(str,"20"); bytes2str(t, len, 10, "-", str+2); str[10]=' '; len = strlen(str); str[len]='\0'; return str; } void tm2str(int argc, char **argv) { char s[30]; time2Str(s); LOG_I("result is %s",s); getTimestmp(s); LOG_I("result is %s",s); date2Str(s); LOG_I("result is %s",s); } MSH_CMD_EXPORT(tm2str,时间转换为字符串) /** * @brief 将整型数据转换为字符串,支持负数。windows环境下的itoa(= integer to alphanumeric)源码。 * * @param num 待转换数据 * @param str 指向转换结果字符串的指针 * @param radix 进制 * @return char* */ char *int2str(int num, char *str, int radix) { char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 索引表 unsigned unum; // 存放要转换的整数的绝对值,转换的整数可能是负数 int i = 0, j, k; // i用来指示设置字符串相应位,转换之后i其实就是字符串的长度;转换后顺序是逆序的,有正负的情况,k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。 // 获取要转换的整数的绝对值 if (radix == 10 && num < 0) // 要转换成十进制数并且是负数 { unum = (unsigned)-num; // 将num的绝对值赋给unum str[i++] = '-'; // 在字符串最前面设置为'-'号,并且索引加1 } else unum = (unsigned)num; // 若是num为正,直接赋值给unum // 转换部分,注意转换后是逆序的 do { str[i++] = index[unum % (unsigned)radix]; // 取unum的最后一位,并设置为str对应位,指示索引加1 unum /= radix; // unum去掉最后一位 } while (unum); // 直至unum为0退出循环 str[i] = '\0'; // 在字符串最后添加'\0'字符,c语言字符串以'\0'结束。 // 将顺序调整过来 if (str[0] == '-') k = 1; // 如果是负数,符号不用调整,从符号后面开始调整 else k = 0; // 不是负数,全部都要调整 char temp; // 临时变量,交换两个值时用到 for (j = k; j <= (i - 1) / 2; j++) // 头尾一一对称交换,i其实就是字符串的长度,索引最大值比长度少1 { temp = str[j]; // 头部赋值给临时变量 str[j] = str[i - 1 + k - j]; // 尾部赋值给头部 str[i - 1 + k - j] = temp; // 将临时变量的值(其实就是之前的头部值)赋给尾部 } return str; // 返回转换后的字符串 } /** * @brief 将字节数组转换为字符串 * * @param din 待转换的数组 * @param count 待转换数组长度 * @param radix 指定进制 * @param sep 指定连接符 * @param str 转换结果 * @return char* 指向转换结果的指针 */ char *bytes2str(uint8_t *din, size_t count, int radix, char *sep, char *str) { char rst[600]="";//=malloc(512); for (size_t i = 0; i < count; i++) { char s[10]=""; // sprintf(s, tmp, din[i]); int2str(din[i],s,radix); // printf("str=%02X,s=%s,len=%d,p=%p\n", din[i], s, strlen(s), s); if (strlen(s) == 1) { strcat(rst,"0");//补充前导零 } strcat(rst, s); // strcat需要字符串尾 strcat(rst,sep); // printf("rst=%s,s=%s\n",rst,s); } int len = strlen(rst)-strlen(sep); strncpy(str,rst,len);//去掉末尾的连接符 str[len]='\0'; return str; } /** * @brief 将字符串按指定进制转换为字节数组,非法字符转换为0,如" AT5AA5"可转换为{0xA0,0x5A,0xA5} * * @param str 待转换字符串 * @param step 每次转换字符个数 * @param base 指定进制 * @param rst 转换结果 * @return size_t 转换结果的长度,包含失败的转换 */ size_t str2Byte(char *str, size_t step, int base, uint8_t *rst) { size_t len = strlen(str) / step; if (strlen(str)%2) { len +=1; } uint8_t b[200]; for (size_t i = 0; i < strlen(str); i = i + step) { char tmp[step]; strncpy(tmp, str + i, step); long d = strtol(tmp, NULL, base); b[i / step] = d; } memcpy(rst, b, len); return len; } /** * @brief 奇偶校验。实际采用的是XOR校验。文档中有出入。 * * @param din 待校验数组 * @param count 待校验数组长度 * @param isEven 偶校验还是奇校验 * @return uint8_t 校验结果 */ uint8_t parityCheck(uint8_t *din, size_t count, uint8_t isEven) { uint8_t rst = 0; if (isEven) { for (size_t i = 0; i < count; i++) { rst += GET_BIT_N_VAL((din), i); } return (rst & 0x1); } else { for (size_t i = 0; i < count; i++) { rst += rst + GET_BIT_N_VAL((din), i); } if (rst % 2 == 0) return 1; else return 0; } } /** * @brief 异或XOR校验 * * @param din 待校验数组 * @param count 待校验数组长度 * @return uint8_t 校验结果 */ uint8_t bccCRC(uint8_t *din, size_t count) { uint8_t rst = 0; // Initial value while(count--) { rst ^= *din++; } return rst; } /** * @brief 在指定数组中搜索目标数组 * * @param din 待搜索数组 * @param len 待搜索数组长度 * @param s 目标数组 * @param slen 搜索长度 * @param dout 搜索结果 * @return int 匹配个数 */ size_t isInByte(uint8_t *din, size_t len, uint8_t *s, size_t slen, uint8_t *dout) { size_t cnt = 0; uint8_t tmp[len]; for (size_t i = 0; i < len - slen+1; i++) { if (memcmp(din + i, s, slen) == 0) { tmp[cnt++] = i; i = i+slen-1; } } memcpy(dout,tmp,cnt); return cnt; } //static char cfname[60]=""; /** * 获取新缓存文件的文件名 * @param fin 指向文件名的数组 * @return */ void updateCacheFileName() { char f[60]=""; char rootDir[22] = ROOT_PATH_DATA; mkdir(rootDir, 0); strcat(rootDir, "2023_07_19/"); //更新时戳 char ts[30] = ""; time2Str(ts); //更新文件夹 strncpy(rootDir + strlen(rootDir) - 9, ts, 8); mkdir(rootDir, 0); //更新文件名 f[0] = '\0'; strcat(f, rootDir); // strcpy(f,rootDir); strcat(f, "23_07_19_16_38_36_36.bin"); // LOG_D("need to creat new file"); strncpy(f + strlen(rootDir), ts, strlen(ts)); // strcpy(cfname,f); setLstFile(f); // strcpy(fin,f); // return fin; } /** * 获取当前缓存文件的文件名 * @param fin 指向文件名的数组 * @return */ char *getLstCacheFileName(char *fin) { // if (strcmp(cfname,"") == 0) { // getNewCacheFileName(fin); // } char f[60]; // while (!getLstFile(f)) { // updateCacheFileName(); // rt_thread_mdelay(1000); // } if (!getLstFile(f)) { updateCacheFileName(); } getLstFile(f); strcpy(fin,f); return fin; } void d_gcf() { char f[60]; LOG_D("--%s",getLstCacheFileName(f)); updateCacheFileName(); LOG_D("--%s",getLstCacheFileName(f)); } MSH_CMD_EXPORT(d_gcf,cache file); /** * 检测数组数据是ASCII还是还是BIN * @param din 待检测数组 * @param len 数组长度 * @return 1-ASCII,0-BIN */ int isDataASCII(uint8_t *din, size_t len) { int rst=0; for (size_t i = 0; i < len; i++) { if (!isprint(din[i])) { rst = 0; break; } if (i == len-1) { rst = 1; } } return rst; } /** * 加密单条信息。为方便上位机解析,加密每条信息 * @param din 待加密的数组 * @param len 待加密长度 * @param dout 加密后的数组 * @return 加密后的长度 */ int cryptSingleMsg(uint8_t *din, size_t len, uint8_t *dout) { //加密。因加密后数据长度会变化,故不能只加密位置数据。 uint8_t cd[200]={0xAB,0xBA}; size_t nlen = 0; //#define FULL_DATA_CRYPT #ifdef FULL_DATA_CRYPT nlen = cryp_data(din, len, cd); #else //单独加密时在加密后数据头部添加0xABBA便于识别、解析 nlen = cryp_data(din, len, cd + 2) + 2; #endif memcpy(dout, cd, nlen); return nlen; }