TT12-MCU/applications/func/func.c

1866 lines
50 KiB
C
Raw Normal View History

/*
* 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);
2023-09-07 07:24:38 +00:00
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
}
2023-07-26 08:26:53 +00:00
/**
* ASCII字符形式存入log
* @param din
* @param len
* @return 1-0-
2023-07-26 08:26:53 +00:00
*/
int trDataTolog(uint8_t *din, size_t len, uint8_t isTx)
2023-08-26 11:36:36 +00:00
{
// return RT_EOK;
char fn[60] = "\n";
initDataLogPath(fn);
2023-07-26 08:26:53 +00:00
int fd = open(fn, O_WRONLY | O_CREAT | O_APPEND);
//没有加锁,多试几次再报错
int trycnt=0;
while (fd < 0)
2023-07-26 08:26:53 +00:00
{
2023-08-25 08:36:00 +00:00
rt_thread_mdelay(200);
fd = open(fn, O_WRONLY | O_CREAT | O_APPEND);
trycnt +=1;
if (trycnt>5) {
break;
}
}
2023-08-25 08:36:00 +00:00
if (fd<0) {
2023-07-26 08:26:53 +00:00
LOG_E("open file %s failed!", fn);
return -RT_ERROR;
}
else
{
char log[30]="\n";
getTimestmp(log+1);
2023-07-26 08:26:53 +00:00
strcat(log,isTx?" [T]: ":" [R]: ");
write(fd, log, strlen(log));
2023-07-26 08:26:53 +00:00
int rst = write(fd, din, len);
if (rst != len)
2023-07-26 08:26:53 +00:00
{
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;
}
2023-07-25 06:55:03 +00:00
typedef struct
{
rt_uint8_t len;
rt_uint8_t data[200];
2023-07-25 06:55:03 +00:00
} SMSG;//single messgae
rt_sem_t one_msg_send_done=RT_NULL;
2023-07-25 06:55:03 +00:00
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
2023-08-25 08:36:00 +00:00
uint8_t trycnt = 0;
while (!isTTjh()) //判断TT状态
{
rt_thread_mdelay(4000);
trycnt += 1;
if (trycnt > 3)
{
break;
}
}
2023-08-25 08:36:00 +00:00
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 ;
}
2023-07-25 06:55:03 +00:00
//打包数据
uint8_t dout[300];
2023-07-25 06:55:03 +00:00
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] = 1;
#ifdef CRYPT_BEFRE_PACK
//crypt before pack
uint8_t tmp[200];
uint8_t len = cryptSingleMsg(msg->data, msg->len, tmp);
if (len>170) {
LOG_W("length of msg is too long.[%d->%d]",msg->len,len);
}
size_t rst = packMsg(&cfg, tmp, len, dout);//packMsgs
#else
size_t rst = packMsg(&cfg, tmpmsg->data, msg->len, dout);//packMsgs
#endif
2023-07-25 06:55:03 +00:00
LOG_HEX("upSend", 27, dout, rst);
if (rst)
{
2023-07-25 06:55:03 +00:00
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);
}
2023-07-25 06:55:03 +00:00
}
2023-08-25 08:36:00 +00:00
// rt_sem_release(one_msg_send_done);
// list_thread();
return ;
2023-07-25 06:55:03 +00:00
}
/**
*
* @param din
* @param len
* @return
*/
int upSend(uint8_t *din, size_t len)
{
2023-07-26 08:26:53 +00:00
LOG_D("try to upsend to TT.");
//return;
2023-08-25 08:36:00 +00:00
// if (one_msg_send_done == RT_NULL) {
// one_msg_send_done = rt_sem_create("senddone", 1, RT_IPC_FLAG_PRIO);
// }
2023-07-25 06:55:03 +00:00
static SMSG msg;
rt_memset(&msg, 0, sizeof(SMSG));
rt_memcpy(msg.data,din,len);
2023-07-25 06:55:03 +00:00
msg.len=len;
// LOG_D("0--%p",&msg);
//仅创建一个线程用于发送
2023-08-25 08:36:00 +00:00
// 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;
// }
2023-07-25 06:55:03 +00:00
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("upSend", upSend_thread_entry, (void *) &msg, 1024 * 5, 26, 10);
2023-07-25 06:55:03 +00:00
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
2023-07-26 08:26:53 +00:00
return RT_EOK;
2023-07-25 06:55:03 +00:00
}
else
{
LOG_E("thread 'upSend' create failure.");
2023-07-26 08:26:53 +00:00
return -RT_ERROR;
2023-07-25 06:55:03 +00:00
}
}
/**
*
*/
void selfTest(void)
{
// return;
LOG_I("FUNC = selftest");
2023-08-25 08:36:00 +00:00
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_sw(void)
{
uint8_t cfg[]={0x03, 0x1F, 0x03, 0x20, 0x07, 0x1F, 0x09, 0x1E};
setCommWindow(cfg, 8);
}
/**
* 便
* @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) {
2023-09-07 11:46:03 +00:00
// LOG_W("NONE Loc data, using 0x37 replaced");
cnt = pairCnt*10;
memset(loc,0x37,cnt);
}
2023-08-18 07:36:41 +00:00
if (!cnt) {
return 0;
// LOG_W("位置信息还未准备好。");
2023-08-18 07:36:41 +00:00
}
// else {
// memcpy(dout,loc,cnt);
// }
// return cnt;
2023-08-18 07:36:41 +00:00
// 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的定义
2023-08-03 03:04:50 +00:00
/**
*
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;
2023-08-03 03:04:50 +00:00
*/
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);
2023-08-03 03:04:50 +00:00
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");
2023-08-03 03:04:50 +00:00
// 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]
*
* 15MOB(most oldest bit)
* 1610
* @param dout
* @return
*/
#define _LOC_CNT 10
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);
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
*/
2023-09-12 03:40:39 +00:00
RT_WEAK size_t getSignals(uint8_t *dout, uint8_t len);
void packSignal(void)
{
2023-09-12 03:40:39 +00:00
LOG_I("FUNC = get signals");
uint8_t signalMsg[200] =
{ 0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _INFO_SIGNAL >> 8, _INFO_SIGNAL & 0xFF, 0, 0 };
2023-09-12 03:40:39 +00:00
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;
2023-09-12 03:40:39 +00:00
LOG_HEX("signal",16,signalMsg,len);
upSend(signalMsg,len);
}
2023-09-08 09:03:44 +00:00
/**
*
*/
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);
2023-09-08 09:03:44 +00:00
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;
2023-09-12 03:40:39 +00:00
// LOG_HEX("battInfo", 16, battInfo, len); //bccCRC+Tail
2023-09-08 09:03:44 +00:00
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;
2023-09-10 01:43:53 +00:00
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 truefalse
*/
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/rxdata/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");
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:
2023-09-08 09:03:44 +00:00
reportBattInfo();
break;
2023-09-07 07:24:38 +00:00
case _CMD_SET_RTC:
updateSysRTC(din+8, din[7]);
break;
2023-09-12 03:40:39 +00:00
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);
}
2023-07-26 08:26:53 +00:00
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数据0x5AA50xED
*
* @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的指令需要再加工返回数据可能也需要再加工
{
//
2023-07-26 08:26:53 +00:00
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())
2023-07-26 08:26:53 +00:00
{//如果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
2023-08-26 11:36:36 +00:00
#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;
}
}
2023-08-26 11:36:36 +00:00
#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("帧头不匹配");
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
2023-07-26 08:26:53 +00:00
/**
* get file size in byte
2023-07-26 08:26:53 +00:00
* @param file file name whith fullpath
*/
unsigned long getFileSize(char *file)
{
struct stat stat;
char *fullpath, *path;
unsigned long rst=0;
2023-07-26 08:26:53 +00:00
#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;
2023-07-26 08:26:53 +00:00
}
rt_free(fullpath);
rt_free(path);
return rst;
2023-07-26 08:26:53 +00:00
}
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--
*/
2023-07-26 08:26:53 +00:00
int cacheDataToFile(uint8_t *din, size_t len)
{
LOG_I("FUNC = cache to upsend");
2023-08-25 08:36:00 +00:00
int rst = -RT_ERROR;
2023-08-26 11:36:36 +00:00
//return RT_EOK;
//lock file
2023-08-25 08:36:00 +00:00
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);
2023-08-25 08:36:00 +00:00
goto _exit;
}
else
{
2023-08-25 08:36:00 +00:00
iscdlock=1;
int rst = write(fd, din, len);
if (rst != len)
{
LOG_E("write to file %s failed!", f);
2023-08-25 08:36:00 +00:00
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();//更新文件名,置于线程前避免冲突
postFileInfo(f,0);//加入待发列表
}
2023-08-25 08:36:00 +00:00
rst=RT_EOK;
}
_exit:
if (fd) {
close(fd);
}
iscdlock=0;
2023-08-25 08:36:00 +00:00
return rst;
}
void d_cacheData()
{
uint8_t demo[200];
size_t len = sizeof(demo);
memset(demo,0xAB,len);
2023-07-26 08:26:53 +00:00
cacheDataToFile(demo, len);
}
2023-08-26 11:36:36 +00:00
//#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);
2023-07-26 08:26:53 +00:00
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");
2023-07-26 08:26:53 +00:00
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);
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中无匹配帧[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);
// if (chk3SDataValid(tmp, ncnt) != RT_EOK) {
//#ifdef CHECK_3S_DATA
// return;
//#endif
// }
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中无匹配帧[BIN]");
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);
if (n>1) LOG_HEX("frame",16,ndin,cnt);
// if (chk3SDataValid(ndin, cnt) != RT_EOK) {
//#ifdef CHECK_3S_DATA
// return;
//#endif
// }
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);
2023-09-07 07:24:38 +00:00
/**
* 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);
2023-09-07 07:24:38 +00:00
cmd[15]=0xED;
LOG_HEX("cmdRTC",16,cmd,sizeof(cmd));
2023-09-07 07:24:38 +00:00
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));
}
}
2023-09-10 02:09:28 +00:00
/**
* TT工作后设置状态
* @param flag
*/
void setWorkSta(int flag)
{
set_cfg("isWorking", flag);
}
/**
*
* @return
*/
int isNeedRestore(void)
{
2023-09-10 09:16:20 +00:00
int rst = get_cfg("isWorking");
2023-09-10 09:20:43 +00:00
if (rst > 0) {
2023-09-10 09:16:20 +00:00
LOG_W("restoring TT after crash");
}
2023-09-10 09:20:43 +00:00
else {
rst = 0;
}
2023-09-10 09:16:20 +00:00
return rst;
2023-09-10 02:09:28 +00:00
}
#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);
2023-07-26 08:26:53 +00:00
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_sw,msw);
MSH_CMD_EXPORT(set3SRTC,RTC);
#endif