1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
|
#include "displayapp/screens/WatchFaceDigital.h"
#include <date/date.h>
#include <lvgl/lvgl.h>
#include <cstdio>
#include "displayapp/screens/BatteryIcon.h"
#include "displayapp/screens/BleIcon.h"
#include "displayapp/screens/NotificationIcon.h"
#include "displayapp/screens/Symbols.h"
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "components/heartrate/HeartRateController.h"
#include "components/motion/MotionController.h"
#include "components/settings/Settings.h"
using namespace Pinetime::Applications::Screens;
WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
Controllers::DateTime& dateTimeController,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController,
System::SystemTask& systemTask)
: Screen(app),
systemTask {systemTask},
currentDateTime {{}},
dateTimeController {dateTimeController},
batteryController {batteryController},
bleController {bleController},
notificatioManager {notificatioManager},
settingsController {settingsController},
heartRateController {heartRateController},
motionController {motionController} {
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(batteryIcon, Symbols::batteryFull);
lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
batteryPlug = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
lv_label_set_text_static(batteryPlug, Symbols::plug);
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, 0, 0);
batteryPercentLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color( batteryPercentLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999));
lv_obj_set_style_local_text_font( batteryPercentLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &neofont1);
lv_label_set_text_static( batteryPercentLabel, battery_percent_label_text);
lv_obj_align( batteryPercentLabel, batteryIcon, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, 0);
lv_label_set_align( batteryPercentLabel, LV_LABEL_ALIGN_RIGHT);
batteryVoltageLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font( batteryVoltageLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &neofont1);
lv_obj_set_style_local_text_color( batteryVoltageLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999));
lv_label_set_text_static( batteryVoltageLabel, battery_voltage_label_text);
lv_obj_align( batteryVoltageLabel, batteryPercentLabel, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, 0);
bleIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0082FC));
lv_label_set_text_static(bleIcon, Symbols::bluetooth);
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);
notificationIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false));
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
label_date = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_date, nullptr, LV_ALIGN_CENTER, 0, 60);
lv_obj_set_auto_realign(label_date, true);
lv_obj_set_style_local_text_color(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999));
label_temp = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color( label_temp, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x555555));
lv_label_set_text_fmt(label_temp, "??°C");
lv_obj_align(label_temp, nullptr, LV_ALIGN_CENTER, 60, -60);
label_time = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &neofont3);
lv_label_set_text_fmt(label_time, hhmm_label_text);
lv_obj_align(label_time, nullptr, LV_ALIGN_CENTER, 0, 0);
lv_label_set_long_mode(label_time, LV_LABEL_LONG_CROP);
lv_label_set_align(label_time, LV_LABEL_ALIGN_RIGHT);
label_time_pm = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(label_time_pm, "P ");
lv_obj_align(label_time_pm, label_time, LV_ALIGN_OUT_LEFT_TOP, 0, 0);
label_time_seconds = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(label_time_seconds, seconds_label_text);
lv_obj_align(label_time_seconds, label_time, LV_ALIGN_OUT_RIGHT_BOTTOM, 0, 0);
label_time_deciseconds = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(label_time_deciseconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &neofont1);
lv_label_set_text_static(label_time_deciseconds, seconds_label_text);
lv_obj_align(label_time_deciseconds, label_time_seconds, LV_ALIGN_OUT_RIGHT_BOTTOM, 0, 0);
backgroundLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_click(backgroundLabel, true);
lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP);
lv_obj_set_size(backgroundLabel, 240, 240);
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text_static(backgroundLabel, "");
heartbeatIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat);
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
lv_obj_align(heartbeatIcon, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
lv_label_set_text_static(heartbeatValue, "");
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
stepValue = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
lv_label_set_text_static(stepValue, "0");
lv_obj_align(stepValue, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
stepIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
lv_label_set_text_static(stepIcon, Symbols::shoe);
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
Refresh();
}
WatchFaceDigital::~WatchFaceDigital() {
lv_task_del(taskRefresh);
lv_obj_clean(lv_scr_act());
}
void WatchFaceDigital::Refresh() {
bool batteryRefreshed = false;
powerPresent = batteryController.IsPowerPresent();
if (powerPresent.IsUpdated()) {
lv_label_set_text_static(batteryPlug, BatteryIcon::GetPlugIcon(powerPresent.Get()));
}
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated()) {
batteryRefreshed = true;
auto batteryPercent = batteryPercentRemaining.Get();
if (batteryPercent == 100) {
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
} else {
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
}
lv_label_set_text_static(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
}
bleState = bleController.IsConnected();
if (bleState.IsUpdated()) {
lv_label_set_text_static(bleIcon, BleIcon::GetIcon(bleState.Get()));
}
lv_obj_realign(batteryIcon);
lv_obj_realign(batteryPlug);
lv_obj_realign(bleIcon);
notificationState = notificatioManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) {
lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get()));
}
systemTask.ObtainMotionSensorTemperature(temperature);
if (temperature.IsUpdated()) {
lv_obj_set_style_local_text_color( label_temp, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999));
lv_label_set_text_fmt(label_temp, "%d°C", temperature.Get());
#if 0
lv_label_set_text_fmt(label_temp, "T%d [%d,%d]",
((int)(systemTask.motionSensor.temperature_last_read_value+23)),
((int)(systemTask.motionSensor.temperature_last_result)),
((int)(systemTask.motionSensor.temperature_read_counter))
);
#endif
}
uint8_t second = dateTimeController.Seconds();
uint8_t decisecond = dateTimeController.Deciseconds();
if (second != displayedSecond) {
displayedSecond = second;
seconds_label_text[1] = '0' + (second / 10);
seconds_label_text[2] = '0' + (second % 10);
lv_label_set_text_static(label_time_seconds, seconds_label_text);
}
if (decisecond != displayedDecisecond) {
displayedDecisecond = decisecond;
deciseconds_label_text[0] = '0' + decisecond;
lv_label_set_text_static(label_time_deciseconds, deciseconds_label_text);
}
currentDateTime = dateTimeController.CurrentDateTime();
if (currentDateTime.IsUpdated()) {
auto newDateTime = currentDateTime.Get();
auto dp = date::floor<date::days>(newDateTime);
auto time = date::make_time(newDateTime - dp);
auto yearMonthDay = date::year_month_day(dp);
auto year = static_cast<int>(yearMonthDay.year());
auto month = static_cast<Pinetime::Controllers::DateTime::Months>(static_cast<unsigned>(yearMonthDay.month()));
auto day = static_cast<unsigned>(yearMonthDay.day());
auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding());
uint8_t hour = time.hours().count();
uint8_t minute = time.minutes().count();
if (displayedHour != hour || displayedMinute != minute) {
refreshBatteryInfo = true;
displayedHour = hour;
displayedMinute = minute;
bool hide_pm = true;
uint8_t h0;
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
if (hour == 0) {
hour = 12;
} else if (hour == 12) {
hide_pm = false;
} else if (hour > 12) {
hour -= 12;
hide_pm = false;
}
h0 = hour < 10 ? ' ' : '1';
} else {
h0 = '0' + (hour / 10);
}
hhmm_label_text[0] = h0;
hhmm_label_text[1] = '0' + (hour%10);
hhmm_label_text[3] = '0' + (minute / 10);
hhmm_label_text[4] = '0' + (minute % 10);
lv_label_set_text_static(label_time, hhmm_label_text);
lv_obj_set_hidden(label_time_pm, hide_pm);
}
if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) {
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
lv_label_set_text_fmt(
label_date, "%s %d %s %d", dateTimeController.DayOfWeekShortToString(), day, dateTimeController.MonthShortToString(), year);
} else {
lv_label_set_text_fmt(
label_date, "%s %s %d %d", dateTimeController.DayOfWeekShortToString(), dateTimeController.MonthShortToString(), day, year);
}
currentYear = year;
currentMonth = month;
currentDayOfWeek = dayOfWeek;
currentDay = day;
}
}
heartbeat = heartRateController.HeartRate();
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
if (heartbeatRunning.Get()) {
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
auto v = heartbeat.Get();
if (v) {
lv_label_set_text_fmt(heartbeatValue, "%d", v);
} else {
lv_label_set_text_static(heartbeatValue, "");
}
} else {
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B));
lv_label_set_text_static(heartbeatValue, "");
}
lv_obj_realign(heartbeatIcon);
lv_obj_realign(heartbeatValue);
}
stepCount = motionController.NbSteps();
motionSensorOk = motionController.IsSensorOk();
if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get());
lv_obj_realign(stepValue);
lv_obj_realign(stepIcon);
}
if (batteryRefreshed || refreshBatteryInfo) {
if (refreshBatteryInfo) {
batteryController.MeasureVoltage();
refreshBatteryInfo = false;
}
{
auto x = batteryController.Voltage();
battery_voltage_label_text[3] = '0' + (x%10); x /= 10;
battery_voltage_label_text[2] = '0' + (x%10); x /= 10;
battery_voltage_label_text[1] = '0' + (x%10); x /= 10;
battery_voltage_label_text[0] = '0' + (x%10);
}
lv_label_set_text_static(batteryVoltageLabel, battery_voltage_label_text);
{
uint8_t x = batteryController.PercentRemaining();
battery_percent_label_text[2] = '0' + (x%10); x /= 10;
battery_percent_label_text[1] = '0' + (x%10); x /= 10;
battery_percent_label_text[0] = x ? '0' + (x%10): ' ';
}
lv_label_set_text_static(batteryPercentLabel, battery_percent_label_text);
}
}
|