5 #ifndef HERALD_BLE_COORDINATION_PROVIDER_H
6 #define HERALD_BLE_COORDINATION_PROVIDER_H
8 #include "../context.h"
10 #include "ble_database.h"
11 #include "ble_protocols.h"
12 #include "ble_coordinator.h"
13 #include "../engine/activities.h"
14 #include "ble_protocols.h"
15 #include "../data/sensor_logger.h"
16 #include "ble_sensor_configuration.h"
26 template <
typename ContextT,
typename BLEDBT,
typename Prov
iderT>
34 previouslyProvisioned(),
35 iterationsSinceBreak(0),
38 HLOGGERINIT(ctx,
"heraldble",
"coordinationprovider")
47 return std::vector<FeatureTag>(1,herald::engine::Features::HeraldBluetoothProtocolConnection);
53 const std::vector<PrioritisedPrerequisite>& requested)
override {
54 if (requested.empty()) {
57 HTDBG(
"Provisioning connections");
61 if (iterationsSinceBreak >= breakEvery &&
62 iterationsSinceBreak < (breakEvery + breakFor) ) {
63 return previouslyProvisioned;
67 for (
auto& previous : previouslyProvisioned) {
69 for (
auto& req : requested) {
70 found = found || std::get<2>(req)==std::get<2>(previous);
73 HTDBG(
" - Found connection to remove");
74 auto& optTarget = std::get<2>(previous);
76 if (optTarget.has_value()) {
78 pp.closeConnection(optTarget.value());
84 std::vector<PrioritisedPrerequisite> provisioned;
86 auto requestIter = requested.cbegin();
87 bool lastConnectionSuccessful =
true;
89 lastConnectionSuccessful &&
90 requestIter != requested.cend()) {
91 HTDBG(
" - Satisfying prereq");
94 auto& req = *requestIter;
98 auto& optTarget = std::get<2>(req);
99 if (optTarget.has_value()) {
100 HTDBG(
" - Have defined target for this prerequisite. Requesting connection be made available.");
109 lastConnectionSuccessful = pp.openConnection(optTarget.value());
112 if (lastConnectionSuccessful) {
113 HTDBG(
" - Ensuring connection successful");
114 provisioned.push_back(req);
117 HTDBG(
" - Ensuring connection UNSUCCESSFUL");
120 HTDBG(
" - No defined target, returning satisfied - always true for Herald BLE");
122 provisioned.push_back(req);
128 lastConnectionSuccessful =
true;
131 previouslyProvisioned = provisioned;
145 std::vector<std::tuple<FeatureTag,Priority,std::optional<TargetIdentifier>>> results;
148 iterationsSinceBreak++;
149 if (iterationsSinceBreak >= breakEvery &&
150 iterationsSinceBreak < (breakEvery + breakFor) ) {
151 HTDBG(
"###### Skipping connections - giving advertising & scanning a chance");
153 pp.restartScanningAndAdvertising();
156 }
else if (iterationsSinceBreak == (breakEvery + breakFor) ) {
158 iterationsSinceBreak = 0;
162 auto expired = db.matches([] (
const BLEDevice& device) ->
bool {
163 auto interval = device.timeIntervalSinceLastUpdate();
164 bool notZero = interval != TimeInterval::zero();
165 bool isOld = interval > TimeInterval::minutes(15);
173 return notZero && isOld;
175 for (
auto& exp : expired) {
176 db.remove(exp.get().identifier());
177 HTDBG(
"Removing expired device with ID: ");
178 HTDBG((std::string)exp.get().identifier());
179 HTDBG(
"time since last update:-");
180 HTDBG(std::to_string(exp.get().timeIntervalSinceLastUpdate()));
184 auto tempIgnoredOS = db.matches([](
const BLEDevice& device) ->
bool {
185 return device.operatingSystem() == BLEDeviceOperatingSystem::ignore;
187 for (
auto& device : tempIgnoredOS) {
189 device.get().operatingSystem(BLEDeviceOperatingSystem::unknown);
194 auto newConns = db.matches([
this](
const BLEDevice& device) ->
bool {
195 return !device.ignore() &&
197 !device.
hasService(context.getSensorConfiguration().serviceUUID)
199 device.payloadData().
size() == 0
205 for (
auto& device : newConns) {
206 results.emplace_back(herald::engine::Features::HeraldBluetoothProtocolConnection,
207 herald::engine::Priorities::High,
208 device.get().identifier()
215 if (newConns.size() > 0) {
217 HTDBG(
"BLE DATABASE CURRENT CONTENTS:-");
218 auto allDevices = db.matches([](
const BLEDevice& device) ->
bool {
221 for (
auto& device : allDevices) {
222 std::string di(
" - ");
223 BLEMacAddress mac(device.get().identifier().underlyingData());
224 di += (std::string)mac;
227 di +=
", pseudoAddress=";
228 auto pseudo = device.get().pseudoDeviceAddress();
229 if (pseudo.has_value()) {
230 di += (std::string)pseudo.value();
235 auto os = device.get().operatingSystem();
237 if (herald::ble::BLEDeviceOperatingSystem::ios == os) {
239 }
else if (herald::ble::BLEDeviceOperatingSystem::android == os) {
241 }
else if (herald::ble::BLEDeviceOperatingSystem::unknown == os) {
243 }
else if (herald::ble::BLEDeviceOperatingSystem::ignore == os) {
245 }
else if (herald::ble::BLEDeviceOperatingSystem::android_tbc == os) {
247 }
else if (herald::ble::BLEDeviceOperatingSystem::ios_tbc == os) {
249 }
else if (herald::ble::BLEDeviceOperatingSystem::shared == os) {
256 auto ignore = device.get().ignore();
259 di += std::to_string(device.get().timeIntervalUntilIgnoreExpired().millis());
266 di +=
", hasReadPayload=";
267 di += (device.get().payloadData().
size() > 0 ? device.get().payloadData().
hexEncodedString() :
"false");
272 pp.restartScanningAndAdvertising();
279 std::vector<Activity> results;
283 auto expiredDevices = db.matches([
this](
const BLEDevice& device) ->
bool {
284 return device.timeIntervalSinceLastUpdate() > context.getSensorConfiguration().peripheralCleanInterval;
286 std::size_t dbSizeBefore = db.size();
287 for (
auto& device : expiredDevices) {
289 HTDBG(
"taskRemoveExpiredDevices (remove={})", (std::string)device.get().identifier());
290 db.remove(device.get().identifier());
292 std::size_t dbSizeAfter = db.size();
293 if (dbSizeAfter < dbSizeBefore) {
294 HTDBG(
" db size has reduced");
314 auto state1Devices = db.matches([
this](
const BLEDevice& device) ->
bool {
315 return !device.ignore() &&
317 !device.
hasService(context.getSensorConfiguration().serviceUUID);
319 auto state2Devices = db.matches([
this](
const BLEDevice& device) ->
bool {
320 return !device.ignore() &&
322 device.
hasService(context.getSensorConfiguration().serviceUUID) &&
323 device.payloadData().
size() == 0;
337 for (
auto& device : state1Devices) {
340 .name =
"herald-service-discovery",
341 .prerequisites = std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
343 std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
344 herald::engine::Features::HeraldBluetoothProtocolConnection,
345 device.get().identifier()
352 .executor = [
this](
const Activity activity) -> std::optional<Activity> {
354 pp.serviceDiscovery(activity);
361 for (
auto& device : state2Devices) {
364 .name =
"herald-read-payload",
365 .prerequisites = std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
367 std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
368 herald::engine::Features::HeraldBluetoothProtocolConnection,
369 device.get().identifier()
376 .executor = [
this](
const Activity activity) -> std::optional<Activity> {
378 pp.readPayload(activity);
421 std::vector<PrioritisedPrerequisite> previouslyProvisioned;
423 int iterationsSinceBreak;
Definition: ble_device.h:181
bool hasService(const UUID &serviceUUID) const
Definition: ble_mac_address.h:18
Definition: ble_coordinator.h:27
std::vector< Activity > requiredActivities() override
Get a list of activities that are currently outstanding in this iteration.
Definition: ble_coordinator.h:278
std::vector< PrioritisedPrerequisite > requiredConnections() override
Definition: ble_coordinator.h:144
std::vector< PrioritisedPrerequisite > provision(const std::vector< PrioritisedPrerequisite > &requested) override
Runtime connection provisioning (if it isn't requested, it can be closed)
Definition: ble_coordinator.h:52
std::vector< FeatureTag > connectionsProvided() override
Definition: ble_coordinator.h:46
std::string hexEncodedString() const noexcept
Returns a hex encoded string of this binary data.
Definition: data.h:443
std::size_t size() const noexcept
Returns the size in allocated bytes of this instance.
Definition: data.h:469
Coordination management class that arranges Sensor's periodic requirements and activity interdependen...
Definition: activities.h:93
Acts as a non-global memory arena for arbitrary classes.
Definition: aggregates.h:15
An activity that needs to be performed due to some state being achieved in a Sensor.
Definition: activities.h:75
Priority priority
The relative priority for this Activity compared to the scale.
Definition: activities.h:78