Skip to content

Commit 45e1f5d

Browse files
feat: add status parameter to gatt client notifications, discovery and characteristic callbacks (#956)
* enhance gatt client error handling * increase test coverage * remove unused methods StartCharacteristicDiscovery and StartCharacteristicDiscovery from GattClientDiscovery
1 parent ff57c4b commit 45e1f5d

12 files changed

+400
-365
lines changed

services/ble/ClaimingGattClientAdapter.cpp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ namespace services
4949
});
5050
}
5151

52-
void ClaimingGattClientAdapter::ServiceDiscoveryComplete()
52+
void ClaimingGattClientAdapter::ServiceDiscoveryComplete(OperationStatus status)
5353
{
5454
discoveryClaimer.Release();
55-
GattClientDiscovery::NotifyObservers([](auto& observer)
55+
GattClientDiscovery::NotifyObservers([status](auto& observer)
5656
{
57-
observer.ServiceDiscoveryComplete();
57+
observer.ServiceDiscoveryComplete(status);
5858
});
5959
}
6060

@@ -68,12 +68,12 @@ namespace services
6868
});
6969
}
7070

71-
void ClaimingGattClientAdapter::CharacteristicDiscoveryComplete()
71+
void ClaimingGattClientAdapter::CharacteristicDiscoveryComplete(OperationStatus status)
7272
{
7373
discoveryClaimer.Release();
74-
GattClientDiscovery::NotifyObservers([](auto& observer)
74+
GattClientDiscovery::NotifyObservers([status](auto& observer)
7575
{
76-
observer.CharacteristicDiscoveryComplete();
76+
observer.CharacteristicDiscoveryComplete(status);
7777
});
7878
}
7979

@@ -87,22 +87,22 @@ namespace services
8787
});
8888
}
8989

90-
void ClaimingGattClientAdapter::DescriptorDiscoveryComplete()
90+
void ClaimingGattClientAdapter::DescriptorDiscoveryComplete(OperationStatus status)
9191
{
9292
discoveryClaimer.Release();
93-
GattClientDiscovery::NotifyObservers([](auto& observer)
93+
GattClientDiscovery::NotifyObservers([status](auto& observer)
9494
{
95-
observer.DescriptorDiscoveryComplete();
95+
observer.DescriptorDiscoveryComplete(status);
9696
});
9797
}
9898

99-
void ClaimingGattClientAdapter::Read(AttAttribute::Handle handle, const infra::Function<void(const infra::ConstByteRange&)>& onRead, const infra::Function<void(uint8_t)>& onDone)
99+
void ClaimingGattClientAdapter::Read(AttAttribute::Handle handle, const infra::Function<void(const infra::ConstByteRange&)>& onRead, const infra::Function<void(OperationStatus)>& onDone)
100100
{
101101
characteristicOperationContext.emplace(ReadOperation{ onRead, onDone }, handle);
102102
characteristicOperationsClaimer.Claim([this]()
103103
{
104104
const auto& readContext = std::get<ReadOperation>(characteristicOperationContext->operation);
105-
GattClientObserver::Subject().Read(characteristicOperationContext->handle, readContext.onRead, [this](uint8_t result)
105+
GattClientObserver::Subject().Read(characteristicOperationContext->handle, readContext.onRead, [this](OperationStatus result)
106106
{
107107
characteristicOperationsClaimer.Release();
108108
const auto& readContext = std::get<ReadOperation>(characteristicOperationContext->operation);
@@ -111,13 +111,13 @@ namespace services
111111
});
112112
}
113113

114-
void ClaimingGattClientAdapter::Write(AttAttribute::Handle handle, infra::ConstByteRange data, const infra::Function<void(uint8_t)>& onDone)
114+
void ClaimingGattClientAdapter::Write(AttAttribute::Handle handle, infra::ConstByteRange data, const infra::Function<void(OperationStatus)>& onDone)
115115
{
116116
characteristicOperationContext.emplace(WriteOperation{ data, onDone }, handle);
117117
characteristicOperationsClaimer.Claim([this]()
118118
{
119119
const auto& writeContext = std::get<WriteOperation>(characteristicOperationContext->operation);
120-
GattClientObserver::Subject().Write(characteristicOperationContext->handle, writeContext.data, [this](uint8_t result)
120+
GattClientObserver::Subject().Write(characteristicOperationContext->handle, writeContext.data, [this](OperationStatus result)
121121
{
122122
characteristicOperationsClaimer.Release();
123123
const auto& writeContext = std::get<WriteOperation>(characteristicOperationContext->operation);
@@ -131,9 +131,9 @@ namespace services
131131
GattClientObserver::Subject().WriteWithoutResponse(handle, data, onDone);
132132
}
133133

134-
void ClaimingGattClientAdapter::EnableNotification(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone)
134+
void ClaimingGattClientAdapter::EnableNotification(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone)
135135
{
136-
characteristicOperationContext.emplace(DescriptorOperation{ onDone, [this](const infra::Function<void(uint8_t)>& callback)
136+
characteristicOperationContext.emplace(DescriptorOperation{ onDone, [this](const infra::Function<void(OperationStatus)>& callback)
137137
{
138138
GattClientObserver::Subject().EnableNotification(characteristicOperationContext->handle, callback);
139139
} },
@@ -142,10 +142,10 @@ namespace services
142142
PerformDescriptorOperation();
143143
}
144144

145-
void ClaimingGattClientAdapter::DisableNotification(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone)
145+
void ClaimingGattClientAdapter::DisableNotification(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone)
146146
{
147147
characteristicOperationContext.emplace(DescriptorOperation{ onDone,
148-
[this](const infra::Function<void(uint8_t)>& callback)
148+
[this](const infra::Function<void(OperationStatus)>& callback)
149149
{
150150
GattClientObserver::Subject().DisableNotification(characteristicOperationContext->handle, callback);
151151
} },
@@ -154,10 +154,10 @@ namespace services
154154
PerformDescriptorOperation();
155155
}
156156

157-
void ClaimingGattClientAdapter::EnableIndication(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone)
157+
void ClaimingGattClientAdapter::EnableIndication(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone)
158158
{
159159
characteristicOperationContext.emplace(DescriptorOperation{ onDone,
160-
[this](const infra::Function<void(uint8_t)>& callback)
160+
[this](const infra::Function<void(OperationStatus)>& callback)
161161
{
162162
GattClientObserver::Subject().EnableIndication(characteristicOperationContext->handle, callback);
163163
} },
@@ -166,10 +166,10 @@ namespace services
166166
PerformDescriptorOperation();
167167
}
168168

169-
void ClaimingGattClientAdapter::DisableIndication(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone)
169+
void ClaimingGattClientAdapter::DisableIndication(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone)
170170
{
171171
characteristicOperationContext.emplace(DescriptorOperation{ onDone,
172-
[this](const infra::Function<void(uint8_t)>& callback)
172+
[this](const infra::Function<void(OperationStatus)>& callback)
173173
{
174174
GattClientObserver::Subject().DisableIndication(characteristicOperationContext->handle, callback);
175175
} },
@@ -196,7 +196,7 @@ namespace services
196196
characteristicOperationsClaimer.Claim([this]()
197197
{
198198
auto descriptorOperationContext = std::get<DescriptorOperation>(characteristicOperationContext->operation);
199-
descriptorOperationContext.operation([this](uint8_t result)
199+
descriptorOperationContext.operation([this](OperationStatus result)
200200
{
201201
characteristicOperationsClaimer.Release();
202202
auto descriptorOperationContext = std::get<DescriptorOperation>(characteristicOperationContext->operation);

services/ble/ClaimingGattClientAdapter.hpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ namespace services
3030
void StartDescriptorDiscovery(AttAttribute::Handle handle, AttAttribute::Handle endHandle) override;
3131

3232
// Implementation of GattClientCharacteristicOperations
33-
void Read(AttAttribute::Handle handle, const infra::Function<void(const infra::ConstByteRange&)>& onRead, const infra::Function<void(uint8_t)>& onDone) override;
34-
void Write(AttAttribute::Handle handle, infra::ConstByteRange data, const infra::Function<void(uint8_t)>& onDone) override;
33+
void Read(AttAttribute::Handle handle, const infra::Function<void(const infra::ConstByteRange&)>& onRead, const infra::Function<void(OperationStatus)>& onDone) override;
34+
void Write(AttAttribute::Handle handle, infra::ConstByteRange data, const infra::Function<void(OperationStatus)>& onDone) override;
3535
void WriteWithoutResponse(AttAttribute::Handle handle, infra::ConstByteRange data, const infra::Function<void(OperationStatus)>& onDone) override;
36-
void EnableNotification(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone) override;
37-
void DisableNotification(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone) override;
38-
void EnableIndication(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone) override;
39-
void DisableIndication(AttAttribute::Handle handle, const infra::Function<void(uint8_t)>& onDone) override;
36+
void EnableNotification(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone) override;
37+
void DisableNotification(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone) override;
38+
void EnableIndication(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone) override;
39+
void DisableIndication(AttAttribute::Handle handle, const infra::Function<void(OperationStatus)>& onDone) override;
4040

4141
// Implementation of AttMtuExchange
4242
uint16_t EffectiveMaxAttMtuSize() const override;
@@ -45,11 +45,11 @@ namespace services
4545
private:
4646
// Implementation of GattClientObserver
4747
void ServiceDiscovered(const AttAttribute::Uuid& type, AttAttribute::Handle handle, AttAttribute::Handle endHandle) override;
48-
void ServiceDiscoveryComplete() override;
48+
void ServiceDiscoveryComplete(OperationStatus status) override;
4949
void CharacteristicDiscovered(const AttAttribute::Uuid& type, AttAttribute::Handle handle, AttAttribute::Handle valueHandle, GattCharacteristic::PropertyFlags properties) override;
50-
void CharacteristicDiscoveryComplete() override;
50+
void CharacteristicDiscoveryComplete(OperationStatus status) override;
5151
void DescriptorDiscovered(const AttAttribute::Uuid& type, AttAttribute::Handle handle) override;
52-
void DescriptorDiscoveryComplete() override;
52+
void DescriptorDiscoveryComplete(OperationStatus status) override;
5353
void NotificationReceived(AttAttribute::Handle handle, infra::ConstByteRange data) override;
5454
void IndicationReceived(AttAttribute::Handle handle, infra::ConstByteRange data, const infra::Function<void()>& onDone) override;
5555

@@ -94,19 +94,19 @@ namespace services
9494
struct ReadOperation
9595
{
9696
const infra::Function<void(const infra::ConstByteRange&)> onRead;
97-
const infra::Function<void(uint8_t)> onDone;
97+
const infra::Function<void(OperationStatus)> onDone;
9898
};
9999

100100
struct WriteOperation
101101
{
102102
infra::ConstByteRange data;
103-
const infra::Function<void(uint8_t)> onDone;
103+
const infra::Function<void(OperationStatus)> onDone;
104104
};
105105

106106
struct DescriptorOperation
107107
{
108-
const infra::Function<void(uint8_t)> onDone;
109-
infra::Function<void(const infra::Function<void(uint8_t)>&)> operation;
108+
const infra::Function<void(OperationStatus)> onDone;
109+
infra::Function<void(const infra::Function<void(OperationStatus)>&)> operation;
110110
};
111111

112112
struct CharacteristicOperation
@@ -115,7 +115,7 @@ namespace services
115115

116116
CharacteristicOperation(Operation operation, AttAttribute::Handle handle)
117117
: operation(operation)
118-
, handle(handle) {};
118+
, handle(handle){};
119119

120120
Operation operation;
121121
AttAttribute::Handle handle;

services/ble/Gatt.proto

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,21 @@ message Descriptr
6969
Handle handle = 2;
7070
}
7171

72-
// Value 0 indicates success
73-
// Any non-zero value indicates an error. The actual meaning of the error code is platform specific.
74-
// For ST-based platforms error codes are defined in "Status error codes" section of ST application note AN5270
75-
message GattResult
72+
message ReadResult
7673
{
77-
uint32 value = 1;
74+
CharacteristicData data = 1;
7875
}
7976

80-
message ReadResult
77+
enum OperationStatus
8178
{
82-
CharacteristicData data = 1;
79+
success = 0;
80+
retry = 1;
81+
error = 2;
82+
}
83+
84+
message OperationResult
85+
{
86+
OperationStatus value = 1;
8387
}
8488

8589
service GattClient
@@ -127,7 +131,7 @@ service GattClientResponse
127131
rpc ReadResponse(ReadResult) returns (Nothing) { option (method_id) = 8; }
128132

129133
// Called after completion of characteristic operations with response: Read, Write, Enable/Disable Notification/Indication
130-
rpc CharacteristicOperationComplete(GattResult) returns (Nothing) { option (method_id) = 9; }
134+
rpc CharacteristicOperationComplete(OperationResult) returns (Nothing) { option (method_id) = 9; }
131135

132136
rpc IndicationReceived(CharacteristicData) returns (Nothing) { option (method_id) = 10; }
133137
rpc NotificationReceived(CharacteristicData) returns (Nothing) { option (method_id) = 11; }

services/ble/GattClient.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ namespace services
1414
: GattCharacteristic(type, handle, valueHandle, properties)
1515
{}
1616

17-
void GattClientCharacteristic::Read(const infra::Function<void(const infra::ConstByteRange&)>& onResponse, const infra::Function<void(uint8_t)>& onDone)
17+
void GattClientCharacteristic::Read(const infra::Function<void(const infra::ConstByteRange&)>& onResponse, const infra::Function<void(OperationStatus)>& onDone)
1818
{
1919
really_assert(operations != nullptr);
2020

2121
operations->Read(valueHandle, onResponse, onDone);
2222
}
2323

24-
void GattClientCharacteristic::Write(infra::ConstByteRange data, const infra::Function<void(uint8_t)>& onDone)
24+
void GattClientCharacteristic::Write(infra::ConstByteRange data, const infra::Function<void(OperationStatus)>& onDone)
2525
{
2626
really_assert(operations != nullptr);
2727

@@ -35,28 +35,28 @@ namespace services
3535
operations->WriteWithoutResponse(valueHandle, data, onDone);
3636
}
3737

38-
void GattClientCharacteristic::EnableNotification(const infra::Function<void(uint8_t)>& onDone)
38+
void GattClientCharacteristic::EnableNotification(const infra::Function<void(OperationStatus)>& onDone)
3939
{
4040
really_assert(operations != nullptr);
4141

4242
operations->EnableNotification(valueHandle, onDone);
4343
}
4444

45-
void GattClientCharacteristic::DisableNotification(const infra::Function<void(uint8_t)>& onDone)
45+
void GattClientCharacteristic::DisableNotification(const infra::Function<void(OperationStatus)>& onDone)
4646
{
4747
really_assert(operations != nullptr);
4848

4949
operations->DisableNotification(valueHandle, onDone);
5050
}
5151

52-
void GattClientCharacteristic::EnableIndication(const infra::Function<void(uint8_t)>& onDone)
52+
void GattClientCharacteristic::EnableIndication(const infra::Function<void(OperationStatus)>& onDone)
5353
{
5454
really_assert(operations != nullptr);
5555

5656
operations->EnableIndication(valueHandle, onDone);
5757
}
5858

59-
void GattClientCharacteristic::DisableIndication(const infra::Function<void(uint8_t)>& onDone)
59+
void GattClientCharacteristic::DisableIndication(const infra::Function<void(OperationStatus)>& onDone)
6060
{
6161
really_assert(operations != nullptr);
6262

@@ -120,14 +120,25 @@ namespace services
120120
{
121121
return characteristics;
122122
}
123+
}
123124

124-
void GattClientDiscovery::StartCharacteristicDiscovery(const GattService& service)
125+
namespace infra
126+
{
127+
infra::TextOutputStream& operator<<(infra::TextOutputStream& stream, const services::OperationStatus& status)
125128
{
126-
StartCharacteristicDiscovery(service.Handle(), service.EndHandle());
127-
}
129+
switch (status)
130+
{
131+
case services::OperationStatus::success:
132+
stream << "success";
133+
break;
134+
case services::OperationStatus::retry:
135+
stream << "retry";
136+
break;
137+
case services::OperationStatus::error:
138+
stream << "error";
139+
break;
140+
}
128141

129-
void GattClientDiscovery::StartDescriptorDiscovery(const GattService& service)
130-
{
131-
StartDescriptorDiscovery(service.Handle(), service.EndHandle());
142+
return stream;
132143
}
133144
}

0 commit comments

Comments
 (0)