InfiniTime.git

commit f3728c41bb311f3838dc9c10a2157a16196b4420

Author: JF <jf@codingfield.com>

Add Immediate Alert Service, needed by the "Find Me" profile from BLE spec.

 src/CMakeLists.txt | 2 
 src/Components/Ble/ImmediateAlertService.cpp | 76 ++++++++++++++++++++++
 src/Components/Ble/ImmediateAlertService.h | 46 +++++++++++++
 src/Components/Ble/NimbleController.cpp | 4 
 src/Components/Ble/NimbleController.h | 2 


diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 57dbe8b975419313e9f00a4e8f30d99a2e08e27e..eee1d61ac2a6ecc1115c92a880607ce7cc89f9a7 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -363,6 +363,7 @@   Components/Ble/CurrentTimeService.cpp
   Components/Ble/AlertNotificationService.cpp
   Components/Ble/MusicService.cpp
   Components/Ble/BatteryInformationService.cpp
+  Components/Ble/ImmediateAlertService.cpp
   Components/FirmwareValidator/FirmwareValidator.cpp
   drivers/Cst816s.cpp
   FreeRTOS/port.c
@@ -437,6 +438,7 @@   Components/Ble/AlertNotificationClient.h
   Components/Ble/DfuService.h
   Components/FirmwareValidator/FirmwareValidator.h
   Components/Ble/BatteryInformationService.h
+  Components/Ble/ImmediateAlertService.h
   drivers/Cst816s.h
   FreeRTOS/portmacro.h
   FreeRTOS/portmacro_cmsis.h




diff --git a/src/Components/Ble/ImmediateAlertService.cpp b/src/Components/Ble/ImmediateAlertService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2c4cffb0d01bd76fb36c0fe1067add572b45b99
--- /dev/null
+++ b/src/Components/Ble/ImmediateAlertService.cpp
@@ -0,0 +1,76 @@
+#include "ImmediateAlertService.h"
+#include <SystemTask/SystemTask.h>
+#include "AlertNotificationService.h"
+
+using namespace Pinetime::Controllers;
+
+constexpr ble_uuid16_t ImmediateAlertService::immediateAlertServiceUuid;
+constexpr ble_uuid16_t ImmediateAlertService::alertLevelUuid;
+
+namespace {
+  int AlertLevelCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
+    auto *immediateAlertService = static_cast<ImmediateAlertService *>(arg);
+    return immediateAlertService->OnAlertLevelChanged(conn_handle, attr_handle, ctxt);
+  }
+
+  const char* ToString(ImmediateAlertService::Levels level) {
+    switch (level) {
+      case ImmediateAlertService::Levels::NoAlert: return "Alert : None";
+      case ImmediateAlertService::Levels::HighAlert: return "Alert : High";
+      case ImmediateAlertService::Levels::MildAlert: return "Alert : Mild";
+      default: return "";
+    }
+  }
+}
+
+ImmediateAlertService::ImmediateAlertService(Pinetime::System::SystemTask &systemTask,
+                                             Pinetime::Controllers::NotificationManager &notificationManager) :
+        systemTask{systemTask},
+        notificationManager{notificationManager},
+        characteristicDefinition{
+                {
+                        .uuid = (ble_uuid_t *) &alertLevelUuid,
+                        .access_cb = AlertLevelCallback,
+                        .arg = this,
+                        .flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
+                        .val_handle = &alertLevelHandle
+                },
+                {
+                        0
+                }
+        },
+        serviceDefinition{
+                {
+                        /* Device Information Service */
+                        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+                        .uuid = (ble_uuid_t *) &immediateAlertServiceUuid,
+                        .characteristics = characteristicDefinition
+                },
+                {
+                        0
+                },
+        }{
+
+}
+
+void ImmediateAlertService::Init() {
+  int res = 0;
+  res = ble_gatts_count_cfg(serviceDefinition);
+  ASSERT(res == 0);
+
+  res = ble_gatts_add_svcs(serviceDefinition);
+  ASSERT(res == 0);
+}
+
+int ImmediateAlertService::OnAlertLevelChanged(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context) {
+  if(attributeHandle == alertLevelHandle) {
+    if(context->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+      auto alertLevel = static_cast<Levels>(context->om->om_data[0]);
+      auto* alertString = ToString(alertLevel);
+      notificationManager.Push(Pinetime::Controllers::NotificationManager::Categories::SimpleAlert, alertString, strlen(alertString));
+      systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification);
+    }
+  }
+
+  return 0;
+}
\ No newline at end of file




diff --git a/src/Components/Ble/ImmediateAlertService.h b/src/Components/Ble/ImmediateAlertService.h
new file mode 100644
index 0000000000000000000000000000000000000000..c42846c485cd9fe25713bcc511674ee3ba9c87f9
--- /dev/null
+++ b/src/Components/Ble/ImmediateAlertService.h
@@ -0,0 +1,46 @@
+#pragma once
+#include <host/ble_gap.h>
+
+namespace Pinetime {
+  namespace System {
+    class SystemTask;
+  }
+  namespace Controllers {
+    class NotificationManager;
+    class ImmediateAlertService {
+      public:
+        enum class Levels : uint8_t {
+            NoAlert = 0,
+            MildAlert = 1,
+            HighAlert = 2
+        };
+
+        ImmediateAlertService(Pinetime::System::SystemTask &systemTask,
+                              Pinetime::Controllers::NotificationManager &notificationManager);
+        void Init();
+        int OnAlertLevelChanged(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
+
+      private:
+        Pinetime::System::SystemTask& systemTask;
+        NotificationManager& notificationManager;
+
+        static constexpr uint16_t immediateAlertServiceId {0x1802};
+        static constexpr uint16_t alertLevelId {0x2A06};
+
+        static constexpr ble_uuid16_t immediateAlertServiceUuid {
+                .u {.type = BLE_UUID_TYPE_16},
+                .value = immediateAlertServiceId
+        };
+
+        static constexpr ble_uuid16_t alertLevelUuid {
+                .u {.type = BLE_UUID_TYPE_16},
+                .value = alertLevelId
+        };
+
+        struct ble_gatt_chr_def characteristicDefinition[3];
+        struct ble_gatt_svc_def serviceDefinition[2];
+
+        uint16_t alertLevelHandle;
+    };
+  }
+}




diff --git a/src/Components/Ble/NimbleController.cpp b/src/Components/Ble/NimbleController.cpp
index a8add0dfcccbc93b4fc9de3640dff05a32d158db..b13f9ce3bf7888df78e000a0653bd29afaeac5ad 100644
--- a/src/Components/Ble/NimbleController.cpp
+++ b/src/Components/Ble/NimbleController.cpp
@@ -39,7 +39,8 @@         anService{systemTask, notificationManager},
         alertNotificationClient{systemTask, notificationManager},
         currentTimeService{dateTimeController},
         musicService{systemTask},
-        batteryInformationService{batteryController} {
+        batteryInformationService{batteryController},
+        immediateAlertService{systemTask, notificationManager} {
 
 }
 
@@ -88,6 +89,7 @@   musicService.Init();
   anService.Init();
   dfuService.Init();
   batteryInformationService.Init();
+  immediateAlertService.Init();
   int res;
   res = ble_hs_util_ensure_addr(0);
   ASSERT(res == 0);




diff --git a/src/Components/Ble/NimbleController.h b/src/Components/Ble/NimbleController.h
index 2dee8987a18737ac12a94bf4a54a326efa575595..89fa4250e692fa387dd7e1e615e369c09883213a 100644
--- a/src/Components/Ble/NimbleController.h
+++ b/src/Components/Ble/NimbleController.h
@@ -9,6 +9,7 @@ #include "DfuService.h"
 #include "CurrentTimeService.h"
 #include "MusicService.h"
 #include "BatteryInformationService.h"
+#include "ImmediateAlertService.h"
 #include <host/ble_gap.h>
 
 namespace Pinetime {
@@ -59,6 +60,7 @@         AlertNotificationClient alertNotificationClient;
         CurrentTimeService currentTimeService;
         MusicService musicService;
         BatteryInformationService batteryInformationService;
+        ImmediateAlertService immediateAlertService;
 
         uint8_t addrType; // 1 = Random, 0 = PUBLIC
         uint16_t connectionHandle = 0;