mirror of
https://github.com/seemoo-lab/openhaystack.git
synced 2026-08-19 03:26:15 +00:00
Unmark devices as nearby when they stop sending advertisements
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user