ilabs-flir 2.2.24 → 2.2.27
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.
- package/android/Flir/src/main/java/flir/android/FlirManager.kt +6 -4
- package/android/Flir/src/main/java/flir/android/FlirModule.kt +10 -0
- package/android/Flir/src/main/java/flir/android/FlirSdkManager.java +83 -13
- package/ios/Flir/src/FlirManager.swift +640 -567
- package/ios/Flir/src/FlirModule.m +25 -2
- package/package.json +1 -1
|
@@ -180,8 +180,10 @@ object FlirManager {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
fun getTemperatureAtNormalized(nx: Double, ny: Double): Double? {
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
val bitmap = latestBitmap ?: return null
|
|
184
|
+
val px = (nx * bitmap.width).toInt().coerceIn(0, bitmap.width - 1)
|
|
185
|
+
val py = (ny * bitmap.height).toInt().coerceIn(0, bitmap.height - 1)
|
|
186
|
+
return getTemperatureAt(px, py)
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
fun getTemperatureAtPoint(x: Int, y: Int): Double? = getTemperatureAt(x, y)
|
|
@@ -255,9 +257,9 @@ object FlirManager {
|
|
|
255
257
|
return
|
|
256
258
|
}
|
|
257
259
|
|
|
258
|
-
// THROTTLE: Limit to ~
|
|
260
|
+
// THROTTLE: Limit to ~30 FPS for smoother streaming
|
|
259
261
|
val now = System.currentTimeMillis()
|
|
260
|
-
if (now - lastEmitMs.get() <
|
|
262
|
+
if (now - lastEmitMs.get() < 33) { // 33ms ~= 30 FPS
|
|
261
263
|
return
|
|
262
264
|
}
|
|
263
265
|
lastEmitMs.set(now)
|
|
@@ -67,6 +67,16 @@ class FlirModule(private val reactContext: ReactApplicationContext) : ReactConte
|
|
|
67
67
|
promise.reject("ERR_FLIR_SAMPLE", e)
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
|
|
71
|
+
@ReactMethod
|
|
72
|
+
fun getTemperatureAtNormalized(nx: Double, ny: Double, promise: Promise) {
|
|
73
|
+
try {
|
|
74
|
+
val temp = FlirManager.getTemperatureAtNormalized(nx, ny)
|
|
75
|
+
if (temp != null) promise.resolve(temp) else promise.resolve(null)
|
|
76
|
+
} catch (e: Exception) {
|
|
77
|
+
promise.reject("ERR_FLIR_TEMP_NORM", e)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
70
80
|
|
|
71
81
|
@ReactMethod
|
|
72
82
|
fun isEmulator(promise: Promise) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package flir.android;
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
|
+
import android.content.SharedPreferences;
|
|
4
5
|
import android.graphics.Bitmap;
|
|
5
6
|
import android.util.Log;
|
|
6
7
|
|
|
@@ -9,6 +10,7 @@ import com.flir.thermalsdk.androidsdk.ThermalSdkAndroid;
|
|
|
9
10
|
import com.flir.thermalsdk.androidsdk.image.BitmapAndroid;
|
|
10
11
|
import com.flir.thermalsdk.image.Point;
|
|
11
12
|
import com.flir.thermalsdk.image.ThermalValue;
|
|
13
|
+
import com.flir.thermalsdk.live.AuthenticationResponse;
|
|
12
14
|
import com.flir.thermalsdk.live.Camera;
|
|
13
15
|
import com.flir.thermalsdk.live.CommunicationInterface;
|
|
14
16
|
import com.flir.thermalsdk.live.ConnectParameters;
|
|
@@ -25,6 +27,7 @@ import java.util.Collections;
|
|
|
25
27
|
import java.util.List;
|
|
26
28
|
import java.util.concurrent.Executor;
|
|
27
29
|
import java.util.concurrent.Executors;
|
|
30
|
+
import java.util.concurrent.atomic.AtomicBoolean;
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
33
|
* Simplified FLIR SDK Manager - matches sample app pattern
|
|
@@ -45,6 +48,8 @@ public class FlirSdkManager {
|
|
|
45
48
|
private Stream activeStream;
|
|
46
49
|
private final List<Identity> discoveredDevices = Collections.synchronizedList(new ArrayList<>());
|
|
47
50
|
private volatile Bitmap latestBitmap;
|
|
51
|
+
private final AtomicBoolean isProcessingFrame = new AtomicBoolean(false);
|
|
52
|
+
private boolean useHalfScale = false;
|
|
48
53
|
|
|
49
54
|
// Listener
|
|
50
55
|
private Listener listener;
|
|
@@ -173,6 +178,57 @@ public class FlirSdkManager {
|
|
|
173
178
|
|
|
174
179
|
Log.d(TAG, "Connecting to: " + identity.deviceId);
|
|
175
180
|
camera = new Camera();
|
|
181
|
+
|
|
182
|
+
// ── Authenticate for NETWORK cameras (required by FLIR SDK) ──
|
|
183
|
+
// Matches the official NetworkCamera sample app pattern.
|
|
184
|
+
// The FLIR One Edge Pro is a network camera and will reject
|
|
185
|
+
// connections without prior authentication + trust approval.
|
|
186
|
+
if (identity.communicationInterface == CommunicationInterface.NETWORK) {
|
|
187
|
+
Log.d(TAG, "Network camera detected — authenticating...");
|
|
188
|
+
|
|
189
|
+
// Use a persistent application name (workaround for camera bug
|
|
190
|
+
// where re-auth with a different name conflicts). Same pattern
|
|
191
|
+
// as CameraAuthName in the NetworkCamera sample.
|
|
192
|
+
SharedPreferences prefs = context.getSharedPreferences(
|
|
193
|
+
"flir_auth", Context.MODE_PRIVATE);
|
|
194
|
+
String authName = prefs.getString("auth_name", null);
|
|
195
|
+
if (authName == null) {
|
|
196
|
+
authName = context.getPackageName() + "-" +
|
|
197
|
+
(System.currentTimeMillis() % 10000);
|
|
198
|
+
prefs.edit().putString("auth_name", authName).apply();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
AuthenticationResponse response;
|
|
202
|
+
int attempts = 0;
|
|
203
|
+
final int MAX_AUTH_ATTEMPTS = 30; // 30 seconds max wait
|
|
204
|
+
do {
|
|
205
|
+
response = camera.authenticate(identity, authName,
|
|
206
|
+
41 * 1000); // 41-second timeout per attempt
|
|
207
|
+
Log.d(TAG, "Auth attempt " + (attempts + 1) +
|
|
208
|
+
" status: " + response.authenticationStatus);
|
|
209
|
+
|
|
210
|
+
if (response.authenticationStatus ==
|
|
211
|
+
AuthenticationResponse.AuthenticationStatus.PENDING) {
|
|
212
|
+
// Camera is waiting for user to press "Trust" on its screen
|
|
213
|
+
Thread.sleep(1000);
|
|
214
|
+
}
|
|
215
|
+
attempts++;
|
|
216
|
+
} while (response.authenticationStatus ==
|
|
217
|
+
AuthenticationResponse.AuthenticationStatus.PENDING
|
|
218
|
+
&& attempts < MAX_AUTH_ATTEMPTS);
|
|
219
|
+
|
|
220
|
+
if (response.authenticationStatus !=
|
|
221
|
+
AuthenticationResponse.AuthenticationStatus.APPROVED) {
|
|
222
|
+
Log.e(TAG, "Authentication rejected/timed out: " +
|
|
223
|
+
response.authenticationStatus);
|
|
224
|
+
camera = null;
|
|
225
|
+
notifyError("Camera authentication failed. " +
|
|
226
|
+
"Check the camera screen for a trust prompt.");
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
Log.d(TAG, "Authentication approved");
|
|
230
|
+
}
|
|
231
|
+
|
|
176
232
|
camera.connect(identity, connectionStatusListener, new ConnectParameters());
|
|
177
233
|
Log.d(TAG, "Connected to: " + identity.deviceId);
|
|
178
234
|
|
|
@@ -221,6 +277,15 @@ public class FlirSdkManager {
|
|
|
221
277
|
executor.execute(this::startStreamInternal);
|
|
222
278
|
}
|
|
223
279
|
|
|
280
|
+
public void setUseHalfScale(boolean useHalfScale) {
|
|
281
|
+
this.useHalfScale = useHalfScale;
|
|
282
|
+
executor.execute(() -> {
|
|
283
|
+
if (streamer != null) {
|
|
284
|
+
// We'll apply this when the streamer is created or updated
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
224
289
|
private void startStreamInternal() {
|
|
225
290
|
if (camera == null) {
|
|
226
291
|
notifyError("Not connected");
|
|
@@ -258,22 +323,27 @@ public class FlirSdkManager {
|
|
|
258
323
|
// Start stream with simple callback (matches sample app)
|
|
259
324
|
thermalStream.start(
|
|
260
325
|
unused -> {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (
|
|
269
|
-
|
|
326
|
+
// Skip if previous frame still processing
|
|
327
|
+
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
|
+
}
|
|
270
338
|
}
|
|
271
339
|
}
|
|
340
|
+
} catch (Exception e) {
|
|
341
|
+
Log.e(TAG, "Frame error", e);
|
|
342
|
+
} finally {
|
|
343
|
+
isProcessingFrame.set(false);
|
|
272
344
|
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
});
|
|
345
|
+
});
|
|
346
|
+
}
|
|
277
347
|
},
|
|
278
348
|
error -> {
|
|
279
349
|
executor.execute(() -> {
|