本文章介紹Raspberry Pi Pico W c-sdk,使用lwIP的HTTP Client Application 存取openweathermap網站的氣象資料,顯示在TFT LCD上。
使用httpc_get_file_dns function取得 網站資料。分別設定三個callback function:
1: httpc_result_fn:
2. httpc_headers_done_fn:
err_t recv_fn(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err)
詳細程式碼請參閱文末說明。
成果影片:
程式碼:
#include <stdio.h> #include "pico/stdlib.h" #include "pico/cyw43_arch.h" #include "lwip/apps/http_client.h" #include "modules/ili9341_tft/fonts/wind_deg.h" #include "modules/ili9341_tft/fonts/wind.h" #include "modules/ili9341_tft/fonts/temp.h" #include "modules/ili9341_tft/fonts/feels.h" #include "modules/ili9341_tft/fonts/humidity.h" #include "modules/ili9341_tft/fonts/Rain.h" #include "modules/ili9341_tft/fonts/Clouds.h" #include "modules/ili9341_tft/fonts/Clear.h" #include "modules/ili9341_tft/fonts/Font36.h" #include "modules/ili9341_tft/fonts/font_fixedsys_mono_24.h" #include "hardware/rtc.h" #include "modules/ili9341_tft/ili9341.h" #include "time.h" #include "ntp_time.h" #include "cJSON.h" #include "math.h" char ssid[] = "your_SSIO"; char pass[] = "your_PASSWORD"; uint32_t country = CYW43_COUNTRY_TAIWAN; uint32_t auth = CYW43_AUTH_WPA2_AES_PSK; char myBuff[1000]; typedef struct weather_data_t { cJSON *data_json; bool completed; int temp; int feels_like; uint8_t humidity; uint16_t pressure; uint8_t name[20]; uint8_t weather[10]; float wind_speed; uint16_t wind_deg; }WEATHER_DATA; WEATHER_DATA weather_data; void rotate_image(const uint8_t *src, uint8_t *dest, uint16_t width, uint16_t height, uint16_t deg) { double sinx = sin((-1*deg)/180.0 * M_PI); // -degrees double cosx = cos((-1*deg)/180.0 * M_PI); uint16_t inputImage[width][height]; uint16_t rotatedImage[width][height]; for (int y=0; y < height; y++) { for (int x=0; x < width; x++) { inputImage[x][y] = src[y*width*2+2*x]<<8 | src[y*width*2+2*x+1]; } } int xCenter = height/2; // Rotate image by its center. int yCenter = width/2; int xt,yt,xRotate,yRotate; for(int x=0; x<height; x++) { xt = x - xCenter; double xt_cosx = xt*cosx; double xt_sinx = xt*sinx; for(int y=0; y<width; y++) { yt = y - yCenter; xRotate = (int)(lround(xt_cosx - (yt*sinx)) + xCenter); yRotate = lround((yt*cosx) + xt_sinx) + yCenter; if( (xRotate >= 0) && (xRotate < height) && (yRotate >= 0) && (yRotate < width) ) { rotatedImage[x][y] = inputImage[xRotate][yRotate]; } else { rotatedImage[x][y] = 0xffff; } } } for (int y=0; y < height; y++) { for (int x=0; x < width; x++) { dest[y*width*2+2*x] = rotatedImage[x][y] >> 8; dest[y*width*2+2*x+1] = rotatedImage[x][y] &0xff; } } } void result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, u32_t srv_res, err_t err) { if (httpc_result == HTTPC_RESULT_OK) { printf("transfer complete\n"); printf("result=%d\n", httpc_result); } else { printf("httpc error, result=:%d\n", httpc_result); } } err_t headers(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u32_t content_len) { return ERR_OK; } err_t body(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err) { pbuf_copy_partial(p, myBuff, p->tot_len, 0); printf("%s", myBuff); weather_data.data_json = cJSON_Parse(myBuff); weather_data.completed=true; return ERR_OK; } void get_weather_data(WEATHER_DATA *wdata, uint8_t* city) { cJSON_Delete(weather_data.data_json); weather_data.completed=false; httpc_connection_t settings; settings.result_fn = result; settings.headers_done_fn = headers; settings.use_proxy = false; uint8_t qstr[200]; sprintf(qstr, "/data/2.5/weather?q=%s,tw&APPID={your_APPID}", city); err_t err = httpc_get_file_dns( "api.openweathermap.org", LWIP_IANA_PORT_HTTP, qstr, &settings, body, NULL, NULL ); while(!wdata->completed) { //printf("not receive data yet!\n"); sleep_ms(100); } cJSON *main = cJSON_GetObjectItem(wdata->data_json, "main"); cJSON *wind = cJSON_GetObjectItem(wdata->data_json, "wind"); cJSON *weather = cJSON_GetArrayItem(cJSON_GetObjectItem(wdata->data_json, "weather"), 0); wdata->temp=(int)(round((cJSON_GetNumberValue(cJSON_GetObjectItem(main, "temp"))-273.15))); wdata->feels_like=(int)(round((cJSON_GetNumberValue(cJSON_GetObjectItem(main, "feels_like"))-273.15))); wdata->humidity=(int)(cJSON_GetNumberValue(cJSON_GetObjectItem(main, "humidity"))); wdata->pressure=(uint16_t)(cJSON_GetNumberValue(cJSON_GetObjectItem(main, "pressure"))); wdata->wind_speed=(cJSON_GetNumberValue(cJSON_GetObjectItem(wind, "speed"))); wdata->wind_deg=(uint16_t)(cJSON_GetNumberValue(cJSON_GetObjectItem(wind, "deg"))); strcpy(wdata->weather,cJSON_GetStringValue(cJSON_GetObjectItem(weather, "main"))); strcpy(wdata->name,cJSON_GetStringValue(cJSON_GetObjectItem(wdata->data_json, "name"))); //uint32_t dt =(uint32_t) cJSON_GetNumberValue(cJSON_GetObjectItem(wdata->data_json, "dt")); //uint32_t timezone =(uint32_t) cJSON_GetNumberValue(cJSON_GetObjectItem(wdata->data_json, "timezone")); //time_t t = dt+timezone; //struct tm *now = gmtime(&t); datetime_t now; rtc_get_datetime(&now); //cJSON_free(main); //cJSON_free(wind); //cJSON_free(weather); uint8_t buf[20]; ili9341_draw_string_withbg(65, 5, " ", 0xffff, 0xffff, &Font36); ili9341_draw_string_withbg(65, 5, wdata->name, 0xff00, 0xffff, &Font36); sprintf(buf, "%d ", wdata->temp); ili9341_draw_string_withbg(75, 65, buf, 0x001f, 0xffff, &Font36); sprintf(buf, "%d ", wdata->feels_like); ili9341_draw_string_withbg(225, 65, buf, 0x001f, 0xffff, &Font36); sprintf(buf, "%d%s ", wdata->humidity, "%"); ili9341_draw_string_withbg(65, 125, buf, 0x001f, 0xffff, &Font36); sprintf(buf, "%dhPa ", wdata->pressure); ili9341_draw_string_withbg(185, 125, buf, 0x001f, 0xffff, &Font36); sprintf(buf, "%.1fm/s ", wdata->wind_speed); ili9341_draw_string_withbg(75, 185, buf, 0x001f, 0xffff, &Font36); rotate_image(image_data_wind_deg, rotate_image_data_wind_deg, wind_deg.width, wind_deg.height, wdata->wind_deg); ili9341_draw_bitmap(160, 185, &rotate_wind_deg); sprintf(buf, "%02d/%02d", now.month, now.day); ili9341_draw_string_withbg(220, 185, buf, 0xf800, 0xffff, &font_fixedsys_mono_24); sprintf(buf, "%02d:%02d", now.hour, now.min); ili9341_draw_string_withbg(220, 210, buf, 0xf800, 0xffff, &font_fixedsys_mono_24); if (strcmp(wdata->weather, "Clouds")==0) { ili9341_draw_bitmap(250, 5, &Clouds); } if (strcmp(wdata->weather, "Rain")==0) { ili9341_draw_bitmap(250, 5, &Rain); } if (strcmp(wdata->weather, "Clear")==0) { ili9341_draw_bitmap(250, 5, &Clear); } } bool wifi_connect() { cyw43_arch_enable_sta_mode(); if (cyw43_arch_wifi_connect_timeout_ms(ssid, pass, auth, 10000)) { printf("wifi connect error\n"); return false; } int wait_secs = 0; int link_state; while (wait_secs <= 10) { link_state = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); if (link_state != CYW43_LINK_UP) { wait_secs++; if (wait_secs == 10) { printf("Can not get ip address\n"); return false; } sleep_ms(1000); } else { break; } } return true; } void weather_background() { ili9341_draw_string(5,5, "City:", 0x0000, &Font36); ili9341_draw_bitmap(5, 65, &temp); ili9341_draw_bitmap(165, 65, &feels); ili9341_draw_bitmap(5, 125, &humidity); ili9341_draw_bitmap(5, 185, &wind); } int main() { stdio_init_all(); cyw43_arch_init(); ili9341_init(); weather_data.data_json=cJSON_CreateObject(); weather_background(); if (!wifi_connect()) { printf("connect wifi error\n"); } ntp_time_init(); get_ntp_time(); while(1) { get_weather_data(&weather_data, "Taipei"); sleep_ms(5000); get_weather_data(&weather_data, "Taitung"); sleep_ms(5000); get_weather_data(&weather_data, "Kaohsiung"); sleep_ms(5000); } }
沒有留言:
張貼留言