TT12-MCU/applications/tools.c
CSSC-WORK\murmur 3169b24a24 修复isInByte数据类型错误导致索引不能大于255的bug
修复过长BIN类型数据使用trDataTolog写数据异常的bug
修改系统时钟为50->100MHz,msg_pool大小为256B->4k,串口buffer为4->40k
更新版本号为2.6d
2023-10-27 10:15:22 +08:00

498 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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[600+10]="";//=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;
}