diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 653151dc..fc22c9a9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -318,6 +318,7 @@ list(APPEND SOURCE_FILES Components/Brightness/BrightnessController.cpp Components/Ble/NimbleController.cpp Components/Ble/DeviceInformationService.cpp + Components/Ble/CurrentTimeClient.cpp drivers/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c @@ -364,6 +365,7 @@ set(INCLUDE_FILES Components/Brightness/BrightnessController.h Components/Ble/NimbleController.h Components/Ble/DeviceInformationService.h + Components/Ble/CurrentTimeClient.h drivers/Cst816s.h FreeRTOS/portmacro.h FreeRTOS/portmacro_cmsis.h diff --git a/src/Components/Ble/CurrentTimeClient.cpp b/src/Components/Ble/CurrentTimeClient.cpp new file mode 100644 index 00000000..524c37d5 --- /dev/null +++ b/src/Components/Ble/CurrentTimeClient.cpp @@ -0,0 +1,78 @@ +#include +#include "CurrentTimeClient.h" + +using namespace Pinetime::Controllers; + +constexpr ble_uuid16_t CurrentTimeClient::ctsServiceUuid; +constexpr ble_uuid16_t CurrentTimeClient::currentTimeCharacteristicUuid; + +int Pinetime::Controllers::CurrentTimeDiscoveryEventCallback(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 Pinetime::Controllers::CurrentTimeCharacteristicDiscoveredCallback(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->OnCharacteristicDiscoveryEvent(conn_handle, error, chr); +} + +int Pinetime::Controllers::CurrentTimeReadCallback(uint16_t conn_handle, const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) { + auto client = static_cast(arg); + return client->OnCurrentTimeReadResult(conn_handle, error, attr); +} + + +CurrentTimeClient::CurrentTimeClient(DateTime& dateTimeController) : dateTimeController{dateTimeController} { + +} + +void CurrentTimeClient::Init() { + +} + +void CurrentTimeClient::StartDiscovery(uint16_t connectionHandle) { + ble_gattc_disc_svc_by_uuid(connectionHandle, ((ble_uuid_t*)&ctsServiceUuid), CurrentTimeDiscoveryEventCallback, this); +} + +int CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service) { + if(service == nullptr && error->status == BLE_HS_EDONE) + NRF_LOG_INFO("Discovery complete"); + + if(service != nullptr && ble_uuid_cmp(((ble_uuid_t*)&ctsServiceUuid), &service->uuid.u) == 0) { + NRF_LOG_INFO("CTS discovered : 0x%x", service->start_handle); + ble_gattc_disc_chrs_by_uuid(connectionHandle, service->start_handle, service->end_handle, ((ble_uuid_t*)¤tTimeCharacteristicUuid), CurrentTimeCharacteristicDiscoveredCallback, this); + } + return 0; +} + +int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error, + const ble_gatt_chr *characteristic) { + if(characteristic == nullptr && error->status == BLE_HS_EDONE) + NRF_LOG_INFO("Characteristic discovery complete"); + + if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)¤tTimeCharacteristicUuid), &characteristic->uuid.u) == 0) { + NRF_LOG_INFO("CTS Characteristic discovered : 0x%x", characteristic->val_handle); + + ble_gattc_read(conn_handle, characteristic->val_handle, CurrentTimeReadCallback, this); + } + return 0; +} + +int CurrentTimeClient::OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error *error, const ble_gatt_attr *attribute) { + if(error->status == 0) { + // TODO check that attribute->handle equals the handle discovered in OnCharacteristicDiscoveryEvent + CtsData result; + os_mbuf_copydata(attribute->om, 0, sizeof(CtsData), &result); + NRF_LOG_INFO("Received data: %d-%d-%d %d:%d:%d", result.year, + result.month, result.dayofmonth, + result.hour, result.minute, result.second); + dateTimeController.SetTime(result.year, result.month, result.dayofmonth, + 0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG)); + } else { + NRF_LOG_INFO("Error retrieving current time: %d", error->status); + } + return 0; +} diff --git a/src/Components/Ble/CurrentTimeClient.h b/src/Components/Ble/CurrentTimeClient.h new file mode 100644 index 00000000..94892cef --- /dev/null +++ b/src/Components/Ble/CurrentTimeClient.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include +#include + +namespace Pinetime { + namespace Controllers { + int CurrentTimeDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error *error, + const struct ble_gatt_svc *service, void *arg); + int CurrentTimeCharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error, + const struct ble_gatt_chr *chr, void *arg); + int CurrentTimeReadCallback(uint16_t conn_handle, const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg); + + class CurrentTimeClient { + public: + explicit CurrentTimeClient(DateTime& dateTimeController); + void Init(); + int OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service); + int OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error, + const ble_gatt_chr *characteristic); + int OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error *error, const ble_gatt_attr *attribute); + + + void StartDiscovery(uint16_t connectionHandle); + private: + typedef struct __attribute__((packed)) { + uint16_t year; + uint8_t month; + uint8_t dayofmonth; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t millis; + uint8_t reason; + } CtsData; + + static constexpr uint16_t ctsServiceId {0x1805}; + static constexpr uint16_t currentTimeCharacteristicId {0x2a2b}; + + static constexpr ble_uuid16_t ctsServiceUuid { + .u { .type = BLE_UUID_TYPE_16 }, + .value = ctsServiceId + }; + static constexpr ble_uuid16_t currentTimeCharacteristicUuid { + .u { .type = BLE_UUID_TYPE_16 }, + .value = currentTimeCharacteristicId + }; + + DateTime& dateTimeController; + }; + } +} \ No newline at end of file diff --git a/src/Components/Ble/NimbleController.cpp b/src/Components/Ble/NimbleController.cpp index acee6651..cedc9f60 100644 --- a/src/Components/Ble/NimbleController.cpp +++ b/src/Components/Ble/NimbleController.cpp @@ -14,12 +14,8 @@ using namespace Pinetime::Controllers; // TODO c++ify the following code // - cts should be in it own class -NimbleController::NimbleController(DateTime& datetimeController) : dateTimeController{datetimeController} { - ctsUuid.u.type = BLE_UUID_TYPE_16; - ctsUuid.value = BleGatServiceCts; - - ctsCurrentTimeUuid.u.type = BLE_UUID_TYPE_16; - ctsCurrentTimeUuid.value = bleGattCharacteristicCurrentTime; +NimbleController::NimbleController(DateTime &datetimeController) : dateTimeController{datetimeController}, + currentTimeClient{datetimeController} { } @@ -28,24 +24,6 @@ int GAPEventCallback(struct ble_gap_event *event, void *arg) { return nimbleController->OnGAPEvent(event); } -int DiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error *error, - const struct ble_gatt_svc *service, void *arg) { - auto nimbleController = static_cast(arg); - return nimbleController->OnDiscoveryEvent(conn_handle, error, service); -} - -int CharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error, - const struct ble_gatt_chr *chr, void *arg) { - auto nimbleController = static_cast(arg); - return nimbleController->OnCharacteristicDiscoveryEvent(conn_handle, error, chr); -} - -static int CurrentTimeReadCallback(uint16_t conn_handle, const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, void *arg) { - auto nimbleController = static_cast(arg); - return nimbleController->OnCurrentTimeReadResult(conn_handle, error, attr); -} - void NimbleController::Init() { while (!ble_hs_synced()) {} @@ -53,6 +31,7 @@ void NimbleController::Init() { ble_svc_gatt_init(); deviceInformationService.Init(); + currentTimeClient.Init(); int res; res = ble_hs_util_ensure_addr(0); res = ble_hs_id_infer_auto(0, &addrType); @@ -123,8 +102,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) { StartAdvertising(); } else { connectionHandle = event->connect.conn_handle; - - ble_gattc_disc_svc_by_uuid(connectionHandle, ((ble_uuid_t*)&ctsUuid), DiscoveryEventCallback, this); + currentTimeClient.StartDiscovery(connectionHandle); } } break; @@ -184,48 +162,6 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) { return 0; } -int NimbleController::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service) { - if(service == nullptr && error->status == BLE_HS_EDONE) - NRF_LOG_INFO("Discovery complete"); - - if(service != nullptr && ble_uuid_cmp(((ble_uuid_t*)&ctsUuid), &service->uuid.u) == 0) { - NRF_LOG_INFO("CTS discovered : 0x%x", service->start_handle); - ble_gattc_disc_chrs_by_uuid(connectionHandle, service->start_handle, service->end_handle, ((ble_uuid_t*)&ctsCurrentTimeUuid), CharacteristicDiscoveredCallback, this); - } - - return 0; -} - -int NimbleController::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error, - const ble_gatt_chr *characteristic) { - if(characteristic == nullptr && error->status == BLE_HS_EDONE) - NRF_LOG_INFO("Characteristic discovery complete"); - - if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&ctsCurrentTimeUuid), &characteristic->uuid.u) == 0) { - NRF_LOG_INFO("CTS Characteristic discovered : 0x%x", characteristic->val_handle); - - ble_gattc_read(conn_handle, characteristic->val_handle, CurrentTimeReadCallback, this); - } - return 0; -} - -int NimbleController::OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error *error, const ble_gatt_attr *attribute) { - if(error->status == 0) { - // TODO check that attribute->handle equals the handle discovered in OnCharacteristicDiscoveryEvent - CtsData result; - os_mbuf_copydata(attribute->om, 0, sizeof(CtsData), &result); - NRF_LOG_INFO("Received data: %d-%d-%d %d:%d:%d", result.year, - result.month, result.dayofmonth, - result.hour, result.minute, result.second); - dateTimeController.SetTime(result.year, result.month, result.dayofmonth, - 0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG)); - } else { - NRF_LOG_INFO("Error retrieving current time: %d", error->status); - } - return 0; -} - - diff --git a/src/Components/Ble/NimbleController.h b/src/Components/Ble/NimbleController.h index ce51527e..2a396949 100644 --- a/src/Components/Ble/NimbleController.h +++ b/src/Components/Ble/NimbleController.h @@ -3,6 +3,7 @@ #include #include "DeviceInformationService.h" +#include "CurrentTimeClient.h" #include namespace Pinetime { @@ -14,34 +15,12 @@ namespace Pinetime { void Init(); void StartAdvertising(); int OnGAPEvent(ble_gap_event *event); - int OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service); - int - OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error, - const ble_gatt_chr *characteristic); - int OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error *error, const ble_gatt_attr *attribute); + private: static constexpr char* deviceName = "Pinetime-JF"; - static constexpr uint16_t BleGatServiceCts = 0x1805; - - typedef struct __attribute__((packed)) { - uint16_t year; - uint8_t month; - uint8_t dayofmonth; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t millis; - uint8_t reason; - } CtsData; - DateTime& dateTimeController; DeviceInformationService deviceInformationService; - - ble_uuid16_t ctsUuid; - - static constexpr uint16_t bleGattCharacteristicCurrentTime = 0x2a2b; - ble_uuid16_t ctsCurrentTimeUuid; - + CurrentTimeClient currentTimeClient; uint8_t addrType; uint16_t connectionHandle; };