-
-
Notifications
You must be signed in to change notification settings - Fork 982
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ANCS Support #2217
base: main
Are you sure you want to change the base?
ANCS Support #2217
Changes from all commits
965e69a
646c209
315f69b
fcdecbb
b9cc3c3
72df4fc
0a26a59
3cc4ece
dfa13a9
8916920
7f0e066
fce4a60
9fbc594
1bed731
670c379
5bf8406
288d167
f370d63
0ba425a
2fe3a6b
1e4989f
8ab8296
bb48b5f
c2b392b
f888483
65ead6e
b8da191
de63dce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <functional> | ||
#define min // workaround: nimble's min/max macros conflict with libstdc++ | ||
#define max | ||
#include <host/ble_gap.h> | ||
#undef max | ||
#undef min | ||
#include "components/ble/BleClient.h" | ||
#include <unordered_map> | ||
#include <string> | ||
|
||
namespace Pinetime { | ||
|
||
namespace System { | ||
class SystemTask; | ||
} | ||
|
||
namespace Controllers { | ||
class NotificationManager; | ||
|
||
class AppleNotificationCenterClient : public BleClient { | ||
public: | ||
explicit AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, | ||
Pinetime::Controllers::NotificationManager& notificationManager); | ||
|
||
bool OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service); | ||
int OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic); | ||
int OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute); | ||
int OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, | ||
const ble_gatt_error* error, | ||
uint16_t characteristicValueHandle, | ||
const ble_gatt_dsc* descriptor); | ||
int OnControlPointWrite(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute); | ||
void OnNotification(ble_gap_event* event); | ||
void Reset(); | ||
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override; | ||
void DebugNotification(const char* msg) const; | ||
|
||
void AcceptIncomingCall(uint32_t notificationUid); | ||
void RejectIncomingCall(uint32_t notificationUid); | ||
|
||
static constexpr uint8_t maxTitleSize {20}; | ||
static constexpr uint8_t maxSubtitleSize {15}; | ||
static constexpr uint8_t maxMessageSize {120}; | ||
|
||
// 7905F431-B5CE-4E99-A40F-4B1E122D00D0 | ||
static constexpr ble_uuid128_t ancsUuid { | ||
.u {.type = BLE_UUID_TYPE_128}, | ||
.value = {0xd0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79}}; | ||
|
||
private: | ||
// 9FBF120D-6301-42D9-8C58-25E699A21DBD | ||
const ble_uuid128_t notificationSourceChar { | ||
.u {.type = BLE_UUID_TYPE_128}, | ||
.value = {0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0x8C, 0xD9, 0x42, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F}}; | ||
// 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 | ||
const ble_uuid128_t controlPointChar { | ||
.u {.type = BLE_UUID_TYPE_128}, | ||
.value = {0xD9, 0xD9, 0xAA, 0xFD, 0xBD, 0x9B, 0x21, 0x98, 0xA8, 0x49, 0xE1, 0x45, 0xF3, 0xD8, 0xD1, 0x69}}; | ||
// 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB | ||
const ble_uuid128_t dataSourceChar { | ||
.u {.type = BLE_UUID_TYPE_128}, | ||
.value = {0xFB, 0x7B, 0x7C, 0xCE, 0x6A, 0xB3, 0x44, 0xBE, 0xB5, 0x4B, 0xD6, 0x24, 0xE9, 0xC6, 0xEA, 0x22}}; | ||
|
||
const ble_uuid16_t gattServiceUuid = {BLE_UUID_TYPE_16, 0x1801}; | ||
const ble_uuid16_t serviceChangedCharUuid = {BLE_UUID_TYPE_16, 0x2A05}; | ||
|
||
enum class Categories : uint8_t { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For all of these constants above and below, is there a reference document somewhere? It would be great to have the URL linked in a comment |
||
Other = 0, | ||
IncomingCall = 1, | ||
MissedCall = 2, | ||
Voicemail = 3, | ||
Social = 4, | ||
Schedule = 5, | ||
Email = 6, | ||
News = 7, | ||
HealthAndFitness = 8, | ||
BuissnessAndFinance = 9, | ||
Location = 10, | ||
Entertainment = 11 | ||
}; | ||
|
||
enum class EventIds : uint8_t { Added = 0, Modified = 1, Removed = 2 }; | ||
|
||
enum class EventFlags : uint8_t { | ||
Silent = (1 << 0), | ||
Important = (1 << 1), | ||
PreExisting = (1 << 2), | ||
PositiveAction = (1 << 3), | ||
NegativeAction = (1 << 4) | ||
}; | ||
|
||
struct AncsNotification { | ||
uint8_t eventId {0}; | ||
uint8_t eventFlags {0}; | ||
uint8_t category {0}; | ||
uint32_t uuid {0}; | ||
}; | ||
|
||
std::unordered_map<uint32_t, AncsNotification> notifications; | ||
|
||
std::string DecodeUtf8String(os_mbuf* om, uint16_t size, uint16_t offset); | ||
|
||
uint16_t ancsStartHandle {0}; | ||
uint16_t ancsEndHandle {0}; | ||
uint16_t notificationSourceHandle {0}; | ||
uint16_t controlPointHandle {0}; | ||
uint16_t dataSourceHandle {0}; | ||
uint16_t notificationSourceDescriptorHandle {0}; | ||
uint16_t controlPointDescriptorHandle {0}; | ||
uint16_t dataSourceDescriptorHandle {0}; | ||
|
||
uint16_t gattStartHandle {0}; | ||
uint16_t gattEndHandle {0}; | ||
uint16_t serviceChangedHandle {0}; | ||
uint16_t serviceChangedDescriptorHandle {0}; | ||
bool isGattDiscovered {false}; | ||
bool isGattCharacteristicDiscovered {false}; | ||
bool isGattDescriptorFound {false}; | ||
bool isDiscovered {false}; | ||
bool isCharacteristicDiscovered {false}; | ||
bool isDescriptorFound {false}; | ||
bool isControlCharacteristicDiscovered {false}; | ||
bool isControlDescriptorFound {false}; | ||
bool isDataCharacteristicDiscovered {false}; | ||
bool isDataDescriptorFound {false}; | ||
Comment on lines
+119
to
+128
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Massive networks of booleans like this scare me a bit. There are theoretically 2^10 = 1024 states here. Could this be refactored into a state enum somehow? |
||
Pinetime::System::SystemTask& systemTask; | ||
Pinetime::Controllers::NotificationManager& notificationManager; | ||
std::function<void(uint16_t)> onServiceDiscovered; | ||
}; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs a trailing newline (this applies to some other files too) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,7 +49,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, | |
heartRateService {*this, heartRateController}, | ||
motionService {*this, motionController}, | ||
fsService {systemTask, fs}, | ||
serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { | ||
ancsClient {systemTask, notificationManager}, | ||
serviceDiscovery({¤tTimeClient, &alertNotificationClient, &ancsClient}) { | ||
} | ||
|
||
void nimble_on_reset(int reason) { | ||
|
@@ -161,8 +162,10 @@ void NimbleController::StartAdvertising() { | |
fields.uuids16 = &HeartRateService::heartRateServiceUuid; | ||
fields.num_uuids16 = 1; | ||
fields.uuids16_is_complete = 1; | ||
fields.uuids128 = &DfuService::serviceUuid; | ||
fields.num_uuids128 = 1; | ||
const ble_uuid128_t uuids128[2] = {DfuService::serviceUuid, AppleNotificationCenterClient::ancsUuid}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is all OK size wise? I have vague memories of there not being space in the advertisement packet for more 128bit UUIDS. Could be totally wrong on this |
||
// fields.uuids128 = &DfuService::serviceUuid; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove comment |
||
fields.uuids128 = uuids128; | ||
fields.num_uuids128 = 2; | ||
fields.uuids128_is_complete = 1; | ||
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; | ||
|
||
|
@@ -200,6 +203,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { | |
/* Connection failed; resume advertising. */ | ||
currentTimeClient.Reset(); | ||
alertNotificationClient.Reset(); | ||
ancsClient.Reset(); | ||
connectionHandle = BLE_HS_CONN_HANDLE_NONE; | ||
bleController.Disconnect(); | ||
fastAdvCount = 0; | ||
|
@@ -209,6 +213,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { | |
bleController.Connect(); | ||
systemTask.PushMessage(Pinetime::System::Messages::BleConnected); | ||
// Service discovery is deferred via systemtask | ||
ble_gap_security_initiate(event->connect.conn_handle); | ||
} | ||
break; | ||
|
||
|
@@ -223,6 +228,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { | |
|
||
currentTimeClient.Reset(); | ||
alertNotificationClient.Reset(); | ||
ancsClient.Reset(); | ||
connectionHandle = BLE_HS_CONN_HANDLE_NONE; | ||
if (bleController.IsConnected()) { | ||
bleController.Disconnect(); | ||
|
@@ -370,6 +376,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { | |
notifSize); | ||
|
||
alertNotificationClient.OnNotification(event); | ||
ancsClient.OnNotification(event); | ||
} break; | ||
|
||
case BLE_GAP_EVENT_NOTIFY_TX: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
"sources": [ | ||
{ | ||
"file": "JetBrainsMono-Bold.ttf", | ||
"range": "0x20-0x7e, 0x410-0x44f, 0xB0" | ||
"range": "0x20-0x7e, 0x410-0x44f, 0xB0, 0xBF, 0xFFFD" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I quite like this addition semantically. How does it look on hardware? If this is the way to go, should the normal notification service need to be ported to this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is |
||
}, | ||
{ | ||
"file": "FontAwesome5-Solid+Brands+Regular.woff", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of these constants can be
static constexpr