From a1e89cd86b0a9c97ec8f1897611b6b72a7d196a5 Mon Sep 17 00:00:00 2001 From: "CSSC-WORK\\murmur" Date: Wed, 19 Jul 2023 18:57:54 +0800 Subject: [PATCH] =?UTF-8?q?func.c=20=E6=B7=BB=E5=8A=A0packLocMsg=20cacheDa?= =?UTF-8?q?ta=20=E7=AD=89=E5=87=BD=E6=95=B0=EF=BC=8C=E5=B9=B6=E6=B5=8B?= =?UTF-8?q?=E8=AF=95ok=20tools.c=20=E6=9B=B4=E6=96=B0time2Str=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applications/func/func.c | 337 +++++++++++++++++++++++++++++++++------ applications/func/func.h | 20 ++- applications/tools.c | 28 ++-- 3 files changed, 318 insertions(+), 67 deletions(-) diff --git a/applications/func/func.c b/applications/func/func.c index 4c22e01..1239e31 100644 --- a/applications/func/func.c +++ b/applications/func/func.c @@ -8,9 +8,7 @@ * 2023-07-06 murmur the first version */ -#include -#include -#include + #include "func.h" #define LOG_TAG "func" @@ -47,10 +45,7 @@ int getCommMode() } //3.2.2状态自检 -/** - * 系统自检,自动发送自检结果 - */ -extern int df(const char *path); + /** * 获取磁盘剩余空间大小,单位MB * @param path指定磁盘挂载的路径,为空时表示挂载在根目录的磁盘 @@ -70,13 +65,13 @@ static uint16_t getFreeSpace(const char *path) cap = (uint16_t)((long long)buffer.f_bsize) * ((long long)buffer.f_bfree) / 1024LL / 1024LL ;//转换为MB return cap; } -void ddf() + +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); } -MSH_CMD_EXPORT(ddf,getFreeSpace); /** * 獲取電池電量。 @@ -86,22 +81,38 @@ RT_WEAK int getPowerLevel(void) { return 0; } + + + /** * 上傳天通數據 * @param din 待發送數據 * @param len 待發送數據的長度 * @return */ -RT_WEAK int uploadData(uint8_t *din, size_t len) +RT_WEAK int upSend(uint8_t *din, size_t len) { -return 0; + 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); + LOG_HEX("upSend", 16, din, rst); + return 0; } -void sysSelfTest() +/** + * 系统自检,自动发送自检结果 + */ +void selfTest() { 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; + //长度 rst[p++]=0x00; rst[p++]=0x09; @@ -126,9 +137,9 @@ void sysSelfTest() LOG_HEX("selfTestRes",16,rst,p); //发送结果 - uploadData(rst,p); + upSend(rst,p); } -MSH_CMD_EXPORT(sysSelfTest,sysSelfTest); + //3.2.3日志记录 //日志功能由各函数通过LOG_D()实现 @@ -221,9 +232,131 @@ void closeWindow() //这里主要实现浮体自身 //浮体自身的参数配置各功能函数有实现,此处需规定参数下发协议和解码实现 +//获取当前位置 +/** + * 获取当前经纬度信息 + * @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 //3.2.8定时自报位置信息 //每小时传数据时同步传位置信息 +//与告警信息共用编码方式 +//首字节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); + +} //3.2.9深度异常告警 int packDeepMsg(uint8_t *din, int len, uint8_t *dout) @@ -235,18 +368,10 @@ int packDeepMsg(uint8_t *din, int len, uint8_t *dout) rt_memcpy(din+6, loc, 8);//位置数据从【】字节开始,共8个字节 //加密。因加密后数据长度会变化,故不能只加密位置数据。 - uint8_t cd[200]; - size_t nlen = cryp_data(din, len, cd); + size_t nlen = cryptByte(din, len, dout); + LOG_D("位置数据加密完成"); + upSend(dout, nlen); - //打包数据 - static MSG cfg; - rt_memset(&cfg, 0, sizeof(MSG)); // 分配空间 - char *fin; - time2Str(fin); - packInit(&cfg, fin, 0);//写入配置 - size_t rst = packMsg(&cfg, din, nlen, dout); - LOG_D("位置数据打包完成"); - return rst; } //3.2.10位置异常告警 @@ -279,18 +404,30 @@ void setLocationAlertSWT(int setON) void checkLocAndAlert() { //get Lon and Lat - float x,y; - if (!x || !y) { - LOG_W("location info is not ready."); - return; - } + uint8_t loc[8]; + getAndCheckLoc(loc,1); + float x,y =0; + memcpy(&x,loc,4); + memcpy(&y,loc+4,4); + int isIN = isInFence(x, y); if (isIN) { LOG_I("设备在预设范围内,位置正常。"); } else { LOG_W("警告!设备不在预设范围内!"); - //告警 + 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)); } } @@ -301,8 +438,8 @@ void checkLocAndAlert() */ void clearAllData() { - mkfs("elm", "W25Q128");//format flash mkfs("elm","sd0");//format SD + mkfs("elm", "W25Q128");//format flash } @@ -316,27 +453,43 @@ void clearAllData() */ void ttRunCMD(uint8_t *din, size_t len) { - int cmd=(din[4]<<8) + din[5]; +/** ++--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+ +| 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: - /* code */ + 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);//只支持两组开窗 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; default: LOG_W("未支持的指令。"); @@ -345,7 +498,10 @@ void ttRunCMD(uint8_t *din, size_t len) } - +RT_WEAK xpParse(uint8_t * din, size_t len) +{ + LOG_D("直接调用小彭的函数进行处理。"); +} //原计划将指令粗解析放在上位机,考虑到上位机到位时间晚,现放到MCU端 /** @@ -356,7 +512,14 @@ void ttRunCMD(uint8_t *din, size_t len) */ void parse3SData(uint8_t *din, size_t count) { - uint8_t head[]={0x5a,0xA5}; +/** ++--------+--------+------------+------------+---------+--------+------+------+-------+-----+-------+---------+------+ +| 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}; //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) @@ -376,18 +539,17 @@ void parse3SData(uint8_t *din, size_t count) return; } - uint8_t dout[200]; - size_t len=0; +// uint8_t dout[200]; +// size_t len=0; if (din[3] == ADDR_TT)//仅给TT的消息 { - ttRunCMD(din,len); + ttRunCMD(din,count); } if (din[3] == ADDR_3S)//给3S的指令,需要再加工,返回数据可能也需要再加工 { // - LOG_D("直接调用小彭的函数进行处理。"); - // extern void xpParse(uint8_t *din, size_t len); - // xpParse(din,len); + + xpParse(din,count); @@ -420,6 +582,14 @@ void parse3SData(uint8_t *din, size_t count) */ 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,0x22 | 0x70,0x21 | 0x00,0xAA | 0x00 | 0x27,0x22,0x22,0x22 | | +* +---------------------+-----------+-----------+-----------+-----------+---------+---------------------+------------+ +*/ 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] uint8_t rst = memcmp(din,head,sizeof(head)); @@ -469,13 +639,82 @@ void parseTTData(uint8_t *din, size_t len) - - - - - - - +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); + } + + strcat(rootDir, "2023_07_19/"); + + //name of cachefile + static char f[60] = ""; + + 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); + return RT_ERROR; + } + else + { + int rst = write(fd, din, len); + if (rst != len) + { + LOG_E("write to file %s failed!", f); + close(fd); + return RT_ERROR; + } + cnt += len; + close(fd); + } + + return RT_EOK; +} +void d_cacheData() +{ + uint8_t demo[200]; + size_t len = sizeof(demo); + memset(demo,0xAB,len); + cacheData(demo, len); +} + + +#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(packAndSendLoc,packAndSendLoc); +MSH_CMD_EXPORT(d_cacheData,d_cacheData); +#endif diff --git a/applications/func/func.h b/applications/func/func.h index 09ce921..24f0087 100644 --- a/applications/func/func.h +++ b/applications/func/func.h @@ -10,6 +10,10 @@ #ifndef APPLICATIONS_FUNC_FUNC_H_ #define APPLICATIONS_FUNC_FUNC_H_ +#include +#include +#include +#include enum { _ONLY_FOR_TT=0, @@ -46,22 +50,22 @@ enum // CFG 代表更新配置 // CMD 代表执行相关功能 -#define _CFG_COMM_MODE 0x00 // 配置工作方式 +#define _CFG_COMM_MODE 0x7000 // 配置工作方式 -#define _CMD_SELF_TEST 0x01 // 执行自检 +#define _CMD_SELF_TEST 0x7001 // 执行自检 #define _CFG_SELF_DESTRUCT 0x0A21 // 设置自毁开关 -#define _CMD_SELF_DESTRUCT 0x02 // 执行自毁 +#define _CMD_SELF_DESTRUCT 0x7002 // 执行自毁 -#define _CFG_COMM_WINDOW 0x03 // 配置开窗 +#define _CFG_COMM_WINDOW 0x7003 // 配置开窗 #define _CMD_OPEN_WINDOW 0x0B11 // 执行手动开窗 #define _CMD_CLOSE_WINDOW 0x1905 // 执行手动关窗 -#define _CFG_LOCATION_ALERT 0x04// 配置位置告警 +#define _CFG_LOCATION_ALERT 0x7004// 配置位置告警 -#define _CMD_CLEAR_DATA 0x05 // 执行清空数据 +#define _CMD_CLEAR_DATA 0x7005 // 执行清空数据 -#define _CMD_RETRY_DATA 0x06 // +#define _CMD_RETRY_DATA 0x7006 // #define _CFG_UPDATE_CFG 0x7001 @@ -70,7 +74,7 @@ enum #define _CMD_RTC_CHECK 0x410F // -#define ADDR_ANJI 0x32 //0x42? +#define ADDR_ANJI 0x42 //0x42? #define ADDR_TT 0x41 #define ADDR_3S 0x3E diff --git a/applications/tools.c b/applications/tools.c index 3a04b45..dbd583c 100644 --- a/applications/tools.c +++ b/applications/tools.c @@ -124,12 +124,8 @@ void hexFile(int argc, char **argv) } MSH_CMD_EXPORT(hexFile,以HEX方式显示文件内容); -/** - * 将当前时间转为字符串 - * @param str 字符串buffer - * @return 字符串长度 - */ -int time2Str(char *str) + +int time2Byte(uint8_t * t) { static time_t now; static struct tm *tm, tm_tmp; @@ -137,11 +133,23 @@ int time2Str(char *str) now = time(RT_NULL); tm = localtime_r(&now, &tm_tmp); - /* show the time format MM-DD HH:MM:SS */ - size_t len = rt_snprintf(str, 30, "%04d_%02d_%02d_%02d_%02d_%02d_%03d", 2000+tm->tm_year-100, tm->tm_mon+1, - tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,tm->tm_sec); + uint8_t tmp[]={tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,tm->tm_sec}; + memcpy(t,tmp,sizeof(tmp)); + return sizeof(tmp); +} +char *bytes2str(uint8_t *din, size_t count, int radix, char *sep, char *str); +/** + * 将当前时间转为字符串 + * @param str 字符串buffer + * @return 字符串长度 + */ +int time2Str(char *str) +{ + uint8_t t[10]; + size_t len=time2Byte(t); + bytes2str(t, len, 10, "_", str); + len = strlen(str); str[len]='\0'; - return len; }