ilabs-flir 2.2.27 → 2.2.30

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.
@@ -133,20 +133,25 @@ public class FlirSdkManager {
133
133
  }
134
134
 
135
135
  public void stopScan() {
136
+ if (!isScanning) return;
137
+
138
+ // Use a temporary flag to prevent concurrent stop calls
139
+ isScanning = false;
140
+
136
141
  executor.execute(() -> {
137
- if (!isScanning)
138
- return;
139
142
  try {
143
+ Log.d(TAG, "Stopping discovery...");
140
144
  DiscoveryFactory.getInstance().stop(
141
145
  CommunicationInterface.EMULATOR,
142
146
  CommunicationInterface.USB,
143
147
  CommunicationInterface.NETWORK,
144
148
  CommunicationInterface.FLIR_ONE_WIRELESS);
149
+ Log.d(TAG, "Discovery stopped successfully");
145
150
  } catch (Exception e) {
146
- Log.e(TAG, "Stop scan failed", e);
151
+ // This is where the 'Receiver not registered' usually happens in SDK internals.
152
+ // We catch it silently as it means the SDK already cleaned up or is in a weird state.
153
+ Log.w(TAG, "Stop scan warning (internal SDK): " + e.getMessage());
147
154
  }
148
- isScanning = false;
149
- Log.d(TAG, "Discovery stopped");
150
155
  });
151
156
  }
152
157
 
@@ -179,12 +184,13 @@ public class FlirSdkManager {
179
184
  Log.d(TAG, "Connecting to: " + identity.deviceId);
180
185
  camera = new Camera();
181
186
 
182
- // ── Authenticate for NETWORK cameras (required by FLIR SDK) ──
187
+ // ── Authenticate for NETWORK/WIRELESS cameras (required by FLIR SDK) ──
183
188
  // Matches the official NetworkCamera sample app pattern.
184
- // The FLIR One Edge Pro is a network camera and will reject
189
+ // The FLIR One Edge Pro is a network/wireless camera and will reject
185
190
  // connections without prior authentication + trust approval.
186
- if (identity.communicationInterface == CommunicationInterface.NETWORK) {
187
- Log.d(TAG, "Network camera detected — authenticating...");
191
+ if (identity.communicationInterface == CommunicationInterface.NETWORK ||
192
+ identity.communicationInterface == CommunicationInterface.FLIR_ONE_WIRELESS) {
193
+ Log.d(TAG, "Network/Wireless camera detected — authenticating...");
188
194
 
189
195
  // Use a persistent application name (workaround for camera bug
190
196
  // where re-auth with a different name conflicts). Same pattern
@@ -323,26 +329,28 @@ public class FlirSdkManager {
323
329
  // Start stream with simple callback (matches sample app)
324
330
  thermalStream.start(
325
331
  unused -> {
326
- // Skip if previous frame still processing
332
+ // CRITICAL: Frame processing must happen in a controlled way.
333
+ // For Android, we perform streamer.update() on the callback thread
334
+ // to ensure the native frame reference remains valid.
327
335
  if (isProcessingFrame.compareAndSet(false, true)) {
328
- executor.execute(() -> {
329
- try {
330
- if (streamer != null && activeStream != null) {
331
- streamer.update();
332
- Bitmap bitmap = BitmapAndroid.createBitmap(streamer.getImage()).getBitMap();
333
- if (bitmap != null) {
334
- latestBitmap = bitmap;
335
- if (listener != null) {
336
- listener.onFrame(bitmap);
337
- }
336
+ try {
337
+ if (streamer != null && activeStream != null) {
338
+ streamer.update();
339
+
340
+ // createBitmap is safe to do here or in executor
341
+ Bitmap bitmap = BitmapAndroid.createBitmap(streamer.getImage()).getBitMap();
342
+ if (bitmap != null) {
343
+ latestBitmap = bitmap;
344
+ if (listener != null) {
345
+ listener.onFrame(bitmap);
338
346
  }
339
347
  }
340
- } catch (Exception e) {
341
- Log.e(TAG, "Frame error", e);
342
- } finally {
343
- isProcessingFrame.set(false);
344
348
  }
345
- });
349
+ } catch (Exception e) {
350
+ Log.e(TAG, "Frame processing error", e);
351
+ } finally {
352
+ isProcessingFrame.set(false);
353
+ }
346
354
  }
347
355
  },
348
356
  error -> {
package/app.plugin.js CHANGED
@@ -178,11 +178,19 @@ const withFlirInfoPlist = (config, props = {}) => {
178
178
 
179
179
  /**
180
180
  * Adds FLIR-specific entitlements for iOS
181
+ * Required for FLIR One Edge Pro and network discovery
181
182
  */
182
183
  const withFlirEntitlements = (config) => {
183
184
  return withEntitlementsPlist(config, (config) => {
184
- // Required to read current WiFi SSID for direct connections
185
+ // 1. Access Wi-Fi Information
185
186
  config.modResults['com.apple.developer.networking.wifi-info'] = true;
187
+
188
+ // 2. Hotspot Configuration (Required for FLIR Edge)
189
+ config.modResults['com.apple.developer.networking.HotspotConfiguration'] = true;
190
+
191
+ // 3. Wireless Accessory Configuration (Required for FLIR Edge)
192
+ config.modResults['com.apple.external-accessory.wireless-configuration'] = true;
193
+
186
194
  return config;
187
195
  });
188
196
  };
@@ -247,6 +255,19 @@ const withFlirAndroidManifest = (config, props = {}) => {
247
255
 
248
256
  // WiFi feature for network cameras
249
257
  addFeature('android.hardware.wifi', false);
258
+
259
+ // OpenGL ES 3.0 requirement (mandatory for Atlas SDK rendering)
260
+ const hasOpenGL = mainApplication['uses-feature'].some(
261
+ (f) => f.$?.['android:glEsVersion'] === '0x00030000'
262
+ );
263
+ if (!hasOpenGL) {
264
+ mainApplication['uses-feature'].push({
265
+ $: {
266
+ 'android:glEsVersion': '0x00030000',
267
+ 'android:required': 'true',
268
+ },
269
+ });
270
+ }
250
271
 
251
272
  // Network permissions (always added on Android)
252
273
  addPermission('android.permission.INTERNET');
@@ -255,13 +276,49 @@ const withFlirAndroidManifest = (config, props = {}) => {
255
276
  addPermission('android.permission.CHANGE_WIFI_STATE');
256
277
  addPermission('android.permission.CHANGE_NETWORK_STATE');
257
278
  addPermission('android.permission.CHANGE_WIFI_MULTICAST_STATE');
279
+
280
+ // Required for Wi-Fi discovery on Android 13+ (API 33)
258
281
  addPermission('android.permission.NEARBY_WIFI_DEVICES');
282
+
259
283
  addPermission('android.permission.BLUETOOTH');
260
284
  addPermission('android.permission.BLUETOOTH_ADMIN');
261
285
  addPermission('android.permission.BLUETOOTH_CONNECT');
262
286
  addPermission('android.permission.BLUETOOTH_SCAN');
263
287
  addPermission('android.permission.ACCESS_FINE_LOCATION'); // Required for BLE scanning
264
288
 
289
+ // =========================================================================
290
+ // USB AUTO-LAUNCH CONFIGURATION
291
+ // Allows the app to open automatically when a FLIR USB device is attached.
292
+ // =========================================================================
293
+ const activity = mainApplication.application[0].activity[0];
294
+
295
+ // 1. Add intent filter for USB_DEVICE_ATTACHED
296
+ if (!activity['intent-filter']) activity['intent-filter'] = [];
297
+ const hasUsbIntent = activity['intent-filter'].some(filter =>
298
+ filter.action?.some(action => action.$['android:name'] === 'android.hardware.usb.action.USB_DEVICE_ATTACHED')
299
+ );
300
+
301
+ if (!hasUsbIntent) {
302
+ activity['intent-filter'].push({
303
+ action: [{ $: { 'android:name': 'android.hardware.usb.action.USB_DEVICE_ATTACHED' } }]
304
+ });
305
+ }
306
+
307
+ // 2. Add meta-data pointing to the flir_usb_device_filter.xml
308
+ if (!activity['meta-data']) activity['meta-data'] = [];
309
+ const hasUsbMetadata = activity['meta-data'].some(meta =>
310
+ meta.$['android:name'] === 'android.hardware.usb.action.USB_DEVICE_ATTACHED'
311
+ );
312
+
313
+ if (!hasUsbMetadata) {
314
+ activity['meta-data'].push({
315
+ $: {
316
+ 'android:name': 'android.hardware.usb.action.USB_DEVICE_ATTACHED',
317
+ 'android:resource': '@xml/flir_usb_device_filter'
318
+ }
319
+ });
320
+ }
321
+
265
322
  return config;
266
323
  });
267
324
  };
@@ -284,18 +341,67 @@ const withFlirManifest = (config) => {
284
341
  };
285
342
 
286
343
  /**
287
- * Copies sdk-manifest.json to Android assets
344
+ * Copies sdk-manifest.json to Android assets AND creates the USB filter XML
288
345
  */
289
346
  const withFlirAndroidAssets = (config) => {
290
347
  return withDangerousMod(config, [
291
348
  'android',
292
349
  async (config) => {
293
- const src = path.join(__dirname, 'sdk-manifest.json');
294
- const dst = path.join(config.modRequest.platformProjectRoot, 'app/src/main/assets/sdk-manifest.json');
295
- if (fs.existsSync(src)) {
296
- fs.mkdirSync(path.dirname(dst), { recursive: true });
297
- fs.copyFileSync(src, dst);
350
+ const projectRoot = config.modRequest.projectRoot;
351
+ const platformRoot = config.modRequest.platformProjectRoot;
352
+
353
+ // 1. Copy sdk-manifest.json
354
+ const manifestSrc = path.join(__dirname, 'sdk-manifest.json');
355
+ const manifestDst = path.join(platformRoot, 'app/src/main/assets/sdk-manifest.json');
356
+ if (fs.existsSync(manifestSrc)) {
357
+ fs.mkdirSync(path.dirname(manifestDst), { recursive: true });
358
+ fs.copyFileSync(manifestSrc, manifestDst);
359
+ }
360
+
361
+ // 2. Create flir_usb_device_filter.xml (Required for auto-launch)
362
+ const usbFilterXml = `<?xml version="1.0" encoding="utf-8"?>
363
+ <resources>
364
+ <!-- FLIR Vendor ID (2507) -->
365
+ <usb-device vendor-id="2507" />
366
+ </resources>`;
367
+
368
+ const xmlDst = path.join(platformRoot, 'app/src/main/res/xml/flir_usb_device_filter.xml');
369
+ fs.mkdirSync(path.dirname(xmlDst), { recursive: true });
370
+ fs.writeFileSync(xmlDst, usbFilterXml);
371
+
372
+ return config;
373
+ },
374
+ ]);
375
+ };
376
+
377
+ /**
378
+ * Patch Xcode project settings (Bitcode, Linker Flags)
379
+ */
380
+ const withFlirXcodeSettings = (config) => {
381
+ return withDangerousMod(config, [
382
+ 'ios',
383
+ async (config) => {
384
+ const { modRequest } = config;
385
+ const xcodeProjectPath = path.join(modRequest.platformProjectRoot, 'ThermalCameraFx.xcodeproj/project.pbxproj');
386
+
387
+ if (!fs.existsSync(xcodeProjectPath)) return config;
388
+
389
+ let pbxproj = fs.readFileSync(xcodeProjectPath, 'utf8');
390
+
391
+ // 1. Disable Bitcode (Required for FLIR SDK)
392
+ // Matches: ENABLE_BITCODE = YES; -> ENABLE_BITCODE = NO;
393
+ pbxproj = pbxproj.replace(/ENABLE_BITCODE = YES/g, 'ENABLE_BITCODE = NO');
394
+
395
+ // 2. Add -ObjC to OTHER_LDFLAGS if not present
396
+ // This is a bit tricky with regex, so we look for the OTHER_LDFLAGS line
397
+ if (!pbxproj.includes('"-ObjC"') && !pbxproj.includes('-ObjC')) {
398
+ pbxproj = pbxproj.replace(
399
+ /OTHER_LDFLAGS = \(\n/g,
400
+ 'OTHER_LDFLAGS = (\n\t\t\t\t"-ObjC",\n'
401
+ );
298
402
  }
403
+
404
+ fs.writeFileSync(xcodeProjectPath, pbxproj, 'utf8');
299
405
  return config;
300
406
  },
301
407
  ]);
@@ -368,6 +474,7 @@ const withFlirThermalSDK = (config, props = {}) => {
368
474
  // Apply iOS modifications
369
475
  config = withFlirInfoPlist(config, props);
370
476
  config = withFlirEntitlements(config);
477
+ config = withFlirXcodeSettings(config);
371
478
  config = withFlirManifest(config);
372
479
 
373
480
  // Apply Android modifications
@@ -170,8 +170,8 @@ import ThermalSDK
170
170
  // ── AUTHENTICATE for network cameras ──
171
171
  // Official FLIR CameraConnector sample checks .generic camera type,
172
172
  // but FLIR One Edge Pro over network may report a different type.
173
- // Check BOTH: camera type == .generic OR interface contains .network
174
- let needsAuth = (camType == .generic) || iface.contains(.network)
173
+ // Check BOTH: camera type == .generic OR interface contains .network/.flirOneWireless
174
+ let needsAuth = (camType == .generic) || iface.contains(.network) || iface.contains(.flirOneWireless)
175
175
 
176
176
  if needsAuth {
177
177
  NSLog("[FlirManager] Network camera detected — authenticating...")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilabs-flir",
3
- "version": "2.2.27",
3
+ "version": "2.2.30",
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",
@@ -6,8 +6,8 @@ const fs = require('fs');
6
6
  const path = require('path');
7
7
  const { execSync } = require('child_process');
8
8
 
9
- let IOS_URL = 'https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/ios.zip';
10
- let ANDROID_URL = 'https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/android.zip';
9
+ let IOS_URL = 'https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.2/ios.zip';
10
+ let ANDROID_URL = 'https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.2/android.zip';
11
11
  // Manifest override
12
12
  try {
13
13
  const manifest = require(path.join(__dirname, '..', 'sdk-manifest.json'));
package/sdk-manifest.json CHANGED
@@ -2,9 +2,9 @@
2
2
  "version": "2.0.0",
3
3
  "sdkVersion": "5.0.0",
4
4
  "ios": {
5
- "downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/ios.zip",
5
+ "downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.2/ios.zip",
6
6
  "directDownload": {
7
- "downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/ios.zip",
7
+ "downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.2/ios.zip",
8
8
  "sha256": "",
9
9
  "sizeBytes": 0
10
10
  },
@@ -14,14 +14,14 @@
14
14
  "xcframeworks": [
15
15
  "ThermalSDK.xcframework",
16
16
  "MeterLink.xcframework",
17
- "libavcodec.61.dylib.xcframework",
18
- "libavdevice.61.dylib.xcframework",
19
- "libavfilter.10.dylib.xcframework",
20
- "libavformat.61.dylib.xcframework",
21
- "libavutil.59.dylib.xcframework",
17
+ "libavcodec.62.dylib.xcframework",
18
+ "libavdevice.62.dylib.xcframework",
19
+ "libavfilter.11.dylib.xcframework",
20
+ "libavformat.62.dylib.xcframework",
21
+ "libavutil.60.dylib.xcframework",
22
22
  "liblive666.dylib.xcframework",
23
- "libswresample.5.dylib.xcframework",
24
- "libswscale.8.dylib.xcframework"
23
+ "libswresample.6.dylib.xcframework",
24
+ "libswscale.9.dylib.xcframework"
25
25
  ],
26
26
  "minDeploymentTarget": "13.0",
27
27
  "supportedArchitectures": [
@@ -32,7 +32,7 @@
32
32
  "android": {
33
33
 
34
34
  "directDownload": {
35
- "downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/android.zip",
35
+ "downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.2/android.zip",
36
36
  "sha256": "",
37
37
  "sizeBytes": 0
38
38
  }