前幾天發(fā)布了開(kāi)源4.3寸觸摸屏的文章,里面有WIFI獲取時(shí)間和天氣預(yù)報(bào)相關(guān)的功能,今天就來(lái)介紹一下這個(gè)功能是怎樣實(shí)現(xiàn)的。
1.底層驅(qū)動(dòng)
首先,硬件上,單片機(jī)通過(guò)串口AT指令訪問(wèn)WIFI模塊(ESP8266)。具體AT指令怎樣寫(xiě),可以參考之前的文章《單片機(jī)裸機(jī)環(huán)境下編寫(xiě)AT指令程序》。上電后,先配置WIFI模塊的工作模式等,用到的AT指令如下:
1. 關(guān)閉回顯
ATE0
2. 設(shè)置為STA模式
AT+CWMODE_DEF=1
3. 設(shè)置WIFI名稱和密碼
AT+CWJAP_DEF=”SSID”,”P(pán)assword”
4. 開(kāi)啟DHCP
AT+CWDHCP_DEF=1,1
5. 設(shè)置為單連接模式
AT+CIPMUX=0
6.設(shè)置為透?jìng)髂J?/strong>
AT+CIPMODE=1
2.獲取網(wǎng)絡(luò)時(shí)間 獲取網(wǎng)絡(luò)時(shí)間的方式有兩種,對(duì)于較新版本的固件,可以直接通過(guò)AT指令來(lái)獲取。(可以通過(guò)AT+GMR指令來(lái)查詢固件的版本。) AT+CIPSNTPTIME? 對(duì)于較老版本的固件,不支持該AT指令,只能通過(guò)自己連接網(wǎng)絡(luò)服務(wù)器來(lái)獲取當(dāng)前時(shí)間。具體需要的AT指令如下:
1.建立TCP鏈接
AT+CIPSTART="TCP","www.beijing-time.org",80
2.打開(kāi)傳透模式
AT+CIPSEND
3.收到‘>’符號(hào)后,隨便發(fā)送個(gè)數(shù)據(jù)
4.等待接收數(shù)據(jù)
接收的數(shù)據(jù)可以先用網(wǎng)絡(luò)調(diào)試助手來(lái)測(cè)試,如下,可以看到,數(shù)據(jù)中包含了當(dāng)前的日期和時(shí)間信息,我們可以先找到字符串中“Data”的位置,再解析后面的數(shù)據(jù)。數(shù)據(jù)格式固定,直接按照字符位置解析就行。
需要注意的是,獲取的這個(gè)時(shí)間是格林威治時(shí)間,與北京時(shí)間相差8個(gè)小時(shí)。
當(dāng)然,也可以通過(guò)連接其它NTP時(shí)間服務(wù)器來(lái)獲取時(shí)間,步驟是類似的。
3.獲取天氣預(yù)報(bào) 天氣的獲取就要比時(shí)間稍復(fù)雜一些,網(wǎng)上有很多可以提供天氣預(yù)報(bào)的服務(wù)器,有些可以免費(fèi)使用,一般都需要注冊(cè)一個(gè)賬號(hào),這里以“心知天氣”為例進(jìn)行介紹。步驟如下:
1.注冊(cè)賬號(hào)。
在該網(wǎng)站注冊(cè)一個(gè)賬號(hào):https://www.seniverse.com/。注冊(cè)之后就可以通過(guò)其開(kāi)放的API來(lái)獲取天氣預(yù)報(bào)。有免費(fèi)版和付費(fèi)版,區(qū)別在于訪問(wèn)頻次和獲取的天氣信息內(nèi)容不同。如下:
2.查看私鑰。
在控制臺(tái)查看賬號(hào)的私鑰,這個(gè)在程序中要用。
3.API。
有了這個(gè)私鑰,我們就可以通過(guò)API來(lái)獲取天氣預(yù)報(bào)了,相關(guān)的API說(shuō)明可以在這里查詢:
https://seniverse.yuque.com/books/share/f4f9bf1a-d3d9-4a68-8996-950f8c88400e/sl6gvt#d29hl
先用網(wǎng)絡(luò)調(diào)試助手測(cè)試一下:
可以看到,通過(guò)TCP連接服務(wù)器后,發(fā)送GET請(qǐng)求就可以收到天氣預(yù)報(bào)數(shù)據(jù),接下來(lái)就是解析數(shù)據(jù)了。
4.解析數(shù)據(jù)。
接收的數(shù)據(jù)是JSON格式的字符串,在單片機(jī)中我們可以移植cJSON來(lái)進(jìn)行解析。cJSON是一個(gè)開(kāi)源的C語(yǔ)音解析庫(kù),只有cJSON.c、cJSON.h兩個(gè)文件,直接添加到工程中就可以使用相關(guān)函數(shù)。
程序如下:
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);//接受到的數(shù)據(jù) root = cJSON_Parse(data); if(root) { //printf("JSON格式正確: %s ",cJSON_Print(root)); //輸出json字符串 results = cJSON_GetObjectItem(root, "results"); results = cJSON_GetArrayItem(results,0); if(results) { loc_json = cJSON_GetObjectItem(results, "location"); //得到location鍵對(duì)應(yīng)的值,是一個(gè)對(duì)象 loc_tmp = cJSON_GetObjectItem(loc_json, "id") -> valuestring; //printf("城市ID:%s ",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("城市時(shí)區(qū):%s ",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;//風(fēng)向 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;//風(fēng)力 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格式錯(cuò)誤 "); Weather_Dat[0].Flag = 0; } } else { Weather_Dat[0].Flag = 0; //printf("results格式錯(cuò)誤:%s ", cJSON_GetErrorPtr()); } } else { Weather_Dat[0].Flag = 0; //printf("JSON格式錯(cuò)誤 "); } cJSON_Delete(root); }解析后,將有用數(shù)據(jù)轉(zhuǎn)換為自己想要的格式存儲(chǔ)在變量中。需要注意的是,cJSON可能占用較大的堆棧,因此堆棧需要設(shè)大一些。
總結(jié)一下,獲取天氣預(yù)報(bào)的步驟如下:
1.注冊(cè)賬號(hào)。
2.獲取私鑰。
3.連接服務(wù)器。
AT+CIPSTART="TCP”,” api.seniverse.com”,80
4..打開(kāi)傳透模式。
AT+CIPSEND
5..收到‘>’符號(hào)后,發(fā)送GET請(qǐng)求
GET https://api.seniverse.com/v3/weather/daily.json?key=your_key&location=ip&language=zh-Hans&unit=c&start=0&days=3
6.等待接收數(shù)據(jù),并解析。
以上就是單片機(jī)通過(guò)AT指令訪問(wèn)WIFI模塊獲取網(wǎng)絡(luò)時(shí)間和天氣預(yù)報(bào)的方法,需要注意的是上述所有指令后面別忘了加回車換行符。
審核編輯:劉清
-
單片機(jī)
+關(guān)注
關(guān)注
6037文章
44569瀏覽量
636152 -
觸摸屏
+關(guān)注
關(guān)注
42文章
2309瀏覽量
116331 -
wifi模塊
+關(guān)注
關(guān)注
60文章
380瀏覽量
73540 -
ESP8266
+關(guān)注
關(guān)注
50文章
962瀏覽量
45105
原文標(biāo)題:?jiǎn)纹瑱C(jī)通過(guò)WIFI模塊(ESP8266)獲取網(wǎng)絡(luò)時(shí)間與天氣預(yù)報(bào)
文章出處:【微信號(hào):嵌入式技術(shù)開(kāi)發(fā),微信公眾號(hào):嵌入式技術(shù)開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論