Skip to content

Commit fa97dad

Browse files
committed
notifications: Add phone alarm support with dismiss/snooze
Map HighPrioritizedAlert category to a new PhoneAlarm notification type that shows dismiss and snooze buttons and rings until the user interacts or times out. Watch sends 2-byte BLE responses back to the phone to dismiss or snooze the alarm.
1 parent 0706d4f commit fa97dad

5 files changed

Lines changed: 81 additions & 9 deletions

File tree

src/components/ble/AlertNotificationService.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ int AlertNotificationService::OnAlert(struct ble_gatt_access_ctxt* ctxt) {
7272
case Categories::Call:
7373
notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall;
7474
break;
75+
case Categories::HighPrioritizedAlert:
76+
notif.category = Pinetime::Controllers::NotificationManager::Categories::PhoneAlarm;
77+
break;
7578
default:
7679
notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert;
7780
break;
@@ -122,3 +125,29 @@ void AlertNotificationService::MuteIncomingCall() {
122125

123126
ble_gattc_notify_custom(connectionHandle, eventHandle, om);
124127
}
128+
129+
void AlertNotificationService::DismissPhoneAlarm() {
130+
uint8_t response[2] = {0x01, static_cast<uint8_t>(PhoneAlarmResponses::Dismiss)};
131+
auto* om = ble_hs_mbuf_from_flat(response, sizeof(response));
132+
133+
uint16_t connectionHandle = systemTask.nimble().connHandle();
134+
135+
if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) {
136+
return;
137+
}
138+
139+
ble_gattc_notify_custom(connectionHandle, eventHandle, om);
140+
}
141+
142+
void AlertNotificationService::SnoozePhoneAlarm() {
143+
uint8_t response[2] = {0x01, static_cast<uint8_t>(PhoneAlarmResponses::Snooze)};
144+
auto* om = ble_hs_mbuf_from_flat(response, sizeof(response));
145+
146+
uint16_t connectionHandle = systemTask.nimble().connHandle();
147+
148+
if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) {
149+
return;
150+
}
151+
152+
ble_gattc_notify_custom(connectionHandle, eventHandle, om);
153+
}

src/components/ble/AlertNotificationService.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ namespace Pinetime {
3333

3434
enum class IncomingCallResponses : uint8_t { Reject = 0x00, Answer = 0x01, Mute = 0x02 };
3535

36+
void DismissPhoneAlarm();
37+
void SnoozePhoneAlarm();
38+
39+
enum class PhoneAlarmResponses : uint8_t { Dismiss = 0x00, Snooze = 0x01 };
40+
3641
private:
3742
enum class Categories : uint8_t {
3843
SimpleAlert = 0x00,

src/components/ble/NotificationManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace Pinetime {
1919
Sms,
2020
VoiceMail,
2121
Schedule,
22-
HighProriotyAlert,
22+
PhoneAlarm, // ANS HighPriorityAlert (0x08) is only used for phone alarms in Gadgetbridge
2323
InstantMessage
2424
};
2525
static constexpr uint8_t MessageSize {100};

src/displayapp/screens/Notifications.cpp

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ Notifications::Notifications(DisplayApp* app,
4141
}
4242
if (mode == Modes::Preview) {
4343
wakeLock.Lock();
44-
if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) {
44+
if (notification.category == Controllers::NotificationManager::Categories::IncomingCall ||
45+
notification.category == Controllers::NotificationManager::Categories::PhoneAlarm) {
4546
motorController.StartRinging();
4647
} else {
4748
motorController.RunForDuration(35);
@@ -262,7 +263,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
262263
uint8_t notifNb,
263264
Pinetime::Controllers::AlertNotificationService& alertNotificationService,
264265
Pinetime::Controllers::MotorController& motorController)
265-
: alertNotificationService {alertNotificationService}, motorController {motorController} {
266+
: alertNotificationService {alertNotificationService}, motorController {motorController}, category {category} {
266267
container = lv_cont_create(lv_scr_act(), nullptr);
267268
lv_obj_set_size(container, LV_HOR_RES, LV_VER_RES);
268269
lv_obj_set_style_local_bg_color(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
@@ -348,6 +349,34 @@ Notifications::NotificationItem::NotificationItem(const char* title,
348349
lv_label_set_text_static(label_mute, Symbols::volumMute);
349350
lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
350351
} break;
352+
case Controllers::NotificationManager::Categories::PhoneAlarm: {
353+
lv_obj_set_height(subject_container, 108);
354+
lv_label_set_text_static(alert_subject, "Phone Alarm");
355+
356+
lv_obj_t* alert_label = lv_label_create(subject_container, nullptr);
357+
lv_obj_align(alert_label, alert_subject, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
358+
lv_label_set_long_mode(alert_label, LV_LABEL_LONG_BREAK);
359+
lv_obj_set_width(alert_label, LV_HOR_RES - 20);
360+
lv_label_set_text(alert_label, msg);
361+
362+
bt_reject = lv_btn_create(container, nullptr);
363+
bt_reject->user_data = this;
364+
lv_obj_set_event_cb(bt_reject, CallEventHandler);
365+
lv_obj_set_size(bt_reject, 115, 76);
366+
lv_obj_align(bt_reject, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
367+
label_reject = lv_label_create(bt_reject, nullptr);
368+
lv_label_set_text_static(label_reject, Symbols::stop);
369+
lv_obj_set_style_local_bg_color(bt_reject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
370+
371+
bt_mute = lv_btn_create(container, nullptr);
372+
bt_mute->user_data = this;
373+
lv_obj_set_event_cb(bt_mute, CallEventHandler);
374+
lv_obj_set_size(bt_mute, 115, 76);
375+
lv_obj_align(bt_mute, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
376+
label_mute = lv_label_create(bt_mute, nullptr);
377+
lv_label_set_text_static(label_mute, "zzz");
378+
lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::violet);
379+
} break;
351380
}
352381
}
353382

@@ -358,12 +387,20 @@ void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_
358387

359388
motorController.StopRinging();
360389

361-
if (obj == bt_accept) {
362-
alertNotificationService.AcceptIncomingCall();
363-
} else if (obj == bt_reject) {
364-
alertNotificationService.RejectIncomingCall();
365-
} else if (obj == bt_mute) {
366-
alertNotificationService.MuteIncomingCall();
390+
if (category == Controllers::NotificationManager::Categories::PhoneAlarm) {
391+
if (obj == bt_reject) {
392+
alertNotificationService.DismissPhoneAlarm();
393+
} else if (obj == bt_mute) {
394+
alertNotificationService.SnoozePhoneAlarm();
395+
}
396+
} else {
397+
if (obj == bt_accept) {
398+
alertNotificationService.AcceptIncomingCall();
399+
} else if (obj == bt_reject) {
400+
alertNotificationService.RejectIncomingCall();
401+
} else if (obj == bt_mute) {
402+
alertNotificationService.MuteIncomingCall();
403+
}
367404
}
368405

369406
running = false;

src/displayapp/screens/Notifications.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ namespace Pinetime {
6666
Pinetime::Controllers::AlertNotificationService& alertNotificationService;
6767
Pinetime::Controllers::MotorController& motorController;
6868

69+
Controllers::NotificationManager::Categories category = Controllers::NotificationManager::Categories::Unknown;
6970
bool running = true;
7071
};
7172

0 commit comments

Comments
 (0)