Unmark devices as nearby when they stop sending advertisements

This commit is contained in:
Milan Stute
2021-03-15 17:16:01 +01:00
parent eb07546640
commit cf0416e174
3 changed files with 39 additions and 4 deletions
@@ -14,32 +14,66 @@ class AccessoryNearbyMonitor: BluetoothAccessoryDelegate {
var accessoryController: AccessoryController
var scanner: BluetoothAccessoryScanner
var cleanup: Timer?
init(accessoryController: AccessoryController) {
self.accessoryController = accessoryController
self.scanner = BluetoothAccessoryScanner()
self.initScanner()
self.initTimer()
}
func initScanner() {
self.scanner.delegate = self
}
func initTimer() {
self.cleanup = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
self.removeNearbyAccessories()
}
}
func received(_ advertisement: Advertisement) {
guard let accessory = getAccessoryForAdvertisement(advertisement) else {
return
}
updateNearbyAccessory(accessory)
}
func updateNearbyAccessory(_ accessory: Accessory) {
if !accessory.isNearby {
// Only set on state change
accessory.isNearby = true
}
accessory.lastAdvertisement = Date()
}
func removeNearbyAccessories(now: Date = Date(), timeout: TimeInterval = 10.0) {
let nearbyAccessories = self.accessoryController.accessories.filter({ $0.isNearby })
for accessory in nearbyAccessories {
guard let lastAdvertisement = accessory.lastAdvertisement else {
continue
}
if lastAdvertisement + timeout < now {
accessory.isNearby = false
}
}
}
func getAccessoryForAdvertisement(_ advertisement: Advertisement) -> Accessory? {
let accessory =
try? self.accessoryController.accessories.first {
let accessoryPublicKey = try $0.getAdvertisementKey().advanced(by: 6)
return accessoryPublicKey == advertisement.publicKeyPayload
self.accessoryController.accessories.first {
isAdvertisement(advertisement, from: $0)
} ?? nil
return accessory
}
func isAdvertisement(_ advertisement: Advertisement, from: Accessory) -> Bool {
do {
let accessoryPublicKey = try from.getAdvertisementKey().advanced(by: 6)
return accessoryPublicKey == advertisement.publicKeyPayload
} catch {
return false
}
}
}
@@ -18,7 +18,7 @@ struct Advertisement {
guard let manufacturerData = fromAdvertisementData[CBAdvertisementDataManufacturerDataKey] as? Data else {
return nil
}
try? self.init(fromManufacturerData: manufacturerData)
self.init(fromManufacturerData: manufacturerData)
}
init?(fromManufacturerData: Data) {
@@ -53,6 +53,7 @@ class Accessory: ObservableObject, Codable, Identifiable, Equatable, Hashable {
}
}
}
var lastAdvertisement: Date?
init(name: String = "New accessory", color: Color = randomColor(), iconName: String = randomIcon()) throws {
self.name = name