#include #include //#include <../packages/webclient-v2.2.0/inc/webclient.h> #include #define LOG_TAG "getinfo" #define LOG_LVL LOG_LVL_INFO #include #include #include #include //#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 //#include //用于strtod函数 //#include 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,其余位为xh,xh值若大于31则为31(31=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具备发送条件 // TTisReady(); 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.); /** * 判断TT是否为开机状态 * @return 1-开机,0-关机 */ int isTTon(void) { return !rt_pin_read(TT_EN); } /** * 判断TT是否激活 * @return 1-已激活,0-未激活 */ int isTTjh(void) { return atoi(TTinfo->jh); } 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© 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); //}