Compare commits
No commits in common. "4618df919140633b2e3a2fee8ba70a1b865b9710" and "9ddb9ebe1b9d5b20ff7a2dec53747140583c121d" have entirely different histories.
4618df9191
...
9ddb9ebe1b
3 changed files with 32 additions and 166 deletions
|
|
@ -141,43 +141,6 @@ class Api {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a single business by ID
|
|
||||||
func getBusiness(businessId: Int) async throws -> Business? {
|
|
||||||
let json = try await postRequest(
|
|
||||||
endpoint: "/businesses/get.php",
|
|
||||||
body: ["BusinessID": businessId],
|
|
||||||
extraHeaders: ["X-Business-Id": String(businessId)]
|
|
||||||
)
|
|
||||||
|
|
||||||
guard parseBool(json["OK"] ?? json["ok"]) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let b = (json["BUSINESS"] ?? json["business"]) as? [String: Any],
|
|
||||||
let id = parseIntValue(b["BusinessID"] ?? b["BUSINESSID"]) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = ((b["BusinessName"] ?? b["BUSINESSNAME"] ?? b["Name"] ?? b["NAME"]) as? String) ?? ""
|
|
||||||
let headerImageExtension = (b["HeaderImageExtension"] ?? b["HEADERIMAGEEXTENSION"]) as? String
|
|
||||||
return Business(businessId: id, name: name, headerImageExtension: headerImageExtension)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Business name cache (matches Android's caching behavior)
|
|
||||||
private var businessNameCache: [Int: String] = [:]
|
|
||||||
|
|
||||||
/// Get business name with caching (avoids repeated API calls)
|
|
||||||
func getBusinessName(businessId: Int) async throws -> String {
|
|
||||||
if let cached = businessNameCache[businessId] {
|
|
||||||
return cached
|
|
||||||
}
|
|
||||||
if let business = try await getBusiness(businessId: businessId) {
|
|
||||||
businessNameCache[business.businessId] = business.name
|
|
||||||
return business.name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// BEACONS
|
// BEACONS
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
@ -448,7 +411,7 @@ class Api {
|
||||||
)
|
)
|
||||||
|
|
||||||
// Debug log
|
// Debug log
|
||||||
DebugLog.shared.log("[API] allocateBusinessNamespace response: \(json)")
|
print("[API] allocateBusinessNamespace response: \(json)")
|
||||||
|
|
||||||
if !parseBool(json["OK"] ?? json["ok"]) {
|
if !parseBool(json["OK"] ?? json["ok"]) {
|
||||||
let error = ((json["ERROR"] ?? json["error"]) as? String) ?? "Failed to allocate namespace"
|
let error = ((json["ERROR"] ?? json["error"]) as? String) ?? "Failed to allocate namespace"
|
||||||
|
|
@ -473,28 +436,6 @@ class Api {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a minor value for a service point (auto-assigns next available minor)
|
|
||||||
func allocateServicePointMinor(businessId: Int, servicePointId: Int) async throws -> UInt16 {
|
|
||||||
let json = try await postRequest(
|
|
||||||
endpoint: "/beacon-sharding/allocate_servicepoint_minor.php",
|
|
||||||
body: ["BusinessID": businessId, "ServicePointID": servicePointId],
|
|
||||||
extraHeaders: ["X-Business-Id": String(businessId)]
|
|
||||||
)
|
|
||||||
|
|
||||||
DebugLog.shared.log("[API] allocateServicePointMinor response: \(json)")
|
|
||||||
|
|
||||||
if !parseBool(json["OK"] ?? json["ok"]) {
|
|
||||||
let error = ((json["ERROR"] ?? json["error"]) as? String) ?? "Failed to allocate minor"
|
|
||||||
throw ApiException(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let minor = parseIntValue(json["MINOR"] ?? json["minor"] ?? json["Minor"] ?? json["BeaconMinor"] ?? json["BEACONMINOR"]) else {
|
|
||||||
throw ApiException("Invalid response - no Minor value")
|
|
||||||
}
|
|
||||||
|
|
||||||
return UInt16(minor)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// List service points for a business (for beacon assignment)
|
/// List service points for a business (for beacon assignment)
|
||||||
func listServicePoints(businessId: Int) async throws -> [ServicePoint] {
|
func listServicePoints(businessId: Int) async throws -> [ServicePoint] {
|
||||||
let json = try await postRequest(
|
let json = try await postRequest(
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,10 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import CoreBluetooth
|
import CoreBluetooth
|
||||||
|
|
||||||
/// Structured provisioning error codes (matches Android's BeaconConfig error codes)
|
|
||||||
enum ProvisioningError: String, LocalizedError {
|
|
||||||
case bluetoothUnavailable = "BLUETOOTH_UNAVAILABLE"
|
|
||||||
case connectionFailed = "CONNECTION_FAILED"
|
|
||||||
case connectionTimeout = "CONNECTION_TIMEOUT"
|
|
||||||
case serviceNotFound = "SERVICE_NOT_FOUND"
|
|
||||||
case authFailed = "AUTH_FAILED"
|
|
||||||
case writeFailed = "WRITE_FAILED"
|
|
||||||
case verificationFailed = "VERIFICATION_FAILED"
|
|
||||||
case disconnected = "DISCONNECTED"
|
|
||||||
case noConfig = "NO_CONFIG"
|
|
||||||
case timeout = "TIMEOUT"
|
|
||||||
case unknown = "UNKNOWN"
|
|
||||||
|
|
||||||
var errorDescription: String? {
|
|
||||||
switch self {
|
|
||||||
case .bluetoothUnavailable: return "Bluetooth not available"
|
|
||||||
case .connectionFailed: return "Failed to connect to beacon"
|
|
||||||
case .connectionTimeout: return "Connection timed out"
|
|
||||||
case .serviceNotFound: return "Config service not found on device"
|
|
||||||
case .authFailed: return "Authentication failed - all passwords rejected"
|
|
||||||
case .writeFailed: return "Failed to write configuration"
|
|
||||||
case .verificationFailed: return "Beacon not broadcasting expected values"
|
|
||||||
case .disconnected: return "Unexpected disconnect"
|
|
||||||
case .noConfig: return "No configuration provided"
|
|
||||||
case .timeout: return "Operation timed out"
|
|
||||||
case .unknown: return "Unknown error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Result of a provisioning operation
|
/// Result of a provisioning operation
|
||||||
enum ProvisioningResult {
|
enum ProvisioningResult {
|
||||||
case success(macAddress: String?)
|
case success(macAddress: String?)
|
||||||
case failure(String)
|
case failure(String)
|
||||||
case failureWithCode(ProvisioningError, detail: String? = nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration to write to a beacon
|
/// Configuration to write to a beacon
|
||||||
|
|
@ -96,8 +64,8 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
// DX-Smart packet header
|
// DX-Smart packet header
|
||||||
private static let DXSMART_HEADER: [UInt8] = [0x4E, 0x4F]
|
private static let DXSMART_HEADER: [UInt8] = [0x4E, 0x4F]
|
||||||
|
|
||||||
// DX-Smart connection passwords (tried in order until one works)
|
// DX-Smart connection password
|
||||||
private static let DXSMART_PASSWORDS = ["555555", "dx1234", "000000"]
|
private static let DXSMART_PASSWORD = "dx1234"
|
||||||
|
|
||||||
// DX-Smart command codes
|
// DX-Smart command codes
|
||||||
private enum DXCmd: UInt8 {
|
private enum DXCmd: UInt8 {
|
||||||
|
|
@ -195,7 +163,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
/// Provision a beacon with the given configuration
|
/// Provision a beacon with the given configuration
|
||||||
func provision(beacon: DiscoveredBeacon, config: BeaconConfig, completion: @escaping (ProvisioningResult) -> Void) {
|
func provision(beacon: DiscoveredBeacon, config: BeaconConfig, completion: @escaping (ProvisioningResult) -> Void) {
|
||||||
guard centralManager.state == .poweredOn else {
|
guard centralManager.state == .poweredOn else {
|
||||||
completion(.failureWithCode(.bluetoothUnavailable))
|
completion(.failure("Bluetooth not available"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,7 +193,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
// Timeout after 30 seconds
|
// Timeout after 30 seconds
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 30) { [weak self] in
|
DispatchQueue.main.asyncAfter(deadline: .now() + 30) { [weak self] in
|
||||||
if self?.state != .success && self?.state != .idle {
|
if self?.state != .success && self?.state != .idle {
|
||||||
self?.fail("Connection timeout", code: .connectionTimeout)
|
self?.fail("Connection timeout")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +221,6 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
self.operationMode = .readingConfig
|
self.operationMode = .readingConfig
|
||||||
self.readCompletion = completion
|
self.readCompletion = completion
|
||||||
self.readResult = BeaconCheckResult()
|
self.readResult = BeaconCheckResult()
|
||||||
self.passwordIndex = 0
|
|
||||||
self.characteristics.removeAll()
|
self.characteristics.removeAll()
|
||||||
self.dxSmartAuthenticated = false
|
self.dxSmartAuthenticated = false
|
||||||
self.dxSmartNotifySubscribed = false
|
self.dxSmartNotifySubscribed = false
|
||||||
|
|
@ -301,17 +268,13 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
progress = ""
|
progress = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fail(_ message: String, code: ProvisioningError? = nil) {
|
private func fail(_ message: String) {
|
||||||
DebugLog.shared.log("BLE: Failed [\(code?.rawValue ?? "UNTYPED")] - \(message)")
|
DebugLog.shared.log("BLE: Failed - \(message)")
|
||||||
state = .failed(message)
|
state = .failed(message)
|
||||||
if let peripheral = peripheral {
|
if let peripheral = peripheral {
|
||||||
centralManager.cancelPeripheralConnection(peripheral)
|
centralManager.cancelPeripheralConnection(peripheral)
|
||||||
}
|
}
|
||||||
if let code = code {
|
|
||||||
completion?(.failureWithCode(code, detail: message))
|
|
||||||
} else {
|
|
||||||
completion?(.failure(message))
|
completion?(.failure(message))
|
||||||
}
|
|
||||||
cleanup()
|
cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,7 +293,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
|
|
||||||
private func provisionDXSmart() {
|
private func provisionDXSmart() {
|
||||||
guard let service = configService else {
|
guard let service = configService else {
|
||||||
fail("DX-Smart config service not found", code: .serviceNotFound)
|
fail("DX-Smart config service not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -356,40 +319,21 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write password to FFE3 (tries multiple passwords in sequence)
|
/// Write password to FFE3
|
||||||
private func dxSmartAuthenticate() {
|
private func dxSmartAuthenticate() {
|
||||||
guard let passwordChar = characteristics[BeaconProvisioner.DXSMART_PASSWORD_CHAR] else {
|
guard let passwordChar = characteristics[BeaconProvisioner.DXSMART_PASSWORD_CHAR] else {
|
||||||
fail("DX-Smart password characteristic (FFE3) not found", code: .serviceNotFound)
|
fail("DX-Smart password characteristic (FFE3) not found")
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard passwordIndex < BeaconProvisioner.DXSMART_PASSWORDS.count else {
|
|
||||||
fail("Authentication failed - all passwords rejected", code: .authFailed)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
state = .authenticating
|
state = .authenticating
|
||||||
let currentPassword = BeaconProvisioner.DXSMART_PASSWORDS[passwordIndex]
|
progress = "Authenticating..."
|
||||||
progress = "Authenticating (attempt \(passwordIndex + 1)/\(BeaconProvisioner.DXSMART_PASSWORDS.count))..."
|
|
||||||
|
|
||||||
let passwordData = Data(currentPassword.utf8)
|
let passwordData = Data(BeaconProvisioner.DXSMART_PASSWORD.utf8)
|
||||||
DebugLog.shared.log("BLE: Writing password \(passwordIndex + 1)/\(BeaconProvisioner.DXSMART_PASSWORDS.count) to FFE3 (\(passwordData.count) bytes)")
|
DebugLog.shared.log("BLE: Writing password to FFE3 (\(passwordData.count) bytes)")
|
||||||
peripheral?.writeValue(passwordData, for: passwordChar, type: .withResponse)
|
peripheral?.writeValue(passwordData, for: passwordChar, type: .withResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a password attempt fails — tries the next one
|
|
||||||
private func dxSmartRetryNextPassword() {
|
|
||||||
passwordIndex += 1
|
|
||||||
if passwordIndex < BeaconProvisioner.DXSMART_PASSWORDS.count {
|
|
||||||
DebugLog.shared.log("BLE: Password rejected, trying next (\(passwordIndex + 1)/\(BeaconProvisioner.DXSMART_PASSWORDS.count))")
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
|
|
||||||
self?.dxSmartAuthenticate()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fail("Authentication failed - all \(BeaconProvisioner.DXSMART_PASSWORDS.count) passwords rejected", code: .authFailed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read device info (MAC address) before writing config
|
/// Read device info (MAC address) before writing config
|
||||||
private func dxSmartReadDeviceInfoBeforeWrite() {
|
private func dxSmartReadDeviceInfoBeforeWrite() {
|
||||||
guard let commandChar = characteristics[BeaconProvisioner.DXSMART_COMMAND_CHAR] else {
|
guard let commandChar = characteristics[BeaconProvisioner.DXSMART_COMMAND_CHAR] else {
|
||||||
|
|
@ -437,7 +381,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
/// 24. SaveConfig 0x60 — persist to flash
|
/// 24. SaveConfig 0x60 — persist to flash
|
||||||
private func dxSmartWriteConfig() {
|
private func dxSmartWriteConfig() {
|
||||||
guard let config = config else {
|
guard let config = config else {
|
||||||
fail("No config provided", code: .noConfig)
|
fail("No config provided")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -535,7 +479,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
progress = "Writing config (\(current)/\(total))..."
|
progress = "Writing config (\(current)/\(total))..."
|
||||||
|
|
||||||
guard let commandChar = characteristics[BeaconProvisioner.DXSMART_COMMAND_CHAR] else {
|
guard let commandChar = characteristics[BeaconProvisioner.DXSMART_COMMAND_CHAR] else {
|
||||||
fail("DX-Smart command characteristic (FFE2) not found", code: .serviceNotFound)
|
fail("DX-Smart command characteristic (FFE2) not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -624,7 +568,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Authenticate on FFE3 for read mode (uses same multi-password fallback)
|
/// Authenticate on FFE3 for read mode
|
||||||
private func dxSmartReadAuth() {
|
private func dxSmartReadAuth() {
|
||||||
guard let passwordChar = characteristics[BeaconProvisioner.DXSMART_PASSWORD_CHAR] else {
|
guard let passwordChar = characteristics[BeaconProvisioner.DXSMART_PASSWORD_CHAR] else {
|
||||||
DebugLog.shared.log("BLE: No FFE3 for auth, finishing")
|
DebugLog.shared.log("BLE: No FFE3 for auth, finishing")
|
||||||
|
|
@ -632,18 +576,11 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard passwordIndex < BeaconProvisioner.DXSMART_PASSWORDS.count else {
|
|
||||||
DebugLog.shared.log("BLE: All passwords exhausted in read mode")
|
|
||||||
finishRead()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
state = .authenticating
|
state = .authenticating
|
||||||
let currentPassword = BeaconProvisioner.DXSMART_PASSWORDS[passwordIndex]
|
progress = "Authenticating..."
|
||||||
progress = "Authenticating (attempt \(passwordIndex + 1)/\(BeaconProvisioner.DXSMART_PASSWORDS.count))..."
|
|
||||||
|
|
||||||
let passwordData = Data(currentPassword.utf8)
|
let passwordData = Data(BeaconProvisioner.DXSMART_PASSWORD.utf8)
|
||||||
DebugLog.shared.log("BLE: Read mode — writing password \(passwordIndex + 1)/\(BeaconProvisioner.DXSMART_PASSWORDS.count) to FFE3")
|
DebugLog.shared.log("BLE: Read mode — writing password to FFE3")
|
||||||
peripheral?.writeValue(passwordData, for: passwordChar, type: .withResponse)
|
peripheral?.writeValue(passwordData, for: passwordChar, type: .withResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -960,7 +897,7 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
|
||||||
if operationMode == .readingConfig {
|
if operationMode == .readingConfig {
|
||||||
readFail(msg)
|
readFail(msg)
|
||||||
} else {
|
} else {
|
||||||
fail(msg, code: .connectionFailed)
|
fail(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -975,7 +912,7 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
|
||||||
if case .failed = state {
|
if case .failed = state {
|
||||||
// Already failed
|
// Already failed
|
||||||
} else {
|
} else {
|
||||||
fail("Unexpected disconnect", code: .disconnected)
|
fail("Unexpected disconnect")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -990,7 +927,7 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
if operationMode == .readingConfig {
|
if operationMode == .readingConfig {
|
||||||
readFail("Service discovery failed: \(error.localizedDescription)")
|
readFail("Service discovery failed: \(error.localizedDescription)")
|
||||||
} else {
|
} else {
|
||||||
fail("Service discovery failed: \(error.localizedDescription)", code: .serviceNotFound)
|
fail("Service discovery failed: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -999,7 +936,7 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
if operationMode == .readingConfig {
|
if operationMode == .readingConfig {
|
||||||
readFail("No services found")
|
readFail("No services found")
|
||||||
} else {
|
} else {
|
||||||
fail("No services found", code: .serviceNotFound)
|
fail("No services found")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1022,7 +959,7 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fail("Config service not found on device", code: .serviceNotFound)
|
fail("Config service not found on device")
|
||||||
}
|
}
|
||||||
|
|
||||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
|
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
|
||||||
|
|
@ -1032,7 +969,7 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
DebugLog.shared.log("BLE: Char discovery failed for \(service.uuid): \(error.localizedDescription)")
|
DebugLog.shared.log("BLE: Char discovery failed for \(service.uuid): \(error.localizedDescription)")
|
||||||
exploreNextService()
|
exploreNextService()
|
||||||
} else {
|
} else {
|
||||||
fail("Characteristic discovery failed: \(error.localizedDescription)", code: .serviceNotFound)
|
fail("Characteristic discovery failed: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1041,7 +978,7 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
if operationMode == .readingConfig {
|
if operationMode == .readingConfig {
|
||||||
exploreNextService()
|
exploreNextService()
|
||||||
} else {
|
} else {
|
||||||
fail("No characteristics found", code: .serviceNotFound)
|
fail("No characteristics found")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1078,14 +1015,10 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
DebugLog.shared.log("BLE: Write failed for \(characteristic.uuid): \(error.localizedDescription)")
|
DebugLog.shared.log("BLE: Write failed for \(characteristic.uuid): \(error.localizedDescription)")
|
||||||
|
|
||||||
if characteristic.uuid == BeaconProvisioner.DXSMART_PASSWORD_CHAR {
|
if characteristic.uuid == BeaconProvisioner.DXSMART_PASSWORD_CHAR {
|
||||||
// Password rejected — try next password in the list
|
if operationMode == .readingConfig {
|
||||||
if passwordIndex + 1 < BeaconProvisioner.DXSMART_PASSWORDS.count {
|
readFail("Authentication failed: \(error.localizedDescription)")
|
||||||
DebugLog.shared.log("BLE: Password \(passwordIndex + 1) rejected, trying next...")
|
|
||||||
dxSmartRetryNextPassword()
|
|
||||||
} else if operationMode == .readingConfig {
|
|
||||||
readFail("Authentication failed - all passwords rejected")
|
|
||||||
} else {
|
} else {
|
||||||
fail("Authentication failed - all \(BeaconProvisioner.DXSMART_PASSWORDS.count) passwords rejected", code: .authFailed)
|
fail("Authentication failed: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1108,7 +1041,7 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
self?.dxSmartSendNextCommand()
|
self?.dxSmartSendNextCommand()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fail("Command write failed at step \(dxSmartWriteIndex + 1): \(error.localizedDescription)", code: .writeFailed)
|
fail("Command write failed at step \(dxSmartWriteIndex + 1): \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
@ -1118,7 +1051,7 @@ extension BeaconProvisioner: CBPeripheralDelegate {
|
||||||
DebugLog.shared.log("BLE: Write failed in read mode, ignoring: \(error.localizedDescription)")
|
DebugLog.shared.log("BLE: Write failed in read mode, ignoring: \(error.localizedDescription)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fail("Write failed: \(error.localizedDescription)", code: .writeFailed)
|
fail("Write failed: \(error.localizedDescription)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -913,10 +913,6 @@ struct ScanView: View {
|
||||||
}
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
failProvisioning(error)
|
failProvisioning(error)
|
||||||
case .failureWithCode(let code, let detail):
|
|
||||||
let msg = detail ?? code.errorDescription ?? code.rawValue
|
|
||||||
DebugLog.shared.log("[ScanView] Provisioning failed [\(code.rawValue)]: \(msg)")
|
|
||||||
failProvisioning(msg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1000,10 +996,6 @@ struct ScanView: View {
|
||||||
}
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
failProvisioning(error)
|
failProvisioning(error)
|
||||||
case .failureWithCode(let code, let detail):
|
|
||||||
let msg = detail ?? code.errorDescription ?? code.rawValue
|
|
||||||
DebugLog.shared.log("[ScanView] Provisioning failed [\(code.rawValue)]: \(msg)")
|
|
||||||
failProvisioning(msg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue