ilabs-flir 2.0.8 → 2.1.0

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,36 @@ 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)")
257
+ }
239
258
  } else {
240
- NSLog("[FlirManager] SDK not available - cannot set palette")
259
+ NSLog("[FlirManager] SDK palette APIs not available - cannot set palette")
241
260
  }
242
261
  #else
243
262
  NSLog("[FlirManager] SDK not available - cannot set palette")
@@ -366,15 +385,34 @@ import ThermalSDK
366
385
  }
367
386
  }
368
387
 
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())")
388
+ // Connect (support multiple SDK signatures via ObjC runtime)
389
+ var connectedOK = false
390
+ if let cam = camera {
391
+ if cam.responds(to: Selector(("connect:error:"))) {
392
+ // Call connect:identity error:nil (ignore NSError pointer for compatibility)
393
+ _ = cam.perform(Selector(("connect:error:")), with: identity, with: nil)
394
+ connectedOK = true
395
+ } else if cam.responds(to: Selector(("connect:"))) {
396
+ _ = cam.perform(Selector(("connect:")), with: identity)
397
+ connectedOK = true
398
+ } else {
399
+ NSLog("[FlirManager] No compatible connect API on FLIRCamera")
400
+ }
401
+ }
402
+
403
+ if connectedOK {
404
+ connectedIdentity = identity
405
+ connectedDeviceId = identity.deviceId()
406
+ connectedDeviceName = identity.deviceId()
407
+ _isConnected = true
408
+ NSLog("[FlirManager] Connected to: \(identity.deviceId())")
409
+ } else {
410
+ NSLog("[FlirManager] Connection failed: no compatible connect API")
411
+ DispatchQueue.main.async { [weak self] in
412
+ self?.delegate?.onError("Connection failed: unsupported SDK API")
413
+ }
414
+ return
415
+ }
378
416
 
379
417
  // Get streams
380
418
  if let streams = camera?.getStreams(), !streams.isEmpty {
@@ -424,7 +462,7 @@ import ThermalSDK
424
462
  if iface.contains(.network) { return "NETWORK" }
425
463
  if iface.contains(.flirOneWireless) { return "WIRELESS" }
426
464
  if iface.contains(.emulator) { return "EMULATOR" }
427
- if iface.contains(.usb) { return "USB" }
465
+ if String(describing: iface).lowercased().contains("usb") { return "USB" }
428
466
  return "UNKNOWN"
429
467
  }
430
468
  #endif
@@ -736,10 +774,23 @@ extension FlirManager: FLIRStreamDelegate {
736
774
  if let image = streamer.getImage() {
737
775
  _latestImage = image
738
776
 
739
- // Get temperature from thermal image
777
+ // Get temperature from thermal image (use runtime selectors to be resilient across SDK versions)
740
778
  streamer.withThermalImage { [weak self] thermalImage in
741
- if let stats = thermalImage.getStatistics() {
742
- self?.lastTemperature = stats.getMax().value
779
+ var tempVal: Double = Double.nan
780
+ // Try getImageStatistics then fallback to getStatistics (different SDK versions)
781
+ if let statsObj = (thermalImage.perform(Selector(("getImageStatistics")))?.takeUnretainedValue() as? NSObject) ?? (thermalImage.perform(Selector(("getStatistics")))?.takeUnretainedValue() as? NSObject) {
782
+ if statsObj.responds(to: Selector(("getMax"))) {
783
+ if let maxObj = statsObj.perform(Selector(("getMax")))?.takeUnretainedValue() as? NSObject,
784
+ let val = maxObj.value(forKey: "value") as? Double {
785
+ tempVal = val
786
+ }
787
+ } else if let maxVal = statsObj.value(forKey: "max") as? NSObject,
788
+ let val = maxVal.value(forKey: "value") as? Double {
789
+ tempVal = val
790
+ }
791
+ }
792
+ if !tempVal.isNaN {
793
+ self?.lastTemperature = tempVal
743
794
  }
744
795
  }
745
796
 
@@ -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.1.0",
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",