ilabs-flir 2.2.9 → 2.2.11
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.
- package/ios/Flir/src/FlirManager.swift +53 -57
- package/package.json +1 -1
|
@@ -481,16 +481,31 @@ import ThermalSDK
|
|
|
481
481
|
|
|
482
482
|
// MARK: - Connection
|
|
483
483
|
|
|
484
|
+
// Flag to prevent re-entrant connections
|
|
485
|
+
private var isConnecting = false
|
|
486
|
+
|
|
484
487
|
@objc public func connectToDevice(_ deviceId: String) {
|
|
485
488
|
FlirLogger.logConnectionAttempt(deviceId: deviceId)
|
|
486
489
|
|
|
487
490
|
#if FLIR_ENABLED
|
|
488
|
-
// Guard: if already
|
|
489
|
-
|
|
490
|
-
FlirLogger.log(.connection, "⚠️
|
|
491
|
+
// Guard: if already connecting, skip (like demo app's guard pattern)
|
|
492
|
+
guard !isConnecting else {
|
|
493
|
+
FlirLogger.log(.connection, "⚠️ Connection already in progress - skipping")
|
|
494
|
+
return
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Guard: if already connected to this device, skip (matches demo app)
|
|
498
|
+
if _isConnected && connectedDeviceId == deviceId {
|
|
499
|
+
FlirLogger.log(.connection, "⚠️ Already connected to this device - skipping")
|
|
500
|
+
return
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// If connected to a different device, disconnect first but DON'T block
|
|
504
|
+
if _isConnected && connectedDeviceId != deviceId {
|
|
505
|
+
FlirLogger.log(.connection, "⚠️ Connected to different device - disconnecting first...")
|
|
491
506
|
disconnect()
|
|
492
|
-
//
|
|
493
|
-
|
|
507
|
+
// Don't block! The new connection will proceed immediately
|
|
508
|
+
// The disconnect is async and will complete in the background
|
|
494
509
|
}
|
|
495
510
|
|
|
496
511
|
// Find the identity for this device
|
|
@@ -503,33 +518,14 @@ import ThermalSDK
|
|
|
503
518
|
return
|
|
504
519
|
}
|
|
505
520
|
|
|
506
|
-
|
|
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
|
|
513
|
-
self?.performConnection(identity: identity)
|
|
514
|
-
connectionCompleted = true
|
|
515
|
-
}
|
|
521
|
+
isConnecting = true
|
|
516
522
|
|
|
517
|
-
//
|
|
518
|
-
DispatchQueue.global(
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
// Force cleanup
|
|
524
|
-
self.camera = nil
|
|
525
|
-
self._isConnected = false
|
|
526
|
-
self.connectedDeviceId = nil
|
|
527
|
-
|
|
528
|
-
DispatchQueue.main.async {
|
|
529
|
-
FlirLogger.log(.connection, "⏱ Emitting connection_failed to RN due to timeout")
|
|
530
|
-
self.emitStateChange("connection_failed")
|
|
531
|
-
self.delegate?.onError("Connection timeout - device not responding")
|
|
532
|
-
}
|
|
523
|
+
// Run connection on background thread - simple pattern matching demo app
|
|
524
|
+
// Demo app uses: DispatchQueue.global().async { try pair(); try connect(); try stream.start() }
|
|
525
|
+
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
526
|
+
guard let self = self else { return }
|
|
527
|
+
self.performConnection(identity: identity)
|
|
528
|
+
self.isConnecting = false
|
|
533
529
|
}
|
|
534
530
|
#else
|
|
535
531
|
FlirLogger.logError(.connection, "FLIR SDK not available")
|
|
@@ -538,6 +534,7 @@ import ThermalSDK
|
|
|
538
534
|
}
|
|
539
535
|
#endif
|
|
540
536
|
}
|
|
537
|
+
|
|
541
538
|
|
|
542
539
|
#if FLIR_ENABLED
|
|
543
540
|
private func findIdentity(for deviceId: String) -> FLIRIdentity? {
|
|
@@ -566,34 +563,18 @@ import ThermalSDK
|
|
|
566
563
|
}
|
|
567
564
|
|
|
568
565
|
// Handle authentication for generic cameras (network cameras)
|
|
566
|
+
// Note: This uses a single attempt since the SDK doesn't provide async callback
|
|
569
567
|
if identity.cameraType() == .generic {
|
|
570
|
-
FlirLogger.log(.connection, "
|
|
568
|
+
FlirLogger.log(.connection, "Generic/network camera - attempting authentication...")
|
|
571
569
|
let certName = getCertificateName()
|
|
572
|
-
|
|
573
|
-
var attempts = 0
|
|
574
|
-
let maxAttempts = 10 // 10 seconds max
|
|
575
|
-
let authStartTime = Date()
|
|
570
|
+
let status = cam.authenticate(identity, trustedConnectionName: certName)
|
|
576
571
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
FlirLogger.log(.connection, "Waiting for camera authentication approval... (\(attempts + 1)/\(maxAttempts))")
|
|
581
|
-
Thread.sleep(forTimeInterval: 1.0)
|
|
582
|
-
attempts += 1
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
if status == .pending {
|
|
587
|
-
let authDuration = Date().timeIntervalSince(authStartTime)
|
|
588
|
-
FlirLogger.logError(.connection, "❌ Authentication TIMEOUT after \(authDuration)s (\(maxAttempts) attempts)")
|
|
589
|
-
DispatchQueue.main.async { [weak self] in
|
|
590
|
-
self?.delegate?.onError("Camera authentication timeout - device may require approval")
|
|
591
|
-
}
|
|
592
|
-
return
|
|
593
|
-
}
|
|
572
|
+
// Log the status - don't block on pending, just proceed
|
|
573
|
+
// The connect() call will fail appropriately if auth is truly required
|
|
574
|
+
FlirLogger.log(.connection, "Authentication status: \(status.rawValue)")
|
|
594
575
|
|
|
595
|
-
|
|
596
|
-
|
|
576
|
+
// Only fail on explicit rejection (status values vary by SDK version)
|
|
577
|
+
// Pending status means we should try to connect anyway
|
|
597
578
|
}
|
|
598
579
|
|
|
599
580
|
do {
|
|
@@ -708,9 +689,15 @@ import ThermalSDK
|
|
|
708
689
|
}
|
|
709
690
|
|
|
710
691
|
@objc public func stopStream() {
|
|
692
|
+
#if FLIR_ENABLED
|
|
693
|
+
// Guard: if not streaming, skip to avoid redundant operations
|
|
694
|
+
guard _isStreaming || stream != nil else {
|
|
695
|
+
FlirLogger.log(.streaming, "Not streaming - skipping stopStream")
|
|
696
|
+
return
|
|
697
|
+
}
|
|
698
|
+
|
|
711
699
|
FlirLogger.log(.streaming, "Stopping stream...")
|
|
712
700
|
|
|
713
|
-
#if FLIR_ENABLED
|
|
714
701
|
stream?.stop()
|
|
715
702
|
stream = nil
|
|
716
703
|
streamer = nil
|
|
@@ -743,6 +730,9 @@ import ThermalSDK
|
|
|
743
730
|
FlirLogger.logError(.streaming, "Stream start failed", error: error)
|
|
744
731
|
stream = nil
|
|
745
732
|
streamer = nil
|
|
733
|
+
_isStreaming = false
|
|
734
|
+
// Emit state change so RN knows streaming failed
|
|
735
|
+
emitStateChange("connected") // Fall back to connected (not streaming)
|
|
746
736
|
delegate?.onError("Stream start failed: \(error.localizedDescription)")
|
|
747
737
|
}
|
|
748
738
|
}
|
|
@@ -751,9 +741,15 @@ import ThermalSDK
|
|
|
751
741
|
// MARK: - Disconnect
|
|
752
742
|
|
|
753
743
|
@objc public func disconnect() {
|
|
744
|
+
#if FLIR_ENABLED
|
|
745
|
+
// Guard: if already disconnected, do nothing (prevents re-entrant issues)
|
|
746
|
+
guard _isConnected || stream != nil || camera != nil else {
|
|
747
|
+
FlirLogger.log(.disconnect, "Already disconnected - skipping")
|
|
748
|
+
return
|
|
749
|
+
}
|
|
750
|
+
|
|
754
751
|
FlirLogger.log(.disconnect, "Disconnecting...")
|
|
755
752
|
|
|
756
|
-
#if FLIR_ENABLED
|
|
757
753
|
// Stop battery polling
|
|
758
754
|
stopBatteryPolling()
|
|
759
755
|
|