2023-07-10 02:42:26 +00:00
|
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
|
2023-07-18 11:23:48 +00:00
|
|
|
|
#include "func.h"
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
|
|
|
|
#define LOG_TAG "func"
|
|
|
|
|
#define LOG_LVL LOG_LVL_DBG
|
|
|
|
|
#include <ulog.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//3.2.1双模通信功能
|
|
|
|
|
//1为TT通信,0为BD短报文通信
|
|
|
|
|
void setCommMode(int isTT)
|
|
|
|
|
{
|
|
|
|
|
if (isTT) {
|
|
|
|
|
//change mode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//write to cfg file
|
|
|
|
|
set_cfg("commMode", isTT);
|
|
|
|
|
LOG_D("set commMode to %s",isTT?"TT":"BD");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int getCommMode()
|
|
|
|
|
{
|
|
|
|
|
//load from cfg file
|
|
|
|
|
int flag = get_cfg("commMode");
|
|
|
|
|
if (flag < 0) {
|
|
|
|
|
LOG_W("get mode fault.");
|
|
|
|
|
}
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//3.2.2状态自检
|
2023-07-19 10:57:54 +00:00
|
|
|
|
|
2023-07-18 11:23:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* 获取磁盘剩余空间大小,单位MB
|
|
|
|
|
* @param path指定磁盘挂载的路径,为空时表示挂载在根目录的磁盘
|
|
|
|
|
* @return 返回结果,单位MB
|
|
|
|
|
*/
|
|
|
|
|
static uint16_t getFreeSpace(const char *path)
|
2023-07-10 02:42:26 +00:00
|
|
|
|
{
|
2023-07-18 11:23:48 +00:00
|
|
|
|
long long cap;
|
|
|
|
|
struct statfs buffer;
|
|
|
|
|
int result = dfs_statfs(path ? path : "/", &buffer);
|
|
|
|
|
if (result != 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_E("dfs_statfs failed.");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
2023-07-18 11:23:48 +00:00
|
|
|
|
cap = (uint16_t)((long long)buffer.f_bsize) * ((long long)buffer.f_bfree) / 1024LL / 1024LL ;//转换为MB
|
|
|
|
|
return cap;
|
|
|
|
|
}
|
2023-07-19 10:57:54 +00:00
|
|
|
|
|
|
|
|
|
void d_getFreeSpace()
|
2023-07-18 11:23:48 +00:00
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
2023-07-18 11:23:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* 獲取電池電量。
|
|
|
|
|
* @return 返回電量百分比
|
|
|
|
|
*/
|
|
|
|
|
RT_WEAK int getPowerLevel(void)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-07-19 10:57:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-07-18 11:23:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* 上傳天通數據
|
|
|
|
|
* @param din 待發送數據
|
|
|
|
|
* @param len 待發送數據的長度
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2023-07-19 10:57:54 +00:00
|
|
|
|
RT_WEAK int upSend(uint8_t *din, size_t len)
|
2023-07-18 11:23:48 +00:00
|
|
|
|
{
|
2023-07-20 07:29:37 +00:00
|
|
|
|
//此函数有打包操作,需线程操作
|
|
|
|
|
LOG_D("upsend.");
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
uint8_t dout[200];
|
|
|
|
|
//打包数据
|
|
|
|
|
static MSG cfg;
|
|
|
|
|
rt_memset(&cfg, 0, sizeof(MSG)); // 分配空间
|
|
|
|
|
char *fin;
|
|
|
|
|
time2Str(fin);
|
|
|
|
|
packInit(&cfg, fin, 0); //写入配置
|
|
|
|
|
size_t rst = packMsg(&cfg, din, len, dout);
|
2023-07-20 07:29:37 +00:00
|
|
|
|
LOG_HEX("upSend", 16, dout, rst);
|
2023-07-19 10:57:54 +00:00
|
|
|
|
return 0;
|
2023-07-18 11:23:48 +00:00
|
|
|
|
}
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
/**
|
|
|
|
|
* 系统自检,自动发送自检结果
|
|
|
|
|
*/
|
|
|
|
|
void selfTest()
|
2023-07-18 11:23:48 +00:00
|
|
|
|
{
|
2023-07-20 07:29:37 +00:00
|
|
|
|
LOG_D("FUNC = selftest");
|
2023-07-18 11:23:48 +00:00
|
|
|
|
rt_uint8_t rst[100]={0x5A, 0xA5, 0x32, 0x3E, 0x0A, 0x41};
|
|
|
|
|
int p = 6;
|
|
|
|
|
rt_uint8_t sysSta=1,xh=0,jh=0,commSpeed=0;
|
2023-07-19 10:57:54 +00:00
|
|
|
|
//长度
|
2023-07-18 11:23:48 +00:00
|
|
|
|
rst[p++]=0x00;
|
|
|
|
|
rst[p++]=0x09;
|
|
|
|
|
|
|
|
|
|
rst[p++] = sysSta;
|
|
|
|
|
rst[p++] = xh;
|
|
|
|
|
rst[p++] = jh;
|
|
|
|
|
rst[p++] = commSpeed;
|
|
|
|
|
rst[p++] = getPowerLevel();
|
|
|
|
|
|
|
|
|
|
//flash 剩餘空間
|
|
|
|
|
uint16_t cap = getFreeSpace("/");
|
|
|
|
|
rst[p++] = (uint8_t)(cap >> 8);
|
|
|
|
|
rst[p++] = (uint8_t)(cap & 0xff);
|
|
|
|
|
|
|
|
|
|
//SD卡剩餘空間
|
|
|
|
|
cap = getFreeSpace("/sd");
|
|
|
|
|
rst[p++] = (uint8_t)(cap >> 8);
|
|
|
|
|
rst[p++] = (uint8_t)(cap & 0xff);
|
|
|
|
|
|
|
|
|
|
rst[p++] = bccCRC(rst+2, p-1); ////校验位为1个字节,采用异或运算,从指令的第3个字节开始,到奇偶校验位的前一个字节结束
|
|
|
|
|
rst[p++] = 0xED; //结束位
|
|
|
|
|
|
|
|
|
|
LOG_HEX("selfTestRes",16,rst,p);
|
2023-07-10 02:42:26 +00:00
|
|
|
|
//发送结果
|
2023-07-19 10:57:54 +00:00
|
|
|
|
upSend(rst,p);
|
2023-07-10 02:42:26 +00:00
|
|
|
|
}
|
2023-07-19 10:57:54 +00:00
|
|
|
|
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
|
|
|
|
//3.2.3日志记录
|
|
|
|
|
//日志功能由各函数通过LOG_D()实现
|
|
|
|
|
|
|
|
|
|
//3.2.4自毁功能
|
|
|
|
|
/**
|
|
|
|
|
* 设置自毁功能开关
|
|
|
|
|
* @param setON 1-自毁功能开启,0-关闭
|
|
|
|
|
*/
|
|
|
|
|
void setSelfDestructSWT(int setON)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//write to cfg file
|
|
|
|
|
set_cfg("SelfDesSW", setON);
|
|
|
|
|
LOG_D("set SelfDesSW to %s",setON?"ON":"OFF");
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 获取自毁开关状态
|
|
|
|
|
* @return 1-自毁功能开启,0-关闭
|
|
|
|
|
*/
|
|
|
|
|
int getSelfDestructSWT()
|
|
|
|
|
{
|
|
|
|
|
//load from cfg file
|
|
|
|
|
int flag = get_cfg("SelfDesSW");
|
|
|
|
|
if (flag < 0) {
|
|
|
|
|
LOG_W("get mode fault.");
|
|
|
|
|
}
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 启动自毁
|
|
|
|
|
*/
|
|
|
|
|
void selfDestruct()
|
|
|
|
|
{
|
|
|
|
|
if (getSelfDestructSWT()) {
|
|
|
|
|
//硬件自毁
|
|
|
|
|
LOG_W("SELF DESTRUCT START.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//3.2.5开、关窗功能
|
|
|
|
|
extern void updateAlarm(int *t);
|
|
|
|
|
/**
|
|
|
|
|
* 更新开窗时间,目前支持两组开窗时段。更新会清除之前的开窗设置
|
|
|
|
|
*/
|
|
|
|
|
void setCommWindow(int *t)
|
|
|
|
|
{
|
|
|
|
|
updateAlarm(t);
|
|
|
|
|
LOG_D("更新开窗时间完成。");
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 手动控制开窗
|
|
|
|
|
* @param t 开窗时长,单位分钟,时间到则自动关窗。t=0时需要手动关窗。
|
|
|
|
|
*/
|
|
|
|
|
void openWindow(int t)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//开启TT
|
|
|
|
|
pwTT_thread_entry("1");//开机
|
|
|
|
|
if (!t) {
|
|
|
|
|
LOG_D("手动开窗完成,需手动关窗。");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//设置定时器,定时器到则关窗
|
|
|
|
|
/* 创建定时器,单次定时器 */
|
|
|
|
|
rt_timer_t timer1;
|
|
|
|
|
timer1 = rt_timer_create("window", pwTT_thread_entry,
|
|
|
|
|
0, rt_tick_from_millisecond(t*60*1000),
|
|
|
|
|
RT_TIMER_FLAG_ONE_SHOT);
|
|
|
|
|
/* 启动定时器 */
|
|
|
|
|
if (timer1 != RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
rt_timer_start(timer1);
|
|
|
|
|
LOG_D("手动开窗完成,%d分钟后自动关窗。",t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 手动关窗
|
|
|
|
|
*/
|
|
|
|
|
void closeWindow()
|
|
|
|
|
{
|
|
|
|
|
pwTT_thread_entry("0");//关 机
|
|
|
|
|
LOG_D("手动关窗完成。");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//3.2.6工作参数配置、状态查询
|
|
|
|
|
//包含浮体自身、标体透传、两者结合
|
|
|
|
|
//这里主要实现浮体自身
|
|
|
|
|
//浮体自身的参数配置各功能函数有实现,此处需规定参数下发协议和解码实现
|
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
//获取当前位置
|
|
|
|
|
/**
|
|
|
|
|
* 获取当前经纬度信息
|
|
|
|
|
* @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);
|
|
|
|
|
while (!cnt)
|
|
|
|
|
{
|
|
|
|
|
static i=0;
|
|
|
|
|
LOG_W("位置信息还未准备好。");
|
|
|
|
|
rt_thread_mdelay(4000);//状态数据默认3s更新一次
|
|
|
|
|
cnt = getLoc(loc,pairCnt);
|
|
|
|
|
if (i++ > 20) {
|
|
|
|
|
LOG_E("位置信息获取异常");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
memcpy(dout,loc,cnt);
|
|
|
|
|
return cnt;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* c回应深度数据,含位置信息
|
|
|
|
|
* @param din
|
|
|
|
|
* @param len
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
int reportDepth(uint8_t *din,size_t len)
|
|
|
|
|
{
|
|
|
|
|
uint8_t rst[len];
|
|
|
|
|
memcpy(rst,din,len);
|
|
|
|
|
// 000000000000000000005AA53E320608000A170407101B33FFFFFFFF24ED
|
|
|
|
|
|
|
|
|
|
getAndCheckLoc(rst+0,1);//有10个位置的空余字节,尚不清楚定义
|
|
|
|
|
upSend(rst, len);
|
|
|
|
|
}
|
|
|
|
|
//天通指令类型:0x70 0x01
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
|
|
|
|
//3.2.8定时自报位置信息
|
|
|
|
|
//每小时传数据时同步传位置信息
|
2023-07-19 10:57:54 +00:00
|
|
|
|
//与告警信息共用编码方式
|
|
|
|
|
//首字节00为定时发送,未检测围栏;其它为在围栏外
|
|
|
|
|
//单次最多可上报15条位置信息
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 按15条经纬度打包位置信息
|
|
|
|
|
* @param dout 存储位置信息的数组
|
|
|
|
|
* @return 数组大小
|
|
|
|
|
*/
|
|
|
|
|
static int packLocMsg(uint8_t *dout)
|
|
|
|
|
{
|
|
|
|
|
uint8_t alertMsg[200] =
|
|
|
|
|
{ 0x5A, 0xA5, ADDR_ANJI, ADDR_TT, _CFG_LOCATION_ALERT >> 8, _CFG_LOCATION_ALERT & 0xFF, 0, 0 };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
alertMsg[8] = 0; //首字节00为定时发送,未检测围栏;其它为在围栏外
|
|
|
|
|
int len = time2Byte(alertMsg+9);//添加时间戳
|
|
|
|
|
len += (getAndCheckLoc(alertMsg + 9 + len, 15)+1); //p指向第2个数据
|
|
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
packLocMsg(tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 加密位置信息。对位置信息的更改需在加密前操作
|
|
|
|
|
* @param din 存储待加密位置信息的数组
|
|
|
|
|
* @param len 带加密长度
|
|
|
|
|
* @param dout 存储加密结果的数组
|
|
|
|
|
* @return 加密后的长度
|
|
|
|
|
*/
|
|
|
|
|
static int cryptLocMsg(uint8_t *din, size_t len, uint8_t *dout)
|
|
|
|
|
{ //加密。因加密后数据长度会变化,故不能只加密位置数据。
|
|
|
|
|
uint8_t cd[200]={0xAB,0xAB};
|
|
|
|
|
size_t nlen = 0;
|
|
|
|
|
|
|
|
|
|
//#define FULL_DATA_CRYPT
|
|
|
|
|
#ifdef FULL_DATA_CRYPT
|
|
|
|
|
nlen = cryp_data(din, len, cd);
|
|
|
|
|
#else
|
|
|
|
|
//单独加密时在加密后数据头部添加0xABAB便于识别、解析
|
|
|
|
|
nlen = cryp_data(din, len, cd + 2) + 2;
|
|
|
|
|
#endif
|
|
|
|
|
memcpy(dout, cd, nlen);
|
|
|
|
|
return nlen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int packAndSendLoc()
|
|
|
|
|
{
|
|
|
|
|
uint8_t rst[200];
|
|
|
|
|
int len = packLocMsg(rst);
|
|
|
|
|
LOG_D("len=%d",len);
|
|
|
|
|
len = cryptLocMsg(rst, len, rst);
|
|
|
|
|
LOG_D("len=%d",len);
|
|
|
|
|
LOG_HEX("crypt",16,rst,len);
|
|
|
|
|
|
|
|
|
|
}
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
|
|
|
|
//3.2.9深度异常告警
|
|
|
|
|
int packDeepMsg(uint8_t *din, int len, uint8_t *dout)
|
|
|
|
|
{
|
|
|
|
|
//获取并更新位置信息
|
|
|
|
|
uint8_t loc[]={};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rt_memcpy(din+6, loc, 8);//位置数据从【】字节开始,共8个字节
|
|
|
|
|
|
|
|
|
|
//加密。因加密后数据长度会变化,故不能只加密位置数据。
|
2023-07-19 10:57:54 +00:00
|
|
|
|
size_t nlen = cryptByte(din, len, dout);
|
|
|
|
|
LOG_D("位置数据加密完成");
|
|
|
|
|
upSend(dout, nlen);
|
2023-07-10 02:42:26 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//3.2.10位置异常告警
|
|
|
|
|
//map.c中实现
|
|
|
|
|
/**
|
|
|
|
|
* 判断是否在电子围栏内部
|
|
|
|
|
* @param x 当前位置经度
|
|
|
|
|
* @param y 当前位置纬度
|
|
|
|
|
* @return 在内部则返回true,反之false
|
|
|
|
|
*/
|
|
|
|
|
static int isInFence(float x, float y)
|
|
|
|
|
{
|
|
|
|
|
float polyX[]={},polyY[]={};
|
|
|
|
|
int polyCorners = mapParse("/map.geojson",polyX,polyY);
|
|
|
|
|
return pointInPolygon(polyCorners,polyX,polyY,x,y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置位置告警功能开关
|
|
|
|
|
* @param setON 1-告警功能开启,0-关闭
|
|
|
|
|
*/
|
|
|
|
|
void setLocationAlertSWT(int setON)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查是否在电子围栏内部,并发出告警
|
|
|
|
|
*/
|
|
|
|
|
void checkLocAndAlert()
|
|
|
|
|
{
|
|
|
|
|
//get Lon and Lat
|
2023-07-19 10:57:54 +00:00
|
|
|
|
uint8_t loc[8];
|
|
|
|
|
getAndCheckLoc(loc,1);
|
|
|
|
|
float x,y =0;
|
|
|
|
|
memcpy(&x,loc,4);
|
|
|
|
|
memcpy(&y,loc+4,4);
|
|
|
|
|
|
2023-07-10 02:42:26 +00:00
|
|
|
|
int isIN = isInFence(x, y);
|
|
|
|
|
if (isIN) {
|
|
|
|
|
LOG_I("设备在预设范围内,位置正常。");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
LOG_W("警告!设备不在预设范围内!");
|
2023-07-19 10:57:54 +00:00
|
|
|
|
uint8_t msg[200];
|
|
|
|
|
int len = packLocMsg(msg);
|
|
|
|
|
len = cryptLocMsg(msg,len,msg);
|
|
|
|
|
//告警信息与3.2.8定时自报位置信息的共用编码方式
|
|
|
|
|
// uint8_t alertMsg[]={0x5A,0xA5,ADDR_ANJI,ADDR_TT};
|
|
|
|
|
// alertMsg[4] = _CFG_LOCATION_ALERT >> 8;
|
|
|
|
|
// alertMsg[5] = _CFG_LOCATION_ALERT & 0xFF;
|
|
|
|
|
//
|
|
|
|
|
// //加密。
|
|
|
|
|
// uint8_t cd[200];
|
|
|
|
|
// size_t nlen = cryptByte(din, len, cd);
|
|
|
|
|
// upSend(alertMsg, sizeof(alertMsg));
|
2023-07-10 02:42:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//3.2.12数据存储区清空
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* 采用格式化命令对存储区进行清空,谨慎使用!
|
|
|
|
|
*/
|
|
|
|
|
void clearAllData()
|
|
|
|
|
{
|
|
|
|
|
mkfs("elm","sd0");//format SD
|
2023-07-19 10:57:54 +00:00
|
|
|
|
mkfs("elm", "W25Q128");//format flash
|
2023-07-10 02:42:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief TT根据下发的指令执行对应的功能
|
|
|
|
|
*
|
|
|
|
|
* @param din 待执行的指令数据
|
|
|
|
|
* @param len 数据长度,单位字节
|
|
|
|
|
*/
|
|
|
|
|
void ttRunCMD(uint8_t *din, size_t len)
|
|
|
|
|
{
|
2023-07-19 10:57:54 +00:00
|
|
|
|
/**
|
|
|
|
|
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
|
|
|
|
| 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[]
|
2023-07-18 11:23:48 +00:00
|
|
|
|
switch (cmd)
|
|
|
|
|
{
|
|
|
|
|
case _CFG_COMM_MODE:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
setCommMode(din[8]);
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CMD_SELF_TEST:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
selfTest();
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CFG_SELF_DESTRUCT:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
setSelfDestructSWT(din[8]);
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CMD_SELF_DESTRUCT:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
selfDestruct();
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CFG_COMM_WINDOW:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
setCommWindow(din+8);//只支持两组开窗
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CMD_OPEN_WINDOW:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
openWindow(din[7]?((din[8] << 8) + din[9]):0);//两字节开窗时间
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CMD_CLOSE_WINDOW:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
closeWindow();
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CFG_LOCATION_ALERT:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
setLocationAlertSWT(din[8]);
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
case _CMD_CLEAR_DATA:
|
2023-07-19 10:57:54 +00:00
|
|
|
|
clearAllData();
|
2023-07-18 11:23:48 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
LOG_W("未支持的指令。");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-20 07:29:37 +00:00
|
|
|
|
RT_WEAK int xpParse(uint8_t * din, size_t len)
|
2023-07-19 10:57:54 +00:00
|
|
|
|
{
|
|
|
|
|
LOG_D("直接调用小彭的函数进行处理。");
|
2023-07-20 07:29:37 +00:00
|
|
|
|
return 0;
|
2023-07-19 10:57:54 +00:00
|
|
|
|
}
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
|
|
|
|
//原计划将指令粗解析放在上位机,考虑到上位机到位时间晚,现放到MCU端
|
|
|
|
|
/**
|
|
|
|
|
* @brief 校验、解析3S数据,以0x5AA5开头0xED结尾。
|
|
|
|
|
*
|
|
|
|
|
* @param din 待解析数据
|
|
|
|
|
* @param count 待解析数据长度
|
|
|
|
|
*/
|
|
|
|
|
void parse3SData(uint8_t *din, size_t count)
|
|
|
|
|
{
|
2023-07-19 10:57:54 +00:00
|
|
|
|
/**
|
|
|
|
|
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
|
|
|
|
| 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 |
|
|
|
|
|
+--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+
|
|
|
|
|
*/
|
|
|
|
|
uint8_t head[]={0x5A,0xA5};
|
2023-07-18 11:23:48 +00:00
|
|
|
|
//header[4] addr[2] func[2] len[2] data[N] fcrc[1] tail[1]
|
|
|
|
|
uint8_t rst = memcmp(din,head,sizeof(head[0]));
|
|
|
|
|
if (rst)
|
|
|
|
|
{
|
|
|
|
|
LOG_W("0x%02X%02X != 0x%5AA5,帧头不匹配",din[0],din[1]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (din[count-2] != bccCRC(din+2,count-2-2))//校验位为1个字节,采用异或运算,从指令的第3个字节开始,到奇偶校验位的前一个字节结束
|
|
|
|
|
{
|
|
|
|
|
LOG_W("0x%02X != 0x%02X,校验值不匹配",din[count-2] , bccCRC(din+2,count-2-2));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (din[count-1] != 0xED)
|
|
|
|
|
{
|
|
|
|
|
LOG_W("0x%02X != 0xED,帧尾不匹配",din[count-1]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
// uint8_t dout[200];
|
|
|
|
|
// size_t len=0;
|
2023-07-20 07:29:37 +00:00
|
|
|
|
if (din[2] == ADDR_TT)//仅给TT的消息
|
2023-07-18 11:23:48 +00:00
|
|
|
|
{
|
2023-07-19 10:57:54 +00:00
|
|
|
|
ttRunCMD(din,count);
|
2023-07-18 11:23:48 +00:00
|
|
|
|
}
|
|
|
|
|
if (din[3] == ADDR_3S)//给3S的指令,需要再加工,返回数据可能也需要再加工
|
|
|
|
|
{
|
|
|
|
|
//
|
2023-07-19 10:57:54 +00:00
|
|
|
|
|
|
|
|
|
xpParse(din,count);
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//以下处理逻辑作废
|
|
|
|
|
//绝大部分数据均需要转换。详见《主要指令一览》
|
|
|
|
|
// int cmd = (din[4]<<8) + din[5]
|
|
|
|
|
// switch (cmd)
|
|
|
|
|
// {
|
|
|
|
|
// case _CMD_RTC_CHECK:
|
|
|
|
|
// case 0:
|
|
|
|
|
// /* 不转换 */
|
|
|
|
|
|
|
|
|
|
// break;
|
|
|
|
|
|
|
|
|
|
// default:
|
|
|
|
|
// //转换
|
|
|
|
|
// char rst[]="";
|
|
|
|
|
// bytes2str(din,count,16,"",rst);
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
// //发送
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 解析TT数据,TT收到的指令必是单指令,解析容易。
|
|
|
|
|
*
|
|
|
|
|
* @param din
|
|
|
|
|
* @param len
|
|
|
|
|
*/
|
|
|
|
|
void parseTTData(uint8_t *din, size_t len)
|
|
|
|
|
{
|
2023-07-19 10:57:54 +00:00
|
|
|
|
/**
|
|
|
|
|
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
|
|
|
|
* | 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,0x22 | 0x70,0x21 | 0x00,0xAA | 0x00 | 0x27,0x22,0x22,0x22 | |
|
|
|
|
|
* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+
|
|
|
|
|
*/
|
2023-07-18 11:23:48 +00:00
|
|
|
|
uint8_t head[]={0x88,0xAA,0xBB,0x88, 0x00,0x01, 0x00,0x22, 0x70,0x21, 0x00,0xaa, 0x00, 0x27,0x22,0x22,0x22 };
|
|
|
|
|
//fstart[4] fnum[2] bak[2] ftype[2] fdlen[2] fcrc[1] ftccid[4]
|
2023-07-20 07:29:37 +00:00
|
|
|
|
// uint8_t rst[10];
|
|
|
|
|
// size_t n=isInByte(din, len, head, 10, rst);
|
|
|
|
|
// uint8_t ndin[200];
|
|
|
|
|
// for (size_t i = 0; i < n; i++)
|
|
|
|
|
// {
|
|
|
|
|
// int n=rst[i+1]
|
|
|
|
|
// memcpy(ndin,din,rst[i+1]-rst[i]);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
uint8_t rst = memcmp(din,head,10);//只比较到ftype
|
2023-07-18 11:23:48 +00:00
|
|
|
|
if (rst)
|
|
|
|
|
{
|
|
|
|
|
LOG_W("帧头不匹配");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t id[30]="";
|
|
|
|
|
LOG_D("get new data: id=\"%s\", cur/all=[%d/%d]",bytes2str(din+17,7,10,"_",id),din[25],din[26]);
|
|
|
|
|
if (din[24] >> 7) // fcfg=数据类型。解析TT收到的数据时仅需解析“命令”,“数据”传输是单向的。
|
|
|
|
|
{
|
|
|
|
|
LOG_W("浮标端仅接受指令,暂不支持数据。");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
uint8_t rawData[200];
|
|
|
|
|
uint8_t rawDataLen=len-27;
|
|
|
|
|
memcpy(rawData, din + 27, rawDataLen);
|
|
|
|
|
parse3SData(rawData,rawDataLen);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// switch (din[24] & 0x7F) // 识别指令的目标地址
|
|
|
|
|
// {
|
|
|
|
|
// case _ONLY_FOR_TT:
|
|
|
|
|
// ttRunCMD(rawData, len - 27);
|
|
|
|
|
// break;
|
|
|
|
|
// case _ONLY_FOR_3S:
|
|
|
|
|
// /* code */
|
|
|
|
|
// // 发送数据至3S
|
|
|
|
|
// break;
|
|
|
|
|
// case _FOR_BOTH:
|
|
|
|
|
// // 发送数据至3S
|
|
|
|
|
|
|
|
|
|
// // 等待返回数据
|
|
|
|
|
|
|
|
|
|
// // 打包
|
|
|
|
|
|
|
|
|
|
// // 上传
|
|
|
|
|
// break;
|
|
|
|
|
|
|
|
|
|
// default:
|
|
|
|
|
// LOG_W("未识别到指令的目标地址");
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-20 07:29:37 +00:00
|
|
|
|
/**
|
|
|
|
|
* 缓存任务数据
|
|
|
|
|
* @param din 单次收到的任务数据
|
|
|
|
|
* @param len 任务数据长度
|
|
|
|
|
* @return 0--正常,-1--异常
|
|
|
|
|
*/
|
2023-07-19 10:57:54 +00:00
|
|
|
|
int cacheData(uint8_t *din, size_t len)
|
|
|
|
|
{
|
|
|
|
|
static int cnt = 0;
|
|
|
|
|
LOG_D("cached size=%d", cnt);
|
|
|
|
|
char rootDir[22] = "/sd/rxdata/";
|
|
|
|
|
// if (!opendir(rootDir))
|
|
|
|
|
{
|
|
|
|
|
mkdir(rootDir, 0);
|
|
|
|
|
}
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
strcat(rootDir, "2023_07_19/");
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
//name of cachefile
|
|
|
|
|
static char f[60] = "";
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
if (cnt == 0 || cnt > 1024)
|
|
|
|
|
{
|
|
|
|
|
//广播待发送文件
|
|
|
|
|
cnt = 0;
|
|
|
|
|
//更新时戳
|
|
|
|
|
char ts[30] = "";
|
|
|
|
|
time2Str(ts);
|
|
|
|
|
//更新文件夹
|
|
|
|
|
strncpy(rootDir + strlen(rootDir) - 9, ts, 8);
|
|
|
|
|
// if (!opendir(rootDir))
|
|
|
|
|
{
|
|
|
|
|
mkdir(rootDir, 0);
|
|
|
|
|
}
|
|
|
|
|
//更新文件名
|
|
|
|
|
f[0] = '\0';
|
|
|
|
|
strcat(f, rootDir);
|
|
|
|
|
// strcpy(f,rootDir);
|
|
|
|
|
strcat(f, "23_07_19_16_38_36_36.bin");
|
|
|
|
|
LOG_D("need to creat new file");
|
|
|
|
|
strncpy(f + strlen(rootDir), ts, strlen(ts));
|
|
|
|
|
}
|
|
|
|
|
LOG_D("f=%s", f);
|
|
|
|
|
int fd = open(f, O_WRONLY | O_CREAT | O_APPEND);
|
|
|
|
|
if (fd < 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_E("open file %s failed!", f);
|
2023-07-20 07:29:37 +00:00
|
|
|
|
return -RT_ERROR;
|
2023-07-19 10:57:54 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int rst = write(fd, din, len);
|
|
|
|
|
if (rst != len)
|
|
|
|
|
{
|
|
|
|
|
LOG_E("write to file %s failed!", f);
|
|
|
|
|
close(fd);
|
2023-07-20 07:29:37 +00:00
|
|
|
|
return -RT_ERROR;
|
2023-07-19 10:57:54 +00:00
|
|
|
|
}
|
|
|
|
|
cnt += len;
|
|
|
|
|
close(fd);
|
|
|
|
|
}
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
void d_cacheData()
|
|
|
|
|
{
|
|
|
|
|
uint8_t demo[200];
|
|
|
|
|
size_t len = sizeof(demo);
|
|
|
|
|
memset(demo,0xAB,len);
|
|
|
|
|
cacheData(demo, len);
|
|
|
|
|
}
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
#define FUNC_DEMO
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
2023-07-19 10:57:54 +00:00
|
|
|
|
#ifdef FUNC_DEMO //测试时导出命令到控制台
|
|
|
|
|
MSH_CMD_EXPORT(d_getFreeSpace,getFreeSpace);
|
|
|
|
|
MSH_CMD_EXPORT(selfTest,sysSelfTest);
|
|
|
|
|
MSH_CMD_EXPORT(d_packLocMsg,dpackLocMsg);
|
|
|
|
|
MSH_CMD_EXPORT(packAndSendLoc,packAndSendLoc);
|
|
|
|
|
MSH_CMD_EXPORT(d_cacheData,d_cacheData);
|
|
|
|
|
#endif
|
2023-07-18 11:23:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|