Coverage Report

Created: 2021-08-28 18:14

D:\git\skunkworks\herald-for-cpp\herald\include\herald\ble\ble_coordinator.h
Line
Count
Source (jump to first uncovered line)
1
//  Copyright 2021 Herald Project Contributors
2
//  SPDX-License-Identifier: Apache-2.0
3
//
4
5
#ifndef HERALD_BLE_COORDINATION_PROVIDER_H
6
#define HERALD_BLE_COORDINATION_PROVIDER_H
7
8
#include "../context.h"
9
#include "../sensor.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"
17
18
#include <memory>
19
#include <functional>
20
#include <optional>
21
#include <tuple>
22
23
namespace herald {
24
namespace ble {
25
26
template <typename ContextT, typename BLEDBT, typename ProviderT>
27
class HeraldProtocolBLECoordinationProvider : public CoordinationProvider {
28
public:
29
  HeraldProtocolBLECoordinationProvider(ContextT& ctx, BLEDBT& bledb, 
30
    ProviderT& provider) 
31
  : context(ctx),
32
    db(bledb),
33
    pp(provider),
34
    previouslyProvisioned(),
35
    iterationsSinceBreak(0),
36
    breakEvery(10),
37
    breakFor(10)
38
    HLOGGERINIT(ctx,"heraldble","coordinationprovider")
39
8
  {}
??0?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@QEAA@AEAU?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@2@AEAV?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@12@AEAV?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@Z
Line
Count
Source
39
7
  {}
??0?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@QEAA@AEAU?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@2@AEAV?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@12@AEAV?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@Z
Line
Count
Source
39
1
  {}
40
41
8
  ~HeraldProtocolBLECoordinationProvider() = default;
??1?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA@XZ
Line
Count
Source
41
7
  ~HeraldProtocolBLECoordinationProvider() = default;
??1?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA@XZ
Line
Count
Source
41
1
  ~HeraldProtocolBLECoordinationProvider() = default;
42
43
  // Overrides
44
  
45
  /** What connections does this Sensor type provide for Coordination **/
46
2
  std::vector<FeatureTag> connectionsProvided() override {
47
2
    return std::vector<FeatureTag>(1,herald::engine::Features::HeraldBluetoothProtocolConnection);
48
2
  }
?connectionsProvided@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@V?$allocator@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@@std@@@std@@XZ
Line
Count
Source
46
1
  std::vector<FeatureTag> connectionsProvided() override {
47
1
    return std::vector<FeatureTag>(1,herald::engine::Features::HeraldBluetoothProtocolConnection);
48
1
  }
?connectionsProvided@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@V?$allocator@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@@std@@@std@@XZ
Line
Count
Source
46
1
  std::vector<FeatureTag> connectionsProvided() override {
47
1
    return std::vector<FeatureTag>(1,herald::engine::Features::HeraldBluetoothProtocolConnection);
48
1
  }
49
50
  // void provision(const std::vector<PrioritisedPrerequisite>& requested,
51
  //   const ConnectionCallback& connCallback) override;
52
  std::vector<PrioritisedPrerequisite> provision(
53
4
    const std::vector<PrioritisedPrerequisite>& requested) override {
54
4
    if (requested.empty()) {
55
2
      // HTDBG("No connections requested for provisioning");
56
2
    } else {
57
2
      HTDBG("Provisioning connections");
58
2
    }
59
4
60
4
    // Don't close connections if we've only paused for advertising/scanning
61
4
    if (iterationsSinceBreak >= breakEvery &&
62
4
      
iterationsSinceBreak < (breakEvery + breakFor)0
) {
63
0
        return previouslyProvisioned;
64
0
    }
65
4
66
4
    // Remove those previously provisoned that we no longer require
67
4
    for (auto& previous : previouslyProvisioned) {
68
2
      bool found = false;
69
2
      for (auto& req : requested) {
70
1
        found = found || std::get<2>(req)==std::get<2>(previous); // comparing target values
71
1
      }
72
2
      if (!found) {
73
1
        HTDBG(" - Found connection to remove");
74
1
        auto& optTarget = std::get<2>(previous);
75
1
        // We can't disconnect from 'all', so check for target
76
1
        if (optTarget.has_value()) {
77
1
          // Ignoring closed true/false result
78
1
          pp.closeConnection(optTarget.value());
79
1
        }
80
1
      }
81
2
    }
82
4
83
4
    // Now provision new connections
84
4
    std::vector<PrioritisedPrerequisite> provisioned;
85
4
    // For this provider, a prerequisite is a connection to a remote target identifier over Bluetooth
86
4
    auto requestIter = requested.cbegin();
87
4
    bool lastConnectionSuccessful = true;
88
4
    while (/*currentConnections < maxConnections && */
89
6
          lastConnectionSuccessful && 
90
6
          requestIter != requested.cend()) {
91
2
      HTDBG(" - Satisfying prereq");
92
2
      // HTDBG(" - currentConnections currently:-");
93
2
      // HTDBG(std::to_string(currentConnections));
94
2
      auto& req = *requestIter;
95
2
      // See if we're already connected
96
2
      // If so, add to provisioned list
97
2
      // If not, try to connect
98
2
      auto& optTarget = std::get<2>(req);
99
2
      if (optTarget.has_value()) {
100
2
        HTDBG(" - Have defined target for this prerequisite. Requesting connection be made available.");
101
2
        // std::future<void> fut = std::async(std::launch::async,
102
2
        //     &HeraldProtocolV1Provider::openConnection,pp,
103
2
        //     optTarget.value(),[&lastConnectionSuccessful] (
104
2
        //     const TargetIdentifier& targetForConnection, bool success) -> void {
105
2
        //   lastConnectionSuccessful = success;
106
2
        // });
107
2
        // fut.get(); // TODO FIND OUT HOW TO DO THIS FUTURE WAITING FUNCTIONALITY
108
2
109
2
        lastConnectionSuccessful = pp.openConnection(optTarget.value());
110
2
111
2
        // If successful, add to provisioned list
112
2
        if (lastConnectionSuccessful) {
113
2
          HTDBG(" - Ensuring connection successful");
114
2
          provisioned.push_back(req);
115
2
          // currentConnections++;
116
2
        } else {
117
0
          HTDBG(" - Ensuring connection UNSUCCESSFUL");
118
0
        }
119
2
      } else {
120
0
        HTDBG(" - No defined target, returning satisfied - always true for Herald BLE");
121
0
        // if target not specified then it just means any open connection, so return OK
122
0
        provisioned.push_back(req);
123
0
        // TODO determine what to do here if sensor stopped, bluetooth disabled, or no connections open
124
0
      }
125
2
      // move forward in iterator
126
2
      requestIter++;
127
2
128
2
      lastConnectionSuccessful = true;
129
2
    }
130
4
131
4
    previouslyProvisioned = provisioned;
132
4
133
4
    // TODO schedule disconnection from not required items (E.g. after minimum connection time)
134
4
    //  - we already do this if provision is called, but not after a time period
135
4
    //  - Bluetooth timeout will deal with the underlying connection, but not any intermediate state in the PP instance
136
4
137
4
    // HTDBG("Returning from provision");
138
4
    // connCallback(provisioned);
139
4
    return provisioned;
140
4
  }
Unexecuted instantiation: ?provision@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@AEBV45@@Z
?provision@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@AEBV45@@Z
Line
Count
Source
53
4
    const std::vector<PrioritisedPrerequisite>& requested) override {
54
4
    if (requested.empty()) {
55
2
      // HTDBG("No connections requested for provisioning");
56
2
    } else {
57
2
      HTDBG("Provisioning connections");
58
2
    }
59
4
60
4
    // Don't close connections if we've only paused for advertising/scanning
61
4
    if (iterationsSinceBreak >= breakEvery &&
62
4
      
iterationsSinceBreak < (breakEvery + breakFor)0
) {
63
0
        return previouslyProvisioned;
64
0
    }
65
4
66
4
    // Remove those previously provisoned that we no longer require
67
4
    for (auto& previous : previouslyProvisioned) {
68
2
      bool found = false;
69
2
      for (auto& req : requested) {
70
1
        found = found || std::get<2>(req)==std::get<2>(previous); // comparing target values
71
1
      }
72
2
      if (!found) {
73
1
        HTDBG(" - Found connection to remove");
74
1
        auto& optTarget = std::get<2>(previous);
75
1
        // We can't disconnect from 'all', so check for target
76
1
        if (optTarget.has_value()) {
77
1
          // Ignoring closed true/false result
78
1
          pp.closeConnection(optTarget.value());
79
1
        }
80
1
      }
81
2
    }
82
4
83
4
    // Now provision new connections
84
4
    std::vector<PrioritisedPrerequisite> provisioned;
85
4
    // For this provider, a prerequisite is a connection to a remote target identifier over Bluetooth
86
4
    auto requestIter = requested.cbegin();
87
4
    bool lastConnectionSuccessful = true;
88
4
    while (/*currentConnections < maxConnections && */
89
6
          lastConnectionSuccessful && 
90
6
          requestIter != requested.cend()) {
91
2
      HTDBG(" - Satisfying prereq");
92
2
      // HTDBG(" - currentConnections currently:-");
93
2
      // HTDBG(std::to_string(currentConnections));
94
2
      auto& req = *requestIter;
95
2
      // See if we're already connected
96
2
      // If so, add to provisioned list
97
2
      // If not, try to connect
98
2
      auto& optTarget = std::get<2>(req);
99
2
      if (optTarget.has_value()) {
100
2
        HTDBG(" - Have defined target for this prerequisite. Requesting connection be made available.");
101
2
        // std::future<void> fut = std::async(std::launch::async,
102
2
        //     &HeraldProtocolV1Provider::openConnection,pp,
103
2
        //     optTarget.value(),[&lastConnectionSuccessful] (
104
2
        //     const TargetIdentifier& targetForConnection, bool success) -> void {
105
2
        //   lastConnectionSuccessful = success;
106
2
        // });
107
2
        // fut.get(); // TODO FIND OUT HOW TO DO THIS FUTURE WAITING FUNCTIONALITY
108
2
109
2
        lastConnectionSuccessful = pp.openConnection(optTarget.value());
110
2
111
2
        // If successful, add to provisioned list
112
2
        if (lastConnectionSuccessful) {
113
2
          HTDBG(" - Ensuring connection successful");
114
2
          provisioned.push_back(req);
115
2
          // currentConnections++;
116
2
        } else {
117
0
          HTDBG(" - Ensuring connection UNSUCCESSFUL");
118
0
        }
119
2
      } else {
120
0
        HTDBG(" - No defined target, returning satisfied - always true for Herald BLE");
121
0
        // if target not specified then it just means any open connection, so return OK
122
0
        provisioned.push_back(req);
123
0
        // TODO determine what to do here if sensor stopped, bluetooth disabled, or no connections open
124
0
      }
125
2
      // move forward in iterator
126
2
      requestIter++;
127
2
128
2
      lastConnectionSuccessful = true;
129
2
    }
130
4
131
4
    previouslyProvisioned = provisioned;
132
4
133
4
    // TODO schedule disconnection from not required items (E.g. after minimum connection time)
134
4
    //  - we already do this if provision is called, but not after a time period
135
4
    //  - Bluetooth timeout will deal with the underlying connection, but not any intermediate state in the PP instance
136
4
137
4
    // HTDBG("Returning from provision");
138
4
    // connCallback(provisioned);
139
4
    return provisioned;
140
4
  }
141
142
  // Runtime coordination callbacks
143
  /** Get a list of what connections are required to which devices now (may start, maintain, end (if not included)) **/
144
11
  std::vector<PrioritisedPrerequisite> requiredConnections() override {
145
11
    std::vector<std::tuple<FeatureTag,Priority,std::optional<TargetIdentifier>>> results;
146
11
147
11
    // This ensures we break from making connections to allow advertising and scanning
148
11
    iterationsSinceBreak++;
149
11
    if (iterationsSinceBreak >= breakEvery &&
150
11
      
iterationsSinceBreak < (breakEvery + breakFor)0
) {
151
0
      HTDBG("###### Skipping connections - giving advertising & scanning a chance");
152
0
      // if (iterationsSinceBreak == breakEvery) { // incase it fails
153
0
        pp.restartScanningAndAdvertising();
154
0
      // }
155
0
      return results;
156
11
    } else if (iterationsSinceBreak == (breakEvery + breakFor) ) {
157
0
      // reset
158
0
      iterationsSinceBreak = 0;
159
0
    }
160
11
161
11
    // Remove expired devices
162
13
    
auto expired = db.matches([/*this*/] (const BLEDevice& device) -> bool 11
{
163
13
      auto interval = device.timeIntervalSinceLastUpdate();
164
13
      bool notZero = interval != TimeInterval::zero();
165
13
      bool isOld = interval > TimeInterval::minutes(15);
166
13
      // HTDBG("ID, created, Now, interval, notZero, isOld:-");
167
13
      // HTDBG((std::string)device.identifier());
168
13
      // HTDBG(std::to_string((long)device.created()));
169
13
      // HTDBG(std::to_string((long)Date()));
170
13
      // HTDBG((std::string)interval);
171
13
      // HTDBG(notZero?"true":"false");
172
13
      // HTDBG(isOld?"true":"false");
173
13
      return notZero && 
isOld0
;
174
13
    });
??R<lambda_1>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
162
9
    auto expired = db.matches([/*this*/] (const BLEDevice& device) -> bool {
163
9
      auto interval = device.timeIntervalSinceLastUpdate();
164
9
      bool notZero = interval != TimeInterval::zero();
165
9
      bool isOld = interval > TimeInterval::minutes(15);
166
9
      // HTDBG("ID, created, Now, interval, notZero, isOld:-");
167
9
      // HTDBG((std::string)device.identifier());
168
9
      // HTDBG(std::to_string((long)device.created()));
169
9
      // HTDBG(std::to_string((long)Date()));
170
9
      // HTDBG((std::string)interval);
171
9
      // HTDBG(notZero?"true":"false");
172
9
      // HTDBG(isOld?"true":"false");
173
9
      return notZero && 
isOld0
;
174
9
    });
??R<lambda_1>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
162
4
    auto expired = db.matches([/*this*/] (const BLEDevice& device) -> bool {
163
4
      auto interval = device.timeIntervalSinceLastUpdate();
164
4
      bool notZero = interval != TimeInterval::zero();
165
4
      bool isOld = interval > TimeInterval::minutes(15);
166
4
      // HTDBG("ID, created, Now, interval, notZero, isOld:-");
167
4
      // HTDBG((std::string)device.identifier());
168
4
      // HTDBG(std::to_string((long)device.created()));
169
4
      // HTDBG(std::to_string((long)Date()));
170
4
      // HTDBG((std::string)interval);
171
4
      // HTDBG(notZero?"true":"false");
172
4
      // HTDBG(isOld?"true":"false");
173
4
      return notZero && 
isOld0
;
174
4
    });
175
11
    for (auto& exp : expired) {
176
0
      db.remove(exp.get().identifier());
177
0
      HTDBG("Removing expired device with ID: ");
178
0
      HTDBG((std::string)exp.get().identifier());
179
0
      HTDBG("time since last update:-");
180
0
      HTDBG(std::to_string(exp.get().timeIntervalSinceLastUpdate()));
181
0
    }
182
11
183
11
    // Allow updates from ignored (for a time) status, to retry status
184
13
    auto tempIgnoredOS = db.matches([](const BLEDevice& device) -> bool {
185
13
      return device.operatingSystem() == BLEDeviceOperatingSystem::ignore;
186
13
    });
??R<lambda_2>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
184
9
    auto tempIgnoredOS = db.matches([](const BLEDevice& device) -> bool {
185
9
      return device.operatingSystem() == BLEDeviceOperatingSystem::ignore;
186
9
    });
??R<lambda_2>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
184
4
    auto tempIgnoredOS = db.matches([](const BLEDevice& device) -> bool {
185
4
      return device.operatingSystem() == BLEDeviceOperatingSystem::ignore;
186
4
    });
187
11
    for (auto& device : tempIgnoredOS) {
188
0
      // don't bother with separate activity right now - no connection required
189
0
      device.get().operatingSystem(BLEDeviceOperatingSystem::unknown);
190
0
    }
191
11
192
11
193
11
    // Add all targets in database that are not known
194
13
    auto newConns = db.matches([this](const BLEDevice& device) -> bool {
195
13
      return !device.ignore() &&
196
13
        (
197
13
          !device.hasService(context.getSensorConfiguration().serviceUUID)
198
13
          ||
199
13
          
device.payloadData().size() == 011
// Know the OS, but not the payload (ID)
200
13
          // ||
201
13
          // device.immediateSendData().has_value()
202
13
        )
203
13
        ;
204
13
    });
??R<lambda_3>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
194
9
    auto newConns = db.matches([this](const BLEDevice& device) -> bool {
195
9
      return !device.ignore() &&
196
9
        (
197
9
          !device.hasService(context.getSensorConfiguration().serviceUUID)
198
9
          ||
199
9
          
device.payloadData().size() == 08
// Know the OS, but not the payload (ID)
200
9
          // ||
201
9
          // device.immediateSendData().has_value()
202
9
        )
203
9
        ;
204
9
    });
??R<lambda_3>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
194
4
    auto newConns = db.matches([this](const BLEDevice& device) -> bool {
195
4
      return !device.ignore() &&
196
4
        (
197
4
          !device.hasService(context.getSensorConfiguration().serviceUUID)
198
4
          ||
199
4
          
device.payloadData().size() == 03
// Know the OS, but not the payload (ID)
200
4
          // ||
201
4
          // device.immediateSendData().has_value()
202
4
        )
203
4
        ;
204
4
    });
205
11
    for (auto& device : newConns) {
206
8
      results.emplace_back(herald::engine::Features::HeraldBluetoothProtocolConnection,
207
8
        herald::engine::Priorities::High,
208
8
        device.get().identifier()
209
8
      );
210
8
    }
211
11
212
11
    // TODO any other devices we may have outstanding work for that requires connections
213
11
214
11
    // DEBUG ONLY ELEMENTS
215
11
    if (newConns.size() > 0) {
216
7
      // print debug info about the BLE Database
217
7
      HTDBG("BLE DATABASE CURRENT CONTENTS:-");
218
10
      auto allDevices = db.matches([](const BLEDevice& device) -> bool {
219
10
        return true;
220
10
      });
??R<lambda_4>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
218
8
      auto allDevices = db.matches([](const BLEDevice& device) -> bool {
219
8
        return true;
220
8
      });
??R<lambda_4>@?0??requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
218
2
      auto allDevices = db.matches([](const BLEDevice& device) -> bool {
219
2
        return true;
220
2
      });
221
10
      for (auto& device : allDevices) {
222
10
        std::string di(" - ");
223
10
        BLEMacAddress mac(device.get().identifier().underlyingData());
224
10
        di += (std::string)mac;
225
10
        // di += ", created=";
226
10
        // di += std::to_string(device.get().created());
227
10
        di += ", pseudoAddress=";
228
10
        auto pseudo = device.get().pseudoDeviceAddress();
229
10
        if (pseudo.has_value()) {
230
7
          di += (std::string)pseudo.value();
231
7
        } else {
232
3
          di += "unset";
233
3
        }
234
10
        di += ", os=";
235
10
        auto os = device.get().operatingSystem();
236
10
        // if (os.has_value()) {
237
10
          if (herald::ble::BLEDeviceOperatingSystem::ios == os) {
238
2
            di += "ios";
239
8
          } else if (herald::ble::BLEDeviceOperatingSystem::android == os) {
240
4
            di += "android";
241
4
          } else if (herald::ble::BLEDeviceOperatingSystem::unknown == os) {
242
4
            di += "unknown";
243
4
          } else 
if (0
herald::ble::BLEDeviceOperatingSystem::ignore == os0
) {
244
0
            di += "ignore";
245
0
          } else if (herald::ble::BLEDeviceOperatingSystem::android_tbc == os) {
246
0
            di += "android_tbc";
247
0
          } else if (herald::ble::BLEDeviceOperatingSystem::ios_tbc == os) {
248
0
            di += "ios_tbc";
249
0
          } else if (herald::ble::BLEDeviceOperatingSystem::shared == os) {
250
0
            di += "shared";
251
0
          }
252
10
        // } else {
253
10
        //   di += "unknown/unset";
254
10
        // }
255
10
        di += ", ignore=";
256
10
        auto ignore = device.get().ignore();
257
10
        if (ignore) {
258
0
          di += "true (for ";
259
0
          di += std::to_string(device.get().timeIntervalUntilIgnoreExpired().millis());
260
0
          di += " more secs)";
261
10
        } else {
262
10
          di += "false";
263
10
        }
264
10
        // di += ", hasServices=";
265
10
        // di += (device.get().hasServicesSet() ? "true" : "false");
266
10
        di += ", hasReadPayload=";
267
10
        di += (device.get().payloadData().size() > 0 ? 
device.get().payloadData().hexEncodedString()2
:
"false"8
);
268
10
        HTDBG(di);
269
10
      }
270
7
    } else {
271
4
      // restart scanning when no connection activity is expected
272
4
      pp.restartScanningAndAdvertising();
273
4
    }
274
11
275
11
    return results;
276
11
  }
?requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ
Line
Count
Source
144
7
  std::vector<PrioritisedPrerequisite> requiredConnections() override {
145
7
    std::vector<std::tuple<FeatureTag,Priority,std::optional<TargetIdentifier>>> results;
146
7
147
7
    // This ensures we break from making connections to allow advertising and scanning
148
7
    iterationsSinceBreak++;
149
7
    if (iterationsSinceBreak >= breakEvery &&
150
7
      
iterationsSinceBreak < (breakEvery + breakFor)0
) {
151
0
      HTDBG("###### Skipping connections - giving advertising & scanning a chance");
152
0
      // if (iterationsSinceBreak == breakEvery) { // incase it fails
153
0
        pp.restartScanningAndAdvertising();
154
0
      // }
155
0
      return results;
156
7
    } else if (iterationsSinceBreak == (breakEvery + breakFor) ) {
157
0
      // reset
158
0
      iterationsSinceBreak = 0;
159
0
    }
160
7
161
7
    // Remove expired devices
162
7
    auto expired = db.matches([/*this*/] (const BLEDevice& device) -> bool {
163
7
      auto interval = device.timeIntervalSinceLastUpdate();
164
7
      bool notZero = interval != TimeInterval::zero();
165
7
      bool isOld = interval > TimeInterval::minutes(15);
166
7
      // HTDBG("ID, created, Now, interval, notZero, isOld:-");
167
7
      // HTDBG((std::string)device.identifier());
168
7
      // HTDBG(std::to_string((long)device.created()));
169
7
      // HTDBG(std::to_string((long)Date()));
170
7
      // HTDBG((std::string)interval);
171
7
      // HTDBG(notZero?"true":"false");
172
7
      // HTDBG(isOld?"true":"false");
173
7
      return notZero && isOld;
174
7
    });
175
7
    for (auto& exp : expired) {
176
0
      db.remove(exp.get().identifier());
177
0
      HTDBG("Removing expired device with ID: ");
178
0
      HTDBG((std::string)exp.get().identifier());
179
0
      HTDBG("time since last update:-");
180
0
      HTDBG(std::to_string(exp.get().timeIntervalSinceLastUpdate()));
181
0
    }
182
7
183
7
    // Allow updates from ignored (for a time) status, to retry status
184
7
    auto tempIgnoredOS = db.matches([](const BLEDevice& device) -> bool {
185
7
      return device.operatingSystem() == BLEDeviceOperatingSystem::ignore;
186
7
    });
187
7
    for (auto& device : tempIgnoredOS) {
188
0
      // don't bother with separate activity right now - no connection required
189
0
      device.get().operatingSystem(BLEDeviceOperatingSystem::unknown);
190
0
    }
191
7
192
7
193
7
    // Add all targets in database that are not known
194
7
    auto newConns = db.matches([this](const BLEDevice& device) -> bool {
195
7
      return !device.ignore() &&
196
7
        (
197
7
          !device.hasService(context.getSensorConfiguration().serviceUUID)
198
7
          ||
199
7
          device.payloadData().size() == 0 // Know the OS, but not the payload (ID)
200
7
          // ||
201
7
          // device.immediateSendData().has_value()
202
7
        )
203
7
        ;
204
7
    });
205
7
    for (auto& device : newConns) {
206
6
      results.emplace_back(herald::engine::Features::HeraldBluetoothProtocolConnection,
207
6
        herald::engine::Priorities::High,
208
6
        device.get().identifier()
209
6
      );
210
6
    }
211
7
212
7
    // TODO any other devices we may have outstanding work for that requires connections
213
7
214
7
    // DEBUG ONLY ELEMENTS
215
7
    if (newConns.size() > 0) {
216
5
      // print debug info about the BLE Database
217
5
      HTDBG("BLE DATABASE CURRENT CONTENTS:-");
218
5
      auto allDevices = db.matches([](const BLEDevice& device) -> bool {
219
5
        return true;
220
5
      });
221
8
      for (auto& device : allDevices) {
222
8
        std::string di(" - ");
223
8
        BLEMacAddress mac(device.get().identifier().underlyingData());
224
8
        di += (std::string)mac;
225
8
        // di += ", created=";
226
8
        // di += std::to_string(device.get().created());
227
8
        di += ", pseudoAddress=";
228
8
        auto pseudo = device.get().pseudoDeviceAddress();
229
8
        if (pseudo.has_value()) {
230
6
          di += (std::string)pseudo.value();
231
6
        } else {
232
2
          di += "unset";
233
2
        }
234
8
        di += ", os=";
235
8
        auto os = device.get().operatingSystem();
236
8
        // if (os.has_value()) {
237
8
          if (herald::ble::BLEDeviceOperatingSystem::ios == os) {
238
2
            di += "ios";
239
6
          } else if (herald::ble::BLEDeviceOperatingSystem::android == os) {
240
3
            di += "android";
241
3
          } else if (herald::ble::BLEDeviceOperatingSystem::unknown == os) {
242
3
            di += "unknown";
243
3
          } else 
if (0
herald::ble::BLEDeviceOperatingSystem::ignore == os0
) {
244
0
            di += "ignore";
245
0
          } else if (herald::ble::BLEDeviceOperatingSystem::android_tbc == os) {
246
0
            di += "android_tbc";
247
0
          } else if (herald::ble::BLEDeviceOperatingSystem::ios_tbc == os) {
248
0
            di += "ios_tbc";
249
0
          } else if (herald::ble::BLEDeviceOperatingSystem::shared == os) {
250
0
            di += "shared";
251
0
          }
252
8
        // } else {
253
8
        //   di += "unknown/unset";
254
8
        // }
255
8
        di += ", ignore=";
256
8
        auto ignore = device.get().ignore();
257
8
        if (ignore) {
258
0
          di += "true (for ";
259
0
          di += std::to_string(device.get().timeIntervalUntilIgnoreExpired().millis());
260
0
          di += " more secs)";
261
8
        } else {
262
8
          di += "false";
263
8
        }
264
8
        // di += ", hasServices=";
265
8
        // di += (device.get().hasServicesSet() ? "true" : "false");
266
8
        di += ", hasReadPayload=";
267
8
        di += (device.get().payloadData().size() > 0 ? 
device.get().payloadData().hexEncodedString()2
:
"false"6
);
268
8
        HTDBG(di);
269
8
      }
270
5
    } else {
271
2
      // restart scanning when no connection activity is expected
272
2
      pp.restartScanningAndAdvertising();
273
2
    }
274
7
275
7
    return results;
276
7
  }
?requiredConnections@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@V?$allocator@V?$tuple@V?$DataRef@V?$MemoryArena@$0CAAA@$07@datatype@herald@@@datatype@herald@@EV?$optional@VTargetIdentifier@datatype@herald@@@std@@@std@@@2@@std@@XZ
Line
Count
Source
144
4
  std::vector<PrioritisedPrerequisite> requiredConnections() override {
145
4
    std::vector<std::tuple<FeatureTag,Priority,std::optional<TargetIdentifier>>> results;
146
4
147
4
    // This ensures we break from making connections to allow advertising and scanning
148
4
    iterationsSinceBreak++;
149
4
    if (iterationsSinceBreak >= breakEvery &&
150
4
      
iterationsSinceBreak < (breakEvery + breakFor)0
) {
151
0
      HTDBG("###### Skipping connections - giving advertising & scanning a chance");
152
0
      // if (iterationsSinceBreak == breakEvery) { // incase it fails
153
0
        pp.restartScanningAndAdvertising();
154
0
      // }
155
0
      return results;
156
4
    } else if (iterationsSinceBreak == (breakEvery + breakFor) ) {
157
0
      // reset
158
0
      iterationsSinceBreak = 0;
159
0
    }
160
4
161
4
    // Remove expired devices
162
4
    auto expired = db.matches([/*this*/] (const BLEDevice& device) -> bool {
163
4
      auto interval = device.timeIntervalSinceLastUpdate();
164
4
      bool notZero = interval != TimeInterval::zero();
165
4
      bool isOld = interval > TimeInterval::minutes(15);
166
4
      // HTDBG("ID, created, Now, interval, notZero, isOld:-");
167
4
      // HTDBG((std::string)device.identifier());
168
4
      // HTDBG(std::to_string((long)device.created()));
169
4
      // HTDBG(std::to_string((long)Date()));
170
4
      // HTDBG((std::string)interval);
171
4
      // HTDBG(notZero?"true":"false");
172
4
      // HTDBG(isOld?"true":"false");
173
4
      return notZero && isOld;
174
4
    });
175
4
    for (auto& exp : expired) {
176
0
      db.remove(exp.get().identifier());
177
0
      HTDBG("Removing expired device with ID: ");
178
0
      HTDBG((std::string)exp.get().identifier());
179
0
      HTDBG("time since last update:-");
180
0
      HTDBG(std::to_string(exp.get().timeIntervalSinceLastUpdate()));
181
0
    }
182
4
183
4
    // Allow updates from ignored (for a time) status, to retry status
184
4
    auto tempIgnoredOS = db.matches([](const BLEDevice& device) -> bool {
185
4
      return device.operatingSystem() == BLEDeviceOperatingSystem::ignore;
186
4
    });
187
4
    for (auto& device : tempIgnoredOS) {
188
0
      // don't bother with separate activity right now - no connection required
189
0
      device.get().operatingSystem(BLEDeviceOperatingSystem::unknown);
190
0
    }
191
4
192
4
193
4
    // Add all targets in database that are not known
194
4
    auto newConns = db.matches([this](const BLEDevice& device) -> bool {
195
4
      return !device.ignore() &&
196
4
        (
197
4
          !device.hasService(context.getSensorConfiguration().serviceUUID)
198
4
          ||
199
4
          device.payloadData().size() == 0 // Know the OS, but not the payload (ID)
200
4
          // ||
201
4
          // device.immediateSendData().has_value()
202
4
        )
203
4
        ;
204
4
    });
205
4
    for (auto& device : newConns) {
206
2
      results.emplace_back(herald::engine::Features::HeraldBluetoothProtocolConnection,
207
2
        herald::engine::Priorities::High,
208
2
        device.get().identifier()
209
2
      );
210
2
    }
211
4
212
4
    // TODO any other devices we may have outstanding work for that requires connections
213
4
214
4
    // DEBUG ONLY ELEMENTS
215
4
    if (newConns.size() > 0) {
216
2
      // print debug info about the BLE Database
217
2
      HTDBG("BLE DATABASE CURRENT CONTENTS:-");
218
2
      auto allDevices = db.matches([](const BLEDevice& device) -> bool {
219
2
        return true;
220
2
      });
221
2
      for (auto& device : allDevices) {
222
2
        std::string di(" - ");
223
2
        BLEMacAddress mac(device.get().identifier().underlyingData());
224
2
        di += (std::string)mac;
225
2
        // di += ", created=";
226
2
        // di += std::to_string(device.get().created());
227
2
        di += ", pseudoAddress=";
228
2
        auto pseudo = device.get().pseudoDeviceAddress();
229
2
        if (pseudo.has_value()) {
230
1
          di += (std::string)pseudo.value();
231
1
        } else {
232
1
          di += "unset";
233
1
        }
234
2
        di += ", os=";
235
2
        auto os = device.get().operatingSystem();
236
2
        // if (os.has_value()) {
237
2
          if (herald::ble::BLEDeviceOperatingSystem::ios == os) {
238
0
            di += "ios";
239
2
          } else if (herald::ble::BLEDeviceOperatingSystem::android == os) {
240
1
            di += "android";
241
1
          } else if (herald::ble::BLEDeviceOperatingSystem::unknown == os) {
242
1
            di += "unknown";
243
1
          } else 
if (0
herald::ble::BLEDeviceOperatingSystem::ignore == os0
) {
244
0
            di += "ignore";
245
0
          } else if (herald::ble::BLEDeviceOperatingSystem::android_tbc == os) {
246
0
            di += "android_tbc";
247
0
          } else if (herald::ble::BLEDeviceOperatingSystem::ios_tbc == os) {
248
0
            di += "ios_tbc";
249
0
          } else if (herald::ble::BLEDeviceOperatingSystem::shared == os) {
250
0
            di += "shared";
251
0
          }
252
2
        // } else {
253
2
        //   di += "unknown/unset";
254
2
        // }
255
2
        di += ", ignore=";
256
2
        auto ignore = device.get().ignore();
257
2
        if (ignore) {
258
0
          di += "true (for ";
259
0
          di += std::to_string(device.get().timeIntervalUntilIgnoreExpired().millis());
260
0
          di += " more secs)";
261
2
        } else {
262
2
          di += "false";
263
2
        }
264
2
        // di += ", hasServices=";
265
2
        // di += (device.get().hasServicesSet() ? "true" : "false");
266
2
        di += ", hasReadPayload=";
267
2
        di += (device.get().payloadData().size() > 0 ? 
device.get().payloadData().hexEncodedString()0
: "false");
268
2
        HTDBG(di);
269
2
      }
270
2
    } else {
271
2
      // restart scanning when no connection activity is expected
272
2
      pp.restartScanningAndAdvertising();
273
2
    }
274
4
275
4
    return results;
276
4
  }
277
278
11
  std::vector<Activity> requiredActivities() override {
279
11
    std::vector<Activity> results;
280
11
281
11
    // General activities first - no connections required
282
11
    // taskRemoveExpiredDevices
283
13
    auto expiredDevices = db.matches([this](const BLEDevice& device) -> bool {
284
13
      return device.timeIntervalSinceLastUpdate() > context.getSensorConfiguration().peripheralCleanInterval;
285
13
    });
??R<lambda_1>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
283
9
    auto expiredDevices = db.matches([this](const BLEDevice& device) -> bool {
284
9
      return device.timeIntervalSinceLastUpdate() > context.getSensorConfiguration().peripheralCleanInterval;
285
9
    });
??R<lambda_1>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
283
4
    auto expiredDevices = db.matches([this](const BLEDevice& device) -> bool {
284
4
      return device.timeIntervalSinceLastUpdate() > context.getSensorConfiguration().peripheralCleanInterval;
285
4
    });
286
11
    std::size_t dbSizeBefore = db.size();
287
11
    for (auto& device : expiredDevices) {
288
0
      // remove now so we don't get tasks later for expired devices
289
0
      HTDBG("taskRemoveExpiredDevices (remove={})", (std::string)device.get().identifier());
290
0
      db.remove(device.get().identifier());
291
0
    }
292
11
    std::size_t dbSizeAfter = db.size();
293
11
    if (dbSizeAfter < dbSizeBefore) {
294
0
      HTDBG("  db size has reduced");
295
0
    }
296
11
297
11
298
11
    // State 0 - New device -> Read full advert data to see if DCT/Herald -> State Z, 1 or State 3
299
11
    // State 1 - Discover services for DCT/Herald on this device -> State Z, or 2
300
11
    // State 2 - New Herald BLE device -> Read payload -> State 3
301
11
    // State 3 - Steady state - do nothing
302
11
    // State 4 - Has immediateSend data -> Send immediate -> State 3
303
11
    // TODO check for nearby payloads
304
11
    // State 3 - Not seen in a while -> State X
305
11
    // State X - Out of range. No actions.
306
11
    // State Z - Ignore (not a relevant device for Herald... right now). Ignore for a period of time. No actions.
307
11
308
11
    // TODO is IOS and needs payload sharing
309
11
310
11
    
311
11
    // auto state0Devices = db.matches([](BLEDevice device) -> bool {
312
11
    //   return !device.ignore() && !device.pseudoDeviceAddress().has_value();
313
11
    // });
314
13
    auto state1Devices = db.matches([this](const BLEDevice& device) -> bool {
315
13
      return !device.ignore() && 
316
13
            // !device.receiveOnly() &&
317
13
            !device.hasService(context.getSensorConfiguration().serviceUUID);
318
13
    });
??R<lambda_2>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
314
9
    auto state1Devices = db.matches([this](const BLEDevice& device) -> bool {
315
9
      return !device.ignore() && 
316
9
            // !device.receiveOnly() &&
317
9
            !device.hasService(context.getSensorConfiguration().serviceUUID);
318
9
    });
??R<lambda_2>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
314
4
    auto state1Devices = db.matches([this](const BLEDevice& device) -> bool {
315
4
      return !device.ignore() && 
316
4
            // !device.receiveOnly() &&
317
4
            !device.hasService(context.getSensorConfiguration().serviceUUID);
318
4
    });
319
13
    auto state2Devices = db.matches([this](const BLEDevice& device) -> bool {
320
13
      return !device.ignore() && 
321
13
            // !device.receiveOnly() &&
322
13
              device.hasService(context.getSensorConfiguration().serviceUUID) &&
323
13
              
device.payloadData().size() == 011
; // TODO check for Herald transferred payload data (not legacy)
324
13
    });
??R<lambda_3>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
319
9
    auto state2Devices = db.matches([this](const BLEDevice& device) -> bool {
320
9
      return !device.ignore() && 
321
9
            // !device.receiveOnly() &&
322
9
              device.hasService(context.getSensorConfiguration().serviceUUID) &&
323
9
              
device.payloadData().size() == 08
; // TODO check for Herald transferred payload data (not legacy)
324
9
    });
??R<lambda_3>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@AEBVBLEDevice@34@@Z
Line
Count
Source
319
4
    auto state2Devices = db.matches([this](const BLEDevice& device) -> bool {
320
4
      return !device.ignore() && 
321
4
            // !device.receiveOnly() &&
322
4
              device.hasService(context.getSensorConfiguration().serviceUUID) &&
323
4
              
device.payloadData().size() == 03
; // TODO check for Herald transferred payload data (not legacy)
324
4
    });
325
11
    // auto state4Devices = db.matches([this](const BLEDevice& device) -> bool {
326
11
    //   return !device.ignore() && 
327
11
    //         // !device.receiveOnly() &&
328
11
    //           device.hasService(context.getSensorConfiguration().serviceUUID) 
329
11
    //           // && device.immediateSendData().has_value()
330
11
    //           ;
331
11
    // });
332
11
    // TODO State X (timed out / out of range) devices filter check -> Then remove from BLEDatabase
333
11
    
334
11
    // NOTE State 0 is handled by the Herald BLE scan function, and so has no specific activity
335
11
336
11
    // State 1 - discovery Herald service
337
11
    for (auto& device : state1Devices) {
338
2
      results.emplace_back(Activity{
339
2
        .priority = Priorities::High + 10,
340
2
        .name = "herald-service-discovery",
341
2
        .prerequisites = std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
342
2
          1,
343
2
          std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
344
2
            herald::engine::Features::HeraldBluetoothProtocolConnection,
345
2
            device.get().identifier()
346
2
          }
347
2
        },
348
2
        // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
349
2
        //   // fill this out
350
2
        //   pp->serviceDiscovery(activity,callback);
351
2
        // }
352
2
        .executor = [this](const Activity activity) -> std::optional<Activity> {
353
1
          // fill this out
354
1
          pp.serviceDiscovery(activity);
355
1
          return {};
356
1
        }
Unexecuted instantiation: ??R<lambda_4>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@UActivity@engine@4@@Z
??R<lambda_4>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@UActivity@engine@4@@Z
Line
Count
Source
352
1
        .executor = [this](const Activity activity) -> std::optional<Activity> {
353
1
          // fill this out
354
1
          pp.serviceDiscovery(activity);
355
1
          return {};
356
1
        }
357
2
      });
358
2
    }
359
11
360
11
    // State 2 - read herald payload(s)
361
11
    for (auto& device : state2Devices) {
362
6
      results.emplace_back(Activity{
363
6
        .priority = Priorities::High + 9,
364
6
        .name = "herald-read-payload",
365
6
        .prerequisites =  std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
366
6
          1,
367
6
          std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
368
6
            herald::engine::Features::HeraldBluetoothProtocolConnection,
369
6
            device.get().identifier()
370
6
          }
371
6
        },
372
6
        // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
373
6
        //   // fill this out
374
6
        //   pp->readPayload(activity,callback);
375
6
        // }
376
6
        .executor = [this](const Activity activity) -> std::optional<Activity> {
377
1
          // fill this out
378
1
        pp.readPayload(activity);
379
1
        return {};
380
1
        }
Unexecuted instantiation: ??R<lambda_5>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@UActivity@engine@4@@Z
??R<lambda_5>@?0??requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ@QEBA@UActivity@engine@4@@Z
Line
Count
Source
376
1
        .executor = [this](const Activity activity) -> std::optional<Activity> {
377
1
          // fill this out
378
1
        pp.readPayload(activity);
379
1
        return {};
380
1
        }
381
6
      });
382
6
    }
383
11
    // TODO add check for sensor config payload timeout in above IF
384
11
    // TODO add BLESensorConfiguration.deviceIntrospectionEnabled && device.supportsModelCharacteristic() && device.model() == null
385
11
    // TODO add BLESensorConfiguration.deviceIntrospectionEnabled && device.supportsDeviceNameCharacteristic() && device.deviceName() == null
386
11
    
387
11
    // State 4 - Has data for immediate send
388
11
    // for (auto& device : state4Devices) {
389
11
    //   results.emplace_back(Activity{
390
11
    //     .priority = Priorities::Default + 10,
391
11
    //     .name = "herald-immediate-send-targeted",
392
11
    //     .prerequisites =  std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
393
11
    //       1,
394
11
    //       std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
395
11
    //         herald::engine::Features::HeraldBluetoothProtocolConnection,
396
11
    //         device.get().identifier()
397
11
    //       }
398
11
    //     },
399
11
    //     // For std::async based platforms:-
400
11
    //     // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
401
11
    //     //   // fill this out
402
11
    //     //   pp->immediateSend(activity,callback);
403
11
    //     // }
404
11
    //     .executor = [this](const Activity activity) -> std::optional<Activity> {
405
11
    //       // fill this out
406
11
    //       pp.immediateSend(activity);
407
11
    //       return {};
408
11
    //     }
409
11
    //   });
410
11
    //   // TODO add immediate send all support
411
11
    //   // TODO add read of nearby payload data from remotes
412
11
    // }
413
11
    return results;
414
11
  }
?requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$NoOpHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ
Line
Count
Source
278
7
  std::vector<Activity> requiredActivities() override {
279
7
    std::vector<Activity> results;
280
7
281
7
    // General activities first - no connections required
282
7
    // taskRemoveExpiredDevices
283
7
    auto expiredDevices = db.matches([this](const BLEDevice& device) -> bool {
284
7
      return device.timeIntervalSinceLastUpdate() > context.getSensorConfiguration().peripheralCleanInterval;
285
7
    });
286
7
    std::size_t dbSizeBefore = db.size();
287
7
    for (auto& device : expiredDevices) {
288
0
      // remove now so we don't get tasks later for expired devices
289
0
      HTDBG("taskRemoveExpiredDevices (remove={})", (std::string)device.get().identifier());
290
0
      db.remove(device.get().identifier());
291
0
    }
292
7
    std::size_t dbSizeAfter = db.size();
293
7
    if (dbSizeAfter < dbSizeBefore) {
294
0
      HTDBG("  db size has reduced");
295
0
    }
296
7
297
7
298
7
    // State 0 - New device -> Read full advert data to see if DCT/Herald -> State Z, 1 or State 3
299
7
    // State 1 - Discover services for DCT/Herald on this device -> State Z, or 2
300
7
    // State 2 - New Herald BLE device -> Read payload -> State 3
301
7
    // State 3 - Steady state - do nothing
302
7
    // State 4 - Has immediateSend data -> Send immediate -> State 3
303
7
    // TODO check for nearby payloads
304
7
    // State 3 - Not seen in a while -> State X
305
7
    // State X - Out of range. No actions.
306
7
    // State Z - Ignore (not a relevant device for Herald... right now). Ignore for a period of time. No actions.
307
7
308
7
    // TODO is IOS and needs payload sharing
309
7
310
7
    
311
7
    // auto state0Devices = db.matches([](BLEDevice device) -> bool {
312
7
    //   return !device.ignore() && !device.pseudoDeviceAddress().has_value();
313
7
    // });
314
7
    auto state1Devices = db.matches([this](const BLEDevice& device) -> bool {
315
7
      return !device.ignore() && 
316
7
            // !device.receiveOnly() &&
317
7
            !device.hasService(context.getSensorConfiguration().serviceUUID);
318
7
    });
319
7
    auto state2Devices = db.matches([this](const BLEDevice& device) -> bool {
320
7
      return !device.ignore() && 
321
7
            // !device.receiveOnly() &&
322
7
              device.hasService(context.getSensorConfiguration().serviceUUID) &&
323
7
              device.payloadData().size() == 0; // TODO check for Herald transferred payload data (not legacy)
324
7
    });
325
7
    // auto state4Devices = db.matches([this](const BLEDevice& device) -> bool {
326
7
    //   return !device.ignore() && 
327
7
    //         // !device.receiveOnly() &&
328
7
    //           device.hasService(context.getSensorConfiguration().serviceUUID) 
329
7
    //           // && device.immediateSendData().has_value()
330
7
    //           ;
331
7
    // });
332
7
    // TODO State X (timed out / out of range) devices filter check -> Then remove from BLEDatabase
333
7
    
334
7
    // NOTE State 0 is handled by the Herald BLE scan function, and so has no specific activity
335
7
336
7
    // State 1 - discovery Herald service
337
7
    for (auto& device : state1Devices) {
338
1
      results.emplace_back(Activity{
339
1
        .priority = Priorities::High + 10,
340
1
        .name = "herald-service-discovery",
341
1
        .prerequisites = std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
342
1
          1,
343
1
          std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
344
1
            herald::engine::Features::HeraldBluetoothProtocolConnection,
345
1
            device.get().identifier()
346
1
          }
347
1
        },
348
1
        // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
349
1
        //   // fill this out
350
1
        //   pp->serviceDiscovery(activity,callback);
351
1
        // }
352
1
        .executor = [this](const Activity activity) -> std::optional<Activity> {
353
1
          // fill this out
354
1
          pp.serviceDiscovery(activity);
355
1
          return {};
356
1
        }
357
1
      });
358
1
    }
359
7
360
7
    // State 2 - read herald payload(s)
361
7
    for (auto& device : state2Devices) {
362
5
      results.emplace_back(Activity{
363
5
        .priority = Priorities::High + 9,
364
5
        .name = "herald-read-payload",
365
5
        .prerequisites =  std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
366
5
          1,
367
5
          std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
368
5
            herald::engine::Features::HeraldBluetoothProtocolConnection,
369
5
            device.get().identifier()
370
5
          }
371
5
        },
372
5
        // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
373
5
        //   // fill this out
374
5
        //   pp->readPayload(activity,callback);
375
5
        // }
376
5
        .executor = [this](const Activity activity) -> std::optional<Activity> {
377
5
          // fill this out
378
5
        pp.readPayload(activity);
379
5
        return {};
380
5
        }
381
5
      });
382
5
    }
383
7
    // TODO add check for sensor config payload timeout in above IF
384
7
    // TODO add BLESensorConfiguration.deviceIntrospectionEnabled && device.supportsModelCharacteristic() && device.model() == null
385
7
    // TODO add BLESensorConfiguration.deviceIntrospectionEnabled && device.supportsDeviceNameCharacteristic() && device.deviceName() == null
386
7
    
387
7
    // State 4 - Has data for immediate send
388
7
    // for (auto& device : state4Devices) {
389
7
    //   results.emplace_back(Activity{
390
7
    //     .priority = Priorities::Default + 10,
391
7
    //     .name = "herald-immediate-send-targeted",
392
7
    //     .prerequisites =  std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
393
7
    //       1,
394
7
    //       std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
395
7
    //         herald::engine::Features::HeraldBluetoothProtocolConnection,
396
7
    //         device.get().identifier()
397
7
    //       }
398
7
    //     },
399
7
    //     // For std::async based platforms:-
400
7
    //     // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
401
7
    //     //   // fill this out
402
7
    //     //   pp->immediateSend(activity,callback);
403
7
    //     // }
404
7
    //     .executor = [this](const Activity activity) -> std::optional<Activity> {
405
7
    //       // fill this out
406
7
    //       pp.immediateSend(activity);
407
7
    //       return {};
408
7
    //     }
409
7
    //   });
410
7
    //   // TODO add immediate send all support
411
7
    //   // TODO add read of nearby payload data from remotes
412
7
    // }
413
7
    return results;
414
7
  }
?requiredActivities@?$HeraldProtocolBLECoordinationProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@V?$MockHeraldV1ProtocolProvider@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@V?$ConcreteBLEDatabase@U?$Context@UDefaultPlatformType@herald@@UDummyLoggingSink@@VDummyBluetoothStateManager@@@herald@@$09@ble@2@@@@ble@herald@@UEAA?AV?$vector@UActivity@engine@herald@@V?$allocator@UActivity@engine@herald@@@std@@@std@@XZ
Line
Count
Source
278
4
  std::vector<Activity> requiredActivities() override {
279
4
    std::vector<Activity> results;
280
4
281
4
    // General activities first - no connections required
282
4
    // taskRemoveExpiredDevices
283
4
    auto expiredDevices = db.matches([this](const BLEDevice& device) -> bool {
284
4
      return device.timeIntervalSinceLastUpdate() > context.getSensorConfiguration().peripheralCleanInterval;
285
4
    });
286
4
    std::size_t dbSizeBefore = db.size();
287
4
    for (auto& device : expiredDevices) {
288
0
      // remove now so we don't get tasks later for expired devices
289
0
      HTDBG("taskRemoveExpiredDevices (remove={})", (std::string)device.get().identifier());
290
0
      db.remove(device.get().identifier());
291
0
    }
292
4
    std::size_t dbSizeAfter = db.size();
293
4
    if (dbSizeAfter < dbSizeBefore) {
294
0
      HTDBG("  db size has reduced");
295
0
    }
296
4
297
4
298
4
    // State 0 - New device -> Read full advert data to see if DCT/Herald -> State Z, 1 or State 3
299
4
    // State 1 - Discover services for DCT/Herald on this device -> State Z, or 2
300
4
    // State 2 - New Herald BLE device -> Read payload -> State 3
301
4
    // State 3 - Steady state - do nothing
302
4
    // State 4 - Has immediateSend data -> Send immediate -> State 3
303
4
    // TODO check for nearby payloads
304
4
    // State 3 - Not seen in a while -> State X
305
4
    // State X - Out of range. No actions.
306
4
    // State Z - Ignore (not a relevant device for Herald... right now). Ignore for a period of time. No actions.
307
4
308
4
    // TODO is IOS and needs payload sharing
309
4
310
4
    
311
4
    // auto state0Devices = db.matches([](BLEDevice device) -> bool {
312
4
    //   return !device.ignore() && !device.pseudoDeviceAddress().has_value();
313
4
    // });
314
4
    auto state1Devices = db.matches([this](const BLEDevice& device) -> bool {
315
4
      return !device.ignore() && 
316
4
            // !device.receiveOnly() &&
317
4
            !device.hasService(context.getSensorConfiguration().serviceUUID);
318
4
    });
319
4
    auto state2Devices = db.matches([this](const BLEDevice& device) -> bool {
320
4
      return !device.ignore() && 
321
4
            // !device.receiveOnly() &&
322
4
              device.hasService(context.getSensorConfiguration().serviceUUID) &&
323
4
              device.payloadData().size() == 0; // TODO check for Herald transferred payload data (not legacy)
324
4
    });
325
4
    // auto state4Devices = db.matches([this](const BLEDevice& device) -> bool {
326
4
    //   return !device.ignore() && 
327
4
    //         // !device.receiveOnly() &&
328
4
    //           device.hasService(context.getSensorConfiguration().serviceUUID) 
329
4
    //           // && device.immediateSendData().has_value()
330
4
    //           ;
331
4
    // });
332
4
    // TODO State X (timed out / out of range) devices filter check -> Then remove from BLEDatabase
333
4
    
334
4
    // NOTE State 0 is handled by the Herald BLE scan function, and so has no specific activity
335
4
336
4
    // State 1 - discovery Herald service
337
4
    for (auto& device : state1Devices) {
338
1
      results.emplace_back(Activity{
339
1
        .priority = Priorities::High + 10,
340
1
        .name = "herald-service-discovery",
341
1
        .prerequisites = std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
342
1
          1,
343
1
          std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
344
1
            herald::engine::Features::HeraldBluetoothProtocolConnection,
345
1
            device.get().identifier()
346
1
          }
347
1
        },
348
1
        // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
349
1
        //   // fill this out
350
1
        //   pp->serviceDiscovery(activity,callback);
351
1
        // }
352
1
        .executor = [this](const Activity activity) -> std::optional<Activity> {
353
1
          // fill this out
354
1
          pp.serviceDiscovery(activity);
355
1
          return {};
356
1
        }
357
1
      });
358
1
    }
359
4
360
4
    // State 2 - read herald payload(s)
361
4
    for (auto& device : state2Devices) {
362
1
      results.emplace_back(Activity{
363
1
        .priority = Priorities::High + 9,
364
1
        .name = "herald-read-payload",
365
1
        .prerequisites =  std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
366
1
          1,
367
1
          std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
368
1
            herald::engine::Features::HeraldBluetoothProtocolConnection,
369
1
            device.get().identifier()
370
1
          }
371
1
        },
372
1
        // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
373
1
        //   // fill this out
374
1
        //   pp->readPayload(activity,callback);
375
1
        // }
376
1
        .executor = [this](const Activity activity) -> std::optional<Activity> {
377
1
          // fill this out
378
1
        pp.readPayload(activity);
379
1
        return {};
380
1
        }
381
1
      });
382
1
    }
383
4
    // TODO add check for sensor config payload timeout in above IF
384
4
    // TODO add BLESensorConfiguration.deviceIntrospectionEnabled && device.supportsModelCharacteristic() && device.model() == null
385
4
    // TODO add BLESensorConfiguration.deviceIntrospectionEnabled && device.supportsDeviceNameCharacteristic() && device.deviceName() == null
386
4
    
387
4
    // State 4 - Has data for immediate send
388
4
    // for (auto& device : state4Devices) {
389
4
    //   results.emplace_back(Activity{
390
4
    //     .priority = Priorities::Default + 10,
391
4
    //     .name = "herald-immediate-send-targeted",
392
4
    //     .prerequisites =  std::vector<std::tuple<FeatureTag,std::optional<TargetIdentifier>>>{
393
4
    //       1,
394
4
    //       std::tuple<FeatureTag,std::optional<TargetIdentifier>>{
395
4
    //         herald::engine::Features::HeraldBluetoothProtocolConnection,
396
4
    //         device.get().identifier()
397
4
    //       }
398
4
    //     },
399
4
    //     // For std::async based platforms:-
400
4
    //     // .executor = [this](const Activity activity, CompletionCallback callback) -> void {
401
4
    //     //   // fill this out
402
4
    //     //   pp->immediateSend(activity,callback);
403
4
    //     // }
404
4
    //     .executor = [this](const Activity activity) -> std::optional<Activity> {
405
4
    //       // fill this out
406
4
    //       pp.immediateSend(activity);
407
4
    //       return {};
408
4
    //     }
409
4
    //   });
410
4
    //   // TODO add immediate send all support
411
4
    //   // TODO add read of nearby payload data from remotes
412
4
    // }
413
4
    return results;
414
4
  }
415
416
private:
417
  ContextT& context; 
418
  BLEDBT& db;
419
  ProviderT& pp;
420
421
  std::vector<PrioritisedPrerequisite> previouslyProvisioned;
422
423
  int iterationsSinceBreak;
424
  int breakEvery;
425
  int breakFor;
426
427
  HLOGGER(ContextT);
428
};
429
430
}
431
}
432
433
#endif