Coverage Report

Created: 2021-08-28 18:14

D:\git\skunkworks\herald-for-cpp\herald\src\ble\ble_device.cpp
Line
Count
Source (jump to first uncovered line)
1
//  Copyright 2020-2021 Herald Project Contributors
2
//  SPDX-License-Identifier: Apache-2.0
3
//
4
5
#include "herald/ble/ble_device.h"
6
#include "herald/ble/ble_device_delegate.h"
7
#include "herald/ble/ble_tx_power.h"
8
#include "herald/ble/ble_mac_address.h"
9
#include "herald/ble/filter/ble_advert_parser.h"
10
11
#include "herald/datatype/date.h"
12
#include "herald/datatype/time_interval.h"
13
#include "herald/datatype/target_identifier.h"
14
15
#include <optional>
16
17
namespace herald {
18
namespace ble {
19
20
using namespace herald::datatype;
21
using namespace herald::ble::filter;
22
23
BLEDeviceFlags::BLEDeviceFlags() : bitFields(0) /* empty */
24
120
{
25
120
  reset();
26
120
}
27
28
void
29
BLEDeviceFlags::reset()
30
120
{
31
120
  bitFields.reset();
32
120
33
120
  bitFields.set(0);
34
120
  bitFields.set(1);
35
120
  bitFields.set(2);
36
120
37
120
  bitFields.set(3);
38
120
  bitFields.set(4);
39
120
40
120
  bitFields.set(6);
41
120
42
120
  bitFields.set(9);
43
120
  bitFields.set(10);
44
120
  bitFields.set(11);
45
120
}
46
47
BLEInternalState
48
BLEDeviceFlags::internalState() const
49
93
{
50
93
  if (bitFields.test(0)) {
51
70
    if (bitFields.test(1)) {
52
36
      if (bitFields.test(2)) {
53
35
        return BLEInternalState::discovered;
54
35
      } else {
55
1
        return BLEInternalState::filtered;
56
1
      }
57
34
    } else {
58
34
      if (bitFields.test(2)) {
59
0
        return BLEInternalState::has_potential;
60
34
      } else {
61
34
        return BLEInternalState::relevant;
62
34
      }
63
23
    }
64
23
  } else {
65
23
    if (bitFields.test(1)) {
66
23
      if (bitFields.test(2)) {
67
23
        return BLEInternalState::identified;
68
23
      } else {
69
0
        return BLEInternalState::timed_out;
70
0
      }
71
0
    }
72
23
    // remaining values reserved
73
23
  }
74
0
  return BLEInternalState::discovered;
75
0
}
76
77
void
78
BLEDeviceFlags::internalState(const BLEInternalState newState)
79
38
{
80
38
  switch (newState)
81
38
  {
82
16
  case BLEInternalState::discovered:
83
16
    bitFields.set(0,true);
84
16
    bitFields.set(1,true);
85
16
    bitFields.set(2,true);
86
16
    break;
87
1
  case BLEInternalState::filtered:
88
1
    bitFields.set(0,true);
89
1
    bitFields.set(1,true);
90
1
    bitFields.set(2,false);
91
1
    break;
92
0
  case BLEInternalState::has_potential:
93
0
    bitFields.set(0,true);
94
0
    bitFields.set(1,false);
95
0
    bitFields.set(2,true);
96
0
    break;
97
13
  case BLEInternalState::relevant:
98
13
    bitFields.set(0,true);
99
13
    bitFields.set(1,false);
100
13
    bitFields.set(2,false);
101
13
    break;
102
8
  case BLEInternalState::identified:
103
8
    bitFields.set(0,false);
104
8
    bitFields.set(1,true);
105
8
    bitFields.set(2,true);
106
8
    break;
107
0
  case BLEInternalState::timed_out:
108
0
    bitFields.set(0,false);
109
0
    bitFields.set(1,true);
110
0
    bitFields.set(2,false);
111
0
    break;
112
38
  }
113
38
}
114
115
BLEDeviceState
116
BLEDeviceFlags::state() const
117
1.43k
{
118
1.43k
  if (bitFields.test(3)) {
119
1.24k
    if (bitFields.test(4)) {
120
1.24k
      return BLEDeviceState::uninitialised;
121
1.24k
    } else {
122
0
      return BLEDeviceState::connecting;
123
0
    }
124
191
  } else {
125
191
    if (bitFields.test(4)) {
126
0
      return BLEDeviceState::connected;
127
191
    } else {
128
191
      return BLEDeviceState::disconnected;
129
191
    }
130
191
  }
131
1.43k
}
132
133
void
134
BLEDeviceFlags::state(const BLEDeviceState newState)
135
20
{
136
20
  switch (newState)
137
20
  {
138
3
  case BLEDeviceState::uninitialised:
139
3
    bitFields.set(3,true);
140
3
    bitFields.set(4,true);
141
3
    break;
142
0
  case BLEDeviceState::connecting:
143
0
    bitFields.set(3,true);
144
0
    bitFields.set(4,false);
145
0
    break;
146
0
  case BLEDeviceState::connected:
147
0
    bitFields.set(3,false);
148
0
    bitFields.set(4,true);
149
0
    break;
150
17
  case BLEDeviceState::disconnected:
151
17
    bitFields.set(3,false);
152
17
    bitFields.set(4,false);
153
17
    break;
154
20
  }
155
20
}
156
157
158
BLEDeviceOperatingSystem
159
BLEDeviceFlags::operatingSystem() const
160
34
{
161
34
  if (bitFields.test(0) && 
bitFields.test(1)27
&&
!bitFields.test(2)7
) {
162
0
    return BLEDeviceOperatingSystem::ignore;
163
0
  }
164
34
  if (bitFields.test(5)) {
165
16
    if (bitFields.test(6)) {
166
12
      if (bitFields.test(7)) {
167
0
        return BLEDeviceOperatingSystem::android_tbc;
168
12
      } else {
169
12
        return BLEDeviceOperatingSystem::android;
170
12
      }
171
4
    } else {
172
4
      if (bitFields.test(7)) {
173
0
        return BLEDeviceOperatingSystem::ios_tbc;
174
4
      } else {
175
4
        return BLEDeviceOperatingSystem::ios;
176
4
      }
177
18
    }
178
18
  } else {
179
18
    if (bitFields.test(6)) {
180
18
      if (bitFields.test(7)) {
181
0
        return BLEDeviceOperatingSystem::shared;
182
18
      } else {
183
18
        return BLEDeviceOperatingSystem::unknown;
184
18
      }
185
0
    }
186
18
    // remaining values reserved
187
18
  }
188
0
  return BLEDeviceOperatingSystem::unknown;
189
0
}
190
191
void
192
BLEDeviceFlags::operatingSystem(BLEDeviceOperatingSystem newOS)
193
9
{
194
9
  switch (newOS)
195
9
  {
196
0
  case BLEDeviceOperatingSystem::android_tbc:
197
0
    bitFields.set(5,true);
198
0
    bitFields.set(6,true);
199
0
    bitFields.set(7,true);
200
0
    break;
201
7
  case BLEDeviceOperatingSystem::android:
202
7
    bitFields.set(5,true);
203
7
    bitFields.set(6,true);
204
7
    bitFields.set(7,false);
205
7
    break;
206
0
  case BLEDeviceOperatingSystem::ios_tbc:
207
0
    bitFields.set(5,true);
208
0
    bitFields.set(6,false);
209
0
    bitFields.set(7,true);
210
0
    break;
211
2
  case BLEDeviceOperatingSystem::ios:
212
2
    bitFields.set(5,true);
213
2
    bitFields.set(6,false);
214
2
    bitFields.set(7,false);
215
2
    break;
216
0
  case BLEDeviceOperatingSystem::shared:
217
0
    bitFields.set(5,false);
218
0
    bitFields.set(6,true);
219
0
    bitFields.set(7,true);
220
0
    break;
221
0
  case BLEDeviceOperatingSystem::unknown:
222
0
    bitFields.set(5,false);
223
0
    bitFields.set(6,true);
224
0
    bitFields.set(7,false);
225
0
    break;
226
0
  case BLEDeviceOperatingSystem::ignore:
227
0
    // This is now tracked in the Filtered internal state field instead
228
0
    bitFields.set(0,true);
229
0
    bitFields.set(1,true);
230
0
    bitFields.set(2,false);
231
9
  }
232
9
}
233
234
235
bool
236
BLEDeviceFlags::hasHeraldService() const
237
39
{
238
39
  return bitFields.test(8);
239
39
}
240
241
void
242
BLEDeviceFlags::hasHeraldService(bool newValue)
243
10
{
244
10
  bitFields.set(8,newValue);
245
10
}
246
247
bool
248
BLEDeviceFlags::hasLegacyService() const
249
0
{
250
0
  return bitFields.test(9) || bitFields.test(10) || bitFields.test(11);
251
0
252
0
}
253
254
BLELegacyService
255
BLEDeviceFlags::legacyService() const
256
0
{
257
0
  if (hasHeraldService()) {
258
0
    return BLELegacyService::NotApplicable;
259
0
  }
260
0
  if (bitFields.test(9)) {
261
0
    if (bitFields.test(10)) {
262
0
      if (bitFields.test(11)) {
263
0
        return BLELegacyService::Unknown;
264
0
      } else {
265
0
        return BLELegacyService::OpenTrace;
266
0
      }
267
0
    } else {
268
0
      if (bitFields.test(11)) {
269
0
        return BLELegacyService::AustraliaCovidSafe;
270
0
      }
271
0
    }
272
0
  }
273
0
  return BLELegacyService::Unknown;
274
0
}
275
276
void
277
BLEDeviceFlags::legacyService(BLELegacyService newValue)
278
1
{
279
1
  switch (newValue)
280
1
  {
281
0
  case BLELegacyService::NotApplicable:
282
0
    bitFields.set(9,true);
283
0
    bitFields.set(10,true);
284
0
    bitFields.set(11,true);
285
0
    break;
286
1
  case BLELegacyService::Unknown:
287
1
    bitFields.set(9,true);
288
1
    bitFields.set(10,true);
289
1
    bitFields.set(11,true);
290
1
    break;
291
0
  case BLELegacyService::OpenTrace:
292
0
    bitFields.set(9,true);
293
0
    bitFields.set(10,true);
294
0
    bitFields.set(11,false);
295
0
    break;
296
0
  case BLELegacyService::AustraliaCovidSafe:
297
0
    bitFields.set(9,true);
298
0
    bitFields.set(10,false);
299
0
    bitFields.set(11,true);
300
0
    break;
301
1
  }
302
1
}
303
304
bool
305
BLEDeviceFlags::hasPayloadCharacteristic() const
306
1
{
307
1
  return bitFields.test(12);
308
1
}
309
310
void
311
BLEDeviceFlags::hasPayloadCharacteristic(bool newValue)
312
1
{
313
1
  bitFields.set(12,newValue);
314
1
}
315
316
bool
317
BLEDeviceFlags::signalCharacteristic() const
318
1
{
319
1
  return bitFields.test(13);
320
1
}
321
322
void
323
BLEDeviceFlags::signalCharacteristic(bool newValue)
324
2
{
325
2
  bitFields.set(13,newValue);
326
2
}
327
328
bool
329
BLEDeviceFlags::hasSecureCharacteristic() const
330
0
{
331
0
  return bitFields.test(14);
332
0
}
333
334
void
335
BLEDeviceFlags::hasSecureCharacteristic(bool newValue)
336
0
{
337
0
  bitFields.set(14,newValue);
338
0
}
339
340
bool
341
BLEDeviceFlags::hasEverConnected() const
342
0
{
343
0
  return bitFields.test(15);
344
0
}
345
346
void
347
BLEDeviceFlags::hasEverConnected(bool newValue)
348
0
{
349
0
  bitFields.set(15,newValue);
350
0
}
351
352
353
BLEDevice::BLEDevice()
354
  : Device(),
355
    conf(staticConfig),
356
    delegate(std::nullopt),
357
    id(),
358
    flags(),
359
    lastUpdated(Date(0)),
360
    stateData(std::monostate()),
361
    payload(),
362
    mRssi(0)
363
110
{
364
110
  ;
365
110
}
366
367
368
369
BLEDevice::BLEDevice(BLESensorConfiguration& config)
370
  : Device(),
371
    conf(config),
372
    delegate(std::nullopt),
373
    id(),
374
    flags(),
375
    lastUpdated(Date(0)),
376
    stateData(std::monostate()),
377
    payload(),
378
    mRssi(0)
379
0
{
380
0
  ;
381
0
}
382
383
BLEDevice::BLEDevice(BLESensorConfiguration& config, TargetIdentifier identifier, BLEDeviceDelegate& del,
384
  const Date& createdAt)
385
  : Device(),
386
    conf(config),
387
    delegate(std::make_optional(std::reference_wrapper<BLEDeviceDelegate>(del))),
388
    id(identifier),
389
    flags(),
390
    lastUpdated(createdAt),
391
    stateData(DiscoveredState()),
392
    payload(),
393
    mRssi(0)
394
10
{
395
10
  ;
396
10
}
397
398
BLEDevice::BLEDevice(const BLEDevice& other)
399
  : Device(),
400
    conf(other.conf),
401
    delegate(other.delegate),
402
    id(other.id),
403
    flags(other.flags),
404
    lastUpdated(other.lastUpdated),
405
    stateData(other.stateData),
406
    payload(other.payload),
407
    mRssi(other.mRssi)
408
16
{
409
16
  ;
410
16
}
411
412
136
BLEDevice::~BLEDevice() = default;
413
414
void
415
BLEDevice::reset(const TargetIdentifier& newID, BLEDeviceDelegate& newDelegate)
416
16
{
417
16
  delegate.emplace(std::reference_wrapper<BLEDeviceDelegate>(newDelegate));
418
16
  id = newID;
419
16
  lastUpdated.setToNow();
420
16
  stateData = DiscoveredState();
421
16
  flags.internalState(BLEInternalState::discovered);
422
16
  flags.state(BLEDeviceState::disconnected); // allows action from protocol providers (i.e. no longer uninitialised)
423
16
  payload.clear();
424
16
  mRssi = 0;
425
16
}
426
427
BLEDevice&
428
BLEDevice::operator=(const BLEDevice& other)
429
0
{
430
0
  conf = other.conf;
431
0
  delegate = other.delegate;
432
0
  id = other.id;
433
0
  flags = other.flags;
434
0
  lastUpdated = other.lastUpdated;
435
0
  stateData = other.stateData;
436
0
  payload = other.payload;
437
0
  mRssi = other.mRssi;
438
0
  return *this;
439
0
}
440
441
bool
442
BLEDevice::operator==(const BLEDevice& other) const noexcept
443
15
{
444
15
  return id == other.id;
445
15
}
446
447
bool
448
BLEDevice::operator!=(const BLEDevice& other) const noexcept
449
0
{
450
0
  return id != other.id;
451
0
}
452
453
454
const TargetIdentifier&
455
BLEDevice::identifier() const
456
106
{
457
106
  return id;
458
106
}
459
460
void
461
BLEDevice::identifier(const TargetIdentifier& toCopyFrom)
462
0
{
463
0
  id = toCopyFrom;
464
0
}
465
466
// Date
467
// BLEDevice::created() const
468
// {
469
//   return mCreated;
470
// }
471
472
// basic descriptors
473
std::string
474
BLEDevice::description() const
475
1
{
476
1
  return (std::string)id;
477
1
}
478
479
BLEDevice::operator std::string() const
480
1
{
481
1
  return (std::string)id;
482
1
}
483
484
// timing related getters
485
TimeInterval
486
BLEDevice::timeIntervalSinceLastUpdate() const
487
36
{
488
36
  // if (std::monostate == stateData) {
489
36
  //   return TimeInterval::zero();
490
36
  // }
491
36
  return TimeInterval(lastUpdated, Date());;
492
0
  // if (!lastUpdated.has_value()) {
493
0
  //   return TimeInterval::zero(); // default to new, just seen rather than 'no activity'
494
0
  // }
495
0
  // return TimeInterval(lastUpdated.value(), Date());
496
0
}
497
498
// TimeInterval
499
// BLEDevice::timeIntervalSinceConnected() const
500
// {
501
//   if (flags.state() != BLEDeviceState::connected) {
502
//     return TimeInterval::never();
503
//   }
504
//   // if (!connected.has_value()) {
505
//   //   return TimeInterval::never();
506
//   // }
507
//   return TimeInterval(connected.value(), Date());
508
// }
509
510
TimeInterval
511
BLEDevice::timeIntervalSinceLastPayloadDataUpdate() const
512
3
{
513
3
  if (BLEInternalState::identified != flags.internalState()) {
514
1
    return TimeInterval::never();
515
1
  }
516
2
  return TimeInterval(std::get<RelevantState>(stateData).payloadUpdated,Date());
517
2
}
518
519
// TimeInterval
520
// BLEDevice::timeIntervalSinceLastWritePayloadSharing() const
521
// {
522
//   if (!lastWritePayloadSharingAt.has_value()) {
523
//     return TimeInterval::never();
524
//   }
525
//   return TimeInterval(lastWritePayloadSharingAt.value(),Date());
526
// }
527
528
// TimeInterval
529
// BLEDevice::timeIntervalSinceLastWritePayload() const
530
// {
531
//   if (!lastWritePayloadAt.has_value()) {
532
//     return TimeInterval::never();
533
//   }
534
//   return TimeInterval(lastWritePayloadAt.value(), Date());
535
// }
536
537
// TimeInterval
538
// BLEDevice::timeIntervalSinceLastWriteRssi() const
539
// {
540
//   if (!lastWriteRssiAt.has_value()) {
541
//     return TimeInterval::never();
542
//   }
543
//   return TimeInterval(lastWriteRssiAt.value(),Date());
544
// }
545
546
TimeInterval
547
BLEDevice::timeIntervalUntilIgnoreExpired() const
548
0
{
549
0
  const auto is = flags.internalState();
550
0
  if (is != BLEInternalState::relevant &&
551
0
      is != BLEInternalState::identified) {
552
0
    return TimeInterval::zero();
553
0
  }
554
0
  const auto ignoreUntil = std::get<RelevantState>(stateData).ignoreUntil;
555
0
  if (ignoreUntil == TimeInterval::never()) {
556
0
    return TimeInterval::never();
557
0
  }
558
0
  return TimeInterval(Date(),ignoreUntil);
559
0
}
560
561
// property getters and setters
562
std::optional<BLEMacAddress>
563
BLEDevice::pseudoDeviceAddress() const
564
13
{
565
13
  const auto is = flags.internalState();
566
13
  if (is == BLEInternalState::discovered ||
567
13
      
is == BLEInternalState::filtered10
||
568
13
      
is == BLEInternalState::timed_out10
) {
569
3
    return {};
570
3
  }
571
10
  return std::make_optional(std::get<RelevantState>(stateData).pseudoAddress);
572
10
}
573
574
void
575
BLEDevice::pseudoDeviceAddress(BLEMacAddress newAddress)
576
1
{
577
1
  // Safety check
578
1
  const auto is = flags.internalState();
579
1
  if (is == BLEInternalState::discovered ||
580
1
      
is == BLEInternalState::filtered0
||
581
1
      
is == BLEInternalState::timed_out0
) {
582
1
    flags.internalState(BLEInternalState::relevant);
583
1
    stateData = RelevantState{};
584
1
  }
585
1
  const auto pa = pseudoDeviceAddress();
586
1
  if (!pa.has_value() || pa.value() != newAddress) {
587
1
    std::get<RelevantState>(stateData).pseudoAddress = newAddress;
588
1
    lastUpdated.setToNow(); // Constructs Date as now
589
1
  }
590
1
}
591
592
BLEDeviceState
593
BLEDevice::state() const
594
1.42k
{
595
1.42k
  return flags.state();
596
1.42k
}
597
598
void
599
BLEDevice::state(BLEDeviceState newState)
600
4
{
601
4
  // Safety check
602
4
  const auto is = flags.internalState();
603
4
  if (is == BLEInternalState::discovered ||
604
4
      
is == BLEInternalState::filtered2
||
605
4
      
is == BLEInternalState::timed_out2
) {
606
2
    flags.internalState(BLEInternalState::relevant);
607
2
    stateData = RelevantState{};
608
2
  }
609
4
  auto& rs = std::get<RelevantState>(stateData);
610
4
611
4
  const auto curState = flags.state();
612
4
  // Check if failed to connect
613
4
  if (BLEDeviceState::disconnected == newState &&
614
4
      
(1
BLEDeviceState::disconnected == curState1
||
615
1
       BLEDeviceState::connecting == curState
616
1
      )
617
0
  ) {
618
0
    ++rs.connectRepeatedFailures;
619
0
    if (rs.connectRepeatedFailures >= 5) { // Changed to 5 from 10 for quicker failure in busy areas
620
0
      // Ignore for a while (progressive backoff)
621
0
      operatingSystem(BLEDeviceOperatingSystem::ignore);
622
0
      // Don't backoff again immediately
623
0
      rs.connectRepeatedFailures = 0;
624
0
    }
625
0
  }
626
4
  if (BLEDeviceState::connected == newState) {
627
0
    flags.hasEverConnected(true);
628
0
    rs.connectRepeatedFailures = 0;
629
0
  }
630
4
  bool changed = curState != newState;
631
4
  if (changed) {
632
4
    flags.state(newState);
633
4
    lastUpdated = Date(); // Constructs Date as now
634
4
    if (delegate.has_value()) {
635
4
      delegate->get().device(*this, BLEDeviceAttribute::state);
636
4
    }
637
4
  }
638
4
}
639
640
BLEDeviceOperatingSystem
641
BLEDevice::operatingSystem() const
642
34
{
643
34
  return flags.operatingSystem();
644
34
}
645
646
void
647
BLEDevice::operatingSystem(BLEDeviceOperatingSystem newOS)
648
9
{
649
9
  // Safety check
650
9
  const auto is = flags.internalState();
651
9
  if (is == BLEInternalState::discovered ||
652
9
      
is == BLEInternalState::filtered0
||
653
9
      
is == BLEInternalState::timed_out0
) {
654
9
    flags.internalState(BLEInternalState::relevant);
655
9
    stateData = RelevantState{};
656
9
  }
657
9
  auto& rs = std::get<RelevantState>(stateData);
658
9
659
9
  lastUpdated.setToNow();
660
9
  const auto os = operatingSystem();
661
9
  if (os != BLEDeviceOperatingSystem::unknown && 
os == BLEDeviceOperatingSystem::ignore0
) {
662
0
    if (TimeInterval::zero() == rs.ignoreForDuration) {
663
0
      rs.ignoreForDuration = TimeInterval::minutes(1);
664
0
    } else if (rs.ignoreForDuration < TimeInterval::minutes(3)) {
665
0
      // progressive backoff for unknown device
666
0
      rs.ignoreForDuration *= 1.2;
667
0
      if (rs.ignoreForDuration > TimeInterval::minutes(7)) {
668
0
        // just ignore as the mac will have rotated (7:43 will occur half way through 15 mins intervals)
669
0
        // As the total BLE DB timeout is ~ 25 minutes, this will save significant connection attempt cycles
670
0
        // mIgnore = true;
671
0
        // Change to ignored (aka filtered) state
672
0
        flags.internalState(BLEInternalState::filtered);
673
0
      }
674
0
    }
675
0
    rs.ignoreUntil = lastUpdated + rs.ignoreForDuration;
676
9
  } else {
677
9
    rs.ignoreUntil = Date(0); // ensure we've already passed the time
678
9
  }
679
9
  if (os == BLEDeviceOperatingSystem::ios || os == BLEDeviceOperatingSystem::android) {
680
0
    rs.ignoreForDuration = TimeInterval::zero();
681
0
  }
682
9
  bool changed = (BLEDeviceOperatingSystem::unknown != os) || os != newOS;
683
9
  if (changed) {
684
9
    flags.operatingSystem(newOS);
685
9
    delegate->get().device(*this, BLEDeviceAttribute::operatingSystem);
686
9
  }
687
9
}
688
689
PayloadData
690
BLEDevice::payloadData() const
691
61
{
692
61
  return payload;
693
61
}
694
695
void
696
BLEDevice::payloadData(PayloadData newPayloadData)
697
8
{
698
8
  if (flags.internalState() != BLEInternalState::identified) {
699
8
    flags.internalState(BLEInternalState::identified);
700
8
    stateData = RelevantState{};
701
8
  }
702
8
  bool changed = payload.size() == 0 || 
payload != newPayloadData0
;
703
8
  if (changed) {
704
8
    payload = newPayloadData;
705
8
    lastUpdated.setToNow(); // Constructs Date as now
706
8
    std::get<RelevantState>(stateData).payloadUpdated.setToNow();
707
8
    // payloadUpdated.emplace();
708
8
    if (delegate.has_value()) {
709
8
      delegate.value().get().device(*this, BLEDeviceAttribute::payloadData);
710
8
    }
711
8
  }
712
8
}
713
714
// std::optional<ImmediateSendData>
715
// BLEDevice::immediateSendData() const
716
// {
717
//   return mImmediateSendData;
718
// }
719
720
// void
721
// BLEDevice::immediateSendData(ImmediateSendData toSend)
722
// {
723
//   bool changed = !mImmediateSendData.has_value() || mImmediateSendData.value() != toSend;
724
//   if (changed) {
725
//     mImmediateSendData.emplace(toSend);
726
//     lastUpdated = Date(); // Constructs Date as now
727
//     delegate->get().device(*this, BLEDeviceAttribute::immediateSendData);
728
//   }
729
// }
730
731
// void
732
// BLEDevice::clearImmediateSendData()
733
// {
734
//   mImmediateSendData.reset();
735
// }
736
737
RSSI
738
BLEDevice::rssi() const
739
2
{
740
2
  return mRssi;
741
2
}
742
743
void
744
BLEDevice::rssi(RSSI newRSSI)
745
2
{
746
2
  bool changed = (0 == mRssi.intValue()) || 
(mRssi != newRSSI)0
;
747
2
  if (changed) {
748
2
    mRssi = newRSSI;
749
2
    // lastUpdated.emplace(); // Constructs Date as now
750
2
    if (delegate.has_value()) {
751
2
      delegate.value().get().device(*this, BLEDeviceAttribute::rssi);
752
2
    }
753
2
  }
754
2
}
755
756
std::optional<BLETxPower>
757
BLEDevice::txPower() const
758
2
{
759
2
  // Safety check
760
2
  const auto is = flags.internalState();
761
2
  if (is == BLEInternalState::discovered ||
762
2
      is == BLEInternalState::filtered ||
763
2
      is == BLEInternalState::timed_out) {
764
0
    return {};
765
0
  }
766
2
  auto& rs = std::get<RelevantState>(stateData);
767
2
  return std::make_optional(rs.txPower);
768
2
}
769
770
void
771
BLEDevice::txPower(BLETxPower newPower)
772
1
{
773
1
  // Safety check
774
1
  const auto is = flags.internalState();
775
1
  if (is == BLEInternalState::discovered ||
776
1
      
is == BLEInternalState::filtered0
||
777
1
      
is == BLEInternalState::timed_out0
) {
778
1
    // return; // TODO convert type to Relevant instead?
779
1
    flags.internalState(BLEInternalState::relevant);
780
1
    stateData = RelevantState{};
781
1
  }
782
1
  auto& rs = std::get<RelevantState>(stateData);
783
1
  bool changed = rs.txPower != newPower;
784
1
  if (changed) {
785
1
    rs.txPower = newPower;
786
1
    lastUpdated.setToNow();
787
1
    delegate->get().device(*this, BLEDeviceAttribute::txPower);
788
1
  }
789
1
}
790
791
// bool
792
// BLEDevice::receiveOnly() const
793
// {
794
//   return mReceiveOnly;
795
// }
796
797
// void
798
// BLEDevice::receiveOnly(bool newReceiveOnly)
799
// {
800
//   mReceiveOnly = newReceiveOnly;
801
// }
802
803
std::optional<UUID>
804
BLEDevice::signalCharacteristic() const
805
1
{
806
1
  // Safety check
807
1
  const auto is = flags.internalState();
808
1
  if (is == BLEInternalState::discovered ||
809
1
      
is == BLEInternalState::filtered0
||
810
1
      
is == BLEInternalState::timed_out0
) {
811
1
    // Apple devices are not spec compliant for Bluetooth, which is what this value really means
812
1
    if (SignalCharacteristicType::SpecCompliant == flags.signalCharacteristic()) {
813
0
      return std::make_optional(conf.androidSignalCharacteristicUUID);
814
0
    }
815
1
    return std::make_optional(conf.iosSignalCharacteristicUUID);
816
1
  }
817
0
  return {};
818
0
}
819
820
void
821
BLEDevice::signalCharacteristic(UUID newChar)
822
1
{
823
1
  if (conf.androidSignalCharacteristicUUID == newChar) {
824
0
    flags.signalCharacteristic(true);
825
1
  } else {
826
1
    flags.signalCharacteristic(false);
827
1
  }
828
1
  lastUpdated.setToNow();
829
1
}
830
831
std::optional<UUID>
832
BLEDevice::payloadCharacteristic() const
833
1
{
834
1
  if (!flags.hasPayloadCharacteristic()) {
835
1
    return {};
836
1
  }
837
0
  return std::make_optional(conf.payloadCharacteristicUUID);
838
0
}
839
840
void
841
BLEDevice::payloadCharacteristic(UUID newChar)
842
2
{
843
2
  if (conf.payloadCharacteristicUUID == newChar) {
844
0
    flags.hasPayloadCharacteristic(true);
845
0
  }
846
2
  lastUpdated.setToNow();
847
2
}
848
849
// State engine methods
850
bool
851
BLEDevice::ignore() const
852
51
{
853
51
  const auto is = flags.internalState();
854
51
  if (is == BLEInternalState::filtered ||
855
51
      
is == BLEInternalState::timed_out50
) {
856
1
    return true;
857
1
  }
858
50
  if (is == BLEInternalState::discovered) {
859
13
    return false;
860
13
  }
861
37
  auto& rs = std::get<RelevantState>(stateData);
862
37
863
37
  // Check for timed ignore
864
37
  if (0 == rs.ignoreUntil) {
865
37
    return false;
866
37
  }
867
0
  if (Date() < rs.ignoreUntil) {
868
0
    return true;
869
0
  }
870
0
  return false;
871
0
}
872
873
void
874
BLEDevice::ignore(bool newIgnore) // set permanent ignore flag
875
1
{
876
1
  // change state to ignored permanently
877
1
  if (newIgnore) {
878
1
    stateData = FilteredState(); // TODO determine if this breaks end of life detection for android devices with pseudo device address
879
1
    flags.internalState(BLEInternalState::filtered);
880
1
  }
881
1
  lastUpdated.setToNow();
882
1
}
883
884
void
885
BLEDevice::invalidateCharacteristics()
886
1
{
887
1
  // mPayloadCharacteristic.reset();
888
1
  // mSignalCharacteristic.reset();
889
1
  flags.hasPayloadCharacteristic(false);
890
1
  flags.legacyService(BLELegacyService::Unknown);
891
1
  flags.signalCharacteristic(SignalCharacteristicType::SpecCompliant); // Assume spec compliant
892
1
  lastUpdated.setToNow();
893
1
}
894
895
void
896
BLEDevice::registerDiscovery(Date at)
897
0
{
898
0
  // lastDiscoveredAt.emplace(at);
899
0
  lastUpdated = Date(); // TODO verify this shouldn't be 'at' instead (for continuity)
900
0
}
901
902
// void
903
// BLEDevice::registerWritePayload(Date at)
904
// {
905
//   lastUpdated.emplace(at);
906
//   lastWritePayloadAt.emplace(at);
907
// }
908
909
// void
910
// BLEDevice::registerWritePayloadSharing(Date at)
911
// {
912
//   lastUpdated.emplace(at);
913
//   lastWritePayloadSharingAt.emplace(at);
914
// }
915
916
// void
917
// BLEDevice::registerWriteRssi(Date at)
918
// {
919
//   lastUpdated.emplace(at);
920
//   lastWriteRssiAt.emplace(at);
921
// }
922
923
// bool
924
// BLEDevice::hasAdvertData() const
925
// {
926
//   const auto is = flags.internalState();
927
//   if (is == BLEInternalState::discovered) {
928
//     return true;
929
//   }
930
// }
931
932
void
933
BLEDevice::advertData(std::vector<BLEAdvertSegment> newSegments)
934
0
{
935
0
  stateData = DiscoveredState{newSegments};
936
0
  flags.internalState(BLEInternalState::discovered);
937
0
}
938
939
// const std::vector<BLEAdvertSegment>&
940
// BLEDevice::advertData() const
941
// {
942
//   const auto is = flags.internalState();
943
//   if (is != BLEInternalState::discovered) {
944
//     return {};
945
//   }
946
//   auto& rs = std::get<DiscoveredState>(stateData);
947
//   return rs.segments;
948
// }
949
950
// bool
951
// BLEDevice::hasServicesSet() const
952
// {
953
//   return mServices.has_value();
954
// }
955
956
void
957
BLEDevice::services(std::vector<UUID> services)
958
10
{
959
10
  lastUpdated.setToNow();
960
10
  for (auto& svc : services) {
961
10
    if (svc == conf.serviceUUID) {
962
10
      flags.hasHeraldService(true);
963
10
      return;
964
10
    }
965
0
    if (svc == herald::ble::legacyOpenTraceUUID) {
966
0
      flags.legacyService(BLELegacyService::OpenTrace);
967
0
      return;
968
0
    }
969
0
    if (svc == herald::ble::legacyAustraliaServiceUUID) {
970
0
      flags.legacyService(BLELegacyService::AustraliaCovidSafe);
971
0
      return;
972
0
    }
973
0
  }
974
10
  flags.hasHeraldService(false);
975
0
}
976
977
bool
978
BLEDevice::hasService(const UUID& serviceUUID) const
979
39
{
980
39
  if (flags.hasHeraldService()) {
981
33
    if (conf.serviceUUID == serviceUUID) {
982
33
      return true;
983
33
    }
984
6
  }
985
6
  return false;
986
6
}
987
988
const BLESensorConfiguration&
989
BLEDevice::configuration() const noexcept
990
0
{
991
0
  return conf;
992
0
}
993
994
995
BLESensorConfiguration
996
BLEDevice::staticConfig = BLESensorConfiguration();
997
998
}
999
}