spotny-sdk 1.0.21 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -99,6 +99,8 @@ public class SpotnyBeaconScanner: NSObject {
|
|
|
99
99
|
private var campaignFetchCooldown: [String: Date] = [:] // backoff after failed fetch
|
|
100
100
|
// 410 from /track means backend session expired — stop sending heartbeats until next NEARBY
|
|
101
101
|
private var impressionDisabled: [String: Bool] = [:]
|
|
102
|
+
// Last time each beacon was seen in a ranging callback — used to detect slow drift exits
|
|
103
|
+
private var beaconLastSeen: [String: Date] = [:]
|
|
102
104
|
|
|
103
105
|
// MARK: - Init
|
|
104
106
|
|
|
@@ -383,6 +385,21 @@ public class SpotnyBeaconScanner: NSObject {
|
|
|
383
385
|
resolve("Logs cleared")
|
|
384
386
|
}
|
|
385
387
|
|
|
388
|
+
// MARK: - Local Notifications (debug)
|
|
389
|
+
|
|
390
|
+
private func sendLocalNotification(title: String, body: String) {
|
|
391
|
+
let content = UNMutableNotificationContent()
|
|
392
|
+
content.title = title
|
|
393
|
+
content.body = body
|
|
394
|
+
content.sound = .default
|
|
395
|
+
let request = UNNotificationRequest(
|
|
396
|
+
identifier: UUID().uuidString,
|
|
397
|
+
content: content,
|
|
398
|
+
trigger: nil
|
|
399
|
+
)
|
|
400
|
+
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
|
|
401
|
+
}
|
|
402
|
+
|
|
386
403
|
// MARK: - Scanning Setup
|
|
387
404
|
|
|
388
405
|
private func startPersistentScanning() {
|
|
@@ -757,6 +774,7 @@ public class SpotnyBeaconScanner: NSObject {
|
|
|
757
774
|
campaignFetched.removeValue(forKey: key)
|
|
758
775
|
campaignFetchCooldown.removeValue(forKey: key)
|
|
759
776
|
impressionDisabled.removeValue(forKey: key)
|
|
777
|
+
beaconLastSeen.removeValue(forKey: key)
|
|
760
778
|
print("🧹 SpotnySDK: Cleaned up \(key)")
|
|
761
779
|
}
|
|
762
780
|
|
|
@@ -853,7 +871,9 @@ extension SpotnyBeaconScanner: KTKBeaconManagerDelegate {
|
|
|
853
871
|
lastProximityDistance[key] = distance
|
|
854
872
|
lastProximityEventSent[key] = now
|
|
855
873
|
}
|
|
856
|
-
|
|
874
|
+
|
|
875
|
+
beaconLastSeen[key] = now
|
|
876
|
+
|
|
857
877
|
// Fetch campaign when distance <= 3m
|
|
858
878
|
if distance <= 3.0 && campaignFetched[key] != true {
|
|
859
879
|
fetchCampaign(key: key, major: major, minor: minor)
|
|
@@ -872,18 +892,31 @@ extension SpotnyBeaconScanner: KTKBeaconManagerDelegate {
|
|
|
872
892
|
}
|
|
873
893
|
}
|
|
874
894
|
}
|
|
895
|
+
|
|
896
|
+
// Slow-drift exit detection — beacon disappeared from ranging without a region exit
|
|
897
|
+
let beaconExitTimeout: TimeInterval = 5.0
|
|
898
|
+
for key in Array(lastProximityEventSent.keys) {
|
|
899
|
+
guard let lastSeen = beaconLastSeen[key] else {
|
|
900
|
+
beaconLastSeen[key] = now; continue
|
|
901
|
+
}
|
|
902
|
+
if now.timeIntervalSince(lastSeen) >= beaconExitTimeout {
|
|
903
|
+
cleanupBeacon(key)
|
|
904
|
+
}
|
|
905
|
+
}
|
|
875
906
|
}
|
|
876
907
|
|
|
877
908
|
public func beaconManager(_ manager: KTKBeaconManager, didEnter region: KTKBeaconRegion) {
|
|
878
909
|
print("🎯 SpotnySDK: Entered region \(region.identifier)")
|
|
879
910
|
eventCallback?("onBeaconRegionEvent", ["region": region.identifier, "event": "enter"])
|
|
880
|
-
|
|
881
|
-
extendBackgroundTime(duration:
|
|
911
|
+
sendLocalNotification(title: "📍 Beacon Region Entered", body: region.identifier)
|
|
912
|
+
extendBackgroundTime(duration: 30.0)
|
|
913
|
+
beaconManager.startRangingBeacons(in: region)
|
|
882
914
|
}
|
|
883
915
|
|
|
884
916
|
public func beaconManager(_ manager: KTKBeaconManager, didExitRegion region: KTKBeaconRegion) {
|
|
885
917
|
print("🚪 SpotnySDK: Exited region \(region.identifier)")
|
|
886
918
|
eventCallback?("onBeaconRegionEvent", ["region": region.identifier, "event": "exit"])
|
|
919
|
+
sendLocalNotification(title: "🚪 Beacon Region Exited", body: region.identifier)
|
|
887
920
|
// FIX #1: use helper; FIX #3: cleanupAllProximityState covers all beacons regardless of region format
|
|
888
921
|
extendBackgroundTime(duration: 2.0)
|
|
889
922
|
cleanupAllProximityState()
|