#include "include.h" #include "func.h" #include "app_variable.h" #if TRACE_EN #define TRACE(...) printf(__VA_ARGS__) #else #define TRACE(...) #endif #define OFFSET(x) ((x) < 127 ? (x) : (x - 256)) /* 连续多天天数 */ #define WEATHER_DISPLAY_DAYS 3 /* 列表高度 */ #define WEATHER_LIST_ITEM_HEIGHT 134 typedef struct weather_info_t_ { s16 temperature; // 当前温度 s16 maxTemp; // 最高气温 s16 minTemp; // 最低气温 WeatherType_t type; // 天气类型 } weather_info_t; typedef struct f_weather_t_ { /* 天气获取状态 */ bool get_sta; /* 屏幕滑动模块 */ page_tp_move_t *ptm; } f_weather_t; // 组件ID enum { /* 图片按钮 */ COMPO_ID_BTN_IMG_BG = 0x01, COMPO_ID_BTN_IMG_BG_MAX = COMPO_ID_BTN_IMG_BG + WEATHER_DISPLAY_DAYS, /* 天气ICON */ COMPO_ID_BTN_ICON = 0x10, COMPO_ID_BTN_ICON_MAX = COMPO_ID_BTN_ICON + WEATHER_DISPLAY_DAYS, /* 当前温度 */ COMPO_ID_BTN_CURR_TEMP = 0x20, COMPO_ID_BTN_CURR_TEMP_MAX = COMPO_ID_BTN_CURR_TEMP + WEATHER_DISPLAY_DAYS, /* 最高、最低温度 */ COMPO_ID_BTN_MAX_MIN_TEMP = 0x30, COMPO_ID_BTN_MAX_MIN_TEMP_MAX = COMPO_ID_BTN_MAX_MIN_TEMP + WEATHER_DISPLAY_DAYS, /* 获取失败重试按钮 */ COMPO_ID_BTN_FAIL_RETRY = 0x40, }; /* 天气列表选择天数 */ int weather_choose_days_idx = 0; static uint32_t func_weather_bg_image_res_get(WeatherType_t weather_type) { switch (weather_type) { /* 晴天 */ case Weather_sunny: return UI_BUF_WEATHER_LIST_BG_SUNNY_BIN; break; /* 多云 */ case Weather_cloudy: case Weather_overcast: return UI_BUF_WEATHER_LIST_BG_CLOUDY_BIN; break; /* 雨天 */ case Weather_Rain1: case Weather_Rain2: case Weather_Rain3: case Weather_Rain4: return UI_BUF_WEATHER_LIST_BG_RAIN_BIN; break; /* 雷阵雨 */ case Weather_Rain5: return UI_BUF_WEATHER_LIST_BG_THUNDERSTORM_BIN; break; /* 下雪 */ case Weather_snow: return UI_BUF_WEATHER_LIST_BG_SNOW_BIN; break; /* 雾霾 */ case Weather_smog: return UI_BUF_WEATHER_LIST_BG_FOG_BIN; break; /* 沙尘暴 */ case Weather_sanddust: return UI_BUF_WEATHER_LIST_BG_DUSTSTORM_BIN; break; /* 龙卷风 */ case Weather_tornado: return UI_BUF_WEATHER_LIST_BG_TORNADO_BIN; break; default: return UI_BUF_WEATHER_LIST_BG_SUNNY_BIN; break; } } static void func_weather_data_init(weather_info_t *weather_data) { if (weather_data == NULL) return; /* 第一天 */ weather_data[0].type = SysVariable.weather.type; weather_data[0].temperature = weather_temperature_transform(OFFSET(SysVariable.weather.temperature)) / 100; weather_data[0].maxTemp = weather_temperature_transform(OFFSET(SysVariable.weather.maxTemp)) / 100; weather_data[0].minTemp = weather_temperature_transform(OFFSET(SysVariable.weather.minTemp)) / 100; /* 第二天 */ weather_data[1].type = SysVariable.weather.n1day_type; weather_data[1].temperature = weather_temperature_transform(OFFSET(SysVariable.weather.n1day_temperature)) / 100; weather_data[1].maxTemp = weather_temperature_transform(OFFSET(SysVariable.weather.n1day_maxTemp)) / 100; weather_data[1].minTemp = weather_temperature_transform(OFFSET(SysVariable.weather.n1day_minTemp)) / 100; /* 第三天 */ weather_data[2].type = SysVariable.weather.n2day_type; weather_data[2].temperature = weather_temperature_transform(OFFSET(SysVariable.weather.n2day_temperature)) / 100; weather_data[2].maxTemp = weather_temperature_transform(OFFSET(SysVariable.weather.n2day_maxTemp)) / 100; weather_data[2].minTemp = weather_temperature_transform(OFFSET(SysVariable.weather.n2day_minTemp)) / 100; } /* 天气列表 */ static void func_weather_show_list(compo_form_t *frm) { char text_buf[TEXTBOX_TEXT_BUF_LEN] = {0}; UNIT_TYPE unit_type = SysVariable.deviceInfo.distanceUnit; /* 设置标题栏 */ compo_form_set_mode(frm, COMPO_FORM_MODE_SHOW_TITLE | COMPO_FORM_MODE_SHOW_TIME); compo_form_set_title(frm, i18n[STR_WEATHER]); /* 获取天气数据 */ weather_info_t weather_data[WEATHER_DISPLAY_DAYS] = {0}; func_weather_data_init(weather_data); /* 显示今天、明天、后天天气列表 */ for (int i = 0; i < WEATHER_DISPLAY_DAYS; i++) { /* 背景 */ compo_button_t *btn_sit = compo_button_create_by_image(frm, func_weather_bg_image_res_get(weather_data[i].type)); compo_setid(btn_sit, COMPO_ID_BTN_IMG_BG + i); compo_button_set_pos(btn_sit, GUI_SCREEN_CENTER_X, (GUI_SCREEN_CENTER_Y - 41) + (i * WEATHER_LIST_ITEM_HEIGHT)); /* 天数 */ compo_textbox_t *days_text = compo_textbox_create(frm, 50); compo_textbox_set_align_center(days_text, false); compo_textbox_set_location(days_text, 19, 59 + (i * WEATHER_LIST_ITEM_HEIGHT), 140, 30); compo_textbox_set(days_text, i18n[STR_WEATHER_CURRENT + i]); /* 温度 */ compo_textbox_t *temp_text = compo_textbox_create(frm, 50); compo_setid(temp_text, COMPO_ID_BTN_CURR_TEMP + i); compo_textbox_set_font(temp_text, UI_BUF_0FONT_FONT_NUM_38_BIN); compo_textbox_set_align_center(temp_text, false); compo_textbox_set_pos(temp_text, 19, 86 + (i * WEATHER_LIST_ITEM_HEIGHT)); sprintf(text_buf, unit_type == UNIT_TYPE_INCH ? "%d℉" : "%d℃", weather_data[i].temperature); compo_textbox_set(temp_text, text_buf); /* 温度范围 */ compo_textbox_t *temp_range_text = compo_textbox_create(frm, 50); compo_setid(temp_range_text, COMPO_ID_BTN_MAX_MIN_TEMP + i); compo_textbox_set_align_center(temp_range_text, false); compo_textbox_set_pos(temp_range_text, 19, 137 + (i * WEATHER_LIST_ITEM_HEIGHT)); sprintf(text_buf, unit_type == UNIT_TYPE_INCH ? "%d/%d℉" : "%d/%d℃", weather_data[i].minTemp, weather_data[i].maxTemp); compo_textbox_set(temp_range_text, text_buf); /* 天气类型ICON */ compo_picturebox_t *type_icon = compo_picturebox_create(frm, UI_BUF_WEATHER_ICON_TYPE_ICON_BIN); compo_setid(type_icon, COMPO_ID_BTN_ICON + i); compo_picturebox_set_pos(type_icon, GUI_SCREEN_CENTER_X + 77, (GUI_SCREEN_CENTER_Y - 72) + (i * WEATHER_LIST_ITEM_HEIGHT)); compo_picturebox_cut(type_icon, weather_data[i].type, WEATHER_CNT); } } /* APP未连接 */ static void func_weather_show_disconnect(compo_form_t *frm) { compo_picturebox_t *pic = compo_picturebox_create(frm, UI_BUF_WORLD_CLOCK_ERROR_BIN); compo_picturebox_set_pos(pic, 116, 120); compo_textbox_t *acquiring_txt = compo_textbox_create(frm, 50); compo_textbox_set_location(acquiring_txt, GUI_SCREEN_CENTER_X, GUI_SCREEN_CENTER_Y + 53, 200, 30); compo_textbox_set(acquiring_txt, i18n[STR_CONNECT_APP]); } /* 未成功获取到天气 */ static void func_weather_show_fail(compo_form_t *frm) { compo_picturebox_t *pic = compo_picturebox_create(frm, UI_BUF_COMMON_ICON_FAIL_BIN); compo_picturebox_set_pos(pic, GUI_SCREEN_CENTER_X, GUI_SCREEN_CENTER_Y - 79); compo_textbox_t *acquiring_txt = compo_textbox_create(frm, 120); compo_textbox_set_location(acquiring_txt, GUI_SCREEN_CENTER_X, GUI_SCREEN_CENTER_Y + 26, 200, 70); compo_textbox_set_multiline(acquiring_txt, true); compo_textbox_set(acquiring_txt, i18n[STR_GET_DATA_FAIL]); /* 重试按钮 */ compo_shape_t *btn_shape = compo_radius_shape_create(frm, COMPO_SHAPE_TYPE_ROUNDED_RECTANGLE, 20); compo_shape_set_color(btn_shape, make_color(19, 126, 250)); compo_shape_set_location(btn_shape, GUI_SCREEN_CENTER_X, GUI_SCREEN_CENTER_Y + 103, 216, 50); compo_button_t *btn = compo_button_create(frm); compo_setid(btn, COMPO_ID_BTN_FAIL_RETRY); compo_button_set_location(btn, GUI_SCREEN_CENTER_X, GUI_SCREEN_CENTER_Y + 103, 216, 50); compo_textbox_t *txt_retry = compo_textbox_create(frm, 20); compo_textbox_set_pos(txt_retry, GUI_SCREEN_CENTER_X, GUI_SCREEN_CENTER_Y + 103); compo_textbox_set(txt_retry, i18n[STR_RETRY]); } /* 创建天气窗体 */ compo_form_t *func_weather_form_create(void) { /* 新建窗体 */ compo_form_t *frm = compo_form_create(true); if (SysVariable.weather.getFlag == true) { /* 获取过天气数据,显示天气列表 */ func_weather_show_list(frm); } else { if (!ble_is_connected()) { /* 显示未连接APP提示 */ func_weather_show_disconnect(frm); } else { /* 显示获取失败提示 */ func_weather_show_fail(frm); } } return frm; } /* 天气界面刷新 */ static void func_weather_refresh(void) { char text_buf[TEXTBOX_TEXT_BUF_LEN] = {0}; UNIT_TYPE unit_type = SysVariable.deviceInfo.distanceUnit; /* 获取天气数据 */ weather_info_t weather_data[WEATHER_DISPLAY_DAYS] = {0}; func_weather_data_init(weather_data); for (int i = 0; i < WEATHER_DISPLAY_DAYS; i++) { /* 背景 */ compo_button_t *btn_img = compo_getobj_byid(COMPO_ID_BTN_IMG_BG + i); if (btn_img != NULL) { widget_icon_set(btn_img->widget, func_weather_bg_image_res_get(weather_data[i].type)); } /* 温度 */ compo_textbox_t *temp_text = compo_getobj_byid(COMPO_ID_BTN_CURR_TEMP + i); if (temp_text != NULL) { memset(text_buf, 0, sizeof(text_buf)); sprintf(text_buf, unit_type == UNIT_TYPE_INCH ? "%d℉" : "%d℃", weather_data[i].temperature); compo_textbox_set(temp_text, text_buf); } /* 温度范围 */ compo_textbox_t *temp_range_text = compo_getobj_byid(COMPO_ID_BTN_MAX_MIN_TEMP + i); if (temp_range_text != NULL) { memset(text_buf, 0, sizeof(text_buf)); sprintf(text_buf, unit_type == UNIT_TYPE_INCH ? "%d/%d℉" : "%d/%d℃", weather_data[i].minTemp, weather_data[i].maxTemp); compo_textbox_set(temp_range_text, text_buf); } /* 天气类型ICON */ compo_picturebox_t *type_icon = compo_getobj_byid(COMPO_ID_BTN_ICON + i); if (type_icon != NULL) { compo_picturebox_cut(type_icon, weather_data[i].type, WEATHER_CNT); } } } static void func_weather_interface(void) { f_weather_t *f_weather = (f_weather_t *)func_cb.f_cb; if ((SysVariable.weather.getFlag == true) && (f_weather->get_sta == false)) { /* 销毁窗体 - 刷新 */ if (func_cb.frm_main != NULL) { compo_form_destroy(func_cb.frm_main); } func_cb.frm_main = func_weather_form_create(); } f_weather->get_sta = SysVariable.weather.getFlag; } // 天气功能事件处理 static void func_weather_process(void) { f_weather_t *f_weather = (f_weather_t *)func_cb.f_cb; compo_page_move_process(f_weather->ptm); /* 界面刷新检查 */ func_weather_interface(); /* 数据刷新 */ static u32 refresh_tick = 0; if (SysVariable.weather.getFlag == true && tick_check_expire(refresh_tick, 1000)) { func_weather_refresh(); refresh_tick = tick_get(); } func_process(); } // 天气按钮点击处理 static void func_weather_click_handler(void) { static u32 retry_tick = 0; u8 id = compo_get_button_id(); switch (id) { case COMPO_ID_BTN_IMG_BG ... COMPO_ID_BTN_IMG_BG_MAX: weather_choose_days_idx = id - COMPO_ID_BTN_IMG_BG; /* 进入天气详情界面 */ compo_button_t *btn_img = compo_getobj_byid(id); compo_form_t *frm = func_create_form(FUNC_WEATHER_DETAIL); func_switching(FUNC_SWITCH_ZOOM_ENTER | FUNC_SWITCH_AUTO, (widget_icon_t *)btn_img->widget); compo_form_destroy(frm); func_switch_to_assign_screen(FUNC_WEATHER_DETAIL, false); break; case COMPO_ID_BTN_FAIL_RETRY: if (ble_is_connected() && tick_check_expire(retry_tick, 1000)) { /* 数据获取异常 - 手动请求重新下发 */ printf("[%s %d][Send_Protocol_Get_Weather]\n", __func__, __LINE__); retry_tick = tick_get(); Send_Protocol_Get_Weather(); } else { /* 销毁窗体 - 切换到未连接页面 */ if (func_cb.frm_main != NULL) { compo_form_destroy(func_cb.frm_main); } func_cb.frm_main = func_weather_form_create(); } break; default: break; } } // 天气功能消息处理 static void func_weather_message(size_msg_t msg) { f_weather_t *f_weather = (f_weather_t *)func_cb.f_cb; switch (msg) { case MSG_CTP_TOUCH: if (SysVariable.weather.getFlag == true) { compo_page_move_touch_handler(f_weather->ptm); } break; case MSG_CTP_CLICK: func_weather_click_handler(); break; case MSG_CTP_SHORT_UP: break; case MSG_CTP_SHORT_DOWN: break; case MSG_CTP_LONG: break; case MSG_QDEC_BACKWARD: if (func_cb.flag_sort) { func_message(msg); } else { compo_page_move_set_by_pages(f_weather->ptm, -WEATHER_LIST_ITEM_HEIGHT); } break; case MSG_QDEC_FORWARD: if (func_cb.flag_sort) { func_message(msg); } else { compo_page_move_set_by_pages(f_weather->ptm, WEATHER_LIST_ITEM_HEIGHT); } break; default: func_message(msg); break; } } // 进入天气功能 static void func_weather_enter(void) { func_cb.f_cb = func_zalloc(sizeof(f_weather_t)); f_weather_t *f_weather = (f_weather_t *)func_cb.f_cb; func_cb.frm_main = func_weather_form_create(); f_weather->get_sta = SysVariable.weather.getFlag; /* 建立界面滑动模块 */ f_weather->ptm = (page_tp_move_t *)func_zalloc(sizeof(page_tp_move_t)); page_move_info_t info = { .title_used = true, .page_size = WEATHER_LIST_ITEM_HEIGHT * WEATHER_DISPLAY_DAYS + 44, .page_count = 1, .quick_jump_perc = 100, .up_over_perc = 10, .down_over_perc = 10, }; compo_page_move_init(f_weather->ptm, func_cb.frm_main->page_body, &info); } // 退出天气功能 static void func_weather_exit(void) { f_weather_t *f_weather = (f_weather_t *)func_cb.f_cb; if (f_weather->ptm) { func_free(f_weather->ptm); } func_cb.last = FUNC_WEATHER; } // 天气功能 void func_weather(void) { printf("%s\n", __func__); func_weather_enter(); while (func_cb.sta == FUNC_WEATHER) { func_weather_process(); func_weather_message(msg_dequeue()); } func_weather_exit(); }