ilabs-flir 2.0.8 → 2.0.9

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.
@@ -111,7 +111,7 @@ import ThermalSDK
111
111
  #if FLIR_ENABLED
112
112
  guard let streamer = streamer else { return nil }
113
113
  var result: [String: Any]? = nil
114
- streamer.withThermalImage { thermalImage in
114
+ streamer.withThermalImage { [weak self] thermalImage in
115
115
  // Attempt to extract per-pixel measurements if available
116
116
  if let measurements = thermalImage.measurements as? [NSNumber],
117
117
  measurements.count > 0,
@@ -127,8 +127,8 @@ import ThermalSDK
127
127
  }
128
128
  }
129
129
  // Fallback: use lastTemperature if set
130
- if result == nil && !lastTemperature.isNaN {
131
- result = ["temperature": lastTemperature]
130
+ if result == nil, let s = self, !s.lastTemperature.isNaN {
131
+ result = ["temperature": s.lastTemperature]
132
132
  }
133
133
  }
134
134
  return result
@@ -227,17 +227,35 @@ import ThermalSDK
227
227
  return
228
228
  }
229
229
 
230
- if let paletteManager = FLIRPaletteManager.defaultPalettes() {
231
- for palette in paletteManager {
232
- if let p = palette as? FLIRPalette, p.name.lowercased() == paletteName.lowercased() {
233
- thermalImage.palette = p
234
- NSLog("[FlirManager] Palette set to: \(paletteName)")
235
- return
230
+ // Use runtime-safe APIs to find and set palette to avoid compile-time
231
+ // coupling to specific SDK versions. Try FLIRPaletteManager.defaultPalettes
232
+ // via ObjC runtime, then attempt a KVC set on the returned image if possible.
233
+ if let pmClass = NSClassFromString("FLIRPaletteManager") as AnyObject?, pmClass.responds(to: Selector(("default"))) {
234
+ if let pmInstance = pmClass.perform(Selector(("default")))?.takeUnretainedValue() as? NSObject,
235
+ pmInstance.responds(to: Selector(("getDefaultPalettes"))) {
236
+ if let arr = pmInstance.perform(Selector(("getDefaultPalettes")))?.takeUnretainedValue() as? NSArray {
237
+ for palette in arr {
238
+ if let p = palette as? NSObject,
239
+ let name = p.value(forKey: "name") as? String,
240
+ name.lowercased() == paletteName.lowercased() {
241
+ if let imgObj = thermalImage as? NSObject {
242
+ // Try both 'palette' and 'Palette' keys depending on SDK
243
+ if imgObj.responds(to: Selector(("setPalette:"))) {
244
+ imgObj.perform(Selector(("setPalette:")), with: p)
245
+ } else {
246
+ imgObj.setValue(p, forKey: "Palette")
247
+ }
248
+ NSLog("[FlirManager] ✅ Palette set to: \(paletteName)")
249
+ return
250
+ }
251
+ }
236
252
  }
253
+ NSLog("[FlirManager] Palette not found: \(paletteName)")
254
+ } else {
255
+ NSLog("[FlirManager] Palette manager returned unexpected type")
237
256
  }
238
- NSLog("[FlirManager] Palette not found: \(paletteName)")
239
257
  } else {
240
- NSLog("[FlirManager] SDK not available - cannot set palette")
258
+ NSLog("[FlirManager] SDK palette APIs not available - cannot set palette")
241
259
  }
242
260
  #else
243
261
  NSLog("[FlirManager] SDK not available - cannot set palette")
@@ -366,15 +384,34 @@ import ThermalSDK
366
384
  }
367
385
  }
368
386
 
369
- // Connect
370
- try camera?.connect(identity)
371
-
372
- connectedIdentity = identity
373
- connectedDeviceId = identity.deviceId()
374
- connectedDeviceName = identity.deviceId()
375
- _isConnected = true
376
-
377
- NSLog("[FlirManager] Connected to: \(identity.deviceId())")
387
+ // Connect (support multiple SDK signatures via ObjC runtime)
388
+ var connectedOK = false
389
+ if let cam = camera {
390
+ if cam.responds(to: Selector(("connect:error:"))) {
391
+ // Call connect:identity error:nil (ignore NSError pointer for compatibility)
392
+ _ = cam.perform(Selector(("connect:error:")), with: identity, with: nil)
393
+ connectedOK = true
394
+ } else if cam.responds(to: Selector(("connect:"))) {
395
+ _ = cam.perform(Selector(("connect:")), with: identity)
396
+ connectedOK = true
397
+ } else {
398
+ NSLog("[FlirManager] No compatible connect API on FLIRCamera")
399
+ }
400
+ }
401
+
402
+ if connectedOK {
403
+ connectedIdentity = identity
404
+ connectedDeviceId = identity.deviceId()
405
+ connectedDeviceName = identity.deviceId()
406
+ _isConnected = true
407
+ NSLog("[FlirManager] Connected to: \(identity.deviceId())")
408
+ } else {
409
+ NSLog("[FlirManager] Connection failed: no compatible connect API")
410
+ DispatchQueue.main.async { [weak self] in
411
+ self?.delegate?.onError("Connection failed: unsupported SDK API")
412
+ }
413
+ return
414
+ }
378
415
 
379
416
  // Get streams
380
417
  if let streams = camera?.getStreams(), !streams.isEmpty {
@@ -424,7 +461,7 @@ import ThermalSDK
424
461
  if iface.contains(.network) { return "NETWORK" }
425
462
  if iface.contains(.flirOneWireless) { return "WIRELESS" }
426
463
  if iface.contains(.emulator) { return "EMULATOR" }
427
- if iface.contains(.usb) { return "USB" }
464
+ if String(describing: iface).lowercased().contains("usb") { return "USB" }
428
465
  return "UNKNOWN"
429
466
  }
430
467
  #endif
@@ -736,10 +773,23 @@ extension FlirManager: FLIRStreamDelegate {
736
773
  if let image = streamer.getImage() {
737
774
  _latestImage = image
738
775
 
739
- // Get temperature from thermal image
776
+ // Get temperature from thermal image (use runtime selectors to be resilient across SDK versions)
740
777
  streamer.withThermalImage { [weak self] thermalImage in
741
- if let stats = thermalImage.getStatistics() {
742
- self?.lastTemperature = stats.getMax().value
778
+ var tempVal: Double = Double.nan
779
+ // Try getImageStatistics then fallback to getStatistics (different SDK versions)
780
+ if let statsObj = (thermalImage.perform(Selector(("getImageStatistics")))?.takeUnretainedValue() as? NSObject) ?? (thermalImage.perform(Selector(("getStatistics")))?.takeUnretainedValue() as? NSObject) {
781
+ if statsObj.responds(to: Selector(("getMax"))) {
782
+ if let maxObj = statsObj.perform(Selector(("getMax")))?.takeUnretainedValue() as? NSObject,
783
+ let val = maxObj.value(forKey: "value") as? Double {
784
+ tempVal = val
785
+ }
786
+ } else if let maxVal = statsObj.value(forKey: "max") as? NSObject,
787
+ let val = maxVal.value(forKey: "value") as? Double {
788
+ tempVal = val
789
+ }
790
+ }
791
+ if !tempVal.isNaN {
792
+ self?.lastTemperature = tempVal
743
793
  }
744
794
  }
745
795
 
@@ -12,6 +12,7 @@
12
12
  #import <React/RCTLog.h>
13
13
  #import <React/RCTBridge.h>
14
14
  #import <objc/message.h>
15
+ #import <objc/runtime.h>
15
16
 
16
17
  #if __has_include(<ThermalSDK/ThermalSDK.h>)
17
18
  #define FLIR_SDK_AVAILABLE 1
@@ -796,7 +797,13 @@ RCT_EXPORT_METHOD(isPreferSdkRotation:(RCTPromiseResolveBlock)resolve
796
797
 
797
798
  // Get temperature from thermal image if available
798
799
  [self.streamer withThermalImage:^(FLIRThermalImage *thermalImage) {
799
- FLIRImageStatistics *stats = [thermalImage getStatistics];
800
+ // Some SDK versions call getImageStatistics(), try both selectors
801
+ FLIRImageStatistics *stats = nil;
802
+ if ([thermalImage respondsToSelector:sel_registerName("getImageStatistics")]) {
803
+ stats = ((id (*)(id, SEL))objc_msgSend)((id)thermalImage, sel_registerName("getImageStatistics"));
804
+ } else if ([thermalImage respondsToSelector:sel_registerName("getStatistics")]) {
805
+ stats = ((id (*)(id, SEL))objc_msgSend)((id)thermalImage, sel_registerName("getStatistics"));
806
+ }
800
807
  if (stats) {
801
808
  self.lastTemperature = [[stats getMax] value];
802
809
  [FlirState shared].lastTemperature = self.lastTemperature;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilabs-flir",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
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",