天天看點

單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報

前幾天釋出了開源4.3寸觸摸屏的文章,裡面有WIFI擷取時間和天氣預報相關的功能,今天就來介紹一下這個功能是怎樣實作的。

1.底層驅動

首先,硬體上,單片機通過序列槽AT指令通路WIFI子產品(ESP8266)。具體AT指令怎樣寫,可以參考之前的文章《單片機裸機環境下編寫AT指令程式》。上電後,先配置WIFI子產品的工作模式等,用到的AT指令如下:

1. 關閉回顯

ATE0

2. 設定為STA模式

AT+CWMODE_DEF=1

3. 設定WIFI名稱和密碼

AT+CWJAP_DEF=”SSID”,”Password”

4. 開啟DHCP

AT+CWDHCP_DEF=1,1

5. 設定為單連接配接模式

AT+CIPMUX=0

6. 設定為透傳模式

AT+CIPMODE=1

2.擷取網絡時間

擷取網絡時間的方式有兩種,對于較新版本的固件,可以直接通過AT指令來擷取。(可以通過AT+GMR指令來查詢固件的版本。)

AT+CIPSNTPTIME?

對于較老版本的固件,不支援該AT指令,隻能通過自己連接配接網絡伺服器來擷取目前時間。具體需要的AT指令如下:

1.建立TCP連結

AT+CIPSTART="TCP","www.beijing-time.org",80

2.打開傳透模式

AT+CIPSEND

3.收到‘>’符号後,随便發送個資料

4.等待接收資料

接收的資料可以先用網絡調試助手來測試,如下,可以看到,資料中包含了目前的日期和時間資訊,我們可以先找到字元串中“Data”的位置,再解析後面的資料。資料格式固定,直接按照字元位置解析就行。

需要注意的是,擷取的這個時間是格林威治時間,與中原標準時間相差8個小時。

當然,也可以通過連接配接其它NTP時間伺服器來擷取時間,步驟是類似的。

單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報

3.擷取天氣預報

天氣的擷取就要比時間稍複雜一些,網上有很多可以提供天氣預報的伺服器,有些可以免費使用,一般都需要注冊一個賬号,這裡以“心知天氣”為例進行介紹。步驟如下:

1.新增賬號。在該網站注冊一個賬号:https://www.seniverse.com/。注冊之後就可以通過其開放的API來擷取天氣預報。有免費版和付費版,差別在于通路頻次和擷取的天氣資訊内容不同。如下:

單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報

2.檢視私鑰。在控制台檢視賬号的私鑰,這個在程式中要用。

單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報

3.API。有了這個私鑰,我們就可以通過API來擷取天氣預報了,相關的API說明可以在這裡查詢:

https://seniverse.yuque.com/books/share/f4f9bf1a-d3d9-4a68-8996-950f8c88400e/sl6gvt#d29hl

先用網絡調試助手測試一下:

單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報

可以看到,通過TCP連接配接伺服器後,發送GET請求就可以收到天氣預報資料,接下來就是解析資料了。

嵌入式物聯網需要學的東西真的非常多,千萬不要學錯了路線和内容,導緻工資要不上去!

無償分享大家一個資料包,差不多150多G。裡面學習内容、面經、項目都比較新也比較全!某魚上買估計至少要好幾十。

點選這裡找小助理0元領取:點選文中藍色字型領取吖

單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報
單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報

4.解析資料。接收的資料是JSON格式的字元串,在單片機中我們可以移植cJSON來進行解析。cJSON是一個開源的C語音解析庫,隻有cJSON.c、cJSON.h兩個檔案,直接添加到工程中就可以使用相關函數。程式如下:

void Weather_JSON( )
{  
    char *data;
    cJSON *root;
    cJSON *results;
    cJSON *last_update;
    cJSON *loc_json, *daily_json;
    cJSON *forecast_json;
    char *loc_tmp, *weather_tmp;
    int i = 0;


    data = (char*)(Uart1.RxBuf);//接受到的資料
    root = cJSON_Parse(data);
    if(root)
    {
        //printf("JSON格式正确:\n%s\n\n",cJSON_Print(root));    //輸出json字元串
        results = cJSON_GetObjectItem(root, "results");
        results = cJSON_GetArrayItem(results,0);
        if(results)
        {
            loc_json = cJSON_GetObjectItem(results, "location");   //得到location鍵對應的值,是一個對象


            loc_tmp = cJSON_GetObjectItem(loc_json, "id") -> valuestring;
            //printf("城市ID:%s\n",loc_tmp);
            loc_tmp = cJSON_GetObjectItem(loc_json, "name") -> valuestring;
            memset(loc_str,0,20);
            memcpy(loc_str,loc_tmp,strlen(loc_tmp));
          
            loc_tmp = cJSON_GetObjectItem(loc_json, "timezone") -> valuestring;
            //printf("城市時區:%s\n\n",loc_tmp);


            daily_json = cJSON_GetObjectItem(results, "daily");
            if(daily_json)
            {
                Weather_Dat[0].Flag = 1;
                for(i = 0; i < 3; i++)
                {
                    forecast_json = cJSON_GetArrayItem(daily_json, i);
                    //weather_tmp = cJSON_GetObjectItem(forecast_json, "date") -> valuestring;//日期


                    weather_tmp = cJSON_GetObjectItem(forecast_json, "code_day") -> valuestring;//白天天氣代碼
                    Weather_Dat[i].Weathcode = atoi(weather_tmp);


                    //weather_tmp = cJSON_GetObjectItem(forecast_json, "code_night") -> valuestring;//晚上天氣代碼


                    weather_tmp = cJSON_GetObjectItem(forecast_json, "high") -> valuestring;//最高溫度
                    memset(Weather_Dat[i].HighT,0,4);
                    memcpy(Weather_Dat[i].HighT,weather_tmp,strlen(weather_tmp));


                  
                    weather_tmp = cJSON_GetObjectItem(forecast_json, "low") -> valuestring;//最低溫度
                    memset(Weather_Dat[i].LowT,0,4);
                    memcpy(Weather_Dat[i].LowT,weather_tmp,strlen(weather_tmp));
                  
                    weather_tmp = cJSON_GetObjectItem(forecast_json, "wind_direction") -> valuestring;//風向
                    memset(Weather_Dat[i].Wind_Dir,0,10);
                    memcpy(Weather_Dat[i].Wind_Dir,weather_tmp,strlen(weather_tmp));
                  
                    weather_tmp = cJSON_GetObjectItem(forecast_json, "wind_scale") -> valuestring;//風力
                    memset(Weather_Dat[i].WindScale,0,4);
                    memcpy(Weather_Dat[i].WindScale,weather_tmp,strlen(weather_tmp));
                  
                    weather_tmp = cJSON_GetObjectItem(forecast_json, "humidity") -> valuestring;//濕度
                    memset(Weather_Dat[i].Humi,0,4);
                    memcpy(Weather_Dat[i].Humi,weather_tmp,strlen(weather_tmp));
                }
            }
            else
            {
                //printf("daily json格式錯誤\r\n");
                Weather_Dat[0].Flag = 0;
            }


        }
        else
        {
            Weather_Dat[0].Flag = 0;
            //printf("results格式錯誤:%s\r\n", cJSON_GetErrorPtr());
        }
    }
    else
    {
        Weather_Dat[0].Flag = 0;
        //printf("JSON格式錯誤\r\n");
    }
    cJSON_Delete(root);  
}           

解析後,将有用資料轉換為自己想要的格式存儲在變量中。需要注意的是,cJSON可能占用較大的堆棧,是以堆棧需要設大一些。

總結一下,擷取天氣預報的步驟如下:

1.新增賬號。

2.擷取私鑰。

3.連接配接伺服器。

AT+CIPSTART="TCP”,” api.seniverse.com”,80

4..打開傳透模式。

AT+CIPSEND

5..收到‘>’符号後,發送GET請求

GET https://api.seniverse.com/v3/weather/daily.json?key=your_key&location=ip&language=zh-Hans&unit=c&start=0&days=3

6.等待接收資料,并解析。

以上就是單片機通過AT指令通路WIFI子產品擷取網絡時間和天氣預報的方法,需要注意的是上述所有指令後面别忘了加回車換行符。

文章連結:https://mp.weixin.qq.com/s/Xy1FJBqAF_ByP4GyznkLxw

轉載自:Mr張工 嵌入式技術開發

文章來源:單片機通過WIFI子產品(ESP8266)擷取網絡時間與天氣預報

版權申明:本文來源于網絡,免費傳達知識,版權歸原作者所有。如涉及作品版權問題,請聯系我進行删除。

繼續閱讀