From 965e69a0958bd3d80be5ed2abff29bbad67b2104 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 18 Dec 2024 20:15:01 -0600 Subject: [PATCH 01/74] Started working on ANCS --- src/CMakeLists.txt | 3 + src/components/ble/ANCSService.cpp | 83 +++++++++++++++++++ src/components/ble/ANCSService.h | 62 ++++++++++++++ .../ble/BatteryInformationService.cpp | 2 +- src/components/ble/NimbleController.cpp | 2 + src/components/ble/NimbleController.h | 6 ++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 src/components/ble/ANCSService.cpp create mode 100644 src/components/ble/ANCSService.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e2b69b8b02..43b5871e59 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -457,6 +457,7 @@ list(APPEND SOURCE_FILES components/ble/SimpleWeatherService.cpp components/ble/NavigationService.cpp components/ble/BatteryInformationService.cpp + components/ble/ANCSService.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -526,6 +527,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/MusicService.cpp components/ble/SimpleWeatherService.cpp components/ble/BatteryInformationService.cpp + components/ble/ANCSService.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -642,6 +644,7 @@ set(INCLUDE_FILES components/ble/DeviceInformationService.h components/ble/CurrentTimeClient.h components/ble/AlertNotificationClient.h + components/ble/ANCSService.h components/ble/DfuService.h components/firmwarevalidator/FirmwareValidator.h components/ble/BatteryInformationService.h diff --git a/src/components/ble/ANCSService.cpp b/src/components/ble/ANCSService.cpp new file mode 100644 index 0000000000..24bea775d9 --- /dev/null +++ b/src/components/ble/ANCSService.cpp @@ -0,0 +1,83 @@ +#include "components/ble/ANCSService.h" +#include +#include +#include +#include "components/ble/NotificationManager.h" +#include "systemtask/SystemTask.h" + +using namespace Pinetime::Controllers; + +constexpr ble_uuid128_t ANCSService::notificationSourceCharUuid; +constexpr ble_uuid128_t ANCSService::ancsBaseUuid; + +int NotifSourceCallback(uint16_t /*conn_handle*/, uint16_t /*attr_handle*/, struct ble_gatt_access_ctxt* ctxt, void* arg) { + auto anService = static_cast(arg); + return anService->OnAlert(ctxt); +} + +void ANCSService::Init() { + int res; + res = ble_gatts_count_cfg(serviceDefinition); + ASSERT(res == 0); + + res = ble_gatts_add_svcs(serviceDefinition); + ASSERT(res == 0); +} + +ANCSService::ANCSService(System::SystemTask& systemTask, NotificationManager& notificationManager) + : characteristicDefinition {{.uuid = ¬ificationSourceCharUuid.u, + .access_cb = NotifSourceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_NOTIFY, + .val_handle = &eventHandle}, + {0}}, + serviceDefinition { + {/* Device Information Service */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &ancsBaseUuid.u, + .characteristics = characteristicDefinition}, + {0}, + }, + systemTask {systemTask}, + notificationManager {notificationManager} { +} + +int ANCSService::OnAlert(struct ble_gatt_access_ctxt* ctxt) { + if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + constexpr size_t stringTerminatorSize = 1; // end of string '\0' + constexpr size_t headerSize = 4; + const auto maxMessageSize {NotificationManager::MaximumMessageSize()}; + const auto maxBufferSize {maxMessageSize + headerSize}; + + // Ignore notifications with empty message + const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); + if (packetLen <= headerSize) { + return 0; + } + + size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize); + auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize)); + Categories category; + + NotificationManager::Notification notif; + os_mbuf_copydata(ctxt->om, headerSize, 4/*messageSize - 1*/, notif.message.data()); + os_mbuf_copydata(ctxt->om, 2, 1, &category); + notif.message[messageSize - 1] = '\0'; + notif.size = messageSize; + + // TODO convert all ANS categories to NotificationController categories + switch (category) { + case Categories::IncomingCall: + notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall; + break; + default: + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + break; + } + + auto event = Pinetime::System::Messages::OnNewNotification; + notificationManager.Push(std::move(notif)); + systemTask.PushMessage(event); + } + return 0; +} diff --git a/src/components/ble/ANCSService.h b/src/components/ble/ANCSService.h new file mode 100644 index 0000000000..1879023489 --- /dev/null +++ b/src/components/ble/ANCSService.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#define min // workaround: nimble's min/max macros conflict with libstdc++ +#define max +#include +#undef max +#undef min + +// Primary ANCS UUID: 7905F431-B5CE-4E99-A40F-4B1E122D00D0 +#define ANCS_SERVICE_UUID_BASE { 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79 } + +// Notification Source UUID: 9FBF120D-6301-42D9-8C58-25E699A21DBD +#define ANCS_NOTIFICATION_SOURCE_UUID { 0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0x8C, 0xD9, 0x42, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F } + +namespace Pinetime { + + namespace System { + class SystemTask; + } + + namespace Controllers { + class NotificationManager; + + class ANCSService { + public: + enum class Categories : uint8_t { + Other = 0, + IncomingCall = 1, + MissedCall = 2, + Voicemail = 3, + Social = 4, + Schedule = 5, + Email = 6, + News = 7, + HealthAndFitness = 8, + BuissnessAndFinance = 9, + Location = 10, + Entertainment = 11 + }; + + ANCSService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager); + void Init(); + + int OnAlert(struct ble_gatt_access_ctxt* ctxt); + + private: + + static constexpr ble_uuid128_t notificationSourceCharUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_NOTIFICATION_SOURCE_UUID}; + + static constexpr ble_uuid128_t ancsBaseUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_SERVICE_UUID_BASE}; + + struct ble_gatt_chr_def characteristicDefinition[2]; + struct ble_gatt_svc_def serviceDefinition[2]; + + Pinetime::System::SystemTask& systemTask; + NotificationManager& notificationManager; + + uint16_t eventHandle; + }; + } +} \ No newline at end of file diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index db7c856622..e776526661 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 5059007ab9..0bcc827d24 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -49,6 +49,7 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, heartRateService {*this, heartRateController}, motionService {*this, motionController}, fsService {systemTask, fs}, + ancsService {systemTask, notificationManager}, serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } @@ -97,6 +98,7 @@ void NimbleController::Init() { immediateAlertService.Init(); heartRateService.Init(); motionService.Init(); + ancsService.Init(); fsService.Init(); int rc; diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 597ef0cc34..1038f6434f 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -23,6 +23,7 @@ #include "components/ble/MotionService.h" #include "components/ble/SimpleWeatherService.h" #include "components/fs/FS.h" +#include "components/ble/ANCSService.h" namespace Pinetime { namespace Drivers { @@ -71,6 +72,10 @@ namespace Pinetime { return weatherService; }; + Pinetime::Controllers::ANCSService& ancs() { + return ancsService; + }; + uint16_t connHandle(); void NotifyBatteryLevel(uint8_t level); @@ -106,6 +111,7 @@ namespace Pinetime { HeartRateService heartRateService; MotionService motionService; FSService fsService; + ANCSService ancsService; ServiceDiscovery serviceDiscovery; uint8_t addrType; From 646c209f76d010bfbbc8f70151838535f9197c21 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 23:35:24 -0600 Subject: [PATCH 02/74] Started working on he client, which is the correct half that needs to be implemented. --- src/CMakeLists.txt | 6 +- src/components/ble/ANCSService.cpp | 83 ----------- src/components/ble/ANCSService.h | 62 -------- .../ble/AppleNotificationCenterClient.cpp | 140 ++++++++++++++++++ .../ble/AppleNotificationCenterClient.h | 76 ++++++++++ src/components/ble/NimbleController.cpp | 8 +- src/components/ble/NimbleController.h | 8 +- src/components/ble/ServiceDiscovery.cpp | 2 +- src/components/ble/ServiceDiscovery.h | 4 +- 9 files changed, 229 insertions(+), 160 deletions(-) delete mode 100644 src/components/ble/ANCSService.cpp delete mode 100644 src/components/ble/ANCSService.h create mode 100644 src/components/ble/AppleNotificationCenterClient.cpp create mode 100644 src/components/ble/AppleNotificationCenterClient.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 43b5871e59..8e01026411 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -457,7 +457,7 @@ list(APPEND SOURCE_FILES components/ble/SimpleWeatherService.cpp components/ble/NavigationService.cpp components/ble/BatteryInformationService.cpp - components/ble/ANCSService.cpp + components/ble/AppleNotificationCenterClient.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -527,7 +527,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/MusicService.cpp components/ble/SimpleWeatherService.cpp components/ble/BatteryInformationService.cpp - components/ble/ANCSService.cpp + components/ble/AppleNotificationCenterClient.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -644,7 +644,7 @@ set(INCLUDE_FILES components/ble/DeviceInformationService.h components/ble/CurrentTimeClient.h components/ble/AlertNotificationClient.h - components/ble/ANCSService.h + components/ble/AppleNotificationCenterClient.h components/ble/DfuService.h components/firmwarevalidator/FirmwareValidator.h components/ble/BatteryInformationService.h diff --git a/src/components/ble/ANCSService.cpp b/src/components/ble/ANCSService.cpp deleted file mode 100644 index 24bea775d9..0000000000 --- a/src/components/ble/ANCSService.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "components/ble/ANCSService.h" -#include -#include -#include -#include "components/ble/NotificationManager.h" -#include "systemtask/SystemTask.h" - -using namespace Pinetime::Controllers; - -constexpr ble_uuid128_t ANCSService::notificationSourceCharUuid; -constexpr ble_uuid128_t ANCSService::ancsBaseUuid; - -int NotifSourceCallback(uint16_t /*conn_handle*/, uint16_t /*attr_handle*/, struct ble_gatt_access_ctxt* ctxt, void* arg) { - auto anService = static_cast(arg); - return anService->OnAlert(ctxt); -} - -void ANCSService::Init() { - int res; - res = ble_gatts_count_cfg(serviceDefinition); - ASSERT(res == 0); - - res = ble_gatts_add_svcs(serviceDefinition); - ASSERT(res == 0); -} - -ANCSService::ANCSService(System::SystemTask& systemTask, NotificationManager& notificationManager) - : characteristicDefinition {{.uuid = ¬ificationSourceCharUuid.u, - .access_cb = NotifSourceCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_NOTIFY, - .val_handle = &eventHandle}, - {0}}, - serviceDefinition { - {/* Device Information Service */ - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = &ancsBaseUuid.u, - .characteristics = characteristicDefinition}, - {0}, - }, - systemTask {systemTask}, - notificationManager {notificationManager} { -} - -int ANCSService::OnAlert(struct ble_gatt_access_ctxt* ctxt) { - if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - constexpr size_t stringTerminatorSize = 1; // end of string '\0' - constexpr size_t headerSize = 4; - const auto maxMessageSize {NotificationManager::MaximumMessageSize()}; - const auto maxBufferSize {maxMessageSize + headerSize}; - - // Ignore notifications with empty message - const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); - if (packetLen <= headerSize) { - return 0; - } - - size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize); - auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize)); - Categories category; - - NotificationManager::Notification notif; - os_mbuf_copydata(ctxt->om, headerSize, 4/*messageSize - 1*/, notif.message.data()); - os_mbuf_copydata(ctxt->om, 2, 1, &category); - notif.message[messageSize - 1] = '\0'; - notif.size = messageSize; - - // TODO convert all ANS categories to NotificationController categories - switch (category) { - case Categories::IncomingCall: - notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall; - break; - default: - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - break; - } - - auto event = Pinetime::System::Messages::OnNewNotification; - notificationManager.Push(std::move(notif)); - systemTask.PushMessage(event); - } - return 0; -} diff --git a/src/components/ble/ANCSService.h b/src/components/ble/ANCSService.h deleted file mode 100644 index 1879023489..0000000000 --- a/src/components/ble/ANCSService.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include -#include -#define min // workaround: nimble's min/max macros conflict with libstdc++ -#define max -#include -#undef max -#undef min - -// Primary ANCS UUID: 7905F431-B5CE-4E99-A40F-4B1E122D00D0 -#define ANCS_SERVICE_UUID_BASE { 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79 } - -// Notification Source UUID: 9FBF120D-6301-42D9-8C58-25E699A21DBD -#define ANCS_NOTIFICATION_SOURCE_UUID { 0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0x8C, 0xD9, 0x42, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F } - -namespace Pinetime { - - namespace System { - class SystemTask; - } - - namespace Controllers { - class NotificationManager; - - class ANCSService { - public: - enum class Categories : uint8_t { - Other = 0, - IncomingCall = 1, - MissedCall = 2, - Voicemail = 3, - Social = 4, - Schedule = 5, - Email = 6, - News = 7, - HealthAndFitness = 8, - BuissnessAndFinance = 9, - Location = 10, - Entertainment = 11 - }; - - ANCSService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager); - void Init(); - - int OnAlert(struct ble_gatt_access_ctxt* ctxt); - - private: - - static constexpr ble_uuid128_t notificationSourceCharUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_NOTIFICATION_SOURCE_UUID}; - - static constexpr ble_uuid128_t ancsBaseUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_SERVICE_UUID_BASE}; - - struct ble_gatt_chr_def characteristicDefinition[2]; - struct ble_gatt_svc_def serviceDefinition[2]; - - Pinetime::System::SystemTask& systemTask; - NotificationManager& notificationManager; - - uint16_t eventHandle; - }; - } -} \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp new file mode 100644 index 0000000000..7142bfdf15 --- /dev/null +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -0,0 +1,140 @@ +#include "components/ble/AppleNotificationCenterClient.h" +#include +#include "components/ble/NotificationManager.h" +#include "systemtask/SystemTask.h" + +using namespace Pinetime::Controllers; + + +int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_svc* service, void* arg) { + auto client = static_cast(arg); + return client->OnDiscoveryEvent(conn_handle, error, service); +} + +int OnANCSCharacteristicDiscoveredCallback(uint16_t conn_handle, + const struct ble_gatt_error* error, + const struct ble_gatt_chr* chr, + void* arg) { + auto client = static_cast(arg); + return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr); +} + +int OnANCSDescriptorDiscoveryEventCallback( + uint16_t conn_handle, const struct ble_gatt_error* error, uint16_t chr_val_handle, const struct ble_gatt_dsc* dsc, void* arg) { + auto client = static_cast(arg); + return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc); +} + +int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* error, struct ble_gatt_attr* attr, void* arg) { + auto client = static_cast(arg); + return client->OnNewAlertSubcribe(conn_handle, error, attr); +} + +AppleNotificationCenterClient::AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, + Pinetime::Controllers::NotificationManager& notificationManager) + : systemTask {systemTask}, notificationManager {notificationManager} { +} + +bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service) { + if (service == nullptr && error->status == BLE_HS_EDONE) { + if (isDiscovered) { + NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); + + ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); + } else { + NRF_LOG_INFO("ANCS not found"); + onServiceDiscovered(connectionHandle); + } + return true; + } + + if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { + NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); + ancsStartHandle = service->start_handle; + ancsEndHandle = service->end_handle; + isDiscovered = true; + } + return false; +} + +int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic) { + if (error->status != 0 && error->status != BLE_HS_EDONE) { + NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); + onServiceDiscovered(connectionHandle); + return 0; + } + + if (characteristic == nullptr && error->status == BLE_HS_EDONE) { + NRF_LOG_INFO("ANCS Characteristic discovery complete"); + if (isCharacteristicDiscovered) { + ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); + } else { + onServiceDiscovered(connectionHandle); + } + } else { + if (characteristic != nullptr && ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + notificationSourceHandle = characteristic->val_handle; + // notificationSourceDefHandle = characteristic->def_handle; + isCharacteristicDiscovered = true; + } + } + return 0; +} + +int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error* error, uint16_t characteristicValueHandle, const ble_gatt_dsc* descriptor) { + if (error->status == 0) { + if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { + if (notificationSourceDescriptorHandle == 0) { + NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + notificationSourceDescriptorHandle = descriptor->handle; + isDescriptorFound = true; + uint8_t value[2] {1, 0}; + ble_gattc_write_flat(connectionHandle, notificationSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); + } + } + } else { + if (!isDescriptorFound) + onServiceDiscovered(connectionHandle); + } + return 0; +} + +int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { + if (error->status == 0) { + NRF_LOG_INFO("ANCS New alert subscribe OK"); + } else { + NRF_LOG_INFO("ANCS New alert subscribe ERROR"); + } + onServiceDiscovered(connectionHandle); + + return 0; +} + +void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { + if (event->notify_rx.attr_handle == notificationSourceHandle) { + NotificationManager::Notification notif; + notif.message = std::array {"Hello\0World"}; + notif.size = 11; + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + } +} + +void AppleNotificationCenterClient::Reset() { + ancsStartHandle = 0; + ancsEndHandle = 0; + notificationSourceHandle = 0; + notificationSourceDescriptorHandle = 0; + isDiscovered = false; + isCharacteristicDiscovered = false; + isDescriptorFound = false; +} + +void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { + NRF_LOG_INFO("[ANCS] Starting discovery"); + this->onServiceDiscovered = onServiceDiscovered; + ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); +} \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h new file mode 100644 index 0000000000..ac22c96e7d --- /dev/null +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#define min // workaround: nimble's min/max macros conflict with libstdc++ +#define max +#include +#undef max +#undef min +#include "components/ble/BleClient.h" + +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); + void OnNotification(ble_gap_event* event); + void Reset(); + void Discover(uint16_t connectionHandle, std::function lambda) override; + + private: + // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 + const ble_uuid128_t ancsUuid { + {BLE_UUID_TYPE_128}, + {0xd0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0x24, 0x99, 0x0E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79} + }; + + // 9FBF120D-6301-42D9-8C58-25E699A21DBD + const ble_uuid128_t notificationSourceChar { + {BLE_UUID_TYPE_128}, + {0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0X0C, 0xD9, 0x02, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F} + }; + // 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 + const ble_uuid128_t controlPointChar { + {BLE_UUID_TYPE_128}, + {0xD9, 0xD9, 0xAA, 0xFD, 0xBD, 0x9B, 0x21, 0X18,0xA8, 0x09,0xE1, 0x45, 0xF3, 0xD8, 0xD1, 0x69 } + }; + // 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB + const ble_uuid128_t dataSourceChar { + {BLE_UUID_TYPE_128}, + {0xFB, 0x7B, 0x7C, 0xCE, 0x6A, 0xB3, 0x44, 0X3E,0xB5, 0x0B,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}; + + + 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 serviceChangedHandle {0}; + bool isDiscovered {false}; + bool isCharacteristicDiscovered {false}; + bool isDescriptorFound {false}; + Pinetime::System::SystemTask& systemTask; + Pinetime::Controllers::NotificationManager& notificationManager; + std::function onServiceDiscovered; + }; + } +} \ No newline at end of file diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 0bcc827d24..046d69be52 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -49,8 +49,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, heartRateService {*this, heartRateController}, motionService {*this, motionController}, fsService {systemTask, fs}, - ancsService {systemTask, notificationManager}, - serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { + ancsClient {systemTask, notificationManager}, + serviceDiscovery({¤tTimeClient, &alertNotificationClient, &ancsClient}) { } void nimble_on_reset(int reason) { @@ -98,7 +98,6 @@ void NimbleController::Init() { immediateAlertService.Init(); heartRateService.Init(); motionService.Init(); - ancsService.Init(); fsService.Init(); int rc; @@ -202,6 +201,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; @@ -225,6 +225,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(); @@ -372,6 +373,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { notifSize); alertNotificationClient.OnNotification(event); + ancsClient.OnNotification(event); } break; case BLE_GAP_EVENT_NOTIFY_TX: diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 1038f6434f..b84cd1556e 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -23,7 +23,7 @@ #include "components/ble/MotionService.h" #include "components/ble/SimpleWeatherService.h" #include "components/fs/FS.h" -#include "components/ble/ANCSService.h" +#include "components/ble/AppleNotificationCenterClient.h" namespace Pinetime { namespace Drivers { @@ -72,10 +72,6 @@ namespace Pinetime { return weatherService; }; - Pinetime::Controllers::ANCSService& ancs() { - return ancsService; - }; - uint16_t connHandle(); void NotifyBatteryLevel(uint8_t level); @@ -111,7 +107,7 @@ namespace Pinetime { HeartRateService heartRateService; MotionService motionService; FSService fsService; - ANCSService ancsService; + AppleNotificationCenterClient ancsClient; ServiceDiscovery serviceDiscovery; uint8_t addrType; diff --git a/src/components/ble/ServiceDiscovery.cpp b/src/components/ble/ServiceDiscovery.cpp index 03bcfeb47b..e467c014f2 100644 --- a/src/components/ble/ServiceDiscovery.cpp +++ b/src/components/ble/ServiceDiscovery.cpp @@ -4,7 +4,7 @@ using namespace Pinetime::Controllers; -ServiceDiscovery::ServiceDiscovery(std::array&& clients) : clients {clients} { +ServiceDiscovery::ServiceDiscovery(std::array&& clients) : clients {clients} { } void ServiceDiscovery::StartDiscovery(uint16_t connectionHandle) { diff --git a/src/components/ble/ServiceDiscovery.h b/src/components/ble/ServiceDiscovery.h index fc3b38c0a6..039862a442 100644 --- a/src/components/ble/ServiceDiscovery.h +++ b/src/components/ble/ServiceDiscovery.h @@ -9,13 +9,13 @@ namespace Pinetime { class ServiceDiscovery { public: - ServiceDiscovery(std::array&& bleClients); + ServiceDiscovery(std::array&& bleClients); void StartDiscovery(uint16_t connectionHandle); private: BleClient** clientIterator; - std::array clients; + std::array clients; void OnServiceDiscovered(uint16_t connectionHandle); void DiscoverNextService(uint16_t connectionHandle); }; From 315f69b2c6ad66aa6626e60bb826ee7feff96d04 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 18:27:13 -0600 Subject: [PATCH 03/74] Formatting --- .../ble/AppleNotificationCenterClient.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 7142bfdf15..2d79a7c93b 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -5,7 +5,6 @@ using namespace Pinetime::Controllers; - int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_svc* service, void* arg) { auto client = static_cast(arg); return client->OnDiscoveryEvent(conn_handle, error, service); @@ -19,8 +18,11 @@ int OnANCSCharacteristicDiscoveredCallback(uint16_t conn_handle, return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr); } -int OnANCSDescriptorDiscoveryEventCallback( - uint16_t conn_handle, const struct ble_gatt_error* error, uint16_t chr_val_handle, const struct ble_gatt_dsc* dsc, void* arg) { +int OnANCSDescriptorDiscoveryEventCallback(uint16_t conn_handle, + const struct ble_gatt_error* error, + uint16_t chr_val_handle, + const struct ble_gatt_dsc* dsc, + void* arg) { auto client = static_cast(arg); return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc); } @@ -31,7 +33,7 @@ int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* } AppleNotificationCenterClient::AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, - Pinetime::Controllers::NotificationManager& notificationManager) + Pinetime::Controllers::NotificationManager& notificationManager) : systemTask {systemTask}, notificationManager {notificationManager} { } @@ -57,7 +59,9 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, return false; } -int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic) { +int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, + const ble_gatt_error* error, + const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); @@ -82,7 +86,10 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn return 0; } -int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error* error, uint16_t characteristicValueHandle, const ble_gatt_dsc* descriptor) { +int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, + const ble_gatt_error* error, + uint16_t characteristicValueHandle, + const ble_gatt_dsc* descriptor) { if (error->status == 0) { if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { From fcdecbb485b815543a2f7a36f737489d27e7c807 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 18:27:22 -0600 Subject: [PATCH 04/74] Added RTT logging --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e01026411..3f7d182d84 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -834,8 +834,8 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") # NRF SDK Logging add_definitions(-DNRF_LOG_ENABLED=1) - # add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) - # add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) + add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) + add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) # NRF SDK individual modules logging # add_definitions(-DCLOCK_CONFIG_LOG_ENABLED=1) From b9cc3c39d96f9727e05570cae99dc2d527df6209 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 23 Dec 2024 22:51:58 -0600 Subject: [PATCH 05/74] Added debugging through watch notifications --- .../ble/AppleNotificationCenterClient.cpp | 23 +++++++++++++++++++ .../ble/AppleNotificationCenterClient.h | 1 + 2 files changed, 24 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 2d79a7c93b..569a301ceb 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -41,10 +41,12 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service == nullptr && error->status == BLE_HS_EDONE) { if (isDiscovered) { NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); + DebugNotification("ANCS Discovery found, starting characteristics discovery"); ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); } else { NRF_LOG_INFO("ANCS not found"); + DebugNotification("ANCS not found"); onServiceDiscovered(connectionHandle); } return true; @@ -52,6 +54,7 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); + DebugNotification("ANCS discovered"); ancsStartHandle = service->start_handle; ancsEndHandle = service->end_handle; isDiscovered = true; @@ -64,12 +67,14 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); + DebugNotification("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); return 0; } if (characteristic == nullptr && error->status == BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery complete"); + DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } else { @@ -78,6 +83,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn } else { if (characteristic != nullptr && ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + DebugNotification("ANCS Characteristic discovered: Notification Source"); notificationSourceHandle = characteristic->val_handle; // notificationSourceDefHandle = characteristic->def_handle; isCharacteristicDiscovered = true; @@ -94,6 +100,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + DebugNotification("ANCS Descriptor discovered"); notificationSourceDescriptorHandle = descriptor->handle; isDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -110,8 +117,10 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); + DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); + DebugNotification("ANCS New alert subscribe ERROR"); } onServiceDiscovered(connectionHandle); @@ -142,6 +151,20 @@ void AppleNotificationCenterClient::Reset() { void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { NRF_LOG_INFO("[ANCS] Starting discovery"); + DebugNotification("[ANCS] Starting discovery"); this->onServiceDiscovered = onServiceDiscovered; ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); +} + +void AppleNotificationCenterClient::DebugNotification(const char* msg) const { + NRF_LOG_INFO("[ANCS DEBUG] %s", msg); + + NotificationManager::Notification notif; + std::strncpy(notif.message.data(), msg, notif.message.size() - 1); + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(msg), notif.message.size()); + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index ac22c96e7d..042fa1fa62 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -30,6 +30,7 @@ namespace Pinetime { void OnNotification(ble_gap_event* event); void Reset(); void Discover(uint16_t connectionHandle, std::function lambda) override; + void DebugNotification(const char* msg) const; private: // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 From 72df4fc149a2d04c23c7a0ea57da72cba6da2e05 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 29 Dec 2024 12:40:06 -0600 Subject: [PATCH 06/74] Removed encryption of battery and added required pairing on connect GAP event --- src/components/ble/BatteryInformationService.cpp | 2 +- src/components/ble/NimbleController.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index e776526661..db7c856622 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 046d69be52..0e46415f52 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -211,6 +211,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; From 0a26a595f4e603e2bfa005a4dfad51afc5676fd4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 29 Dec 2024 12:48:01 -0600 Subject: [PATCH 07/74] ANCS Partially works Currently, the notification UID, Event ID and Category are shown. --- .../ble/AppleNotificationCenterClient.cpp | 59 ++++++++++++++++- .../ble/AppleNotificationCenterClient.h | 66 +++++++++++++++---- src/components/ble/NimbleController.cpp | 6 +- 3 files changed, 115 insertions(+), 16 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 569a301ceb..cec1fad3c6 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -129,9 +129,49 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (event->notify_rx.attr_handle == notificationSourceHandle) { + NRF_LOG_INFO("ANCS Notification received"); + uint8_t eventId; + uint8_t eventFlag; + uint8_t category; + uint8_t categoryCount; + uint32_t notificationUuid; + + os_mbuf_copydata(event->notify_rx.om, 0, 1, &eventId); + os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlag); + os_mbuf_copydata(event->notify_rx.om, 2, 1, &category); + os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); + os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); + + if (eventId != static_cast(EventIds::Added)) { + return; + } + + // Request ANCS more info + // uint8_t request[] = { + // 0x00, // Command ID: Get Notification Attributes + // (uint8_t) (notificationUuid & 0xFF), + // (uint8_t) ((notificationUuid >> 8) & 0xFF), + // (uint8_t) ((notificationUuid >> 16) & 0xFF), + // (uint8_t) ((notificationUuid >> 24) & 0xFF), + // 0x01, + // 0x00, + // 0xFF, + // 0xFF, // Title (max length 65535) + // 0x03, + // 0x00, + // 0xFF, + // 0xFF // Message (max length 65535) + // }; + // ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), nullptr, nullptr); + NotificationManager::Notification notif; - notif.message = std::array {"Hello\0World"}; - notif.size = 11; + char uuidStr[55]; + snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); + notif.message = std::array {}; + std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + notif.message[10] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(uuidStr), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; notificationManager.Push(std::move(notif)); @@ -142,11 +182,26 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { void AppleNotificationCenterClient::Reset() { ancsStartHandle = 0; ancsEndHandle = 0; + gattStartHandle = 0; + gattEndHandle = 0; + serviceChangedHandle = 0; + serviceChangedDescriptorHandle = 0; notificationSourceHandle = 0; notificationSourceDescriptorHandle = 0; + controlPointHandle = 0; + controlPointDescriptorHandle = 0; + dataSourceHandle = 0; + dataSourceDescriptorHandle = 0; + isGattDiscovered = false; + isGattCharacteristicDiscovered = false; + isGattDescriptorFound = false; isDiscovered = false; isCharacteristicDiscovered = false; isDescriptorFound = false; + isControlCharacteristicDiscovered = false; + isControlDescriptorFound = false; + isDataCharacteristicDiscovered = false; + isDataDescriptorFound = false; } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 042fa1fa62..ea1a65f5e0 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -32,43 +32,85 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function lambda) override; void DebugNotification(const char* msg) const; - private: // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 - const ble_uuid128_t ancsUuid { - {BLE_UUID_TYPE_128}, - {0xd0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0x24, 0x99, 0x0E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79} + 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 { - {BLE_UUID_TYPE_128}, - {0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0X0C, 0xD9, 0x02, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F} + .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 { - {BLE_UUID_TYPE_128}, - {0xD9, 0xD9, 0xAA, 0xFD, 0xBD, 0x9B, 0x21, 0X18,0xA8, 0x09,0xE1, 0x45, 0xF3, 0xD8, 0xD1, 0x69 } + .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 { - {BLE_UUID_TYPE_128}, - {0xFB, 0x7B, 0x7C, 0xCE, 0x6A, 0xB3, 0x44, 0X3E,0xB5, 0x0B,0xD6, 0x24, 0xE9, 0xC6, 0xEA, 0x22 } + .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 { + 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 = 0x01, + Important = 0x02, + PreExisting = 0x04, + PositiveAction = 0x08, + NegativeAction = 0x10 + }; + uint16_t ancsStartHandle {0}; uint16_t ancsEndHandle {0}; uint16_t notificationSourceHandle {0}; - //uint16_t controlPointHandle {0}; - //uint16_t dataSourceHandle {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}; Pinetime::System::SystemTask& systemTask; Pinetime::Controllers::NotificationManager& notificationManager; std::function onServiceDiscovered; diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 0e46415f52..223a4e37d7 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -162,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}; + // fields.uuids128 = &DfuService::serviceUuid; + fields.uuids128 = uuids128; + fields.num_uuids128 = 2; fields.uuids128_is_complete = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; From 3cc4ece9babbabffc37d5ebdac51d1080d476cf3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 30 Dec 2024 17:23:45 -0600 Subject: [PATCH 08/74] Started working on using Control Point and Data Source: Data source is not working properly, the Characteristic and/or descriptor isn't being found correctly --- .../ble/AppleNotificationCenterClient.cpp | 162 +++++++++++++----- .../ble/AppleNotificationCenterClient.h | 3 +- 2 files changed, 118 insertions(+), 47 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index cec1fad3c6..3bbb65b142 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -32,6 +32,11 @@ int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* return client->OnNewAlertSubcribe(conn_handle, error, attr); } +int OnControlPointWriteCallback(uint16_t conn_handle, const struct ble_gatt_error* error, struct ble_gatt_attr* attr, void* arg) { + auto client = static_cast(arg); + return client->OnControlPointWrite(conn_handle, error, attr); +} + AppleNotificationCenterClient::AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager) : systemTask {systemTask}, notificationManager {notificationManager} { @@ -41,12 +46,12 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service == nullptr && error->status == BLE_HS_EDONE) { if (isDiscovered) { NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); - DebugNotification("ANCS Discovery found, starting characteristics discovery"); + // DebugNotification("ANCS Discovery found, starting characteristics discovery"); ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); } else { NRF_LOG_INFO("ANCS not found"); - DebugNotification("ANCS not found"); + // DebugNotification("ANCS not found"); onServiceDiscovered(connectionHandle); } return true; @@ -54,7 +59,7 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); - DebugNotification("ANCS discovered"); + // DebugNotification("ANCS discovered"); ancsStartHandle = service->start_handle; ancsEndHandle = service->end_handle; isDiscovered = true; @@ -67,7 +72,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); - DebugNotification("ANCS Characteristic discovery ERROR"); + // DebugNotification("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); return 0; } @@ -77,16 +82,31 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); - } else { + } if (isDataCharacteristicDiscovered) { + // DebugNotification("ANCS Characteristic discovery complete: Data Source"); + ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, 0xFFFF, OnANCSDescriptorDiscoveryEventCallback, this); + } + if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { onServiceDiscovered(connectionHandle); } } else { - if (characteristic != nullptr && ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); - DebugNotification("ANCS Characteristic discovered: Notification Source"); - notificationSourceHandle = characteristic->val_handle; - // notificationSourceDefHandle = characteristic->def_handle; - isCharacteristicDiscovered = true; + if (characteristic != nullptr) { + if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + // DebugNotification("ANCS Characteristic discovered: Notification Source"); + notificationSourceHandle = characteristic->val_handle; + isCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); + // DebugNotification("ANCS Characteristic discovered: Control Point"); + controlPointHandle = characteristic->val_handle; + isControlCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); + DebugNotification("ANCS Characteristic discovered: Data Source"); + dataSourceHandle = characteristic->val_handle; + isDataCharacteristicDiscovered = true; + } } } return 0; @@ -100,15 +120,35 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - DebugNotification("ANCS Descriptor discovered"); + // DebugNotification("ANCS Descriptor discovered"); notificationSourceDescriptorHandle = descriptor->handle; isDescriptorFound = true; uint8_t value[2] {1, 0}; ble_gattc_write_flat(connectionHandle, notificationSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); } + } else if (characteristicValueHandle == controlPointHandle && ble_uuid_cmp(&controlPointChar.u, &descriptor->uuid.u)) { + if (controlPointDescriptorHandle == 0) { + NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + // DebugNotification("ANCS Descriptor discovered"); + controlPointDescriptorHandle = descriptor->handle; + isControlDescriptorFound = true; + } + } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { + if (dataSourceDescriptorHandle == 0) { + NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + DebugNotification("ANCS Descriptor discovered: Data Source"); + dataSourceDescriptorHandle = descriptor->handle; + isDataDescriptorFound = true; + uint8_t value[2] {1, 0}; + ble_gattc_write_flat(connectionHandle, dataSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); + } } } else { - if (!isDescriptorFound) + char errorStr[55]; + snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); + NRF_LOG_INFO(errorStr); + DebugNotification(errorStr); + if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); } return 0; @@ -122,60 +162,90 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, NRF_LOG_INFO("ANCS New alert subscribe ERROR"); DebugNotification("ANCS New alert subscribe ERROR"); } - onServiceDiscovered(connectionHandle); + if (isDescriptorFound == isControlDescriptorFound && isDescriptorFound == isDataDescriptorFound) + onServiceDiscovered(connectionHandle); return 0; } +int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHandle*/, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { + if (error->status == 0) { + NRF_LOG_INFO("ANCS Control Point write OK"); + // DebugNotification("ANCS Control Point write OK"); + } else { + char errorStr[55]; + snprintf(errorStr, sizeof(errorStr), "ANCS Control Point ERROR: %d", error->status); + NRF_LOG_INFO(errorStr); + DebugNotification(errorStr); + } + return 0; +} + void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { - if (event->notify_rx.attr_handle == notificationSourceHandle) { + if (event->notify_rx.attr_handle == notificationSourceHandle || event->notify_rx.attr_handle == notificationSourceDescriptorHandle) { NRF_LOG_INFO("ANCS Notification received"); uint8_t eventId; - uint8_t eventFlag; + uint8_t eventFlags; uint8_t category; uint8_t categoryCount; uint32_t notificationUuid; os_mbuf_copydata(event->notify_rx.om, 0, 1, &eventId); - os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlag); + os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlags); os_mbuf_copydata(event->notify_rx.om, 2, 1, &category); os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); - if (eventId != static_cast(EventIds::Added)) { + // bool silent = eventFlags & static_cast(EventFlags::Silent); + // bool important = eventFlags & static_cast(EventFlags::Important); + bool preExisting = eventFlags & static_cast(EventFlags::PreExisting); + // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); + // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + + if (eventId != static_cast(EventIds::Added) && preExisting != true) { return; } // Request ANCS more info - // uint8_t request[] = { - // 0x00, // Command ID: Get Notification Attributes - // (uint8_t) (notificationUuid & 0xFF), - // (uint8_t) ((notificationUuid >> 8) & 0xFF), - // (uint8_t) ((notificationUuid >> 16) & 0xFF), - // (uint8_t) ((notificationUuid >> 24) & 0xFF), - // 0x01, - // 0x00, - // 0xFF, - // 0xFF, // Title (max length 65535) - // 0x03, - // 0x00, - // 0xFF, - // 0xFF // Message (max length 65535) - // }; - // ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), nullptr, nullptr); - - NotificationManager::Notification notif; - char uuidStr[55]; - snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); - notif.message = std::array {}; - std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message - notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - notificationManager.Push(std::move(notif)); + uint8_t titleSize = 30; + BYTE request[8]; + request[0] = 0x00; // Command ID: Get Notification Attributes + request[1] = (uint8_t) (notificationUuid & 0xFF); + request[2] = (uint8_t) ((notificationUuid >> 8) & 0xFF); + request[3] = (uint8_t) ((notificationUuid >> 16) & 0xFF); + request[4] = (uint8_t) ((notificationUuid >> 24) & 0xFF); + request[5] = 0x01; + // request[6] = 0x00; + request[6] = (titleSize & 0xFF); + request[7] = ((titleSize >> 8) & 0xFF); + + ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); + + // NotificationManager::Notification notif; + // char uuidStr[55]; + // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); + // notif.message = std::array {}; + // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + // notif.message[10] = '\0'; // Seperate Title and Message + // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); + // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + // notificationManager.Push(std::move(notif)); systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { + uint16_t titleSize; + uint16_t title; + + os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); + os_mbuf_copydata(event->notify_rx.om, 8, titleSize, &title); + + // char mesgStr[90]; + // snprintf(mesgStr, sizeof(mesgStr), "ANCS Data Source received\nTitle: %d", title); + + // NRF_LOG_INFO(mesgStr); + // DebugNotification(mesgStr); + DebugNotification("ANCS Data Source received"); } } @@ -206,7 +276,7 @@ void AppleNotificationCenterClient::Reset() { void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { NRF_LOG_INFO("[ANCS] Starting discovery"); - DebugNotification("[ANCS] Starting discovery"); + // DebugNotification("[ANCS] Starting discovery"); this->onServiceDiscovered = onServiceDiscovered; ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); } diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index ea1a65f5e0..8fe8fc44e0 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -27,6 +27,7 @@ namespace Pinetime { 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 lambda) override; @@ -52,7 +53,7 @@ namespace Pinetime { // 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 } + .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}; From dfa13a9616ecc6142df95e0dda1d0898d99c447c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 30 Dec 2024 19:24:23 -0600 Subject: [PATCH 09/74] More debugging --- .../ble/AppleNotificationCenterClient.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 3bbb65b142..e12b8d1c42 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -84,7 +84,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isDataCharacteristicDiscovered) { // DebugNotification("ANCS Characteristic discovery complete: Data Source"); - ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, 0xFFFF, OnANCSDescriptorDiscoveryEventCallback, this); + ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { onServiceDiscovered(connectionHandle); @@ -102,8 +102,10 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn controlPointHandle = characteristic->val_handle; isControlCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); - DebugNotification("ANCS Characteristic discovered: Data Source"); + char msg[55]; + snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); + NRF_LOG_INFO(msg); + DebugNotification(msg); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } @@ -144,10 +146,12 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c } } } else { - char errorStr[55]; - snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); - NRF_LOG_INFO(errorStr); - DebugNotification(errorStr); + if (error->status != BLE_HS_EDONE) { + char errorStr[55]; + snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); + NRF_LOG_INFO(errorStr); + DebugNotification(errorStr); + } if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); } From 89169205d5a0d20d3c01301653d452dbb6828bbe Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 31 Dec 2024 00:31:54 -0600 Subject: [PATCH 10/74] Got Datsource to somewhat work and notifications now show title. Datasource seems to go off and on. --- .../ble/AppleNotificationCenterClient.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index e12b8d1c42..886f10c9c5 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -127,6 +127,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c isDescriptorFound = true; uint8_t value[2] {1, 0}; ble_gattc_write_flat(connectionHandle, notificationSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); + ble_gattc_write_flat(connectionHandle, ancsEndHandle, value, sizeof(value), NewAlertSubcribeCallback, this); } } else if (characteristicValueHandle == controlPointHandle && ble_uuid_cmp(&controlPointChar.u, &descriptor->uuid.u)) { if (controlPointDescriptorHandle == 0) { @@ -236,7 +237,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; // notificationManager.Push(std::move(notif)); - systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; uint16_t title; @@ -244,12 +246,17 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); os_mbuf_copydata(event->notify_rx.om, 8, titleSize, &title); - // char mesgStr[90]; - // snprintf(mesgStr, sizeof(mesgStr), "ANCS Data Source received\nTitle: %d", title); + std::string decodedTitle; + decodedTitle.reserve(titleSize); + for (uint16_t i = 0; i < titleSize; ++i) { + uint8_t byte; + os_mbuf_copydata(event->notify_rx.om, 8 + i, 1, &byte); + decodedTitle.push_back(static_cast(byte)); + } - // NRF_LOG_INFO(mesgStr); - // DebugNotification(mesgStr); - DebugNotification("ANCS Data Source received"); + NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); + DebugNotification(decodedTitle.c_str()); + // DebugNotification("ANCS Data Source received"); } } From 7f0e0660acf1ada78000c19083872d8014f9cab5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 31 Dec 2024 00:38:02 -0600 Subject: [PATCH 11/74] Fixed check to only let new notifications pass (maybe) --- src/components/ble/AppleNotificationCenterClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 886f10c9c5..70a7c04ae8 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -203,11 +203,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool silent = eventFlags & static_cast(EventFlags::Silent); // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = eventFlags & static_cast(EventFlags::PreExisting); + bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) == 1; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - if (eventId != static_cast(EventIds::Added) && preExisting != true) { + if (eventId != static_cast(EventIds::Added) || preExisting == true) { return; } From fce4a60198a5a54edf7a242a69c0a13891bcf7b1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 31 Dec 2024 19:14:19 -0600 Subject: [PATCH 12/74] Proper Notification works. Need to iron out some things like characteristics disappearing and reappearing. --- .../ble/AppleNotificationCenterClient.cpp | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 70a7c04ae8..4f2ec14f64 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -207,22 +207,30 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - if (eventId != static_cast(EventIds::Added) || preExisting == true) { + if (preExisting || eventId != static_cast(EventIds::Added)) { return; } // Request ANCS more info uint8_t titleSize = 30; - BYTE request[8]; + uint8_t subTitleSize = 30; + uint8_t messageSize = 90; + BYTE request[14]; request[0] = 0x00; // Command ID: Get Notification Attributes request[1] = (uint8_t) (notificationUuid & 0xFF); request[2] = (uint8_t) ((notificationUuid >> 8) & 0xFF); request[3] = (uint8_t) ((notificationUuid >> 16) & 0xFF); request[4] = (uint8_t) ((notificationUuid >> 24) & 0xFF); - request[5] = 0x01; + request[5] = 0x01; // Attribute ID: Title // request[6] = 0x00; request[6] = (titleSize & 0xFF); request[7] = ((titleSize >> 8) & 0xFF); + request[8] = 0x02; // Attribute ID: Subtitle + request[9] = (subTitleSize & 0xFF); + request[10] = ((subTitleSize >> 8) & 0xFF); + request[11] = 0x03; // Attribute ID: Message + request[12] = (messageSize & 0xFF); + request[13] = ((messageSize >> 8) & 0xFF); ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); @@ -241,10 +249,12 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; - uint16_t title; + uint16_t subTitleSize; + uint16_t messageSize; os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); - os_mbuf_copydata(event->notify_rx.om, 8, titleSize, &title); + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1, 2, &subTitleSize); + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1, 2, &messageSize); std::string decodedTitle; decodedTitle.reserve(titleSize); @@ -254,9 +264,54 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedTitle.push_back(static_cast(byte)); } + std::string decodedSubTitle; + decodedSubTitle.reserve(subTitleSize); + for (uint16_t i = 0; i < subTitleSize; ++i) { + uint8_t byte; + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + i, 1, &byte); + decodedSubTitle.push_back(static_cast(byte)); + } + + std::string decodedMessage; + decodedMessage.reserve(messageSize); + for (uint16_t i = 0; i < messageSize; ++i) { + uint8_t byte; + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2 + i, 1, &byte); + decodedMessage.push_back(static_cast(byte)); + } + NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); - DebugNotification(decodedTitle.c_str()); + NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); + // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); + + if (titleSize > 10) { + decodedTitle.resize(7); + decodedTitle += "... "; + } + + if (subTitleSize > 15) { + decodedSubTitle.resize(12); + decodedSubTitle += "..."; + } + + if (messageSize > 50) { + decodedMessage.resize(47); + decodedMessage += "..."; + } + + NotificationManager::Notification notif; + // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; + std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; + notif.message = std::array {}; + std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); + notif.message[10] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } From 9fbc59461bd759dcd4ceeb273e7ef9dee20fad00 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 1 Jan 2025 20:57:01 -0600 Subject: [PATCH 13/74] Fixed the event flag detection. Only shows a notification when it's new. Also added constants to set lengths for the title, subtitle, and message. --- .../ble/AppleNotificationCenterClient.cpp | 54 ++++++++++--------- .../ble/AppleNotificationCenterClient.h | 15 ++++-- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 4f2ec14f64..c75fee6836 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -203,7 +203,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool silent = eventFlags & static_cast(EventFlags::Silent); // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) == 1; + bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); @@ -212,9 +212,9 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // Request ANCS more info - uint8_t titleSize = 30; - uint8_t subTitleSize = 30; - uint8_t messageSize = 90; + uint8_t titleSize = maxTitleSize + 4; + uint8_t subTitleSize = maxSubtitleSize + 4; + uint8_t messageSize = maxMessageSize + 4; BYTE request[14]; request[0] = 0x00; // Command ID: Get Notification Attributes request[1] = (uint8_t) (notificationUuid & 0xFF); @@ -234,19 +234,19 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); - // NotificationManager::Notification notif; - // char uuidStr[55]; - // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); - // notif.message = std::array {}; - // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - // notif.message[10] = '\0'; // Seperate Title and Message - // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - // notificationManager.Push(std::move(notif)); - - // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); - DebugNotification("ANCS Notification received"); + NotificationManager::Notification notif; + char uuidStr[55]; + snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); + notif.message = std::array {}; + std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + notif.message[10] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(uuidStr), notif.message.size()); + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; uint16_t subTitleSize; @@ -285,27 +285,33 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); - if (titleSize > 10) { - decodedTitle.resize(7); + if (titleSize > maxTitleSize) { + decodedTitle.resize(maxTitleSize - 3); decodedTitle += "... "; + } else { + decodedTitle += " "; } - if (subTitleSize > 15) { - decodedSubTitle.resize(12); + if (subTitleSize > maxSubtitleSize) { + decodedSubTitle.resize(maxSubtitleSize - 3); decodedSubTitle += "..."; } - if (messageSize > 50) { - decodedMessage.resize(47); + if (messageSize > maxMessageSize) { + decodedMessage.resize(maxMessageSize - 3); decodedMessage += "..."; } + titleSize = std::min(titleSize, static_cast(decodedTitle.size())); + subTitleSize = std::min(subTitleSize, static_cast(decodedSubTitle.size())); + messageSize = std::min(messageSize, static_cast(decodedMessage.size())); + NotificationManager::Notification notif; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message + notif.message[titleSize] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 8fe8fc44e0..a79e222ae5 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -33,6 +33,11 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function lambda) override; void DebugNotification(const char* msg) const; + // Lengths of the parts of the notification, MUST ADD TO 100 + static constexpr uint8_t maxTitleSize {15}; + static constexpr uint8_t maxSubtitleSize {17}; + static constexpr uint8_t maxMessageSize {68}; + // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 static constexpr ble_uuid128_t ancsUuid { .u {.type = BLE_UUID_TYPE_128}, @@ -81,11 +86,11 @@ namespace Pinetime { }; enum class EventFlags : uint8_t { - Silent = 0x01, - Important = 0x02, - PreExisting = 0x04, - PositiveAction = 0x08, - NegativeAction = 0x10 + Silent = (1 << 0), + Important = (1 << 1), + PreExisting = (1 << 2), + PositiveAction = (1 << 3), + NegativeAction = (1 << 4) }; From 1bed73184ba1ce6bb5c0423d4dc91a1d7ca183a2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 13:06:19 -0600 Subject: [PATCH 14/74] Fixed first letter in Subtitle being cut off --- .../ble/AppleNotificationCenterClient.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index c75fee6836..d70bca4f15 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -285,11 +285,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); - if (titleSize > maxTitleSize) { + if (titleSize >= maxTitleSize) { decodedTitle.resize(maxTitleSize - 3); - decodedTitle += "... "; + decodedTitle += "..._"; } else { - decodedTitle += " "; + decodedTitle += "_"; } if (subTitleSize > maxSubtitleSize) { @@ -302,16 +302,16 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedMessage += "..."; } - titleSize = std::min(titleSize, static_cast(decodedTitle.size())); - subTitleSize = std::min(subTitleSize, static_cast(decodedSubTitle.size())); - messageSize = std::min(messageSize, static_cast(decodedMessage.size())); + titleSize = static_cast(decodedTitle.size()); + subTitleSize = static_cast(decodedSubTitle.size()); + messageSize = static_cast(decodedMessage.size()); NotificationManager::Notification notif; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - notif.message[titleSize] = '\0'; // Seperate Title and Message + notif.message[titleSize-1] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; From 670c379a047dfe9e74b6bab460962b26db19729e Mon Sep 17 00:00:00 2001 From: liamcharger Date: Thu, 2 Jan 2025 15:41:16 -0500 Subject: [PATCH 15/74] Improve message display --- src/components/ble/AppleNotificationCenterClient.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index d70bca4f15..0d85b3bbca 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -308,7 +308,13 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { NotificationManager::Notification notif; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; - std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; + std::string notifStr; + + notifStr += decodedTitle; + if (!decodedSubTitle.empty()) { + notifStr += decodedSubTitle + ": "; + } + notifStr += decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); notif.message[titleSize-1] = '\0'; // Seperate Title and Message From 5bf840646df2c10ddd141063f84439c7888136dc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 17:58:28 -0600 Subject: [PATCH 16/74] Updated notification, Title and Subtitle are in the orange test and message is in the body. --- .../ble/AppleNotificationCenterClient.cpp | 30 ++++++++++++++----- .../ble/AppleNotificationCenterClient.h | 7 ++--- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 0d85b3bbca..8917b70011 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -287,9 +287,18 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (titleSize >= maxTitleSize) { decodedTitle.resize(maxTitleSize - 3); - decodedTitle += "..._"; + decodedTitle += "..."; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } else { - decodedTitle += "_"; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } if (subTitleSize > maxSubtitleSize) { @@ -297,10 +306,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedSubTitle += "..."; } - if (messageSize > maxMessageSize) { - decodedMessage.resize(maxMessageSize - 3); - decodedMessage += "..."; - } + // if (messageSize > maxMessageSize) { + // decodedMessage.resize(maxMessageSize - 3); + // decodedMessage += "..."; + // } titleSize = static_cast(decodedTitle.size()); subTitleSize = static_cast(decodedSubTitle.size()); @@ -312,12 +321,17 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notifStr += decodedTitle; if (!decodedSubTitle.empty()) { - notifStr += decodedSubTitle + ": "; + notifStr += decodedSubTitle + ":"; } notifStr += decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - notif.message[titleSize-1] = '\0'; // Seperate Title and Message + + if (!decodedSubTitle.empty()) + notif.message[titleSize+subTitleSize] = '\0'; // Seperate Title and Message + else + notif.message[titleSize-1] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index a79e222ae5..7ae22b0510 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -33,10 +33,9 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function lambda) override; void DebugNotification(const char* msg) const; - // Lengths of the parts of the notification, MUST ADD TO 100 - static constexpr uint8_t maxTitleSize {15}; - static constexpr uint8_t maxSubtitleSize {17}; - static constexpr uint8_t maxMessageSize {68}; + 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 { From 288d1677912ff49d1d43c4ac35f9c78f533711c2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 21:32:52 -0600 Subject: [PATCH 17/74] Implemented Incoming Calls to ANCS Accepting and Declining works --- .../ble/AppleNotificationCenterClient.cpp | 144 ++++++++++++++---- .../ble/AppleNotificationCenterClient.h | 12 ++ src/components/ble/NimbleController.h | 4 + src/components/ble/NotificationManager.h | 2 + src/displayapp/DisplayApp.cpp | 2 + src/displayapp/screens/Notifications.cpp | 36 ++++- src/displayapp/screens/Notifications.h | 10 +- 7 files changed, 174 insertions(+), 36 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 8917b70011..01ec55abeb 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -207,6 +207,22 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + AncsNotitfication ancsNotif; + ancsNotif.eventId = eventId; + ancsNotif.eventFlags = eventFlags; + ancsNotif.category = category; + ancsNotif.uuid = notificationUuid; + + while (notifications.size() > 6) { + notifications.erase(notifications.begin()); + } + + if (notifications.contains(notificationUuid)) { + notifications[notificationUuid] = ancsNotif; + } else { + notifications.insert({notificationUuid, ancsNotif}); + } + if (preExisting || eventId != static_cast(EventIds::Added)) { return; } @@ -251,11 +267,20 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { uint16_t titleSize; uint16_t subTitleSize; uint16_t messageSize; + uint32_t notificationUid; + os_mbuf_copydata(event->notify_rx.om, 1, 4, ¬ificationUid); os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1, 2, &subTitleSize); os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1, 2, &messageSize); + AncsNotitfication ancsNotif; + ancsNotif.uuid = 0; + + if (notifications.contains(notificationUid)) { + ancsNotif = notifications[notificationUid]; + } + std::string decodedTitle; decodedTitle.reserve(titleSize); for (uint16_t i = 0; i < titleSize; ++i) { @@ -285,62 +310,125 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); - if (titleSize >= maxTitleSize) { - decodedTitle.resize(maxTitleSize - 3); - decodedTitle += "..."; - if (!decodedSubTitle.empty()) { - decodedTitle += " - "; + bool incomingCall = ancsNotif.uuid != 0 && ancsNotif.category == static_cast(Categories::IncomingCall); + + if (!incomingCall) { + if (titleSize >= maxTitleSize) { + decodedTitle.resize(maxTitleSize - 3); + decodedTitle += "..."; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } else { - decodedTitle += "-"; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } - } else { - if (!decodedSubTitle.empty()) { - decodedTitle += " - "; - } else { - decodedTitle += "-"; + + if (subTitleSize > maxSubtitleSize) { + decodedSubTitle.resize(maxSubtitleSize - 3); + decodedSubTitle += "..."; } - } - if (subTitleSize > maxSubtitleSize) { - decodedSubTitle.resize(maxSubtitleSize - 3); - decodedSubTitle += "..."; + // if (messageSize > maxMessageSize) { + // decodedMessage.resize(maxMessageSize - 3); + // decodedMessage += "..."; + // } } - // if (messageSize > maxMessageSize) { - // decodedMessage.resize(maxMessageSize - 3); - // decodedMessage += "..."; - // } - titleSize = static_cast(decodedTitle.size()); subTitleSize = static_cast(decodedSubTitle.size()); messageSize = static_cast(decodedMessage.size()); NotificationManager::Notification notif; + notif.ancsUid = notificationUid; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr; - notifStr += decodedTitle; - if (!decodedSubTitle.empty()) { - notifStr += decodedSubTitle + ":"; + if (incomingCall) { + notifStr += "Incoming Call:"; + notifStr += decodedTitle; + notifStr += "\n"; + notifStr += decodedSubTitle; + } else { + notifStr += decodedTitle; + if (!decodedSubTitle.empty()) { + notifStr += decodedSubTitle + ":"; + } + notifStr += decodedMessage; } - notifStr += decodedMessage; + notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - - if (!decodedSubTitle.empty()) + + if (incomingCall) + notif.message[13] = '\0'; // Seperate Title and Message + else if (!decodedSubTitle.empty()) notif.message[titleSize+subTitleSize] = '\0'; // Seperate Title and Message else notif.message[titleSize-1] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + if (incomingCall) { + notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall; + } else { + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + } notificationManager.Push(std::move(notif)); systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } +void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { + AncsNotitfication ancsNotif; + if (notifications.contains(uuid)) { + ancsNotif = notifications[uuid]; + if (ancsNotif.category != static_cast(Categories::IncomingCall)) { + return; + } + } else { + return; + } + + uint8_t value[6]; + value[0] = 0x02; // Command ID: Perform Notification Action + value[1] = (uint8_t) (uuid & 0xFF); + value[2] = (uint8_t) ((uuid >> 8) & 0xFF); + value[3] = (uint8_t) ((uuid >> 16) & 0xFF); + value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[5] = 0x00; // Action ID: Positive Action + + ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); +} + +void AppleNotificationCenterClient::RejectIncomingCall(uint32_t uuid) { + AncsNotitfication ancsNotif; + if (notifications.contains(uuid)) { + ancsNotif = notifications[uuid]; + if (ancsNotif.category != static_cast(Categories::IncomingCall)) { + return; + } + } else { + return; + } + + uint8_t value[6]; + value[0] = 0x02; // Command ID: Perform Notification Action + value[1] = (uint8_t) (uuid & 0xFF); + value[2] = (uint8_t) ((uuid >> 8) & 0xFF); + value[3] = (uint8_t) ((uuid >> 16) & 0xFF); + value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[5] = 0x01; // Action ID: Negative Action + + ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); +} + void AppleNotificationCenterClient::Reset() { ancsStartHandle = 0; ancsEndHandle = 0; @@ -364,6 +452,8 @@ void AppleNotificationCenterClient::Reset() { isControlDescriptorFound = false; isDataCharacteristicDiscovered = false; isDataDescriptorFound = false; + + notifications.clear(); } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 7ae22b0510..084ed25cc6 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -8,6 +8,7 @@ #undef max #undef min #include "components/ble/BleClient.h" +#include namespace Pinetime { @@ -33,6 +34,9 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function 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}; @@ -92,6 +96,14 @@ namespace Pinetime { NegativeAction = (1 << 4) }; + struct AncsNotitfication { + uint8_t eventId {0}; + uint8_t eventFlags {0}; + uint8_t category {0}; + uint32_t uuid {0}; + }; + + std::unordered_map notifications; uint16_t ancsStartHandle {0}; uint16_t ancsEndHandle {0}; diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index b84cd1556e..8f3a1dc3f7 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -68,6 +68,10 @@ namespace Pinetime { return anService; }; + Pinetime::Controllers::AppleNotificationCenterClient& ancs() { + return ancsClient; + }; + Pinetime::Controllers::SimpleWeatherService& weather() { return weatherService; }; diff --git a/src/components/ble/NotificationManager.h b/src/components/ble/NotificationManager.h index 189a7e1355..69e5dab357 100644 --- a/src/components/ble/NotificationManager.h +++ b/src/components/ble/NotificationManager.h @@ -34,6 +34,8 @@ namespace Pinetime { Id id = 0; bool valid = false; + uint32_t ancsUid = 0; + const char* Message() const; const char* Title() const; }; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index b1594f197c..933b919a7b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -561,6 +561,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(this, notificationManager, systemTask->nimble().alertService(), + systemTask->nimble().ancs(), motorController, *systemTask, Screens::Notifications::Modes::Normal); @@ -569,6 +570,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(this, notificationManager, systemTask->nimble().alertService(), + systemTask->nimble().ancs(), motorController, *systemTask, Screens::Notifications::Modes::Preview); diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 45f72f2e20..23edddac37 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -2,6 +2,7 @@ #include "displayapp/DisplayApp.h" #include "components/ble/MusicService.h" #include "components/ble/AlertNotificationService.h" +#include "components/ble/AppleNotificationCenterClient.h" #include "displayapp/screens/Symbols.h" #include #include "displayapp/InfiniTimeTheme.h" @@ -13,12 +14,14 @@ extern lv_font_t jetbrains_mono_bold_20; Notifications::Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode) : app {app}, notificationManager {notificationManager}, alertNotificationService {alertNotificationService}, + ancsClient {ancsClient}, motorController {motorController}, wakeLock(systemTask), mode {mode} { @@ -33,10 +36,12 @@ Notifications::Notifications(DisplayApp* app, notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + notification.ancsUid); validDisplay = true; } else { - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, ancsClient, motorController); validDisplay = false; } if (mode == Modes::Preview) { @@ -109,7 +114,9 @@ void Notifications::Refresh() { notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + notification.ancsUid); } else { running = false; } @@ -202,7 +209,9 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { previousNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + previousNotification.ancsUid); } return true; case Pinetime::Applications::TouchEvents::SwipeUp: { @@ -229,7 +238,9 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { nextNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + nextNotification.ancsUid); } return true; default: @@ -245,6 +256,7 @@ namespace { } Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController) : NotificationItem("Notification", "No notification to display", @@ -252,7 +264,9 @@ Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNo Controllers::NotificationManager::Categories::Unknown, 0, alertNotificationService, - motorController) { + ancsClient, + motorController, + 0) { } Notifications::NotificationItem::NotificationItem(const char* title, @@ -261,8 +275,12 @@ Notifications::NotificationItem::NotificationItem(const char* title, Controllers::NotificationManager::Categories category, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController) - : alertNotificationService {alertNotificationService}, motorController {motorController} { + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::MotorController& motorController, + uint32_t ancsUid) + : alertNotificationService {alertNotificationService}, ancsClient {ancsClient}, motorController {motorController} { + this->ancsUid = ancsUid; + container = lv_cont_create(lv_scr_act(), nullptr); lv_obj_set_size(container, LV_HOR_RES, LV_VER_RES); lv_obj_set_style_local_bg_color(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); @@ -360,8 +378,10 @@ void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_ if (obj == bt_accept) { alertNotificationService.AcceptIncomingCall(); + ancsClient.AcceptIncomingCall(ancsUid); } else if (obj == bt_reject) { alertNotificationService.RejectIncomingCall(); + ancsClient.RejectIncomingCall(ancsUid); } else if (obj == bt_mute) { alertNotificationService.MuteIncomingCall(); } diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 8488dc5bb2..a7e00661fa 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -24,6 +24,7 @@ namespace Pinetime { explicit Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode); @@ -38,6 +39,7 @@ namespace Pinetime { class NotificationItem { public: NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController); NotificationItem(const char* title, const char* msg, @@ -45,13 +47,17 @@ namespace Pinetime { Controllers::NotificationManager::Categories, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController); + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::MotorController& motorController, + uint32_t ancsUid); ~NotificationItem(); bool IsRunning() const { return running; } + uint32_t ancsUid = 0; + void OnCallButtonEvent(lv_obj_t*, lv_event_t event); private: @@ -64,6 +70,7 @@ namespace Pinetime { lv_obj_t* label_mute; lv_obj_t* label_reject; Pinetime::Controllers::AlertNotificationService& alertNotificationService; + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient; Pinetime::Controllers::MotorController& motorController; bool running = true; @@ -73,6 +80,7 @@ namespace Pinetime { DisplayApp* app; Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::AlertNotificationService& alertNotificationService; + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient; Pinetime::Controllers::MotorController& motorController; System::WakeLock wakeLock; Modes mode = Modes::Normal; From f370d63291ea31b49058769123b5abd04ec77d4f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 21:48:28 -0600 Subject: [PATCH 18/74] Turned off non important debugs --- src/components/ble/AppleNotificationCenterClient.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 01ec55abeb..81c3b5922f 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -79,7 +79,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn if (characteristic == nullptr && error->status == BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery complete"); - DebugNotification("ANCS Characteristic discovery complete"); + // DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isDataCharacteristicDiscovered) { @@ -105,7 +105,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn char msg[55]; snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); NRF_LOG_INFO(msg); - DebugNotification(msg); + // DebugNotification(msg); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } @@ -139,7 +139,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { if (dataSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - DebugNotification("ANCS Descriptor discovered: Data Source"); + // DebugNotification("ANCS Descriptor discovered: Data Source"); dataSourceDescriptorHandle = descriptor->handle; isDataDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -151,7 +151,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - DebugNotification(errorStr); + // DebugNotification(errorStr); } if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); @@ -181,7 +181,7 @@ int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHand char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Control Point ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - DebugNotification(errorStr); + // DebugNotification(errorStr); } return 0; } From 0ba425a57c839511e78e7865e3c67f1fce53f69f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 22:01:15 -0600 Subject: [PATCH 19/74] Formatted Code --- .../ble/AppleNotificationCenterClient.cpp | 23 ++++++++------ .../ble/AppleNotificationCenterClient.h | 31 ++++++++----------- src/displayapp/screens/Notifications.cpp | 2 +- src/displayapp/screens/Notifications.h | 2 +- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 81c3b5922f..6f166b030e 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -82,7 +82,8 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn // DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); - } if (isDataCharacteristicDiscovered) { + } + if (isDataCharacteristicDiscovered) { // DebugNotification("ANCS Characteristic discovery complete: Data Source"); ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } @@ -134,7 +135,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); // DebugNotification("ANCS Descriptor discovered"); controlPointDescriptorHandle = descriptor->handle; - isControlDescriptorFound = true; + isControlDescriptorFound = true; } } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { if (dataSourceDescriptorHandle == 0) { @@ -159,7 +160,9 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c return 0; } -int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { +int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, + const ble_gatt_error* error, + ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); DebugNotification("ANCS New alert subscribe OK"); @@ -173,7 +176,9 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, return 0; } -int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHandle*/, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { +int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHandle*/, + const ble_gatt_error* error, + ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS Control Point write OK"); // DebugNotification("ANCS Control Point write OK"); @@ -255,7 +260,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); notif.message = std::array {}; std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message + notif.message[10] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(uuidStr), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; @@ -365,13 +370,13 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - if (incomingCall) + if (incomingCall) notif.message[13] = '\0'; // Seperate Title and Message else if (!decodedSubTitle.empty()) - notif.message[titleSize+subTitleSize] = '\0'; // Seperate Title and Message + notif.message[titleSize + subTitleSize] = '\0'; // Seperate Title and Message else - notif.message[titleSize-1] = '\0'; // Seperate Title and Message - + notif.message[titleSize - 1] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); if (incomingCall) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 084ed25cc6..76e1a51a19 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -22,12 +22,15 @@ namespace Pinetime { class AppleNotificationCenterClient : public BleClient { public: explicit AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, - Pinetime::Controllers::NotificationManager& notificationManager); + 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 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(); @@ -42,27 +45,23 @@ namespace Pinetime { static constexpr uint8_t maxMessageSize {120}; // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 - static constexpr ble_uuid128_t ancsUuid { + 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} - }; + .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} - }; + 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 } - }; + .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 } - }; + .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}; @@ -82,11 +81,7 @@ namespace Pinetime { Entertainment = 11 }; - enum class EventIds : uint8_t { - Added = 0, - Modified = 1, - Removed = 2 - }; + enum class EventIds : uint8_t { Added = 0, Modified = 1, Removed = 2 }; enum class EventFlags : uint8_t { Silent = (1 << 0), diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 23edddac37..f32c37827b 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -14,7 +14,7 @@ extern lv_font_t jetbrains_mono_bold_20; Notifications::Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode) diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index a7e00661fa..18ab8e5a34 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -24,7 +24,7 @@ namespace Pinetime { explicit Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode); From 2fe3a6b413b423ae96a2115092af6987d452d7c2 Mon Sep 17 00:00:00 2001 From: liamcharger Date: Fri, 3 Jan 2025 07:31:56 -0500 Subject: [PATCH 20/74] Remove RTT settings --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3f7d182d84..8e01026411 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -834,8 +834,8 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") # NRF SDK Logging add_definitions(-DNRF_LOG_ENABLED=1) - add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) - add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) + # add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) + # add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) # NRF SDK individual modules logging # add_definitions(-DCLOCK_CONFIG_LOG_ENABLED=1) From 1e4989fed20b58f3fb5222e1ff0d10a233e96231 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 16:08:38 -0600 Subject: [PATCH 21/74] Removed more debug notifications --- .../ble/AppleNotificationCenterClient.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 6f166b030e..b380abee79 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -165,7 +165,7 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); - DebugNotification("ANCS New alert subscribe OK"); + // DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); DebugNotification("ANCS New alert subscribe ERROR"); @@ -255,18 +255,18 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); - NotificationManager::Notification notif; - char uuidStr[55]; - snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); - notif.message = std::array {}; - std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message - notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - notificationManager.Push(std::move(notif)); - - systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // NotificationManager::Notification notif; + // char uuidStr[55]; + // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); + // notif.message = std::array {}; + // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + // notif.message[10] = '\0'; // Seperate Title and Message + // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); + // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + // notificationManager.Push(std::move(notif)); + + // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); // DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; From 8ab8296bf88543014d7e8f0ace4bcb056cac02f1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 18:40:41 -0600 Subject: [PATCH 22/74] Added check for special characters and show unknown symbol. --- .../ble/AppleNotificationCenterClient.cpp | 103 ++++++++++++++---- .../ble/AppleNotificationCenterClient.h | 3 + src/displayapp/fonts/fonts.json | 2 +- 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index b380abee79..685b063647 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -286,29 +286,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ancsNotif = notifications[notificationUid]; } - std::string decodedTitle; - decodedTitle.reserve(titleSize); - for (uint16_t i = 0; i < titleSize; ++i) { - uint8_t byte; - os_mbuf_copydata(event->notify_rx.om, 8 + i, 1, &byte); - decodedTitle.push_back(static_cast(byte)); - } + std::string decodedTitle = DecodeUtf8String(event->notify_rx.om, titleSize, 8); - std::string decodedSubTitle; - decodedSubTitle.reserve(subTitleSize); - for (uint16_t i = 0; i < subTitleSize; ++i) { - uint8_t byte; - os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + i, 1, &byte); - decodedSubTitle.push_back(static_cast(byte)); - } + std::string decodedSubTitle = DecodeUtf8String(event->notify_rx.om, subTitleSize, 8 + titleSize + 1 + 2); - std::string decodedMessage; - decodedMessage.reserve(messageSize); - for (uint16_t i = 0; i < messageSize; ++i) { - uint8_t byte; - os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2 + i, 1, &byte); - decodedMessage.push_back(static_cast(byte)); - } + std::string decodedMessage = DecodeUtf8String(event->notify_rx.om, messageSize, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2); NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); @@ -479,4 +461,83 @@ void AppleNotificationCenterClient::DebugNotification(const char* msg) const { notificationManager.Push(std::move(notif)); systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); +} + +std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_t size, uint16_t offset) { + std::string decoded; + decoded.reserve(size); + + auto isInFontDefinition = [](uint32_t codepoint) -> bool { + // Check if the codepoint falls into the specified font ranges or is explicitly listed + return (codepoint >= 0x20 && codepoint <= 0x7E) || // Printable ASCII + (codepoint >= 0x410 && codepoint <= 0x44F) || // Cyrillic + codepoint == 0xB0; + }; + + for (uint16_t i = 0; i < size;) { + uint8_t byte; + if (os_mbuf_copydata(om, offset + i, 1, &byte) != 0) { + break; // Handle error in copying data (e.g., log or terminate processing) + } + + if (byte <= 0x7F) { // Single-byte UTF-8 (ASCII) + if (isInFontDefinition(byte)) { + decoded.push_back(static_cast(byte)); + } else { + decoded.append("�"); // Replace unsupported + } + ++i; + } else { // Multi-byte UTF-8 + // Determine sequence length based on leading byte + int sequenceLength = 0; + if ((byte & 0xE0) == 0xC0) + sequenceLength = 2; // 2-byte sequence + else if ((byte & 0xF0) == 0xE0) + sequenceLength = 3; // 3-byte sequence + else if ((byte & 0xF8) == 0xF0) + sequenceLength = 4; // 4-byte sequence + + if (i + sequenceLength > size) { + decoded.append("�"); // Incomplete sequence, replace + break; + } + + // Read the full sequence + std::string utf8Char; + bool validSequence = true; + uint32_t codepoint = 0; + + for (int j = 0; j < sequenceLength; ++j) { + uint8_t nextByte; + os_mbuf_copydata(om, offset + i + j, 1, &nextByte); + utf8Char.push_back(static_cast(nextByte)); + + if (j == 0) { + // Leading byte contributes significant bits + if (sequenceLength == 2) + codepoint = nextByte & 0x1F; + else if (sequenceLength == 3) + codepoint = nextByte & 0x0F; + else if (sequenceLength == 4) + codepoint = nextByte & 0x07; + } else { + // Continuation bytes contribute lower bits + if ((nextByte & 0xC0) != 0x80) { + validSequence = false; // Invalid UTF-8 continuation byte + break; + } + codepoint = (codepoint << 6) | (nextByte & 0x3F); + } + } + + if (validSequence && isInFontDefinition(codepoint)) { + decoded.append(utf8Char); // Append valid UTF-8 character + } else { + decoded.append("�"); // Replace unsupported + } + i += sequenceLength; + } + } + + return decoded; } \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 76e1a51a19..994d037c41 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -9,6 +9,7 @@ #undef min #include "components/ble/BleClient.h" #include +#include namespace Pinetime { @@ -100,6 +101,8 @@ namespace Pinetime { std::unordered_map 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}; diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 41c383c0d4..4fb418b1cb 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -3,7 +3,7 @@ "sources": [ { "file": "JetBrainsMono-Bold.ttf", - "range": "0x20-0x7e, 0x410-0x44f, 0xB0" + "range": "0x20-0x7e, 0x410-0x44f, 0xB0, 0xBF, 0xFFFD" }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", From bb48b5f10f5fcdcc189e4879d9757603dc0aafe9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 22:12:56 -0600 Subject: [PATCH 23/74] removed all debug notifications --- src/components/ble/AppleNotificationCenterClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 685b063647..8f8997ad2d 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -168,7 +168,7 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, // DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); - DebugNotification("ANCS New alert subscribe ERROR"); + // DebugNotification("ANCS New alert subscribe ERROR"); } if (isDescriptorFound == isControlDescriptorFound && isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); From c2b392b45b8c308e2ba8c36c72511e84eaeaca09 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 22:19:39 -0600 Subject: [PATCH 24/74] Ignore silent notifications --- src/components/ble/AppleNotificationCenterClient.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 8f8997ad2d..c410644828 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -206,7 +206,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); - // bool silent = eventFlags & static_cast(EventFlags::Silent); + bool silent = (eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); @@ -224,11 +224,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (notifications.contains(notificationUuid)) { notifications[notificationUuid] = ancsNotif; - } else { + } else if (!silent) { notifications.insert({notificationUuid, ancsNotif}); } - if (preExisting || eventId != static_cast(EventIds::Added)) { + if (preExisting || eventId != static_cast(EventIds::Added) || silent) { return; } From f88848362c5e3b7b3282f27c49e312273e8e5b11 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 22:22:10 -0600 Subject: [PATCH 25/74] Make trunacated messages end in "..." to indicate that message has more on iOS --- src/components/ble/AppleNotificationCenterClient.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index c410644828..41583322ec 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -349,6 +349,12 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notifStr += decodedMessage; } + // Adjust notification if too long + if (notifStr.size() > 100) { + notifStr.resize(97); + notifStr += "..."; + } + notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); From 65ead6e76bf3a7fa26d8617de7b8797c2fb75829 Mon Sep 17 00:00:00 2001 From: liamcharger Date: Thu, 16 Jan 2025 09:30:50 -0500 Subject: [PATCH 26/74] Fix typos and remove unnecessary commented code --- .../ble/AppleNotificationCenterClient.cpp | 51 +++---------------- .../ble/AppleNotificationCenterClient.h | 4 +- 2 files changed, 10 insertions(+), 45 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 41583322ec..628d3a3c87 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -46,12 +46,9 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service == nullptr && error->status == BLE_HS_EDONE) { if (isDiscovered) { NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); - // DebugNotification("ANCS Discovery found, starting characteristics discovery"); - ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); } else { NRF_LOG_INFO("ANCS not found"); - // DebugNotification("ANCS not found"); onServiceDiscovered(connectionHandle); } return true; @@ -59,7 +56,7 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); - // DebugNotification("ANCS discovered"); + ancsStartHandle = service->start_handle; ancsEndHandle = service->end_handle; isDiscovered = true; @@ -72,19 +69,16 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); - // DebugNotification("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); return 0; } if (characteristic == nullptr && error->status == BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery complete"); - // DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isDataCharacteristicDiscovered) { - // DebugNotification("ANCS Characteristic discovery complete: Data Source"); ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { @@ -94,19 +88,16 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn if (characteristic != nullptr) { if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); - // DebugNotification("ANCS Characteristic discovered: Notification Source"); notificationSourceHandle = characteristic->val_handle; isCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); - // DebugNotification("ANCS Characteristic discovered: Control Point"); controlPointHandle = characteristic->val_handle; isControlCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { char msg[55]; snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); NRF_LOG_INFO(msg); - // DebugNotification(msg); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } @@ -123,7 +114,6 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - // DebugNotification("ANCS Descriptor discovered"); notificationSourceDescriptorHandle = descriptor->handle; isDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -133,14 +123,12 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c } else if (characteristicValueHandle == controlPointHandle && ble_uuid_cmp(&controlPointChar.u, &descriptor->uuid.u)) { if (controlPointDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - // DebugNotification("ANCS Descriptor discovered"); controlPointDescriptorHandle = descriptor->handle; isControlDescriptorFound = true; } } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { if (dataSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - // DebugNotification("ANCS Descriptor discovered: Data Source"); dataSourceDescriptorHandle = descriptor->handle; isDataDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -152,7 +140,6 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - // DebugNotification(errorStr); } if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); @@ -165,10 +152,8 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); - // DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); - // DebugNotification("ANCS New alert subscribe ERROR"); } if (isDescriptorFound == isControlDescriptorFound && isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); @@ -181,12 +166,10 @@ int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHand ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS Control Point write OK"); - // DebugNotification("ANCS Control Point write OK"); } else { char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Control Point ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - // DebugNotification(errorStr); } return 0; } @@ -212,7 +195,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; ancsNotif.eventId = eventId; ancsNotif.eventFlags = eventFlags; ancsNotif.category = category; @@ -254,20 +237,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { request[13] = ((messageSize >> 8) & 0xFF); ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); - - // NotificationManager::Notification notif; - // char uuidStr[55]; - // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); - // notif.message = std::array {}; - // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - // notif.message[10] = '\0'; // Seperate Title and Message - // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - // notificationManager.Push(std::move(notif)); - - // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); - // DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; uint16_t subTitleSize; @@ -279,7 +248,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1, 2, &subTitleSize); os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1, 2, &messageSize); - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; ancsNotif.uuid = 0; if (notifications.contains(notificationUid)) { @@ -294,8 +263,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); - // DebugNotification(decodedTitle.c_str()); - // DebugNotification("ANCS Data Source received"); bool incomingCall = ancsNotif.uuid != 0 && ancsNotif.category == static_cast(Categories::IncomingCall); @@ -333,7 +300,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { NotificationManager::Notification notif; notif.ancsUid = notificationUid; - // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr; if (incomingCall) { @@ -359,11 +325,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); if (incomingCall) - notif.message[13] = '\0'; // Seperate Title and Message + notif.message[13] = '\0'; // Separate Title and Message else if (!decodedSubTitle.empty()) - notif.message[titleSize + subTitleSize] = '\0'; // Seperate Title and Message + notif.message[titleSize + subTitleSize] = '\0'; // Separate Title and Message else - notif.message[titleSize - 1] = '\0'; // Seperate Title and Message + notif.message[titleSize - 1] = '\0'; // Separate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); @@ -379,7 +345,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; if (notifications.contains(uuid)) { ancsNotif = notifications[uuid]; if (ancsNotif.category != static_cast(Categories::IncomingCall)) { @@ -401,7 +367,7 @@ void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { } void AppleNotificationCenterClient::RejectIncomingCall(uint32_t uuid) { - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; if (notifications.contains(uuid)) { ancsNotif = notifications[uuid]; if (ancsNotif.category != static_cast(Categories::IncomingCall)) { @@ -451,7 +417,6 @@ void AppleNotificationCenterClient::Reset() { void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { NRF_LOG_INFO("[ANCS] Starting discovery"); - // DebugNotification("[ANCS] Starting discovery"); this->onServiceDiscovered = onServiceDiscovered; ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); } diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 994d037c41..d33b887406 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -92,14 +92,14 @@ namespace Pinetime { NegativeAction = (1 << 4) }; - struct AncsNotitfication { + struct AncsNotification { uint8_t eventId {0}; uint8_t eventFlags {0}; uint8_t category {0}; uint32_t uuid {0}; }; - std::unordered_map notifications; + std::unordered_map notifications; std::string DecodeUtf8String(os_mbuf* om, uint16_t size, uint16_t offset); From 3669665aef0ffe8d361a2a77ef1146cb2306e6ac Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 19 May 2025 13:12:07 -0500 Subject: [PATCH 27/74] Made codebase changes based on PR Comments https://github.com/InfiniTimeOrg/InfiniTime/pull/2217/files/de63dce4ce5ef9b796013a6a9150d90b81fc3981#diff-a57dcf730dd40f33f9081712a57f33d39d6a73096f630df41deb58f5032e1870 --- .../ble/AppleNotificationCenterClient.cpp | 129 ++++++++---------- .../ble/AppleNotificationCenterClient.h | 14 +- .../ble/BatteryInformationService.cpp | 2 +- src/components/ble/NimbleController.cpp | 3 +- src/displayapp/fonts/fonts.json | 2 +- 5 files changed, 70 insertions(+), 80 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 628d3a3c87..f5a82ce7d9 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -1,7 +1,7 @@ #include "components/ble/AppleNotificationCenterClient.h" -#include #include "components/ble/NotificationManager.h" #include "systemtask/SystemTask.h" +#include using namespace Pinetime::Controllers; @@ -84,8 +84,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { onServiceDiscovered(connectionHandle); } - } else { - if (characteristic != nullptr) { + } else if (characteristic != nullptr) { if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); notificationSourceHandle = characteristic->val_handle; @@ -95,13 +94,10 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn controlPointHandle = characteristic->val_handle; isControlCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { - char msg[55]; - snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); - NRF_LOG_INFO(msg); + NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } - } } return 0; } @@ -177,64 +173,58 @@ int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHand void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (event->notify_rx.attr_handle == notificationSourceHandle || event->notify_rx.attr_handle == notificationSourceDescriptorHandle) { NRF_LOG_INFO("ANCS Notification received"); - uint8_t eventId; - uint8_t eventFlags; - uint8_t category; - uint8_t categoryCount; - uint32_t notificationUuid; - - os_mbuf_copydata(event->notify_rx.om, 0, 1, &eventId); - os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlags); - os_mbuf_copydata(event->notify_rx.om, 2, 1, &category); - os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); - os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); - - bool silent = (eventFlags & static_cast(EventFlags::Silent)) != 0; + + AncsNotification ancsNotif; + + os_mbuf_copydata(event->notify_rx.om, 0, 1, &ancsNotif.eventId); + os_mbuf_copydata(event->notify_rx.om, 1, 1, &ancsNotif.eventFlags); + os_mbuf_copydata(event->notify_rx.om, 2, 1, &ancsNotif.category); + // Can be used to see how many grouped notifications are present + // os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); + os_mbuf_copydata(event->notify_rx.om, 4, 4, &ancsNotif.uuid); + + bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) != 0; + bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - AncsNotification ancsNotif; - ancsNotif.eventId = eventId; - ancsNotif.eventFlags = eventFlags; - ancsNotif.category = category; - ancsNotif.uuid = notificationUuid; - + // The 6 is from TotalNbNotifications in NotificationManager.h + 1 while (notifications.size() > 6) { notifications.erase(notifications.begin()); } - if (notifications.contains(notificationUuid)) { - notifications[notificationUuid] = ancsNotif; + if (notifications.contains(ancsNotif.uuid)) { + notifications[ancsNotif.uuid] = ancsNotif; } else if (!silent) { - notifications.insert({notificationUuid, ancsNotif}); + notifications.insert({ancsNotif.uuid, ancsNotif}); } - if (preExisting || eventId != static_cast(EventIds::Added) || silent) { + if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added) || silent) { return; } // Request ANCS more info + // The +4 is for the "..." at the end of the string uint8_t titleSize = maxTitleSize + 4; uint8_t subTitleSize = maxSubtitleSize + 4; uint8_t messageSize = maxMessageSize + 4; BYTE request[14]; request[0] = 0x00; // Command ID: Get Notification Attributes - request[1] = (uint8_t) (notificationUuid & 0xFF); - request[2] = (uint8_t) ((notificationUuid >> 8) & 0xFF); - request[3] = (uint8_t) ((notificationUuid >> 16) & 0xFF); - request[4] = (uint8_t) ((notificationUuid >> 24) & 0xFF); + request[1] = static_cast(ancsNotif.uuid & 0xFF); + request[2] = static_cast((ancsNotif.uuid >> 8) & 0xFF); + request[3] = static_cast((ancsNotif.uuid >> 16) & 0xFF); + request[4] = static_cast((ancsNotif.uuid >> 24) & 0xFF); request[5] = 0x01; // Attribute ID: Title // request[6] = 0x00; - request[6] = (titleSize & 0xFF); - request[7] = ((titleSize >> 8) & 0xFF); + request[6] = static_cast(titleSize & 0xFF); + request[7] = static_cast((titleSize >> 8) & 0xFF); request[8] = 0x02; // Attribute ID: Subtitle - request[9] = (subTitleSize & 0xFF); - request[10] = ((subTitleSize >> 8) & 0xFF); + request[9] = static_cast(subTitleSize & 0xFF); + request[10] = static_cast((subTitleSize >> 8) & 0xFF); request[11] = 0x03; // Attribute ID: Message - request[12] = (messageSize & 0xFF); - request[13] = ((messageSize >> 8) & 0xFF); + request[12] = static_cast(messageSize & 0xFF); + request[13] = static_cast((messageSize >> 8) & 0xFF); ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { @@ -287,11 +277,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedSubTitle.resize(maxSubtitleSize - 3); decodedSubTitle += "..."; } - - // if (messageSize > maxMessageSize) { - // decodedMessage.resize(maxMessageSize - 3); - // decodedMessage += "..."; - // } } titleSize = static_cast(decodedTitle.size()); @@ -316,20 +301,21 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // Adjust notification if too long - if (notifStr.size() > 100) { + if (notifStr.size() > NotificationManager::MessageSize) { notifStr.resize(97); notifStr += "..."; } - notif.message = std::array {}; + notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - if (incomingCall) + if (incomingCall) { notif.message[13] = '\0'; // Separate Title and Message - else if (!decodedSubTitle.empty()) + } else if (!decodedSubTitle.empty()) { notif.message[titleSize + subTitleSize] = '\0'; // Separate Title and Message - else + } else { notif.message[titleSize - 1] = '\0'; // Separate Title and Message + } notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); @@ -345,9 +331,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { - AncsNotification ancsNotif; if (notifications.contains(uuid)) { - ancsNotif = notifications[uuid]; + const AncsNotification ancsNotif = notifications[uuid]; if (ancsNotif.category != static_cast(Categories::IncomingCall)) { return; } @@ -357,10 +342,10 @@ void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { uint8_t value[6]; value[0] = 0x02; // Command ID: Perform Notification Action - value[1] = (uint8_t) (uuid & 0xFF); - value[2] = (uint8_t) ((uuid >> 8) & 0xFF); - value[3] = (uint8_t) ((uuid >> 16) & 0xFF); - value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[1] = static_cast((uuid & 0xFF)); + value[2] = static_cast((uuid >> 8) & 0xFF); + value[3] = static_cast((uuid >> 16) & 0xFF); + value[4] = static_cast((uuid >> 24) & 0xFF); value[5] = 0x00; // Action ID: Positive Action ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); @@ -379,10 +364,10 @@ void AppleNotificationCenterClient::RejectIncomingCall(uint32_t uuid) { uint8_t value[6]; value[0] = 0x02; // Command ID: Perform Notification Action - value[1] = (uint8_t) (uuid & 0xFF); - value[2] = (uint8_t) ((uuid >> 8) & 0xFF); - value[3] = (uint8_t) ((uuid >> 16) & 0xFF); - value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[1] = static_cast(uuid & 0xFF); + value[2] = static_cast((uuid >> 8) & 0xFF); + value[3] = static_cast((uuid >> 16) & 0xFF); + value[4] = static_cast((uuid >> 24) & 0xFF); value[5] = 0x01; // Action ID: Negative Action ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); @@ -421,6 +406,8 @@ void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::fun ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); } +// This function is used for debugging purposes to log a message and push a notification +// Used to test BLE debugging on production devices void AppleNotificationCenterClient::DebugNotification(const char* msg) const { NRF_LOG_INFO("[ANCS DEBUG] %s", msg); @@ -446,7 +433,7 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ }; for (uint16_t i = 0; i < size;) { - uint8_t byte; + uint8_t byte = 0; if (os_mbuf_copydata(om, offset + i, 1, &byte) != 0) { break; // Handle error in copying data (e.g., log or terminate processing) } @@ -461,12 +448,13 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ } else { // Multi-byte UTF-8 // Determine sequence length based on leading byte int sequenceLength = 0; - if ((byte & 0xE0) == 0xC0) + if ((byte & 0xE0) == 0xC0) { sequenceLength = 2; // 2-byte sequence - else if ((byte & 0xF0) == 0xE0) + } else if ((byte & 0xF0) == 0xE0) { sequenceLength = 3; // 3-byte sequence - else if ((byte & 0xF8) == 0xF0) + } else if ((byte & 0xF8) == 0xF0) { sequenceLength = 4; // 4-byte sequence + } if (i + sequenceLength > size) { decoded.append("�"); // Incomplete sequence, replace @@ -479,18 +467,19 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ uint32_t codepoint = 0; for (int j = 0; j < sequenceLength; ++j) { - uint8_t nextByte; + uint8_t nextByte = 0; os_mbuf_copydata(om, offset + i + j, 1, &nextByte); utf8Char.push_back(static_cast(nextByte)); if (j == 0) { // Leading byte contributes significant bits - if (sequenceLength == 2) + if (sequenceLength == 2) { codepoint = nextByte & 0x1F; - else if (sequenceLength == 3) + } else if (sequenceLength == 3) { codepoint = nextByte & 0x0F; - else if (sequenceLength == 4) + } else if (sequenceLength == 4) { codepoint = nextByte & 0x07; + } } else { // Continuation bytes contribute lower bits if ((nextByte & 0xC0) != 0x80) { @@ -511,4 +500,4 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ } return decoded; -} \ No newline at end of file +} diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index d33b887406..fd0bd9a2f3 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -45,6 +45,8 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; + // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html + // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 static constexpr ble_uuid128_t ancsUuid { .u {.type = BLE_UUID_TYPE_128}, @@ -52,20 +54,20 @@ namespace Pinetime { private: // 9FBF120D-6301-42D9-8C58-25E699A21DBD - const ble_uuid128_t notificationSourceChar { + static constexpr 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 { + static constexpr 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 { + static constexpr 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}; + static constexpr ble_uuid16_t gattServiceUuid = {BLE_UUID_TYPE_16, 0x1801}; + static constexpr ble_uuid16_t serviceChangedCharUuid = {BLE_UUID_TYPE_16, 0x2A05}; enum class Categories : uint8_t { Other = 0, @@ -131,4 +133,4 @@ namespace Pinetime { std::function onServiceDiscovered; }; } -} \ No newline at end of file +} diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index db7c856622..e776526661 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 223a4e37d7..a7dfce4f9e 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -163,7 +163,6 @@ void NimbleController::StartAdvertising() { fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; const ble_uuid128_t uuids128[2] = {DfuService::serviceUuid, AppleNotificationCenterClient::ancsUuid}; - // fields.uuids128 = &DfuService::serviceUuid; fields.uuids128 = uuids128; fields.num_uuids128 = 2; fields.uuids128_is_complete = 1; @@ -213,7 +212,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); + // ble_gap_security_initiate(event->connect.conn_handle); } break; diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 8d1140aa7c..2c9a90591d 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -3,7 +3,7 @@ "sources": [ { "file": "JetBrainsMono-Bold.ttf", - "range": "0x20-0x7e, 0x410-0x44f, 0xB0, 0xBF, 0xFFFD" + "range": "0x20-0x7e, 0x410-0x44f, 0xB0, 0xFFFD" }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", From f47c921aa1f9615d7a0319c3a12265044199f90d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 18:02:00 -0500 Subject: [PATCH 28/74] Added security initiate back for ancs to work. --- src/components/ble/NimbleController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index a7dfce4f9e..b40fe7a3c0 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -212,7 +212,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); + ble_gap_security_initiate(event->connect.conn_handle); } break; From 8cb0ec4d87ccae5e1393139a5da8d90c5cb8e209 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 18:12:49 -0500 Subject: [PATCH 29/74] Updated checks to prevent duplicate notification triggers, NEEDS testing but not issues so far. --- .../ble/AppleNotificationCenterClient.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index f5a82ce7d9..f2f5b8c232 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -183,12 +183,17 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, &ancsNotif.uuid); - bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; + //bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list + if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added)) { + return; + } + // The 6 is from TotalNbNotifications in NotificationManager.h + 1 while (notifications.size() > 6) { notifications.erase(notifications.begin()); @@ -196,14 +201,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (notifications.contains(ancsNotif.uuid)) { notifications[ancsNotif.uuid] = ancsNotif; - } else if (!silent) { + } else { notifications.insert({ancsNotif.uuid, ancsNotif}); } - if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added) || silent) { - return; - } - // Request ANCS more info // The +4 is for the "..." at the end of the string uint8_t titleSize = maxTitleSize + 4; @@ -326,7 +327,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } notificationManager.Push(std::move(notif)); - systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // Only ping the system task if the notification was added + if (ancsNotif.eventId == static_cast(EventIds::Added)) { + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + } } } From 1937e7eefc8588e302eda076f4dfd671fad63dc8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 22:00:34 -0500 Subject: [PATCH 30/74] Check for silent before ringing notification --- src/components/ble/AppleNotificationCenterClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index f2f5b8c232..5a7987b399 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -328,7 +328,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notificationManager.Push(std::move(notif)); // Only ping the system task if the notification was added - if (ancsNotif.eventId == static_cast(EventIds::Added)) { + if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } From 1d1789902be5c0b716124e47313614c4b42eb299 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 22:14:33 -0500 Subject: [PATCH 31/74] Fix typo in ping check --- src/components/ble/AppleNotificationCenterClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 5a7987b399..02cb75b8cc 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -328,7 +328,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notificationManager.Push(std::move(notif)); // Only ping the system task if the notification was added - if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0) { + if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } From 345095689d8cfa15f4da21c1533c282d9b23d983 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 21:44:17 -0500 Subject: [PATCH 32/74] ignore notifications not in list --- src/components/ble/AppleNotificationCenterClient.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 02cb75b8cc..2793976814 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -244,6 +244,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (notifications.contains(notificationUid)) { ancsNotif = notifications[notificationUid]; + } else { + // If the Notification source didn't add it earlier, then don't process it + NRF_LOG_INFO("Notification with UID %d not found in notifications map, ignoring datasource", notificationUid); + return; } std::string decodedTitle = DecodeUtf8String(event->notify_rx.om, titleSize, 8); From 9c919d3ec5154d65317d3b8311711d53ae371f28 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 22:17:11 -0500 Subject: [PATCH 33/74] Added a session uuid cache to try to help with duplicate pings --- .../ble/AppleNotificationCenterClient.cpp | 39 ++++++++++++++++++- .../ble/AppleNotificationCenterClient.h | 6 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 2793976814..e4240d5d3d 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -185,12 +185,31 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { //bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; + //bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + // If notification was removed, we remove it from the notifications map + if (ancsNotif.eventId == static_cast(EventIds::Removed) && sessionNotificationUids.contains(ancsNotif.uuid)) { + sessionNotificationUids.erase(ancsNotif.uuid); + if (notifications.contains(ancsNotif.uuid)) { + notifications.erase(ancsNotif.uuid); + } + NRF_LOG_INFO("ANCS Notification removed: %d", ancsNotif.uuid); + return; + } + // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list - if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added)) { + if (sessionNotificationUids.contains(ancsNotif.uuid)) { + return; + } + + // If new notification, add it to the sessionNotificationUids + if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { + sessionNotificationUids.insert({ancsNotif.uuid, false}); + } else { + // If the notification is not added, we ignore it + NRF_LOG_INFO("ANCS Notification not added, ignoring: %d", ancsNotif.uuid); return; } @@ -242,6 +261,19 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { AncsNotification ancsNotif; ancsNotif.uuid = 0; + // Check if the notification is in the session + if (sessionNotificationUids.contains(notificationUid)) { + if (sessionNotificationUids[notificationUid]) { + // If the notification is already processed, we ignore it + NRF_LOG_INFO("Notification with UID %d already processed, ignoring", notificationUid); + return; + } + } else { + // If the notification is not in the session, we ignore it + NRF_LOG_INFO("Notification with UID %d not found in session, ignoring", notificationUid); + return; + } + if (notifications.contains(notificationUid)) { ancsNotif = notifications[notificationUid]; } else { @@ -331,6 +363,9 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } notificationManager.Push(std::move(notif)); + // Mark the notification as processed in the session + sessionNotificationUids[notificationUid] = true; + // Only ping the system task if the notification was added if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index fd0bd9a2f3..6ecbe2ba59 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -45,6 +45,12 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; + // Keep track of the ANCS UUIDs in array for this session to avoid re-pings for old notifications + // Keep track of max notifications UUIDs at most + static constexpr uint8_t maxNotifications {200}; + // make this unordered map have a boolean attached to see if data has been received for this notification + std::unordered_map sessionNotificationUids {}; + // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 From e549e897cd9f3659b40bb74eaeb6d6e425a0bd7c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 22:18:45 -0500 Subject: [PATCH 34/74] clear session uids on reset --- src/components/ble/AppleNotificationCenterClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index e4240d5d3d..c190285e74 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -441,6 +441,7 @@ void AppleNotificationCenterClient::Reset() { isDataDescriptorFound = false; notifications.clear(); + sessionNotificationUids.clear(); } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { From a693cfffb8fb628cef41d446060e8dc586ac9a6e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 18 Jul 2025 12:20:16 -0500 Subject: [PATCH 35/74] removed extra array --- .../ble/AppleNotificationCenterClient.cpp | 46 ++++++++++--------- .../ble/AppleNotificationCenterClient.h | 7 +-- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index c190285e74..3ff0e96ab1 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -190,23 +190,22 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); // If notification was removed, we remove it from the notifications map - if (ancsNotif.eventId == static_cast(EventIds::Removed) && sessionNotificationUids.contains(ancsNotif.uuid)) { - sessionNotificationUids.erase(ancsNotif.uuid); - if (notifications.contains(ancsNotif.uuid)) { - notifications.erase(ancsNotif.uuid); - } + if (ancsNotif.eventId == static_cast(EventIds::Removed) && notifications.contains(ancsNotif.uuid)) { + notifications.erase(ancsNotif.uuid); NRF_LOG_INFO("ANCS Notification removed: %d", ancsNotif.uuid); return; } // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list - if (sessionNotificationUids.contains(ancsNotif.uuid)) { + if (notifications.contains(ancsNotif.uuid) || + (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0 || + (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0) { return; } - // If new notification, add it to the sessionNotificationUids + // If new notification, add it to the notifications if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { - sessionNotificationUids.insert({ancsNotif.uuid, false}); + notifications.insert({ancsNotif.uuid, ancsNotif}); } else { // If the notification is not added, we ignore it NRF_LOG_INFO("ANCS Notification not added, ignoring: %d", ancsNotif.uuid); @@ -214,15 +213,15 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // The 6 is from TotalNbNotifications in NotificationManager.h + 1 - while (notifications.size() > 6) { + while (notifications.size() > 100) { notifications.erase(notifications.begin()); } - if (notifications.contains(ancsNotif.uuid)) { - notifications[ancsNotif.uuid] = ancsNotif; - } else { - notifications.insert({ancsNotif.uuid, ancsNotif}); - } + // if (notifications.contains(ancsNotif.uuid)) { + // notifications[ancsNotif.uuid] = ancsNotif; + // } else { + // notifications.insert({ancsNotif.uuid, ancsNotif}); + // } // Request ANCS more info // The +4 is for the "..." at the end of the string @@ -262,8 +261,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ancsNotif.uuid = 0; // Check if the notification is in the session - if (sessionNotificationUids.contains(notificationUid)) { - if (sessionNotificationUids[notificationUid]) { + if (notifications.contains(notificationUid)) { + if (notifications[notificationUid].isProcessed) { // If the notification is already processed, we ignore it NRF_LOG_INFO("Notification with UID %d already processed, ignoring", notificationUid); return; @@ -288,6 +287,9 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { std::string decodedMessage = DecodeUtf8String(event->notify_rx.om, messageSize, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2); + //Debug event ids ands flags by putting them at front of message (in int format) + //decodedMessage = std::to_string(ancsNotif.uuid) + " " + decodedMessage; + NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); @@ -363,13 +365,14 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } notificationManager.Push(std::move(notif)); - // Mark the notification as processed in the session - sessionNotificationUids[notificationUid] = true; - - // Only ping the system task if the notification was added - if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { + // Only ping the system task if the notification was added and ignore pre-existing notifications + if (ancsNotif.isProcessed == false && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0 && + (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) == 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } + + // Mark the notification as processed in the session + notifications[notificationUid].isProcessed = true; } } @@ -441,7 +444,6 @@ void AppleNotificationCenterClient::Reset() { isDataDescriptorFound = false; notifications.clear(); - sessionNotificationUids.clear(); } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 6ecbe2ba59..d6264efe75 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -45,12 +45,6 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; - // Keep track of the ANCS UUIDs in array for this session to avoid re-pings for old notifications - // Keep track of max notifications UUIDs at most - static constexpr uint8_t maxNotifications {200}; - // make this unordered map have a boolean attached to see if data has been received for this notification - std::unordered_map sessionNotificationUids {}; - // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 @@ -105,6 +99,7 @@ namespace Pinetime { uint8_t eventFlags {0}; uint8_t category {0}; uint32_t uuid {0}; + bool isProcessed {false}; }; std::unordered_map notifications; From 6c89b7901283690422f4d867a96ca18f752826df Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Sat, 27 Sep 2025 12:22:16 +0200 Subject: [PATCH 36/74] add new helper method --- .../ble/AppleNotificationCenterClient.cpp | 63 ++++++++++--------- .../ble/AppleNotificationCenterClient.h | 4 +- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 3ff0e96ab1..824ec5dbd5 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -49,7 +49,7 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); } else { NRF_LOG_INFO("ANCS not found"); - onServiceDiscovered(connectionHandle); + MaybeFinishDiscovery(connectionHandle); } return true; } @@ -69,7 +69,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); - onServiceDiscovered(connectionHandle); + MaybeFinishDiscovery(connectionHandle); return 0; } @@ -82,22 +82,22 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { - onServiceDiscovered(connectionHandle); + MaybeFinishDiscovery(connectionHandle); } } else if (characteristic != nullptr) { - if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); - notificationSourceHandle = characteristic->val_handle; - isCharacteristicDiscovered = true; - } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); - controlPointHandle = characteristic->val_handle; - isControlCharacteristicDiscovered = true; - } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); - dataSourceHandle = characteristic->val_handle; - isDataCharacteristicDiscovered = true; - } + if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + notificationSourceHandle = characteristic->val_handle; + isCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); + controlPointHandle = characteristic->val_handle; + isControlCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); + dataSourceHandle = characteristic->val_handle; + isDataCharacteristicDiscovered = true; + } } return 0; } @@ -138,7 +138,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c NRF_LOG_INFO(errorStr); } if (isDescriptorFound == isDataDescriptorFound) - onServiceDiscovered(connectionHandle); + MaybeFinishDiscovery(connectionHandle); } return 0; } @@ -152,7 +152,7 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, NRF_LOG_INFO("ANCS New alert subscribe ERROR"); } if (isDescriptorFound == isControlDescriptorFound && isDescriptorFound == isDataDescriptorFound) - onServiceDiscovered(connectionHandle); + MaybeFinishDiscovery(connectionHandle); return 0; } @@ -170,6 +170,13 @@ int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHand return 0; } +void AppleNotificationCenterClient::MaybeFinishDiscovery(uint16_t connectionHandle) { + if (isCharacteristicDiscovered && isControlCharacteristicDiscovered && isDataCharacteristicDiscovered && isDescriptorFound && + isControlDescriptorFound && isDataDescriptorFound && subscriptionsDone) { + onServiceDiscovered(connectionHandle); + } +} + void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (event->notify_rx.attr_handle == notificationSourceHandle || event->notify_rx.attr_handle == notificationSourceDescriptorHandle) { NRF_LOG_INFO("ANCS Notification received"); @@ -183,11 +190,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, &ancsNotif.uuid); - //bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; - // bool important = eventFlags & static_cast(EventFlags::Important); - //bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; - // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); - // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + // bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; + // bool important = eventFlags & static_cast(EventFlags::Important); + // bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; + // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); + // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); // If notification was removed, we remove it from the notifications map if (ancsNotif.eventId == static_cast(EventIds::Removed) && notifications.contains(ancsNotif.uuid)) { @@ -197,14 +204,14 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list - if (notifications.contains(ancsNotif.uuid) || - (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0 || + if (notifications.contains(ancsNotif.uuid) || (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0 || (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0) { return; } // If new notification, add it to the notifications - if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { + if (ancsNotif.eventId == static_cast(EventIds::Added) && + (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { notifications.insert({ancsNotif.uuid, ancsNotif}); } else { // If the notification is not added, we ignore it @@ -287,8 +294,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { std::string decodedMessage = DecodeUtf8String(event->notify_rx.om, messageSize, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2); - //Debug event ids ands flags by putting them at front of message (in int format) - //decodedMessage = std::to_string(ancsNotif.uuid) + " " + decodedMessage; + // Debug event ids ands flags by putting them at front of message (in int format) + // decodedMessage = std::to_string(ancsNotif.uuid) + " " + decodedMessage; NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index d6264efe75..c91dfe6fa1 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -33,6 +33,7 @@ namespace Pinetime { uint16_t characteristicValueHandle, const ble_gatt_dsc* descriptor); int OnControlPointWrite(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute); + void MaybeFinishDiscovery(uint16_t connectionHandle); void OnNotification(ble_gap_event* event); void Reset(); void Discover(uint16_t connectionHandle, std::function lambda) override; @@ -45,7 +46,8 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; - // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html + // The Apple Notification Center Service UUID are from + // https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 static constexpr ble_uuid128_t ancsUuid { From d7450496fe224fc347a14b908aa095d3304e5f77 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Sat, 27 Sep 2025 12:23:44 +0200 Subject: [PATCH 37/74] add another condition for connecting --- src/components/ble/AppleNotificationCenterClient.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 824ec5dbd5..f7e200e9ce 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -148,6 +148,11 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); + + // Mark subscriptions complete only after both CCCDs are known + if (notificationSourceDescriptorHandle != 0 && dataSourceDescriptorHandle != 0) { + subscriptionsDone = true; + } } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); } @@ -449,6 +454,7 @@ void AppleNotificationCenterClient::Reset() { isControlDescriptorFound = false; isDataCharacteristicDiscovered = false; isDataDescriptorFound = false; + subscriptionsDone = false; notifications.clear(); } From 34a6850ece70d55be277e3d2cf8df0e47535333e Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Sat, 27 Sep 2025 12:24:09 +0200 Subject: [PATCH 38/74] add in header as well --- src/components/ble/AppleNotificationCenterClient.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index c91dfe6fa1..a3a3a5342e 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -108,6 +108,8 @@ namespace Pinetime { std::string DecodeUtf8String(os_mbuf* om, uint16_t size, uint16_t offset); + bool subscriptionsDone = false; + uint16_t ancsStartHandle {0}; uint16_t ancsEndHandle {0}; uint16_t notificationSourceHandle {0}; From 791a483446262cae282316e37eeed3384478b79e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 18 Dec 2024 20:15:01 -0600 Subject: [PATCH 39/74] Started working on ANCS --- src/CMakeLists.txt | 3 + src/components/ble/ANCSService.cpp | 83 +++++++++++++++++++ src/components/ble/ANCSService.h | 62 ++++++++++++++ .../ble/BatteryInformationService.cpp | 2 +- src/components/ble/NimbleController.cpp | 2 + src/components/ble/NimbleController.h | 6 ++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 src/components/ble/ANCSService.cpp create mode 100644 src/components/ble/ANCSService.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dbbdb010a0..7de9339224 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -461,6 +461,7 @@ list(APPEND SOURCE_FILES components/ble/SimpleWeatherService.cpp components/ble/NavigationService.cpp components/ble/BatteryInformationService.cpp + components/ble/ANCSService.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -531,6 +532,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/MusicService.cpp components/ble/SimpleWeatherService.cpp components/ble/BatteryInformationService.cpp + components/ble/ANCSService.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -648,6 +650,7 @@ set(INCLUDE_FILES components/ble/DeviceInformationService.h components/ble/CurrentTimeClient.h components/ble/AlertNotificationClient.h + components/ble/ANCSService.h components/ble/DfuService.h components/firmwarevalidator/FirmwareValidator.h components/ble/BatteryInformationService.h diff --git a/src/components/ble/ANCSService.cpp b/src/components/ble/ANCSService.cpp new file mode 100644 index 0000000000..24bea775d9 --- /dev/null +++ b/src/components/ble/ANCSService.cpp @@ -0,0 +1,83 @@ +#include "components/ble/ANCSService.h" +#include +#include +#include +#include "components/ble/NotificationManager.h" +#include "systemtask/SystemTask.h" + +using namespace Pinetime::Controllers; + +constexpr ble_uuid128_t ANCSService::notificationSourceCharUuid; +constexpr ble_uuid128_t ANCSService::ancsBaseUuid; + +int NotifSourceCallback(uint16_t /*conn_handle*/, uint16_t /*attr_handle*/, struct ble_gatt_access_ctxt* ctxt, void* arg) { + auto anService = static_cast(arg); + return anService->OnAlert(ctxt); +} + +void ANCSService::Init() { + int res; + res = ble_gatts_count_cfg(serviceDefinition); + ASSERT(res == 0); + + res = ble_gatts_add_svcs(serviceDefinition); + ASSERT(res == 0); +} + +ANCSService::ANCSService(System::SystemTask& systemTask, NotificationManager& notificationManager) + : characteristicDefinition {{.uuid = ¬ificationSourceCharUuid.u, + .access_cb = NotifSourceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_NOTIFY, + .val_handle = &eventHandle}, + {0}}, + serviceDefinition { + {/* Device Information Service */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &ancsBaseUuid.u, + .characteristics = characteristicDefinition}, + {0}, + }, + systemTask {systemTask}, + notificationManager {notificationManager} { +} + +int ANCSService::OnAlert(struct ble_gatt_access_ctxt* ctxt) { + if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + constexpr size_t stringTerminatorSize = 1; // end of string '\0' + constexpr size_t headerSize = 4; + const auto maxMessageSize {NotificationManager::MaximumMessageSize()}; + const auto maxBufferSize {maxMessageSize + headerSize}; + + // Ignore notifications with empty message + const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); + if (packetLen <= headerSize) { + return 0; + } + + size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize); + auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize)); + Categories category; + + NotificationManager::Notification notif; + os_mbuf_copydata(ctxt->om, headerSize, 4/*messageSize - 1*/, notif.message.data()); + os_mbuf_copydata(ctxt->om, 2, 1, &category); + notif.message[messageSize - 1] = '\0'; + notif.size = messageSize; + + // TODO convert all ANS categories to NotificationController categories + switch (category) { + case Categories::IncomingCall: + notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall; + break; + default: + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + break; + } + + auto event = Pinetime::System::Messages::OnNewNotification; + notificationManager.Push(std::move(notif)); + systemTask.PushMessage(event); + } + return 0; +} diff --git a/src/components/ble/ANCSService.h b/src/components/ble/ANCSService.h new file mode 100644 index 0000000000..1879023489 --- /dev/null +++ b/src/components/ble/ANCSService.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#define min // workaround: nimble's min/max macros conflict with libstdc++ +#define max +#include +#undef max +#undef min + +// Primary ANCS UUID: 7905F431-B5CE-4E99-A40F-4B1E122D00D0 +#define ANCS_SERVICE_UUID_BASE { 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79 } + +// Notification Source UUID: 9FBF120D-6301-42D9-8C58-25E699A21DBD +#define ANCS_NOTIFICATION_SOURCE_UUID { 0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0x8C, 0xD9, 0x42, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F } + +namespace Pinetime { + + namespace System { + class SystemTask; + } + + namespace Controllers { + class NotificationManager; + + class ANCSService { + public: + enum class Categories : uint8_t { + Other = 0, + IncomingCall = 1, + MissedCall = 2, + Voicemail = 3, + Social = 4, + Schedule = 5, + Email = 6, + News = 7, + HealthAndFitness = 8, + BuissnessAndFinance = 9, + Location = 10, + Entertainment = 11 + }; + + ANCSService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager); + void Init(); + + int OnAlert(struct ble_gatt_access_ctxt* ctxt); + + private: + + static constexpr ble_uuid128_t notificationSourceCharUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_NOTIFICATION_SOURCE_UUID}; + + static constexpr ble_uuid128_t ancsBaseUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_SERVICE_UUID_BASE}; + + struct ble_gatt_chr_def characteristicDefinition[2]; + struct ble_gatt_svc_def serviceDefinition[2]; + + Pinetime::System::SystemTask& systemTask; + NotificationManager& notificationManager; + + uint16_t eventHandle; + }; + } +} \ No newline at end of file diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index db7c856622..e776526661 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 5059007ab9..0bcc827d24 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -49,6 +49,7 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, heartRateService {*this, heartRateController}, motionService {*this, motionController}, fsService {systemTask, fs}, + ancsService {systemTask, notificationManager}, serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } @@ -97,6 +98,7 @@ void NimbleController::Init() { immediateAlertService.Init(); heartRateService.Init(); motionService.Init(); + ancsService.Init(); fsService.Init(); int rc; diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 597ef0cc34..1038f6434f 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -23,6 +23,7 @@ #include "components/ble/MotionService.h" #include "components/ble/SimpleWeatherService.h" #include "components/fs/FS.h" +#include "components/ble/ANCSService.h" namespace Pinetime { namespace Drivers { @@ -71,6 +72,10 @@ namespace Pinetime { return weatherService; }; + Pinetime::Controllers::ANCSService& ancs() { + return ancsService; + }; + uint16_t connHandle(); void NotifyBatteryLevel(uint8_t level); @@ -106,6 +111,7 @@ namespace Pinetime { HeartRateService heartRateService; MotionService motionService; FSService fsService; + ANCSService ancsService; ServiceDiscovery serviceDiscovery; uint8_t addrType; From dd9865bcb330ded1888258a2c3363021a970d6ca Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 23:35:24 -0600 Subject: [PATCH 40/74] Started working on he client, which is the correct half that needs to be implemented. --- src/CMakeLists.txt | 6 +- src/components/ble/ANCSService.cpp | 83 ----------- src/components/ble/ANCSService.h | 62 -------- .../ble/AppleNotificationCenterClient.cpp | 140 ++++++++++++++++++ .../ble/AppleNotificationCenterClient.h | 76 ++++++++++ src/components/ble/NimbleController.cpp | 8 +- src/components/ble/NimbleController.h | 8 +- src/components/ble/ServiceDiscovery.cpp | 2 +- src/components/ble/ServiceDiscovery.h | 4 +- 9 files changed, 229 insertions(+), 160 deletions(-) delete mode 100644 src/components/ble/ANCSService.cpp delete mode 100644 src/components/ble/ANCSService.h create mode 100644 src/components/ble/AppleNotificationCenterClient.cpp create mode 100644 src/components/ble/AppleNotificationCenterClient.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7de9339224..3901651143 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -461,7 +461,7 @@ list(APPEND SOURCE_FILES components/ble/SimpleWeatherService.cpp components/ble/NavigationService.cpp components/ble/BatteryInformationService.cpp - components/ble/ANCSService.cpp + components/ble/AppleNotificationCenterClient.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -532,7 +532,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/MusicService.cpp components/ble/SimpleWeatherService.cpp components/ble/BatteryInformationService.cpp - components/ble/ANCSService.cpp + components/ble/AppleNotificationCenterClient.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -650,7 +650,7 @@ set(INCLUDE_FILES components/ble/DeviceInformationService.h components/ble/CurrentTimeClient.h components/ble/AlertNotificationClient.h - components/ble/ANCSService.h + components/ble/AppleNotificationCenterClient.h components/ble/DfuService.h components/firmwarevalidator/FirmwareValidator.h components/ble/BatteryInformationService.h diff --git a/src/components/ble/ANCSService.cpp b/src/components/ble/ANCSService.cpp deleted file mode 100644 index 24bea775d9..0000000000 --- a/src/components/ble/ANCSService.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "components/ble/ANCSService.h" -#include -#include -#include -#include "components/ble/NotificationManager.h" -#include "systemtask/SystemTask.h" - -using namespace Pinetime::Controllers; - -constexpr ble_uuid128_t ANCSService::notificationSourceCharUuid; -constexpr ble_uuid128_t ANCSService::ancsBaseUuid; - -int NotifSourceCallback(uint16_t /*conn_handle*/, uint16_t /*attr_handle*/, struct ble_gatt_access_ctxt* ctxt, void* arg) { - auto anService = static_cast(arg); - return anService->OnAlert(ctxt); -} - -void ANCSService::Init() { - int res; - res = ble_gatts_count_cfg(serviceDefinition); - ASSERT(res == 0); - - res = ble_gatts_add_svcs(serviceDefinition); - ASSERT(res == 0); -} - -ANCSService::ANCSService(System::SystemTask& systemTask, NotificationManager& notificationManager) - : characteristicDefinition {{.uuid = ¬ificationSourceCharUuid.u, - .access_cb = NotifSourceCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_NOTIFY, - .val_handle = &eventHandle}, - {0}}, - serviceDefinition { - {/* Device Information Service */ - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = &ancsBaseUuid.u, - .characteristics = characteristicDefinition}, - {0}, - }, - systemTask {systemTask}, - notificationManager {notificationManager} { -} - -int ANCSService::OnAlert(struct ble_gatt_access_ctxt* ctxt) { - if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - constexpr size_t stringTerminatorSize = 1; // end of string '\0' - constexpr size_t headerSize = 4; - const auto maxMessageSize {NotificationManager::MaximumMessageSize()}; - const auto maxBufferSize {maxMessageSize + headerSize}; - - // Ignore notifications with empty message - const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); - if (packetLen <= headerSize) { - return 0; - } - - size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize); - auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize)); - Categories category; - - NotificationManager::Notification notif; - os_mbuf_copydata(ctxt->om, headerSize, 4/*messageSize - 1*/, notif.message.data()); - os_mbuf_copydata(ctxt->om, 2, 1, &category); - notif.message[messageSize - 1] = '\0'; - notif.size = messageSize; - - // TODO convert all ANS categories to NotificationController categories - switch (category) { - case Categories::IncomingCall: - notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall; - break; - default: - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - break; - } - - auto event = Pinetime::System::Messages::OnNewNotification; - notificationManager.Push(std::move(notif)); - systemTask.PushMessage(event); - } - return 0; -} diff --git a/src/components/ble/ANCSService.h b/src/components/ble/ANCSService.h deleted file mode 100644 index 1879023489..0000000000 --- a/src/components/ble/ANCSService.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include -#include -#define min // workaround: nimble's min/max macros conflict with libstdc++ -#define max -#include -#undef max -#undef min - -// Primary ANCS UUID: 7905F431-B5CE-4E99-A40F-4B1E122D00D0 -#define ANCS_SERVICE_UUID_BASE { 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79 } - -// Notification Source UUID: 9FBF120D-6301-42D9-8C58-25E699A21DBD -#define ANCS_NOTIFICATION_SOURCE_UUID { 0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0x8C, 0xD9, 0x42, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F } - -namespace Pinetime { - - namespace System { - class SystemTask; - } - - namespace Controllers { - class NotificationManager; - - class ANCSService { - public: - enum class Categories : uint8_t { - Other = 0, - IncomingCall = 1, - MissedCall = 2, - Voicemail = 3, - Social = 4, - Schedule = 5, - Email = 6, - News = 7, - HealthAndFitness = 8, - BuissnessAndFinance = 9, - Location = 10, - Entertainment = 11 - }; - - ANCSService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager); - void Init(); - - int OnAlert(struct ble_gatt_access_ctxt* ctxt); - - private: - - static constexpr ble_uuid128_t notificationSourceCharUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_NOTIFICATION_SOURCE_UUID}; - - static constexpr ble_uuid128_t ancsBaseUuid {.u {.type = BLE_UUID_TYPE_128}, .value = ANCS_SERVICE_UUID_BASE}; - - struct ble_gatt_chr_def characteristicDefinition[2]; - struct ble_gatt_svc_def serviceDefinition[2]; - - Pinetime::System::SystemTask& systemTask; - NotificationManager& notificationManager; - - uint16_t eventHandle; - }; - } -} \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp new file mode 100644 index 0000000000..7142bfdf15 --- /dev/null +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -0,0 +1,140 @@ +#include "components/ble/AppleNotificationCenterClient.h" +#include +#include "components/ble/NotificationManager.h" +#include "systemtask/SystemTask.h" + +using namespace Pinetime::Controllers; + + +int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_svc* service, void* arg) { + auto client = static_cast(arg); + return client->OnDiscoveryEvent(conn_handle, error, service); +} + +int OnANCSCharacteristicDiscoveredCallback(uint16_t conn_handle, + const struct ble_gatt_error* error, + const struct ble_gatt_chr* chr, + void* arg) { + auto client = static_cast(arg); + return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr); +} + +int OnANCSDescriptorDiscoveryEventCallback( + uint16_t conn_handle, const struct ble_gatt_error* error, uint16_t chr_val_handle, const struct ble_gatt_dsc* dsc, void* arg) { + auto client = static_cast(arg); + return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc); +} + +int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* error, struct ble_gatt_attr* attr, void* arg) { + auto client = static_cast(arg); + return client->OnNewAlertSubcribe(conn_handle, error, attr); +} + +AppleNotificationCenterClient::AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, + Pinetime::Controllers::NotificationManager& notificationManager) + : systemTask {systemTask}, notificationManager {notificationManager} { +} + +bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service) { + if (service == nullptr && error->status == BLE_HS_EDONE) { + if (isDiscovered) { + NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); + + ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); + } else { + NRF_LOG_INFO("ANCS not found"); + onServiceDiscovered(connectionHandle); + } + return true; + } + + if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { + NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); + ancsStartHandle = service->start_handle; + ancsEndHandle = service->end_handle; + isDiscovered = true; + } + return false; +} + +int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic) { + if (error->status != 0 && error->status != BLE_HS_EDONE) { + NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); + onServiceDiscovered(connectionHandle); + return 0; + } + + if (characteristic == nullptr && error->status == BLE_HS_EDONE) { + NRF_LOG_INFO("ANCS Characteristic discovery complete"); + if (isCharacteristicDiscovered) { + ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); + } else { + onServiceDiscovered(connectionHandle); + } + } else { + if (characteristic != nullptr && ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + notificationSourceHandle = characteristic->val_handle; + // notificationSourceDefHandle = characteristic->def_handle; + isCharacteristicDiscovered = true; + } + } + return 0; +} + +int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error* error, uint16_t characteristicValueHandle, const ble_gatt_dsc* descriptor) { + if (error->status == 0) { + if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { + if (notificationSourceDescriptorHandle == 0) { + NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + notificationSourceDescriptorHandle = descriptor->handle; + isDescriptorFound = true; + uint8_t value[2] {1, 0}; + ble_gattc_write_flat(connectionHandle, notificationSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); + } + } + } else { + if (!isDescriptorFound) + onServiceDiscovered(connectionHandle); + } + return 0; +} + +int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { + if (error->status == 0) { + NRF_LOG_INFO("ANCS New alert subscribe OK"); + } else { + NRF_LOG_INFO("ANCS New alert subscribe ERROR"); + } + onServiceDiscovered(connectionHandle); + + return 0; +} + +void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { + if (event->notify_rx.attr_handle == notificationSourceHandle) { + NotificationManager::Notification notif; + notif.message = std::array {"Hello\0World"}; + notif.size = 11; + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + } +} + +void AppleNotificationCenterClient::Reset() { + ancsStartHandle = 0; + ancsEndHandle = 0; + notificationSourceHandle = 0; + notificationSourceDescriptorHandle = 0; + isDiscovered = false; + isCharacteristicDiscovered = false; + isDescriptorFound = false; +} + +void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { + NRF_LOG_INFO("[ANCS] Starting discovery"); + this->onServiceDiscovered = onServiceDiscovered; + ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); +} \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h new file mode 100644 index 0000000000..ac22c96e7d --- /dev/null +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#define min // workaround: nimble's min/max macros conflict with libstdc++ +#define max +#include +#undef max +#undef min +#include "components/ble/BleClient.h" + +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); + void OnNotification(ble_gap_event* event); + void Reset(); + void Discover(uint16_t connectionHandle, std::function lambda) override; + + private: + // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 + const ble_uuid128_t ancsUuid { + {BLE_UUID_TYPE_128}, + {0xd0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0x24, 0x99, 0x0E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79} + }; + + // 9FBF120D-6301-42D9-8C58-25E699A21DBD + const ble_uuid128_t notificationSourceChar { + {BLE_UUID_TYPE_128}, + {0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0X0C, 0xD9, 0x02, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F} + }; + // 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 + const ble_uuid128_t controlPointChar { + {BLE_UUID_TYPE_128}, + {0xD9, 0xD9, 0xAA, 0xFD, 0xBD, 0x9B, 0x21, 0X18,0xA8, 0x09,0xE1, 0x45, 0xF3, 0xD8, 0xD1, 0x69 } + }; + // 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB + const ble_uuid128_t dataSourceChar { + {BLE_UUID_TYPE_128}, + {0xFB, 0x7B, 0x7C, 0xCE, 0x6A, 0xB3, 0x44, 0X3E,0xB5, 0x0B,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}; + + + 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 serviceChangedHandle {0}; + bool isDiscovered {false}; + bool isCharacteristicDiscovered {false}; + bool isDescriptorFound {false}; + Pinetime::System::SystemTask& systemTask; + Pinetime::Controllers::NotificationManager& notificationManager; + std::function onServiceDiscovered; + }; + } +} \ No newline at end of file diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 0bcc827d24..046d69be52 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -49,8 +49,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, heartRateService {*this, heartRateController}, motionService {*this, motionController}, fsService {systemTask, fs}, - ancsService {systemTask, notificationManager}, - serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { + ancsClient {systemTask, notificationManager}, + serviceDiscovery({¤tTimeClient, &alertNotificationClient, &ancsClient}) { } void nimble_on_reset(int reason) { @@ -98,7 +98,6 @@ void NimbleController::Init() { immediateAlertService.Init(); heartRateService.Init(); motionService.Init(); - ancsService.Init(); fsService.Init(); int rc; @@ -202,6 +201,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; @@ -225,6 +225,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(); @@ -372,6 +373,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { notifSize); alertNotificationClient.OnNotification(event); + ancsClient.OnNotification(event); } break; case BLE_GAP_EVENT_NOTIFY_TX: diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 1038f6434f..b84cd1556e 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -23,7 +23,7 @@ #include "components/ble/MotionService.h" #include "components/ble/SimpleWeatherService.h" #include "components/fs/FS.h" -#include "components/ble/ANCSService.h" +#include "components/ble/AppleNotificationCenterClient.h" namespace Pinetime { namespace Drivers { @@ -72,10 +72,6 @@ namespace Pinetime { return weatherService; }; - Pinetime::Controllers::ANCSService& ancs() { - return ancsService; - }; - uint16_t connHandle(); void NotifyBatteryLevel(uint8_t level); @@ -111,7 +107,7 @@ namespace Pinetime { HeartRateService heartRateService; MotionService motionService; FSService fsService; - ANCSService ancsService; + AppleNotificationCenterClient ancsClient; ServiceDiscovery serviceDiscovery; uint8_t addrType; diff --git a/src/components/ble/ServiceDiscovery.cpp b/src/components/ble/ServiceDiscovery.cpp index 03bcfeb47b..e467c014f2 100644 --- a/src/components/ble/ServiceDiscovery.cpp +++ b/src/components/ble/ServiceDiscovery.cpp @@ -4,7 +4,7 @@ using namespace Pinetime::Controllers; -ServiceDiscovery::ServiceDiscovery(std::array&& clients) : clients {clients} { +ServiceDiscovery::ServiceDiscovery(std::array&& clients) : clients {clients} { } void ServiceDiscovery::StartDiscovery(uint16_t connectionHandle) { diff --git a/src/components/ble/ServiceDiscovery.h b/src/components/ble/ServiceDiscovery.h index fc3b38c0a6..039862a442 100644 --- a/src/components/ble/ServiceDiscovery.h +++ b/src/components/ble/ServiceDiscovery.h @@ -9,13 +9,13 @@ namespace Pinetime { class ServiceDiscovery { public: - ServiceDiscovery(std::array&& bleClients); + ServiceDiscovery(std::array&& bleClients); void StartDiscovery(uint16_t connectionHandle); private: BleClient** clientIterator; - std::array clients; + std::array clients; void OnServiceDiscovered(uint16_t connectionHandle); void DiscoverNextService(uint16_t connectionHandle); }; From dd08767e98804545f3bbe1e979905ff60795a9c6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 18:27:13 -0600 Subject: [PATCH 41/74] Formatting --- .../ble/AppleNotificationCenterClient.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 7142bfdf15..2d79a7c93b 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -5,7 +5,6 @@ using namespace Pinetime::Controllers; - int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_svc* service, void* arg) { auto client = static_cast(arg); return client->OnDiscoveryEvent(conn_handle, error, service); @@ -19,8 +18,11 @@ int OnANCSCharacteristicDiscoveredCallback(uint16_t conn_handle, return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr); } -int OnANCSDescriptorDiscoveryEventCallback( - uint16_t conn_handle, const struct ble_gatt_error* error, uint16_t chr_val_handle, const struct ble_gatt_dsc* dsc, void* arg) { +int OnANCSDescriptorDiscoveryEventCallback(uint16_t conn_handle, + const struct ble_gatt_error* error, + uint16_t chr_val_handle, + const struct ble_gatt_dsc* dsc, + void* arg) { auto client = static_cast(arg); return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc); } @@ -31,7 +33,7 @@ int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* } AppleNotificationCenterClient::AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, - Pinetime::Controllers::NotificationManager& notificationManager) + Pinetime::Controllers::NotificationManager& notificationManager) : systemTask {systemTask}, notificationManager {notificationManager} { } @@ -57,7 +59,9 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, return false; } -int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic) { +int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, + const ble_gatt_error* error, + const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); @@ -82,7 +86,10 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn return 0; } -int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error* error, uint16_t characteristicValueHandle, const ble_gatt_dsc* descriptor) { +int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, + const ble_gatt_error* error, + uint16_t characteristicValueHandle, + const ble_gatt_dsc* descriptor) { if (error->status == 0) { if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { From 07d16671c62d1aff517a92e3432536279445d1c1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 18:27:22 -0600 Subject: [PATCH 42/74] Added RTT logging --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3901651143..a93abd551c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -841,8 +841,8 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") # NRF SDK Logging add_definitions(-DNRF_LOG_ENABLED=1) - # add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) - # add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) + add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) + add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) # NRF SDK individual modules logging # add_definitions(-DCLOCK_CONFIG_LOG_ENABLED=1) From 7ea3de3a6111bbdcd9763d3d1540c07dbfd48fac Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 23 Dec 2024 22:51:58 -0600 Subject: [PATCH 43/74] Added debugging through watch notifications --- .../ble/AppleNotificationCenterClient.cpp | 23 +++++++++++++++++++ .../ble/AppleNotificationCenterClient.h | 1 + 2 files changed, 24 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 2d79a7c93b..569a301ceb 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -41,10 +41,12 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service == nullptr && error->status == BLE_HS_EDONE) { if (isDiscovered) { NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); + DebugNotification("ANCS Discovery found, starting characteristics discovery"); ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); } else { NRF_LOG_INFO("ANCS not found"); + DebugNotification("ANCS not found"); onServiceDiscovered(connectionHandle); } return true; @@ -52,6 +54,7 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); + DebugNotification("ANCS discovered"); ancsStartHandle = service->start_handle; ancsEndHandle = service->end_handle; isDiscovered = true; @@ -64,12 +67,14 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); + DebugNotification("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); return 0; } if (characteristic == nullptr && error->status == BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery complete"); + DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } else { @@ -78,6 +83,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn } else { if (characteristic != nullptr && ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + DebugNotification("ANCS Characteristic discovered: Notification Source"); notificationSourceHandle = characteristic->val_handle; // notificationSourceDefHandle = characteristic->def_handle; isCharacteristicDiscovered = true; @@ -94,6 +100,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + DebugNotification("ANCS Descriptor discovered"); notificationSourceDescriptorHandle = descriptor->handle; isDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -110,8 +117,10 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); + DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); + DebugNotification("ANCS New alert subscribe ERROR"); } onServiceDiscovered(connectionHandle); @@ -142,6 +151,20 @@ void AppleNotificationCenterClient::Reset() { void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { NRF_LOG_INFO("[ANCS] Starting discovery"); + DebugNotification("[ANCS] Starting discovery"); this->onServiceDiscovered = onServiceDiscovered; ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); +} + +void AppleNotificationCenterClient::DebugNotification(const char* msg) const { + NRF_LOG_INFO("[ANCS DEBUG] %s", msg); + + NotificationManager::Notification notif; + std::strncpy(notif.message.data(), msg, notif.message.size() - 1); + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(msg), notif.message.size()); + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index ac22c96e7d..042fa1fa62 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -30,6 +30,7 @@ namespace Pinetime { void OnNotification(ble_gap_event* event); void Reset(); void Discover(uint16_t connectionHandle, std::function lambda) override; + void DebugNotification(const char* msg) const; private: // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 From ad47ee0627557e70689d7443c14aa85d891e5c14 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 29 Dec 2024 12:40:06 -0600 Subject: [PATCH 44/74] Removed encryption of battery and added required pairing on connect GAP event --- src/components/ble/BatteryInformationService.cpp | 2 +- src/components/ble/NimbleController.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index e776526661..db7c856622 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 046d69be52..0e46415f52 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -211,6 +211,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; From f636067e57ecbc9ae6c5ad0961aa4d697b54ddc9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 29 Dec 2024 12:48:01 -0600 Subject: [PATCH 45/74] ANCS Partially works Currently, the notification UID, Event ID and Category are shown. --- .../ble/AppleNotificationCenterClient.cpp | 59 ++++++++++++++++- .../ble/AppleNotificationCenterClient.h | 66 +++++++++++++++---- src/components/ble/NimbleController.cpp | 6 +- 3 files changed, 115 insertions(+), 16 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 569a301ceb..cec1fad3c6 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -129,9 +129,49 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (event->notify_rx.attr_handle == notificationSourceHandle) { + NRF_LOG_INFO("ANCS Notification received"); + uint8_t eventId; + uint8_t eventFlag; + uint8_t category; + uint8_t categoryCount; + uint32_t notificationUuid; + + os_mbuf_copydata(event->notify_rx.om, 0, 1, &eventId); + os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlag); + os_mbuf_copydata(event->notify_rx.om, 2, 1, &category); + os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); + os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); + + if (eventId != static_cast(EventIds::Added)) { + return; + } + + // Request ANCS more info + // uint8_t request[] = { + // 0x00, // Command ID: Get Notification Attributes + // (uint8_t) (notificationUuid & 0xFF), + // (uint8_t) ((notificationUuid >> 8) & 0xFF), + // (uint8_t) ((notificationUuid >> 16) & 0xFF), + // (uint8_t) ((notificationUuid >> 24) & 0xFF), + // 0x01, + // 0x00, + // 0xFF, + // 0xFF, // Title (max length 65535) + // 0x03, + // 0x00, + // 0xFF, + // 0xFF // Message (max length 65535) + // }; + // ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), nullptr, nullptr); + NotificationManager::Notification notif; - notif.message = std::array {"Hello\0World"}; - notif.size = 11; + char uuidStr[55]; + snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); + notif.message = std::array {}; + std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + notif.message[10] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(uuidStr), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; notificationManager.Push(std::move(notif)); @@ -142,11 +182,26 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { void AppleNotificationCenterClient::Reset() { ancsStartHandle = 0; ancsEndHandle = 0; + gattStartHandle = 0; + gattEndHandle = 0; + serviceChangedHandle = 0; + serviceChangedDescriptorHandle = 0; notificationSourceHandle = 0; notificationSourceDescriptorHandle = 0; + controlPointHandle = 0; + controlPointDescriptorHandle = 0; + dataSourceHandle = 0; + dataSourceDescriptorHandle = 0; + isGattDiscovered = false; + isGattCharacteristicDiscovered = false; + isGattDescriptorFound = false; isDiscovered = false; isCharacteristicDiscovered = false; isDescriptorFound = false; + isControlCharacteristicDiscovered = false; + isControlDescriptorFound = false; + isDataCharacteristicDiscovered = false; + isDataDescriptorFound = false; } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 042fa1fa62..ea1a65f5e0 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -32,43 +32,85 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function lambda) override; void DebugNotification(const char* msg) const; - private: // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 - const ble_uuid128_t ancsUuid { - {BLE_UUID_TYPE_128}, - {0xd0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0x24, 0x99, 0x0E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79} + 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 { - {BLE_UUID_TYPE_128}, - {0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0X0C, 0xD9, 0x02, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F} + .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 { - {BLE_UUID_TYPE_128}, - {0xD9, 0xD9, 0xAA, 0xFD, 0xBD, 0x9B, 0x21, 0X18,0xA8, 0x09,0xE1, 0x45, 0xF3, 0xD8, 0xD1, 0x69 } + .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 { - {BLE_UUID_TYPE_128}, - {0xFB, 0x7B, 0x7C, 0xCE, 0x6A, 0xB3, 0x44, 0X3E,0xB5, 0x0B,0xD6, 0x24, 0xE9, 0xC6, 0xEA, 0x22 } + .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 { + 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 = 0x01, + Important = 0x02, + PreExisting = 0x04, + PositiveAction = 0x08, + NegativeAction = 0x10 + }; + uint16_t ancsStartHandle {0}; uint16_t ancsEndHandle {0}; uint16_t notificationSourceHandle {0}; - //uint16_t controlPointHandle {0}; - //uint16_t dataSourceHandle {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}; Pinetime::System::SystemTask& systemTask; Pinetime::Controllers::NotificationManager& notificationManager; std::function onServiceDiscovered; diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 0e46415f52..223a4e37d7 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -162,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}; + // fields.uuids128 = &DfuService::serviceUuid; + fields.uuids128 = uuids128; + fields.num_uuids128 = 2; fields.uuids128_is_complete = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; From c1997d58c0842f888836430019c2e56173750207 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 30 Dec 2024 17:23:45 -0600 Subject: [PATCH 46/74] Started working on using Control Point and Data Source: Data source is not working properly, the Characteristic and/or descriptor isn't being found correctly --- .../ble/AppleNotificationCenterClient.cpp | 162 +++++++++++++----- .../ble/AppleNotificationCenterClient.h | 3 +- 2 files changed, 118 insertions(+), 47 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index cec1fad3c6..3bbb65b142 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -32,6 +32,11 @@ int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* return client->OnNewAlertSubcribe(conn_handle, error, attr); } +int OnControlPointWriteCallback(uint16_t conn_handle, const struct ble_gatt_error* error, struct ble_gatt_attr* attr, void* arg) { + auto client = static_cast(arg); + return client->OnControlPointWrite(conn_handle, error, attr); +} + AppleNotificationCenterClient::AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager) : systemTask {systemTask}, notificationManager {notificationManager} { @@ -41,12 +46,12 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service == nullptr && error->status == BLE_HS_EDONE) { if (isDiscovered) { NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); - DebugNotification("ANCS Discovery found, starting characteristics discovery"); + // DebugNotification("ANCS Discovery found, starting characteristics discovery"); ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); } else { NRF_LOG_INFO("ANCS not found"); - DebugNotification("ANCS not found"); + // DebugNotification("ANCS not found"); onServiceDiscovered(connectionHandle); } return true; @@ -54,7 +59,7 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); - DebugNotification("ANCS discovered"); + // DebugNotification("ANCS discovered"); ancsStartHandle = service->start_handle; ancsEndHandle = service->end_handle; isDiscovered = true; @@ -67,7 +72,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); - DebugNotification("ANCS Characteristic discovery ERROR"); + // DebugNotification("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); return 0; } @@ -77,16 +82,31 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); - } else { + } if (isDataCharacteristicDiscovered) { + // DebugNotification("ANCS Characteristic discovery complete: Data Source"); + ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, 0xFFFF, OnANCSDescriptorDiscoveryEventCallback, this); + } + if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { onServiceDiscovered(connectionHandle); } } else { - if (characteristic != nullptr && ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); - DebugNotification("ANCS Characteristic discovered: Notification Source"); - notificationSourceHandle = characteristic->val_handle; - // notificationSourceDefHandle = characteristic->def_handle; - isCharacteristicDiscovered = true; + if (characteristic != nullptr) { + if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + // DebugNotification("ANCS Characteristic discovered: Notification Source"); + notificationSourceHandle = characteristic->val_handle; + isCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); + // DebugNotification("ANCS Characteristic discovered: Control Point"); + controlPointHandle = characteristic->val_handle; + isControlCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); + DebugNotification("ANCS Characteristic discovered: Data Source"); + dataSourceHandle = characteristic->val_handle; + isDataCharacteristicDiscovered = true; + } } } return 0; @@ -100,15 +120,35 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - DebugNotification("ANCS Descriptor discovered"); + // DebugNotification("ANCS Descriptor discovered"); notificationSourceDescriptorHandle = descriptor->handle; isDescriptorFound = true; uint8_t value[2] {1, 0}; ble_gattc_write_flat(connectionHandle, notificationSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); } + } else if (characteristicValueHandle == controlPointHandle && ble_uuid_cmp(&controlPointChar.u, &descriptor->uuid.u)) { + if (controlPointDescriptorHandle == 0) { + NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + // DebugNotification("ANCS Descriptor discovered"); + controlPointDescriptorHandle = descriptor->handle; + isControlDescriptorFound = true; + } + } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { + if (dataSourceDescriptorHandle == 0) { + NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); + DebugNotification("ANCS Descriptor discovered: Data Source"); + dataSourceDescriptorHandle = descriptor->handle; + isDataDescriptorFound = true; + uint8_t value[2] {1, 0}; + ble_gattc_write_flat(connectionHandle, dataSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); + } } } else { - if (!isDescriptorFound) + char errorStr[55]; + snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); + NRF_LOG_INFO(errorStr); + DebugNotification(errorStr); + if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); } return 0; @@ -122,60 +162,90 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, NRF_LOG_INFO("ANCS New alert subscribe ERROR"); DebugNotification("ANCS New alert subscribe ERROR"); } - onServiceDiscovered(connectionHandle); + if (isDescriptorFound == isControlDescriptorFound && isDescriptorFound == isDataDescriptorFound) + onServiceDiscovered(connectionHandle); return 0; } +int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHandle*/, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { + if (error->status == 0) { + NRF_LOG_INFO("ANCS Control Point write OK"); + // DebugNotification("ANCS Control Point write OK"); + } else { + char errorStr[55]; + snprintf(errorStr, sizeof(errorStr), "ANCS Control Point ERROR: %d", error->status); + NRF_LOG_INFO(errorStr); + DebugNotification(errorStr); + } + return 0; +} + void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { - if (event->notify_rx.attr_handle == notificationSourceHandle) { + if (event->notify_rx.attr_handle == notificationSourceHandle || event->notify_rx.attr_handle == notificationSourceDescriptorHandle) { NRF_LOG_INFO("ANCS Notification received"); uint8_t eventId; - uint8_t eventFlag; + uint8_t eventFlags; uint8_t category; uint8_t categoryCount; uint32_t notificationUuid; os_mbuf_copydata(event->notify_rx.om, 0, 1, &eventId); - os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlag); + os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlags); os_mbuf_copydata(event->notify_rx.om, 2, 1, &category); os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); - if (eventId != static_cast(EventIds::Added)) { + // bool silent = eventFlags & static_cast(EventFlags::Silent); + // bool important = eventFlags & static_cast(EventFlags::Important); + bool preExisting = eventFlags & static_cast(EventFlags::PreExisting); + // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); + // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + + if (eventId != static_cast(EventIds::Added) && preExisting != true) { return; } // Request ANCS more info - // uint8_t request[] = { - // 0x00, // Command ID: Get Notification Attributes - // (uint8_t) (notificationUuid & 0xFF), - // (uint8_t) ((notificationUuid >> 8) & 0xFF), - // (uint8_t) ((notificationUuid >> 16) & 0xFF), - // (uint8_t) ((notificationUuid >> 24) & 0xFF), - // 0x01, - // 0x00, - // 0xFF, - // 0xFF, // Title (max length 65535) - // 0x03, - // 0x00, - // 0xFF, - // 0xFF // Message (max length 65535) - // }; - // ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), nullptr, nullptr); - - NotificationManager::Notification notif; - char uuidStr[55]; - snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); - notif.message = std::array {}; - std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message - notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - notificationManager.Push(std::move(notif)); + uint8_t titleSize = 30; + BYTE request[8]; + request[0] = 0x00; // Command ID: Get Notification Attributes + request[1] = (uint8_t) (notificationUuid & 0xFF); + request[2] = (uint8_t) ((notificationUuid >> 8) & 0xFF); + request[3] = (uint8_t) ((notificationUuid >> 16) & 0xFF); + request[4] = (uint8_t) ((notificationUuid >> 24) & 0xFF); + request[5] = 0x01; + // request[6] = 0x00; + request[6] = (titleSize & 0xFF); + request[7] = ((titleSize >> 8) & 0xFF); + + ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); + + // NotificationManager::Notification notif; + // char uuidStr[55]; + // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); + // notif.message = std::array {}; + // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + // notif.message[10] = '\0'; // Seperate Title and Message + // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); + // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + // notificationManager.Push(std::move(notif)); systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { + uint16_t titleSize; + uint16_t title; + + os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); + os_mbuf_copydata(event->notify_rx.om, 8, titleSize, &title); + + // char mesgStr[90]; + // snprintf(mesgStr, sizeof(mesgStr), "ANCS Data Source received\nTitle: %d", title); + + // NRF_LOG_INFO(mesgStr); + // DebugNotification(mesgStr); + DebugNotification("ANCS Data Source received"); } } @@ -206,7 +276,7 @@ void AppleNotificationCenterClient::Reset() { void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { NRF_LOG_INFO("[ANCS] Starting discovery"); - DebugNotification("[ANCS] Starting discovery"); + // DebugNotification("[ANCS] Starting discovery"); this->onServiceDiscovered = onServiceDiscovered; ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); } diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index ea1a65f5e0..8fe8fc44e0 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -27,6 +27,7 @@ namespace Pinetime { 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 lambda) override; @@ -52,7 +53,7 @@ namespace Pinetime { // 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 } + .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}; From cf10a8b587aeaa706e14d7ed57afaecf1fa8e6bd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 30 Dec 2024 19:24:23 -0600 Subject: [PATCH 47/74] More debugging --- .../ble/AppleNotificationCenterClient.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 3bbb65b142..e12b8d1c42 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -84,7 +84,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isDataCharacteristicDiscovered) { // DebugNotification("ANCS Characteristic discovery complete: Data Source"); - ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, 0xFFFF, OnANCSDescriptorDiscoveryEventCallback, this); + ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { onServiceDiscovered(connectionHandle); @@ -102,8 +102,10 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn controlPointHandle = characteristic->val_handle; isControlCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); - DebugNotification("ANCS Characteristic discovered: Data Source"); + char msg[55]; + snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); + NRF_LOG_INFO(msg); + DebugNotification(msg); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } @@ -144,10 +146,12 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c } } } else { - char errorStr[55]; - snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); - NRF_LOG_INFO(errorStr); - DebugNotification(errorStr); + if (error->status != BLE_HS_EDONE) { + char errorStr[55]; + snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); + NRF_LOG_INFO(errorStr); + DebugNotification(errorStr); + } if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); } From 4500493b782a0d619285a297078701ed6e8e0cc6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 31 Dec 2024 00:31:54 -0600 Subject: [PATCH 48/74] Got Datsource to somewhat work and notifications now show title. Datasource seems to go off and on. --- .../ble/AppleNotificationCenterClient.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index e12b8d1c42..886f10c9c5 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -127,6 +127,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c isDescriptorFound = true; uint8_t value[2] {1, 0}; ble_gattc_write_flat(connectionHandle, notificationSourceDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this); + ble_gattc_write_flat(connectionHandle, ancsEndHandle, value, sizeof(value), NewAlertSubcribeCallback, this); } } else if (characteristicValueHandle == controlPointHandle && ble_uuid_cmp(&controlPointChar.u, &descriptor->uuid.u)) { if (controlPointDescriptorHandle == 0) { @@ -236,7 +237,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; // notificationManager.Push(std::move(notif)); - systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; uint16_t title; @@ -244,12 +246,17 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); os_mbuf_copydata(event->notify_rx.om, 8, titleSize, &title); - // char mesgStr[90]; - // snprintf(mesgStr, sizeof(mesgStr), "ANCS Data Source received\nTitle: %d", title); + std::string decodedTitle; + decodedTitle.reserve(titleSize); + for (uint16_t i = 0; i < titleSize; ++i) { + uint8_t byte; + os_mbuf_copydata(event->notify_rx.om, 8 + i, 1, &byte); + decodedTitle.push_back(static_cast(byte)); + } - // NRF_LOG_INFO(mesgStr); - // DebugNotification(mesgStr); - DebugNotification("ANCS Data Source received"); + NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); + DebugNotification(decodedTitle.c_str()); + // DebugNotification("ANCS Data Source received"); } } From 202a0bd1bd01ee93db1cc0d7380dd1f1a9f85383 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 31 Dec 2024 00:38:02 -0600 Subject: [PATCH 49/74] Fixed check to only let new notifications pass (maybe) --- src/components/ble/AppleNotificationCenterClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 886f10c9c5..70a7c04ae8 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -203,11 +203,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool silent = eventFlags & static_cast(EventFlags::Silent); // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = eventFlags & static_cast(EventFlags::PreExisting); + bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) == 1; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - if (eventId != static_cast(EventIds::Added) && preExisting != true) { + if (eventId != static_cast(EventIds::Added) || preExisting == true) { return; } From 08882adb8124d04c16488c855ede083615a35d15 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 31 Dec 2024 19:14:19 -0600 Subject: [PATCH 50/74] Proper Notification works. Need to iron out some things like characteristics disappearing and reappearing. --- .../ble/AppleNotificationCenterClient.cpp | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 70a7c04ae8..4f2ec14f64 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -207,22 +207,30 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - if (eventId != static_cast(EventIds::Added) || preExisting == true) { + if (preExisting || eventId != static_cast(EventIds::Added)) { return; } // Request ANCS more info uint8_t titleSize = 30; - BYTE request[8]; + uint8_t subTitleSize = 30; + uint8_t messageSize = 90; + BYTE request[14]; request[0] = 0x00; // Command ID: Get Notification Attributes request[1] = (uint8_t) (notificationUuid & 0xFF); request[2] = (uint8_t) ((notificationUuid >> 8) & 0xFF); request[3] = (uint8_t) ((notificationUuid >> 16) & 0xFF); request[4] = (uint8_t) ((notificationUuid >> 24) & 0xFF); - request[5] = 0x01; + request[5] = 0x01; // Attribute ID: Title // request[6] = 0x00; request[6] = (titleSize & 0xFF); request[7] = ((titleSize >> 8) & 0xFF); + request[8] = 0x02; // Attribute ID: Subtitle + request[9] = (subTitleSize & 0xFF); + request[10] = ((subTitleSize >> 8) & 0xFF); + request[11] = 0x03; // Attribute ID: Message + request[12] = (messageSize & 0xFF); + request[13] = ((messageSize >> 8) & 0xFF); ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); @@ -241,10 +249,12 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; - uint16_t title; + uint16_t subTitleSize; + uint16_t messageSize; os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); - os_mbuf_copydata(event->notify_rx.om, 8, titleSize, &title); + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1, 2, &subTitleSize); + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1, 2, &messageSize); std::string decodedTitle; decodedTitle.reserve(titleSize); @@ -254,9 +264,54 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedTitle.push_back(static_cast(byte)); } + std::string decodedSubTitle; + decodedSubTitle.reserve(subTitleSize); + for (uint16_t i = 0; i < subTitleSize; ++i) { + uint8_t byte; + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + i, 1, &byte); + decodedSubTitle.push_back(static_cast(byte)); + } + + std::string decodedMessage; + decodedMessage.reserve(messageSize); + for (uint16_t i = 0; i < messageSize; ++i) { + uint8_t byte; + os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2 + i, 1, &byte); + decodedMessage.push_back(static_cast(byte)); + } + NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); - DebugNotification(decodedTitle.c_str()); + NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); + // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); + + if (titleSize > 10) { + decodedTitle.resize(7); + decodedTitle += "... "; + } + + if (subTitleSize > 15) { + decodedSubTitle.resize(12); + decodedSubTitle += "..."; + } + + if (messageSize > 50) { + decodedMessage.resize(47); + decodedMessage += "..."; + } + + NotificationManager::Notification notif; + // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; + std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; + notif.message = std::array {}; + std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); + notif.message[10] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } From 6347ee37c374316bc6e4e8c6364ae3edf24ef4f5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 1 Jan 2025 20:57:01 -0600 Subject: [PATCH 51/74] Fixed the event flag detection. Only shows a notification when it's new. Also added constants to set lengths for the title, subtitle, and message. --- .../ble/AppleNotificationCenterClient.cpp | 54 ++++++++++--------- .../ble/AppleNotificationCenterClient.h | 15 ++++-- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 4f2ec14f64..c75fee6836 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -203,7 +203,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool silent = eventFlags & static_cast(EventFlags::Silent); // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) == 1; + bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); @@ -212,9 +212,9 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // Request ANCS more info - uint8_t titleSize = 30; - uint8_t subTitleSize = 30; - uint8_t messageSize = 90; + uint8_t titleSize = maxTitleSize + 4; + uint8_t subTitleSize = maxSubtitleSize + 4; + uint8_t messageSize = maxMessageSize + 4; BYTE request[14]; request[0] = 0x00; // Command ID: Get Notification Attributes request[1] = (uint8_t) (notificationUuid & 0xFF); @@ -234,19 +234,19 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); - // NotificationManager::Notification notif; - // char uuidStr[55]; - // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d", notificationUuid, eventId, category); - // notif.message = std::array {}; - // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - // notif.message[10] = '\0'; // Seperate Title and Message - // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - // notificationManager.Push(std::move(notif)); - - // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); - DebugNotification("ANCS Notification received"); + NotificationManager::Notification notif; + char uuidStr[55]; + snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); + notif.message = std::array {}; + std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + notif.message[10] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + notif.size = std::min(std::strlen(uuidStr), notif.message.size()); + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; uint16_t subTitleSize; @@ -285,27 +285,33 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); - if (titleSize > 10) { - decodedTitle.resize(7); + if (titleSize > maxTitleSize) { + decodedTitle.resize(maxTitleSize - 3); decodedTitle += "... "; + } else { + decodedTitle += " "; } - if (subTitleSize > 15) { - decodedSubTitle.resize(12); + if (subTitleSize > maxSubtitleSize) { + decodedSubTitle.resize(maxSubtitleSize - 3); decodedSubTitle += "..."; } - if (messageSize > 50) { - decodedMessage.resize(47); + if (messageSize > maxMessageSize) { + decodedMessage.resize(maxMessageSize - 3); decodedMessage += "..."; } + titleSize = std::min(titleSize, static_cast(decodedTitle.size())); + subTitleSize = std::min(subTitleSize, static_cast(decodedSubTitle.size())); + messageSize = std::min(messageSize, static_cast(decodedMessage.size())); + NotificationManager::Notification notif; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message + notif.message[titleSize] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 8fe8fc44e0..a79e222ae5 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -33,6 +33,11 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function lambda) override; void DebugNotification(const char* msg) const; + // Lengths of the parts of the notification, MUST ADD TO 100 + static constexpr uint8_t maxTitleSize {15}; + static constexpr uint8_t maxSubtitleSize {17}; + static constexpr uint8_t maxMessageSize {68}; + // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 static constexpr ble_uuid128_t ancsUuid { .u {.type = BLE_UUID_TYPE_128}, @@ -81,11 +86,11 @@ namespace Pinetime { }; enum class EventFlags : uint8_t { - Silent = 0x01, - Important = 0x02, - PreExisting = 0x04, - PositiveAction = 0x08, - NegativeAction = 0x10 + Silent = (1 << 0), + Important = (1 << 1), + PreExisting = (1 << 2), + PositiveAction = (1 << 3), + NegativeAction = (1 << 4) }; From 6d3d668db3fc1591c05222e5cd22b4ac49f88d26 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 13:06:19 -0600 Subject: [PATCH 52/74] Fixed first letter in Subtitle being cut off --- .../ble/AppleNotificationCenterClient.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index c75fee6836..d70bca4f15 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -285,11 +285,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); - if (titleSize > maxTitleSize) { + if (titleSize >= maxTitleSize) { decodedTitle.resize(maxTitleSize - 3); - decodedTitle += "... "; + decodedTitle += "..._"; } else { - decodedTitle += " "; + decodedTitle += "_"; } if (subTitleSize > maxSubtitleSize) { @@ -302,16 +302,16 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedMessage += "..."; } - titleSize = std::min(titleSize, static_cast(decodedTitle.size())); - subTitleSize = std::min(subTitleSize, static_cast(decodedSubTitle.size())); - messageSize = std::min(messageSize, static_cast(decodedMessage.size())); + titleSize = static_cast(decodedTitle.size()); + subTitleSize = static_cast(decodedSubTitle.size()); + messageSize = static_cast(decodedMessage.size()); NotificationManager::Notification notif; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - notif.message[titleSize] = '\0'; // Seperate Title and Message + notif.message[titleSize-1] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; From d6c5bacf78cd5f0e357beebcf9be748a0253fb14 Mon Sep 17 00:00:00 2001 From: liamcharger Date: Thu, 2 Jan 2025 15:41:16 -0500 Subject: [PATCH 53/74] Improve message display --- src/components/ble/AppleNotificationCenterClient.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index d70bca4f15..0d85b3bbca 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -308,7 +308,13 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { NotificationManager::Notification notif; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; - std::string notifStr = decodedTitle + decodedSubTitle + "\n\n" + decodedMessage; + std::string notifStr; + + notifStr += decodedTitle; + if (!decodedSubTitle.empty()) { + notifStr += decodedSubTitle + ": "; + } + notifStr += decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); notif.message[titleSize-1] = '\0'; // Seperate Title and Message From f148fea8b277968290cc481b0d56fdf7bd850c98 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 17:58:28 -0600 Subject: [PATCH 54/74] Updated notification, Title and Subtitle are in the orange test and message is in the body. --- .../ble/AppleNotificationCenterClient.cpp | 30 ++++++++++++++----- .../ble/AppleNotificationCenterClient.h | 7 ++--- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 0d85b3bbca..8917b70011 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -287,9 +287,18 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (titleSize >= maxTitleSize) { decodedTitle.resize(maxTitleSize - 3); - decodedTitle += "..._"; + decodedTitle += "..."; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } else { - decodedTitle += "_"; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } if (subTitleSize > maxSubtitleSize) { @@ -297,10 +306,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedSubTitle += "..."; } - if (messageSize > maxMessageSize) { - decodedMessage.resize(maxMessageSize - 3); - decodedMessage += "..."; - } + // if (messageSize > maxMessageSize) { + // decodedMessage.resize(maxMessageSize - 3); + // decodedMessage += "..."; + // } titleSize = static_cast(decodedTitle.size()); subTitleSize = static_cast(decodedSubTitle.size()); @@ -312,12 +321,17 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notifStr += decodedTitle; if (!decodedSubTitle.empty()) { - notifStr += decodedSubTitle + ": "; + notifStr += decodedSubTitle + ":"; } notifStr += decodedMessage; notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - notif.message[titleSize-1] = '\0'; // Seperate Title and Message + + if (!decodedSubTitle.empty()) + notif.message[titleSize+subTitleSize] = '\0'; // Seperate Title and Message + else + notif.message[titleSize-1] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index a79e222ae5..7ae22b0510 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -33,10 +33,9 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function lambda) override; void DebugNotification(const char* msg) const; - // Lengths of the parts of the notification, MUST ADD TO 100 - static constexpr uint8_t maxTitleSize {15}; - static constexpr uint8_t maxSubtitleSize {17}; - static constexpr uint8_t maxMessageSize {68}; + 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 { From 756201ea6cdeec60744dfc1d35bf7ce449caaff3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 21:32:52 -0600 Subject: [PATCH 55/74] Implemented Incoming Calls to ANCS Accepting and Declining works --- .../ble/AppleNotificationCenterClient.cpp | 144 ++++++++++++++---- .../ble/AppleNotificationCenterClient.h | 12 ++ src/components/ble/NimbleController.h | 4 + src/components/ble/NotificationManager.h | 2 + src/displayapp/DisplayApp.cpp | 2 + src/displayapp/screens/Notifications.cpp | 36 ++++- src/displayapp/screens/Notifications.h | 10 +- 7 files changed, 174 insertions(+), 36 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 8917b70011..01ec55abeb 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -207,6 +207,22 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + AncsNotitfication ancsNotif; + ancsNotif.eventId = eventId; + ancsNotif.eventFlags = eventFlags; + ancsNotif.category = category; + ancsNotif.uuid = notificationUuid; + + while (notifications.size() > 6) { + notifications.erase(notifications.begin()); + } + + if (notifications.contains(notificationUuid)) { + notifications[notificationUuid] = ancsNotif; + } else { + notifications.insert({notificationUuid, ancsNotif}); + } + if (preExisting || eventId != static_cast(EventIds::Added)) { return; } @@ -251,11 +267,20 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { uint16_t titleSize; uint16_t subTitleSize; uint16_t messageSize; + uint32_t notificationUid; + os_mbuf_copydata(event->notify_rx.om, 1, 4, ¬ificationUid); os_mbuf_copydata(event->notify_rx.om, 6, 2, &titleSize); os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1, 2, &subTitleSize); os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1, 2, &messageSize); + AncsNotitfication ancsNotif; + ancsNotif.uuid = 0; + + if (notifications.contains(notificationUid)) { + ancsNotif = notifications[notificationUid]; + } + std::string decodedTitle; decodedTitle.reserve(titleSize); for (uint16_t i = 0; i < titleSize; ++i) { @@ -285,62 +310,125 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // DebugNotification(decodedTitle.c_str()); // DebugNotification("ANCS Data Source received"); - if (titleSize >= maxTitleSize) { - decodedTitle.resize(maxTitleSize - 3); - decodedTitle += "..."; - if (!decodedSubTitle.empty()) { - decodedTitle += " - "; + bool incomingCall = ancsNotif.uuid != 0 && ancsNotif.category == static_cast(Categories::IncomingCall); + + if (!incomingCall) { + if (titleSize >= maxTitleSize) { + decodedTitle.resize(maxTitleSize - 3); + decodedTitle += "..."; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } else { - decodedTitle += "-"; + if (!decodedSubTitle.empty()) { + decodedTitle += " - "; + } else { + decodedTitle += "-"; + } } - } else { - if (!decodedSubTitle.empty()) { - decodedTitle += " - "; - } else { - decodedTitle += "-"; + + if (subTitleSize > maxSubtitleSize) { + decodedSubTitle.resize(maxSubtitleSize - 3); + decodedSubTitle += "..."; } - } - if (subTitleSize > maxSubtitleSize) { - decodedSubTitle.resize(maxSubtitleSize - 3); - decodedSubTitle += "..."; + // if (messageSize > maxMessageSize) { + // decodedMessage.resize(maxMessageSize - 3); + // decodedMessage += "..."; + // } } - // if (messageSize > maxMessageSize) { - // decodedMessage.resize(maxMessageSize - 3); - // decodedMessage += "..."; - // } - titleSize = static_cast(decodedTitle.size()); subTitleSize = static_cast(decodedSubTitle.size()); messageSize = static_cast(decodedMessage.size()); NotificationManager::Notification notif; + notif.ancsUid = notificationUid; // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr; - notifStr += decodedTitle; - if (!decodedSubTitle.empty()) { - notifStr += decodedSubTitle + ":"; + if (incomingCall) { + notifStr += "Incoming Call:"; + notifStr += decodedTitle; + notifStr += "\n"; + notifStr += decodedSubTitle; + } else { + notifStr += decodedTitle; + if (!decodedSubTitle.empty()) { + notifStr += decodedSubTitle + ":"; + } + notifStr += decodedMessage; } - notifStr += decodedMessage; + notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - - if (!decodedSubTitle.empty()) + + if (incomingCall) + notif.message[13] = '\0'; // Seperate Title and Message + else if (!decodedSubTitle.empty()) notif.message[titleSize+subTitleSize] = '\0'; // Seperate Title and Message else notif.message[titleSize-1] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + if (incomingCall) { + notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall; + } else { + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + } notificationManager.Push(std::move(notif)); systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } +void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { + AncsNotitfication ancsNotif; + if (notifications.contains(uuid)) { + ancsNotif = notifications[uuid]; + if (ancsNotif.category != static_cast(Categories::IncomingCall)) { + return; + } + } else { + return; + } + + uint8_t value[6]; + value[0] = 0x02; // Command ID: Perform Notification Action + value[1] = (uint8_t) (uuid & 0xFF); + value[2] = (uint8_t) ((uuid >> 8) & 0xFF); + value[3] = (uint8_t) ((uuid >> 16) & 0xFF); + value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[5] = 0x00; // Action ID: Positive Action + + ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); +} + +void AppleNotificationCenterClient::RejectIncomingCall(uint32_t uuid) { + AncsNotitfication ancsNotif; + if (notifications.contains(uuid)) { + ancsNotif = notifications[uuid]; + if (ancsNotif.category != static_cast(Categories::IncomingCall)) { + return; + } + } else { + return; + } + + uint8_t value[6]; + value[0] = 0x02; // Command ID: Perform Notification Action + value[1] = (uint8_t) (uuid & 0xFF); + value[2] = (uint8_t) ((uuid >> 8) & 0xFF); + value[3] = (uint8_t) ((uuid >> 16) & 0xFF); + value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[5] = 0x01; // Action ID: Negative Action + + ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); +} + void AppleNotificationCenterClient::Reset() { ancsStartHandle = 0; ancsEndHandle = 0; @@ -364,6 +452,8 @@ void AppleNotificationCenterClient::Reset() { isControlDescriptorFound = false; isDataCharacteristicDiscovered = false; isDataDescriptorFound = false; + + notifications.clear(); } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 7ae22b0510..084ed25cc6 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -8,6 +8,7 @@ #undef max #undef min #include "components/ble/BleClient.h" +#include namespace Pinetime { @@ -33,6 +34,9 @@ namespace Pinetime { void Discover(uint16_t connectionHandle, std::function 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}; @@ -92,6 +96,14 @@ namespace Pinetime { NegativeAction = (1 << 4) }; + struct AncsNotitfication { + uint8_t eventId {0}; + uint8_t eventFlags {0}; + uint8_t category {0}; + uint32_t uuid {0}; + }; + + std::unordered_map notifications; uint16_t ancsStartHandle {0}; uint16_t ancsEndHandle {0}; diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index b84cd1556e..8f3a1dc3f7 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -68,6 +68,10 @@ namespace Pinetime { return anService; }; + Pinetime::Controllers::AppleNotificationCenterClient& ancs() { + return ancsClient; + }; + Pinetime::Controllers::SimpleWeatherService& weather() { return weatherService; }; diff --git a/src/components/ble/NotificationManager.h b/src/components/ble/NotificationManager.h index 57a9c715d2..74eda10996 100644 --- a/src/components/ble/NotificationManager.h +++ b/src/components/ble/NotificationManager.h @@ -34,6 +34,8 @@ namespace Pinetime { Id id = 0; bool valid = false; + uint32_t ancsUid = 0; + const char* Message() const; const char* Title() const; }; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 45a41032dd..9f1a754a7b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -564,6 +564,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(this, notificationManager, systemTask->nimble().alertService(), + systemTask->nimble().ancs(), motorController, *systemTask, Screens::Notifications::Modes::Normal); @@ -572,6 +573,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(this, notificationManager, systemTask->nimble().alertService(), + systemTask->nimble().ancs(), motorController, *systemTask, Screens::Notifications::Modes::Preview); diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 837c4683aa..3c03be5fed 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -2,6 +2,7 @@ #include "displayapp/DisplayApp.h" #include "components/ble/MusicService.h" #include "components/ble/AlertNotificationService.h" +#include "components/ble/AppleNotificationCenterClient.h" #include "displayapp/screens/Symbols.h" #include #include "displayapp/InfiniTimeTheme.h" @@ -13,12 +14,14 @@ extern lv_font_t jetbrains_mono_bold_20; Notifications::Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode) : app {app}, notificationManager {notificationManager}, alertNotificationService {alertNotificationService}, + ancsClient {ancsClient}, motorController {motorController}, wakeLock(systemTask), mode {mode} { @@ -33,10 +36,12 @@ Notifications::Notifications(DisplayApp* app, notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + notification.ancsUid); validDisplay = true; } else { - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, ancsClient, motorController); validDisplay = false; } if (mode == Modes::Preview) { @@ -109,7 +114,9 @@ void Notifications::Refresh() { notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + notification.ancsUid); } else { running = false; } @@ -202,7 +209,9 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { previousNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + previousNotification.ancsUid); } return true; case Pinetime::Applications::TouchEvents::SwipeUp: { @@ -229,7 +238,9 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { nextNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + ancsClient, + motorController, + nextNotification.ancsUid); } return true; default: @@ -245,6 +256,7 @@ namespace { } Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController) : NotificationItem("Notifications", "No notifications to display", @@ -252,7 +264,9 @@ Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNo Controllers::NotificationManager::Categories::Unknown, 0, alertNotificationService, - motorController) { + ancsClient, + motorController, + 0) { } Notifications::NotificationItem::NotificationItem(const char* title, @@ -261,8 +275,12 @@ Notifications::NotificationItem::NotificationItem(const char* title, Controllers::NotificationManager::Categories category, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController) - : alertNotificationService {alertNotificationService}, motorController {motorController} { + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::MotorController& motorController, + uint32_t ancsUid) + : alertNotificationService {alertNotificationService}, ancsClient {ancsClient}, motorController {motorController} { + this->ancsUid = ancsUid; + container = lv_cont_create(lv_scr_act(), nullptr); lv_obj_set_size(container, LV_HOR_RES, LV_VER_RES); lv_obj_set_style_local_bg_color(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); @@ -360,8 +378,10 @@ void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_ if (obj == bt_accept) { alertNotificationService.AcceptIncomingCall(); + ancsClient.AcceptIncomingCall(ancsUid); } else if (obj == bt_reject) { alertNotificationService.RejectIncomingCall(); + ancsClient.RejectIncomingCall(ancsUid); } else if (obj == bt_mute) { alertNotificationService.MuteIncomingCall(); } diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 8488dc5bb2..a7e00661fa 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -24,6 +24,7 @@ namespace Pinetime { explicit Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode); @@ -38,6 +39,7 @@ namespace Pinetime { class NotificationItem { public: NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController); NotificationItem(const char* title, const char* msg, @@ -45,13 +47,17 @@ namespace Pinetime { Controllers::NotificationManager::Categories, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController); + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::MotorController& motorController, + uint32_t ancsUid); ~NotificationItem(); bool IsRunning() const { return running; } + uint32_t ancsUid = 0; + void OnCallButtonEvent(lv_obj_t*, lv_event_t event); private: @@ -64,6 +70,7 @@ namespace Pinetime { lv_obj_t* label_mute; lv_obj_t* label_reject; Pinetime::Controllers::AlertNotificationService& alertNotificationService; + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient; Pinetime::Controllers::MotorController& motorController; bool running = true; @@ -73,6 +80,7 @@ namespace Pinetime { DisplayApp* app; Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::AlertNotificationService& alertNotificationService; + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient; Pinetime::Controllers::MotorController& motorController; System::WakeLock wakeLock; Modes mode = Modes::Normal; From f3aff14afeca6fa9a31f8b9468109be080170281 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 21:48:28 -0600 Subject: [PATCH 56/74] Turned off non important debugs --- src/components/ble/AppleNotificationCenterClient.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 01ec55abeb..81c3b5922f 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -79,7 +79,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn if (characteristic == nullptr && error->status == BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery complete"); - DebugNotification("ANCS Characteristic discovery complete"); + // DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isDataCharacteristicDiscovered) { @@ -105,7 +105,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn char msg[55]; snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); NRF_LOG_INFO(msg); - DebugNotification(msg); + // DebugNotification(msg); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } @@ -139,7 +139,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { if (dataSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - DebugNotification("ANCS Descriptor discovered: Data Source"); + // DebugNotification("ANCS Descriptor discovered: Data Source"); dataSourceDescriptorHandle = descriptor->handle; isDataDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -151,7 +151,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - DebugNotification(errorStr); + // DebugNotification(errorStr); } if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); @@ -181,7 +181,7 @@ int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHand char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Control Point ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - DebugNotification(errorStr); + // DebugNotification(errorStr); } return 0; } From 54908fb450d70fa9d290e1aca6f91aae56eb99ff Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 2 Jan 2025 22:01:15 -0600 Subject: [PATCH 57/74] Formatted Code --- .../ble/AppleNotificationCenterClient.cpp | 23 ++++++++------ .../ble/AppleNotificationCenterClient.h | 31 ++++++++----------- src/displayapp/screens/Notifications.cpp | 2 +- src/displayapp/screens/Notifications.h | 2 +- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 81c3b5922f..6f166b030e 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -82,7 +82,8 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn // DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); - } if (isDataCharacteristicDiscovered) { + } + if (isDataCharacteristicDiscovered) { // DebugNotification("ANCS Characteristic discovery complete: Data Source"); ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } @@ -134,7 +135,7 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); // DebugNotification("ANCS Descriptor discovered"); controlPointDescriptorHandle = descriptor->handle; - isControlDescriptorFound = true; + isControlDescriptorFound = true; } } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { if (dataSourceDescriptorHandle == 0) { @@ -159,7 +160,9 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c return 0; } -int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { +int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, + const ble_gatt_error* error, + ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); DebugNotification("ANCS New alert subscribe OK"); @@ -173,7 +176,9 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, return 0; } -int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHandle*/, const ble_gatt_error* error, ble_gatt_attr* /*attribute*/) { +int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHandle*/, + const ble_gatt_error* error, + ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS Control Point write OK"); // DebugNotification("ANCS Control Point write OK"); @@ -255,7 +260,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); notif.message = std::array {}; std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message + notif.message[10] = '\0'; // Seperate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(uuidStr), notif.message.size()); notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; @@ -365,13 +370,13 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - if (incomingCall) + if (incomingCall) notif.message[13] = '\0'; // Seperate Title and Message else if (!decodedSubTitle.empty()) - notif.message[titleSize+subTitleSize] = '\0'; // Seperate Title and Message + notif.message[titleSize + subTitleSize] = '\0'; // Seperate Title and Message else - notif.message[titleSize-1] = '\0'; // Seperate Title and Message - + notif.message[titleSize - 1] = '\0'; // Seperate Title and Message + notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); if (incomingCall) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 084ed25cc6..76e1a51a19 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -22,12 +22,15 @@ namespace Pinetime { class AppleNotificationCenterClient : public BleClient { public: explicit AppleNotificationCenterClient(Pinetime::System::SystemTask& systemTask, - Pinetime::Controllers::NotificationManager& notificationManager); + 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 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(); @@ -42,27 +45,23 @@ namespace Pinetime { static constexpr uint8_t maxMessageSize {120}; // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 - static constexpr ble_uuid128_t ancsUuid { + 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} - }; + .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} - }; + 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 } - }; + .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 } - }; + .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}; @@ -82,11 +81,7 @@ namespace Pinetime { Entertainment = 11 }; - enum class EventIds : uint8_t { - Added = 0, - Modified = 1, - Removed = 2 - }; + enum class EventIds : uint8_t { Added = 0, Modified = 1, Removed = 2 }; enum class EventFlags : uint8_t { Silent = (1 << 0), diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 3c03be5fed..54c761327b 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -14,7 +14,7 @@ extern lv_font_t jetbrains_mono_bold_20; Notifications::Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode) diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index a7e00661fa..18ab8e5a34 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -24,7 +24,7 @@ namespace Pinetime { explicit Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, + Pinetime::Controllers::AppleNotificationCenterClient& ancsClient, Pinetime::Controllers::MotorController& motorController, System::SystemTask& systemTask, Modes mode); From 23242e84a16766c355fb7b42b7de76e8b6352034 Mon Sep 17 00:00:00 2001 From: liamcharger Date: Fri, 3 Jan 2025 07:31:56 -0500 Subject: [PATCH 58/74] Remove RTT settings --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a93abd551c..3901651143 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -841,8 +841,8 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") # NRF SDK Logging add_definitions(-DNRF_LOG_ENABLED=1) - add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) - add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) + # add_definitions(-DNRF_LOG_BACKEND_RTT_ENABLED=1) + # add_definitions(-DNRF_LOG_BACKEND_SERIAL_USES_RTT=1) # NRF SDK individual modules logging # add_definitions(-DCLOCK_CONFIG_LOG_ENABLED=1) From 72c3b047ea946f063b08f3361c46943573cbb1e6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 16:08:38 -0600 Subject: [PATCH 59/74] Removed more debug notifications --- .../ble/AppleNotificationCenterClient.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 6f166b030e..b380abee79 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -165,7 +165,7 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); - DebugNotification("ANCS New alert subscribe OK"); + // DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); DebugNotification("ANCS New alert subscribe ERROR"); @@ -255,18 +255,18 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); - NotificationManager::Notification notif; - char uuidStr[55]; - snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); - notif.message = std::array {}; - std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - notif.message[10] = '\0'; // Seperate Title and Message - notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - notificationManager.Push(std::move(notif)); - - systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // NotificationManager::Notification notif; + // char uuidStr[55]; + // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); + // notif.message = std::array {}; + // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); + // notif.message[10] = '\0'; // Seperate Title and Message + // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination + // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); + // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + // notificationManager.Push(std::move(notif)); + + // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); // DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; From 7a7f1b0f95cbaacfd0e3ad27026ddab700d501d3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 18:40:41 -0600 Subject: [PATCH 60/74] Added check for special characters and show unknown symbol. --- .../ble/AppleNotificationCenterClient.cpp | 103 ++++++++++++++---- .../ble/AppleNotificationCenterClient.h | 3 + src/displayapp/fonts/fonts.json | 2 +- 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index b380abee79..685b063647 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -286,29 +286,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ancsNotif = notifications[notificationUid]; } - std::string decodedTitle; - decodedTitle.reserve(titleSize); - for (uint16_t i = 0; i < titleSize; ++i) { - uint8_t byte; - os_mbuf_copydata(event->notify_rx.om, 8 + i, 1, &byte); - decodedTitle.push_back(static_cast(byte)); - } + std::string decodedTitle = DecodeUtf8String(event->notify_rx.om, titleSize, 8); - std::string decodedSubTitle; - decodedSubTitle.reserve(subTitleSize); - for (uint16_t i = 0; i < subTitleSize; ++i) { - uint8_t byte; - os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + i, 1, &byte); - decodedSubTitle.push_back(static_cast(byte)); - } + std::string decodedSubTitle = DecodeUtf8String(event->notify_rx.om, subTitleSize, 8 + titleSize + 1 + 2); - std::string decodedMessage; - decodedMessage.reserve(messageSize); - for (uint16_t i = 0; i < messageSize; ++i) { - uint8_t byte; - os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2 + i, 1, &byte); - decodedMessage.push_back(static_cast(byte)); - } + std::string decodedMessage = DecodeUtf8String(event->notify_rx.om, messageSize, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2); NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); @@ -479,4 +461,83 @@ void AppleNotificationCenterClient::DebugNotification(const char* msg) const { notificationManager.Push(std::move(notif)); systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); +} + +std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_t size, uint16_t offset) { + std::string decoded; + decoded.reserve(size); + + auto isInFontDefinition = [](uint32_t codepoint) -> bool { + // Check if the codepoint falls into the specified font ranges or is explicitly listed + return (codepoint >= 0x20 && codepoint <= 0x7E) || // Printable ASCII + (codepoint >= 0x410 && codepoint <= 0x44F) || // Cyrillic + codepoint == 0xB0; + }; + + for (uint16_t i = 0; i < size;) { + uint8_t byte; + if (os_mbuf_copydata(om, offset + i, 1, &byte) != 0) { + break; // Handle error in copying data (e.g., log or terminate processing) + } + + if (byte <= 0x7F) { // Single-byte UTF-8 (ASCII) + if (isInFontDefinition(byte)) { + decoded.push_back(static_cast(byte)); + } else { + decoded.append("�"); // Replace unsupported + } + ++i; + } else { // Multi-byte UTF-8 + // Determine sequence length based on leading byte + int sequenceLength = 0; + if ((byte & 0xE0) == 0xC0) + sequenceLength = 2; // 2-byte sequence + else if ((byte & 0xF0) == 0xE0) + sequenceLength = 3; // 3-byte sequence + else if ((byte & 0xF8) == 0xF0) + sequenceLength = 4; // 4-byte sequence + + if (i + sequenceLength > size) { + decoded.append("�"); // Incomplete sequence, replace + break; + } + + // Read the full sequence + std::string utf8Char; + bool validSequence = true; + uint32_t codepoint = 0; + + for (int j = 0; j < sequenceLength; ++j) { + uint8_t nextByte; + os_mbuf_copydata(om, offset + i + j, 1, &nextByte); + utf8Char.push_back(static_cast(nextByte)); + + if (j == 0) { + // Leading byte contributes significant bits + if (sequenceLength == 2) + codepoint = nextByte & 0x1F; + else if (sequenceLength == 3) + codepoint = nextByte & 0x0F; + else if (sequenceLength == 4) + codepoint = nextByte & 0x07; + } else { + // Continuation bytes contribute lower bits + if ((nextByte & 0xC0) != 0x80) { + validSequence = false; // Invalid UTF-8 continuation byte + break; + } + codepoint = (codepoint << 6) | (nextByte & 0x3F); + } + } + + if (validSequence && isInFontDefinition(codepoint)) { + decoded.append(utf8Char); // Append valid UTF-8 character + } else { + decoded.append("�"); // Replace unsupported + } + i += sequenceLength; + } + } + + return decoded; } \ No newline at end of file diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 76e1a51a19..994d037c41 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -9,6 +9,7 @@ #undef min #include "components/ble/BleClient.h" #include +#include namespace Pinetime { @@ -100,6 +101,8 @@ namespace Pinetime { std::unordered_map 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}; diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 90be1febe6..b16df09f43 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -3,7 +3,7 @@ "sources": [ { "file": "JetBrainsMono-Bold.ttf", - "range": "0x20-0x7e, 0x410-0x44f, 0xB0" + "range": "0x20-0x7e, 0x410-0x44f, 0xB0, 0xBF, 0xFFFD" }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", From f0850c02dc9165aeefbb2dbd1e7fa8dcda5aaeb4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 22:12:56 -0600 Subject: [PATCH 61/74] removed all debug notifications --- src/components/ble/AppleNotificationCenterClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 685b063647..8f8997ad2d 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -168,7 +168,7 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, // DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); - DebugNotification("ANCS New alert subscribe ERROR"); + // DebugNotification("ANCS New alert subscribe ERROR"); } if (isDescriptorFound == isControlDescriptorFound && isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); From 624cef1a434d0a45f339ce5b379f0de9bceb0ab8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 22:19:39 -0600 Subject: [PATCH 62/74] Ignore silent notifications --- src/components/ble/AppleNotificationCenterClient.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 8f8997ad2d..c410644828 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -206,7 +206,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); - // bool silent = eventFlags & static_cast(EventFlags::Silent); + bool silent = (eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); @@ -224,11 +224,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (notifications.contains(notificationUuid)) { notifications[notificationUuid] = ancsNotif; - } else { + } else if (!silent) { notifications.insert({notificationUuid, ancsNotif}); } - if (preExisting || eventId != static_cast(EventIds::Added)) { + if (preExisting || eventId != static_cast(EventIds::Added) || silent) { return; } From 4c4d21eb3a2b8fe1856ee57a45d2f367cdaa76af Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 4 Jan 2025 22:22:10 -0600 Subject: [PATCH 63/74] Make trunacated messages end in "..." to indicate that message has more on iOS --- src/components/ble/AppleNotificationCenterClient.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index c410644828..41583322ec 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -349,6 +349,12 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notifStr += decodedMessage; } + // Adjust notification if too long + if (notifStr.size() > 100) { + notifStr.resize(97); + notifStr += "..."; + } + notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); From 77f5ce2817bc5fe6b07a73391b44f4ec3cb624b3 Mon Sep 17 00:00:00 2001 From: liamcharger Date: Thu, 16 Jan 2025 09:30:50 -0500 Subject: [PATCH 64/74] Fix typos and remove unnecessary commented code --- .../ble/AppleNotificationCenterClient.cpp | 51 +++---------------- .../ble/AppleNotificationCenterClient.h | 4 +- 2 files changed, 10 insertions(+), 45 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 41583322ec..628d3a3c87 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -46,12 +46,9 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service == nullptr && error->status == BLE_HS_EDONE) { if (isDiscovered) { NRF_LOG_INFO("ANCS Discovery found, starting characteristics discovery"); - // DebugNotification("ANCS Discovery found, starting characteristics discovery"); - ble_gattc_disc_all_chrs(connectionHandle, ancsStartHandle, ancsEndHandle, OnANCSCharacteristicDiscoveredCallback, this); } else { NRF_LOG_INFO("ANCS not found"); - // DebugNotification("ANCS not found"); onServiceDiscovered(connectionHandle); } return true; @@ -59,7 +56,7 @@ bool AppleNotificationCenterClient::OnDiscoveryEvent(uint16_t connectionHandle, if (service != nullptr && ble_uuid_cmp(&ancsUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("ANCS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); - // DebugNotification("ANCS discovered"); + ancsStartHandle = service->start_handle; ancsEndHandle = service->end_handle; isDiscovered = true; @@ -72,19 +69,16 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn const ble_gatt_chr* characteristic) { if (error->status != 0 && error->status != BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery ERROR"); - // DebugNotification("ANCS Characteristic discovery ERROR"); onServiceDiscovered(connectionHandle); return 0; } if (characteristic == nullptr && error->status == BLE_HS_EDONE) { NRF_LOG_INFO("ANCS Characteristic discovery complete"); - // DebugNotification("ANCS Characteristic discovery complete"); if (isCharacteristicDiscovered) { ble_gattc_disc_all_dscs(connectionHandle, notificationSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isDataCharacteristicDiscovered) { - // DebugNotification("ANCS Characteristic discovery complete: Data Source"); ble_gattc_disc_all_dscs(connectionHandle, dataSourceHandle, ancsEndHandle, OnANCSDescriptorDiscoveryEventCallback, this); } if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { @@ -94,19 +88,16 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn if (characteristic != nullptr) { if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); - // DebugNotification("ANCS Characteristic discovered: Notification Source"); notificationSourceHandle = characteristic->val_handle; isCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); - // DebugNotification("ANCS Characteristic discovered: Control Point"); controlPointHandle = characteristic->val_handle; isControlCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { char msg[55]; snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); NRF_LOG_INFO(msg); - // DebugNotification(msg); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } @@ -123,7 +114,6 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c if (characteristicValueHandle == notificationSourceHandle && ble_uuid_cmp(¬ificationSourceChar.u, &descriptor->uuid.u)) { if (notificationSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - // DebugNotification("ANCS Descriptor discovered"); notificationSourceDescriptorHandle = descriptor->handle; isDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -133,14 +123,12 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c } else if (characteristicValueHandle == controlPointHandle && ble_uuid_cmp(&controlPointChar.u, &descriptor->uuid.u)) { if (controlPointDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - // DebugNotification("ANCS Descriptor discovered"); controlPointDescriptorHandle = descriptor->handle; isControlDescriptorFound = true; } } else if (characteristicValueHandle == dataSourceHandle && ble_uuid_cmp(&dataSourceChar.u, &descriptor->uuid.u)) { if (dataSourceDescriptorHandle == 0) { NRF_LOG_INFO("ANCS Descriptor discovered : %d", descriptor->handle); - // DebugNotification("ANCS Descriptor discovered: Data Source"); dataSourceDescriptorHandle = descriptor->handle; isDataDescriptorFound = true; uint8_t value[2] {1, 0}; @@ -152,7 +140,6 @@ int AppleNotificationCenterClient::OnDescriptorDiscoveryEventCallback(uint16_t c char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Descriptor discovery ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - // DebugNotification(errorStr); } if (isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); @@ -165,10 +152,8 @@ int AppleNotificationCenterClient::OnNewAlertSubcribe(uint16_t connectionHandle, ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS New alert subscribe OK"); - // DebugNotification("ANCS New alert subscribe OK"); } else { NRF_LOG_INFO("ANCS New alert subscribe ERROR"); - // DebugNotification("ANCS New alert subscribe ERROR"); } if (isDescriptorFound == isControlDescriptorFound && isDescriptorFound == isDataDescriptorFound) onServiceDiscovered(connectionHandle); @@ -181,12 +166,10 @@ int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHand ble_gatt_attr* /*attribute*/) { if (error->status == 0) { NRF_LOG_INFO("ANCS Control Point write OK"); - // DebugNotification("ANCS Control Point write OK"); } else { char errorStr[55]; snprintf(errorStr, sizeof(errorStr), "ANCS Control Point ERROR: %d", error->status); NRF_LOG_INFO(errorStr); - // DebugNotification(errorStr); } return 0; } @@ -212,7 +195,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; ancsNotif.eventId = eventId; ancsNotif.eventFlags = eventFlags; ancsNotif.category = category; @@ -254,20 +237,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { request[13] = ((messageSize >> 8) & 0xFF); ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); - - // NotificationManager::Notification notif; - // char uuidStr[55]; - // snprintf(uuidStr, sizeof(uuidStr), "iOS Notif.:%08lx\nEvID: %d\nCat: %d\nFlags: %d", notificationUuid, eventId, category, eventFlags); - // notif.message = std::array {}; - // std::strncpy(notif.message.data(), uuidStr, notif.message.size() - 1); - // notif.message[10] = '\0'; // Seperate Title and Message - // notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination - // notif.size = std::min(std::strlen(uuidStr), notif.message.size()); - // notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; - // notificationManager.Push(std::move(notif)); - - // systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); - // DebugNotification("ANCS Notification received"); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { uint16_t titleSize; uint16_t subTitleSize; @@ -279,7 +248,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1, 2, &subTitleSize); os_mbuf_copydata(event->notify_rx.om, 8 + titleSize + 1 + 2 + subTitleSize + 1, 2, &messageSize); - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; ancsNotif.uuid = 0; if (notifications.contains(notificationUid)) { @@ -294,8 +263,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); - // DebugNotification(decodedTitle.c_str()); - // DebugNotification("ANCS Data Source received"); bool incomingCall = ancsNotif.uuid != 0 && ancsNotif.category == static_cast(Categories::IncomingCall); @@ -333,7 +300,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { NotificationManager::Notification notif; notif.ancsUid = notificationUid; - // std::string notifStr = "iOS Notif.:" + decodedTitle + "\n" + decodedSubTitle; std::string notifStr; if (incomingCall) { @@ -359,11 +325,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); if (incomingCall) - notif.message[13] = '\0'; // Seperate Title and Message + notif.message[13] = '\0'; // Separate Title and Message else if (!decodedSubTitle.empty()) - notif.message[titleSize + subTitleSize] = '\0'; // Seperate Title and Message + notif.message[titleSize + subTitleSize] = '\0'; // Separate Title and Message else - notif.message[titleSize - 1] = '\0'; // Seperate Title and Message + notif.message[titleSize - 1] = '\0'; // Separate Title and Message notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); @@ -379,7 +345,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; if (notifications.contains(uuid)) { ancsNotif = notifications[uuid]; if (ancsNotif.category != static_cast(Categories::IncomingCall)) { @@ -401,7 +367,7 @@ void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { } void AppleNotificationCenterClient::RejectIncomingCall(uint32_t uuid) { - AncsNotitfication ancsNotif; + AncsNotification ancsNotif; if (notifications.contains(uuid)) { ancsNotif = notifications[uuid]; if (ancsNotif.category != static_cast(Categories::IncomingCall)) { @@ -451,7 +417,6 @@ void AppleNotificationCenterClient::Reset() { void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { NRF_LOG_INFO("[ANCS] Starting discovery"); - // DebugNotification("[ANCS] Starting discovery"); this->onServiceDiscovered = onServiceDiscovered; ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); } diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 994d037c41..d33b887406 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -92,14 +92,14 @@ namespace Pinetime { NegativeAction = (1 << 4) }; - struct AncsNotitfication { + struct AncsNotification { uint8_t eventId {0}; uint8_t eventFlags {0}; uint8_t category {0}; uint32_t uuid {0}; }; - std::unordered_map notifications; + std::unordered_map notifications; std::string DecodeUtf8String(os_mbuf* om, uint16_t size, uint16_t offset); From 3ae45612ab84b75ba6530cc4e6f2c8fb6cb49a65 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 19 May 2025 13:12:07 -0500 Subject: [PATCH 65/74] Made codebase changes based on PR Comments https://github.com/InfiniTimeOrg/InfiniTime/pull/2217/files/de63dce4ce5ef9b796013a6a9150d90b81fc3981#diff-a57dcf730dd40f33f9081712a57f33d39d6a73096f630df41deb58f5032e1870 --- .../ble/AppleNotificationCenterClient.cpp | 129 ++++++++---------- .../ble/AppleNotificationCenterClient.h | 14 +- .../ble/BatteryInformationService.cpp | 2 +- src/components/ble/NimbleController.cpp | 3 +- src/displayapp/fonts/fonts.json | 2 +- 5 files changed, 70 insertions(+), 80 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 628d3a3c87..f5a82ce7d9 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -1,7 +1,7 @@ #include "components/ble/AppleNotificationCenterClient.h" -#include #include "components/ble/NotificationManager.h" #include "systemtask/SystemTask.h" +#include using namespace Pinetime::Controllers; @@ -84,8 +84,7 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn if (isCharacteristicDiscovered == isControlCharacteristicDiscovered && isCharacteristicDiscovered == isDataCharacteristicDiscovered) { onServiceDiscovered(connectionHandle); } - } else { - if (characteristic != nullptr) { + } else if (characteristic != nullptr) { if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); notificationSourceHandle = characteristic->val_handle; @@ -95,13 +94,10 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn controlPointHandle = characteristic->val_handle; isControlCharacteristicDiscovered = true; } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { - char msg[55]; - snprintf(msg, sizeof(msg), "ANCS Characteristic discovered: Data Source\n%d", characteristic->val_handle); - NRF_LOG_INFO(msg); + NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); dataSourceHandle = characteristic->val_handle; isDataCharacteristicDiscovered = true; } - } } return 0; } @@ -177,64 +173,58 @@ int AppleNotificationCenterClient::OnControlPointWrite(uint16_t /*connectionHand void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (event->notify_rx.attr_handle == notificationSourceHandle || event->notify_rx.attr_handle == notificationSourceDescriptorHandle) { NRF_LOG_INFO("ANCS Notification received"); - uint8_t eventId; - uint8_t eventFlags; - uint8_t category; - uint8_t categoryCount; - uint32_t notificationUuid; - - os_mbuf_copydata(event->notify_rx.om, 0, 1, &eventId); - os_mbuf_copydata(event->notify_rx.om, 1, 1, &eventFlags); - os_mbuf_copydata(event->notify_rx.om, 2, 1, &category); - os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); - os_mbuf_copydata(event->notify_rx.om, 4, 4, ¬ificationUuid); - - bool silent = (eventFlags & static_cast(EventFlags::Silent)) != 0; + + AncsNotification ancsNotif; + + os_mbuf_copydata(event->notify_rx.om, 0, 1, &ancsNotif.eventId); + os_mbuf_copydata(event->notify_rx.om, 1, 1, &ancsNotif.eventFlags); + os_mbuf_copydata(event->notify_rx.om, 2, 1, &ancsNotif.category); + // Can be used to see how many grouped notifications are present + // os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); + os_mbuf_copydata(event->notify_rx.om, 4, 4, &ancsNotif.uuid); + + bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = (eventFlags & static_cast(EventFlags::PreExisting)) != 0; + bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); - AncsNotification ancsNotif; - ancsNotif.eventId = eventId; - ancsNotif.eventFlags = eventFlags; - ancsNotif.category = category; - ancsNotif.uuid = notificationUuid; - + // The 6 is from TotalNbNotifications in NotificationManager.h + 1 while (notifications.size() > 6) { notifications.erase(notifications.begin()); } - if (notifications.contains(notificationUuid)) { - notifications[notificationUuid] = ancsNotif; + if (notifications.contains(ancsNotif.uuid)) { + notifications[ancsNotif.uuid] = ancsNotif; } else if (!silent) { - notifications.insert({notificationUuid, ancsNotif}); + notifications.insert({ancsNotif.uuid, ancsNotif}); } - if (preExisting || eventId != static_cast(EventIds::Added) || silent) { + if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added) || silent) { return; } // Request ANCS more info + // The +4 is for the "..." at the end of the string uint8_t titleSize = maxTitleSize + 4; uint8_t subTitleSize = maxSubtitleSize + 4; uint8_t messageSize = maxMessageSize + 4; BYTE request[14]; request[0] = 0x00; // Command ID: Get Notification Attributes - request[1] = (uint8_t) (notificationUuid & 0xFF); - request[2] = (uint8_t) ((notificationUuid >> 8) & 0xFF); - request[3] = (uint8_t) ((notificationUuid >> 16) & 0xFF); - request[4] = (uint8_t) ((notificationUuid >> 24) & 0xFF); + request[1] = static_cast(ancsNotif.uuid & 0xFF); + request[2] = static_cast((ancsNotif.uuid >> 8) & 0xFF); + request[3] = static_cast((ancsNotif.uuid >> 16) & 0xFF); + request[4] = static_cast((ancsNotif.uuid >> 24) & 0xFF); request[5] = 0x01; // Attribute ID: Title // request[6] = 0x00; - request[6] = (titleSize & 0xFF); - request[7] = ((titleSize >> 8) & 0xFF); + request[6] = static_cast(titleSize & 0xFF); + request[7] = static_cast((titleSize >> 8) & 0xFF); request[8] = 0x02; // Attribute ID: Subtitle - request[9] = (subTitleSize & 0xFF); - request[10] = ((subTitleSize >> 8) & 0xFF); + request[9] = static_cast(subTitleSize & 0xFF); + request[10] = static_cast((subTitleSize >> 8) & 0xFF); request[11] = 0x03; // Attribute ID: Message - request[12] = (messageSize & 0xFF); - request[13] = ((messageSize >> 8) & 0xFF); + request[12] = static_cast(messageSize & 0xFF); + request[13] = static_cast((messageSize >> 8) & 0xFF); ble_gattc_write_flat(event->notify_rx.conn_handle, controlPointHandle, request, sizeof(request), OnControlPointWriteCallback, this); } else if (event->notify_rx.attr_handle == dataSourceHandle || event->notify_rx.attr_handle == dataSourceDescriptorHandle) { @@ -287,11 +277,6 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { decodedSubTitle.resize(maxSubtitleSize - 3); decodedSubTitle += "..."; } - - // if (messageSize > maxMessageSize) { - // decodedMessage.resize(maxMessageSize - 3); - // decodedMessage += "..."; - // } } titleSize = static_cast(decodedTitle.size()); @@ -316,20 +301,21 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // Adjust notification if too long - if (notifStr.size() > 100) { + if (notifStr.size() > NotificationManager::MessageSize) { notifStr.resize(97); notifStr += "..."; } - notif.message = std::array {}; + notif.message = std::array {}; std::strncpy(notif.message.data(), notifStr.c_str(), notif.message.size() - 1); - if (incomingCall) + if (incomingCall) { notif.message[13] = '\0'; // Separate Title and Message - else if (!decodedSubTitle.empty()) + } else if (!decodedSubTitle.empty()) { notif.message[titleSize + subTitleSize] = '\0'; // Separate Title and Message - else + } else { notif.message[titleSize - 1] = '\0'; // Separate Title and Message + } notif.message[notif.message.size() - 1] = '\0'; // Ensure null-termination notif.size = std::min(std::strlen(notifStr.c_str()), notif.message.size()); @@ -345,9 +331,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { - AncsNotification ancsNotif; if (notifications.contains(uuid)) { - ancsNotif = notifications[uuid]; + const AncsNotification ancsNotif = notifications[uuid]; if (ancsNotif.category != static_cast(Categories::IncomingCall)) { return; } @@ -357,10 +342,10 @@ void AppleNotificationCenterClient::AcceptIncomingCall(uint32_t uuid) { uint8_t value[6]; value[0] = 0x02; // Command ID: Perform Notification Action - value[1] = (uint8_t) (uuid & 0xFF); - value[2] = (uint8_t) ((uuid >> 8) & 0xFF); - value[3] = (uint8_t) ((uuid >> 16) & 0xFF); - value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[1] = static_cast((uuid & 0xFF)); + value[2] = static_cast((uuid >> 8) & 0xFF); + value[3] = static_cast((uuid >> 16) & 0xFF); + value[4] = static_cast((uuid >> 24) & 0xFF); value[5] = 0x00; // Action ID: Positive Action ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); @@ -379,10 +364,10 @@ void AppleNotificationCenterClient::RejectIncomingCall(uint32_t uuid) { uint8_t value[6]; value[0] = 0x02; // Command ID: Perform Notification Action - value[1] = (uint8_t) (uuid & 0xFF); - value[2] = (uint8_t) ((uuid >> 8) & 0xFF); - value[3] = (uint8_t) ((uuid >> 16) & 0xFF); - value[4] = (uint8_t) ((uuid >> 24) & 0xFF); + value[1] = static_cast(uuid & 0xFF); + value[2] = static_cast((uuid >> 8) & 0xFF); + value[3] = static_cast((uuid >> 16) & 0xFF); + value[4] = static_cast((uuid >> 24) & 0xFF); value[5] = 0x01; // Action ID: Negative Action ble_gattc_write_flat(systemTask.nimble().connHandle(), controlPointHandle, value, sizeof(value), OnControlPointWriteCallback, this); @@ -421,6 +406,8 @@ void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::fun ble_gattc_disc_svc_by_uuid(connectionHandle, &ancsUuid.u, OnDiscoveryEventCallback, this); } +// This function is used for debugging purposes to log a message and push a notification +// Used to test BLE debugging on production devices void AppleNotificationCenterClient::DebugNotification(const char* msg) const { NRF_LOG_INFO("[ANCS DEBUG] %s", msg); @@ -446,7 +433,7 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ }; for (uint16_t i = 0; i < size;) { - uint8_t byte; + uint8_t byte = 0; if (os_mbuf_copydata(om, offset + i, 1, &byte) != 0) { break; // Handle error in copying data (e.g., log or terminate processing) } @@ -461,12 +448,13 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ } else { // Multi-byte UTF-8 // Determine sequence length based on leading byte int sequenceLength = 0; - if ((byte & 0xE0) == 0xC0) + if ((byte & 0xE0) == 0xC0) { sequenceLength = 2; // 2-byte sequence - else if ((byte & 0xF0) == 0xE0) + } else if ((byte & 0xF0) == 0xE0) { sequenceLength = 3; // 3-byte sequence - else if ((byte & 0xF8) == 0xF0) + } else if ((byte & 0xF8) == 0xF0) { sequenceLength = 4; // 4-byte sequence + } if (i + sequenceLength > size) { decoded.append("�"); // Incomplete sequence, replace @@ -479,18 +467,19 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ uint32_t codepoint = 0; for (int j = 0; j < sequenceLength; ++j) { - uint8_t nextByte; + uint8_t nextByte = 0; os_mbuf_copydata(om, offset + i + j, 1, &nextByte); utf8Char.push_back(static_cast(nextByte)); if (j == 0) { // Leading byte contributes significant bits - if (sequenceLength == 2) + if (sequenceLength == 2) { codepoint = nextByte & 0x1F; - else if (sequenceLength == 3) + } else if (sequenceLength == 3) { codepoint = nextByte & 0x0F; - else if (sequenceLength == 4) + } else if (sequenceLength == 4) { codepoint = nextByte & 0x07; + } } else { // Continuation bytes contribute lower bits if ((nextByte & 0xC0) != 0x80) { @@ -511,4 +500,4 @@ std::string AppleNotificationCenterClient::DecodeUtf8String(os_mbuf* om, uint16_ } return decoded; -} \ No newline at end of file +} diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index d33b887406..fd0bd9a2f3 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -45,6 +45,8 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; + // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html + // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 static constexpr ble_uuid128_t ancsUuid { .u {.type = BLE_UUID_TYPE_128}, @@ -52,20 +54,20 @@ namespace Pinetime { private: // 9FBF120D-6301-42D9-8C58-25E699A21DBD - const ble_uuid128_t notificationSourceChar { + static constexpr 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 { + static constexpr 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 { + static constexpr 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}; + static constexpr ble_uuid16_t gattServiceUuid = {BLE_UUID_TYPE_16, 0x1801}; + static constexpr ble_uuid16_t serviceChangedCharUuid = {BLE_UUID_TYPE_16, 0x2A05}; enum class Categories : uint8_t { Other = 0, @@ -131,4 +133,4 @@ namespace Pinetime { std::function onServiceDiscovered; }; } -} \ No newline at end of file +} diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index db7c856622..e776526661 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 223a4e37d7..a7dfce4f9e 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -163,7 +163,6 @@ void NimbleController::StartAdvertising() { fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; const ble_uuid128_t uuids128[2] = {DfuService::serviceUuid, AppleNotificationCenterClient::ancsUuid}; - // fields.uuids128 = &DfuService::serviceUuid; fields.uuids128 = uuids128; fields.num_uuids128 = 2; fields.uuids128_is_complete = 1; @@ -213,7 +212,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); + // ble_gap_security_initiate(event->connect.conn_handle); } break; diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index b16df09f43..5293ed7bb1 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -3,7 +3,7 @@ "sources": [ { "file": "JetBrainsMono-Bold.ttf", - "range": "0x20-0x7e, 0x410-0x44f, 0xB0, 0xBF, 0xFFFD" + "range": "0x20-0x7e, 0x410-0x44f, 0xB0, 0xFFFD" }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", From f8b55d9b9737bacb3745674e573d3da59987b491 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 18:02:00 -0500 Subject: [PATCH 66/74] Added security initiate back for ancs to work. --- src/components/ble/NimbleController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index a7dfce4f9e..b40fe7a3c0 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -212,7 +212,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); + ble_gap_security_initiate(event->connect.conn_handle); } break; From b29d4fb6bd1217f99adecdea94fae7db72f27e53 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 18:12:49 -0500 Subject: [PATCH 67/74] Updated checks to prevent duplicate notification triggers, NEEDS testing but not issues so far. --- .../ble/AppleNotificationCenterClient.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index f5a82ce7d9..f2f5b8c232 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -183,12 +183,17 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, &ancsNotif.uuid); - bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; + //bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list + if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added)) { + return; + } + // The 6 is from TotalNbNotifications in NotificationManager.h + 1 while (notifications.size() > 6) { notifications.erase(notifications.begin()); @@ -196,14 +201,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (notifications.contains(ancsNotif.uuid)) { notifications[ancsNotif.uuid] = ancsNotif; - } else if (!silent) { + } else { notifications.insert({ancsNotif.uuid, ancsNotif}); } - if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added) || silent) { - return; - } - // Request ANCS more info // The +4 is for the "..." at the end of the string uint8_t titleSize = maxTitleSize + 4; @@ -326,7 +327,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } notificationManager.Push(std::move(notif)); - systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + // Only ping the system task if the notification was added + if (ancsNotif.eventId == static_cast(EventIds::Added)) { + systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); + } } } From da887a479f4efebdfc05575b763bc6c58c636100 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 22:00:34 -0500 Subject: [PATCH 68/74] Check for silent before ringing notification --- src/components/ble/AppleNotificationCenterClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index f2f5b8c232..5a7987b399 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -328,7 +328,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notificationManager.Push(std::move(notif)); // Only ping the system task if the notification was added - if (ancsNotif.eventId == static_cast(EventIds::Added)) { + if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } From 9244a3d6082652a9eb80cf01fa0db692b7122370 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 22:14:33 -0500 Subject: [PATCH 69/74] Fix typo in ping check --- src/components/ble/AppleNotificationCenterClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 5a7987b399..02cb75b8cc 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -328,7 +328,7 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { notificationManager.Push(std::move(notif)); // Only ping the system task if the notification was added - if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0) { + if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } } From 32e0cbe0b057c66c439f44a99304ac91fb1fdbec Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 21:44:17 -0500 Subject: [PATCH 70/74] ignore notifications not in list --- src/components/ble/AppleNotificationCenterClient.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 02cb75b8cc..2793976814 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -244,6 +244,10 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { if (notifications.contains(notificationUid)) { ancsNotif = notifications[notificationUid]; + } else { + // If the Notification source didn't add it earlier, then don't process it + NRF_LOG_INFO("Notification with UID %d not found in notifications map, ignoring datasource", notificationUid); + return; } std::string decodedTitle = DecodeUtf8String(event->notify_rx.om, titleSize, 8); From 59a6e8dabc16362bf39d0ab0bbe26ccaedb523bd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 22:17:11 -0500 Subject: [PATCH 71/74] Added a session uuid cache to try to help with duplicate pings --- .../ble/AppleNotificationCenterClient.cpp | 39 ++++++++++++++++++- .../ble/AppleNotificationCenterClient.h | 6 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 2793976814..e4240d5d3d 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -185,12 +185,31 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { //bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; // bool important = eventFlags & static_cast(EventFlags::Important); - bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; + //bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + // If notification was removed, we remove it from the notifications map + if (ancsNotif.eventId == static_cast(EventIds::Removed) && sessionNotificationUids.contains(ancsNotif.uuid)) { + sessionNotificationUids.erase(ancsNotif.uuid); + if (notifications.contains(ancsNotif.uuid)) { + notifications.erase(ancsNotif.uuid); + } + NRF_LOG_INFO("ANCS Notification removed: %d", ancsNotif.uuid); + return; + } + // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list - if (preExisting || ancsNotif.eventId != static_cast(EventIds::Added)) { + if (sessionNotificationUids.contains(ancsNotif.uuid)) { + return; + } + + // If new notification, add it to the sessionNotificationUids + if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { + sessionNotificationUids.insert({ancsNotif.uuid, false}); + } else { + // If the notification is not added, we ignore it + NRF_LOG_INFO("ANCS Notification not added, ignoring: %d", ancsNotif.uuid); return; } @@ -242,6 +261,19 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { AncsNotification ancsNotif; ancsNotif.uuid = 0; + // Check if the notification is in the session + if (sessionNotificationUids.contains(notificationUid)) { + if (sessionNotificationUids[notificationUid]) { + // If the notification is already processed, we ignore it + NRF_LOG_INFO("Notification with UID %d already processed, ignoring", notificationUid); + return; + } + } else { + // If the notification is not in the session, we ignore it + NRF_LOG_INFO("Notification with UID %d not found in session, ignoring", notificationUid); + return; + } + if (notifications.contains(notificationUid)) { ancsNotif = notifications[notificationUid]; } else { @@ -331,6 +363,9 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } notificationManager.Push(std::move(notif)); + // Mark the notification as processed in the session + sessionNotificationUids[notificationUid] = true; + // Only ping the system task if the notification was added if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index fd0bd9a2f3..6ecbe2ba59 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -45,6 +45,12 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; + // Keep track of the ANCS UUIDs in array for this session to avoid re-pings for old notifications + // Keep track of max notifications UUIDs at most + static constexpr uint8_t maxNotifications {200}; + // make this unordered map have a boolean attached to see if data has been received for this notification + std::unordered_map sessionNotificationUids {}; + // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 From 733935f4c6ab739f7f6b460bba1a463430e979e1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 22:18:45 -0500 Subject: [PATCH 72/74] clear session uids on reset --- src/components/ble/AppleNotificationCenterClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index e4240d5d3d..c190285e74 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -441,6 +441,7 @@ void AppleNotificationCenterClient::Reset() { isDataDescriptorFound = false; notifications.clear(); + sessionNotificationUids.clear(); } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { From 3a63df36fbf82ea2232d05b9e8030192605d2596 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 18 Jul 2025 12:20:16 -0500 Subject: [PATCH 73/74] removed extra array --- .../ble/AppleNotificationCenterClient.cpp | 46 ++++++++++--------- .../ble/AppleNotificationCenterClient.h | 7 +-- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index c190285e74..3ff0e96ab1 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -190,23 +190,22 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); // If notification was removed, we remove it from the notifications map - if (ancsNotif.eventId == static_cast(EventIds::Removed) && sessionNotificationUids.contains(ancsNotif.uuid)) { - sessionNotificationUids.erase(ancsNotif.uuid); - if (notifications.contains(ancsNotif.uuid)) { - notifications.erase(ancsNotif.uuid); - } + if (ancsNotif.eventId == static_cast(EventIds::Removed) && notifications.contains(ancsNotif.uuid)) { + notifications.erase(ancsNotif.uuid); NRF_LOG_INFO("ANCS Notification removed: %d", ancsNotif.uuid); return; } // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list - if (sessionNotificationUids.contains(ancsNotif.uuid)) { + if (notifications.contains(ancsNotif.uuid) || + (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0 || + (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0) { return; } - // If new notification, add it to the sessionNotificationUids + // If new notification, add it to the notifications if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { - sessionNotificationUids.insert({ancsNotif.uuid, false}); + notifications.insert({ancsNotif.uuid, ancsNotif}); } else { // If the notification is not added, we ignore it NRF_LOG_INFO("ANCS Notification not added, ignoring: %d", ancsNotif.uuid); @@ -214,15 +213,15 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // The 6 is from TotalNbNotifications in NotificationManager.h + 1 - while (notifications.size() > 6) { + while (notifications.size() > 100) { notifications.erase(notifications.begin()); } - if (notifications.contains(ancsNotif.uuid)) { - notifications[ancsNotif.uuid] = ancsNotif; - } else { - notifications.insert({ancsNotif.uuid, ancsNotif}); - } + // if (notifications.contains(ancsNotif.uuid)) { + // notifications[ancsNotif.uuid] = ancsNotif; + // } else { + // notifications.insert({ancsNotif.uuid, ancsNotif}); + // } // Request ANCS more info // The +4 is for the "..." at the end of the string @@ -262,8 +261,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { ancsNotif.uuid = 0; // Check if the notification is in the session - if (sessionNotificationUids.contains(notificationUid)) { - if (sessionNotificationUids[notificationUid]) { + if (notifications.contains(notificationUid)) { + if (notifications[notificationUid].isProcessed) { // If the notification is already processed, we ignore it NRF_LOG_INFO("Notification with UID %d already processed, ignoring", notificationUid); return; @@ -288,6 +287,9 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { std::string decodedMessage = DecodeUtf8String(event->notify_rx.om, messageSize, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2); + //Debug event ids ands flags by putting them at front of message (in int format) + //decodedMessage = std::to_string(ancsNotif.uuid) + " " + decodedMessage; + NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); @@ -363,13 +365,14 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } notificationManager.Push(std::move(notif)); - // Mark the notification as processed in the session - sessionNotificationUids[notificationUid] = true; - - // Only ping the system task if the notification was added - if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { + // Only ping the system task if the notification was added and ignore pre-existing notifications + if (ancsNotif.isProcessed == false && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0 && + (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) == 0) { systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification); } + + // Mark the notification as processed in the session + notifications[notificationUid].isProcessed = true; } } @@ -441,7 +444,6 @@ void AppleNotificationCenterClient::Reset() { isDataDescriptorFound = false; notifications.clear(); - sessionNotificationUids.clear(); } void AppleNotificationCenterClient::Discover(uint16_t connectionHandle, std::function onServiceDiscovered) { diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index 6ecbe2ba59..d6264efe75 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -45,12 +45,6 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; - // Keep track of the ANCS UUIDs in array for this session to avoid re-pings for old notifications - // Keep track of max notifications UUIDs at most - static constexpr uint8_t maxNotifications {200}; - // make this unordered map have a boolean attached to see if data has been received for this notification - std::unordered_map sessionNotificationUids {}; - // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 @@ -105,6 +99,7 @@ namespace Pinetime { uint8_t eventFlags {0}; uint8_t category {0}; uint32_t uuid {0}; + bool isProcessed {false}; }; std::unordered_map notifications; From 07f6b727b2985a877f5299672df58cc53964aa7c Mon Sep 17 00:00:00 2001 From: Liam Willey Date: Wed, 5 Nov 2025 10:56:15 -0500 Subject: [PATCH 74/74] Fix formatting --- .../ble/AppleNotificationCenterClient.cpp | 46 +++++++++---------- .../ble/AppleNotificationCenterClient.h | 3 +- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/components/ble/AppleNotificationCenterClient.cpp b/src/components/ble/AppleNotificationCenterClient.cpp index 3ff0e96ab1..b8f0508a32 100644 --- a/src/components/ble/AppleNotificationCenterClient.cpp +++ b/src/components/ble/AppleNotificationCenterClient.cpp @@ -85,19 +85,19 @@ int AppleNotificationCenterClient::OnCharacteristicsDiscoveryEvent(uint16_t conn onServiceDiscovered(connectionHandle); } } else if (characteristic != nullptr) { - if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); - notificationSourceHandle = characteristic->val_handle; - isCharacteristicDiscovered = true; - } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); - controlPointHandle = characteristic->val_handle; - isControlCharacteristicDiscovered = true; - } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); - dataSourceHandle = characteristic->val_handle; - isDataCharacteristicDiscovered = true; - } + if (ble_uuid_cmp(¬ificationSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Notification Source"); + notificationSourceHandle = characteristic->val_handle; + isCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&controlPointChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Control Point"); + controlPointHandle = characteristic->val_handle; + isControlCharacteristicDiscovered = true; + } else if (ble_uuid_cmp(&dataSourceChar.u, &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("ANCS Characteristic discovered: Data Source"); + dataSourceHandle = characteristic->val_handle; + isDataCharacteristicDiscovered = true; + } } return 0; } @@ -183,11 +183,11 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { // os_mbuf_copydata(event->notify_rx.om, 3, 1, &categoryCount); os_mbuf_copydata(event->notify_rx.om, 4, 4, &ancsNotif.uuid); - //bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; - // bool important = eventFlags & static_cast(EventFlags::Important); - //bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; - // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); - // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); + // bool silent = (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0; + // bool important = eventFlags & static_cast(EventFlags::Important); + // bool preExisting = (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0; + // bool positiveAction = eventFlags & static_cast(EventFlags::PositiveAction); + // bool negativeAction = eventFlags & static_cast(EventFlags::NegativeAction); // If notification was removed, we remove it from the notifications map if (ancsNotif.eventId == static_cast(EventIds::Removed) && notifications.contains(ancsNotif.uuid)) { @@ -197,14 +197,14 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { } // If the notification is pre-existing, or if it is a silent notification, we do not add it to the list - if (notifications.contains(ancsNotif.uuid) || - (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0 || + if (notifications.contains(ancsNotif.uuid) || (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) != 0 || (ancsNotif.eventFlags & static_cast(EventFlags::PreExisting)) != 0) { return; } // If new notification, add it to the notifications - if (ancsNotif.eventId == static_cast(EventIds::Added) && (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { + if (ancsNotif.eventId == static_cast(EventIds::Added) && + (ancsNotif.eventFlags & static_cast(EventFlags::Silent)) == 0) { notifications.insert({ancsNotif.uuid, ancsNotif}); } else { // If the notification is not added, we ignore it @@ -287,8 +287,8 @@ void AppleNotificationCenterClient::OnNotification(ble_gap_event* event) { std::string decodedMessage = DecodeUtf8String(event->notify_rx.om, messageSize, 8 + titleSize + 1 + 2 + subTitleSize + 1 + 2); - //Debug event ids ands flags by putting them at front of message (in int format) - //decodedMessage = std::to_string(ancsNotif.uuid) + " " + decodedMessage; + // Debug event ids ands flags by putting them at front of message (in int format) + // decodedMessage = std::to_string(ancsNotif.uuid) + " " + decodedMessage; NRF_LOG_INFO("Decoded Title: %s", decodedTitle.c_str()); NRF_LOG_INFO("Decoded SubTitle: %s", decodedSubTitle.c_str()); diff --git a/src/components/ble/AppleNotificationCenterClient.h b/src/components/ble/AppleNotificationCenterClient.h index d6264efe75..d6f4b03b56 100644 --- a/src/components/ble/AppleNotificationCenterClient.h +++ b/src/components/ble/AppleNotificationCenterClient.h @@ -45,7 +45,8 @@ namespace Pinetime { static constexpr uint8_t maxSubtitleSize {15}; static constexpr uint8_t maxMessageSize {120}; - // The Apple Notification Center Service UUID are from https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html + // The Apple Notification Center Service UUID are from + // https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html // 7905F431-B5CE-4E99-A40F-4B1E122D00D0 static constexpr ble_uuid128_t ancsUuid {