TT12-MCU/applications/getinfo.c
CSSC-WORK\murmur 736bf46d2f 更新电池电量算法
其它更改(待测试)
2023-09-02 19:33:16 +08:00

492 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
/**
在纬度相等的情况下:
经度每隔0.000001度距离相差约1米
经度每隔0.00001度距离相差约10米
经度每隔0.0001度距离相差约100米
经度每隔0.001度距离相差约1000米
经度每隔0.01度距离相差约10000米
在经度相等的情况下:
纬度每隔0.000001度距离相差约1.1米
纬度每隔0.00001度距离相差约11米
纬度每隔0.0001度距离相差约111米
纬度每隔0.001度距离相差约1113米
纬度每隔0.01度距离相差约11132米
*/
}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的数组
void resetInfo()
{
rt_memset(rstInfo,0x3f,RST_LEN);//初始化
}
/**
* @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[4];
rt_memset(tmp,0,4);
if ((rstInfo[0] == 0x3f) || (memcmp(rstInfo+1,tmp,4) == 0)) {//无有效位置数据1+4+4+1
return 0;
}
memcpy(dout,rstInfo+RST_LEN-cnt*10,cnt*10);//从后开始取
return cnt*10;//1+4+4+1
}
extern SYS_CFG scfg;
void initcfg()
{
rt_memset(rstInfo,0x3f,RST_LEN);//初始化
bootstamp = rt_tick_get_millisecond();
}
INIT_APP_EXPORT(initcfg);
/**
* 更新统计信息
*/
//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 size_t okCnt=0;
if (!okCnt) {
// LOG_D("当前规则为:连续%d个采集周期TT信号质量不低于%d",scfg.minTTPeriCnt,scfg.minTTsinal);
}
int xh=atoi(TTinfo->xh);
if (xh > 90) {
xh=0;
}
if (atoi(TTinfo->jh) && !(xh < scfg.minTTsinal) ) {//
okCnt += 1;
LOG_D("第%d次符合规则。",okCnt);
}
else {
okCnt = 0;
// LOG_W("不符合。");
return;
}
if (okCnt >= scfg.minTTPeriCnt) {
//TT具备发送条件
// LOG_I("----");
extern void TTIsReady(void);
TTIsReady();
// LOG_I("符合规则TT具备发送状态。");
okCnt = scfg.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)
{
// LOG_I("%s",data);
extern TT *TTinfo;
cJSON *root = RT_NULL, *object = RT_NULL, *item = RT_NULL;
root = cJSON_Parse((const char *) data);
if (!root)
{
LOG_W("JSON string is not ok, or No memory for cJSON root!");
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 (!isTCPok() || webclient_request(url, RT_NULL, RT_NULL, 0, (void **) &buffer, &length) <= 0)
{
LOG_E("TT server or webclient is not ready.");
if (buffer)
{
web_free(buffer);
}
return -RT_ERROR;
}
LOG_D("webclient GET request response data :");
LOG_D("%s", buffer);
if (buffer && length && buffer[length-1] == 0x7d) //0x7d='}',首次返回的数据不完整,此处直接丢掉避免报错
{
tt_parse(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;
rt_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 * 5, 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.);
/**
* 判断TT是否为开机状态
* @return 1-开机0-关机
*/
int isTTon(void)
{
#ifndef RELAY
return !rt_pin_read(TT_EN);
#else
return rt_pin_read(TT_EN);
#endif
}
/**
* 判断TT是否激活
* @return 1-已激活0-未激活
*/
uint8_t isTTjh(void)
{
return atoi(TTinfo->jh);
}
uint8_t getXh(void)
{
return (uint8_t)atoi(TTinfo->xh);
}
void repGetTT_thread_entry(void* parameter)
{
// while(!isTCPok())//第一次运行时未上电则等待
// {}
while(isTCPok())//中间未上电则退出
{
for (size_t var = 0; var < (sizeof(infoH) / sizeof(infoH[0])); var++) //轮询每个参数
{
if (!isTCPok()) {
break;
}
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)
{
// LOG_E("---------");
web_free(url);
strcpy(TTinfo->sim,"-");
strcpy(TTinfo->xh,"-");
strcpy(TTinfo->jh,"-");
strcpy(TTinfo->jd,"-");
strcpy(TTinfo->wd,"-");
strcpy(TTinfo->ele,"-");
break;
}
if (url) {
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更新一次数据
}
rt_memset(rstInfo,0x3f,RST_LEN);//初始化
}
/**
* 持续更新TT状态信息数据3s刷新一次。TT断电后退出。
*/
void repGetTT(void)
{
while(!isTCPok())//第一次运行时未上电则等待
{}
rt_memset(rstInfo,0x3f,RST_LEN);//初始化
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("repGetTT", repGetTT_thread_entry, RT_NULL, 1024 * 30, 27+2, 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);