内容介绍
内容介绍
Wio Terminal 天气预报仪
Wio Terminal 介绍
产品特性
- 高度集成的设计
-
- MCU, LCD, WIFI, BT, IMU, 麦克风, 蜂鸣器, microSD Card, 光传感器, 五向开关, 光传感器和红外发射器 (IR 940nm), 加密验证
- 由 Microchip ATSAMD51P19 提供支持
-
- ARM Cortex-M4F运行速度 120MHz (最高可达200MHz)
- 4 MB 外置闪存, 192 KB RAM
- 全面的协议支持
-
- SPI, I2C, I2S, ADC, DAC, PWM, UART(Serial)
- 强大的 无线连接
-
- 由 Realtek RTL8720DN 提供支持
- 双频 2.4Ghz / 5Ghz Wi-Fi (802.11 a/b/g/n)
-
- BLE / BLE 5.0
- USB OTG支持
-
- USB 主机
- USB 客户端
- 软件支持
-
- Arduino
- MicroPython
-
- ArduPy
- AT Firmware
实现功能介绍
1. 连接WiFi;
2. HTTP访问心知天气API, 获取天气信息;
3. JSON代码解析天气信息;
4. LCD上显示天气;
5. 按键切换显示城市;
开发流程
代码解析
1. main中创建任务
void setup()
{
Serial.begin(115200);
LvglInit();
xTaskCreate(LvglTask, "Lvgl Task", 1024, NULL, tskIDLE_PRIORITY + 1, &Handle_lvglTask);
xTaskCreate(GetWeatherTask, "Weather Task", 1024, NULL, tskIDLE_PRIORITY + 2, &Handle_weatherTask);
xTaskCreate(ScanKeyTask, "key Task", 1024, NULL, tskIDLE_PRIORITY + 0, &Handle_keyTask);
}
void loop()
{
delay(1000);
}
2. 各任务处理内容
void GetWeatherTask(void* pvParameters)
{
xSemaphore = xSemaphoreCreateBinary();
assert(xSemaphore != NULL);
WifiConncet();
delay(1000);
WeatherUi();
for (;;) {
xSemaphoreTake(xSemaphore, 3000);
GetWeatherJsonData(CityList[CitySelect]);
SetWeatherShow(TodayWeather, FutureWeather);
xSemaphoreGive(xSemaphore);
delay(5000);
}
}
void ScanKeyTask(void* pvParameters)
{
pinMode(WIO_5S_PRESS, INPUT);
for (;;) {
if (digitalRead(WIO_5S_PRESS) == LOW) {
delay(10);
if (digitalRead(WIO_5S_PRESS) == LOW) {
xSemaphoreTake(xSemaphore, 3000);
CitySelect++;
CitySelect %= sizeof(CityList) / sizeof(CityList[0]);
GetWeatherJsonData(CityList[CitySelect]);
SetWeatherShow(TodayWeather, FutureWeather);
xSemaphoreGive(xSemaphore);
}
}
delay(50);
}
}
void LvglTask(void* pvParameters)
{
for (;;) {
lv_tick_handler();
lv_task_handler(); /* let the GUI do its work */
delay(LVGL_TICK_PERIOD);
}
}
3. 天气获取
void GetWeatherJsonData(String city)
{
String today_weather_json = GetHttpsClinetJsonData(URL[0] + city);
String air_info_json = GetHttpsClinetJsonData(URL[1] + city);
String future_weather_json = GetHttpsClinetJsonData(URL[2] + city);
if (today_weather_json) {
deserializeJson(doc, today_weather_json);
TodayWeather.city = doc["results"][0]["location"]["name"].as<String>();
TodayWeather.date.year = doc["results"][0]["last_update"].as<String>().substring(0, 4).toInt();
TodayWeather.date.mon = doc["results"][0]["last_update"].as<String>().substring(5, 7).toInt();
TodayWeather.date.day = doc["results"][0]["last_update"].as<String>().substring(8, 10).toInt();
TodayWeather.weather = doc["results"][0]["now"]["text"].as<String>();
TodayWeather.temperature = doc["results"][0]["now"]["temperature"].as<int8_t>();
TodayWeather.humidity = doc["results"][0]["now"]["humidity"].as<uint8_t>();
}
if (air_info_json) {
deserializeJson(doc, air_info_json);
TodayWeather.airQuality = doc["results"][0]["air"]["city"]["aqi"].as<uint8_t>();
}
if (future_weather_json) {
deserializeJson(doc, future_weather_json);
for (uint8_t i = 0; i < sizeof(FutureWeather) / sizeof(FutureWeatherType); i++) {
FutureWeather[i].date.year = doc["results"][0]["daily"][i]["date"].as<String>().substring(0, 4).toInt();
FutureWeather[i].date.mon = doc["results"][0]["daily"][i]["date"].as<String>().substring(5, 7).toInt();
FutureWeather[i].date.day = doc["results"][0]["daily"][i]["date"].as<String>().substring(8, 10).toInt();
FutureWeather[i].weatherDay = doc["results"][0]["daily"][i]["text_day"].as<String>();
FutureWeather[i].weatherNight = doc["results"][0]["daily"][i]["text_night"].as<String>();
FutureWeather[i].tempMax = doc["results"][0]["daily"][i]["high"].as<int8_t>();
FutureWeather[i].tempMin = doc["results"][0]["daily"][i]["low"].as<int8_t>();
}
}
PrintWeatherData();
}
4. WiFi连接
static void WifiConncet(void)
{
Serial.printf("WiFi Firmware Version: %s\n", rpc_system_version());
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(50);
ui.connect = lv_label_create(lv_scr_act(), NULL);
lv_obj_align(ui.connect, NULL, LV_ALIGN_CENTER, 0, -60);
lv_label_set_align(ui.connect, LV_LABEL_ALIGN_CENTER);
lv_obj_set_style_local_text_font(ui.connect, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font24);
if(!WiFi.isConnected()) {
lv_label_set_text_fmt(ui.connect, "\"%s\" 连接中...", WIFI_SSID);
lv_obj_align(ui.connect, NULL, LV_ALIGN_CENTER, 0, 0);
WiFi.begin(WIFI_SSID, WIFI_PWD);
if (WiFi.isConnected()) {
lv_label_set_text_fmt(ui.connect, "\"%s\" 连接成功. \nIP: %s",
WIFI_SSID, WiFi.localIP().toString().c_str());
}
else {
lv_label_set_text_fmt(ui.connect, "\"%s\" 连接失败!", WIFI_SSID);
}
lv_obj_align(ui.connect, NULL, LV_ALIGN_CENTER, 0, 0);
}
}
5. 界面绘制
void WeatherUi(void)
{
ui.screen = lv_scr_act();
lv_obj_clean(ui.screen);
ui.city = lv_label_create(ui.screen, NULL);
lv_label_set_text(ui.city, "深圳·晴");
lv_obj_set_style_local_text_font(ui.city, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font24);
lv_obj_align(ui.city, NULL, LV_ALIGN_IN_TOP_MID, 0, 15);
ui.temp = lv_label_create(ui.screen, NULL);
lv_label_set_align(ui.temp, LV_LABEL_ALIGN_CENTER);
lv_label_set_long_mode(ui.temp, LV_LABEL_LONG_BREAK);
lv_obj_set_width(ui.temp, 192);
lv_label_set_text(ui.temp, "99°");
lv_obj_set_style_local_text_font(ui.temp, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font48);
lv_obj_align(ui.temp, NULL, LV_ALIGN_IN_TOP_MID, 10, 50);
ui.hum = lv_label_create(ui.screen, NULL);
lv_label_set_text(ui.hum, "湿度: 99");
lv_obj_set_style_local_text_font(ui.hum, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font24);
lv_obj_align(ui.hum, NULL, LV_ALIGN_CENTER, 0, -44);
ui.aqi = lv_label_create(ui.screen, NULL);
lv_label_set_text(ui.aqi, "空气质量: 99");
lv_obj_set_style_local_text_font(ui.aqi, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font24);
lv_obj_align(ui.aqi, NULL, LV_ALIGN_CENTER, 0, -8);
// 画框
static lv_point_t line_points[4][2] = {
{ {0, 70}, {LV_HOR_RES_MAX, 70} },
{ {0, 100}, {LV_HOR_RES_MAX, 100} },
{ {0, 130}, {LV_HOR_RES_MAX, 130} },
{ {0, 160}, {LV_HOR_RES_MAX, 160} }
};
static lv_style_t style_line;
lv_style_init(&style_line);
lv_style_set_line_width(&style_line, LV_STATE_DEFAULT, 1);
lv_style_set_line_color(&style_line, LV_STATE_DEFAULT, LV_COLOR_BLACK);
//lv_style_set_line_rounded(&style_line, LV_STATE_DEFAULT, true);
lv_obj_t* line[4];
line[0] = lv_line_create(ui.screen, NULL);
lv_line_set_points(line[0], line_points[0], 2); /*Set the points*/
lv_obj_add_style(line[0], LV_LINE_PART_MAIN, &style_line); /*Set the points*/
lv_obj_align(line[0], NULL, LV_ALIGN_CENTER, 0, 0);
for (uint8_t i = 1; i < sizeof(line) / sizeof(line[0]); i++) {
line[i] = lv_line_create(ui.screen, line[0]);
lv_line_set_points(line[i], line_points[i], 2);
}
lv_obj_t* future_date_title_l[FUTURE_DAY_COUNT];
future_date_title_l[0] = lv_label_create(ui.screen, NULL);
lv_label_set_align(future_date_title_l[0], LV_LABEL_ALIGN_CENTER);
lv_obj_set_size(future_date_title_l[0], 64, 16);
lv_obj_set_style_local_text_font(future_date_title_l[0], LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font16);
future_date_title_l[1] = lv_label_create(ui.screen, future_date_title_l[0]);
future_date_title_l[2] = lv_label_create(ui.screen, future_date_title_l[0]);
// 框中内容
lv_label_set_text(future_date_title_l[0], "未来三天");
lv_obj_align(future_date_title_l[0], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 6, -100);
ui.furDate[0] = lv_label_create(ui.screen, future_date_title_l[0]);
ui.furDate[1] = lv_label_create(ui.screen, future_date_title_l[0]);
ui.furDate[2] = lv_label_create(ui.screen, future_date_title_l[0]);
lv_label_set_text(ui.furDate[0], "11月11日");
lv_obj_align(ui.furDate[0], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 4, -70);
lv_label_set_text(ui.furDate[1], "22月22日");
lv_obj_align(ui.furDate[1], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 4, -40);
lv_label_set_text(ui.furDate[2], "33月33日");
lv_obj_align(ui.furDate[2], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 4, -10);
lv_label_set_text(future_date_title_l[1], "温度范围");
lv_obj_align(future_date_title_l[1], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 90, -100);
ui.furTemp[0] = lv_label_create(ui.screen, future_date_title_l[0]);
lv_label_set_long_mode(ui.furTemp[0], LV_LABEL_LONG_SROLL_CIRC);
lv_obj_set_width(ui.furTemp[0], 64);
ui.furTemp[1] = lv_label_create(ui.screen, ui.furTemp[0]);
ui.furTemp[2] = lv_label_create(ui.screen, ui.furTemp[0]);
lv_label_set_text(ui.furTemp[0], "22~11°");
lv_obj_align(ui.furTemp[0], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 84, -70);
lv_label_set_text(ui.furTemp[1], " 1~10°");
lv_obj_align(ui.furTemp[1], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 84, -40);
lv_label_set_text(ui.furTemp[2], "33~33°");
lv_obj_align(ui.furTemp[2], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 84, -10);
lv_label_set_text(future_date_title_l[2], "天气");
lv_obj_align(future_date_title_l[2], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 180, -100);
ui.furWeather[0] = lv_label_create(ui.screen, future_date_title_l[0]);
lv_label_set_long_mode(ui.furWeather[0], LV_LABEL_LONG_SROLL_CIRC);
lv_obj_set_width(ui.furWeather[0], 64);
ui.furWeather[1] = lv_label_create(ui.screen, ui.furWeather[0]);
ui.furWeather[2] = lv_label_create(ui.screen, ui.furWeather[0]);
lv_label_set_text(ui.furWeather[0], "特大暴雨");
lv_obj_align(ui.furWeather[0], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 160, -70);
lv_label_set_text(ui.furWeather[1], "雷阵雨");
lv_obj_align(ui.furWeather[1], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 160, -40);
lv_label_set_text(ui.furWeather[2], "晴间多云");
lv_obj_align(ui.furWeather[2], NULL, LV_ALIGN_IN_BOTTOM_LEFT, 160, -10);
}
6. 天气信息刷新
void SetWeatherShow(TodayWeatherType today, FutureWeatherType future[FUTURE_DAY_COUNT])
{
lv_label_set_text_fmt(ui.city, "%s·%s", today.city.c_str(), today.weather.c_str());
lv_label_set_text_fmt(ui.temp, "%d°", today.temperature);
lv_label_set_text_fmt(ui.hum, "湿度: %d", today.humidity);
lv_label_set_text_fmt(ui.aqi, "空气质量: %d", today.airQuality);
for (uint8_t i = 0; i < FUTURE_DAY_COUNT; i++) {
lv_label_set_text_fmt(ui.furDate[i], "%2d月%02d日", future[i].date.mon, future[i].date.day);
lv_label_set_text_fmt(ui.furTemp[i], "%d~%d°", future[i].tempMin, future[i].tempMax);
lv_label_set_text_fmt(ui.furWeather[i], "%s", future[i].weatherDay.c_str());
}
}
实物展示:
WiFi连接界面:
城市天气显示:
总结
每次参加funpack活动都能带来不小的收获,这次也不例外。描述页的编辑确实有些难用,希望能有所改进。
附件下载
firmware.bin
烧录固件
WioTerminal.rar
源码
团队介绍
一位普通的嵌入式软件工程师
团队成员
willcome0
评论
0 / 100
查看更多
猜你喜欢
Funpack第12期 Wio Terminal 网络天气预报仪本项目使用Wio Terminal制作了一个网络天气预报仪,可以连接WiFi后通过HTTP GET获取OpenWeatherMap提供的天气API数据并显示在LCD上
常勃兄
1027
Funpack第12期-Wio Terminal-自动联网的天气预报仪_LVGLFunpack第12期-Wio Terminal-自动联网的天气预报仪_LVGL
奈奎斯特不稳定
1577
Funpack第12期 - Wio Terminal - Arduino天气预报仪这次选择了第二个项目, 开发制作一个自动联网的天气预报仪,在设计界面显示温湿度、天气情况、空气质量以及未来三天内的天气变化。
Seanny
833