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

This commit is contained in:
JF 2020-09-27 20:59:06 +02:00
parent efd0c9eff7
commit f3728c41bb
5 changed files with 129 additions and 1 deletions

View file

@ -363,6 +363,7 @@ list(APPEND SOURCE_FILES
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 @@ set(INCLUDE_FILES
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

View file

@ -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;
}

View file

@ -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;
};
}
}

View file

@ -39,7 +39,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
alertNotificationClient{systemTask, notificationManager},
currentTimeService{dateTimeController},
musicService{systemTask},
batteryInformationService{batteryController} {
batteryInformationService{batteryController},
immediateAlertService{systemTask, notificationManager} {
}
@ -88,6 +89,7 @@ void NimbleController::Init() {
anService.Init();
dfuService.Init();
batteryInformationService.Init();
immediateAlertService.Init();
int res;
res = ble_hs_util_ensure_addr(0);
ASSERT(res == 0);

View file

@ -9,6 +9,7 @@
#include "CurrentTimeService.h"
#include "MusicService.h"
#include "BatteryInformationService.h"
#include "ImmediateAlertService.h"
#include <host/ble_gap.h>
namespace Pinetime {
@ -59,6 +60,7 @@ namespace Pinetime {
CurrentTimeService currentTimeService;
MusicService musicService;
BatteryInformationService batteryInformationService;
ImmediateAlertService immediateAlertService;
uint8_t addrType; // 1 = Random, 0 = PUBLIC
uint16_t connectionHandle = 0;