100% fresh codebase — no legacy code carried over. Built against the Android beacon app as the behavioral spec. Architecture: - App: SwiftUI @main, AppState-driven navigation, Keychain storage - Views: LoginView (OTP + biometric), BusinessListView, ScanView (provisioning hub) - Models: Business, ServicePoint, BeaconConfig, BeaconType, DiscoveredBeacon - Services: APIClient (actor, async/await), BLEManager (CoreBluetooth scanner) - Provisioners: KBeacon, DXSmart (2-step auth + flashing), BlueCharm - Utils: UUIDFormatting, BeaconBanList, BeaconShardPool (64 shards) Matches Android feature parity: - 4-screen flow: Login → Business Select → Scan/Provision - 3 beacon types with correct GATT protocols and timeouts - Namespace allocation via beacon-sharding API - Smart service point naming (Table N auto-increment) - DXSmart special flow (connect → flash → user confirms → write) - Biometric auth, dev/prod build configs, DEV banner overlay Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
24 lines
819 B
Swift
24 lines
819 B
Swift
import Foundation
|
|
|
|
/// Factory-default UUIDs that indicate an unconfigured beacon (matches Android BeaconBanList.kt)
|
|
enum BeaconBanList {
|
|
|
|
/// UUID prefixes (first 8 hex chars) that are factory defaults
|
|
static let bannedPrefixes: Set<String> = [
|
|
"E2C56DB5", // Apple AirLocate / Minew
|
|
"B9407F30", // Estimote
|
|
"FDA50693", // Generic Chinese bulk
|
|
"F7826DA6", // Kontakt.io
|
|
"2F234454", // Radius Networks
|
|
"74278BDA", // Generic bulk
|
|
"00000000", // Unconfigured
|
|
"FFFFFFFF", // Unconfigured
|
|
]
|
|
|
|
/// Check if a UUID is a factory default
|
|
static func isBanned(_ uuid: String) -> Bool {
|
|
let normalized = uuid.normalizedUUID
|
|
let prefix = String(normalized.prefix(8))
|
|
return bannedPrefixes.contains(prefix)
|
|
}
|
|
}
|