ilabs-flir 2.2.6 → 2.2.8
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.
|
@@ -361,13 +361,19 @@ import ThermalSDK
|
|
|
361
361
|
FlirLogger.log(.discovery, "Starting discovery...")
|
|
362
362
|
|
|
363
363
|
#if FLIR_ENABLED
|
|
364
|
+
// Guard: prevent re-entry if already scanning
|
|
364
365
|
if isScanning {
|
|
365
|
-
FlirLogger.log(.discovery, "
|
|
366
|
+
FlirLogger.log(.discovery, "⚠️ Discovery already in progress - ignoring duplicate startDiscovery call")
|
|
366
367
|
return
|
|
367
368
|
}
|
|
368
369
|
|
|
370
|
+
// Cancel any previous timeout and reset state
|
|
371
|
+
discoveryTimeoutWorkItem?.cancel()
|
|
372
|
+
discoveryTimeoutWorkItem = nil
|
|
373
|
+
|
|
369
374
|
isScanning = true
|
|
370
375
|
discoveredDevices.removeAll()
|
|
376
|
+
identityMap.removeAll()
|
|
371
377
|
|
|
372
378
|
if discovery == nil {
|
|
373
379
|
discovery = FLIRDiscovery()
|
|
@@ -459,6 +465,16 @@ import ThermalSDK
|
|
|
459
465
|
discoveryTimeoutWorkItem = nil
|
|
460
466
|
discovery?.stop()
|
|
461
467
|
isScanning = false
|
|
468
|
+
|
|
469
|
+
// Emit final device list to RN so UI updates properly
|
|
470
|
+
DispatchQueue.main.async { [weak self] in
|
|
471
|
+
guard let self = self else { return }
|
|
472
|
+
self.delegate?.onDevicesFound(self.discoveredDevices)
|
|
473
|
+
if self.discoveredDevices.isEmpty {
|
|
474
|
+
self.emitStateChange("no_device_found")
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
462
478
|
FlirLogger.log(.discovery, "Discovery stopped")
|
|
463
479
|
#endif
|
|
464
480
|
}
|
|
@@ -469,19 +485,56 @@ import ThermalSDK
|
|
|
469
485
|
FlirLogger.logConnectionAttempt(deviceId: deviceId)
|
|
470
486
|
|
|
471
487
|
#if FLIR_ENABLED
|
|
488
|
+
// Guard: if already connected, disconnect first
|
|
489
|
+
if _isConnected {
|
|
490
|
+
FlirLogger.log(.connection, "⚠️ Already connected - disconnecting first...")
|
|
491
|
+
disconnect()
|
|
492
|
+
// Give disconnect a moment to complete
|
|
493
|
+
Thread.sleep(forTimeInterval: 0.5)
|
|
494
|
+
}
|
|
495
|
+
|
|
472
496
|
// Find the identity for this device
|
|
473
497
|
guard let identity = findIdentity(for: deviceId) else {
|
|
474
498
|
FlirLogger.logError(.connection, "Device not found in identity map: \(deviceId)")
|
|
475
|
-
|
|
499
|
+
DispatchQueue.main.async { [weak self] in
|
|
500
|
+
self?.emitStateChange("connection_failed")
|
|
501
|
+
self?.delegate?.onError("Device not found: \(deviceId)")
|
|
502
|
+
}
|
|
476
503
|
return
|
|
477
504
|
}
|
|
478
505
|
|
|
479
|
-
|
|
506
|
+
// Run connection on background thread with overall timeout
|
|
507
|
+
let timeoutSeconds: Double = 15.0
|
|
508
|
+
var connectionCompleted = false
|
|
509
|
+
let connectionQueue = DispatchQueue.global(qos: .userInitiated)
|
|
510
|
+
|
|
511
|
+
// Start connection attempt
|
|
512
|
+
connectionQueue.async { [weak self] in
|
|
480
513
|
self?.performConnection(identity: identity)
|
|
514
|
+
connectionCompleted = true
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Monitor for timeout
|
|
518
|
+
DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + timeoutSeconds) { [weak self] in
|
|
519
|
+
guard let self = self, !connectionCompleted else { return }
|
|
520
|
+
|
|
521
|
+
FlirLogger.logError(.connection, "⏱ Connection timeout after \(timeoutSeconds) seconds - aborting")
|
|
522
|
+
|
|
523
|
+
// Force cleanup
|
|
524
|
+
self.camera = nil
|
|
525
|
+
self._isConnected = false
|
|
526
|
+
self.connectedDeviceId = nil
|
|
527
|
+
|
|
528
|
+
DispatchQueue.main.async {
|
|
529
|
+
self.emitStateChange("connection_failed")
|
|
530
|
+
self.delegate?.onError("Connection timeout - device not responding")
|
|
531
|
+
}
|
|
481
532
|
}
|
|
482
533
|
#else
|
|
483
534
|
FlirLogger.logError(.connection, "FLIR SDK not available")
|
|
484
|
-
|
|
535
|
+
DispatchQueue.main.async { [weak self] in
|
|
536
|
+
self?.delegate?.onError("FLIR SDK not available")
|
|
537
|
+
}
|
|
485
538
|
#endif
|
|
486
539
|
}
|
|
487
540
|
|
|
@@ -514,13 +567,26 @@ import ThermalSDK
|
|
|
514
567
|
FlirLogger.log(.connection, "Generic/network camera - starting authentication...")
|
|
515
568
|
let certName = getCertificateName()
|
|
516
569
|
var status = FLIRAuthenticationStatus.pending
|
|
517
|
-
|
|
570
|
+
var attempts = 0
|
|
571
|
+
let maxAttempts = 10 // 10 seconds max
|
|
572
|
+
|
|
573
|
+
while status == .pending && attempts < maxAttempts {
|
|
518
574
|
status = cam.authenticate(identity, trustedConnectionName: certName)
|
|
519
575
|
if status == .pending {
|
|
520
|
-
FlirLogger.log(.connection, "Waiting for camera authentication approval...")
|
|
576
|
+
FlirLogger.log(.connection, "Waiting for camera authentication approval... (\(attempts + 1)/\(maxAttempts))")
|
|
521
577
|
Thread.sleep(forTimeInterval: 1.0)
|
|
578
|
+
attempts += 1
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
if status == .pending {
|
|
583
|
+
FlirLogger.logError(.connection, "Authentication timeout after \(maxAttempts) seconds")
|
|
584
|
+
DispatchQueue.main.async { [weak self] in
|
|
585
|
+
self?.delegate?.onError("Camera authentication timeout - device may require approval")
|
|
522
586
|
}
|
|
587
|
+
return
|
|
523
588
|
}
|
|
589
|
+
|
|
524
590
|
FlirLogger.log(.connection, "Authentication status: \(status.rawValue)")
|
|
525
591
|
}
|
|
526
592
|
|
|
@@ -532,6 +598,7 @@ import ThermalSDK
|
|
|
532
598
|
FlirLogger.log(.connection, "✅ Paired successfully with: \(identity.deviceId())")
|
|
533
599
|
|
|
534
600
|
// Step 2: Connect (no identity parameter - uses paired identity)
|
|
601
|
+
// Note: This can hang on some devices - ensure we have timeout in place
|
|
535
602
|
FlirLogger.log(.connection, "Step 2: Connecting to device...")
|
|
536
603
|
try cam.connect()
|
|
537
604
|
FlirLogger.log(.connection, "✅ Connected successfully to: \(identity.deviceId())")
|
|
@@ -586,8 +653,14 @@ import ThermalSDK
|
|
|
586
653
|
} catch {
|
|
587
654
|
FlirLogger.logError(.connection, "Connection failed", error: error)
|
|
588
655
|
_isConnected = false
|
|
656
|
+
_isStreaming = false
|
|
657
|
+
connectedDeviceId = nil
|
|
658
|
+
connectedDeviceName = nil
|
|
589
659
|
camera = nil
|
|
660
|
+
|
|
661
|
+
// CRITICAL: Always emit error state to RN so UI doesn't hang waiting
|
|
590
662
|
DispatchQueue.main.async { [weak self] in
|
|
663
|
+
self?.emitStateChange("connection_failed")
|
|
591
664
|
self?.delegate?.onError("Connection failed: \(error.localizedDescription)")
|
|
592
665
|
}
|
|
593
666
|
}
|