simplejsble 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NitroSimplejsble.podspec +1 -1
- package/VERSION +1 -1
- package/dependencies/external/kvn/kvn_bytearray.h +7 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +2 -0
- package/lib/specs/Adapter.nitro.d.ts +10 -0
- package/lib/specs/Adapter.nitro.d.ts.map +1 -0
- package/lib/specs/Adapter.nitro.js +1 -0
- package/package.json +2 -2
- package/simpleble/CMakeLists.txt +1 -6
- package/simpleble/src/backends/dongl/AdapterDongl.cpp +10 -143
- package/simpleble/src/backends/dongl/AdapterDongl.h +0 -1
- package/simpleble/src/backends/dongl/PeripheralDongl.cpp +120 -118
- package/simpleble/src/backends/dongl/PeripheralDongl.h +9 -2
- package/simpleble/src/backends/dongl/protocol/d2h.pb.h +9 -26
- package/simpleble/src/backends/dongl/protocol/h2d.pb.h +2 -12
- package/simpleble/src/backends/dongl/serial/Protocol.cpp +1 -755
- package/simpleble/src/backends/dongl/serial/Protocol.h +0 -75
- package/simpleble/test/src/test_bytearray.cpp +7 -0
- package/simpleble/src/backends/dongl/protocol/softdevice.pb.c +0 -18
- package/simpleble/src/backends/dongl/protocol/softdevice.pb.h +0 -815
- package/simpleble/src/backends/dongl/protocol/softdevice_gap.pb.c +0 -339
- package/simpleble/src/backends/dongl/protocol/softdevice_gap.pb.h +0 -2086
- package/simpleble/src/backends/dongl/protocol/softdevice_gattc.pb.c +0 -114
- package/simpleble/src/backends/dongl/protocol/softdevice_gattc.pb.h +0 -772
- package/simpleble/src/backends/dongl/protocol/softdevice_gatts.pb.c +0 -117
- package/simpleble/src/backends/dongl/protocol/softdevice_gatts.pb.h +0 -766
- package/simpleble/src/backends/dongl/protocol/softdevice_types.pb.c +0 -207
- package/simpleble/src/backends/dongl/protocol/softdevice_types.pb.h +0 -1686
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <simpleble/Exceptions.h>
|
|
8
8
|
|
|
9
9
|
#include <cstdint>
|
|
10
|
+
#include <functional>
|
|
10
11
|
#include <memory>
|
|
11
12
|
#include <thread>
|
|
12
13
|
|
|
@@ -104,10 +105,8 @@ void PeripheralDongl::unpair() {}
|
|
|
104
105
|
SharedPtrVector<ServiceBase> PeripheralDongl::available_services() {
|
|
105
106
|
SharedPtrVector<ServiceBase> service_list;
|
|
106
107
|
for (auto& service : _services) {
|
|
107
|
-
fmt::print("PeripheralDongl::available_services: Service UUID: {}\n", service.uuid);
|
|
108
108
|
SharedPtrVector<CharacteristicBase> characteristic_list;
|
|
109
109
|
for (auto& characteristic : service.characteristics) {
|
|
110
|
-
fmt::print("PeripheralDongl::available_services: Characteristic UUID: {}\n", characteristic.uuid);
|
|
111
110
|
SharedPtrVector<DescriptorBase> descriptor_list;
|
|
112
111
|
for (auto& descriptor : characteristic.descriptors) {
|
|
113
112
|
descriptor_list.push_back(std::make_shared<DescriptorBase>(descriptor.uuid));
|
|
@@ -133,122 +132,125 @@ SharedPtrVector<ServiceBase> PeripheralDongl::advertised_services() {
|
|
|
133
132
|
|
|
134
133
|
std::map<uint16_t, ByteArray> PeripheralDongl::manufacturer_data() { return _manufacturer_data; }
|
|
135
134
|
|
|
136
|
-
ByteArray PeripheralDongl::read(BluetoothUUID const&
|
|
137
|
-
auto&
|
|
135
|
+
ByteArray PeripheralDongl::read(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid) {
|
|
136
|
+
auto& characteristic = _find_characteristic_from_uuid(service_uuid, characteristic_uuid);
|
|
138
137
|
|
|
139
|
-
if (!
|
|
140
|
-
throw Exception::OperationFailed(fmt::format("Characteristic {} is not readable",
|
|
138
|
+
if (!characteristic.can_read) {
|
|
139
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} is not readable", characteristic_uuid));
|
|
141
140
|
}
|
|
142
141
|
|
|
143
|
-
simpleble_ReadRsp rsp = _serial_protocol->simpleble_read(_conn_handle,
|
|
142
|
+
simpleble_ReadRsp rsp = _serial_protocol->simpleble_read(_conn_handle, characteristic.handle_value);
|
|
144
143
|
if (rsp.ret_code != 0) {
|
|
145
144
|
throw Exception::OperationFailed(
|
|
146
|
-
fmt::format("Failed to read characteristic {} - ret_code: {}",
|
|
145
|
+
fmt::format("Failed to read characteristic {} - ret_code: {}", characteristic_uuid, rsp.ret_code));
|
|
147
146
|
}
|
|
148
147
|
|
|
149
148
|
return ByteArray(rsp.data.bytes, rsp.data.size);
|
|
150
149
|
}
|
|
151
150
|
|
|
152
|
-
void PeripheralDongl::write_request(BluetoothUUID const&
|
|
151
|
+
void PeripheralDongl::write_request(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid,
|
|
153
152
|
ByteArray const& data) {
|
|
154
|
-
auto&
|
|
153
|
+
auto& characteristic = _find_characteristic_from_uuid(service_uuid, characteristic_uuid);
|
|
155
154
|
|
|
156
|
-
if (!
|
|
157
|
-
throw Exception::OperationFailed(fmt::format("Characteristic {} is not writable",
|
|
155
|
+
if (!characteristic.can_write_request) {
|
|
156
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} is not writable", characteristic_uuid));
|
|
158
157
|
}
|
|
159
158
|
|
|
160
|
-
simpleble_WriteRsp rsp = _serial_protocol->simpleble_write(_conn_handle,
|
|
159
|
+
simpleble_WriteRsp rsp = _serial_protocol->simpleble_write(_conn_handle, characteristic.handle_value,
|
|
161
160
|
simpleble_WriteOperation_WRITE_REQ, data);
|
|
162
161
|
if (rsp.ret_code != 0) {
|
|
163
162
|
throw Exception::OperationFailed(
|
|
164
|
-
fmt::format("Failed to write characteristic {} - ret_code: {}",
|
|
163
|
+
fmt::format("Failed to write characteristic {} - ret_code: {}", characteristic_uuid, rsp.ret_code));
|
|
165
164
|
}
|
|
166
165
|
}
|
|
167
166
|
|
|
168
|
-
void PeripheralDongl::write_command(BluetoothUUID const&
|
|
167
|
+
void PeripheralDongl::write_command(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid,
|
|
169
168
|
ByteArray const& data) {
|
|
170
|
-
auto&
|
|
169
|
+
auto& characteristic = _find_characteristic_from_uuid(service_uuid, characteristic_uuid);
|
|
171
170
|
|
|
172
|
-
if (!
|
|
173
|
-
throw Exception::OperationFailed(fmt::format("Characteristic {} is not writable",
|
|
171
|
+
if (!characteristic.can_write_command) {
|
|
172
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} is not writable", characteristic_uuid));
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
simpleble_WriteRsp rsp = _serial_protocol->simpleble_write(_conn_handle,
|
|
175
|
+
simpleble_WriteRsp rsp = _serial_protocol->simpleble_write(_conn_handle, characteristic.handle_value,
|
|
177
176
|
simpleble_WriteOperation_WRITE_CMD, data);
|
|
178
177
|
if (rsp.ret_code != 0) {
|
|
179
178
|
throw Exception::OperationFailed(
|
|
180
|
-
fmt::format("Failed to write characteristic {} - ret_code: {}",
|
|
179
|
+
fmt::format("Failed to write characteristic {} - ret_code: {}", characteristic_uuid, rsp.ret_code));
|
|
181
180
|
}
|
|
182
181
|
}
|
|
183
182
|
|
|
184
|
-
void PeripheralDongl::notify(BluetoothUUID const&
|
|
183
|
+
void PeripheralDongl::notify(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid,
|
|
185
184
|
std::function<void(ByteArray payload)> callback) {
|
|
186
|
-
auto&
|
|
185
|
+
auto& characteristic = _find_characteristic_from_uuid(service_uuid, characteristic_uuid);
|
|
187
186
|
|
|
188
|
-
if (!
|
|
189
|
-
throw Exception::OperationFailed(fmt::format("Characteristic {} is not notifyable",
|
|
187
|
+
if (!characteristic.can_notify) {
|
|
188
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} is not notifyable", characteristic_uuid));
|
|
190
189
|
}
|
|
191
190
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
191
|
+
if (characteristic.handle_cccd == 0) {
|
|
192
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} does not have a CCCD", characteristic_uuid));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
_callbacks_on_value_changed[characteristic.handle_value] = std::move(callback);
|
|
196
|
+
|
|
197
|
+
ByteArray data = {0x01, 0x00};
|
|
198
|
+
simpleble_WriteRsp rsp = _serial_protocol->simpleble_write(_conn_handle, characteristic.handle_cccd,
|
|
199
|
+
simpleble_WriteOperation_WRITE_REQ, data);
|
|
200
|
+
if (rsp.ret_code != 0) {
|
|
201
|
+
throw Exception::OperationFailed(
|
|
202
|
+
fmt::format("Failed to write characteristic {} - ret_code: {}", characteristic_uuid, rsp.ret_code));
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
void PeripheralDongl::indicate(BluetoothUUID const&
|
|
206
|
+
void PeripheralDongl::indicate(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid,
|
|
207
207
|
std::function<void(ByteArray payload)> callback) {
|
|
208
|
-
auto&
|
|
208
|
+
auto& characteristic = _find_characteristic_from_uuid(service_uuid, characteristic_uuid);
|
|
209
209
|
|
|
210
|
-
if (!
|
|
211
|
-
throw Exception::OperationFailed(fmt::format("Characteristic {} is not indicateable",
|
|
210
|
+
if (!characteristic.can_indicate) {
|
|
211
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} is not indicateable", characteristic_uuid));
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
214
|
+
if (characteristic.handle_cccd == 0) {
|
|
215
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} does not have a CCCD", characteristic_uuid));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
_callbacks_on_value_changed[characteristic.handle_value] = callback;
|
|
219
|
+
|
|
220
|
+
ByteArray data = {0x02, 0x00};
|
|
221
|
+
simpleble_WriteRsp rsp = _serial_protocol->simpleble_write(_conn_handle, characteristic.handle_cccd,
|
|
222
|
+
simpleble_WriteOperation_WRITE_REQ, data);
|
|
223
|
+
if (rsp.ret_code != 0) {
|
|
224
|
+
throw Exception::OperationFailed(
|
|
225
|
+
fmt::format("Failed to write characteristic {} - ret_code: {}", characteristic_uuid, rsp.ret_code));
|
|
225
226
|
}
|
|
226
227
|
}
|
|
227
228
|
|
|
228
|
-
void PeripheralDongl::unsubscribe(BluetoothUUID const&
|
|
229
|
-
auto&
|
|
229
|
+
void PeripheralDongl::unsubscribe(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid) {
|
|
230
|
+
auto& characteristic = _find_characteristic_from_uuid(service_uuid, characteristic_uuid);
|
|
230
231
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
232
|
+
if (characteristic.handle_cccd == 0) {
|
|
233
|
+
throw Exception::OperationFailed(fmt::format("Characteristic {} does not have a CCCD", characteristic_uuid));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
_callbacks_on_value_changed.erase(characteristic.handle_value);
|
|
237
|
+
|
|
238
|
+
ByteArray data = {0x00, 0x00};
|
|
239
|
+
simpleble_WriteRsp rsp = _serial_protocol->simpleble_write(_conn_handle, characteristic.handle_cccd,
|
|
240
|
+
simpleble_WriteOperation_WRITE_REQ, data);
|
|
241
|
+
if (rsp.ret_code != 0) {
|
|
242
|
+
throw Exception::OperationFailed(
|
|
243
|
+
fmt::format("Failed to write characteristic {} - ret_code: {}", characteristic_uuid, rsp.ret_code));
|
|
242
244
|
}
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
ByteArray PeripheralDongl::read(BluetoothUUID const&
|
|
246
|
-
BluetoothUUID const&
|
|
247
|
+
ByteArray PeripheralDongl::read(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid,
|
|
248
|
+
BluetoothUUID const& descriptor_uuid) {
|
|
247
249
|
return {};
|
|
248
250
|
}
|
|
249
251
|
|
|
250
|
-
void PeripheralDongl::write(BluetoothUUID const&
|
|
251
|
-
BluetoothUUID const&
|
|
252
|
+
void PeripheralDongl::write(BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid,
|
|
253
|
+
BluetoothUUID const& descriptor_uuid, ByteArray const& data) {}
|
|
252
254
|
|
|
253
255
|
void PeripheralDongl::set_callback_on_connected(std::function<void()> on_connected) {
|
|
254
256
|
if (on_connected) {
|
|
@@ -284,7 +286,7 @@ bool PeripheralDongl::_attempt_connect() {
|
|
|
284
286
|
if (_conn_handle != BLE_CONN_HANDLE_INVALID) {
|
|
285
287
|
auto response = _serial_protocol->simpleble_disconnect(_conn_handle);
|
|
286
288
|
if (response.ret_code != 0) {
|
|
287
|
-
fmt::
|
|
289
|
+
SIMPLEBLE_LOG_ERROR(fmt::format("Failed to disconnect during connect attempt: {}", response.ret_code));
|
|
288
290
|
}
|
|
289
291
|
|
|
290
292
|
// Wait for the disconnection to be confirmed.
|
|
@@ -292,7 +294,6 @@ bool PeripheralDongl::_attempt_connect() {
|
|
|
292
294
|
disconnection_cv_.wait_for(lock, 500ms, [this]() { return !is_connected(); });
|
|
293
295
|
}
|
|
294
296
|
|
|
295
|
-
fmt::println("Disconnection confirmed");
|
|
296
297
|
_conn_handle = BLE_CONN_HANDLE_INVALID;
|
|
297
298
|
|
|
298
299
|
auto response = _serial_protocol->simpleble_connect(static_cast<simpleble_BluetoothAddressType>(_address_type),
|
|
@@ -311,39 +312,34 @@ bool PeripheralDongl::_attempt_connect() {
|
|
|
311
312
|
std::unique_lock<std::mutex> lock(connection_mutex_);
|
|
312
313
|
connection_cv_.wait_for(lock, 5000ms, [this]() { return _conn_handle != BLE_CONN_HANDLE_INVALID; });
|
|
313
314
|
if (_conn_handle == BLE_CONN_HANDLE_INVALID) {
|
|
314
|
-
|
|
315
|
-
fmt::println("Timeout while waiting for connection confirmation");
|
|
315
|
+
SIMPLEBLE_LOG_ERROR("Timeout while waiting for connection confirmation");
|
|
316
316
|
return false;
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
fmt::println("Connection confirmed");
|
|
321
|
-
|
|
322
320
|
// Wait for the attributes to be discovered.
|
|
323
321
|
{
|
|
324
322
|
std::unique_lock<std::mutex> lock(attributes_discovered_mutex_);
|
|
325
323
|
attributes_discovered_cv_.wait_for(
|
|
326
324
|
lock, 15000ms, [this]() { return !_services.empty() || _conn_handle == BLE_CONN_HANDLE_INVALID; });
|
|
327
325
|
if (_services.empty()) {
|
|
328
|
-
|
|
326
|
+
SIMPLEBLE_LOG_ERROR("Timeout while waiting for attributes to be discovered");
|
|
329
327
|
return false;
|
|
330
328
|
}
|
|
331
329
|
|
|
332
330
|
if (_conn_handle == BLE_CONN_HANDLE_INVALID) {
|
|
333
|
-
|
|
331
|
+
SIMPLEBLE_LOG_ERROR("Connection lost during attribute discovery");
|
|
334
332
|
return false;
|
|
335
333
|
}
|
|
336
334
|
}
|
|
337
335
|
|
|
338
|
-
fmt::println("Attributes discovered. {} services found", _services.size());
|
|
339
|
-
|
|
340
336
|
// Retrieve any missing 128-bit UUIDs.
|
|
341
337
|
for (auto& service : _services) {
|
|
342
338
|
// Fetch the service UUID if missing.
|
|
343
339
|
if (service.uuid.empty()) {
|
|
344
340
|
simpleble_ReadRsp rsp = _serial_protocol->simpleble_read(_conn_handle, service.start_handle);
|
|
345
341
|
if (rsp.ret_code != 0) {
|
|
346
|
-
fmt::
|
|
342
|
+
SIMPLEBLE_LOG_ERROR(fmt::format("Failed to read UUID for service {} - ret_code: {}", service.start_handle, rsp.ret_code));
|
|
347
343
|
continue;
|
|
348
344
|
}
|
|
349
345
|
|
|
@@ -356,7 +352,7 @@ bool PeripheralDongl::_attempt_connect() {
|
|
|
356
352
|
}
|
|
357
353
|
service.uuid = _uuid_from_uuid128(uuid_128);
|
|
358
354
|
} else {
|
|
359
|
-
fmt::
|
|
355
|
+
SIMPLEBLE_LOG_ERROR(fmt::format("Unexpected UUID size: {}", rsp.data.size));
|
|
360
356
|
continue;
|
|
361
357
|
}
|
|
362
358
|
}
|
|
@@ -366,8 +362,8 @@ bool PeripheralDongl::_attempt_connect() {
|
|
|
366
362
|
if (characteristic.uuid.empty()) {
|
|
367
363
|
simpleble_ReadRsp rsp = _serial_protocol->simpleble_read(_conn_handle, characteristic.handle_decl);
|
|
368
364
|
if (rsp.ret_code != 0) {
|
|
369
|
-
fmt::
|
|
370
|
-
rsp.ret_code);
|
|
365
|
+
SIMPLEBLE_LOG_ERROR(fmt::format("Failed to read UUID for characteristic {} - ret_code: {}", characteristic.handle_decl,
|
|
366
|
+
rsp.ret_code));
|
|
371
367
|
continue;
|
|
372
368
|
}
|
|
373
369
|
|
|
@@ -383,20 +379,15 @@ bool PeripheralDongl::_attempt_connect() {
|
|
|
383
379
|
}
|
|
384
380
|
}
|
|
385
381
|
}
|
|
386
|
-
|
|
387
|
-
fmt::println("Service discovery complete");
|
|
388
|
-
|
|
389
382
|
return true;
|
|
390
383
|
}
|
|
391
384
|
|
|
392
385
|
void PeripheralDongl::notify_connected(uint16_t conn_handle) {
|
|
393
|
-
fmt::print("PeripheralDongl::notify_connected: {}\n", conn_handle);
|
|
394
386
|
_conn_handle = conn_handle;
|
|
395
387
|
connection_cv_.notify_all();
|
|
396
388
|
}
|
|
397
389
|
|
|
398
390
|
void PeripheralDongl::notify_disconnected() {
|
|
399
|
-
fmt::print("PeripheralDongl::notify_disconnected: {}\n", _conn_handle);
|
|
400
391
|
_conn_handle = BLE_CONN_HANDLE_INVALID;
|
|
401
392
|
disconnection_cv_.notify_all();
|
|
402
393
|
attributes_discovered_cv_.notify_all();
|
|
@@ -406,10 +397,6 @@ void PeripheralDongl::notify_disconnected() {
|
|
|
406
397
|
}
|
|
407
398
|
|
|
408
399
|
void PeripheralDongl::notify_service_discovered(simpleble_ServiceDiscoveredEvt const& evt) {
|
|
409
|
-
fmt::print(
|
|
410
|
-
"PeripheralDongl::notify_service_discovered: conn_handle={}, uuid16={:04x}, start_handle={}, end_handle={}\n",
|
|
411
|
-
evt.conn_handle, evt.uuid16.uuid, evt.start_handle, evt.end_handle);
|
|
412
|
-
|
|
413
400
|
BluetoothUUID uuid;
|
|
414
401
|
if (evt.has_uuid16) {
|
|
415
402
|
uuid = _uuid_from_uuid16(evt.uuid16.uuid);
|
|
@@ -423,13 +410,7 @@ void PeripheralDongl::notify_service_discovered(simpleble_ServiceDiscoveredEvt c
|
|
|
423
410
|
}
|
|
424
411
|
|
|
425
412
|
void PeripheralDongl::notify_characteristic_discovered(simpleble_CharacteristicDiscoveredEvt const& evt) {
|
|
426
|
-
|
|
427
|
-
"PeripheralDongl::notify_characteristic_discovered: conn_handle={}, uuid16={:04x}, handle_decl={}, "
|
|
428
|
-
"handle_value={}, can_read={}, can_write_wo_resp={}, can_write_cmd={}, can_notify={}, can_indicate={}\n",
|
|
429
|
-
evt.conn_handle, evt.uuid16.uuid, evt.handle_decl, evt.handle_value, evt.props.read, evt.props.write_wo_resp,
|
|
430
|
-
evt.props.write, evt.props.notify, evt.props.indicate);
|
|
431
|
-
|
|
432
|
-
auto& service = _service_definition(evt.handle_decl);
|
|
413
|
+
auto& service = _find_service_from_handle(evt.handle_decl);
|
|
433
414
|
|
|
434
415
|
BluetoothUUID uuid;
|
|
435
416
|
if (evt.has_uuid16) {
|
|
@@ -440,6 +421,7 @@ void PeripheralDongl::notify_characteristic_discovered(simpleble_CharacteristicD
|
|
|
440
421
|
uuid,
|
|
441
422
|
evt.handle_decl,
|
|
442
423
|
evt.handle_value,
|
|
424
|
+
0,
|
|
443
425
|
evt.props.read,
|
|
444
426
|
evt.props.write,
|
|
445
427
|
evt.props.write_wo_resp,
|
|
@@ -449,7 +431,7 @@ void PeripheralDongl::notify_characteristic_discovered(simpleble_CharacteristicD
|
|
|
449
431
|
}
|
|
450
432
|
|
|
451
433
|
void PeripheralDongl::notify_descriptor_discovered(simpleble_DescriptorDiscoveredEvt const& evt) {
|
|
452
|
-
auto& service =
|
|
434
|
+
auto& service = _find_service_from_handle(evt.handle);
|
|
453
435
|
|
|
454
436
|
for (auto& characteristic : service.characteristics) {
|
|
455
437
|
// If the descriptor matches the characteristic declaration handle or value handle, we can ignore it.
|
|
@@ -459,27 +441,32 @@ void PeripheralDongl::notify_descriptor_discovered(simpleble_DescriptorDiscovere
|
|
|
459
441
|
}
|
|
460
442
|
|
|
461
443
|
// At this point we know we have a real descriptor that we shouldn't ignore.
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
break;
|
|
474
|
-
}
|
|
444
|
+
|
|
445
|
+
auto& characteristic = _find_characteristic_from_handle(evt.handle);
|
|
446
|
+
characteristic.descriptors.emplace_back(DescriptorDefinition{
|
|
447
|
+
_uuid_from_uuid16(evt.uuid16.uuid),
|
|
448
|
+
evt.handle,
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// If the descriptor is a client characteristic configuration descriptor (CCCD),
|
|
452
|
+
// save that handle number for the characteristic.
|
|
453
|
+
if (evt.uuid16.uuid == 0x2902) {
|
|
454
|
+
characteristic.handle_cccd = evt.handle;
|
|
475
455
|
}
|
|
476
456
|
}
|
|
477
457
|
|
|
478
458
|
void PeripheralDongl::notify_attribute_discovery_complete() {
|
|
479
|
-
fmt::print("PeripheralDongl::notify_attribute_discovery_complete: {}\n", _conn_handle);
|
|
480
459
|
attributes_discovered_cv_.notify_all();
|
|
481
460
|
}
|
|
482
461
|
|
|
462
|
+
void PeripheralDongl::notify_value_changed(simpleble_ValueChangedEvt const& evt) {
|
|
463
|
+
ByteArray data(evt.data.bytes, evt.data.bytes + evt.data.size);
|
|
464
|
+
std::function<void(ByteArray)> callback = _callbacks_on_value_changed[evt.handle];
|
|
465
|
+
if (callback) {
|
|
466
|
+
callback(data);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
483
470
|
BluetoothUUID PeripheralDongl::_uuid_from_uuid16(uint16_t uuid16) {
|
|
484
471
|
return BluetoothUUID(fmt::format("0000{:04X}-0000-1000-8000-00805F9B34FB", uuid16));
|
|
485
472
|
}
|
|
@@ -531,22 +518,37 @@ BluetoothUUID PeripheralDongl::_uuid_from_proto(simpleble_UUID const& uuid) {
|
|
|
531
518
|
}
|
|
532
519
|
}
|
|
533
520
|
|
|
534
|
-
fmt::print("Unknown UUID type: {}\n", uuid.which_uuid);
|
|
535
521
|
// Should not be reached
|
|
536
|
-
|
|
522
|
+
throw std::runtime_error(fmt::format("Unknown UUID type: {}", uuid.which_uuid));
|
|
537
523
|
}
|
|
538
524
|
|
|
539
|
-
PeripheralDongl::ServiceDefinition& PeripheralDongl::
|
|
525
|
+
PeripheralDongl::ServiceDefinition& PeripheralDongl::_find_service_from_handle(uint16_t handle) {
|
|
540
526
|
for (auto& service : _services) {
|
|
541
527
|
if (service.start_handle <= handle && service.end_handle >= handle) {
|
|
542
528
|
return service;
|
|
543
529
|
}
|
|
544
530
|
}
|
|
545
531
|
|
|
546
|
-
throw std::runtime_error("Service not found");
|
|
532
|
+
throw std::runtime_error(fmt::format("Service not found for handle {}", handle));
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
PeripheralDongl::CharacteristicDefinition& PeripheralDongl::_find_characteristic_from_handle(uint16_t handle) {
|
|
536
|
+
for (auto& service : _services) {
|
|
537
|
+
if (service.start_handle <= handle && service.end_handle >= handle) {
|
|
538
|
+
// For the given service handle, loop the characteristics backwards and select the first characteristic
|
|
539
|
+
// where the handle_value is less than the descriptor handle.
|
|
540
|
+
for (auto it = service.characteristics.rbegin(); it != service.characteristics.rend(); ++it) {
|
|
541
|
+
if (it->handle_value < handle) {
|
|
542
|
+
return *it;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
throw std::runtime_error(fmt::format("Characteristic not found for handle {}", handle));
|
|
547
549
|
}
|
|
548
550
|
|
|
549
|
-
PeripheralDongl::CharacteristicDefinition& PeripheralDongl::
|
|
551
|
+
PeripheralDongl::CharacteristicDefinition& PeripheralDongl::_find_characteristic_from_uuid(
|
|
550
552
|
BluetoothUUID const& service_uuid, BluetoothUUID const& characteristic_uuid) {
|
|
551
553
|
for (auto& service : _services) {
|
|
552
554
|
if (service.uuid == service_uuid) {
|
|
@@ -558,5 +560,5 @@ PeripheralDongl::CharacteristicDefinition& PeripheralDongl::_characteristic_defi
|
|
|
558
560
|
}
|
|
559
561
|
}
|
|
560
562
|
|
|
561
|
-
throw std::runtime_error("Characteristic not found");
|
|
563
|
+
throw std::runtime_error(fmt::format("Characteristic {} not found", characteristic_uuid));
|
|
562
564
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#include <TaskRunner.hpp>
|
|
9
9
|
#include <kvn_safe_callback.hpp>
|
|
10
|
+
#include <kvn_safe_map.hpp>
|
|
10
11
|
|
|
11
12
|
#include <atomic>
|
|
12
13
|
#include <map>
|
|
@@ -61,6 +62,7 @@ class PeripheralDongl : public PeripheralBase {
|
|
|
61
62
|
virtual void set_callback_on_disconnected(std::function<void()> on_disconnected) override;
|
|
62
63
|
|
|
63
64
|
// Internal methods not exposed to the user.
|
|
65
|
+
// TODO: Make these private and the adapter a friend.
|
|
64
66
|
uint16_t conn_handle() const;
|
|
65
67
|
void update_advertising_data(advertising_data_t advertising_data);
|
|
66
68
|
void notify_connected(uint16_t conn_handle);
|
|
@@ -69,6 +71,7 @@ class PeripheralDongl : public PeripheralBase {
|
|
|
69
71
|
void notify_characteristic_discovered(simpleble_CharacteristicDiscoveredEvt const& characteristic_discovered_evt);
|
|
70
72
|
void notify_descriptor_discovered(simpleble_DescriptorDiscoveredEvt const& descriptor_discovered_evt);
|
|
71
73
|
void notify_attribute_discovery_complete();
|
|
74
|
+
void notify_value_changed(simpleble_ValueChangedEvt const& value_changed_evt);
|
|
72
75
|
|
|
73
76
|
const uint16_t BLE_CONN_HANDLE_INVALID = 0xFFFF;
|
|
74
77
|
const uint16_t BLE_CONN_HANDLE_PENDING = 0xFFFE;
|
|
@@ -83,6 +86,7 @@ class PeripheralDongl : public PeripheralBase {
|
|
|
83
86
|
BluetoothUUID uuid;
|
|
84
87
|
uint16_t handle_decl;
|
|
85
88
|
uint16_t handle_value;
|
|
89
|
+
uint16_t handle_cccd = 0;
|
|
86
90
|
bool can_read;
|
|
87
91
|
bool can_write_request;
|
|
88
92
|
bool can_write_command;
|
|
@@ -105,8 +109,10 @@ class PeripheralDongl : public PeripheralBase {
|
|
|
105
109
|
BluetoothUUID _uuid_from_uuid128(const uint8_t uuid[16]);
|
|
106
110
|
BluetoothUUID _uuid_from_proto(simpleble_UUID const& uuid);
|
|
107
111
|
|
|
108
|
-
ServiceDefinition&
|
|
109
|
-
CharacteristicDefinition&
|
|
112
|
+
ServiceDefinition& _find_service_from_handle(uint16_t handle);
|
|
113
|
+
CharacteristicDefinition& _find_characteristic_from_handle(uint16_t handle);
|
|
114
|
+
CharacteristicDefinition& _find_characteristic_from_uuid(BluetoothUUID const& service,
|
|
115
|
+
BluetoothUUID const& characteristic);
|
|
110
116
|
|
|
111
117
|
uint16_t _conn_handle = BLE_CONN_HANDLE_INVALID;
|
|
112
118
|
std::string _identifier;
|
|
@@ -131,6 +137,7 @@ class PeripheralDongl : public PeripheralBase {
|
|
|
131
137
|
|
|
132
138
|
kvn::safe_callback<void()> _callback_on_connected;
|
|
133
139
|
kvn::safe_callback<void()> _callback_on_disconnected;
|
|
140
|
+
kvn::safe_map<uint16_t, std::function<void(ByteArray payload)>> _callbacks_on_value_changed;
|
|
134
141
|
};
|
|
135
142
|
|
|
136
143
|
} // namespace SimpleBLE
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
#include "nanopb/pb.h"
|
|
7
7
|
#include "protocol/basic.pb.h"
|
|
8
8
|
#include "protocol/simpleble.pb.h"
|
|
9
|
-
#include "protocol/softdevice.pb.h"
|
|
10
9
|
|
|
11
10
|
#if PB_PROTO_HEADER_VERSION != 40
|
|
12
11
|
#error Regenerate this file with the current version of nanopb generator.
|
|
@@ -19,14 +18,12 @@ typedef struct _dongl_Response {
|
|
|
19
18
|
union {
|
|
20
19
|
basic_Response basic;
|
|
21
20
|
simpleble_Response simpleble;
|
|
22
|
-
sd_Response softdevice;
|
|
23
21
|
} rsp;
|
|
24
22
|
} dongl_Response;
|
|
25
23
|
|
|
26
24
|
typedef struct _dongl_Event {
|
|
27
25
|
pb_size_t which_evt;
|
|
28
26
|
union {
|
|
29
|
-
sd_Event softdevice;
|
|
30
27
|
simpleble_Event simpleble;
|
|
31
28
|
} evt;
|
|
32
29
|
} dongl_Event;
|
|
@@ -46,38 +43,32 @@ extern "C" {
|
|
|
46
43
|
|
|
47
44
|
/* Initializer values for message structs */
|
|
48
45
|
#define dongl_Response_init_default {0, {basic_Response_init_default}}
|
|
49
|
-
#define dongl_Event_init_default {0, {
|
|
46
|
+
#define dongl_Event_init_default {0, {simpleble_Event_init_default}}
|
|
50
47
|
#define dongl_D2H_init_default {0, {dongl_Response_init_default}}
|
|
51
48
|
#define dongl_Response_init_zero {0, {basic_Response_init_zero}}
|
|
52
|
-
#define dongl_Event_init_zero {0, {
|
|
49
|
+
#define dongl_Event_init_zero {0, {simpleble_Event_init_zero}}
|
|
53
50
|
#define dongl_D2H_init_zero {0, {dongl_Response_init_zero}}
|
|
54
51
|
|
|
55
52
|
/* Field tags (for use in manual encoding/decoding) */
|
|
56
53
|
#define dongl_Response_basic_tag 1
|
|
57
54
|
#define dongl_Response_simpleble_tag 2
|
|
58
|
-
#define
|
|
59
|
-
#define dongl_Event_softdevice_tag 2
|
|
60
|
-
#define dongl_Event_simpleble_tag 3
|
|
55
|
+
#define dongl_Event_simpleble_tag 2
|
|
61
56
|
#define dongl_D2H_rsp_tag 1
|
|
62
57
|
#define dongl_D2H_evt_tag 2
|
|
63
58
|
|
|
64
59
|
/* Struct field encoding specification for nanopb */
|
|
65
60
|
#define dongl_Response_FIELDLIST(X, a) \
|
|
66
61
|
X(a, STATIC, ONEOF, MESSAGE, (rsp,basic,rsp.basic), 1) \
|
|
67
|
-
X(a, STATIC, ONEOF, MESSAGE, (rsp,simpleble,rsp.simpleble), 2)
|
|
68
|
-
X(a, STATIC, ONEOF, MESSAGE, (rsp,softdevice,rsp.softdevice), 3)
|
|
62
|
+
X(a, STATIC, ONEOF, MESSAGE, (rsp,simpleble,rsp.simpleble), 2)
|
|
69
63
|
#define dongl_Response_CALLBACK NULL
|
|
70
64
|
#define dongl_Response_DEFAULT NULL
|
|
71
65
|
#define dongl_Response_rsp_basic_MSGTYPE basic_Response
|
|
72
66
|
#define dongl_Response_rsp_simpleble_MSGTYPE simpleble_Response
|
|
73
|
-
#define dongl_Response_rsp_softdevice_MSGTYPE sd_Response
|
|
74
67
|
|
|
75
68
|
#define dongl_Event_FIELDLIST(X, a) \
|
|
76
|
-
X(a, STATIC, ONEOF, MESSAGE, (evt,
|
|
77
|
-
X(a, STATIC, ONEOF, MESSAGE, (evt,simpleble,evt.simpleble), 3)
|
|
69
|
+
X(a, STATIC, ONEOF, MESSAGE, (evt,simpleble,evt.simpleble), 2)
|
|
78
70
|
#define dongl_Event_CALLBACK NULL
|
|
79
71
|
#define dongl_Event_DEFAULT NULL
|
|
80
|
-
#define dongl_Event_evt_softdevice_MSGTYPE sd_Event
|
|
81
72
|
#define dongl_Event_evt_simpleble_MSGTYPE simpleble_Event
|
|
82
73
|
|
|
83
74
|
#define dongl_D2H_FIELDLIST(X, a) \
|
|
@@ -98,18 +89,10 @@ extern const pb_msgdesc_t dongl_D2H_msg;
|
|
|
98
89
|
#define dongl_D2H_fields &dongl_D2H_msg
|
|
99
90
|
|
|
100
91
|
/* Maximum encoded size of messages (where known) */
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
union dongl_D2H_type_size_union {char f2[(6 + sizeof(union dongl_Event_evt_size_union))]; char f0[549];};
|
|
106
|
-
#endif
|
|
107
|
-
#define DONGL_D2H_PB_H_MAX_SIZE dongl_Response_size
|
|
108
|
-
#define dongl_Response_size 546
|
|
109
|
-
#if defined(sd_Event_size)
|
|
110
|
-
#define dongl_D2H_size (0 + sizeof(union dongl_D2H_type_size_union))
|
|
111
|
-
#define dongl_Event_size (0 + sizeof(union dongl_Event_evt_size_union))
|
|
112
|
-
#endif
|
|
92
|
+
#define DONGL_D2H_PB_H_MAX_SIZE dongl_D2H_size
|
|
93
|
+
#define dongl_D2H_size 534
|
|
94
|
+
#define dongl_Event_size 531
|
|
95
|
+
#define dongl_Response_size 531
|
|
113
96
|
|
|
114
97
|
#ifdef __cplusplus
|
|
115
98
|
} /* extern "C" */
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
#include "nanopb/pb.h"
|
|
7
7
|
#include "protocol/basic.pb.h"
|
|
8
8
|
#include "protocol/simpleble.pb.h"
|
|
9
|
-
#include "protocol/softdevice.pb.h"
|
|
10
9
|
|
|
11
10
|
#if PB_PROTO_HEADER_VERSION != 40
|
|
12
11
|
#error Regenerate this file with the current version of nanopb generator.
|
|
@@ -19,7 +18,6 @@ typedef struct _dongl_Command {
|
|
|
19
18
|
union {
|
|
20
19
|
basic_Command basic;
|
|
21
20
|
simpleble_Command simpleble;
|
|
22
|
-
sd_Command softdevice;
|
|
23
21
|
} cmd;
|
|
24
22
|
} dongl_Command;
|
|
25
23
|
|
|
@@ -35,18 +33,15 @@ extern "C" {
|
|
|
35
33
|
/* Field tags (for use in manual encoding/decoding) */
|
|
36
34
|
#define dongl_Command_basic_tag 1
|
|
37
35
|
#define dongl_Command_simpleble_tag 2
|
|
38
|
-
#define dongl_Command_softdevice_tag 3
|
|
39
36
|
|
|
40
37
|
/* Struct field encoding specification for nanopb */
|
|
41
38
|
#define dongl_Command_FIELDLIST(X, a) \
|
|
42
39
|
X(a, STATIC, ONEOF, MESSAGE, (cmd,basic,cmd.basic), 1) \
|
|
43
|
-
X(a, STATIC, ONEOF, MESSAGE, (cmd,simpleble,cmd.simpleble), 2)
|
|
44
|
-
X(a, STATIC, ONEOF, MESSAGE, (cmd,softdevice,cmd.softdevice), 3)
|
|
40
|
+
X(a, STATIC, ONEOF, MESSAGE, (cmd,simpleble,cmd.simpleble), 2)
|
|
45
41
|
#define dongl_Command_CALLBACK NULL
|
|
46
42
|
#define dongl_Command_DEFAULT NULL
|
|
47
43
|
#define dongl_Command_cmd_basic_MSGTYPE basic_Command
|
|
48
44
|
#define dongl_Command_cmd_simpleble_MSGTYPE simpleble_Command
|
|
49
|
-
#define dongl_Command_cmd_softdevice_MSGTYPE sd_Command
|
|
50
45
|
|
|
51
46
|
extern const pb_msgdesc_t dongl_Command_msg;
|
|
52
47
|
|
|
@@ -54,13 +49,8 @@ extern const pb_msgdesc_t dongl_Command_msg;
|
|
|
54
49
|
#define dongl_Command_fields &dongl_Command_msg
|
|
55
50
|
|
|
56
51
|
/* Maximum encoded size of messages (where known) */
|
|
57
|
-
#if defined(sd_Command_size)
|
|
58
|
-
union dongl_Command_cmd_size_union {char f3[(6 + sd_Command_size)]; char f0[531];};
|
|
59
|
-
#endif
|
|
60
|
-
#if defined(sd_Command_size)
|
|
61
52
|
#define DONGL_H2D_PB_H_MAX_SIZE dongl_Command_size
|
|
62
|
-
#define dongl_Command_size
|
|
63
|
-
#endif
|
|
53
|
+
#define dongl_Command_size 531
|
|
64
54
|
|
|
65
55
|
#ifdef __cplusplus
|
|
66
56
|
} /* extern "C" */
|