日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 嵌入式 > 嵌入式大雜燴
[導讀]點擊上方「嵌入式大雜燴」,選擇「置頂公眾號」第一時間查看嵌入式筆記! 上一篇分享了《基于4G Cat.1的內(nèi)網(wǎng)穿透實踐》,這一篇筆記我們直接使用4G開發(fā)板訪問天氣服務器獲取天氣數(shù)據(jù)。 我們要使用移遠4G模塊進行網(wǎng)絡通信,要經(jīng)歷 3 個主要過程:網(wǎng)絡注冊、網(wǎng)

點擊上方「嵌入式大雜燴」,選擇「置頂公眾號」第一時間查看嵌入式筆記!

上一篇分享了《基于4G Cat.1的內(nèi)網(wǎng)穿透實踐》,這一篇筆記我們直接使用4G開發(fā)板訪問天氣服務器獲取天氣數(shù)據(jù)。

我們要使用移遠4G模塊進行網(wǎng)絡通信,要經(jīng)歷 3 個主要過程:網(wǎng)絡注冊、網(wǎng)絡激活socket 創(chuàng)建。

網(wǎng)絡注冊是自動完成的,無需用戶代碼干預(網(wǎng)絡注冊前,請確認 SIM 卡是否正常識別且 SIM 卡無欠費等業(yè)務異常)。

只有在網(wǎng)絡注冊成功以后,才可進行網(wǎng)絡激活,即本文所述的撥號(下文皆稱為撥號)。只有撥號成功后,才可進行 socket 網(wǎng)絡通信。

撥號+socket 通信基本流程


確保撥號成功的必要條件:SIM 卡沒欠費;硬件良好,天線匹配;撥號前,調(diào)用 ql_network_register_wait 等待網(wǎng)絡注冊成功;撥號時,向 ql_start_data_call 傳遞正確的參數(shù)。

Socket 通信流程


EC100 模塊 Socket 通信基本流程如上圖:

1、在進行 socket 通信之前,必須確保撥號已經(jīng)成功,可以通過 ql_get_data_call_info()查詢需要進行 socket 通信的網(wǎng)絡通道是否撥號成功。

2、撥號成功后進行 socket 通信時,必須對需要通信的網(wǎng)絡通道進行 bind 操作。不管是 UDP 還是 TCP,都必須執(zhí)行 Bind 操作之后才可以正常進行 socket 通信。

sdk中給我們提供了一個tcp_client的demo,這個demo的設計思路完全按照上面兩張圖流程圖來設計。我們在這個demo進行修改,獲取天氣數(shù)據(jù)。

我們修改后的example_tcp_weather_client.c代碼如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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

#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=c\r\n\r\n"

 
/* JSON數(shù)據(jù)包 */ 
#define  NOW_JSON     "now"
//....還用更多其他的天氣數(shù)據(jù)包可查閱心知天氣

/* 天氣數(shù)據(jù)結構體 */
typedef struct
{

 /* 實況天氣數(shù)據(jù) */
 char id[32];     //id
 char name[32];     //地名
 char country[32];    //國家
 char path[32];     //完整地名路徑
 char timezone[32];    //時區(qū)
 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};

// 函數(shù)聲明
static void GetWeather(char *weather_json, char *location, Weather *result);
static int cJSON_NowWeatherParse(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);

/*******************************************************************************************************
** 函數(shù): sockets_weather_test
**------------------------------------------------------------------------------------------------------
** 參數(shù): 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\n");

 /* 撥號開始 */
 datacall_satrt();

 /* 獲取撥號信息 */
 ql_get_data_call_info(10, &info);

 printf("info.profile_idx: %d\r\n", info.profile_idx);
 printf("info.ip_version: %d\r\n", info.ip_version);
 printf("info.v4.state: %d\r\n", info.v4.state);
 printf("info.v4.reconnect: %d\r\n", info.v4.reconnect);

 inet_ntop(AF_INET, &info.v4.addr.ip, ip4_addr_str, sizeof(ip4_addr_str));
 printf("info.v4.addr.ip: %s\r\n", 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: %s\r\n", 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: %s\r\n", ip4_addr_str);

 ip4_addr = info.v4.addr.ip;

 if(info.v4.state)
 {
  memset(&weather_data, 0sizeof(weather_data));  // weather_data清零 
  GetWeather(NOW_JSON, location, &weather_data);   // GET 并解析實況天氣數(shù)據(jù)
  DisplayWeather(&weather_data);      // 顯示天氣結果
 }

 printf("========== sockets tcp test finished\r\n");
 
 return 0;
}
 
static void ql_nw_status_callback(int profile_idx, int nw_status)
{
 printf("profile(%d) status: %d\r\n", profile_idx, nw_status);
}

static void datacall_satrt(void)
{
 printf("wait for network register done\r\n");

 /* 等待網(wǎng)絡注冊結果 */
 if(ql_network_register_wait(120) != 0)
 {
  printf("*** network register fail ***\r\n");
 }
 else
 {
  printf("doing network activing ...\r\n");
  
  ql_wan_start(ql_nw_status_callback);   /* 撥號初始化:注冊撥號回調(diào)函數(shù) */
  ql_set_auto_connect(1, TRUE);     /* 設置撥號掉線是否自動重連 */
  ql_start_data_call(10NULLNULLNULL0);  /* 開始撥號 */
 }
}

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  * reshints;
 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, 0sizeof(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\n");
  goto exit;
 }

 dns_success = 1;
 
 ret = socket(AF_INET, SOCK_STREAM, 0);
 if(ret < 0)
 {
  printf("*** socket create fail ***\r\n");
  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\n");
  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: %u\r\n", ret, errno);

 if(ret == -1 && errno != EINPROGRESS)
 {
  printf("*** connect fail ***\r\n");
  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: %d\r\n", ret);

 if(ret <= 0)
 {
  printf("*** select timeout or error ***\r\n");
  goto exit;
 }

 if(!FD_ISSET(sock_fd, &read_fds) && !FD_ISSET(sock_fd, &write_fds))
 {
  printf("*** connect fail ***\r\n");
  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 success\r\n");
  }
  else
  {
   printf("*** connect fail, sock_err = %d, errno = %u ***\r\n", sock_error, errno);
   goto exit;
  }
 }
 else if(!FD_ISSET(sock_fd, &read_fds) && FD_ISSET(sock_fd, &write_fds))
 {
  printf("connect success\r\n");
 }
 else if(FD_ISSET(sock_fd, &read_fds) && !FD_ISSET(sock_fd, &write_fds))
 {
  printf("*** connect fail ***\r\n");
  goto exit;
 }
 else
 {
  printf("*** connect fail ***\r\n");
  goto exit;
 }

 /* 組合GET請求包 */
 sprintf(GetRequestBuf, GET_REQUEST_PACKAGE, weather_json, KEY, location);

 /* 發(fā)送數(shù)據(jù)到服務端 */
 ret = send(sock_fd, (const void*)GetRequestBuf, strlen(GetRequestBuf), 0);
 if(ret < 0)
 {
  printf("*** send fail ***\r\n");
  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, NULLNULL, &t);

 printf("select ret: %d\r\n", ret);

 if(ret <= 0)
 {
  printf("*** select timeout or error ***\r\n");
  goto exit;
 }

 if(FD_ISSET(sock_fd, &read_fds))
 {
  ret = recv(sock_fd, WeatherRecvBuf, sizeof(WeatherRecvBuf), 0);
  if(ret > 0)
  {
   printf("recv data: [%d]%s\r\n", ret, WeatherRecvBuf);
   /* 解析天氣數(shù)據(jù)并保存到結構體變量weather_data中 */
   if (0 == strcmp(weather_json, NOW_JSON))  // 天氣實況
   {
    cJSON_NowWeatherParse(WeatherRecvBuf, result); 
   }
  }
  else if(ret == 0)
  {
   printf("*** peer closed ***\r\n");
   goto exit;
  }
  else
  {
   if(!(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
   {
    printf("*** error occurs ***\r\n");
    goto exit;
   }
   else
   {
    printf("wait for a while\r\n");
    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));

  /* 清空緩沖區(qū) */
  memset(GetRequestBuf, 0256);   
  memset(WeatherRecvBuf, 02*1024);    
  close(sock_fd);
 }
}

/*******************************************************************************************************
** 函數(shù): cJSON_NowWeatherParse,解析天氣實況數(shù)據(jù)
**------------------------------------------------------------------------------------------------------
** 參數(shù): JSON:天氣數(shù)據(jù)包   result:數(shù)據(jù)解析的結果
** 返回: void
********************************************************************************************************/

static int cJSON_NowWeatherParse(char *JSON, Weather *result)
{
 cJSON *json,*arrayItem,*object,*subobject,*item;
 
 json = cJSON_Parse(JSON); //解析JSON數(shù)據(jù)包
 if(json == NULL)    //檢測JSON數(shù)據(jù)包是否存在語法上的錯誤,返回NULL表示數(shù)據(jù)包無效
 {
  printf("Error before: [%s]\n",cJSON_GetErrorPtr()); //打印數(shù)據(jù)包語法錯誤的位置
  return 1;
 }
 else
 {
  if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL); //匹配字符串"results",獲取數(shù)組內(nèi)容
  {
   int size = cJSON_GetArraySize(arrayItem);     //獲取數(shù)組中對象個數(shù)
#if DEBUG
   printf("cJSON_GetArraySize: size=%d\n",size); 
#endif
   if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//獲取父對象內(nèi)容
   {
    /* 匹配子對象1:城市地區(qū)相關 */
    if((subobject = cJSON_GetObjectItem(object,"location")) != NULL)
    {
     // 匹配id
     if((item = cJSON_GetObjectItem(subobject,"id")) != NULL)   
     {
      memcpy(result->id, item->valuestring,strlen(item->valuestring));   // 保存數(shù)據(jù)供外部調(diào)用
     }
     // 匹配城市名
     if((item = cJSON_GetObjectItem(subobject,"name")) != NULL
     {
      memcpy(result->name, item->valuestring,strlen(item->valuestring));   // 保存數(shù)據(jù)供外部調(diào)用
     }
     // 匹配城市所在的國家
     if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)
     {
      memcpy(result->country, item->valuestring,strlen(item->valuestring));  // 保存數(shù)據(jù)供外部調(diào)用
     }
     // 匹配完整地名路徑
     if((item = cJSON_GetObjectItem(subobject,"path")) != NULL)  
     {
      memcpy(result->path, item->valuestring,strlen(item->valuestring));   // 保存數(shù)據(jù)供外部調(diào)用 
     }
     // 匹配時區(qū)
     if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)
     {
      memcpy(result->timezone, item->valuestring,strlen(item->valuestring));  // 保存數(shù)據(jù)供外部調(diào)用 
     }
     // 匹配時差
     if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)
     {
      memcpy(result->timezone_offset, item->valuestring,strlen(item->valuestring));  // 保存數(shù)據(jù)供外部調(diào)用
     }
    }
    /* 匹配子對象2:今天的天氣情況 */
    if((subobject = cJSON_GetObjectItem(object,"now")) != NULL)
    {
     // 匹配天氣現(xiàn)象文字
     if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)
     {
      memcpy(result->text, item->valuestring,strlen(item->valuestring));  // 保存數(shù)據(jù)供外部調(diào)用
     }
     // 匹配天氣現(xiàn)象代碼
     if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)
     {
      memcpy(result->code, item->valuestring,strlen(item->valuestring));  // 保存數(shù)據(jù)供外部調(diào)用
     }
     // 匹配氣溫
     if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL
     {
      memcpy(result->temperature, item->valuestring,strlen(item->valuestring));   // 保存數(shù)據(jù)供外部調(diào)用
     } 
    }
    /* 匹配子對象3:數(shù)據(jù)更新時間(該城市的本地時間) */
    if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL)
    {
     memcpy(result->last_update, subobject->valuestring,strlen(subobject->valuestring));   // 保存數(shù)據(jù)供外部調(diào)用
    }
   } 
  }
 }
 
 cJSON_Delete(json); //釋放cJSON_Parse()分配出來的內(nèi)存空間
 
 return 0;
}

/*******************************************************************************************************
** 函數(shù): DisplayWeather,顯示天氣數(shù)據(jù)
**------------------------------------------------------------------------------------------------------
** 參數(shù): weather_data:天氣數(shù)據(jù)
** 返回: void
********************************************************************************************************/

static void DisplayWeather(Weather *weather_data)
{
 printf("============%s today weather===========\n", weather_data->name);
 printf("weather_data->text: %s\n", weather_data->text);  
 printf("weather_data->temperature: %s\n", weather_data->temperature); 
 printf("weather_data->timezone: %s\n", weather_data->timezone); 
 printf("weather_data->timezone_offset: %s\n", weather_data->timezone_offset);
 printf("weather_data->last_update: %s\n", weather_data->last_update);
}

application_init(sockets_weather_test, "sockets_weather_test"84);


測試結果:


關于天氣獲取、解析代碼以及亂碼數(shù)據(jù)之前已經(jīng)有詳細分享過,這里不再解釋。相關文章:socket應用】基于C語言的天氣客戶端的實現(xiàn)

猜你喜歡

C語言、嵌入式應用:TCP通信實例分析

一些不可不知的計算機網(wǎng)絡基礎

AT指令測試ESP8266通信模組并獲取天氣數(shù)據(jù)

基于RT-Thread的智慧路燈案例實驗分享

基于GUILite的簡易萬年歷

基于LiteOS的智慧農(nóng)業(yè)案例實驗分享



免責聲明:本文來源網(wǎng)絡,免費傳達知識,版權歸原作者所有。如涉及作品版權問題,請聯(lián)系我進行刪除。

免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅(qū)動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅(qū)動性能的關鍵。

關鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質(zhì)量和效率直接關系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅(qū)動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關鍵字: LED 驅(qū)動電源 開關電源

LED驅(qū)動電源是把電源供應轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅(qū)動電源
關閉