005d3b689e
修复pack_data一处bug 屏蔽部分LOG_HEX
498 lines
12 KiB
C
498 lines
12 KiB
C
|
||
|
||
#include <rtthread.h>
|
||
#define LOG_TAG "tool"
|
||
#define LOG_LVL LOG_LVL_DBG
|
||
#include <ulog.h>
|
||
//#include <cJSON.h>
|
||
#include <dfs_file.h>
|
||
#include <usrcfg.h>
|
||
|
||
/**
|
||
* 以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[1024]="";//=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, uint16_t *dout)
|
||
{
|
||
size_t cnt = 0;
|
||
uint16_t tmp[20];
|
||
for (size_t i = 0; i < len - slen+1; i++)
|
||
{
|
||
if (memcmp(din + i, s, slen) == 0)
|
||
{
|
||
// tmp[cnt++] = i;
|
||
dout[cnt++]=i;
|
||
i = i+slen-1;
|
||
}
|
||
}
|
||
// memcpy(dout,tmp,cnt*sizeof(uint16_t));
|
||
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;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|