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, "Already scanning - skipping")
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
- delegate?.onError("Device not found: \(deviceId)")
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
- DispatchQueue.global(qos: .userInitiated).async { [weak self] in
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
- delegate?.onError("FLIR SDK not available")
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
- while status == .pending {
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilabs-flir",
3
- "version": "2.2.6",
3
+ "version": "2.2.8",
4
4
  "description": "FLIR Thermal SDK for React Native - iOS & Android (bundled at compile time via postinstall)",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",