|
| 1 | +#include "HeartRateService.h" |
| 2 | +#include "components/heartrate/HeartRateController.h" |
| 3 | +#include "systemtask/SystemTask.h" |
| 4 | + |
| 5 | +using namespace Pinetime::Controllers; |
| 6 | + |
| 7 | +constexpr ble_uuid16_t HeartRateService::heartRateServiceUuid; |
| 8 | +constexpr ble_uuid16_t HeartRateService::heartRateMeasurementUuid; |
| 9 | + |
| 10 | +namespace { |
| 11 | + int HeartRateServiceServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { |
| 12 | + auto* heartRateService = static_cast<HeartRateService*>(arg); |
| 13 | + return heartRateService->OnHeartRateRequested(conn_handle, attr_handle, ctxt); |
| 14 | + } |
| 15 | +} |
| 16 | + |
| 17 | +// TODO Refactoring - remove dependency to SystemTask |
| 18 | +HeartRateService::HeartRateService(Pinetime::System::SystemTask &system, Controllers::HeartRateController& heartRateController) : |
| 19 | + system{system}, |
| 20 | + heartRateController{heartRateController}, |
| 21 | + characteristicDefinition{ |
| 22 | + { |
| 23 | + .uuid = (ble_uuid_t *) &heartRateMeasurementUuid, |
| 24 | + .access_cb = HeartRateServiceServiceCallback, |
| 25 | + .arg = this, |
| 26 | + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, |
| 27 | + .val_handle = &heartRateMeasurementHandle |
| 28 | + }, |
| 29 | + { |
| 30 | + 0 |
| 31 | + } |
| 32 | + }, |
| 33 | + serviceDefinition{ |
| 34 | + { |
| 35 | + /* Device Information Service */ |
| 36 | + .type = BLE_GATT_SVC_TYPE_PRIMARY, |
| 37 | + .uuid = (ble_uuid_t *) &heartRateServiceUuid, |
| 38 | + .characteristics = characteristicDefinition |
| 39 | + }, |
| 40 | + { |
| 41 | + 0 |
| 42 | + }, |
| 43 | + }{ |
| 44 | + // TODO refactor to prevent this loop dependency (service depends on controller and controller depends on service) |
| 45 | + heartRateController.SetService(this); |
| 46 | +} |
| 47 | + |
| 48 | +void HeartRateService::Init() { |
| 49 | + int res = 0; |
| 50 | + res = ble_gatts_count_cfg(serviceDefinition); |
| 51 | + ASSERT(res == 0); |
| 52 | + |
| 53 | + res = ble_gatts_add_svcs(serviceDefinition); |
| 54 | + ASSERT(res == 0); |
| 55 | +} |
| 56 | + |
| 57 | +int HeartRateService::OnHeartRateRequested(uint16_t connectionHandle, uint16_t attributeHandle, |
| 58 | + ble_gatt_access_ctxt *context) { |
| 59 | + if(attributeHandle == heartRateMeasurementHandle) { |
| 60 | + NRF_LOG_INFO("BATTERY : handle = %d", heartRateMeasurementHandle); |
| 61 | + static uint8_t batteryValue = heartRateController.HeartRate(); |
| 62 | + |
| 63 | + uint8_t buffer[2] = {0, heartRateController.HeartRate()}; // [0] = flags, [1] = hr value |
| 64 | + |
| 65 | + int res = os_mbuf_append(context->om, buffer, 2); |
| 66 | + return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; |
| 67 | + } |
| 68 | + return 0; |
| 69 | +} |
| 70 | + |
| 71 | +void HeartRateService::OnNewHeartRateValue(uint8_t heartRateValue) { |
| 72 | + uint8_t buffer[2] = {0, heartRateController.HeartRate()}; // [0] = flags, [1] = hr value |
| 73 | + auto *om = ble_hs_mbuf_from_flat(buffer, 2); |
| 74 | + |
| 75 | + uint16_t connectionHandle = system.nimble().connHandle(); |
| 76 | + |
| 77 | + if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) { |
| 78 | + return; |
| 79 | + } |
| 80 | + |
| 81 | + ble_gattc_notify_custom(connectionHandle, heartRateMeasurementHandle, om); |
| 82 | +} |
0 commit comments