TT12-MCU/applications/getinfo.c
CSSC-WORK\murmur d27ad95916 添加更改服务器IP的指令
清理指令增加辨识度,常用指令注释用中文,其它用英文
2024-01-05 08:36:41 +08:00

578 lines
16 KiB
C
Raw Permalink 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"//定位
#define TT_WEB_GET TT_IP "/action/webGetSocketAddr"//服务器地址
#define TT_WEB_SET TT_IP "/action/webSetSocketAddr"//服务器地址
//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的数组
static uint8_t signalInfo[RST_LEN];
void resetInfo()
{
rt_memset(rstInfo,0x3f,RST_LEN);//初始化
rt_memset(signalInfo,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= 0xE1
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()
{
resetInfo();//初始化
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("不符合。");
TTIsNotReady();
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;
static size_t errCnt = 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);
}
if (errCnt++ > 15) {
errCnt = 0;
deInitTT();
rt_thread_mdelay(5000);
fileIsReady();
}
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);
appendInfo(signalInfo, RST_LEN, buffer, 1);
}
rulecheck();
rt_thread_mdelay(5 * 1000);//间隔3s更新一次数据
}
resetInfo();//复位
strcpy(TTinfo->sim,"-");
strcpy(TTinfo->xh,"-");
strcpy(TTinfo->jh,"-");
strcpy(TTinfo->jd,"-");
strcpy(TTinfo->wd,"-");
strcpy(TTinfo->ele,"-");
}
/**
* 持续更新TT状态信息数据3s刷新一次。TT断电后退出。
*/
void repGetTT(void)
{
while(!isTCPok())//第一次运行时未上电则等待
{}
resetInfo();//初始化
/* 创建 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);
/**
* 获取信号状态
* @param dout 存储结果的数组
* @param len 指定获取状态的次数
*/
size_t getSignals(uint8_t *dout, uint8_t len){
memcpy(dout,signalInfo,len);
return len;
}
void dwebser(int argc, char **argv)
{
static unsigned char *buffer = RT_NULL;
size_t length = 0;
char arg[100]="";
if (argc == 1) {//查询
strcpy(arg,TT_WEB_GET);
}
else if (argc == 3) {//设置
if (strcmp(argv[2],"cssc") == 0) {//最后一个参数为密码,避免意外修改
// ?tdsocketip=47.108.213.132&tdsocketport=7222
strcpy(arg,TT_WEB_SET);
strcat(arg,"?tdsocketip=");
strcat(arg,argv[1]);
strcat(arg,"&tdsocketport=7222");
}
else {
LOG_W("wrong password.");
return;
}
}
else if (argc == 2) {//须密码
LOG_W("need password.");
return;
}
static char *url = RT_NULL;
url = web_strdup(arg);
// LOG_I("%s",url);
if (url == RT_NULL)
{
LOG_E("no memory for create getTT url buffer.\n");
return;
}
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;
}
// if (buffer && length && buffer[length-1] == 0x7d) //0x7d='}',首次返回的数据不完整,此处直接丢掉避免报错
{
LOG_I("%s", buffer);
web_free(buffer);
}
}
MSH_CMD_EXPORT(dwebser,'pwebser [IP] [password]'IP无校验)