#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"//定位 #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 //#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 /** 在纬度相等的情况下: 经度每隔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,其余位为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= 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© 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无校验。)