ilabs-flir 1.0.3 → 1.0.4
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/libs/flir-stubs.jar +0 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/ErrorCode.java +13 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/ThermalSdkAndroid.java +16 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/androidsdk/image/BitmapAndroid.java +20 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/Camera.java +26 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/ConnectParameters.java +16 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/RemoteControl.java +16 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/discovery/DiscoveryEventListener.java +14 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/discovery/DiscoveryFactory.java +33 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/streaming/Stream.java +8 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/streaming/ThermalStreamer.java +28 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/streaming/VisualStreamer.java +18 -0
- package/android/Flir/src/main/java/flir/android/FlirCommands.java +40 -15
- package/android/Flir/src/main/java/flir/android/FlirDownloadManager.kt +6 -5
- package/android/Flir/src/main/java/flir/android/FlirManager.kt +265 -42
- package/android/Flir/src/main/java/flir/android/FlirSDKLoader.kt +242 -194
- package/android/Flir/src/main/java/flir/android/FlirSdkManager.java +1376 -755
- package/package.json +1 -1
- package/sdk-manifest.json +14 -7
- package/android/Flir/src/main/java/flir/android/CameraHandler.java +0 -224
- package/android/Flir/src/main/java/flir/android/FlirConnectionManager.java +0 -354
- package/android/Flir/src/main/java/flir/android/FlirController.kt +0 -11
- package/android/Flir/src/main/java/flir/android/FlirDiscoveryManager.java +0 -236
- package/android/Flir/src/main/java/flir/android/FrameDataHolder.java +0 -14
package/package.json
CHANGED
package/sdk-manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.0.
|
|
2
|
+
"version": "1.0.1",
|
|
3
3
|
"sdkVersion": "4.16.0",
|
|
4
4
|
"ios": {
|
|
5
5
|
"downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.0/ios-sdk.zip",
|
|
@@ -19,12 +19,19 @@
|
|
|
19
19
|
]
|
|
20
20
|
},
|
|
21
21
|
"android": {
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
22
|
+
"packages": {
|
|
23
|
+
"arm64-v8a": {
|
|
24
|
+
"downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/flir-sdk-arm64-v8a.zip",
|
|
25
|
+
"sizeBytes": 36328411
|
|
26
|
+
},
|
|
27
|
+
"armeabi-v7a": {
|
|
28
|
+
"downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/flir-sdk-armeabi-v7a.zip",
|
|
29
|
+
"sizeBytes": 33248516
|
|
30
|
+
},
|
|
31
|
+
"x86_64": {
|
|
32
|
+
"downloadUrl": "https://github.com/PraveenOjha/flir-sdk-binaries/releases/download/v1.0.1/flir-sdk-x86_64.zip",
|
|
33
|
+
"sizeBytes": 38421590
|
|
34
|
+
}
|
|
28
35
|
}
|
|
29
36
|
}
|
|
30
37
|
}
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
package flir.android;
|
|
2
|
-
|
|
3
|
-
import android.graphics.Bitmap;
|
|
4
|
-
import android.util.Log;
|
|
5
|
-
|
|
6
|
-
import com.flir.thermalsdk.androidsdk.image.BitmapAndroid;
|
|
7
|
-
import com.flir.thermalsdk.image.ThermalImage;
|
|
8
|
-
import com.flir.thermalsdk.live.Camera;
|
|
9
|
-
import com.flir.thermalsdk.live.CommunicationInterface;
|
|
10
|
-
import com.flir.thermalsdk.live.ConnectParameters;
|
|
11
|
-
import com.flir.thermalsdk.live.Identity;
|
|
12
|
-
import com.flir.thermalsdk.live.connectivity.ConnectionStatusListener;
|
|
13
|
-
import com.flir.thermalsdk.live.discovery.DiscoveryEventListener;
|
|
14
|
-
import com.flir.thermalsdk.live.discovery.DiscoveryFactory;
|
|
15
|
-
import com.flir.thermalsdk.live.streaming.Stream;
|
|
16
|
-
import com.flir.thermalsdk.live.streaming.ThermalStreamer;
|
|
17
|
-
|
|
18
|
-
import java.io.IOException;
|
|
19
|
-
import java.util.LinkedList;
|
|
20
|
-
import java.util.Objects;
|
|
21
|
-
|
|
22
|
-
public class CameraHandler {
|
|
23
|
-
|
|
24
|
-
private static final String TAG = "CameraHandler";
|
|
25
|
-
|
|
26
|
-
private StreamDataListener streamDataListener;
|
|
27
|
-
|
|
28
|
-
public interface StreamDataListener {
|
|
29
|
-
void images(FrameDataHolder dataHolder);
|
|
30
|
-
|
|
31
|
-
void images(Bitmap msxBitmap, Bitmap dcBitmap);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
LinkedList<Identity> foundCameraIdentities = new LinkedList<>();
|
|
35
|
-
|
|
36
|
-
private Camera camera;
|
|
37
|
-
|
|
38
|
-
private Stream connectedStream;
|
|
39
|
-
private ThermalStreamer streamer;
|
|
40
|
-
// Cache the latest ThermalImage delivered by the streamer
|
|
41
|
-
private ThermalImage latestThermalImage;
|
|
42
|
-
|
|
43
|
-
public CameraHandler() {
|
|
44
|
-
Log.d(TAG, "CameraHandler constr");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
public void startDiscovery(DiscoveryEventListener cameraDiscoveryListener, DiscoveryStatus discoveryStatus) {
|
|
48
|
-
DiscoveryFactory.getInstance().scan(cameraDiscoveryListener, CommunicationInterface.EMULATOR,
|
|
49
|
-
CommunicationInterface.USB);
|
|
50
|
-
discoveryStatus.started();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public void stopDiscovery(DiscoveryStatus discoveryStatus) {
|
|
54
|
-
DiscoveryFactory.getInstance().stop(CommunicationInterface.EMULATOR, CommunicationInterface.USB);
|
|
55
|
-
discoveryStatus.stopped();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
public synchronized void connect(Identity identity, ConnectionStatusListener connectionStatusListener)
|
|
59
|
-
throws IOException {
|
|
60
|
-
Log.d(TAG, "connect identity: " + identity);
|
|
61
|
-
camera = new Camera();
|
|
62
|
-
camera.connect(identity, connectionStatusListener, new ConnectParameters());
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
public synchronized void disconnect() {
|
|
66
|
-
Log.d(TAG, "disconnect");
|
|
67
|
-
if (camera == null) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (connectedStream == null) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (connectedStream.isStreaming()) {
|
|
75
|
-
connectedStream.stop();
|
|
76
|
-
}
|
|
77
|
-
camera.disconnect();
|
|
78
|
-
camera = null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public synchronized void startStream(StreamDataListener listener) {
|
|
82
|
-
this.streamDataListener = listener;
|
|
83
|
-
if (camera == null || !camera.isConnected()) {
|
|
84
|
-
Log.e(TAG, "startStream, failed, camera was null or not connected");
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
connectedStream = camera.getStreams().get(0);
|
|
88
|
-
if (connectedStream.isThermal()) {
|
|
89
|
-
streamer = new ThermalStreamer(connectedStream);
|
|
90
|
-
} else {
|
|
91
|
-
Log.e(TAG, "startStream, failed, no thermal stream available for the camera");
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
connectedStream.start(
|
|
95
|
-
unused -> {
|
|
96
|
-
streamer.update();
|
|
97
|
-
final Bitmap[] dcBitmap = new Bitmap[1];
|
|
98
|
-
streamer.withThermalImage(thermalImage -> {
|
|
99
|
-
try {
|
|
100
|
-
// Cache the latest ThermalImage for sampling
|
|
101
|
-
latestThermalImage = thermalImage;
|
|
102
|
-
// TODO: Re-enable fusion when SDK is available at runtime
|
|
103
|
-
// if (thermalImage.getFusion() != null && thermalImage.getFusion().getPhoto()
|
|
104
|
-
// != null) {
|
|
105
|
-
// dcBitmap[0] = BitmapAndroid.createBitmap(thermalImage.getFusion().getPhoto())
|
|
106
|
-
// .getBitMap();
|
|
107
|
-
// }
|
|
108
|
-
// The streamer.getImage() returns the ImageBuffer expected by BitmapAndroid
|
|
109
|
-
// final Bitmap thermalPixels =
|
|
110
|
-
// BitmapAndroid.createBitmap(streamer.getImage()).getBitMap();
|
|
111
|
-
// if (streamDataListener != null) streamDataListener.images(thermalPixels,
|
|
112
|
-
// dcBitmap[0]);
|
|
113
|
-
} catch (Exception e) {
|
|
114
|
-
Log.e(TAG, "thermal bitmap creation error", e);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
},
|
|
118
|
-
error -> Log.e(TAG, "Streaming error: " + error));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
public synchronized Double getTemperatureAt(int x, int y) {
|
|
122
|
-
try {
|
|
123
|
-
if (streamer == null)
|
|
124
|
-
return null;
|
|
125
|
-
ThermalImage img = latestThermalImage;
|
|
126
|
-
if (img == null)
|
|
127
|
-
return null;
|
|
128
|
-
|
|
129
|
-
java.lang.reflect.Method[] methods = img.getClass().getMethods();
|
|
130
|
-
for (java.lang.reflect.Method m : methods) {
|
|
131
|
-
String name = m.getName().toLowerCase();
|
|
132
|
-
Class<?>[] params = m.getParameterTypes();
|
|
133
|
-
|
|
134
|
-
if ((name.contains("get") || name.contains("value") || name.contains("temperature"))
|
|
135
|
-
&& params.length == 2
|
|
136
|
-
&& (params[0] == int.class || params[0] == Integer.class || params[0] == double.class
|
|
137
|
-
|| params[0] == float.class)
|
|
138
|
-
&& (params[1] == int.class || params[1] == Integer.class || params[1] == double.class
|
|
139
|
-
|| params[1] == float.class)) {
|
|
140
|
-
try {
|
|
141
|
-
Object res = null;
|
|
142
|
-
if (params[0] == int.class && params[1] == int.class) {
|
|
143
|
-
res = m.invoke(img, x, y);
|
|
144
|
-
} else if (params[0] == double.class && params[1] == double.class) {
|
|
145
|
-
res = m.invoke(img, (double) x, (double) y);
|
|
146
|
-
} else if (params[0] == float.class && params[1] == float.class) {
|
|
147
|
-
res = m.invoke(img, (float) x, (float) y);
|
|
148
|
-
} else {
|
|
149
|
-
res = m.invoke(img, Integer.valueOf(x), Integer.valueOf(y));
|
|
150
|
-
}
|
|
151
|
-
if (res instanceof Number) {
|
|
152
|
-
return ((Number) res).doubleValue();
|
|
153
|
-
}
|
|
154
|
-
} catch (Exception e) {
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
} catch (Exception e) {
|
|
159
|
-
Log.e(TAG, "getTemperatureAt error", e);
|
|
160
|
-
}
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public void add(Identity identity) {
|
|
165
|
-
foundCameraIdentities.add(identity);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
public Identity getCppEmulator() {
|
|
169
|
-
for (Identity foundCameraIdentity : foundCameraIdentities) {
|
|
170
|
-
if (foundCameraIdentity.deviceId.contains("C++ Emulator")) {
|
|
171
|
-
return foundCameraIdentity;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
public Identity getFlirOneEmulator() {
|
|
178
|
-
for (Identity foundCameraIdentity : foundCameraIdentities) {
|
|
179
|
-
if (foundCameraIdentity.deviceId.contains("EMULATED FLIR ONE")) {
|
|
180
|
-
return foundCameraIdentity;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
public Identity getFlirOne() {
|
|
187
|
-
for (Identity foundCameraIdentity : foundCameraIdentities) {
|
|
188
|
-
if (foundCameraIdentity.communicationInterface == CommunicationInterface.USB)
|
|
189
|
-
return foundCameraIdentity;
|
|
190
|
-
}
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
public String getDeviceInfo() {
|
|
195
|
-
if (camera == null)
|
|
196
|
-
return "N/A";
|
|
197
|
-
try {
|
|
198
|
-
if (camera.getRemoteControl() == null)
|
|
199
|
-
return "N/A";
|
|
200
|
-
return camera.getRemoteControl().cameraInformation().getSync().displayName;
|
|
201
|
-
} catch (Exception e) {
|
|
202
|
-
return "N/A";
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
public void setPalette(String name) {
|
|
207
|
-
if (latestThermalImage != null) {
|
|
208
|
-
java.util.List<com.flir.thermalsdk.image.Palette> palettes = com.flir.thermalsdk.image.PaletteManager
|
|
209
|
-
.getDefaultPalettes();
|
|
210
|
-
for (com.flir.thermalsdk.image.Palette p : palettes) {
|
|
211
|
-
if (p.name.equalsIgnoreCase(name)) {
|
|
212
|
-
latestThermalImage.setPalette(p);
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
public interface DiscoveryStatus {
|
|
220
|
-
void started();
|
|
221
|
-
|
|
222
|
-
void stopped();
|
|
223
|
-
}
|
|
224
|
-
}
|
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
package flir.android;
|
|
2
|
-
|
|
3
|
-
import android.graphics.Bitmap;
|
|
4
|
-
import android.util.Log;
|
|
5
|
-
import com.flir.thermalsdk.ErrorCodeException;
|
|
6
|
-
import com.flir.thermalsdk.androidsdk.image.BitmapAndroid;
|
|
7
|
-
import com.flir.thermalsdk.image.Palette;
|
|
8
|
-
import com.flir.thermalsdk.image.PaletteManager;
|
|
9
|
-
import com.flir.thermalsdk.live.Camera;
|
|
10
|
-
import com.flir.thermalsdk.live.CommunicationInterface;
|
|
11
|
-
import com.flir.thermalsdk.live.ConnectParameters;
|
|
12
|
-
import com.flir.thermalsdk.live.Identity;
|
|
13
|
-
import com.flir.thermalsdk.ErrorCode;
|
|
14
|
-
import com.flir.thermalsdk.live.connectivity.ConnectionStatusListener;
|
|
15
|
-
import com.flir.thermalsdk.live.remote.OnRemoteError;
|
|
16
|
-
import com.flir.thermalsdk.live.remote.OnReceived;
|
|
17
|
-
import com.flir.thermalsdk.live.streaming.Stream;
|
|
18
|
-
import com.flir.thermalsdk.live.streaming.ThermalStreamer;
|
|
19
|
-
import java.net.InetAddress;
|
|
20
|
-
import java.util.List;
|
|
21
|
-
|
|
22
|
-
public class FlirConnectionManager {
|
|
23
|
-
private static final String TAG = "FlirConnectionManager";
|
|
24
|
-
private static FlirConnectionManager instance;
|
|
25
|
-
|
|
26
|
-
private Camera camera;
|
|
27
|
-
private ThermalStreamer thermalStreamer;
|
|
28
|
-
private Identity currentIdentity;
|
|
29
|
-
private boolean isStreaming = false;
|
|
30
|
-
private Palette currentPalette;
|
|
31
|
-
private Bitmap latestFrame;
|
|
32
|
-
|
|
33
|
-
// Event callback interface
|
|
34
|
-
public interface ConnectionEventCallback {
|
|
35
|
-
void onConnectionStatusChanged(boolean connected, String deviceId);
|
|
36
|
-
|
|
37
|
-
void onError(String message);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private ConnectionEventCallback eventCallback;
|
|
41
|
-
|
|
42
|
-
// Callback for frame updates
|
|
43
|
-
public interface FrameCallback {
|
|
44
|
-
void onFrameReceived(Bitmap frame);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private FrameCallback frameCallback;
|
|
48
|
-
|
|
49
|
-
private FlirConnectionManager() {
|
|
50
|
-
// Default to Iron palette
|
|
51
|
-
List<Palette> palettes = PaletteManager.getDefaultPalettes();
|
|
52
|
-
currentPalette = palettes.stream()
|
|
53
|
-
.filter(p -> "iron".equalsIgnoreCase(p.name))
|
|
54
|
-
.findFirst()
|
|
55
|
-
.orElse(palettes.get(0));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
public static synchronized FlirConnectionManager getInstance() {
|
|
59
|
-
if (instance == null) {
|
|
60
|
-
instance = new FlirConnectionManager();
|
|
61
|
-
}
|
|
62
|
-
return instance;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
public void setEventCallback(ConnectionEventCallback callback) {
|
|
66
|
-
this.eventCallback = callback;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public void selectDevice(Identity identity) {
|
|
70
|
-
Log.i(TAG, "[FLIR] 📱 Selecting device: " + identity.deviceId);
|
|
71
|
-
|
|
72
|
-
// ALWAYS disconnect from current device first
|
|
73
|
-
if (isStreaming || camera != null) {
|
|
74
|
-
Log.i(TAG, "[FLIR] 🔌 Disconnecting from current device...");
|
|
75
|
-
stopStreaming();
|
|
76
|
-
disconnect();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
currentIdentity = identity;
|
|
80
|
-
|
|
81
|
-
// Connect in background
|
|
82
|
-
new Thread(() -> {
|
|
83
|
-
try {
|
|
84
|
-
connectToDevice();
|
|
85
|
-
startStreaming();
|
|
86
|
-
} catch (Exception e) {
|
|
87
|
-
Log.e(TAG, "[FLIR] Failed to connect/stream", e);
|
|
88
|
-
emitError("Failed to connect: " + e.getMessage());
|
|
89
|
-
}
|
|
90
|
-
}).start();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private void connectToDevice() throws Exception {
|
|
94
|
-
Log.i(TAG, "[FLIR] 🔌 Connecting to: " + currentIdentity.deviceId);
|
|
95
|
-
|
|
96
|
-
camera = new Camera();
|
|
97
|
-
|
|
98
|
-
// Authenticate for network cameras
|
|
99
|
-
if (currentIdentity.communicationInterface == CommunicationInterface.NETWORK) {
|
|
100
|
-
if (currentIdentity.ipSettings != null) {
|
|
101
|
-
String ipAddress = currentIdentity.ipSettings.ipAddress;
|
|
102
|
-
// Use generic app name or allow injection if needed
|
|
103
|
-
String appName = "ThermalCameraApp";
|
|
104
|
-
Log.d(TAG, "[FLIR] Authenticating network camera at " + ipAddress);
|
|
105
|
-
// authenticate method might vary, assuming simple overload or need to check SDK
|
|
106
|
-
// camera.authenticate(InetAddress.getByName(ipAddress), appName, ...);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Connect to device
|
|
111
|
-
camera.connect(
|
|
112
|
-
currentIdentity,
|
|
113
|
-
errorCode -> {
|
|
114
|
-
Log.w(TAG, "[FLIR] ❌ Connection error: " + errorCode);
|
|
115
|
-
emitError("Connection error: " + errorCode.toString());
|
|
116
|
-
},
|
|
117
|
-
new ConnectParameters());
|
|
118
|
-
|
|
119
|
-
Log.i(TAG, "[FLIR] ✅ Connected successfully");
|
|
120
|
-
emitConnectionStatus(true);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ... authenticate method ...
|
|
124
|
-
|
|
125
|
-
private void startStreaming() {
|
|
126
|
-
if (camera == null) {
|
|
127
|
-
Log.w(TAG, "[FLIR] Cannot start streaming - no camera connected");
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Find thermal stream
|
|
132
|
-
Stream thermalStream = camera.getStreams().stream()
|
|
133
|
-
.filter(Stream::isThermal)
|
|
134
|
-
.findFirst()
|
|
135
|
-
.orElse(null);
|
|
136
|
-
|
|
137
|
-
if (thermalStream == null) {
|
|
138
|
-
Log.w(TAG, "[FLIR] No thermal stream available");
|
|
139
|
-
emitError("No thermal stream available");
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
Log.i(TAG, "[FLIR] 🎥 Starting thermal stream...");
|
|
144
|
-
|
|
145
|
-
thermalStreamer = new ThermalStreamer(thermalStream);
|
|
146
|
-
|
|
147
|
-
thermalStream.start(
|
|
148
|
-
unused -> {
|
|
149
|
-
// Update stream in background
|
|
150
|
-
new Thread(FlirConnectionManager.this::updateFrame).start();
|
|
151
|
-
},
|
|
152
|
-
error -> {
|
|
153
|
-
Log.w(TAG, "[FLIR] Stream error: " + error);
|
|
154
|
-
emitError("Stream error: " + error.toString());
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
isStreaming = true;
|
|
158
|
-
Log.i(TAG, "[FLIR] ✅ Streaming started");
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
private synchronized void updateFrame() {
|
|
162
|
-
if (thermalStreamer == null)
|
|
163
|
-
return;
|
|
164
|
-
|
|
165
|
-
try {
|
|
166
|
-
thermalStreamer.update();
|
|
167
|
-
} catch (NullPointerException e) {
|
|
168
|
-
// Skip first few frames that may have errors
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Get image buffer
|
|
173
|
-
var imageBuffer = thermalStreamer.getImage();
|
|
174
|
-
if (imageBuffer == null)
|
|
175
|
-
return;
|
|
176
|
-
|
|
177
|
-
// Apply palette and get bitmap
|
|
178
|
-
thermalStreamer.withThermalImage(thermalImage -> {
|
|
179
|
-
if (currentPalette != null) {
|
|
180
|
-
thermalImage.setPalette(currentPalette);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
// BitmapAndroid.createBitmap accepts ImageBuffer interface
|
|
185
|
-
Bitmap bmp = BitmapAndroid.createBitmap(imageBuffer).getBitMap();
|
|
186
|
-
if (bmp != null) {
|
|
187
|
-
latestFrame = bmp;
|
|
188
|
-
|
|
189
|
-
// Notify callback
|
|
190
|
-
if (frameCallback != null) {
|
|
191
|
-
frameCallback.onFrameReceived(bmp);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
} catch (IllegalArgumentException e) {
|
|
195
|
-
// Ignore invalid frames
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
public void stopStreaming() {
|
|
201
|
-
if (!isStreaming)
|
|
202
|
-
return;
|
|
203
|
-
|
|
204
|
-
Log.i(TAG, "[FLIR] Stopping stream...");
|
|
205
|
-
|
|
206
|
-
if (camera != null && camera.getStreams() != null) {
|
|
207
|
-
camera.getStreams().forEach(stream -> {
|
|
208
|
-
try {
|
|
209
|
-
if (stream.isStreaming()) {
|
|
210
|
-
stream.stop();
|
|
211
|
-
}
|
|
212
|
-
} catch (Exception e) {
|
|
213
|
-
Log.w(TAG, "[FLIR] Error stopping stream", e);
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
thermalStreamer = null;
|
|
219
|
-
isStreaming = false;
|
|
220
|
-
Log.d(TAG, "[FLIR] Stream stopped");
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
public void disconnect() {
|
|
224
|
-
if (camera == null)
|
|
225
|
-
return;
|
|
226
|
-
|
|
227
|
-
Log.i(TAG, "[FLIR] Disconnecting...");
|
|
228
|
-
|
|
229
|
-
stopStreaming();
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
camera.disconnect();
|
|
233
|
-
} catch (Exception e) {
|
|
234
|
-
Log.w(TAG, "[FLIR] Error disconnecting", e);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
camera = null;
|
|
238
|
-
currentIdentity = null;
|
|
239
|
-
latestFrame = null;
|
|
240
|
-
|
|
241
|
-
emitConnectionStatus(false);
|
|
242
|
-
Log.d(TAG, "[FLIR] Disconnected");
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
public void setPalette(int acol) {
|
|
246
|
-
String paletteName = mapAcolToPalette(acol);
|
|
247
|
-
|
|
248
|
-
List<Palette> palettes = PaletteManager.getDefaultPalettes();
|
|
249
|
-
Palette newPalette = palettes.stream()
|
|
250
|
-
.filter(p -> paletteName.equalsIgnoreCase(p.name))
|
|
251
|
-
.findFirst()
|
|
252
|
-
.orElse(currentPalette);
|
|
253
|
-
|
|
254
|
-
if (newPalette != currentPalette) {
|
|
255
|
-
currentPalette = newPalette;
|
|
256
|
-
Log.i(TAG, "[FLIR] 🎨 Palette changed to: " + paletteName + " (acol=" + acol + ")");
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
private String mapAcolToPalette(int acol) {
|
|
261
|
-
switch (acol) {
|
|
262
|
-
case 1:
|
|
263
|
-
return "iron";
|
|
264
|
-
case 2:
|
|
265
|
-
return "rainbow";
|
|
266
|
-
case 3:
|
|
267
|
-
return "arctic";
|
|
268
|
-
case 4:
|
|
269
|
-
return "lava";
|
|
270
|
-
case 5:
|
|
271
|
-
return "grayscale";
|
|
272
|
-
case 6:
|
|
273
|
-
return "ironbow";
|
|
274
|
-
case 7:
|
|
275
|
-
return "medical";
|
|
276
|
-
case 8:
|
|
277
|
-
return "rainbow_hc";
|
|
278
|
-
case 9:
|
|
279
|
-
return "contrast";
|
|
280
|
-
case 10:
|
|
281
|
-
return "fusion";
|
|
282
|
-
case 11:
|
|
283
|
-
return "arctic2";
|
|
284
|
-
case 12:
|
|
285
|
-
return "coldest";
|
|
286
|
-
case 13:
|
|
287
|
-
return "hottest";
|
|
288
|
-
case 14:
|
|
289
|
-
return "wheel";
|
|
290
|
-
default:
|
|
291
|
-
return "iron";
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
public double getTemperatureAt(int x, int y) {
|
|
296
|
-
if (thermalStreamer == null) {
|
|
297
|
-
Log.w(TAG, "[FLIR] Cannot query temperature - no active stream");
|
|
298
|
-
return Double.NaN;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
try {
|
|
302
|
-
final double[] temp = { Double.NaN };
|
|
303
|
-
|
|
304
|
-
thermalStreamer.withThermalImage(thermalImage -> {
|
|
305
|
-
try {
|
|
306
|
-
// Get image dimensions from ImageBase (parent class)
|
|
307
|
-
int width = thermalImage.getWidth();
|
|
308
|
-
int height = thermalImage.getHeight();
|
|
309
|
-
|
|
310
|
-
// Clamp coordinates
|
|
311
|
-
int clampedX = Math.max(0, Math.min(x, width - 1));
|
|
312
|
-
int clampedY = Math.max(0, Math.min(y, height - 1));
|
|
313
|
-
|
|
314
|
-
// Query temperature using Point
|
|
315
|
-
temp[0] = thermalImage.getValueAt(new com.flir.thermalsdk.image.Point(clampedX, clampedY)).value;
|
|
316
|
-
|
|
317
|
-
Log.d(TAG, "[FLIR] 🌡️ Temperature at (" + x + "," + y + "): " + temp[0] + "°C");
|
|
318
|
-
} catch (Exception e) {
|
|
319
|
-
Log.w(TAG, "[FLIR] Error getting temperature", e);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
return temp[0];
|
|
324
|
-
} catch (Exception e) {
|
|
325
|
-
Log.w(TAG, "[FLIR] Failed to query temperature", e);
|
|
326
|
-
return Double.NaN;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
public Bitmap getLatestFrame() {
|
|
331
|
-
return latestFrame;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
public void setFrameCallback(FrameCallback callback) {
|
|
335
|
-
this.frameCallback = callback;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
public boolean isStreaming() {
|
|
339
|
-
return isStreaming;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
private void emitConnectionStatus(boolean connected) {
|
|
343
|
-
if (eventCallback != null) {
|
|
344
|
-
eventCallback.onConnectionStatusChanged(connected,
|
|
345
|
-
currentIdentity != null ? currentIdentity.deviceId : null);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
private void emitError(String message) {
|
|
350
|
-
if (eventCallback != null) {
|
|
351
|
-
eventCallback.onError(message);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|