Merge pull request 'refactor: consolidate UUID formatting into shared extension' (#1) from schwifty/consolidate-uuid-formatting into main
This commit is contained in:
commit
9ddb9ebe1b
7 changed files with 48 additions and 45 deletions
|
|
@ -155,7 +155,7 @@ class Api {
|
||||||
var result: [String: Int] = [:]
|
var result: [String: Int] = [:]
|
||||||
for item in items {
|
for item in items {
|
||||||
guard let uuid = ((item["UUID"] ?? item["uuid"] ?? item["BeaconUUID"] ?? item["BEACONUUID"]) as? String)?
|
guard let uuid = ((item["UUID"] ?? item["uuid"] ?? item["BeaconUUID"] ?? item["BEACONUUID"]) as? String)?
|
||||||
.replacingOccurrences(of: "-", with: "").uppercased(),
|
.normalizedUUID,
|
||||||
let beaconId = parseIntValue(item["BeaconID"] ?? item["BEACONID"]) else {
|
let beaconId = parseIntValue(item["BeaconID"] ?? item["BEACONID"]) else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +175,7 @@ class Api {
|
||||||
|
|
||||||
return beacons.compactMap { b in
|
return beacons.compactMap { b in
|
||||||
guard let uuid = ((b["UUID"] ?? b["uuid"]) as? String)?
|
guard let uuid = ((b["UUID"] ?? b["uuid"]) as? String)?
|
||||||
.replacingOccurrences(of: "-", with: "").uppercased() else {
|
.normalizedUUID else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return BeaconLookupResult(
|
return BeaconLookupResult(
|
||||||
|
|
@ -204,7 +204,7 @@ class Api {
|
||||||
let beaconId = parseIntValue(b["BeaconID"] ?? b["BEACONID"] ?? b["ID"]) ?? 0
|
let beaconId = parseIntValue(b["BeaconID"] ?? b["BEACONID"] ?? b["ID"]) ?? 0
|
||||||
let name = ((b["Name"] ?? b["NAME"] ?? b["BeaconName"] ?? b["BEACONNAME"]) as? String) ?? ""
|
let name = ((b["Name"] ?? b["NAME"] ?? b["BeaconName"] ?? b["BEACONNAME"]) as? String) ?? ""
|
||||||
let uuid = ((b["UUID"] ?? b["uuid"]) as? String)?
|
let uuid = ((b["UUID"] ?? b["uuid"]) as? String)?
|
||||||
.replacingOccurrences(of: "-", with: "").uppercased() ?? ""
|
.normalizedUUID ?? ""
|
||||||
let isActive = parseBool(b["IsActive"] ?? b["ISACTIVE"] ?? true)
|
let isActive = parseBool(b["IsActive"] ?? b["ISACTIVE"] ?? true)
|
||||||
return BeaconInfo(beaconId: beaconId, name: name, uuid: uuid, isActive: isActive)
|
return BeaconInfo(beaconId: beaconId, name: name, uuid: uuid, isActive: isActive)
|
||||||
}
|
}
|
||||||
|
|
@ -322,7 +322,7 @@ class Api {
|
||||||
DebugLog.shared.log("[API] getBeaconConfig parsed: uuid=\(uuid) major=\(major) minor=\(minor) measuredPower=\(measuredPower) advInterval=\(advInterval) txPower=\(txPower)")
|
DebugLog.shared.log("[API] getBeaconConfig parsed: uuid=\(uuid) major=\(major) minor=\(minor) measuredPower=\(measuredPower) advInterval=\(advInterval) txPower=\(txPower)")
|
||||||
|
|
||||||
return BeaconConfigResponse(
|
return BeaconConfigResponse(
|
||||||
uuid: uuid.replacingOccurrences(of: "-", with: "").uppercased(),
|
uuid: uuid.normalizedUUID,
|
||||||
major: UInt16(major),
|
major: UInt16(major),
|
||||||
minor: UInt16(minor),
|
minor: UInt16(minor),
|
||||||
measuredPower: Int8(clamping: measuredPower),
|
measuredPower: Int8(clamping: measuredPower),
|
||||||
|
|
@ -430,7 +430,7 @@ class Api {
|
||||||
return BusinessNamespace(
|
return BusinessNamespace(
|
||||||
shardId: parseIntValue(json["ShardID"] ?? json["SHARDID"]) ?? 0,
|
shardId: parseIntValue(json["ShardID"] ?? json["SHARDID"]) ?? 0,
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
uuidClean: uuid.replacingOccurrences(of: "-", with: "").uppercased(),
|
uuidClean: uuid.normalizedUUID,
|
||||||
major: UInt16(major),
|
major: UInt16(major),
|
||||||
alreadyAllocated: parseBool(json["AlreadyAllocated"] ?? json["ALREADYALLOCATED"])
|
alreadyAllocated: parseBool(json["AlreadyAllocated"] ?? json["ALREADYALLOCATED"])
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ enum BeaconBanList {
|
||||||
|
|
||||||
/// Check if a UUID is on the ban list.
|
/// Check if a UUID is on the ban list.
|
||||||
static func isBanned(_ uuid: String) -> Bool {
|
static func isBanned(_ uuid: String) -> Bool {
|
||||||
let normalized = uuid.replacingOccurrences(of: "-", with: "").uppercased()
|
let normalized = uuid.normalizedUUID
|
||||||
|
|
||||||
// Check full UUID match
|
// Check full UUID match
|
||||||
if BANNED_FULL_UUIDS[normalized] != nil { return true }
|
if BANNED_FULL_UUIDS[normalized] != nil { return true }
|
||||||
|
|
@ -52,7 +52,7 @@ enum BeaconBanList {
|
||||||
|
|
||||||
/// Get the reason a UUID is banned, or nil if not banned.
|
/// Get the reason a UUID is banned, or nil if not banned.
|
||||||
static func getBanReason(_ uuid: String) -> String? {
|
static func getBanReason(_ uuid: String) -> String? {
|
||||||
let normalized = uuid.replacingOccurrences(of: "-", with: "").uppercased()
|
let normalized = uuid.normalizedUUID
|
||||||
|
|
||||||
// Check full UUID match first
|
// Check full UUID match first
|
||||||
if let reason = BANNED_FULL_UUIDS[normalized] { return reason }
|
if let reason = BANNED_FULL_UUIDS[normalized] { return reason }
|
||||||
|
|
@ -64,16 +64,9 @@ enum BeaconBanList {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format a raw UUID string (32 hex chars) into standard UUID format with dashes.
|
/// Format a raw UUID string into standard UUID format with dashes.
|
||||||
|
/// Delegates to String.uuidWithDashes (UUIDFormatting.swift).
|
||||||
static func formatUuid(_ uuid: String) -> String {
|
static func formatUuid(_ uuid: String) -> String {
|
||||||
let hex = uuid.replacingOccurrences(of: "-", with: "").uppercased()
|
uuid.uuidWithDashes
|
||||||
guard hex.count == 32 else { return uuid }
|
|
||||||
let s = hex
|
|
||||||
let i0 = s.startIndex
|
|
||||||
let i8 = s.index(i0, offsetBy: 8)
|
|
||||||
let i12 = s.index(i0, offsetBy: 12)
|
|
||||||
let i16 = s.index(i0, offsetBy: 16)
|
|
||||||
let i20 = s.index(i0, offsetBy: 20)
|
|
||||||
return "\(s[i0..<i8])-\(s[i8..<i12])-\(s[i12..<i16])-\(s[i16..<i20])-\(s[i20...])"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -826,7 +826,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
|
||||||
private func hexStringToData(_ hex: String) -> Data? {
|
private func hexStringToData(_ hex: String) -> Data? {
|
||||||
let clean = hex.replacingOccurrences(of: "-", with: "").uppercased()
|
let clean = hex.normalizedUUID
|
||||||
guard clean.count == 32 else { return nil }
|
guard clean.count == 32 else { return nil }
|
||||||
|
|
||||||
var data = Data()
|
var data = Data()
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ class BeaconScanner: NSObject, ObservableObject, CLLocationManagerDelegate {
|
||||||
let rssiValue = beacon.rssi
|
let rssiValue = beacon.rssi
|
||||||
guard rssiValue >= BeaconScanner.MIN_RSSI && rssiValue < 0 else { continue }
|
guard rssiValue >= BeaconScanner.MIN_RSSI && rssiValue < 0 else { continue }
|
||||||
|
|
||||||
let uuid = beacon.uuid.uuidString.replacingOccurrences(of: "-", with: "").uppercased()
|
let uuid = beacon.uuid.uuidString.normalizedUUID
|
||||||
let major = beacon.major.uint16Value
|
let major = beacon.major.uint16Value
|
||||||
let minor = beacon.minor.uint16Value
|
let minor = beacon.minor.uint16Value
|
||||||
let key = "\(uuid)|\(major)|\(minor)"
|
let key = "\(uuid)|\(major)|\(minor)"
|
||||||
|
|
@ -148,13 +148,6 @@ struct DetectedBeacon {
|
||||||
/// Format for clipboard (for pasting into manufacturer beacon config apps)
|
/// Format for clipboard (for pasting into manufacturer beacon config apps)
|
||||||
func copyableConfig() -> String {
|
func copyableConfig() -> String {
|
||||||
// Format UUID with dashes for standard display
|
// Format UUID with dashes for standard display
|
||||||
let formattedUuid = formatUuidWithDashes(uuid)
|
return "UUID: \(uuid.uuidWithDashes)\nMajor: \(major)\nMinor: \(minor)"
|
||||||
return "UUID: \(formattedUuid)\nMajor: \(major)\nMinor: \(minor)"
|
|
||||||
}
|
|
||||||
|
|
||||||
private func formatUuidWithDashes(_ raw: String) -> String {
|
|
||||||
guard raw.count == 32 else { return raw }
|
|
||||||
let chars = Array(raw)
|
|
||||||
return "\(String(chars[0..<8]))-\(String(chars[8..<12]))-\(String(chars[12..<16]))-\(String(chars[16..<20]))-\(String(chars[20..<32]))"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -808,7 +808,7 @@ struct ScanView: View {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Format UUID with dashes for API call
|
// Format UUID with dashes for API call
|
||||||
let uuidWithDashes = formatUuidWithDashes(beacon.uuid)
|
let uuidWithDashes = beacon.uuid.uuidWithDashes
|
||||||
let result = try await Api.shared.resolveBusiness(uuid: uuidWithDashes, major: beacon.major)
|
let result = try await Api.shared.resolveBusiness(uuid: uuidWithDashes, major: beacon.major)
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
beaconOwnership[key] = (businessId: result.businessId, businessName: result.businessName)
|
beaconOwnership[key] = (businessId: result.businessId, businessName: result.businessName)
|
||||||
|
|
@ -895,7 +895,7 @@ struct ScanView: View {
|
||||||
case .success(let macAddress):
|
case .success(let macAddress):
|
||||||
do {
|
do {
|
||||||
// Use MAC address as hardware ID, fallback to iBeacon UUID if unavailable
|
// Use MAC address as hardware ID, fallback to iBeacon UUID if unavailable
|
||||||
let uuidWithDashes = formatUuidWithDashes(config.uuid)
|
let uuidWithDashes = config.uuid.uuidWithDashes
|
||||||
let hardwareId = macAddress ?? uuidWithDashes
|
let hardwareId = macAddress ?? uuidWithDashes
|
||||||
DebugLog.shared.log("[ScanView] Registering beacon - MAC: \(macAddress ?? "nil"), hardwareId: \(hardwareId), uuid: \(uuidWithDashes)")
|
DebugLog.shared.log("[ScanView] Registering beacon - MAC: \(macAddress ?? "nil"), hardwareId: \(hardwareId), uuid: \(uuidWithDashes)")
|
||||||
try await Api.shared.registerBeaconHardware(
|
try await Api.shared.registerBeaconHardware(
|
||||||
|
|
@ -978,7 +978,7 @@ struct ScanView: View {
|
||||||
// Register in backend (use UUID with dashes for API)
|
// Register in backend (use UUID with dashes for API)
|
||||||
do {
|
do {
|
||||||
// Use MAC address as hardware ID, fallback to iBeacon UUID if unavailable
|
// Use MAC address as hardware ID, fallback to iBeacon UUID if unavailable
|
||||||
let uuidWithDashes = formatUuidWithDashes(config.uuid)
|
let uuidWithDashes = config.uuid.uuidWithDashes
|
||||||
let hardwareId = macAddress ?? uuidWithDashes
|
let hardwareId = macAddress ?? uuidWithDashes
|
||||||
DebugLog.shared.log("[ScanView] Registering beacon - MAC: \(macAddress ?? "nil"), hardwareId: \(hardwareId), uuid: \(uuidWithDashes)")
|
DebugLog.shared.log("[ScanView] Registering beacon - MAC: \(macAddress ?? "nil"), hardwareId: \(hardwareId), uuid: \(uuidWithDashes)")
|
||||||
try await Api.shared.registerBeaconHardware(
|
try await Api.shared.registerBeaconHardware(
|
||||||
|
|
@ -1039,10 +1039,5 @@ struct ScanView: View {
|
||||||
provisioningError = error
|
provisioningError = error
|
||||||
}
|
}
|
||||||
|
|
||||||
private func formatUuidWithDashes(_ raw: String) -> String {
|
// UUID formatting now handled by String.uuidWithDashes (UUIDFormatting.swift)
|
||||||
let clean = raw.replacingOccurrences(of: "-", with: "").uppercased()
|
|
||||||
guard clean.count == 32 else { return raw }
|
|
||||||
let chars = Array(clean)
|
|
||||||
return "\(String(chars[0..<8]))-\(String(chars[8..<12]))-\(String(chars[12..<16]))-\(String(chars[16..<20]))-\(String(chars[20..<32]))"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,10 @@ struct ServicePointListView: View {
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(formatUuidWithDashes(ns.uuid))
|
Text(ns.uuid.uuidWithDashes)
|
||||||
.font(.system(.caption, design: .monospaced))
|
.font(.system(.caption, design: .monospaced))
|
||||||
Button {
|
Button {
|
||||||
UIPasteboard.general.string = formatUuidWithDashes(ns.uuid)
|
UIPasteboard.general.string = ns.uuid.uuidWithDashes
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "doc.on.doc")
|
Image(systemName: "doc.on.doc")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
|
|
@ -217,7 +217,7 @@ struct ServicePointListView: View {
|
||||||
HStack {
|
HStack {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("UUID").font(.caption2).foregroundColor(.secondary)
|
Text("UUID").font(.caption2).foregroundColor(.secondary)
|
||||||
Text(formatUuidWithDashes(ns.uuid))
|
Text(ns.uuid.uuidWithDashes)
|
||||||
.font(.system(.caption2, design: .monospaced))
|
.font(.system(.caption2, design: .monospaced))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -333,11 +333,6 @@ struct ServicePointListView: View {
|
||||||
return maxNumber + 1
|
return maxNumber + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
private func formatUuidWithDashes(_ raw: String) -> String {
|
// UUID formatting now handled by String.uuidWithDashes (UUIDFormatting.swift)
|
||||||
let clean = raw.replacingOccurrences(of: "-", with: "").uppercased()
|
|
||||||
guard clean.count == 32 else { return raw }
|
|
||||||
let chars = Array(clean)
|
|
||||||
return "\(String(chars[0..<8]))-\(String(chars[8..<12]))-\(String(chars[12..<16]))-\(String(chars[16..<20]))-\(String(chars[20..<32]))"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
27
PayfritBeacon/UUIDFormatting.swift
Normal file
27
PayfritBeacon/UUIDFormatting.swift
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// MARK: - UUID Formatting Utilities
|
||||||
|
// Consolidated UUID normalization and formatting logic.
|
||||||
|
// Previously duplicated across Api.swift, BeaconScanner.swift, ScanView.swift,
|
||||||
|
// ServicePointListView.swift, and BeaconBanList.swift.
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
|
||||||
|
/// Normalize a UUID string: strip dashes, uppercase.
|
||||||
|
/// Input: "e2c56db5-dffb-48d2-b060-d0f5a71096e0" or "E2C56DB5DFFB48D2B060D0F5A71096E0"
|
||||||
|
/// Output: "E2C56DB5DFFB48D2B060D0F5A71096E0"
|
||||||
|
var normalizedUUID: String {
|
||||||
|
replacingOccurrences(of: "-", with: "").uppercased()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format a 32-char hex string into standard UUID format (8-4-4-4-12).
|
||||||
|
/// Input: "E2C56DB5DFFB48D2B060D0F5A71096E0"
|
||||||
|
/// Output: "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"
|
||||||
|
/// Returns the original string unchanged if it's not exactly 32 hex chars after normalization.
|
||||||
|
var uuidWithDashes: String {
|
||||||
|
let clean = normalizedUUID
|
||||||
|
guard clean.count == 32 else { return self }
|
||||||
|
let c = Array(clean)
|
||||||
|
return "\(String(c[0..<8]))-\(String(c[8..<12]))-\(String(c[12..<16]))-\(String(c[16..<20]))-\(String(c[20..<32]))"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue