ilabs-flir 2.2.14 → 2.2.16

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.
@@ -53,6 +53,16 @@ object FlirManager {
53
53
  fun setTextureCallback(callback: TextureUpdateCallback?) {
54
54
  textureCallback = callback
55
55
  }
56
+
57
+ interface TemperatureUpdateCallback {
58
+ fun onTemperatureUpdate(temperature: Double)
59
+ }
60
+
61
+ private var temperatureCallback: TemperatureUpdateCallback? = null
62
+
63
+ fun setTemperatureCallback(callback: TemperatureUpdateCallback?) {
64
+ temperatureCallback = callback
65
+ }
56
66
 
57
67
  fun getLatestBitmap(): Bitmap? = latestBitmap
58
68
 
@@ -130,6 +140,10 @@ object FlirManager {
130
140
  emitError("Device not found: $deviceId")
131
141
  }
132
142
  }
143
+
144
+ fun switchToDevice(deviceId: String) {
145
+ connectToDevice(deviceId)
146
+ }
133
147
 
134
148
  /**
135
149
  * Disconnect
@@ -241,6 +255,13 @@ object FlirManager {
241
255
  return
242
256
  }
243
257
 
258
+ // THROTTLE: Limit to ~15 FPS to prevent UI thread flooding
259
+ val now = System.currentTimeMillis()
260
+ if (now - lastEmitMs.get() < 66) { // 66ms ~= 15 FPS
261
+ return
262
+ }
263
+ lastEmitMs.set(now)
264
+
244
265
  latestBitmap = bitmap
245
266
 
246
267
  // If this is the first frame, notify JS that we are now streaming
@@ -249,16 +270,18 @@ object FlirManager {
249
270
  emitDeviceState("streaming")
250
271
  }
251
272
 
252
- // NON-BLOCKING TEXTURE UPDATE (Drop frames if busy)
273
+ // NON-BLOCKING TEXTURE UPDATE
253
274
  if (textureCallback != null) {
275
+ // We use try-lock to ensure we don't pile up parallel calls,
276
+ // though usually onFrame is serial.
254
277
  if (isUpdatingTexture.compareAndSet(false, true)) {
255
278
  try {
256
279
  textureCallback?.onTextureUpdate(bitmap, 0)
280
+ } catch (e: Exception) {
281
+ Log.e(TAG, "Texture update failed", e)
257
282
  } finally {
258
283
  isUpdatingTexture.set(false)
259
284
  }
260
- } else {
261
- // Log.v(TAG, "Dropping frame - texture update busy")
262
285
  }
263
286
  }
264
287
 
@@ -52,6 +52,10 @@ import ThermalSDK
52
52
  @objc public class FlirManager: NSObject {
53
53
  @objc public static let shared = FlirManager()
54
54
 
55
+ // MARK: - Singleton
56
+
57
+ @objc public static let shared = FlirManager()
58
+
55
59
  // MARK: - Properties
56
60
  @objc public weak var delegate: FlirManagerDelegate?
57
61
 
@@ -307,10 +311,13 @@ import ThermalSDK
307
311
 
308
312
  if let measurements = thermalImage.measurements,
309
313
  let spot = try? measurements.addSpot(CGPoint(x: cx, y: cy)) {
310
- if let value = spot.getValue() {
311
- result = value.value
312
- }
313
- measurements.remove(spot)
314
+
315
+ // getValue() returns non-optional in some SDK versions, or optional in others.
316
+ // Compiler says it is NOT optional here, so direct assignment.
317
+ let value = spot.getValue()
318
+ result = value.value
319
+
320
+ try? measurements.remove(spot)
314
321
  }
315
322
  }
316
323
  return result
@@ -361,9 +368,35 @@ import ThermalSDK
361
368
 
362
369
  // MARK: - Battery (stub - not needed per user)
363
370
 
371
+ // MARK: - Battery (stub - not needed per user)
372
+
364
373
  @objc public func getBatteryLevel() -> Int { return -1 }
365
374
  @objc public func isBatteryCharging() -> Bool { return false }
366
375
 
376
+ // MARK: - Shim Compatibility
377
+
378
+ @objc public static var isSDKAvailable: Bool {
379
+ return true
380
+ }
381
+
382
+ @objc public func setPalette(_ name: String) {
383
+ // stub
384
+ }
385
+
386
+ @objc public func setPaletteFromAcol(_ acol: Float) {
387
+ // stub
388
+ }
389
+
390
+ @objc public func retainClient(_ clientId: String) {
391
+ // simplified manager doesn't track retain counts per client yet
392
+ startDiscovery()
393
+ }
394
+
395
+ @objc public func releaseClient(_ clientId: String) {
396
+ // simplified manager doesn't track retain counts per client yet
397
+ // stopDiscovery() // Optional: could stop if count == 0
398
+ }
399
+
367
400
  // MARK: - Helpers
368
401
 
369
402
  private func emitStateChange(_ state: String) {
@@ -7,6 +7,7 @@
7
7
  //
8
8
 
9
9
  #import "FlirModule.h"
10
+
10
11
  #import "FlirEventEmitter.h"
11
12
  #import "FlirState.h"
12
13
  #import <React/RCTBridge.h>
@@ -309,7 +310,8 @@ RCT_EXPORT_METHOD(getTemperatureAt : (nonnull NSNumber *)x y : (
309
310
  nonnull NSNumber *)y resolver : (RCTPromiseResolveBlock)
310
311
  resolve rejecter : (RCTPromiseRejectBlock)reject) {
311
312
  dispatch_async(dispatch_get_main_queue(), ^{
312
- double temp = flir_getTemperatureAtPoint([x intValue], [y intValue]);
313
+ double temp = [[FLIRManager shared] getTemperatureAtPoint:[x intValue]
314
+ y:[y intValue]];
313
315
  if (isnan(temp)) {
314
316
  resolve([NSNull null]);
315
317
  } else {
@@ -404,7 +406,7 @@ RCT_EXPORT_METHOD(getSDKStatus : (RCTPromiseResolveBlock)
404
406
  RCT_EXPORT_METHOD(getBatteryLevel : (RCTPromiseResolveBlock)
405
407
  resolve rejecter : (RCTPromiseRejectBlock)reject) {
406
408
  dispatch_async(dispatch_get_main_queue(), ^{
407
- int level = flir_getBatteryLevel();
409
+ int level = [[FLIRManager shared] getBatteryLevel];
408
410
  resolve(@(level));
409
411
  });
410
412
  }
@@ -412,7 +414,7 @@ RCT_EXPORT_METHOD(getBatteryLevel : (RCTPromiseResolveBlock)
412
414
  RCT_EXPORT_METHOD(isBatteryCharging : (RCTPromiseResolveBlock)
413
415
  resolve rejecter : (RCTPromiseRejectBlock)reject) {
414
416
  dispatch_async(dispatch_get_main_queue(), ^{
415
- BOOL ch = flir_isBatteryCharging();
417
+ BOOL ch = [[FLIRManager shared] isBatteryCharging];
416
418
  resolve(@(ch));
417
419
  });
418
420
  }
@@ -420,7 +422,7 @@ RCT_EXPORT_METHOD(isBatteryCharging : (RCTPromiseResolveBlock)
420
422
  RCT_EXPORT_METHOD(setPreferSdkRotation : (BOOL)prefer resolver : (
421
423
  RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) {
422
424
  dispatch_async(dispatch_get_main_queue(), ^{
423
- flir_setPreferSdkRotation(prefer);
425
+ [[FLIRManager shared] setPreferSdkRotation:prefer];
424
426
  resolve(@(YES));
425
427
  });
426
428
  }
@@ -428,7 +430,7 @@ RCT_EXPORT_METHOD(setPreferSdkRotation : (BOOL)prefer resolver : (
428
430
  RCT_EXPORT_METHOD(isPreferSdkRotation : (RCTPromiseResolveBlock)
429
431
  resolve rejecter : (RCTPromiseRejectBlock)reject) {
430
432
  dispatch_async(dispatch_get_main_queue(), ^{
431
- BOOL v = flir_isPreferSdkRotation();
433
+ BOOL v = [[FLIRManager shared] isPreferSdkRotation];
432
434
  resolve(@(v));
433
435
  });
434
436
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilabs-flir",
3
- "version": "2.2.14",
3
+ "version": "2.2.16",
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",
@@ -1,24 +0,0 @@
1
- // ObjC shim to expose `FLIRManager` from the npm package and forward to `FlirManager` at runtime
2
- #import <Foundation/Foundation.h>
3
- #import <UIKit/UIKit.h>
4
-
5
- NS_ASSUME_NONNULL_BEGIN
6
-
7
- @interface FLIRManager : NSObject
8
-
9
- + (instancetype)shared;
10
-
11
- - (BOOL)isAvailable;
12
- - (double)getTemperatureAtPoint:(int)x y:(int)y;
13
- - (double)getTemperatureAtNormalized:(double)nx y:(double)ny;
14
- - (int)getBatteryLevel;
15
- - (BOOL)isBatteryCharging;
16
- - (void)setPreferSdkRotation:(BOOL)prefer;
17
- - (BOOL)isPreferSdkRotation;
18
- - (nullable UIImage *)latestFrameImage;
19
- - (void)startDiscovery;
20
- - (void)stopDiscovery;
21
-
22
- @end
23
-
24
- NS_ASSUME_NONNULL_END
@@ -1,153 +0,0 @@
1
- // ObjC shim implementation forwarding to Swift `FlirManager` via runtime selectors
2
- #import "FLIRManager.h"
3
- #import <objc/message.h>
4
-
5
- @implementation FLIRManager
6
-
7
- + (instancetype)shared {
8
- Class cls = NSClassFromString(@"FlirManager");
9
- if (!cls) return nil;
10
- SEL sel = sel_registerName("shared");
11
- if (![cls respondsToSelector:sel]) return nil;
12
- id (*msgSend0)(id, SEL) = (id (*)(id, SEL))objc_msgSend;
13
- return msgSend0((id)cls, sel);
14
- }
15
-
16
- - (BOOL)isAvailable {
17
- Class cls = NSClassFromString(@"FlirManager");
18
- SEL sel = sel_registerName("isSDKAvailable");
19
- if (!cls || ![cls respondsToSelector:sel]) return NO;
20
- BOOL (*msgSend0)(id, SEL) = (BOOL (*)(id, SEL))objc_msgSend;
21
- return msgSend0((id)cls, sel);
22
- }
23
-
24
- - (double)getTemperatureAtPoint:(int)x y:(int)y {
25
- id inst = [[self class] shared];
26
- SEL sel = sel_registerName("getTemperatureAt: y:");
27
- // Swift method name mangling may differ; fall back to method used by FlirModule
28
- SEL selAlt = sel_registerName("getTemperatureAtPoint:y:");
29
- SEL use = NULL;
30
- if (inst && [inst respondsToSelector:sel]) use = sel;
31
- if (inst && [inst respondsToSelector:selAlt]) use = selAlt;
32
- if (!inst || !use) return NAN;
33
- double (*msgSend2)(id, SEL, int, int) = (double (*)(id, SEL, int, int))objc_msgSend;
34
- return msgSend2(inst, use, x, y);
35
- }
36
-
37
- - (double)getTemperatureAtNormalized:(double)nx y:(double)ny {
38
- id inst = [[self class] shared];
39
- SEL sel = sel_registerName("getTemperatureAtNormalized:y:");
40
- if (!inst || ![inst respondsToSelector:sel]) return NAN;
41
- double (*msgSend2)(id, SEL, double, double) = (double (*)(id, SEL, double, double))objc_msgSend;
42
- return msgSend2(inst, sel, nx, ny);
43
- }
44
-
45
- - (int)getBatteryLevel {
46
- id inst = [[self class] shared];
47
- SEL sel = sel_registerName("getBatteryLevel");
48
- if (!inst || ![inst respondsToSelector:sel]) return -1;
49
- int (*msgSend0)(id, SEL) = (int (*)(id, SEL))objc_msgSend;
50
- return msgSend0(inst, sel);
51
- }
52
-
53
- - (BOOL)isBatteryCharging {
54
- id inst = [[self class] shared];
55
- SEL sel = sel_registerName("isBatteryCharging");
56
- if (!inst || ![inst respondsToSelector:sel]) return NO;
57
- BOOL (*msgSend0)(id, SEL) = (BOOL (*)(id, SEL))objc_msgSend;
58
- return msgSend0(inst, sel);
59
- }
60
-
61
- - (void)setPreferSdkRotation:(BOOL)prefer {
62
- id inst = [[self class] shared];
63
- SEL sel = sel_registerName("setPreferSdkRotation:");
64
- if (!inst || ![inst respondsToSelector:sel]) return;
65
- void (*msgSend1)(id, SEL, BOOL) = (void (*)(id, SEL, BOOL))objc_msgSend;
66
- msgSend1(inst, sel, prefer);
67
- }
68
-
69
- - (BOOL)isPreferSdkRotation {
70
- id inst = [[self class] shared];
71
- SEL sel = sel_registerName("isPreferSdkRotation");
72
- if (!inst || ![inst respondsToSelector:sel]) return NO;
73
- BOOL (*msgSend0)(id, SEL) = (BOOL (*)(id, SEL))objc_msgSend;
74
- return msgSend0(inst, sel);
75
- }
76
-
77
- - (nullable NSString *)latestFrameBase64 {
78
- id inst = [[self class] shared];
79
- SEL sel = sel_registerName("latestFrameBase64");
80
- if (!inst || ![inst respondsToSelector:sel]) return nil;
81
- id (*msgSend0)(id, SEL) = (id (*)(id, SEL))objc_msgSend;
82
- return (NSString *)msgSend0(inst, sel);
83
- }
84
-
85
- - (void)retainClient:(NSString *)clientId {
86
- id inst = [[self class] shared];
87
- SEL sel = sel_registerName("retainClient:");
88
- if (!inst || ![inst respondsToSelector:sel]) return;
89
- void (*msgSend1)(id, SEL, id) = (void (*)(id, SEL, id))objc_msgSend;
90
- msgSend1(inst, sel, clientId);
91
- }
92
-
93
- - (void)releaseClient:(NSString *)clientId {
94
- id inst = [[self class] shared];
95
- SEL sel = sel_registerName("releaseClient:");
96
- if (!inst || ![inst respondsToSelector:sel]) return;
97
- void (*msgSend1)(id, SEL, id) = (void (*)(id, SEL, id))objc_msgSend;
98
- msgSend1(inst, sel, clientId);
99
- }
100
-
101
- - (void)setPalette:(NSString *)paletteName {
102
- id inst = [[self class] shared];
103
- SEL sel = sel_registerName("setPalette:");
104
- if (!inst || ![inst respondsToSelector:sel]) return;
105
- void (*msgSend1)(id, SEL, id) = (void (*)(id, SEL, id))objc_msgSend;
106
- msgSend1(inst, sel, paletteName);
107
- }
108
-
109
- - (void)setPaletteFromAcol:(double)acol {
110
- id inst = [[self class] shared];
111
- SEL sel = sel_registerName("setPaletteFromAcol:");
112
- if (!inst || ![inst respondsToSelector:sel]) return;
113
- void (*msgSend1)(id, SEL, double) = (void (*)(id, SEL, double))objc_msgSend;
114
- msgSend1(inst, sel, acol);
115
- }
116
-
117
- - (nullable NSString *)getPaletteNameFromAcol:(double)acol {
118
- Class cls = NSClassFromString(@"FlirManager");
119
- SEL sel = sel_registerName("getPaletteNameFromAcol:");
120
- if (!cls || ![cls respondsToSelector:sel]) return nil;
121
- id (*msgSend1)(id, SEL, double) = (id (*)(id, SEL, double))objc_msgSend;
122
- return (NSString *)msgSend1((id)cls, sel, acol);
123
- }
124
-
125
- - (nullable UIImage *)latestFrameImage {
126
- id inst = [[self class] shared];
127
- SEL sel = sel_registerName("latestImage");
128
- SEL selAlt = sel_registerName("latestFrameImage");
129
- SEL use = NULL;
130
- if (inst && [inst respondsToSelector:selAlt]) use = selAlt;
131
- else if (inst && [inst respondsToSelector:sel]) use = sel;
132
- if (!inst || !use) return nil;
133
- id (*msgSend0)(id, SEL) = (id (*)(id, SEL))objc_msgSend;
134
- return (UIImage *)msgSend0(inst, use);
135
- }
136
-
137
- - (void)startDiscovery {
138
- id inst = [[self class] shared];
139
- SEL sel = sel_registerName("startDiscovery");
140
- if (!inst || ![inst respondsToSelector:sel]) return;
141
- void (*msgSend0)(id, SEL) = (void (*)(id, SEL))objc_msgSend;
142
- msgSend0(inst, sel);
143
- }
144
-
145
- - (void)stopDiscovery {
146
- id inst = [[self class] shared];
147
- SEL sel = sel_registerName("stopDiscovery");
148
- if (!inst || ![inst respondsToSelector:sel]) return;
149
- void (*msgSend0)(id, SEL) = (void (*)(id, SEL))objc_msgSend;
150
- msgSend0(inst, sel);
151
- }
152
-
153
- @end