471 lines
15 KiB
C
471 lines
15 KiB
C
#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();
|
|
}
|