TT12-MCU/applications/ttmsg/ttmsg.c
2023-08-26 16:49:19 +08:00

494 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.

/*
* @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 <dfs_file.h>
#define LOG_TAG "ttmsg"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
#include "ttmsg.h"
#include <board.h>
#include <ttTR.h>
#include <cfg.h>
extern struct rt_event tcp_chk;//tcp条件
/**
* @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);
char idstr[30];
LOG_I("msg id:%s",bytes2str(tmp, len, 10, "_", idstr));
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]; // 打包后数据各维长度
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);
}
return row;
}
/**
* 将指定文件按帧协议进行切片打包,返回二维数组
* @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;
size_t file_size = 0;
rt_uint8_t len = 0;
// rt_uint8_t *buffer = RT_NULL;
static 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);
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;
}
//更新算法,改用特定大小依次读取文件,弃用一次性全部读入文件
uint8_t row = (file_size / flen) + (file_size % flen > 0 ? 1 : 0);
cfg.fallpiece[0] = row;
uint8_t block_size = 0;
rt_uint8_t *buffer = RT_NULL;
buffer = (rt_uint8_t *) rt_malloc(flen);
if (buffer == RT_NULL)
{
LOG_E("No memory for read %s.", fin);
return 0;
}
fd_in = open(fin, O_RDONLY, 0);
for (size_t i = 0; i < file_size; i += flen)
{
if ((file_size - i) < flen)
{
block_size = file_size - i;
}
else
{
block_size = flen;
}
// LOG_D("block_size=%d-%d-%d",block_size,i,file_size);
memset(buffer, 0x00, flen);
read(fd_in, buffer, block_size);
// LOG_HEX("hex_file",27,buffer,block_size);
uint8_t index = (i / flen);
cfg.fcurpiece[0] = index + 1;
//crypt before pack
uint8_t tmp[200];
uint8_t len = cryptSingleMsg(buffer, block_size, tmp);
// LOG_HEX("crypt msg",16,tmp,len);
uint8_t col = packMsg(&cfg, tmp, len, dout[index]);
// uint8_t col = packMsg(&cfg, buffer, block_size, dout[index]);
arrLen[index] = col;
// LOG_D("index/row bef-aft");
// LOG_D("%5d/%3d %3d-%3d",index+1,row,len,col);
// LOG_HEX("per msg",27,dout[index],col);
}
if (buffer != RT_NULL)
{
rt_free(buffer);
}
if (fd_in >= 0)
{
close(fd_in);
}
return row;
}
/**
* 天通上电
* @param parameter "0"断电,其它上电
*/
void pwTT_thread_entry(void *parameter)
{
// LOG_I("--%s--",parameter);
int f = rt_pin_read(TT_EN);
int flag = f;
if (strcmp(parameter,"NULL")==0)//无参数,状态翻转
{
flag = !f;
}
else
{
#ifndef RELAY
flag = !(rt_bool_t) atoi(parameter);
#else
flag = (rt_bool_t) atoi(parameter);
#endif
}
rt_pin_write(TT_EN, flag);//
rt_thread_mdelay(300);
// if (!flag) {
// initTT();
// }
// else {
// deInitTT();
// }
#ifndef RELAY
if (rt_pin_read(TT_EN))//检查设置后状态
{
LOG_I("set TT %s", "OFF");//高电平关断
// add_val("swCnt");//更新统计值
}
else
{
// add_val("swCnt");//更新统计值
LOG_I("set TT %s", "ON");//低电平开启
}
#else
LOG_I("set TT %s", rt_pin_read(TT_EN)?"ON":"OFF");
#endif
}
static int swTT(int argc, char **argv)
{
static char s[5]="NULL";
if (argc >= 2)
{
rt_strcpy(s,argv[1]);
}
else {
rt_strcpy(s,"NULL");
}
/* 创建线程 */
rt_thread_t thread = rt_thread_create("sw_TT", pwTT_thread_entry, (void *) s, 1024 * 2, 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电源);
extern struct rt_messagequeue TTrx_mq;
void recTT_thread_entry()
{
// while(tcpInit() != RT_EOK)
// {
// LOG_W("TT server is not ready.");
// rt_thread_mdelay(100);
// }
// LOG_D("TT server is ready.");
static TTRx_MSG msg;
while (1)
{
if (!isTCPok()) {
break;
}
rt_memset(&msg, 0, sizeof(msg));
if (rt_mq_recv(&TTrx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER) == RT_EOK)
{
//
if (!msg.size)
{ //收到数据长度为0表示tcp断开
break;
}
LOG_I("%d Bytes received from TT",msg.size);
LOG_HEX("TTrec", 27, msg.data, msg.size);
//存入log
char tmp[200]="";//接收的数据不会很长200足矣
trDataTolog(bytes2str(msg.data, msg.size, 16, " ", tmp), strlen(tmp), 0);
//此处调用处理函数
parseTTData(msg.data,msg.size);
}
}
LOG_D("close recTT_thread_entry.");
}
//INIT_COMPONENT_EXPORT(recTT_thread_entry);
/**
* 接收TT数据
*/
void recTT(void)
{
/* 创建线程 */
rt_thread_t thread = rt_thread_create("recTT", recTT_thread_entry, RT_NULL, 1024 * 6, 27-1, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
LOG_E("thread 'recTT' create failure.");
return;
}
}
MSH_CMD_EXPORT(recTT,TTrx demo.)
/**
* 更新目标地址
*/
void updateTargetAddr(uint8_t *din, uint8_t *addr)
{
memcpy(din+13,addr,4);
}