范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

移远4G模组拨号socket获取天气数据

  上一篇分享了4G开发板与我们PC进行通信(需要进行内网穿透),这一篇笔记我们直接使用4G开发板访问天气服务器获取天气数据。
  我们要使用移远4G模块进行网络通信,要经历 3 个主要过程:网络注册、网络激活和socket 创建。
  网络注册是自动完成的,无需用户代码干预(网络注册前,请确认 SIM 卡是否正常识别且 SIM 卡无欠费等业务异常)。只有在网络注册成功以后,才可进行网络激活,即本文所述的拨号(下文皆称为拨号)。只有拨号成功后,才可进行 socket 网络通信。拨号+socket 通信基本流程
  确保拨号成功的必要条件:SIM 卡没欠费; 硬件良好,天线匹配;拨号前,调用 ql_network_register_wait 等待网络注册成功;拨号时,向 ql_start_data_call 传递正确的参数。Socket 通信流程
  EC100 模块 Socket 通信基本流程如上图: 1、在进行 socket 通信之前,必须确保拨号已经成功,可以通过 ql_get_data_call_info()查询需要进行 socket 通信的网络通道是否拨号成功。 2、拨号成功后进行 socket 通信时,必须对需要通信的网络通道进行 bind 操作。不管是 UDP 还是 TCP,都必须执行 Bind 操作之后才可以正常进行 socket 通信。
  sdk中给我们提供了一个tcp_client的demo,这个demo的设计思路完全按照上面两张图流程图来设计。我们在这个demo进行修改,获取天气数据。
  我们修改后的example_tcp_weather_client.c代码如下:#include  #include  #include  #include "ql_type.h" #include "ql_rtos.h" #include "ql_application.h" #include "ql_data_call.h" #include "sockets.h" #include "netdb.h" #include "cJSON.h" ​ #define  DEBUG   0       ​ /* 心知天气(www.seniverse.com)IP及端口 */ #define  WEATHER_IP_ADDR   "116.62.81.138" #define  WEATHER_PORT      80 ​ #define TCP_CONNECT_TIMEOUT_S 10 #define TCP_RECV_TIMEOUT_S 10 #define TCP_CLOSE_LINGER_TIME_S 10 #define TCP_CLIENT_SEND_STR "tcp client send string" #define PROFILE_IDX 1 #define PROFILE_IDX 1 ​ /* 秘钥,注意!!如果要用这一份代码,这个一定要改为自己的,因为这个我已经故意改错了,防止有人与我公用一个KEY */ #define  KEY    "2owqvhhd2dd9o9f9"      // 这是在心知天气注册后,每个用户自己的一个key ​ /* GET请求包 */ #define  GET_REQUEST_PACKAGE               "GET https://api.seniverse.com/v3/weather/%s.json?key=%s&location=%s&language=zh-Hans&unit=cr r "      /* JSON数据包 */    #define  NOW_JSON     "now" //....还用更多其他的天气数据包可查阅心知天气 ​ /* 天气数据结构体 */ typedef struct {     /* 实况天气数据 */     char id[32];                //id     char name[32];              //地名     char country[32];           //国家     char path[32];              //完整地名路径     char timezone[32];          //时区     char timezone_offset[32];   //时差     char text[32];              //天气预报文字     char code[32];              //天气预报代码     char temperature[32];       //气温     char last_update[32];       //最后一次更新的时间 }Weather; ​ // 全局变量 static struct in_addr ip4_addr = {0}; ​ // 函数声明 static void GetWeather(char *weather_json, char *location, Weather *result); static int cJSON_NowWeatherParse(char *JSON, Weather *result); static int cJSON_DailyWeatherParse(char *JSON, Weather *result); static void DisplayWeather(Weather *weather_data); static void ql_nw_status_callback(int profile_idx, int nw_status); static void datacall_satrt(void); ​ /******************************************************************************************************* ** 函数: sockets_weather_test **------------------------------------------------------------------------------------------------------ ** 参数: void ** 返回: void ********************************************************************************************************/ static void sockets_weather_test(void * argv) {     struct ql_data_call_info info = {0};     char ip4_addr_str[16] = {0};     Weather weather_data = {0};     char *location = "shenzhen"; ​     printf("========== sockets tcp test will start ...r "); ​     /* 拨号开始 */     datacall_satrt(); ​     /* 获取拨号信息 */     ql_get_data_call_info(1, 0, &info); ​     printf("info.profile_idx: %dr ", info.profile_idx);     printf("info.ip_version: %dr ", info.ip_version);     printf("info.v4.state: %dr ", info.v4.state);     printf("info.v4.reconnect: %dr ", info.v4.reconnect); ​     inet_ntop(AF_INET, &info.v4.addr.ip, ip4_addr_str, sizeof(ip4_addr_str));     printf("info.v4.addr.ip: %sr ", ip4_addr_str); ​     inet_ntop(AF_INET, &info.v4.addr.pri_dns, ip4_addr_str, sizeof(ip4_addr_str));     printf("info.v4.addr.pri_dns: %sr ", ip4_addr_str); ​     inet_ntop(AF_INET, &info.v4.addr.sec_dns, ip4_addr_str, sizeof(ip4_addr_str));     printf("info.v4.addr.sec_dns: %sr ", ip4_addr_str); ​     ip4_addr = info.v4.addr.ip; ​     if(info.v4.state)     {         memset(&weather_data, 0, sizeof(weather_data));  // weather_data清零          GetWeather(NOW_JSON, location, &weather_data);   // GET 并解析实况天气数据         DisplayWeather(&weather_data);                   // 显示天气结果     } ​     printf("========== sockets tcp test finishedr ");          return 0; }      static void ql_nw_status_callback(int profile_idx, int nw_status) {     printf("profile(%d) status: %dr ", profile_idx, nw_status); } ​ static void datacall_satrt(void) {     printf("wait for network register doner "); ​     /* 等待网络注册结果 */     if(ql_network_register_wait(120) != 0)     {         printf("*** network register fail ***r ");     }     else     {         printf("doing network activing ...r ");                  ql_wan_start(ql_nw_status_callback);            /* 拨号初始化:注册拨号回调函数 */         ql_set_auto_connect(1, TRUE);                   /* 设置拨号掉线是否自动重连 */         ql_start_data_call(1, 0, NULL, NULL, NULL, 0);  /* 开始拨号 */     } } ​ static void GetWeather(char *weather_json, char *location, Weather *result) {     int             sock_nbio   = 1;     int             ret         = 0;     int             sock_fd     = -1;     int             sock_error  = 0;     socklen_t       optlen = 0;     fd_set          read_fds, write_fds;     struct timeval  t;     struct addrinfo     * res, hints;     struct sockaddr_in  * ip4_svr_addr;     struct sockaddr_in  ip4_local_addr = {0};     u8 dns_success = 0;     u8 recv_buf[128] = {0};     u8 GetRequestBuf[256] = {0};     u8 WeatherRecvBuf[2*1024] = {0}; ​     /*  */     memset(&hints, 0, sizeof(struct addrinfo));     hints.ai_family = AF_INET;     hints.ai_socktype = SOCK_STREAM;     if(getaddrinfo_with_pcid(WEATHER_IP_ADDR, NULL, &hints, &res, PROFILE_IDX) != 0)     {         printf("*** DNS fail ***r ");         goto exit;     } ​     dns_success = 1;          ret = socket(AF_INET, SOCK_STREAM, 0);     if(ret < 0)     {         printf("*** socket create fail ***r ");         goto exit;     } ​     sock_fd = ret; ​     ioctl(sock_fd, FIONBIO, &sock_nbio); ​     ip4_local_addr.sin_family = AF_INET;     ip4_local_addr.sin_port = htons(ql_soc_generate_port());     ip4_local_addr.sin_addr = ip4_addr;          ret = bind(sock_fd, (struct sockaddr *)&ip4_local_addr, sizeof(ip4_local_addr));     if(ret < 0)     {         printf("*** bind fail ***r ");         goto exit;     }          ip4_svr_addr = (struct sockaddr_in *)res->ai_addr;     ip4_svr_addr->sin_port = htons(WEATHER_PORT); ​     ret = connect(sock_fd, (struct sockaddr *)ip4_svr_addr, sizeof(struct sockaddr)); ​     printf("connect ret: %d, errno: %ur ", ret, errno); ​     if(ret == -1 && errno != EINPROGRESS)     {         printf("*** connect fail ***r ");         goto exit;     } ​     t.tv_sec = TCP_CONNECT_TIMEOUT_S;     t.tv_usec = 0; ​     FD_ZERO(&read_fds);     FD_ZERO(&write_fds); ​     FD_SET(sock_fd, &read_fds);     FD_SET(sock_fd, &write_fds); ​     ret = select(sock_fd + 1, &read_fds, &write_fds, NULL, &t); ​     printf("select ret: %dr ", ret); ​     if(ret <= 0)     {         printf("*** select timeout or error ***r ");         goto exit;     } ​     if(!FD_ISSET(sock_fd, &read_fds) && !FD_ISSET(sock_fd, &write_fds))     {         printf("*** connect fail ***r ");         goto exit;     }     else if(FD_ISSET(sock_fd, &read_fds) && FD_ISSET(sock_fd, &write_fds))     {         optlen = sizeof(sock_error);         ret = getsockopt(sock_fd, SOL_SOCKET, SO_ERROR, &sock_error, &optlen);         if(ret == 0 && sock_error == 0)         {             printf("connect successr ");         }         else         {             printf("*** connect fail, sock_err = %d, errno = %u ***r ", sock_error, errno);             goto exit;         }     }     else if(!FD_ISSET(sock_fd, &read_fds) && FD_ISSET(sock_fd, &write_fds))     {         printf("connect successr ");     }     else if(FD_ISSET(sock_fd, &read_fds) && !FD_ISSET(sock_fd, &write_fds))     {         printf("*** connect fail ***r ");         goto exit;     }     else     {         printf("*** connect fail ***r ");         goto exit;     } ​     /* 组合GET请求包 */     sprintf(GetRequestBuf, GET_REQUEST_PACKAGE, weather_json, KEY, location); ​     /* 发送数据到服务端 */     ret = send(sock_fd, (const void*)GetRequestBuf, strlen(GetRequestBuf), 0);     if(ret < 0)     {         printf("*** send fail ***r ");         goto exit;     } ​ _recv_:     t.tv_sec = TCP_RECV_TIMEOUT_S;     t.tv_usec = 0; ​     FD_ZERO(&read_fds);     FD_SET(sock_fd, &read_fds); ​     ret = select(sock_fd + 1, &read_fds, NULL, NULL, &t); ​     printf("select ret: %dr ", ret); ​     if(ret <= 0)     {         printf("*** select timeout or error ***r ");         goto exit;     } ​     if(FD_ISSET(sock_fd, &read_fds))     {         ret = recv(sock_fd, WeatherRecvBuf, sizeof(WeatherRecvBuf), 0);         if(ret > 0)         {             printf("recv data: [%d]%sr ", ret, WeatherRecvBuf);             /* 解析天气数据并保存到结构体变量weather_data中 */             if (0 == strcmp(weather_json, NOW_JSON))        // 天气实况             {                 cJSON_NowWeatherParse(WeatherRecvBuf, result);               }         }         else if(ret == 0)         {             printf("*** peer closed ***r ");             goto exit;         }         else         {             if(!(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))             {                 printf("*** error occurs ***r ");                 goto exit;             }             else             {                 printf("wait for a whiler ");                 ql_rtos_task_sleep_ms(20);                 goto _recv_;             }         } ​     } ​ exit:     if(dns_success) freeaddrinfo(res); ​     if(sock_fd >= 0)     {         struct linger linger = {0}; ​         linger.l_onoff = 1;         linger.l_linger = TCP_CLOSE_LINGER_TIME_S; ​         setsockopt(sock_fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));         setsockopt(sock_fd, IPPROTO_TCP, TCP_CLOSE_TIMEROUT, &linger.l_linger, sizeof(linger.l_linger)); ​         /* 清空缓冲区 */         memset(GetRequestBuf, 0, 256);            memset(WeatherRecvBuf, 0, 2*1024);             close(sock_fd);     } } ​ /******************************************************************************************************* ** 函数: cJSON_NowWeatherParse,解析天气实况数据 **------------------------------------------------------------------------------------------------------ ** 参数: JSON:天气数据包   result:数据解析的结果 ** 返回: void ********************************************************************************************************/ static int cJSON_NowWeatherParse(char *JSON, Weather *result) {     cJSON *json,*arrayItem,*object,*subobject,*item;          json = cJSON_Parse(JSON); //解析JSON数据包     if(json == NULL)          //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效     {         printf("Error before: [%s] ",cJSON_GetErrorPtr()); //打印数据包语法错误的位置         return 1;     }     else     {         if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL); //匹配字符串"results",获取数组内容         {             int size = cJSON_GetArraySize(arrayItem);     //获取数组中对象个数 #if DEBUG             printf("cJSON_GetArraySize: size=%d ",size);  #endif             if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容             {                 /* 匹配子对象1:城市地区相关 */                 if((subobject = cJSON_GetObjectItem(object,"location")) != NULL)                 {                     // 匹配id                     if((item = cJSON_GetObjectItem(subobject,"id")) != NULL)                        {                         memcpy(result->id, item->valuestring,strlen(item->valuestring));        // 保存数据供外部调用                     }                     // 匹配城市名                     if((item = cJSON_GetObjectItem(subobject,"name")) != NULL)                      {                         memcpy(result->name, item->valuestring,strlen(item->valuestring));      // 保存数据供外部调用                     }                     // 匹配城市所在的国家                     if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)                     {                         memcpy(result->country, item->valuestring,strlen(item->valuestring));   // 保存数据供外部调用                     }                     // 匹配完整地名路径                     if((item = cJSON_GetObjectItem(subobject,"path")) != NULL)                       {                         memcpy(result->path, item->valuestring,strlen(item->valuestring));      // 保存数据供外部调用                         }                     // 匹配时区                     if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)                     {                         memcpy(result->timezone, item->valuestring,strlen(item->valuestring));  // 保存数据供外部调用                         }                     // 匹配时差                     if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)                     {                         memcpy(result->timezone_offset, item->valuestring,strlen(item->valuestring));   // 保存数据供外部调用                     }                 }                 /* 匹配子对象2:今天的天气情况 */                 if((subobject = cJSON_GetObjectItem(object,"now")) != NULL)                 {                     // 匹配天气现象文字                     if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)                     {                         memcpy(result->text, item->valuestring,strlen(item->valuestring));  // 保存数据供外部调用                     }                     // 匹配天气现象代码                     if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)                     {                         memcpy(result->code, item->valuestring,strlen(item->valuestring));  // 保存数据供外部调用                     }                     // 匹配气温                     if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL)                      {                         memcpy(result->temperature, item->valuestring,strlen(item->valuestring));   // 保存数据供外部调用                     }                    }                 /* 匹配子对象3:数据更新时间(该城市的本地时间) */                 if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL)                 {                     memcpy(result->last_update, subobject->valuestring,strlen(subobject->valuestring));   // 保存数据供外部调用                 }             }          }     }          cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间          return 0; } ​ /******************************************************************************************************* ** 函数: DisplayWeather,显示天气数据 **------------------------------------------------------------------------------------------------------ ** 参数: weather_data:天气数据 ** 返回: void ********************************************************************************************************/ static void DisplayWeather(Weather *weather_data) {     printf("============%s today weather=========== ", weather_data->name);     printf("weather_data->text: %s ", weather_data->text);          printf("weather_data->temperature: %s ", weather_data->temperature);        printf("weather_data->timezone: %s ", weather_data->timezone);      printf("weather_data->timezone_offset: %s ", weather_data->timezone_offset);     printf("weather_data->last_update: %s ", weather_data->last_update); } ​ application_init(sockets_weather_test, "sockets_weather_test", 8, 4);
  关于天气获取、解析代码之前已经有详细分享过,这里不再解释。相关文章:
  「socket应用」基于C语言的TCP天气客户端的实现
  测试结果:

老QQ号有多大的价值?网友达到这些条件,或许能换套房1999年,马化腾与团队员工在深圳开发了第一代聊天软件QQ的前身OICQ,当时的OICQ只有几百KB的大小。马化腾与团队将其研发出来之后为了吸引更多用户,于是扮演女性用户专门与网友马斯克四处造势,推动狗狗币突破新高争当最牛山寨币和狗币的上升逻辑一样,人称一坨屎币的SHIB最近也在上演一场荒诞狂飙。五月七日,马斯克在一条有关SHIB的Twitter上留言说我要找一只柴犬,我想找一只柴犬。这就是捧红了狗币的货谷歌霸气官宣!发布新自研芯片原生安卓旗舰机皇在中国量产上市8月26日讯相信大家都知道,自从国产手机老大哥华为遭受到新一轮芯片禁令之后,也让全球智能手机市场迎来了新一轮的大洗牌,全球TOP5智能手机厂商都获得了非常不错的销量增长,就连被很多漫步者NeoBudsPro圈铁降噪耳机听感为王实力圈粉TWS真无线蓝牙耳机行业在近两年兴起,逐渐引领了一种潮流。各大品牌都相继推出了价格不同的蓝牙耳机。随着这种新潮的诞生,进军真无线蓝牙耳机这个行业的,不仅有一些老品牌,还有新生力量的电商的最后一段红利时期免费流量一说起电商,在大家的脑海中想到更多的是开车烧钱,竞争越来越大,流量越来越贵。。都是叫苦叫难的,今天我就给大家分享一个小众类目的行业医药健康,不开车,不报活动,就可以日销过万,该赚得新能源汽车空间有多秀?小鹏P5特斯拉毛豆3在线打样雨雪天出行,难度MAX购物不能买太多,拎不动太头痛明明居住地到公司只有几公里,还要倒两趟地铁才能到达种种迹象表明,无车真的寸步难行。因此当我有了一笔可观的存款后,第一件事就是将购车特斯拉modelY试驾历险记上个月modelY出了单电机版本,价格降了7万,有一天正好在亦庄办事,下午3点多有空,联系了特斯拉门店,到店试驾了modelY,试驾的车型还是双电机版,外观比model3高一些,比两款重磅扫地机器人新品即将发售,石头G10和追觅W10抢先看8月底,扫地机器人行业的两款重磅产品都进入了预售阶段石头G10和追觅W10。虽然我们还没拿到这两款产品,但是我们对两款产品官方释放的数据信息进行了对比,今天就详细分析一下,希望对有未来已来,欢呼吧人类特斯拉CEO马斯克在8月19号的人工智能大会上宣布他们将于2022年发布一款名为特斯拉机器人的原型产品。这款机器人的身高大约为1。73米。体重达56。7公斤。移动速度8公里每小时。远营商强制手机移除5G开关是否伤天害理几大国有运营商正在强制各手机厂商移除任务栏中的5G快捷开关。三大(或几大)运营商是商业组织,为了一己的商业私利。为了更多赚国民的5g流量钱。强制取消5g开关。这于理于法是否符合,真为什么AMD是目前最值得购买的顶级晶片股AdvancedMicroDevices最大的业务正在蓬勃发展,它正在从英特尔手中夺走市场份额。由于相对于英特尔芯片拥有技术优势,AMD坐拥巨大的收入机会。该公司有望通过发布以更高
中国信通院2021年全年国内手机市场总体出货量累计3。51亿部同比增长13。9央广网北京1月18日消息中国信息通信研究院今日发布2021年12月和全年国内手机市场出货量数据。数据显示,2021年12月,国内手机市场出货量3340。1万部,同比增长25。6,其COLMOSV8油烟机高端厨房必备的一款油烟机SV8,安装后从此爱上烹饪!暗中观察R烹饪时我们都知道会有很多油烟,对人体有很大危害,SV8帮你解决这个问题,四区拢烟设计从下到上吸尽油烟,风量更是做到26ATT和Verizon将在机场附近暂时限制5G信号,以避免影响航班华尔街日报1月19日消息,美国电话电报公司(ATT)和VerizonCommunications周二同意暂时缩减其5G无线网络扩展计划,以解决航空安全监管机构有关其信号对飞机设备影国务院完善设施数字化感知系统,稳步推进5G等网络通信设施覆盖据中国政府网18日消息,国务院印发十四五现代综合交通运输体系发展规划。规划提出,推进基础设施智能化升级。完善设施数字化感知系统。推动既有设施数字化改造升级,加强新建设施与感知网络同如何用逻辑证明这个世界是计算机模拟出来的?1马斯克说,这个世界是真实的概率,不到几十亿分之一。他是随口胡说吗?诶,还真不是,这背后有严谨的逻辑,今天咱们先来盘盘这个。2首先,把能不能这件事扔到一边也许是用计算机模拟很难,也为什么银行储蓄卡都规定有10年的有效期而不能像存折一样无限期使用?估计很多人都没有留意到,无论是借记卡还是信用卡,其实都是有有效使用年限的。其中信用卡的使用年限基本上都是在3年到5年之,极个别银行可能会达到8年时间,但基本上不可能超过10年。至于Java如何优雅的解决空指针?一介绍在实际的系统运行过程中,难免会出现报NullPointerException空指针的错误,造成这样的本质原因就是数据或者对象为空,导致程序进一步执行的时候报错!一般的常规解决WebUI自动化测试的经典设计模式PO一PO设计模式是什么PO的全称是PageObject,是Selenium自动化测试项目开发实践的最佳设计模式之一,通过对界面元素和功能模块的封装减少冗余代码,有利于后期项目的维护。苹果iphone13mini销量不理想下代或被取消去年9月份,苹果发布了很多人期待的十三香iPhone13系列,与iPhone12系列一样依旧是四款产品,并且在Pro版本中首次引入了120Hz高刷,跟上了安卓阵营。日前,市场调研机为什么现在用苹果手机的人还是那样多?因为,他们懂得享受人类技术发展的成果。而不考虑意识形态。连华为老总任正非都说他和她家里人用的都是苹果手机。有各自选择的权利,无可厚非,我还是用华为。我女儿以及她的大部分原来用苹果的苹果手机出货量全世界第一财经网科技1月19日讯,据新浪科技援引Canalys发布的最新报告显示,得益于iPhone13的成功,苹果手机在2021年占全球智能手机出货量的22,夺回全球智能手机市场的头把交椅