TT12-MCU/applications/getinfo.c
CSSC-WORK\murmur 3d9fb6a6bc 添加appendInfo函数
更新getLoc函数
2023-07-24 14:57:28 +08:00

490 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <board.h>
#include <rtthread.h>
//#include <../packages/webclient-v2.2.0/inc/webclient.h>
#include <webclient.h>
#define LOG_TAG "getinfo"
#define LOG_LVL LOG_LVL_INFO
#include <ulog.h>
#include <string.h>
#include <cJSON.h>
#include <usrcfg.h>
//#define HTTP_GET_URL "http://www.rt-thread.com/service/rt-thread.txt"
#ifndef TT_IP
#define TT_IP "http://" TTIP ":4005"
#endif
#define TT_SIM TT_IP "/action/webGetSIMState"//SIM
#define TT_XH TT_IP "/action/webGetTDSignal"//信号值
#define TT_RW TT_IP "/action/webGetTdState"//入网
#define TT_JH TT_IP "/action/webGetPSState"//激活
#define TT_DW TT_IP "/action/webGetBDGPS"//定位
//http://192.168.0.232:4005/action/webGetSIMState webGetBDGPS
#define MAX_LEN 15
//#include <stdio.h>
//#include <stdlib.h> //用于strtod函数
//#include <string.h>
char *infoH[] = { TT_SIM, TT_XH, TT_RW, TT_JH, TT_DW};
typedef struct
{
char sim[MAX_LEN]; // SIM
char xh[MAX_LEN]; // SIM
char rw[MAX_LEN]; // SIM
char jh[MAX_LEN]; // SIM
char jd[MAX_LEN]; // SIM
char wd[MAX_LEN]; // SIM
char ele[MAX_LEN]; // SIM
// rt_uint8_t sim; // SIM
// rt_uint8_t xh; // 信号值
// rt_uint8_t rw; // 入网
// rt_uint8_t jh; // 激活
// char *jd; // 经度
// char *wd; // 纬度
// char *ele; // 高度
}TT;
TT tmp={.sim="-",.xh="-",.rw="-",.jh="-",.jd="-",.wd="-",.ele="-"};
TT *TTinfo=&tmp;
static rt_tick_t bootstamp=0;
#define RST_LEN 100//存储info的数组的长度
static uint8_t rstInfo[RST_LEN];//存储info的数组
/**
* @description: 将TT结构体转换为数组
* @param {TT} *TTinfo TT结构体
* @param {rt_uint8_t} *buffer 存储转换结果
* @return {*} buffer大小
*/
rt_uint8_t info2HEX(TT *TTinfo, rt_uint8_t *buffer)
{
// 功能将tt数据转换为9字节HEX数据并返回存在data
// 第1节为高3位分别为sim、rw和jh其余位为xhxh值若大于31则为3131=b0001 1111
// 第2-5字节为经度。114.410050= 0xF2 0xD1 0xE4 0x42//根据系统大小端的不同可能是反序
// 第6-9字节为纬度。30.426840= 0x2B 0x6A 0xF3 0x41
// 第10字节为高度只保留整数。-31.5= 0x0A
rt_uint8_t tmp = (atoi(TTinfo->sim) << 7) + (atoi(TTinfo->rw) << 6) + (atoi(TTinfo->jh) << 5)
+ (atoi(TTinfo->xh) > 31 ? 31 : atoi(TTinfo->xh)); // 位操作
char *jd_c = &TTinfo->jd[2]; // 从第二位开始取,去除非数字字符
char *wd_c = &TTinfo->wd[2];
float jd_f = strtod(jd_c, NULL); // 字符转浮点
float wd_f = strtod(wd_c, NULL);
rt_int8_t ele_f = atoi(TTinfo->ele);
// printf("jd--%f\nwd--%f\nele-- %d \n", jd_f, wd_f, ele_f);
rt_uint8_t offset = 0;
memcpy(buffer + offset, &tmp, 1);
offset += 1;
memcpy(buffer + offset, &jd_f, sizeof(float));
offset += sizeof(float);
memcpy(buffer + offset, &wd_f, sizeof(float));
offset += sizeof(float);
memcpy(buffer + offset, &ele_f, sizeof(rt_int8_t));
offset += sizeof(rt_int8_t);
return offset;
}
/**
* @brief 将新采集到的数据压入结果数组中。采用固定长度的队列方式压入,空间不足时自动弹出最旧的数据
*
* @param rst 存储采集结果的数组
* @param cnt 数组长度
* @param din 新采集的数据
* @param len 数据长度
* @return size_t 0-正常,-1异常
*/
int appendInfo(uint8_t *rst, size_t cnt, uint8_t *din, size_t len )
{
if (cnt < len)
{
return -1;
}
uint8_t tmp[cnt];
memcpy(tmp, rst + len, cnt - len);
memcpy(rst, tmp, cnt - len);
memcpy(rst + cnt - len, din, len);
return 0;
}
/**
* 获取当前经纬度信息
* @param dout 存储结果的数组
* @param cnt 获取几组位置数据
* @return 数组长度。0表示位置数据未准备好。
*/
int getLoc(uint8_t * dout, size_t cnt)
{
// LOG_D("待实现获取位置函数此处以0xCD代替");
// uint8_t tmp[200];
// memset(tmp,0xCD,200);
if (rstInfo[RST_LEN-1] == 0x3f) {
return 0;
}
memcpy(dout,rstInfo+RST_LEN-cnt*10,cnt*10);//从后开始取
return cnt*10;//1+4+4+1
}
static int minTTPeriCnt=5;
static int minTTsinal=3;
static int minActiveTime=0;
static int maxActiveTime=0;
extern SYS_CFG scfg;
static void updatecfg(void)
{
minTTsinal = scfg.minTTsinal;
minTTPeriCnt = scfg.minTTPeriCnt;
minActiveTime = scfg.minActiveTime;
maxActiveTime = scfg.maxActiveTime;
LOG_D("加载参数完成");
}
void initcfg()
{
updatecfg();
bootstamp = rt_tick_get_millisecond();
}
/**
* 更新统计信息
*/
static void updateSta()
{
uint16_t v = (rt_tick_get_millisecond()-bootstamp)/1000;//转换为秒
LOG_I("耗时%dS.",v);
if ((minActiveTime ==0) | (minActiveTime > v)) {
minActiveTime = v;
set_val("minActiveTime", v);
}
if (v>maxActiveTime) {
maxActiveTime=v;
set_val("maxActiveTime", v);
}
}
/**
* 按规则检查TT状态
*/
static void rulecheck(void)
{
//默认为 TT连续5个周期为激活状态且信号强度不低于5。
//满足加1不满足清零
static rt_uint16_t okCnt=0;
if (!okCnt) {
LOG_D("当前规则为:连续%d个采集周期TT信号质量不低于%d",minTTPeriCnt,minTTsinal);
}
int xh=atoi(TTinfo->xh);
if (xh == 99) {
xh=0;
}
if (atoi(TTinfo->jh) && !(xh < minTTsinal) ) {//
okCnt += 1;
LOG_D("第%d次符合规则。",okCnt);
}
else {
okCnt = 0;
LOG_W("不符合。");
return;
}
if (okCnt >= minTTPeriCnt) {
//TT具备发送条件
// rt_event_send(&sw_check, TT_IS_OK);
// upTTflag();
TTisReady();
LOG_I("符合规则TT具备发送状态。");
// updateSta();
okCnt = minTTPeriCnt -1;
}
// if (okCnt > minTTPeriCnt) {
// //TT具备发送条件
//// rt_event_send(&sw_check, TT_IS_OK);
// upTTflag();
// okCnt = 2;
// LOG_I("符合规则TT具备发送状态。");
//// updateSta();
// }
}
/* 数据解析 */
static void tt_parse(rt_uint8_t *data)
{
extern TT *TTinfo;
cJSON *root = RT_NULL, *object = RT_NULL, *item = RT_NULL;
root = cJSON_Parse((const char *) data);
if (!root)
{
rt_kprintf("No memory for cJSON root!\n");
return;
}
object = cJSON_GetObjectItem(root, "data");
item = cJSON_GetObjectItem(object, "tdsignal");
if (item)
{
// TTinfo->xh = atoi(item->valuestring);
// tmp.xh = item->valuestring;
strcpy(TTinfo->xh,item->valuestring);
// rt_kprintf("\nxh:%s ", item->valuestring);
// rt_kprintf("\nxh:%s ", TTinfo->xh);
cJSON_Delete(root);
return RT_EOK;
}
item = cJSON_GetObjectItem(object, "tdnetregstate");
if (item)
{
// TTinfo->rw = atoi(item->valuestring);
// rt_kprintf("\nrw:%s ", TTinfo.rw);
strcpy(TTinfo->rw,item->valuestring);
cJSON_Delete(root);
return RT_EOK;
}
item = cJSON_GetObjectItem(object, "tdpsstate");
if (item)
{
// TTinfo->jh = atoi(item->valuestring);
// rt_kprintf("\njh:%s ", TTinfo.jh);
strcpy(TTinfo->jh,item->valuestring);
cJSON_Delete(root);
return RT_EOK;
}
item = cJSON_GetObjectItem(object, "latitude");
if (item)
{
// TTinfo->wd = item->valuestring;
strcpy(TTinfo->wd,item->valuestring);
item = cJSON_GetObjectItem(object, "longitude");
// TTinfo->jd = item->valuestring;
strcpy(TTinfo->jd,item->valuestring);
item = cJSON_GetObjectItem(object, "elevation");
// TTinfo->ele = item->valuestring;
strcpy(TTinfo->ele,item->valuestring);
// rt_kprintf("%5s%5s%5s%5s%15s%15s%10s\n", TTinfo->sim, TTinfo->xh, TTinfo->rw,
// TTinfo->jh, TTinfo->jd, TTinfo->wd,TTinfo->ele);
LOG_D("Get RAW data done.");
cJSON_Delete(root);
return RT_EOK;
}
item = cJSON_GetObjectItem(object, "tdsimstate");
if (item)
{
// TTinfo->sim = atoi(item->valuestring);
// tmp.sim = item->valuestring;
strcpy(TTinfo->sim,item->valuestring);
// rt_kprintf("\nSIM:%s \n", TTinfo->sim);
cJSON_Delete(root);
return RT_EOK;
}
if (root != RT_NULL)
cJSON_Delete(root);
}
/* HTTP client download data by GET request */
static int webclient_get_data(const char *url)
{
static unsigned char *buffer = RT_NULL;
size_t length = 0;
if (webclient_request(url, RT_NULL, RT_NULL, 0, (void **) &buffer, &length) < 0)
{
LOG_E("TT server is not ready.");
if (buffer)
{
web_free(buffer);
}
return -RT_ERROR;
}
LOG_D("webclient GET request response data :");
LOG_D("%s", buffer);
tt_parse(buffer);
if (buffer)
{
web_free(buffer);
}
return RT_EOK;
}
void getTTinfo_thread_entry(void* parameter)
{
// bootstamp = rt_tick_get();
CFG* cfg = RT_NULL;
cfg = (CFG*) parameter;
// TT TTinfo;
rt_kprintf("\n%10s%s\n", " ", "↓---------getTT START.--------↓");
rt_kprintf("%5s%5s%5s%5s%15s%15s%10s\n", "SIM", "xh", "rw", "jh", "N", "E", "ele");
for (uint8_t i = 0; i < cfg->cnt; ++i) //按指定次数轮询
{
rt_kprintf("%5s%5s%5s%5s%15s%15s%10s\n", TTinfo->sim, TTinfo->xh, TTinfo->rw, TTinfo->jh, TTinfo->jd,
TTinfo->wd, TTinfo->ele);
if (i != cfg->cnt - 1) //最后一次采集不延时
{
rt_thread_mdelay(cfg->s * 1000);
}
}
rt_kprintf("%10s%s\n", " ", "↑---------getTT DONE.---------↑");
}
void getTT(int argc, char **argv)
{
// size_t cnt = 0, s=3;//次数、间隔
static CFG cfg;
memset(&cfg, 0, sizeof(CFG));
if (argc == 1)
{
cfg.cnt = 1;
cfg.s = 3;
}
else if (argc == 2)
{
cfg.cnt = atoi(argv[1]);
cfg.s = 3;
}
else if (argc == 3)
{
cfg.cnt = atoi(argv[1]);
cfg.s = atoi(argv[2]);
}
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("getTT", getTTinfo_thread_entry, (void *) &cfg, 1024 * 3, 25, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
// rt_kprintf("done");
}
else
{
LOG_E("thread 'getTT' create failure.");
return RT_ERROR;
}
}
/* 导出到自动初始化 */
MSH_CMD_EXPORT(getTT, "getTT 3 1" means try 3 times with 1 second interval.);
//MSH_CMD_EXPORT_ALIAS(webclient_get_data, gTTinfo, GET info of TT server.);
int isTTon(void)
{
return !rt_pin_read(TT_EN);
}
void repGetTT_thread_entry(void* parameter)
{
while(!isTTon())//第一次运行时未上电则等待
{}
while(isTTon())//中间未上电则退出
{
for (size_t var = 0; var < (sizeof(infoH) / sizeof(infoH[0])); var++) //轮询每个参数
{
static char *url = RT_NULL;
url = web_strdup(*(infoH + var));
if (url == RT_NULL)
{
LOG_E("no memory for create getTT url buffer.\n");
break;
// return -RT_ENOMEM;
}
if (webclient_get_data(url) != RT_EOK)
{
web_free(url);
strcpy(TTinfo->sim,"-");
strcpy(TTinfo->xh,"-");
strcpy(TTinfo->jh,"-");
strcpy(TTinfo->jd,"-");
strcpy(TTinfo->wd,"-");
strcpy(TTinfo->ele,"-");
break;
}
web_free(url);
// rt_thread_mdelay(100);
//trans&copy new info to arrBuf
uint8_t buffer[10];
int len = info2HEX(TTinfo, buffer);
appendInfo(rstInfo, RST_LEN, buffer, len);
}
rulecheck();
rt_thread_mdelay(3 * 1000);//间隔3s更新一次数据
}
}
/**
* 持续更新TT状态信息数据3s刷新一次。TT断电后退出。
*/
void repGetTT(void)
{
memset(rstInfo,0x3f,RST_LEN);//初始化
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("repGetTT", repGetTT_thread_entry, RT_NULL, 1024 * 3, 27, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
// rt_kprintf("done");
}
else
{
LOG_E("thread 'repGetTT' create failure.");
return RT_ERROR;
}
}
MSH_CMD_EXPORT(repGetTT,gett);
//由于
//
//static rt_timer_t timer1;
///* 定时器1超时函数 */
//static void timeout1(void *parameter)
//{
//
//// LOG_D("定时时间到,准备发送数据");
// if (isTTon()) {
// repGetTT();
// }
// else {
// rt_timer_stop(timer1);
// }
//// rt_event_send(&readyToSend, TIME_IS_UP);
//}
//void runTT()
//{
///* 创建定时器1 周期定时器 */
//timer1 = rt_timer_create("TTinfotimer", timeout1,
// RT_NULL, rt_tick_from_millisecond(3*1000),
// RT_TIMER_FLAG_PERIODIC);
//
///* 启动定时器1 */
//if (timer1 != RT_NULL && isTTon())
// rt_timer_start(timer1);
//}