本文章介紹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);
}
}
沒有留言:
張貼留言