herald  2.0.0
ble_concrete.h
1 // Copyright 2020-2021 Herald Project Contributors
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 
5 #ifndef HERALD_BLE_CONCRETE_H
6 #define HERALD_BLE_CONCRETE_H
7 
8 #include "ble_concrete_database.h"
9 #include "ble_database.h"
10 #include "ble_receiver.h"
11 #include "ble_sensor.h"
12 #include "ble_transmitter.h"
13 #include "ble_concrete.h"
14 #include "ble_protocols.h"
15 #include "bluetooth_state_manager.h"
16 #include "ble_device_delegate.h"
17 #include "filter/ble_advert_parser.h"
18 #include "../payload/payload_data_supplier.h"
19 #include "../context.h"
20 #include "../data/sensor_logger.h"
21 #include "ble_sensor_configuration.h"
22 #include "ble_coordinator.h"
23 #include "../datatype/bluetooth_state.h"
24 
25 // Include the relevant concrete BLE Receiver here
26 #ifdef __ZEPHYR__
27 #ifdef CONFIG_BT_SCAN
28 #include "zephyr/concrete_ble_receiver.h"
29 #else
30 #include "default/concrete_ble_receiver.h"
31 #endif
32 #include "zephyr/concrete_ble_transmitter.h"
33 // TODO other platforms here
34 #else
35 #include "default/concrete_ble_receiver.h"
36 #include "default/concrete_ble_transmitter.h"
37 #endif
38 
39 #include <memory>
40 #include <algorithm>
41 #include <optional>
42 
43 namespace herald {
44 namespace ble {
45 
46 using namespace herald::datatype;
47 using namespace herald::ble::filter;
48 using namespace herald::payload;
49 
50 // NOTE THIS HEADER IS FOR ALL PLATFORMS.
51 // SPECIFIC PLATFORM DEFINITIONS ARE WITHIN SEVERAL C++ FILES
52 // UNDER WINDOWS AND ZEPHYR SUB DIRECTORIES
53 
54 
58 template <typename ContextT, typename PayloadDataSupplierT, typename SensorDelegateSetT, std::size_t DBSize = 10>
61 public:
62  ConcreteBLESensor(ContextT& ctx, BluetoothStateManager& bluetoothStateManager,
63  PayloadDataSupplierT& payloadDataSupplier, SensorDelegateSetT& dels)
64  : m_context(ctx),
65  database(ctx),
66  stateManager(bluetoothStateManager),
67  transmitter(ctx, bluetoothStateManager, payloadDataSupplier, database, dels),
68  receiver(ctx, bluetoothStateManager, payloadDataSupplier, database, dels),
69  delegates(dels),
70  coordinator(ctx, database, receiver),
71  addedSelfAsDelegate(false)
72  HLOGGERINIT(ctx,"sensor","ConcreteBLESensor")
73  {
74  }
75 
76  // Delete for GCC 8/9. See https://stackoverflow.com/questions/63812165/stdvariant-requires-default-constructor-in-gcc-8-and-9-and-not-require-in-gcc
77  ConcreteBLESensor() = delete;
78  ConcreteBLESensor(const ConcreteBLESensor& from) = delete;
79  ConcreteBLESensor(ConcreteBLESensor&& from) = delete;
80  ~ConcreteBLESensor() = default;
81 
82  // Coordination overrides - Since v1.2-beta3
83  std::optional<std::reference_wrapper<CoordinationProvider>> coordinationProvider() {
84  // Only return this if we support scanning
85  if (m_context.getSensorConfiguration().scanningEnabled) {
86  HTDBG("Providing a BLECoordinationProvider");
87  //return std::optional<std::reference_wrapper<CoordinationProvider>>(std::static_cast<CoordinationProvider>(coordinator));
88  return coordinator;
89  }
90  HTDBG("Scanning not supported - so not returning a BLECoordinationProvider");
91  return {};
92  }
93 
94  bool immediateSend(Data data, const TargetIdentifier& targetIdentifier) {
95  return receiver.immediateSend(data,targetIdentifier);
96  }
97 
98  bool immediateSendAll(Data data) {
99  return receiver.immediateSendAll(data);
100  }
101 
102  // Sensor overrides
103  void start() {
104  if (!addedSelfAsDelegate) {
105  stateManager.add(*this); // FAILS IF USED IN THE CTOR - DO NOT DO THIS FROM CTOR
106  database.add(*this);
107  addedSelfAsDelegate = true;
108  }
109  transmitter.start();
110  receiver.start();
111  // for (auto& delegate : delegates) {
112  delegates.sensor(SensorType::BLE, SensorState::on);
113  // }
114  }
115 
116  void stop() {
117  transmitter.stop();
118  receiver.stop();
119  // for (auto& delegate : delegates) {
120  delegates.sensor(SensorType::BLE, SensorState::off);
121  // }
122  }
123 
124  // Database overrides
125  void bleDatabaseDidCreate(const BLEDevice& device) override {
126  // for (auto& delegate : delegates) {
127  delegates.sensor(SensorType::BLE, device.identifier()); // didDetect
128  // }
129  }
130 
131  void bleDatabaseDidUpdate(const BLEDevice& device, const BLEDeviceAttribute attribute) override {
132  switch (attribute) {
133  case BLEDeviceAttribute::rssi: {
134  auto rssi = device.rssi();
135  if (rssi.intValue() != 0) {
136  double rssiValue = (double)rssi.intValue();
137  auto prox = Proximity{.unit=ProximityMeasurementUnit::RSSI, .value=rssiValue};
138  // for (auto& delegate: delegates) {
139  delegates.sensor(SensorType::BLE,
140  prox,
141  device.identifier()
142  ); // didMeasure
143  // }
144  // also payload with rssi
145  auto payload = device.payloadData();
146  if (payload.size() > 0) {
147  // for (auto& delegate: delegates) {
148  delegates.sensor(SensorType::BLE,
149  prox,
150  device.identifier(),
151  payload
152  ); // didMeasure withPayload
153  // }
154  }
155  }
156  break;
157  }
158  case BLEDeviceAttribute::payloadData: {
159  auto payload = device.payloadData();
160  if (payload.size() > 0) {
161  // for (auto& delegate: delegates) {
162  delegates.sensor(SensorType::BLE,
163  payload,
164  device.identifier()
165  ); // didReadPayload
166  // }
167  // also payload with rssi
168  auto rssi = device.rssi();
169  if (rssi.intValue() != 0) {
170  double rssiValue = (double)rssi.intValue();
171  auto prox = Proximity{.unit=ProximityMeasurementUnit::RSSI, .value=rssiValue};
172  // for (auto& delegate: delegates) {
173  delegates.sensor(SensorType::BLE,
174  prox,
175  device.identifier(),
176  payload
177  ); // didMeasure withPayload
178  // }
179  }
180  }
181  break;
182  }
183  default: {
184  ; // do nothing
185  }
186  }
187  }
188 
189  void bleDatabaseDidDelete(const BLEDevice& device) override {
190  ; // TODO just log this // TODO determine if to pass this on too
191  // TODO fire this for analysis runner and others' benefit
192  }
193 
194  // Bluetooth state manager delegate overrides
195  void bluetoothStateManager(BluetoothState didUpdateState) override {
196  if (BluetoothState::poweredOff == didUpdateState) {
197  // stop();
198  }
199  if (BluetoothState::poweredOn == didUpdateState) {
200  // start();
201  }
202  if (BluetoothState::unsupported == didUpdateState) {
203  // for (auto& delegate : delegates) {
204  delegates.sensor(SensorType::BLE, SensorState::unavailable);
205  // }
206  }
207  }
208 
209 private:
210 
211  // Internal API private methods here too
212 
213  // Data members hidden by PIMPL
214 
215  ContextT& m_context;
217  BluetoothStateManager& stateManager;
220 
221  SensorDelegateSetT& delegates;
222 
224  ContextT,
227  > coordinator;
228 
229  bool addedSelfAsDelegate;
230 
231  HLOGGER(ContextT);
232 };
233 
234 } // end namespace
235 } // end namespace
236 
237 #endif
Definition: ble_database_delegate.h:15
Definition: ble_device.h:181
Definition: bluetooth_state_manager_delegate.h:16
Definition: bluetooth_state_manager.h:19
Definition: ble_concrete_database.h:46
Dummy implementation of a ConcreteBLEReceiver that does nothing (used for testing)
Definition: concrete_ble_receiver.h:24
Definition: ble_concrete.h:60
Dummy implementation of a ConcreteBLETransmitter that does nothing (used for testing)
Definition: concrete_ble_transmitter.h:39
The main data workhorse class of the Herald API.
Definition: data.h:33
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
Definition: proximity.h:17