5 #ifndef HERALD_BLE_CONCRETE_DATABASE_H
6 #define HERALD_BLE_CONCRETE_DATABASE_H
8 #include "ble_database.h"
9 #include "ble_receiver.h"
10 #include "ble_sensor.h"
11 #include "ble_transmitter.h"
12 #include "ble_concrete.h"
13 #include "ble_protocols.h"
14 #include "bluetooth_state_manager.h"
15 #include "ble_device_delegate.h"
16 #include "filter/ble_advert_parser.h"
17 #include "../payload/payload_data_supplier.h"
18 #include "../context.h"
19 #include "../data/sensor_logger.h"
20 #include "ble_sensor_configuration.h"
21 #include "ble_coordinator.h"
22 #include "../datatype/bluetooth_state.h"
34 using namespace herald::ble::filter;
35 using namespace herald::payload;
41 return a.timeIntervalSinceLastUpdate() > b.timeIntervalSinceLastUpdate();
45 template <
typename ContextT, std::
size_t MaxDevicesCached = 10>
48 static constexpr std::size_t MaxDevices = MaxDevicesCached;
54 HLOGGERINIT(context,
"herald",
"ConcreteBLEDatabase")
67 delegates.emplace_back(delegate);
74 auto results = matches([&targetIdentifier](
const BLEDevice& d) {
75 return d.identifier() == targetIdentifier;
77 if (results.size() != 0) {
80 return results.front();
86 auto segments = BLEAdvertParser::extractSegments(advert,0);
89 auto manuData = BLEAdvertParser::extractManufacturerData(segments);
90 auto heraldDataSegments = BLEAdvertParser::extractHeraldManufacturerData(manuData);
107 if (0 != heraldDataSegments.size()) {
111 auto samePseudo = matches([&pseudo](
const BLEDevice& d) {
112 return d.pseudoDeviceAddress() == pseudo;
114 if (0 != samePseudo.size()) {
116 return samePseudo.front();
120 auto& newDevice = device(mac,pseudo);
121 assignAdvertData(newDevice,std::move(segments), manuData);
129 auto& newDevice = device(targetIdentifier);
131 assignAdvertData(newDevice,std::move(segments), manuData);
138 auto samePseudo = matches([&pseudo](
const BLEDevice& d) {
139 return d.pseudoDeviceAddress() == pseudo;
141 if (0 == samePseudo.size()) {
143 ptr.pseudoDeviceAddress(pseudo);
148 std::sort(samePseudo.begin(),samePseudo.end(), comp);
149 BLEDevice& updatedDevice = samePseudo.front();
157 updatedDevice.operatingSystem(BLEDeviceOperatingSystem::android);
160 updatedDevice.registerDiscovery(
Date());
163 for (
auto& delegate : delegates) {
164 delegate.get().bleDatabaseDidCreate(updatedDevice);
166 return updatedDevice;
175 auto results = matches([&pti](
const BLEDevice& d) {
176 return d.identifier() == pti;
183 if (results.size() != 0) {
184 return results.front();
186 BLEDevice& newDevice = devices[indexAvailable()];
187 newDevice.
reset(pti,*
this);
189 for (
auto& delegate : delegates) {
190 delegate.get().bleDatabaseDidCreate(newDevice);
193 device(newDevice,BLEDeviceAttribute::payloadData);
198 auto results = matches([
this,&targetIdentifier](
const BLEDevice& d) {
199 HTDBG(
" Testing existing target identifier {} against new target identifier {}",(std::string)d.identifier(),(std::string)targetIdentifier);
200 return d.identifier() == targetIdentifier;
202 if (results.size() != 0) {
203 HTDBG(
"Device for target identifier {} already exists",(std::string)targetIdentifier);
204 return results.front();
206 HTDBG(
"New target identified: {}",(std::string)targetIdentifier);
207 BLEDevice& newDevice = devices[indexAvailable()];
208 newDevice.
reset(targetIdentifier,*
this);
210 for (
auto& delegate : delegates) {
211 delegate.get().bleDatabaseDidCreate(newDevice);
217 std::size_t size()
const override {
218 std::size_t count = 0;
219 for (
auto& d : devices) {
220 if (d.state() != BLEDeviceState::uninitialised) {
227 std::vector<std::reference_wrapper<BLEDevice>> matches(
228 const std::function<
bool(
const BLEDevice&)>& matcher)
override {
229 std::vector<std::reference_wrapper<BLEDevice>> results;
231 for (
auto iter = devices.begin();iter != devices.end();++iter) {
232 if (BLEDeviceState::uninitialised != iter->state() && matcher(*iter)) {
233 results.push_back(std::reference_wrapper<BLEDevice>(*iter));
241 auto found = std::find_if(devices.begin(),devices.end(),
242 [&targetIdentifier](
BLEDevice& d) ->
bool {
243 return d.identifier() == targetIdentifier;
246 if (found != devices.end()) {
253 void device(
const BLEDevice& device, BLEDeviceAttribute didUpdate)
override {
255 if (BLEDeviceAttribute::payloadData == didUpdate) {
257 auto oldMacsForSamePayload = matches([device](
auto& devRef) {
258 return devRef.identifier() != device.identifier() &&
259 devRef.payloadData().size() > 0 && devRef.payloadData() == device.payloadData();
261 for (
auto& oldMacDevice : oldMacsForSamePayload) {
262 remove(oldMacDevice.get().identifier());
267 for (
auto& delegate : delegates) {
268 delegate.get().bleDatabaseDidUpdate(device, didUpdate);
273 void assignAdvertData(
BLEDevice& newDevice, std::vector<BLEAdvertSegment>&& toMove,
274 const std::vector<BLEAdvertManufacturerData>& manuData)
276 newDevice.advertData(std::move(toMove));
279 auto appleDataSegments = BLEAdvertParser::extractAppleManufacturerSegments(manuData);
280 if (0 != appleDataSegments.size()) {
281 HTDBG(
"Found apple device");
283 newDevice.operatingSystem(BLEDeviceOperatingSystem::ios);
294 for (
auto& segment : appleDataSegments) {
295 HTDBG(segment.data.hexEncodedString());
296 switch (segment.type) {
313 if (segment.data.at(0) == std::byte(0x02)) {
317 if (segment.data.at(2) == std::byte(0x04) || segment.data.at(2) == std::byte(0x14)) {
327 HTDBG(
" - Ignoring Apple device due to Apple data filter");
328 newDevice.ignore(
true);
332 HTDBG(
" - Unknown apple device... Logging so we can discover services later");
336 HTDBG(
"Unknown non Herald device - inspecting (might be a venue beacon or wearable)");
343 if (toRemove.state() == BLEDeviceState::uninitialised) {
346 toRemove.state(BLEDeviceState::uninitialised);
348 for (
auto& delegate : delegates) {
349 delegate.get().bleDatabaseDidDelete(toRemove);
353 std::size_t indexAvailable() noexcept {
354 for (std::size_t idx = 0;idx < devices.size();++idx) {
355 auto& device = devices[idx];
356 if (BLEDeviceState::uninitialised == device.state()) {
363 std::size_t oldestIndex = 0;
364 for (std::size_t idx = 0;idx < devices.size();++idx) {
365 if (!comp(devices[oldestIndex],devices[idx])) {
371 auto& oldest = devices[oldestIndex];
378 std::vector<std::reference_wrapper<BLEDatabaseDelegate>> delegates;
379 std::array<BLEDevice,MaxDevices> devices;
Definition: ble_database_delegate.h:15
Definition: ble_database.h:25
Definition: ble_device_delegate.h:13
Definition: ble_device.h:181
void reset(const TargetIdentifier &newID, BLEDeviceDelegate &newDelegate)
Resets the device to what it's state would be if just constructed. Allows re-use in fixed size contai...
Definition: ble_mac_address.h:18
Definition: ble_concrete_database.h:46
void remove(const TargetIdentifier &targetIdentifier) override
Cannot name a function delete in C++. remove is common.
Definition: ble_concrete_database.h:240
The main data workhorse class of the Herald API.
Definition: data.h:33
Definition: payload_data.h:13
Definition: target_identifier.h:17
Contains all low-level Herald datatype implementations.
Definition: base64_string.h:14
Acts as a non-global memory arena for arbitrary classes.
Definition: aggregates.h:15
Provides a callable that assists in ordering for most recently updated BLEDevice.
Definition: ble_concrete_database.h:39