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
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
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(
|
|
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
|
-
|
|
742
|
-
|
|
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
|
-
|
|
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;
|