Skip to content

Commit 0e97db1

Browse files
authored
Merge pull request #118 from JF002/improve-ble-connection
Improve ble connection
2 parents cb9e881 + 29f8074 commit 0e97db1

10 files changed

Lines changed: 288 additions & 230 deletions

src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ list(APPEND SOURCE_FILES
369369
components/ble/MusicService.cpp
370370
components/ble/BatteryInformationService.cpp
371371
components/ble/ImmediateAlertService.cpp
372+
components/ble/ServiceDiscovery.cpp
372373
components/firmwarevalidator/FirmwareValidator.cpp
373374
drivers/Cst816s.cpp
374375
FreeRTOS/port.c
@@ -447,6 +448,8 @@ set(INCLUDE_FILES
447448
components/firmwarevalidator/FirmwareValidator.h
448449
components/ble/BatteryInformationService.h
449450
components/ble/ImmediateAlertService.h
451+
components/ble/ServiceDiscovery.h
452+
components/ble/BleClient.h
450453
drivers/Cst816s.h
451454
FreeRTOS/portmacro.h
452455
FreeRTOS/portmacro_cmsis.h

src/components/ble/AlertNotificationClient.cpp

Lines changed: 106 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,139 +3,192 @@
33

44
#include "AlertNotificationClient.h"
55

6-
76
using namespace Pinetime::Controllers;
87
constexpr ble_uuid16_t AlertNotificationClient::ansServiceUuid;
9-
108
constexpr ble_uuid16_t AlertNotificationClient::supportedNewAlertCategoryUuid;
11-
constexpr ble_uuid16_t AlertNotificationClient::supportedUnreadAlertCategoryUuid ;
9+
constexpr ble_uuid16_t AlertNotificationClient::supportedUnreadAlertCategoryUuid;
1210
constexpr ble_uuid16_t AlertNotificationClient::newAlertUuid;
1311
constexpr ble_uuid16_t AlertNotificationClient::unreadAlertStatusUuid;
1412
constexpr ble_uuid16_t AlertNotificationClient::controlPointUuid;
1513

16-
int Pinetime::Controllers::NewAlertSubcribeCallback(uint16_t conn_handle,
17-
const struct ble_gatt_error *error,
18-
struct ble_gatt_attr *attr,
19-
void *arg) {
20-
auto client = static_cast<AlertNotificationClient*>(arg);
21-
return client->OnNewAlertSubcribe(conn_handle, error, attr);
22-
}
14+
namespace {
15+
int
16+
OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service,
17+
void *arg) {
18+
auto client = static_cast<AlertNotificationClient *>(arg);
19+
return client->OnDiscoveryEvent(conn_handle, error, service);
20+
}
2321

24-
AlertNotificationClient::AlertNotificationClient(Pinetime::System::SystemTask& systemTask,
25-
Pinetime::Controllers::NotificationManager& notificationManager) :
26-
systemTask{systemTask}, notificationManager{notificationManager}{
22+
int OnAlertNotificationCharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error,
23+
const struct ble_gatt_chr *chr, void *arg) {
24+
auto client = static_cast<AlertNotificationClient *>(arg);
25+
return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr);
26+
}
27+
28+
int OnAlertNotificationDescriptorDiscoveryEventCallback(uint16_t conn_handle,
29+
const struct ble_gatt_error *error,
30+
uint16_t chr_val_handle,
31+
const struct ble_gatt_dsc *dsc,
32+
void *arg) {
33+
auto client = static_cast<AlertNotificationClient *>(arg);
34+
return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc);
35+
}
36+
37+
int NewAlertSubcribeCallback(uint16_t conn_handle,
38+
const struct ble_gatt_error *error,
39+
struct ble_gatt_attr *attr,
40+
void *arg) {
41+
auto client = static_cast<AlertNotificationClient *>(arg);
42+
return client->OnNewAlertSubcribe(conn_handle, error, attr);
43+
}
44+
}
2745

46+
AlertNotificationClient::AlertNotificationClient(Pinetime::System::SystemTask &systemTask,
47+
Pinetime::Controllers::NotificationManager &notificationManager) :
48+
systemTask{systemTask}, notificationManager{notificationManager} {
2849
}
2950

30-
bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service) {
31-
if(service == nullptr && error->status == BLE_HS_EDONE) {
32-
NRF_LOG_INFO("ANS Discovery complete");
51+
bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
52+
const ble_gatt_svc *service) {
53+
if (service == nullptr && error->status == BLE_HS_EDONE) {
54+
if (isDiscovered) {
55+
NRF_LOG_INFO("ANS Discovery found, starting characteristics discovery");
56+
57+
ble_gattc_disc_all_chrs(connectionHandle, ansStartHandle, ansEndHandle,
58+
OnAlertNotificationCharacteristicDiscoveredCallback, this);
59+
} else {
60+
NRF_LOG_INFO("ANS not found");
61+
onServiceDiscovered(connectionHandle);
62+
}
3363
return true;
3464
}
3565

36-
if(service != nullptr && ble_uuid_cmp(((ble_uuid_t*)&ansServiceUuid), &service->uuid.u) == 0) {
37-
NRF_LOG_INFO("ANS discovered : 0x%x", service->start_handle);
38-
ansStartHandle = service->start_handle;
39-
ansEndHandle = service->end_handle;
40-
isDiscovered = true;
66+
if (service != nullptr && ble_uuid_cmp(((ble_uuid_t *) &ansServiceUuid), &service->uuid.u) == 0) {
67+
NRF_LOG_INFO("ANS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle);
68+
ansStartHandle = service->start_handle;
69+
ansEndHandle = service->end_handle;
70+
isDiscovered = true;
4171
}
4272
return false;
4373
}
4474

4575
int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
46-
const ble_gatt_chr *characteristic) {
47-
if(error->status != 0 && error->status != BLE_HS_EDONE) {
76+
const ble_gatt_chr *characteristic) {
77+
if (error->status != 0 && error->status != BLE_HS_EDONE) {
4878
NRF_LOG_INFO("ANS Characteristic discovery ERROR");
79+
onServiceDiscovered(connectionHandle);
4980
return 0;
5081
}
5182

52-
if(characteristic == nullptr && error->status == BLE_HS_EDONE) {
83+
if (characteristic == nullptr && error->status == BLE_HS_EDONE) {
5384
NRF_LOG_INFO("ANS Characteristic discovery complete");
85+
if (isCharacteristicDiscovered) {
86+
ble_gattc_disc_all_dscs(connectionHandle,
87+
newAlertHandle, ansEndHandle,
88+
OnAlertNotificationDescriptorDiscoveryEventCallback, this);
89+
} else
90+
onServiceDiscovered(connectionHandle);
5491
} else {
55-
if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) {
92+
if (characteristic != nullptr &&
93+
ble_uuid_cmp(((ble_uuid_t *) &supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) {
5694
NRF_LOG_INFO("ANS Characteristic discovered : supportedNewAlertCategoryUuid");
5795
supportedNewAlertCategoryHandle = characteristic->val_handle;
58-
} else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) {
96+
} else if (characteristic != nullptr &&
97+
ble_uuid_cmp(((ble_uuid_t *) &supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) {
5998
NRF_LOG_INFO("ANS Characteristic discovered : supportedUnreadAlertCategoryUuid");
6099
supportedUnreadAlertCategoryHandle = characteristic->val_handle;
61-
} else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&newAlertUuid), &characteristic->uuid.u) == 0) {
100+
} else if (characteristic != nullptr &&
101+
ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &characteristic->uuid.u) == 0) {
62102
NRF_LOG_INFO("ANS Characteristic discovered : newAlertUuid");
63103
newAlertHandle = characteristic->val_handle;
64104
newAlertDefHandle = characteristic->def_handle;
65-
} else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&unreadAlertStatusUuid), &characteristic->uuid.u) == 0) {
105+
isCharacteristicDiscovered = true;
106+
} else if (characteristic != nullptr &&
107+
ble_uuid_cmp(((ble_uuid_t *) &unreadAlertStatusUuid), &characteristic->uuid.u) == 0) {
66108
NRF_LOG_INFO("ANS Characteristic discovered : unreadAlertStatusUuid");
67109
unreadAlertStatusHandle = characteristic->val_handle;
68-
} else if(characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*)&controlPointUuid), &characteristic->uuid.u) == 0) {
110+
} else if (characteristic != nullptr &&
111+
ble_uuid_cmp(((ble_uuid_t *) &controlPointUuid), &characteristic->uuid.u) == 0) {
69112
NRF_LOG_INFO("ANS Characteristic discovered : controlPointUuid");
70113
controlPointHandle = characteristic->val_handle;
71-
}else
72-
NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle);
73-
}
114+
} else NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle);
115+
}
74116
return 0;
75117
}
76118

77119
int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error *error,
78120
ble_gatt_attr *attribute) {
79-
if(error->status == 0) {
121+
if (error->status == 0) {
80122
NRF_LOG_INFO("ANS New alert subscribe OK");
81123
} else {
82124
NRF_LOG_INFO("ANS New alert subscribe ERROR");
83125
}
126+
onServiceDiscovered(connectionHandle);
84127

85128
return 0;
86129
}
87130

88131
int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
89132
uint16_t characteristicValueHandle,
90133
const ble_gatt_dsc *descriptor) {
91-
if(error->status == 0) {
92-
if(characteristicValueHandle == newAlertHandle && ble_uuid_cmp(((ble_uuid_t*)&newAlertUuid), &descriptor->uuid.u)) {
93-
if(newAlertDescriptorHandle == 0) {
134+
if (error->status == 0) {
135+
if (characteristicValueHandle == newAlertHandle &&
136+
ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &descriptor->uuid.u)) {
137+
if (newAlertDescriptorHandle == 0) {
94138
NRF_LOG_INFO("ANS Descriptor discovered : %d", descriptor->handle);
95139
newAlertDescriptorHandle = descriptor->handle;
140+
isDescriptorFound = true;
96141
uint8_t value[2];
97142
value[0] = 1;
98143
value[1] = 0;
99144
ble_gattc_write_flat(connectionHandle, newAlertDescriptorHandle, value, sizeof(value), NewAlertSubcribeCallback, this);
100145
}
101146
}
147+
} else {
148+
if (!isDescriptorFound)
149+
onServiceDiscovered(connectionHandle);
102150
}
103151
return 0;
104152
}
105153

106154
void AlertNotificationClient::OnNotification(ble_gap_event *event) {
107-
if(event->notify_rx.attr_handle == newAlertHandle) {
155+
if (event->notify_rx.attr_handle == newAlertHandle) {
108156
constexpr size_t stringTerminatorSize = 1; // end of string '\0'
109157
constexpr size_t headerSize = 3;
110-
const auto maxMessageSize {NotificationManager::MaximumMessageSize()};
158+
const auto maxMessageSize{NotificationManager::MaximumMessageSize()};
111159
const auto maxBufferSize{maxMessageSize + headerSize};
112160

113161
const auto dbgPacketLen = OS_MBUF_PKTLEN(event->notify_rx.om);
114162
size_t bufferSize = min(dbgPacketLen + stringTerminatorSize, maxBufferSize);
115-
auto messageSize = min(maxMessageSize, (bufferSize-headerSize));
163+
auto messageSize = min(maxMessageSize, (bufferSize - headerSize));
116164

117165
NotificationManager::Notification notif;
118-
os_mbuf_copydata(event->notify_rx.om, headerSize, messageSize-1, notif.message.data());
119-
notif.message[messageSize-1] = '\0';
166+
os_mbuf_copydata(event->notify_rx.om, headerSize, messageSize - 1, notif.message.data());
167+
notif.message[messageSize - 1] = '\0';
120168
notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert;
121169
notificationManager.Push(std::move(notif));
122170

123171
systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification);
124172
}
125173
}
126174

127-
bool AlertNotificationClient::IsDiscovered() const {
128-
return isDiscovered;
129-
}
130-
131-
uint16_t AlertNotificationClient::StartHandle() const {
132-
return ansStartHandle;
133-
}
134-
135-
uint16_t AlertNotificationClient::EndHandle() const {
136-
return ansEndHandle;
175+
void AlertNotificationClient::Reset() {
176+
ansStartHandle = 0;
177+
ansEndHandle = 0;
178+
supportedNewAlertCategoryHandle = 0;
179+
supportedUnreadAlertCategoryHandle = 0;
180+
newAlertHandle = 0;
181+
newAlertDescriptorHandle = 0;
182+
newAlertDefHandle = 0;
183+
unreadAlertStatusHandle = 0;
184+
controlPointHandle = 0;
185+
isDiscovered = false;
186+
isCharacteristicDiscovered = false;
187+
isDescriptorFound = false;
137188
}
138189

139-
uint16_t AlertNotificationClient::NewAlerthandle() const {
140-
return newAlertHandle;
190+
void AlertNotificationClient::Discover(uint16_t connectionHandle, std::function<void(uint16_t)> onServiceDiscovered) {
191+
NRF_LOG_INFO("[ANS] Starting discovery");
192+
this->onServiceDiscovered = onServiceDiscovered;
193+
ble_gattc_disc_svc_by_uuid(connectionHandle, &ansServiceUuid.u, OnDiscoveryEventCallback, this);
141194
}

src/components/ble/AlertNotificationClient.h

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@
33
#include <cstdint>
44
#include <array>
55
#include <host/ble_gap.h>
6+
#include "BleClient.h"
67

78

89
namespace Pinetime {
910
namespace Controllers {
10-
int NewAlertSubcribeCallback(uint16_t conn_handle,
11-
const struct ble_gatt_error *error,
12-
struct ble_gatt_attr *attr,
13-
void *arg);
14-
15-
class AlertNotificationClient {
11+
class AlertNotificationClient : public BleClient {
1612
public:
1713
explicit AlertNotificationClient(Pinetime::System::SystemTask &systemTask,
1814
Pinetime::Controllers::NotificationManager &notificationManager);
@@ -24,13 +20,9 @@ namespace Pinetime {
2420
int OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
2521
uint16_t characteristicValueHandle, const ble_gatt_dsc *descriptor);
2622
void OnNotification(ble_gap_event *event);
27-
bool IsDiscovered() const;
28-
uint16_t StartHandle() const;
29-
uint16_t EndHandle() const;
30-
31-
static constexpr const ble_uuid16_t &Uuid() { return ansServiceUuid; }
23+
void Reset();
24+
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override;
3225

33-
uint16_t NewAlerthandle() const;
3426
private:
3527
static constexpr uint16_t ansServiceId{0x1811};
3628
static constexpr uint16_t supportedNewAlertCategoryId = 0x2a47;
@@ -64,18 +56,21 @@ namespace Pinetime {
6456
.value = controlPointId
6557
};
6658

67-
uint16_t ansStartHandle;
68-
uint16_t ansEndHandle;
69-
uint16_t supportedNewAlertCategoryHandle;
70-
uint16_t supportedUnreadAlertCategoryHandle;
71-
uint16_t newAlertHandle;
59+
uint16_t ansStartHandle = 0;
60+
uint16_t ansEndHandle = 0;
61+
uint16_t supportedNewAlertCategoryHandle = 0;
62+
uint16_t supportedUnreadAlertCategoryHandle = 0;
63+
uint16_t newAlertHandle = 0;
7264
uint16_t newAlertDescriptorHandle = 0;
73-
uint16_t newAlertDefHandle;
74-
uint16_t unreadAlertStatusHandle;
75-
uint16_t controlPointHandle;
65+
uint16_t newAlertDefHandle = 0;
66+
uint16_t unreadAlertStatusHandle = 0;
67+
uint16_t controlPointHandle = 0;
7668
bool isDiscovered = false;
7769
Pinetime::System::SystemTask &systemTask;
7870
Pinetime::Controllers::NotificationManager &notificationManager;
71+
std::function<void(uint16_t)> onServiceDiscovered;
72+
bool isCharacteristicDiscovered = false;
73+
bool isDescriptorFound = false;
7974
};
8075
}
8176
}

src/components/ble/BleClient.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <functional>
4+
5+
namespace Pinetime {
6+
namespace Controllers{
7+
class BleClient {
8+
public:
9+
virtual void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) = 0;
10+
};
11+
}
12+
}

0 commit comments

Comments
 (0)