1 #include "../../lv_examples.h"
2 #if LV_USE_OBSERVER && LV_USE_ARC && LV_USE_LABEL && LV_USE_BUTTON && LV_USE_SPINNER && LV_BUILD_EXAMPLES
3 
4 typedef enum {
5     FW_UPDATE_STATE_IDLE,
6     FW_UPDATE_STATE_CONNECTING,
7     FW_UPDATE_STATE_CONNECTED,
8     FW_UPDATE_STATE_DOWNLOADING,
9     FW_UPDATE_STATE_CANCEL,
10     FW_UPDATE_STATE_READY,
11 } fw_update_state_t;
12 
13 static void fw_upload_manager_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
14 static void fw_update_btn_clicked_event_cb(lv_event_t * e);
15 static void fw_update_close_event_cb(lv_event_t * e);
16 static void fw_update_win_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
17 
18 static lv_subject_t fw_download_percent_subject;
19 static lv_subject_t fw_update_status_subject;
20 
21 /**
22  * Show how to handle a complete firmware update process with observers.
23  * Normally it's hard to implement a firmware update process because in some cases
24  *   - the App needs to was for the UI (wait for a button press)
25  *   - the UI needs to wait for the App (connecting or downloading)
26  * With observers these complex mechanisms can be implemented a simple and clean way.
27  */
lv_example_observer_5(void)28 void lv_example_observer_5(void)
29 {
30     lv_subject_init_int(&fw_download_percent_subject, 0);
31     lv_subject_init_int(&fw_update_status_subject, FW_UPDATE_STATE_IDLE);
32 
33     lv_subject_add_observer(&fw_update_status_subject, fw_upload_manager_observer_cb, NULL);
34 
35     /*Create start FW update button*/
36     lv_obj_t * btn = lv_button_create(lv_screen_active());
37     lv_obj_add_event_cb(btn, fw_update_btn_clicked_event_cb, LV_EVENT_CLICKED, NULL);
38     lv_obj_center(btn);
39     lv_obj_t * label = lv_label_create(btn);
40     lv_label_set_text(label, "Firmware update");
41 }
42 
fw_update_btn_clicked_event_cb(lv_event_t * e)43 static void fw_update_btn_clicked_event_cb(lv_event_t * e)
44 {
45     LV_UNUSED(e);
46     lv_obj_t * win = lv_win_create(lv_screen_active());
47     lv_obj_set_size(win, lv_pct(90), lv_pct(90));
48     lv_obj_set_height(lv_win_get_header(win), 40);
49     lv_obj_set_style_radius(win, 8, 0);
50     lv_obj_set_style_shadow_width(win, 24, 0);
51     lv_obj_set_style_shadow_offset_x(win, 2, 0);
52     lv_obj_set_style_shadow_offset_y(win, 3, 0);
53     lv_obj_set_style_shadow_color(win, lv_color_hex3(0x888), 0);
54     lv_win_add_title(win, "Firmware update");
55     lv_obj_t * btn = lv_win_add_button(win, LV_SYMBOL_CLOSE, 40);
56     lv_obj_add_event_cb(btn, fw_update_close_event_cb, LV_EVENT_CLICKED, NULL);
57     lv_obj_center(win);
58 
59     lv_subject_set_int(&fw_update_status_subject, FW_UPDATE_STATE_IDLE);
60     lv_subject_add_observer_obj(&fw_update_status_subject, fw_update_win_observer_cb, win, NULL);
61 }
62 
fw_update_close_event_cb(lv_event_t * e)63 static void fw_update_close_event_cb(lv_event_t * e)
64 {
65     LV_UNUSED(e);
66     lv_subject_set_int(&fw_update_status_subject, FW_UPDATE_STATE_CANCEL);
67 }
68 
restart_btn_click_event_cb(lv_event_t * e)69 static void restart_btn_click_event_cb(lv_event_t * e)
70 {
71     lv_obj_t * win = lv_event_get_user_data(e);
72     lv_obj_delete(win);
73     lv_subject_set_int(&fw_update_status_subject, FW_UPDATE_STATE_IDLE);
74 }
75 
fw_update_win_observer_cb(lv_observer_t * observer,lv_subject_t * subject)76 static void fw_update_win_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
77 {
78     lv_obj_t * win = lv_observer_get_target(observer);
79     lv_obj_t * cont = lv_win_get_content(win);
80     fw_update_state_t status = lv_subject_get_int(&fw_update_status_subject);
81     if(status == FW_UPDATE_STATE_IDLE) {
82         lv_obj_clean(cont);
83         lv_obj_t * spinner = lv_spinner_create(cont);
84         lv_obj_center(spinner);
85         lv_obj_set_size(spinner, 130, 130);
86 
87         lv_obj_t * label = lv_label_create(cont);
88         lv_label_set_text(label, "Connecting");
89         lv_obj_center(label);
90 
91         lv_subject_set_int(subject, FW_UPDATE_STATE_CONNECTING);
92     }
93     else if(status == FW_UPDATE_STATE_DOWNLOADING) {
94         lv_obj_clean(cont);
95         lv_obj_t * arc = lv_arc_create(cont);
96         lv_arc_bind_value(arc, &fw_download_percent_subject);
97         lv_obj_center(arc);
98         lv_obj_set_size(arc, 130, 130);
99         lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
100 
101         lv_obj_t * label = lv_label_create(cont);
102         lv_label_bind_text(label, &fw_download_percent_subject, "%d %%");
103         lv_obj_center(label);
104     }
105     else if(status == FW_UPDATE_STATE_READY) {
106         lv_obj_clean(cont);
107         lv_obj_t * label = lv_label_create(cont);
108         lv_label_set_text(label, "Firmware update is ready");
109         lv_obj_align(label, LV_ALIGN_CENTER, 0, -20);
110 
111         lv_obj_t * btn = lv_button_create(cont);
112         lv_obj_align(btn, LV_ALIGN_CENTER, 0, 20);
113         lv_obj_add_event_cb(btn, restart_btn_click_event_cb, LV_EVENT_CLICKED, win);
114 
115         label = lv_label_create(btn);
116         lv_label_set_text(label, "Restart");
117     }
118     else if(status == FW_UPDATE_STATE_CANCEL) {
119         lv_obj_delete(win);
120     }
121 }
122 
connect_timer_cb(lv_timer_t * t)123 static void connect_timer_cb(lv_timer_t * t)
124 {
125     if(lv_subject_get_int(&fw_update_status_subject) != FW_UPDATE_STATE_CANCEL) {
126         lv_subject_set_int(&fw_update_status_subject, FW_UPDATE_STATE_CONNECTED);
127     }
128     lv_timer_delete(t);
129 }
130 
download_timer_cb(lv_timer_t * t)131 static void download_timer_cb(lv_timer_t * t)
132 {
133     if(lv_subject_get_int(&fw_update_status_subject) == FW_UPDATE_STATE_CANCEL) {
134         lv_timer_delete(t);
135         return;
136     }
137 
138     int32_t v = lv_subject_get_int(&fw_download_percent_subject);
139     if(v < 100) {
140         lv_subject_set_int(&fw_download_percent_subject, v + 1);
141     }
142     else {
143         lv_subject_set_int(&fw_update_status_subject, FW_UPDATE_STATE_READY);
144         lv_timer_delete(t);
145     }
146 }
147 
148 /**
149  * Emulate connection and FW downloading by timers
150  */
fw_upload_manager_observer_cb(lv_observer_t * observer,lv_subject_t * subject)151 static void fw_upload_manager_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
152 {
153     LV_UNUSED(subject);
154     LV_UNUSED(observer);
155 
156     fw_update_state_t state = lv_subject_get_int(&fw_update_status_subject);
157     if(state == FW_UPDATE_STATE_CONNECTING) {
158         lv_timer_create(connect_timer_cb, 2000, NULL);
159     }
160     else if(state == FW_UPDATE_STATE_CONNECTED) {
161         lv_subject_set_int(&fw_download_percent_subject, 0);
162         lv_subject_set_int(&fw_update_status_subject, FW_UPDATE_STATE_DOWNLOADING);
163         lv_timer_create(download_timer_cb, 50, NULL);
164     }
165 }
166 
167 #endif
168