1a14d5b193
添加对232接收断帧数据的处理 更新对不符合帧格式数据的处理方式,改为透传
1944 lines
52 KiB
C
1944 lines
52 KiB
C
/*
|
||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||
*
|
||
* SPDX-License-Identifier: Apache-2.0
|
||
*
|
||
* Change Logs:
|
||
* Date Author Notes
|
||
* 2023-07-06 murmur the first version
|
||
*/
|
||
|
||
|
||
#include "func.h"
|
||
|
||
#define LOG_TAG "func"
|
||
#define LOG_LVL LOG_LVL_DBG
|
||
#include <ulog.h>
|
||
|
||
extern SYS_CFG scfg;
|
||
extern int cryptSingleMsg(uint8_t *din, size_t len, uint8_t *dout);
|
||
extern int pointInPolygon(int polyCorners,float polyX[], float polyY[],float x,float y);
|
||
extern rt_sem_t okToreport;
|
||
extern void resetTM(void);
|
||
unsigned long getFileSize(char *file);
|
||
void updateSysRTC(uint8_t *din, size_t len);
|
||
int isFileExit(char *f);
|
||
#define CFG_ACK
|
||
/**
|
||
* 配置文件后的ack信号
|
||
*/
|
||
void ack(void)
|
||
{
|
||
#ifdef CFG_ACK
|
||
rt_sem_release(okToreport);
|
||
#endif
|
||
}
|
||
/**
|
||
* 将收发数据以ASCII字符形式存入log
|
||
* @param din 待存储数据
|
||
* @param len 数据长度
|
||
* @return 1-发送的数据,0-接收的数据,其它为发送失败的数据
|
||
*/
|
||
int trDataTolog(uint8_t *din, size_t len, uint8_t isTx)
|
||
{
|
||
// return RT_EOK;
|
||
char fn[60];
|
||
initDataLogPath(fn);
|
||
|
||
int fd = open(fn, O_WRONLY | O_CREAT | O_APPEND);
|
||
|
||
//没有加锁,多试几次再报错
|
||
int trycnt=0;
|
||
while (fd < 0)
|
||
{
|
||
rt_thread_mdelay(200);
|
||
fd = open(fn, O_WRONLY | O_CREAT | O_APPEND);
|
||
trycnt +=1;
|
||
if (trycnt>5) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (fd<0) {
|
||
LOG_E("open file %s failed!", fn);
|
||
return -RT_ERROR;
|
||
}
|
||
else
|
||
{
|
||
char log[30]="\n";
|
||
getTimestmp(log+1);
|
||
strcat(log,isTx?" [T]: ":" [R]: ");
|
||
write(fd, log, strlen(log));
|
||
|
||
uint8_t tmp[1024];
|
||
len = cryp_data(din, len, tmp);//加密数据
|
||
bytes2str(tmp, len, 16, "", tmp);
|
||
len = strlen(tmp);
|
||
|
||
int rst = write(fd, tmp, len);
|
||
if (rst != len)
|
||
{
|
||
LOG_E("write to file %s failed!", fn);
|
||
close(fd);
|
||
return -RT_ERROR;
|
||
}
|
||
close(fd);
|
||
return RT_EOK;
|
||
}
|
||
}
|
||
extern rt_sem_t cfgUpdate;
|
||
//3.2.1双模通信功能
|
||
//1为TT通信,0为BD短报文通信
|
||
void setCommMode(int isTT)
|
||
{
|
||
LOG_I("FUNC = setCommMode");
|
||
if (isTT) {
|
||
//change mode
|
||
|
||
|
||
}
|
||
else {
|
||
|
||
}
|
||
//write to cfg file
|
||
// set_cfg("commMode", isTT);
|
||
scfg.commMode=isTT;
|
||
rt_sem_release(cfgUpdate);
|
||
LOG_D("set commMode to %s",isTT?"TT":"BD");
|
||
ack();
|
||
}
|
||
|
||
int getCommMode()
|
||
{
|
||
//load from cfg file
|
||
// int flag = get_cfg("commMode");
|
||
// if (flag < 0) {
|
||
// LOG_W("get mode fault.");
|
||
// }
|
||
// return flag;
|
||
return scfg.commMode;
|
||
}
|
||
|
||
//3.2.2状态自检
|
||
|
||
/**
|
||
* 获取磁盘剩余空间大小,单位MB
|
||
* @param path指定磁盘挂载的路径,为空时表示挂载在根目录的磁盘
|
||
* @return 返回结果,单位MB
|
||
*/
|
||
static uint16_t getFreeSpace(const char *path)
|
||
{
|
||
long long cap;
|
||
struct statfs buffer;
|
||
int result = dfs_statfs(path ? path : "/", &buffer);
|
||
if (result != 0)
|
||
{
|
||
LOG_E("dfs_statfs failed.");
|
||
return 0;
|
||
}
|
||
|
||
cap = (uint16_t)((long long)buffer.f_bsize) * ((long long)buffer.f_bfree) / 1024LL / 1024LL ;//转换为MB
|
||
return cap;
|
||
}
|
||
|
||
void d_getFreeSpace()
|
||
{
|
||
LOG_D("free space of flash is %d MB.",getFreeSpace(NULL));
|
||
uint16_t rst = getFreeSpace("/sd");
|
||
LOG_D("free space of sd is %d MB.%02X,%02X",rst,rst>>8,rst&0xff);
|
||
}
|
||
|
||
/**
|
||
* 獲取電池電量。
|
||
* @return 返回電量百分比
|
||
*/
|
||
RT_WEAK int getPowerLevel(void)
|
||
{
|
||
return 0x63;
|
||
}
|
||
|
||
typedef struct
|
||
{
|
||
uint16_t len;
|
||
rt_uint8_t data[300];
|
||
|
||
} SMSG;//single messgae
|
||
|
||
rt_sem_t one_msg_send_done=RT_NULL;
|
||
void upSend_thread_entry(void* parameter)
|
||
{
|
||
SMSG* msg = RT_NULL;
|
||
msg = (SMSG*) parameter;
|
||
// LOG_D("1--%p",msg);
|
||
// LOG_HEX("--",16,msg->data,msg->len);
|
||
|
||
//check status
|
||
#define CHK_STA
|
||
#ifdef CHK_STA
|
||
uint8_t trycnt = 0;
|
||
while (!isTTjh()) //判断TT状态
|
||
{
|
||
rt_thread_mdelay(4000);
|
||
trycnt += 1;
|
||
if (trycnt > 3)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (!isTTjh()) {
|
||
//cache to file
|
||
LOG_W("TT is not ready, try to cache %d bytes data to file.",msg->len);
|
||
cacheDataToFile(msg->data, msg->len);
|
||
return ;
|
||
}
|
||
#endif
|
||
|
||
//打包数据
|
||
uint8_t dout[300];
|
||
static MSG cfg;
|
||
rt_memset(&cfg, 0, sizeof(MSG)); // 分配空间
|
||
char fin[30];
|
||
time2Str(fin);
|
||
strcat(fin,".bin");
|
||
packInit(&cfg, fin, 0); //写入配置
|
||
|
||
cfg.fcurpiece[0] = 1;
|
||
cfg.fallpiece[0] = msg->len/FRAME_DATA_LEN_MAX+1;
|
||
#ifdef CRYPT_BEFRE_PACK
|
||
//crypt before pack
|
||
//更改后3S单帧数据升为200+,超出TT最大单包数据容量,须分包
|
||
for (size_t var = 0; var < msg->len; var=var+FRAME_DATA_LEN_MAX) {
|
||
cfg.fcurpiece[0] = var/FRAME_DATA_LEN_MAX+1;
|
||
|
||
static uint8_t tmp[200];
|
||
uint8_t tlen = (msg->len-var)>FRAME_DATA_LEN_MAX?FRAME_DATA_LEN_MAX:(msg->len-var);
|
||
uint8_t len = cryptSingleMsg(msg->data+var, tlen, tmp);
|
||
// LOG_HEX("2",16,msg->data+var,tlen);
|
||
|
||
size_t rst = packMsg(&cfg, tmp, len, dout);//引起数据异常
|
||
#else
|
||
size_t rst = packMsg(&cfg, tmpmsg->data, msg->len, dout);//packMsgs
|
||
#endif
|
||
// LOG_HEX("upSend", 27, dout, rst);
|
||
if (rst)
|
||
{
|
||
if (sendMsg(dout, rst) == RT_EOK)
|
||
{
|
||
LOG_I("send %d bytes to TT Done.",rst);
|
||
}
|
||
else//发送失败,实例不存在此种情况
|
||
{
|
||
LOG_E("send error, try to cache %d bytes data to file.",msg->len);
|
||
cacheDataToFile(msg->data, msg->len);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// rt_sem_release(one_msg_send_done);
|
||
// list_thread();
|
||
return ;
|
||
}
|
||
/**
|
||
* 上傳单帧天通數據
|
||
* @param din 待發送數據
|
||
* @param len 待發送數據的長度
|
||
* @return
|
||
*/
|
||
int upSend(uint8_t *din, size_t len)
|
||
{
|
||
LOG_D("try to upsend to TT.");
|
||
//return;
|
||
// if (one_msg_send_done == RT_NULL) {
|
||
// one_msg_send_done = rt_sem_create("senddone", 1, RT_IPC_FLAG_PRIO);
|
||
// }
|
||
|
||
static SMSG msg;
|
||
rt_memset(&msg, 0, sizeof(SMSG));
|
||
rt_memcpy(msg.data,din,len);
|
||
msg.len=len;
|
||
// LOG_D("0--%p",&msg);
|
||
//仅创建一个线程用于发送
|
||
// if (rt_sem_take(one_msg_send_done, rt_tick_from_millisecond(10000)) != RT_EOK) {
|
||
// //10s等待,上一发送仍未完成
|
||
// LOG_E("wait error, try to cache %d bytes data to file.",msg.len);
|
||
// cacheDataToFile(msg.data, msg.len);
|
||
// return -RT_ERROR;
|
||
// }
|
||
/* 创建 serial 线程 */
|
||
rt_thread_t thread = rt_thread_create("upSend", upSend_thread_entry, (void *) &msg, 1024 * 5, 26, 10);
|
||
/* 创建成功则启动线程 */
|
||
if (thread != RT_NULL)
|
||
{
|
||
rt_thread_startup(thread);
|
||
return RT_EOK;
|
||
}
|
||
else
|
||
{
|
||
LOG_E("thread 'upSend' create failure.");
|
||
return -RT_ERROR;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 系统自检,自动发送自检结果
|
||
*/
|
||
void selfTest(void)
|
||
{
|
||
// return;
|
||
LOG_I("FUNC = selftest");
|
||
rt_uint8_t rst[200]={0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _CMD_SELF_TEST>>8, _CMD_SELF_TEST & 0xff};
|
||
int p = 6;
|
||
rt_uint8_t sysSta=1,commSpeed=0;
|
||
//长度
|
||
rst[p++]=0x00;
|
||
rst[p++]=0x09;
|
||
|
||
rst[p++] = sysSta; //系统状态
|
||
rst[p++] = getXh();//xh,jh //信号值
|
||
rst[p++] = isTTjh(); //激活
|
||
rst[p++] = commSpeed; //速率
|
||
// rst[p++] = scfg.commMode;
|
||
rst[p++] = getPowerLevel(); //电量
|
||
|
||
//flash 剩餘空間 //FLASH剩余空间
|
||
uint16_t cap = getFreeSpace("/");
|
||
rst[p++] = (uint8_t)(cap >> 8);
|
||
rst[p++] = (uint8_t)(cap & 0xff);
|
||
|
||
//SD卡剩餘空間
|
||
cap = getFreeSpace("/sd"); //SD卡剩余空间
|
||
rst[p++] = (uint8_t)(cap >> 8);
|
||
rst[p++] = (uint8_t)(cap & 0xff);
|
||
|
||
//添加配置文件信息
|
||
uint8_t size = sizeof(scfg); //配置文件信息
|
||
memcpy(rst + p,&scfg, size);
|
||
p+=size;
|
||
|
||
rst[7] = p-8;//更新数据长度
|
||
|
||
rst[p++] = bccCRC(rst+2, p-1); ////校验位为1个字节,采用异或运算,从指令的第3个字节开始,到奇偶校验位的前一个字节结束
|
||
rst[p++] = 0xED; //结束位
|
||
|
||
// LOG_HEX("selfTestRes",16,rst,p);
|
||
//发送结果
|
||
upSend(rst,p);
|
||
}
|
||
|
||
|
||
//3.2.3日志记录
|
||
//日志功能由各函数通过LOG_D()实现
|
||
|
||
//3.2.4自毁功能
|
||
/**
|
||
* 设置自毁功能开关
|
||
* @param setON 1-自毁功能开启,0-关闭
|
||
*/
|
||
void setSelfDestructSWT(int setON)
|
||
{
|
||
LOG_I("FUNC = set selfdestruct");
|
||
//write to cfg file
|
||
// set_cfg("selfDesSW", setON);
|
||
scfg.selfDesSW=setON;
|
||
rt_sem_release(cfgUpdate);
|
||
LOG_D("set SelfDesSW to %s",setON?"ON":"OFF");
|
||
}
|
||
/**
|
||
* 获取自毁开关状态
|
||
* @return 1-自毁功能开启,0-关闭
|
||
*/
|
||
int getSelfDestructSWT()
|
||
{
|
||
LOG_I("FUNC = get selfdestruct");
|
||
//load from cfg file
|
||
// int flag = get_cfg("selfDesSW");
|
||
// if (flag < 0) {
|
||
// LOG_W("get mode fault.");
|
||
// }
|
||
// return flag;
|
||
return scfg.selfDesSW;
|
||
}
|
||
/**
|
||
* 启动自毁
|
||
*/
|
||
void selfDestruct()
|
||
{
|
||
if (getSelfDestructSWT()) {
|
||
//硬件自毁
|
||
LOG_W("SELF DESTRUCT START.");
|
||
}
|
||
}
|
||
|
||
//3.2.5开、关窗功能
|
||
extern void updateAlarm(uint8_t *t, size_t len);
|
||
/**
|
||
* 更新开窗时间,目前支持两组开窗时段。更新会清除之前的开窗设置
|
||
*/
|
||
void setCommWindow(uint8_t *t, size_t len)
|
||
{
|
||
LOG_I("FUNC = setCommWindow");
|
||
size_t cnt = sizeof(scfg.openWindowTime);
|
||
if (len>cnt) {
|
||
LOG_W("only support %d windows",cnt/4);
|
||
len = cnt;
|
||
}
|
||
len= len/4*4;//窗口需要成对
|
||
|
||
updateAlarm(t,len);
|
||
if (isManualWindow()) {
|
||
stopAlarm();
|
||
}
|
||
else {
|
||
startAlarm();
|
||
}
|
||
memset(scfg.openWindowTime,0,sizeof(scfg.openWindowTime));
|
||
memcpy(scfg.openWindowTime,t,len);
|
||
// rt_sem_release(cfgUpdate);
|
||
char tmpstr[len*3];
|
||
bytes2str(t, len, 10, ",", tmpstr);
|
||
set_cfgs("openWindowTime",tmpstr);
|
||
// LOG_D("updated new CommWindow zone");
|
||
ack();
|
||
|
||
}
|
||
|
||
void d_demo(int argc, char **argv)
|
||
{
|
||
if (argc == 2)
|
||
{
|
||
int fd = open(argv[1], O_RDONLY, 0);
|
||
if (fd < 0)
|
||
{
|
||
LOG_E("open the input file : %s error!\n", argv[1]);
|
||
return;
|
||
}
|
||
rt_uint16_t file_size = lseek(fd, 0, SEEK_END);
|
||
lseek(fd, 0, SEEK_SET);
|
||
|
||
rt_uint8_t *buffer = RT_NULL;
|
||
buffer = (rt_uint8_t *) malloc(file_size);
|
||
if (!buffer)
|
||
{
|
||
LOG_E("No memory for reading file!\n");
|
||
close(fd);
|
||
return;
|
||
}
|
||
|
||
read(fd, buffer, file_size);
|
||
close(fd);
|
||
upSend(buffer, file_size);
|
||
rt_free(buffer);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 存储手动开窗状态,便于意外重启后恢复状态
|
||
* @param isManualWindow 负数代表无,0代表手动开窗不自动关,整数代表自动关窗超时时间
|
||
*/
|
||
void setManualWindow(int isManualWindow)
|
||
{
|
||
scfg.isMaWin = isManualWindow;
|
||
set_cfg("isMaWin", isManualWindow);
|
||
}
|
||
|
||
|
||
void closeWindow(void);
|
||
/**
|
||
* 是否手动开窗状态
|
||
* @return 1-手动开窗模式,0-无
|
||
*/
|
||
int isManualWindow(void)
|
||
{
|
||
int rst = scfg.isMaWin;
|
||
if (rst >= 0) {
|
||
rst = 1;
|
||
LOG_I("is in manual open mode.");
|
||
}
|
||
else {
|
||
rst = 0;
|
||
}
|
||
return rst;
|
||
}
|
||
void checkManualWindow(void)
|
||
{
|
||
int rst = scfg.isMaWin;
|
||
if (rst < 0) {//none
|
||
return;
|
||
}
|
||
stopAlarm();
|
||
if (rst == 0) {//manual open without auto close
|
||
return;
|
||
}
|
||
//设置定时器,定时器到则关窗
|
||
/* 创建定时器,单次定时器 */
|
||
rt_timer_t timer1;
|
||
timer1 = rt_timer_create("manualModeWindow", closeWindow,
|
||
RT_NULL, rt_tick_from_millisecond(rst*60*1000),
|
||
RT_TIMER_FLAG_ONE_SHOT);
|
||
/* 启动定时器 */
|
||
if (timer1 != RT_NULL)
|
||
{
|
||
rt_timer_start(timer1);
|
||
LOG_D("手动开窗完成,%d分钟后自动关窗。",rst);
|
||
}
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 手动控制开窗
|
||
* @param t 开窗时长,单位分钟,时间到则自动关窗。t=0时需要手动关窗。
|
||
*/
|
||
void openWindow(int t)
|
||
{
|
||
//保存记录
|
||
setManualWindow(t);
|
||
//开启TT
|
||
initTT();
|
||
// setWindowMode();
|
||
//手动开窗优先级最高,自动开窗其次,高优先级会屏蔽低优先级
|
||
stopAlarm();
|
||
if (!t) {
|
||
LOG_D("手动开窗完成,需手动关窗。");
|
||
// return;
|
||
}
|
||
else {
|
||
|
||
//设置定时器,定时器到则关窗
|
||
/* 创建定时器,单次定时器 */
|
||
rt_timer_t timer1;
|
||
timer1 = rt_timer_create("manualWin", closeWindow,
|
||
RT_NULL, rt_tick_from_millisecond(t*60*1000),
|
||
RT_TIMER_FLAG_ONE_SHOT);
|
||
/* 启动定时器 */
|
||
if (timer1 != RT_NULL)
|
||
{
|
||
rt_timer_start(timer1);
|
||
LOG_D("手动开窗完成,%d分钟后自动关窗。",t);
|
||
}
|
||
}
|
||
ack();
|
||
|
||
}
|
||
/**
|
||
* 手动关窗
|
||
*/
|
||
void closeWindow(void)
|
||
{
|
||
setManualWindow(-1);
|
||
// 恢复RTC
|
||
startAlarm();
|
||
deInitTT();
|
||
LOG_D("手动关窗完成。");
|
||
}
|
||
|
||
//3.2.6工作参数配置、状态查询
|
||
//包含浮体自身、标体透传、两者结合
|
||
//这里主要实现浮体自身
|
||
//浮体自身的参数配置各功能函数有实现,此处需规定参数下发协议和解码实现
|
||
|
||
//获取当前位置
|
||
/**
|
||
* 获取当前经纬度信息
|
||
* @param dout 存储结果的数组
|
||
* @param cnt 获取几组位置数据
|
||
* @return 数组长度。0表示位置数据未准备好。
|
||
*/
|
||
RT_WEAK int getLoc(uint8_t * dout, size_t cnt)
|
||
{
|
||
LOG_D("待实现获取位置函数,此处以0xCD代替");
|
||
uint8_t tmp[200];
|
||
memset(tmp,0xCD,200);
|
||
memcpy(dout,tmp,cnt*10);
|
||
return cnt*10;//4+4+2
|
||
}
|
||
/**
|
||
* 确保获取正常的位置数据
|
||
* @param dout 位置数据结果
|
||
* @param pairCnt 获取几组位置数据
|
||
* @return 数组长度
|
||
*/
|
||
static int getAndCheckLoc(uint8_t *dout, size_t pairCnt)
|
||
{
|
||
uint8_t loc[200];
|
||
size_t cnt = getLoc(loc,pairCnt);
|
||
|
||
//定位故障,临时填充数据
|
||
if (!cnt) {
|
||
// LOG_W("NONE Loc data, using 0x37 replaced");
|
||
cnt = pairCnt*10;
|
||
memset(loc,0x37,cnt);
|
||
}
|
||
|
||
if (!cnt) {
|
||
return 0;
|
||
// LOG_W("位置信息还未准备好。");
|
||
}
|
||
// else {
|
||
// memcpy(dout,loc,cnt);
|
||
// }
|
||
// return cnt;
|
||
|
||
// while (!cnt)
|
||
// {
|
||
// return 0;
|
||
// static uint8_t i=0;
|
||
// LOG_W("位置信息还未准备好。");
|
||
// rt_thread_mdelay(4000);//状态数据默认3s更新一次
|
||
// cnt = getLoc(loc,pairCnt);
|
||
// if (i++ > 20) {
|
||
// LOG_E("位置信息获取异常");
|
||
//// break;
|
||
// memset(dout,0x37,pairCnt*10);
|
||
// return pairCnt*10;
|
||
// }
|
||
// }
|
||
memcpy(dout,loc,cnt);
|
||
return cnt;
|
||
}
|
||
|
||
/**
|
||
* c回应深度数据,含位置信息
|
||
* @param din
|
||
* @param len
|
||
* @return
|
||
*/
|
||
int reportDepth(uint8_t *din,size_t len)
|
||
{
|
||
// 000000000000000000005AA53E320608000A170407101B33FFFFFFFF24ED
|
||
LOG_I("FUNC = reportDepth");
|
||
//获取并更新位置信息
|
||
uint8_t dout[200];
|
||
rt_memset(dout,0,200);
|
||
size_t nlen = getAndCheckLoc(dout, 1);
|
||
|
||
rt_memcpy(dout+10, din, len);//5aa5从第11字节开始,共len个字节
|
||
LOG_HEX("depth",16,dout,len+10);
|
||
upSend(dout, len+10);
|
||
}
|
||
//天通指令类型:0x70 0x01
|
||
/**
|
||
* 从数组更新系统各项工作参数
|
||
* @param cfg 参数数组
|
||
* @param len 数组长度,为零时使用当前系统的scfg
|
||
*/
|
||
void updateAllSysCfg(uint8_t *cfg, size_t len)
|
||
{
|
||
LOG_I("FUNC = update SYSCFG");
|
||
if (len) {
|
||
memcpy(&scfg,cfg,len);
|
||
}
|
||
|
||
//详见SYS_CFG的定义
|
||
/**
|
||
*
|
||
uint8_t sendInterval;
|
||
uint8_t maxTTWaitTime;
|
||
uint8_t maxTTRetryCnt;
|
||
uint8_t minTTPeriCnt;
|
||
uint8_t minTTsinal;
|
||
uint8_t timeout;
|
||
uint8_t openWindowTime[8];
|
||
uint16_t maxSizePerFile;
|
||
uint8_t commMode;
|
||
uint8_t selfDesSW;
|
||
uint8_t locAlert;
|
||
uint8_t locRepInterval;
|
||
*/
|
||
|
||
static int rst = 1;
|
||
rst &= set_cfg("sendInterval",scfg.sendInterval);
|
||
rst &= set_cfg("maxTTWaitTime",scfg.maxTTWaitTime);
|
||
rst &= set_cfg("maxTTRetryCnt",scfg.maxTTRetryCnt);
|
||
rst &= set_cfg("minTTPeriCnt",scfg.minTTPeriCnt);
|
||
rst &= set_cfg("minTTsinal",scfg.minTTsinal);
|
||
rst &= set_cfg("timeout",scfg.timeout);
|
||
|
||
// char tmpstr[sizeof(scfg.openWindowTime)*3];
|
||
// bytes2str(scfg.openWindowTime, sizeof(scfg.openWindowTime), 10, ",", tmpstr);
|
||
// rst &= set_cfgs("openWindowTime",tmpstr);
|
||
|
||
|
||
rst &= set_cfg("maxSizePerFile", scfg.maxSizePerFile);
|
||
rst &= set_cfg("commMode",scfg.commMode);
|
||
rst &= set_cfg("selfDesSW",scfg.selfDesSW);
|
||
rst &= set_cfg("locAlert",scfg.locAlert);
|
||
rst &= set_cfg("locRepInterval",scfg.locRepInterval);
|
||
rst &= set_cfg("isMaWin",scfg.isMaWin);
|
||
|
||
if (rst) {
|
||
LOG_I("set value success.");
|
||
}
|
||
// if ((uint16_t)getFileSize("cfg.ini") != (uint16_t)getFileSize("sd/cfg.ini")) {
|
||
// LOG_D("backup cfg file to sd");
|
||
// copy("cfg.ini", "sd/cfg.ini");
|
||
// }
|
||
}
|
||
/**
|
||
* 上报系统各项工作参数
|
||
*/
|
||
void reportSysCfg()
|
||
{
|
||
LOG_I("FUNC = report SYSCFG");
|
||
// scfg.commMode=1;
|
||
// scfg.timeout=5;
|
||
// scfg.maxSizePerFile=1024;
|
||
// uint8_t w[]={0x01,2,3,4,5,6,7,8};
|
||
// memcpy(scfg.openWindowTime,w,8);
|
||
|
||
uint8_t size = sizeof(scfg);
|
||
uint8_t rst[200] = { 0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _CFG_UPDATE_CFG >> 8, _CFG_UPDATE_CFG & 0xff };
|
||
int p = 6;
|
||
rst[p++] = 0;
|
||
rst[p++] = size;
|
||
|
||
memcpy(rst + p,&scfg, size);
|
||
p+=size;
|
||
rst[p] = bccCRC(rst + 2, p-2);
|
||
rst[++p] = 0xED;
|
||
|
||
size = p+1;
|
||
LOG_HEX("cfg",16,rst,size);
|
||
upSend(rst, size);
|
||
|
||
// LOG_HEX("scfg",16,&scfg,size);
|
||
// LOG_HEX("cfg",16,rst,p+1);
|
||
// updateAllSysCfg(rst+8, rst[7]);
|
||
}
|
||
|
||
//3.2.8定时自报位置信息
|
||
//每小时传数据时同步传位置信息
|
||
//与告警信息共用编码方式
|
||
//首字节为是否越界,默认为00,此处为预留。
|
||
//单次最多可上报15条位置信息
|
||
|
||
/**
|
||
* 按15条经纬度打包位置信息。由[是否越界]+[时戳]+[15组数据]组成。
|
||
* 是否越界为预留,不在此判断。
|
||
* 15组数据采集顺序为MOB(most oldest bit),越新的数据离时戳越近
|
||
* 由于加密后数据最大会增加16字节,后位置数据条数改为10
|
||
* @param dout 存储位置信息的数组
|
||
* @return 数组大小
|
||
*/
|
||
#define _LOC_CNT 8
|
||
static int packLocMsg(uint8_t *dout)
|
||
{
|
||
uint8_t alertMsg[200] =
|
||
{ 0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _INFO_LOCATION >> 8, _INFO_LOCATION & 0xFF, 0, 0 };
|
||
|
||
|
||
alertMsg[8] = 0; //首字节00为定时发送,未检测围栏;其它为在围栏外
|
||
int len = time2Byte(alertMsg+9) + 1;//添加时间戳,len为数据长度
|
||
size_t rst = getAndCheckLoc(alertMsg + 8 + len, _LOC_CNT);
|
||
if (!rst) {//无有效位置数据
|
||
return 0;
|
||
}
|
||
len += rst;
|
||
|
||
//add battery info
|
||
// uint8_t temp[60];
|
||
// rst = getBattInfo(temp);
|
||
// memcpy(alertMsg+8+len,temp,rst);
|
||
rst = getBattRAWInfo(alertMsg+8+len);
|
||
len += rst;
|
||
|
||
alertMsg[7] = len; //update len of raw data
|
||
alertMsg[8 + len] = bccCRC(alertMsg + 2, 8 + len - 2); //update CRC
|
||
alertMsg[8 + len + 1] = 0xED;
|
||
|
||
len = 8 + len + 2;
|
||
// LOG_HEX("packLocMsg", 16, alertMsg, len); //bccCRC+Tail
|
||
memcpy(dout, alertMsg, len);
|
||
return len;
|
||
}
|
||
static void d_packLocMsg(void)
|
||
{
|
||
uint8_t tmp[200];
|
||
size_t len = packLocMsg(tmp);
|
||
// len = cryptSingleMsg(tmp, len, tmp);
|
||
// uint8_t din[]={0x5A,0xA5,0x3E,0x32,0x06,0x08,0x00,0x0A,0x17,0x09,0x05,0x0F,0x24,0x0B,0xFF,0xFF,0xFF,0xFF,0x33,0xED};
|
||
// reportDepth(din, sizeof(din));
|
||
LOG_HEX("c",16,tmp,len);
|
||
// upSend(tmp, len);
|
||
}
|
||
/**
|
||
* 获取信号信息,以时戳开头
|
||
* @param dout
|
||
*/
|
||
RT_WEAK size_t getSignals(uint8_t *dout, uint8_t len);
|
||
void packSignal(void)
|
||
{
|
||
LOG_I("FUNC = get signals");
|
||
uint8_t signalMsg[200] =
|
||
{ 0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _INFO_SIGNAL >> 8, _INFO_SIGNAL & 0xFF, 0, 0 };
|
||
|
||
|
||
uint8_t len = time2Byte(signalMsg+8);//添加时间戳
|
||
len += getSignals(signalMsg + 8 + len, 100);
|
||
|
||
signalMsg[7] = len; //update len of raw data
|
||
signalMsg[8 + len] = bccCRC(signalMsg + 2, 8 + len - 2); //update CRC
|
||
signalMsg[8 + len + 1] = 0xED;
|
||
|
||
len = 8 + len + 2;
|
||
LOG_HEX("signal",16,signalMsg,len);
|
||
upSend(signalMsg,len);
|
||
}
|
||
|
||
/**
|
||
* 获取电池信息,带时戳
|
||
*/
|
||
void reportBattInfo(void)
|
||
{
|
||
uint8_t battInfo[200] = { 0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _INFO_BATT >> 8, _INFO_BATT & 0xFF, 0, 0 };
|
||
|
||
uint8_t len = time2Byte(battInfo + 8); //添加时间戳
|
||
uint8_t blen = getBattRAWInfo(battInfo + 8 + len);
|
||
len += blen;
|
||
|
||
battInfo[7] = len; //update len of raw data
|
||
battInfo[8 + len] = bccCRC(battInfo + 2, 8 + len - 2); //update CRC
|
||
battInfo[8 + len + 1] = 0xED;
|
||
|
||
len = 8 + len + 2;
|
||
// LOG_HEX("battInfo", 16, battInfo, len); //bccCRC+Tail
|
||
|
||
upSend(battInfo, len);
|
||
|
||
}
|
||
|
||
///**
|
||
// * 加密位置信息。对位置信息的更改需在加密前操作
|
||
// * @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;
|
||
//}
|
||
|
||
//static uint8_t locMsg[200];
|
||
//static rt_timer_t repLoc;
|
||
//static rt_sem_t isReadyToSendLoc;
|
||
|
||
int isInFence(uint8_t *loc);
|
||
/**
|
||
* 打包并检测位置数据 默认10s更新一次
|
||
* @return
|
||
*/
|
||
static int itime=0;//间隔时间
|
||
void reportLoc_thread_entry(void *parameter)
|
||
{
|
||
#define CHECK_INTERVAL 6
|
||
//static int i=0;
|
||
while (isTCPok())
|
||
{
|
||
|
||
rt_thread_mdelay(CHECK_INTERVAL*1000); //默认6s刷新一次
|
||
// static uint32_t i = 0;
|
||
int isReadyToSendLoc=0;
|
||
uint8_t rst[200];
|
||
|
||
size_t len = packLocMsg(rst);
|
||
if (!len) {//无有效位置数据
|
||
// return;
|
||
rt_thread_mdelay(500);//添加延时避免死循环卡死线程
|
||
continue;
|
||
}
|
||
|
||
//检测是否在围栏内
|
||
uint8_t isLocOk[]={0x37,0x37,0x37};
|
||
if (scfg.locAlert && memcmp(rst+len-11-4,isLocOk,sizeof(isLocOk)) != 0 && !isInFence(rst+len-11-4))//不在围栏内。定位正常才判断围栏
|
||
{
|
||
rst[8] |= 1<<7;
|
||
isReadyToSendLoc = 1;
|
||
resetTM();//不关机
|
||
}
|
||
itime += 1 ;
|
||
// LOG_D("%d/%d s",itime*CHECK_INTERVAL,scfg.locRepInterval * 60);
|
||
if (itime*CHECK_INTERVAL >= scfg.locRepInterval * 60)//定时发送,默认5分钟
|
||
{
|
||
itime = 0;
|
||
isReadyToSendLoc = 1;
|
||
}
|
||
|
||
if (isReadyToSendLoc) {
|
||
// LOG_HEX("loc",16,rst,len);
|
||
if (isTTjh()) {//loc数据不用缓存,故需要激活才发送
|
||
upSend(rst, len);
|
||
}
|
||
else {
|
||
itime = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void reportLoc()
|
||
{
|
||
rt_thread_t thread = rt_thread_create("RPLoc", reportLoc_thread_entry, RT_NULL, 1024 * 10, 27, 10);
|
||
/* 创建成功则启动线程 */
|
||
if (thread != RT_NULL)
|
||
{
|
||
rt_thread_startup(thread);
|
||
}
|
||
else
|
||
{
|
||
LOG_E("thread 'PCLoc' create failure.");
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
//3.2.9深度异常告警
|
||
|
||
/**
|
||
* 将位置信息合入深度信息
|
||
* @param din
|
||
* @param len
|
||
* @param dout
|
||
* @return
|
||
*/
|
||
int depthAlert(uint8_t *din, int len)
|
||
{
|
||
//获取并更新位置信息
|
||
// uint8_t loc[10];
|
||
// uint8_t dout[200];
|
||
// size_t nlen = getAndCheckLoc(dout, 1);
|
||
//
|
||
// rt_memcpy(dout+10, din, len);//5aa5从第11字节开始,共len个字节
|
||
// LOG_HEX("depth",16,dout,len+10);
|
||
// //加密。因加密后数据长度会变化,故不能只加密位置数据。
|
||
// upSend(dout, nlen);
|
||
|
||
}
|
||
|
||
//3.2.10位置异常告警
|
||
//map.c中实现
|
||
/**
|
||
* 判断是否在电子围栏内部
|
||
* @param x 当前位置经度
|
||
* @param y 当前位置纬度
|
||
* @return 在内部则返回true,反之false
|
||
*/
|
||
static int isInPolgon(float x, float y)
|
||
{
|
||
float polyX[10]={},polyY[10]={};
|
||
|
||
int polyCorners = mapParse("/map.geojson",polyX,polyY);
|
||
|
||
return pointInPolygon(polyCorners,polyX,polyY,x,y);
|
||
}
|
||
|
||
/**
|
||
* 设置位置告警功能开关
|
||
* @param setON 1-告警功能开启,0-关闭
|
||
*/
|
||
void setLocationAlertSWT(int setON)
|
||
{
|
||
LOG_I("FUNC = set Loc Alert");
|
||
scfg.locAlert = setON;
|
||
set_cfg("locAlert", setON);
|
||
}
|
||
|
||
/**
|
||
* 判断给定位置是否在电子围栏内部
|
||
* @param loc 经纬度数组,8个字节
|
||
* @return 1-
|
||
*/
|
||
int isInFence(uint8_t *loc)
|
||
{
|
||
// LOG_HEX("x=",16,loc,8);
|
||
float x,y =0;
|
||
x=*((float *)loc);
|
||
y=*((float *)(loc+4));
|
||
// LOG_D("%lf-%lf", x, y);
|
||
int isIN = isInPolgon(x, y);
|
||
if (isIN) {
|
||
LOG_D("设备在围栏内,位置正常。");
|
||
return 1;
|
||
}
|
||
else {
|
||
LOG_W("警告!设备不在围栏内!");
|
||
return 0;
|
||
}
|
||
}
|
||
void d_isInFence(void)
|
||
{
|
||
uint8_t rst[200];
|
||
|
||
int len = packLocMsg(rst);
|
||
if (!len)
|
||
{ //无有效位置数据
|
||
LOG_W("无有效位置数据");
|
||
return;
|
||
}
|
||
|
||
//检测是否在围栏内
|
||
isInFence(rst + len - 11);
|
||
//不在围栏内,1+4+4+1+bcc+0x4D
|
||
}
|
||
//创建定时任务,默认时间10秒钟,异常则发送
|
||
|
||
//3.2.12数据存储区清空
|
||
//
|
||
/**
|
||
* 采用格式化命令对存储区进行清空,谨慎使用!
|
||
*/
|
||
void clearAllData()
|
||
{
|
||
// mkfs("elm","sd0");//format SD
|
||
// mkfs("elm", "W25Q128");//format flash
|
||
LOG_I("FUNC = clear files");
|
||
//去掉原static
|
||
//static int cmd_rm(int argc, char **argv)
|
||
//MSH_CMD_EXPORT_ALIAS(cmd_rm, rm, Remove(unlink) the FILE(s).);
|
||
DIR *dir = opendir(ROOT_PATH_DATA);
|
||
if (dir && isFileExit("/sd/tosend.ini"))
|
||
{
|
||
closedir(dir);
|
||
char *arg[]={"rm","-r",ROOT_PATH_DATA,"/sd/tosend.ini" };
|
||
cmd_rm(4,arg);
|
||
}
|
||
LOG_D("files deleted.");
|
||
}
|
||
|
||
/**
|
||
* 重发数据
|
||
* @param din
|
||
* @param len
|
||
*/
|
||
void reSend(uint8_t *din, uint8_t len)
|
||
{
|
||
//file example: sd/cdata/2023_08_23/23_08_23_08_31_44_14.bin
|
||
LOG_I("FUNC = resend file");
|
||
char f[60]="";
|
||
strcat(f,ROOT_PATH_DATA);
|
||
|
||
char str[30]="";
|
||
bytes2str(din, len-1, 10, "_", str);
|
||
strcat(f,"20");
|
||
strncat(f,str,8);
|
||
strcat(f,"/");
|
||
strcat(f,str);
|
||
strcat(f,".bin");
|
||
if (!getFileSize(f)) {
|
||
LOG_W("'%f' is empty.");
|
||
return;
|
||
}
|
||
LOG_D("resend '%s'",f);
|
||
|
||
|
||
for (size_t var = 7; var < len; var++) {
|
||
postFileInfo(f,din[var]);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief TT根据下发的指令执行对应的功能
|
||
*
|
||
* @param din 待执行的指令数据
|
||
* @param len 数据长度,单位字节
|
||
*/
|
||
void ttRunCMD_thread_entry(uint8_t *din, size_t len)
|
||
{
|
||
|
||
/**
|
||
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
||
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 8+N | 9+N | 10+N |
|
||
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
||
| Header | Header | targetAddr | sourceAddr | mainCMD | subCMD | lenH | lenL | data1 | ... | dataN | BbccCRC | tail |
|
||
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
||
*/
|
||
int cmd = (din[4] << 8) + din[5];
|
||
// int para[]
|
||
switch (cmd)
|
||
{
|
||
case _CFG_COMM_MODE:
|
||
setCommMode(din[8]);
|
||
break;
|
||
case _CMD_SELF_TEST:
|
||
selfTest();
|
||
break;
|
||
case _CFG_SELF_DESTRUCT:
|
||
setSelfDestructSWT(din[8]);
|
||
break;
|
||
case _CMD_SELF_DESTRUCT:
|
||
selfDestruct();
|
||
break;
|
||
case _CFG_COMM_WINDOW:
|
||
setCommWindow(din+8,din[7]);//只支持两组开窗,开窗时间为小时、分钟,UTC+0
|
||
break;
|
||
case _CMD_OPEN_WINDOW:
|
||
openWindow(din[7]?((din[8] << 8) + din[9]):0);//两字节开窗时间
|
||
break;
|
||
case _CMD_CLOSE_WINDOW:
|
||
closeWindow();
|
||
break;
|
||
case _CFG_LOCATION_ALERT:
|
||
setLocationAlertSWT(din[8]);
|
||
break;
|
||
case _CMD_CLEAR_DATA:
|
||
clearAllData();
|
||
break;
|
||
case _CFG_UPDATE_CFG:
|
||
if (din[7]) {//数据长度不为0则为覆写参数
|
||
updateAllSysCfg(din+8, din[7]);
|
||
}
|
||
else {//数据长度为0则为请求参数
|
||
reportSysCfg();
|
||
}
|
||
break;
|
||
case _CMD_RETRY_DATA:
|
||
reSend(din+8, din[7]);
|
||
break;
|
||
|
||
case _INFO_BATT:
|
||
reportBattInfo();
|
||
break;
|
||
case _CMD_SET_RTC:
|
||
updateSysRTC(din+8, din[7]);
|
||
break;
|
||
case _INFO_SIGNAL:
|
||
packSignal();
|
||
break;
|
||
default:
|
||
LOG_W("0x%04X=未支持的指令。",cmd);
|
||
break;
|
||
}
|
||
}
|
||
void ttRunCMD(uint8_t *din, size_t len)
|
||
{
|
||
static SMSG msg;
|
||
rt_memset(&msg, 0, sizeof(SMSG));
|
||
rt_memcpy(msg.data,din,len);
|
||
msg.len=len;
|
||
|
||
ttRunCMD_thread_entry(din, len);
|
||
|
||
}
|
||
|
||
RT_WEAK int formatAndSendTo3S(uint8_t * din, size_t len)
|
||
{
|
||
// LOG_D("直接调用小彭的函数进行处理。");
|
||
LOG_I("FUNC = forward to 3S");
|
||
char str[200] = "RCV:";
|
||
|
||
int cmd = (din[4] << 8) + din[5];
|
||
switch (cmd)
|
||
{
|
||
case _CMD_RTC_REQUEST: //不加前后缀的指令,仅有少数
|
||
bytes2str(din, len, 16, "", str);
|
||
break;
|
||
default: //默认加前后缀
|
||
bytes2str(din, len, 16, "", str + 4);
|
||
strcat(str, "\r\n");
|
||
break;
|
||
}
|
||
LOG_D("send '%s' to 3S.", str);
|
||
sendTo3S(str, strlen(str));//作为字符串发送
|
||
return 0;
|
||
}
|
||
//#define CHECK_3S_DATA
|
||
int chk3SDataValid(uint8_t *din, size_t count)
|
||
{
|
||
uint8_t head[]={0x5A,0xA5};
|
||
//header[4] addr[2] func[2] len[2] data[N] fcrc[1] tail[1]
|
||
if (memcmp(din,head,sizeof(head)))
|
||
{
|
||
LOG_W("0x5AA5[√] != 0x%02X%02X[×],帧头不匹配",din[0],din[1]);
|
||
return -RT_ERROR;
|
||
}
|
||
if (din[count-2] != bccCRC(din+2,count-2-2))//校验位为1个字节,采用异或运算,从指令的第3个字节开始,到奇偶校验位的前一个字节结束
|
||
{
|
||
LOG_W("0x%02X[√] != 0x%02X[×],校验值不匹配", bccCRC(din+2,count-2-2),din[count-2] );
|
||
return -RT_ERROR;
|
||
}
|
||
|
||
if (din[count-1] != 0xED)
|
||
{
|
||
LOG_W("0xED[√] != 0x%02X[×],帧尾不匹配",din[count-1]);
|
||
return -RT_ERROR;
|
||
}
|
||
// LOG_D("valid data.");
|
||
return RT_EOK;
|
||
}
|
||
//原计划将指令粗解析放在上位机,考虑到上位机到位时间晚,现放到MCU端
|
||
/**
|
||
* @brief 校验、解析3S数据,以0x5AA5开头0xED结尾。
|
||
*
|
||
* @param din 待解析数据
|
||
* @param count 待解析数据长度
|
||
*/
|
||
void parse3SData(uint8_t *din, size_t count)
|
||
{
|
||
/**
|
||
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
||
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 8+N | 9+N | 10+N |
|
||
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
||
| Header | Header | targetAddr | sourceAddr | mainCMD | subCMD | lenH | lenL | data1 | ... | dataN | BbccCRC | tail |
|
||
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
||
*/
|
||
if (chk3SDataValid(din, count) != RT_EOK) {
|
||
#ifdef CHECK_3S_DATA
|
||
return;
|
||
#endif
|
||
}
|
||
//有效的数据才能复位超时
|
||
|
||
if (isTTon()) {
|
||
resetTM();
|
||
}
|
||
|
||
// uint8_t dout[200];
|
||
// 未采用switch case
|
||
if (din[2] == ADDR_TT)//仅给TT的消息
|
||
{
|
||
ttRunCMD(din,count);
|
||
}
|
||
else if (din[2] == ADDR_3S)//给3S的指令,需要再加工,返回数据可能也需要再加工
|
||
{
|
||
//
|
||
|
||
formatAndSendTo3S(din,count);
|
||
}
|
||
else if (din[2] == ADDR_ANJI)
|
||
{
|
||
//可能需要对回传信息再加工,如查询深度需要加入位置坐标
|
||
//或是缓存任务数据
|
||
//故需要对数据进行简单判断
|
||
int cmd = (din[4] << 8) + din[5];
|
||
switch (cmd)
|
||
{
|
||
// case _CMD_DEPTH_REQUEST:
|
||
// reportDepth(din, count);
|
||
// break;
|
||
case _INFO_DEPTH_ANSWER:
|
||
reportDepth(din, count);
|
||
break;
|
||
default:
|
||
LOG_I("pass-through raw data.");
|
||
if (isTTjh())
|
||
{//如果TT为开机状态(具备通信状态?待商榷)则不缓存直接发
|
||
upSend(din, count);
|
||
}
|
||
else {
|
||
cacheDataToFile(din, count);
|
||
}
|
||
|
||
}
|
||
// upSend(din, count);
|
||
}
|
||
else {
|
||
LOG_W("无法解析的目标地址");
|
||
// cacheDataToFile(din, count);
|
||
if (isTTjh())
|
||
{//如果TT为开机状态(具备通信状态?待商榷)则不缓存直接发
|
||
upSend(din, count);
|
||
}
|
||
else {
|
||
cacheDataToFile(din, count);
|
||
}
|
||
}
|
||
//检查待发文件,相当于失败重发
|
||
// if (getCntOfFileToSend() && !isInFileMode()) {//不严格
|
||
// fileIsReady();
|
||
// }
|
||
|
||
}
|
||
|
||
void chkACK(uint8_t *msg, size_t size)
|
||
{
|
||
rt_uint8_t ackgood[] = { 0x88, 0xAA, 0xBB, 0x88, 0x41, 0x43, 0x4B }; //前四字节=帧头、后三字节=ACK
|
||
if (rt_memcmp(msg, ackgood, 4) == 0 && rt_memcmp(msg + size - 3, ackgood + 4, 3) == 0)
|
||
{
|
||
LOG_I("data is ACK.");
|
||
}
|
||
else {
|
||
LOG_W("INVALID DATA.");
|
||
}
|
||
}
|
||
//#define TR_USE_THREAD
|
||
#ifdef TR_USE_THREAD
|
||
/**
|
||
* @brief 解析TT数据,TT收到的指令必是单指令,解析容易。
|
||
*
|
||
* @param din
|
||
* @param len
|
||
*/
|
||
void parseTTData_thread_entry(void *parameter)
|
||
{
|
||
|
||
SMSG* msg = RT_NULL;
|
||
msg = (SMSG*) parameter;
|
||
uint8_t din[500];
|
||
memcpy(din,msg->data,msg->len);
|
||
size_t len = (size_t)msg->len;
|
||
|
||
/**
|
||
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
||
* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
||
* | fstart[4] | fnum[2] | bak[2] | ftype[2] | fdlen[2] | fcrc[1] | ftccid[4] | rawData[N] |
|
||
* | 0x88,0xAA,0xBB,0x88 | 0x00,0x01 | 0x00,0x00 | 0x70,0x21 | 0x00,0xAA | 0x00 | 0x27,0x22,0x22,0x22 | |
|
||
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
||
*/
|
||
uint8_t head[]={0x88,0xAA,0xBB,0x88, 0xFF,0xFF, 0x00,0x00, 0x70,0x21, 0x00,0xaa, 0x00, 0x27,0x22,0x22,0x22 };
|
||
//fstart[4] fnum[2] bak[2] ftype[2] fdlen[2] fcrc[1] ftccid[4]
|
||
uint8_t index[10];
|
||
size_t n=isInByte(din, len, head, 4, index);//仅判断帧头,因ACK不一样
|
||
uint8_t ndin[200];
|
||
if (!n) {
|
||
LOG_W("TTData中无匹配帧");
|
||
return;
|
||
}
|
||
for (size_t i = 0; i < n; i++)
|
||
{
|
||
//按帧头分割
|
||
int cnt=(i+1<n)?index[i+1]-index[i]:len-index[i];
|
||
memcpy(ndin,din+index[i],cnt);
|
||
if (n>1) {
|
||
LOG_HEX("frame",16,ndin,cnt);
|
||
}
|
||
|
||
|
||
//判断是否为ACK
|
||
if ((ndin[10]<<8) | ndin[11] == 0x03) {//数据长度只有3
|
||
chkACK(ndin, cnt);
|
||
}
|
||
//数据
|
||
else
|
||
{
|
||
resetTM();//非ACK信号才能触发延时逻辑
|
||
uint8_t rst = memcmp(ndin,head,10);//只比较到ftype
|
||
if (rst)
|
||
{
|
||
LOG_W("帧头不匹配");
|
||
return;
|
||
}
|
||
|
||
uint8_t id[30]="";
|
||
LOG_I("data info: id=\"%s\", cur/all=[%d/%d]",bytes2str(ndin+17,7,10,"_",id),ndin[25],ndin[26]);
|
||
if (ndin[24] >> 7) // fcfg=数据类型。解析TT收到的数据时仅需解析“命令”,“数据”传输是单向的。
|
||
{
|
||
LOG_W("浮标端仅接受指令,暂不支持数据。");
|
||
return;
|
||
}
|
||
uint8_t rawData[200];
|
||
uint8_t rawDataLen=cnt-27;
|
||
memcpy(rawData, ndin + 27, rawDataLen);
|
||
parse3SData(rawData,rawDataLen);
|
||
}
|
||
}
|
||
|
||
}
|
||
void parseTTData(uint8_t *din, size_t len)
|
||
{
|
||
static SMSG msg;
|
||
memset(&msg, 0, sizeof(SMSG));
|
||
memcpy(msg.data,din,len);
|
||
msg.len=len;
|
||
|
||
/* 创建 serial 线程 */
|
||
rt_thread_t thread = rt_thread_create("parseTT", parseTTData_thread_entry, (void *) &msg, 1024 * 5, 27-1, 10);
|
||
/* 创建成功则启动线程 */
|
||
if (thread != RT_NULL)
|
||
{
|
||
rt_thread_startup(thread);
|
||
return RT_EOK;
|
||
}
|
||
else
|
||
{
|
||
LOG_E("thread 'parseTT' create failure.");
|
||
return -RT_ERROR;
|
||
}
|
||
|
||
}
|
||
#else
|
||
|
||
/**
|
||
* @brief 解析TT数据,TT收到的指令必是单指令,解析容易。
|
||
*
|
||
* @param din
|
||
* @param len
|
||
*/
|
||
void parseTTData(uint8_t *din, size_t len)
|
||
{
|
||
/**
|
||
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
||
* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
||
* | fstart[4] | fnum[2] | bak[2] | ftype[2] | fdlen[2] | fcrc[1] | ftccid[4] | rawData[N] |
|
||
* | 0x88,0xAA,0xBB,0x88 | 0x00,0x01 | 0x00,0x00 | 0x70,0x21 | 0x00,0xAA | 0x00 | 0x27,0x22,0x22,0x22 | |
|
||
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
||
*/
|
||
uint8_t head[]={0x88,0xAA,0xBB,0x88, 0xFF,0xFF, 0x00,0x00, 0x70,0x21, 0x00,0xaa, 0x00, 0x27,0x22,0x22,0x22 };
|
||
//fstart[4] fnum[2] bak[2] ftype[2] fdlen[2] fcrc[1] ftccid[4]
|
||
uint8_t index[10];
|
||
size_t n=isInByte(din, len, head, 4, index);//仅判断帧头,因ACK不一样
|
||
uint8_t ndin[200];
|
||
if (!n) {
|
||
LOG_W("TTData中无匹配帧");
|
||
return;
|
||
}
|
||
for (size_t i = 0; i < n; i++)
|
||
{
|
||
//按帧头分割
|
||
int cnt=(i+1<n)?index[i+1]-index[i]:len-index[i];
|
||
memcpy(ndin,din+index[i],cnt);
|
||
if (n>1) {
|
||
LOG_HEX("frame",16,ndin,cnt);
|
||
}
|
||
|
||
|
||
//判断是否为ACK
|
||
if ((ndin[10]<<8) | ndin[11] == 0x03) {//数据长度只有3
|
||
chkACK(ndin, cnt);
|
||
}
|
||
//数据
|
||
else
|
||
{
|
||
resetTM();//非ACK信号才能触发延时逻辑
|
||
uint8_t rst = memcmp(ndin,head,10);//只比较到ftype
|
||
if (rst)
|
||
{
|
||
LOG_W("帧头不匹配");
|
||
parse3SData(din,len);//由于串口收数据会出现断帧的情况,这里统一改为不处理,异常数据直接透传
|
||
return;
|
||
}
|
||
|
||
uint8_t id[30]="";
|
||
LOG_I("data info: id=\"%s\", cur/all=[%d/%d]",bytes2str(ndin+17,7,10,"_",id),ndin[25],ndin[26]);
|
||
if (ndin[24] >> 7) // fcfg=数据类型。解析TT收到的数据时仅需解析“命令”,“数据”传输是单向的。
|
||
{
|
||
LOG_W("浮标端仅接受指令,暂不支持数据。");
|
||
return;
|
||
}
|
||
uint8_t rawData[200];
|
||
uint8_t rawDataLen=cnt-27;
|
||
memcpy(rawData, ndin + 27, rawDataLen);
|
||
parse3SData(rawData,rawDataLen);
|
||
}
|
||
}
|
||
|
||
}
|
||
#endif
|
||
/**
|
||
* get file size in byte
|
||
* @param file file name whith fullpath
|
||
*/
|
||
unsigned long getFileSize(char *file)
|
||
{
|
||
struct stat stat;
|
||
char *fullpath, *path;
|
||
unsigned long rst=0;
|
||
|
||
#ifdef DFS_USING_WORKDIR
|
||
/* open current working directory */
|
||
path = rt_strdup("/");
|
||
#endif
|
||
|
||
/* build full path for each file */
|
||
fullpath = dfs_normalize_path(path, file);
|
||
|
||
rt_memset(&stat, 0, sizeof(struct stat));
|
||
if (dfs_file_stat(fullpath, &stat) == 0)
|
||
{
|
||
rst = stat.st_size;
|
||
}
|
||
rt_free(fullpath);
|
||
rt_free(path);
|
||
return rst;
|
||
}
|
||
|
||
void d_getFileSize(int argc, char ** argv)
|
||
{
|
||
// char *f;
|
||
uint16_t size = (uint16_t)getFileSize(argv[1]);
|
||
LOG_D("size = %d Byte.",size);
|
||
}
|
||
|
||
/**
|
||
* 判断文件是否存在,参数为文件完整路径
|
||
* @param f
|
||
* @return
|
||
*/
|
||
int isFileExit(char *f)
|
||
{
|
||
int rst = 0;
|
||
int fd = open(f, O_RDONLY);
|
||
if (fd > 0)
|
||
{
|
||
rst = 1;
|
||
close(fd);
|
||
}
|
||
return rst;
|
||
}
|
||
extern SYS_CFG scfg;
|
||
static uint8_t iscdlock=0;
|
||
/**
|
||
* 缓存任务数据
|
||
* @param din 单次收到的任务数据
|
||
* @param len 任务数据长度
|
||
* @return 0--正常,-1--异常
|
||
*/
|
||
int cacheDataToFile(uint8_t *din, size_t len)
|
||
{
|
||
LOG_I("FUNC = cache to upsend");
|
||
int rst = -RT_ERROR;
|
||
//return RT_EOK;
|
||
|
||
|
||
//lock file
|
||
while (iscdlock) {
|
||
rt_thread_mdelay(1000);
|
||
}
|
||
static char f[60]="";//必须是static,否则log2file报错
|
||
getLstCacheFileName(f);
|
||
|
||
int fd = open(f, O_WRONLY | O_CREAT | O_APPEND);
|
||
if (fd < 0)
|
||
{
|
||
LOG_E("open file %s failed!", f);
|
||
goto _exit;
|
||
}
|
||
else
|
||
{
|
||
iscdlock=1;
|
||
int rst = write(fd, din, len);
|
||
if (rst != len)
|
||
{
|
||
LOG_E("write to file %s failed!", f);
|
||
goto _exit;
|
||
}
|
||
// cnt += len;
|
||
close(fd);
|
||
unsigned long size = getFileSize(f);
|
||
LOG_I("cached %d bytes data to '%s', new size is %ld bytes.",len,f,size);
|
||
|
||
if (size > scfg.maxSizePerFile) {
|
||
updateCacheFileName();//更新文件名,置于线程前避免冲突
|
||
cryptCdata(f);//密文覆盖明文
|
||
postFileInfo(f,0);//加入待发列表
|
||
}
|
||
rst=RT_EOK;
|
||
}
|
||
_exit:
|
||
if (fd) {
|
||
close(fd);
|
||
}
|
||
iscdlock=0;
|
||
|
||
return rst;
|
||
}
|
||
void d_cacheData()
|
||
{
|
||
uint8_t demo[200];
|
||
size_t len = sizeof(demo);
|
||
memset(demo,0xAB,len);
|
||
cacheDataToFile(demo, len);
|
||
}
|
||
|
||
//#define TR_USE_THREAD
|
||
#ifdef TR_USE_THREAD
|
||
void parseRS232_thread_entry(void *parameter)
|
||
{
|
||
|
||
SMSG* msg = RT_NULL;
|
||
msg = (SMSG*) parameter;
|
||
uint8_t din[500];
|
||
memcpy(din,msg->data,msg->len);
|
||
size_t len = (size_t)msg->len;
|
||
|
||
//有HEX有ASCII,统一按HEX解析
|
||
//部分数据以10字节(20字符)的0数据开始,如深度查询,心跳包等
|
||
//处理思路是先不管前导0,对应指令手动加前导数据
|
||
// uint8_t asciiHead[]={0x41, 0x54, 0x2B, 0x53, 0x4E, 0x44,};//"AT+SND"
|
||
uint8_t hexHead[]={0x5a, 0xa5};//"5AA5"
|
||
//由于帧头有多种,且ascii和hex混发,无法处理粘包
|
||
|
||
// LOG_D("data is %s",isDataASCII(din, len)?"ASCII":"BIN");
|
||
//check
|
||
// if (memcmp(din,asciiHead,sizeof(asciiHead)) == 0) {
|
||
if (isDataASCII(din, len)) {
|
||
//ascii
|
||
LOG_I("type = ASCII");
|
||
trDataTolog(din, len, 0);
|
||
|
||
|
||
uint8_t index[10];
|
||
uint8_t tmpHead[]={0x35, 0x41, 0x41, 0x35};
|
||
size_t n=isInByte(din, len, tmpHead, sizeof(tmpHead), index);
|
||
// LOG_D("n=%d",n);
|
||
if (!n) {
|
||
LOG_W("RS232中无匹配帧");
|
||
return;
|
||
}
|
||
for (size_t i = 0; i < n; i++)
|
||
{
|
||
//按帧头分割
|
||
uint8_t ndin[400];
|
||
int cnt=(i+1<n)?index[i+1]-index[i]:len-index[i];
|
||
memcpy(ndin,din+index[i],cnt);
|
||
ndin[cnt]='\0';
|
||
uint8_t tmp[200];
|
||
size_t ncnt = str2Byte(ndin, 2, 16, tmp);
|
||
LOG_HEX("frame",16,tmp,ncnt);
|
||
if (chk3SDataValid(tmp, ncnt) != RT_EOK) {
|
||
return;
|
||
}
|
||
parse3SData(tmp,ncnt);
|
||
}
|
||
}
|
||
else//如果不是ASCII则统一按HEX计// if (memcmp(din,hexHead,sizeof(hexHead)) == 0)
|
||
{
|
||
//bin
|
||
LOG_I("type = BIN");
|
||
char tmp[200]="";
|
||
trDataTolog(bytes2str(din, len, 16, " ", tmp), strlen(tmp), 0);
|
||
|
||
|
||
uint8_t index[10];
|
||
size_t n=isInByte(din, len, hexHead, sizeof(hexHead), index);
|
||
if (!n) {
|
||
LOG_W("RS232中无匹配帧");
|
||
return;
|
||
}
|
||
for (size_t i = 0; i < n; i++)
|
||
{
|
||
//按帧头分割
|
||
uint8_t ndin[200];
|
||
int cnt=(i+1<n)?index[i+1]-index[i]:len-index[i];
|
||
memcpy(ndin,din+index[i],cnt);
|
||
LOG_HEX("frame",16,ndin,cnt);
|
||
if (chk3SDataValid(ndin, cnt) != RT_EOK) {
|
||
return;
|
||
}
|
||
parse3SData(ndin,cnt);
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
void parseRS232(uint8_t *din, size_t len)
|
||
{
|
||
static SMSG msg;
|
||
memset(&msg, 0, sizeof(SMSG));
|
||
memcpy(msg.data, din, len);
|
||
msg.len = len;
|
||
|
||
/* 创建 serial 线程 */
|
||
rt_thread_t thread = rt_thread_create("parse232", parseRS232_thread_entry, (void *) &msg, 1024 * 5, 27 - 1, 10);
|
||
/* 创建成功则启动线程 */
|
||
if (thread != RT_NULL)
|
||
{
|
||
rt_thread_startup(thread);
|
||
return RT_EOK;
|
||
}
|
||
else
|
||
{
|
||
LOG_E("thread 'parse232' create failure.");
|
||
return -RT_ERROR;
|
||
}
|
||
}
|
||
#else
|
||
|
||
void parseRS232(uint8_t *din, size_t len)
|
||
{
|
||
//有HEX有ASCII,统一按HEX解析
|
||
//部分数据以10字节(20字符)的0数据开始,如深度查询,心跳包等
|
||
//处理思路是先不管前导0,对应指令手动加前导数据
|
||
uint8_t asciiHead[]={0x41, 0x54, 0x2B, 0x53, 0x4E, 0x44,};//"AT+SND"
|
||
uint8_t hexHead[]={0x5a, 0xa5};//"5AA5"
|
||
//由于帧头有多种,且ascii和hex混发,无法处理粘包
|
||
|
||
// LOG_D("data is %s",isDataASCII(din, len)?"ASCII":"BIN");
|
||
//check
|
||
if (memcmp(din,asciiHead,sizeof(asciiHead)) == 0) {
|
||
// if (isDataASCII(din, len) || memcmp(din,asciiHead,sizeof(asciiHead)) == 0) {
|
||
//ascii
|
||
LOG_I("type = ASCII");
|
||
trDataTolog(din, len, 0);
|
||
|
||
|
||
uint16_t index[10];
|
||
uint8_t tmpHead[]={0x35, 0x41, 0x41, 0x35};
|
||
size_t n=isInByte(din, len, tmpHead, sizeof(tmpHead), index);
|
||
// LOG_D("n=%d",n);
|
||
if (!n) {
|
||
LOG_W("RS232中无匹配帧[ASCII]");
|
||
return;
|
||
}
|
||
for (size_t i = 0; i < n; i++)
|
||
{
|
||
//按帧头分割
|
||
uint8_t ndin[400];
|
||
int cnt=(i+1<n)?index[i+1]-index[i]:len-index[i];
|
||
memcpy(ndin,din+index[i],cnt);
|
||
ndin[cnt]='\0';
|
||
uint8_t tmp[200];
|
||
size_t ncnt = str2Byte(ndin, 2, 16, tmp)-1;//结尾有\r\n
|
||
// if (n>1) LOG_HEX("frame",16,tmp,ncnt);
|
||
parse3SData(tmp,ncnt);
|
||
}
|
||
}
|
||
else//如果不是ASCII则统一按HEX计// if (memcmp(din,hexHead,sizeof(hexHead)) == 0)
|
||
{
|
||
//bin
|
||
LOG_I("type = BIN");
|
||
trDataTolog(din, len, 0);
|
||
|
||
uint16_t index[20];
|
||
size_t n=isInByte(din, len, hexHead, sizeof(hexHead), index);
|
||
if (!n) {
|
||
LOG_W("RS232中无匹配帧[BIN]");
|
||
return;
|
||
}
|
||
|
||
for (size_t i = 0; i < n; i++)
|
||
{
|
||
//按帧头分割
|
||
uint8_t ndin[MAX_LEN_3S];
|
||
int cnt=(i+1<n)?index[i+1]-index[i]:len-index[i];
|
||
memcpy(ndin,din+index[i],cnt);
|
||
// if (n>1) LOG_HEX("frame",16,ndin,cnt);
|
||
parse3SData(ndin,cnt);
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
#endif
|
||
#include <netdev_ipaddr.h>
|
||
#include <netdev.h>
|
||
/**
|
||
* check eth
|
||
* @return 1-UP,0-DOWN
|
||
*/
|
||
int isEthUP()
|
||
{
|
||
//netdev.c
|
||
extern struct netdev *netdev_default;
|
||
int rst = (netdev_default->flags & 0x01U) ? 1:0; //0x01 = NETDEV_FLAG_UP
|
||
// LOG_D("eth is %s.",rst?"up":"down");
|
||
// rst &= (netdev_default->flags & 0x04U) ? 1:0;//0x04 NETDEV_FLAG_LINK_UP
|
||
return rst;
|
||
}
|
||
|
||
|
||
void reportInfo_thread(void)
|
||
{
|
||
while (1)
|
||
{
|
||
if (rt_sem_take(okToreport, RT_WAITING_FOREVER) == RT_EOK)
|
||
{
|
||
if (isTTjh()) {
|
||
LOG_D("send cfg ACK");
|
||
selfTest();
|
||
}
|
||
else {
|
||
LOG_W("TT is not ready, ACK is invalid.");
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
void reportINFO(void)
|
||
{
|
||
/* 创建 serial 线程 */
|
||
rt_thread_t thread = rt_thread_create("reportINFO", reportInfo_thread, RT_NULL, 1024 * 5, 27, 10);
|
||
/* 创建成功则启动线程 */
|
||
if (thread != RT_NULL)
|
||
{
|
||
rt_thread_startup(thread);
|
||
}
|
||
else
|
||
{
|
||
LOG_E("thread 'updatecfg' create failure.");
|
||
return;
|
||
}
|
||
}
|
||
//INIT_APP_EXPORT(reportINFO);
|
||
|
||
/**
|
||
* 设置3S的RTC时间
|
||
*/
|
||
void set3SRTC(void)
|
||
{
|
||
uint8_t cmd[16]={0x5A, 0xA5, ADDR_3S, ADDR_ANJI, _CMD_SET_RTC >> 8, _CMD_SET_RTC & 0xFF, 0x00, 0x06 };
|
||
|
||
time2Byte(cmd+8);
|
||
cmd[14]=bccCRC(cmd+2, 16-4);
|
||
cmd[15]=0xED;
|
||
LOG_HEX("cmdRTC",16,cmd,sizeof(cmd));
|
||
formatAndSendTo3S(cmd, sizeof(cmd));
|
||
}
|
||
|
||
/**
|
||
* 更新系统RTC时间
|
||
* @param din
|
||
* @param len
|
||
*/
|
||
void updateSysRTC(uint8_t *din, size_t len)
|
||
{
|
||
LOG_I("FUNC = sest RTC");
|
||
|
||
struct tm tm_new = { 0 };
|
||
time_t old = (time_t)0;
|
||
time_t now = (time_t)0;
|
||
|
||
int err = get_timestamp(&old);
|
||
if (err != RT_EOK)
|
||
{
|
||
LOG_E("Get current timestamp failed. %d", err);
|
||
return;
|
||
}
|
||
|
||
din[0] += 2000 - 1900;
|
||
din[1] -= 1;
|
||
// memcpy(tm_new, din, sizeof(tm_new));
|
||
tm_new.tm_year = din[0];
|
||
tm_new.tm_mon = din[1];
|
||
tm_new.tm_mday = din[2];
|
||
tm_new.tm_hour = din[3];
|
||
tm_new.tm_min = din[4];
|
||
tm_new.tm_sec = din[5];
|
||
|
||
/* converts the local time into the calendar time. */
|
||
now = mktime(&tm_new);
|
||
err = set_timestamp(now);
|
||
if (err != RT_EOK)
|
||
{
|
||
LOG_E("set date failed. %d", err);
|
||
return;
|
||
}
|
||
|
||
get_timestamp(&now); /* get new timestamp */
|
||
rt_kprintf("old: %.*s", 25, ctime(&old));
|
||
rt_kprintf("now: %.*s", 25, ctime(&now));
|
||
|
||
//ACK
|
||
uint8_t rst[16]={0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _INFO_RTC_ANSWER >> 8, _INFO_RTC_ANSWER & 0xFF, 0x00, 0x06 };
|
||
uint8_t tm[10];
|
||
time2Byte(tm);
|
||
memcpy(rst+8,tm,6);
|
||
rst[14]=bccCRC(rst+2, 14);
|
||
rst[15]=0xED;
|
||
LOG_HEX("sRTC",16,rst,sizeof(rst));
|
||
if (isTTjh()) {
|
||
upSend(rst, sizeof(rst));
|
||
}
|
||
|
||
}
|
||
/**
|
||
* TT工作后设置状态,用于系统崩溃后恢复
|
||
* @param flag
|
||
*/
|
||
void setWorkSta(int flag)
|
||
{
|
||
set_cfg("isWorking", flag);
|
||
}
|
||
/**
|
||
* 是否需要恢复现场
|
||
* @return
|
||
*/
|
||
int isNeedRestore(void)
|
||
{
|
||
int rst = get_cfg("isWorking");
|
||
if (rst > 0) {
|
||
LOG_W("restoring TT after crash");
|
||
}
|
||
else {
|
||
rst = 0;
|
||
}
|
||
return rst;
|
||
}
|
||
|
||
/**
|
||
* 将密文解密至内存
|
||
* @param fin 密文文件
|
||
* @param buffer 解密后数据
|
||
* @return 数据长度
|
||
*/
|
||
size_t decryptCdata(const char *fin, uint8_t *dout)
|
||
{
|
||
int fd = -1;
|
||
fd = open(fin, O_RDONLY, 0);
|
||
if (fd < 0)
|
||
{
|
||
LOG_E("[hex] open the input file : %s error.", fin);
|
||
return RT_ERROR;
|
||
}
|
||
size_t file_size = lseek(fd, 0, SEEK_END);
|
||
lseek(fd, 0, SEEK_SET);
|
||
|
||
rt_uint8_t *buffer = RT_NULL;
|
||
buffer = rt_malloc(file_size);
|
||
if (!buffer)
|
||
{
|
||
LOG_E("No memory for read cdata!\n");
|
||
return RT_ERROR;
|
||
}
|
||
read(fd, buffer, file_size);
|
||
close(fd);
|
||
|
||
size_t rst = decryp_data(buffer, file_size, dout);
|
||
rt_free(buffer);
|
||
|
||
return rst;
|
||
}
|
||
|
||
/**
|
||
* 加密待发的缓存文件,覆盖源文件
|
||
* 当文件内容不再更新时调用此文件
|
||
* @param f 缓存文件
|
||
*/
|
||
void cryptCdata(const char *f)
|
||
{
|
||
aes_file(f, f);
|
||
}
|
||
|
||
#define FUNC_DEMO
|
||
|
||
#ifdef FUNC_DEMO //测试时导出命令到控制台
|
||
MSH_CMD_EXPORT(d_getFreeSpace,getFreeSpace);
|
||
MSH_CMD_EXPORT(selfTest,sysSelfTest);
|
||
MSH_CMD_EXPORT(d_packLocMsg,dpackLocMsg);
|
||
MSH_CMD_EXPORT(reportLoc,采集并发送位置信息);
|
||
MSH_CMD_EXPORT(d_cacheData,d_cacheData);
|
||
MSH_CMD_EXPORT(d_getFileSize,d_getFileSize);
|
||
MSH_CMD_EXPORT(isEthUP,isEthUP);
|
||
MSH_CMD_EXPORT(reportSysCfg,reportSysCfg);
|
||
MSH_CMD_EXPORT(d_isInFence,d_isInFence);
|
||
MSH_CMD_EXPORT(d_demo,demo for debug function);
|
||
MSH_CMD_EXPORT(set3SRTC,发送指令设置RTC);
|
||
#endif
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|