ilabs-flir 1.0.2 → 1.0.3
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/Flir.podspec +31 -31
- package/README.md +1271 -1271
- package/android/Flir/build.gradle.kts +85 -80
- package/android/Flir/src/main/AndroidManifest.xml +31 -31
- package/android/Flir/src/main/java/com/flir/thermalsdk/ErrorCodeException.java +14 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/ImageBuffer.java +11 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/JavaImageBuffer.java +35 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/Palette.java +15 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/PaletteManager.java +16 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/Point.java +11 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/ThermalImage.java +23 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/ThermalValue.java +9 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/CameraType.java +8 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/CommunicationInterface.java +16 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/Identity.java +23 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/IpSettings.java +9 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/connectivity/ConnectionStatusListener.java +7 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/remote/OnReceived.java +5 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/remote/OnRemoteError.java +7 -0
- package/android/Flir/src/main/java/flir/android/CameraHandler.java +224 -194
- package/android/Flir/src/main/java/flir/android/FlirCommands.java +111 -0
- package/android/Flir/src/main/java/flir/android/FlirConnectionManager.java +354 -0
- package/android/Flir/src/main/java/flir/android/FlirController.kt +11 -11
- package/android/Flir/src/main/java/flir/android/FlirDiscoveryManager.java +236 -0
- package/android/Flir/src/main/java/flir/android/FlirDownloadManager.kt +75 -75
- package/android/Flir/src/main/java/flir/android/FlirDownloadPackage.kt +16 -16
- package/android/Flir/src/main/java/flir/android/FlirFrameCache.kt +6 -6
- package/android/Flir/src/main/java/flir/android/FlirManager.kt +254 -248
- package/android/Flir/src/main/java/flir/android/FlirModule.kt +74 -74
- package/android/Flir/src/main/java/flir/android/FlirPackage.kt +19 -19
- package/android/Flir/src/main/java/flir/android/FlirSDKLoader.kt +195 -195
- package/android/Flir/src/main/java/flir/android/FlirSdkManager.java +890 -0
- package/android/Flir/src/main/java/flir/android/FlirStatus.kt +12 -12
- package/android/Flir/src/main/java/flir/android/FlirView.kt +48 -48
- package/android/Flir/src/main/java/flir/android/FlirViewManager.kt +13 -13
- package/android/Flir/src/main/java/flir/android/FrameDataHolder.java +14 -14
- package/app.plugin.js +264 -264
- package/expo-module.config.json +5 -5
- package/ios/Flir/Framework/ThermalSDK/FLIRBattery.h +76 -76
- package/ios/Flir/Framework/ThermalSDK/FLIRCalibration.h +108 -108
- package/ios/Flir/Framework/ThermalSDK/FLIRCamera.h +156 -156
- package/ios/Flir/Framework/ThermalSDK/FLIRCameraDeviceInfo.h +53 -53
- package/ios/Flir/Framework/ThermalSDK/FLIRCameraEvent.h +132 -132
- package/ios/Flir/Framework/ThermalSDK/FLIRCameraImport.h +204 -204
- package/ios/Flir/Framework/ThermalSDK/FLIRColorDistributionSettings.h +204 -204
- package/ios/Flir/Framework/ThermalSDK/FLIRColorizer.h +82 -82
- package/ios/Flir/Framework/ThermalSDK/FLIRDiscoveredCamera.h +44 -44
- package/ios/Flir/Framework/ThermalSDK/FLIRDiscovery.h +132 -132
- package/ios/Flir/Framework/ThermalSDK/FLIRDisplaySettings.h +29 -29
- package/ios/Flir/Framework/ThermalSDK/FLIRFocus.h +70 -70
- package/ios/Flir/Framework/ThermalSDK/FLIRFusion.h +192 -192
- package/ios/Flir/Framework/ThermalSDK/FLIRFusionController.h +136 -136
- package/ios/Flir/Framework/ThermalSDK/FLIRFusionTransformation.h +35 -35
- package/ios/Flir/Framework/ThermalSDK/FLIRIdentity.h +264 -264
- package/ios/Flir/Framework/ThermalSDK/FLIRImageBase.h +196 -196
- package/ios/Flir/Framework/ThermalSDK/FLIRImageColorizer.h +26 -26
- package/ios/Flir/Framework/ThermalSDK/FLIRImageStatistics.h +61 -61
- package/ios/Flir/Framework/ThermalSDK/FLIRIsotherms.h +208 -208
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementArea.h +38 -38
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementCollection.h +147 -147
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementDelta.h +62 -62
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementDimensions.h +33 -33
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementEllipse.h +49 -49
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementLine.h +66 -66
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementMarker.h +69 -69
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementParameters.h +41 -41
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementRectangle.h +36 -36
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementReference.h +27 -27
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementShape.h +46 -46
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementSpot.h +33 -33
- package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementsController.h +160 -160
- package/ios/Flir/Framework/ThermalSDK/FLIRMeterLinkSensorPoll.h +247 -247
- package/ios/Flir/Framework/ThermalSDK/FLIROverlayController.h +27 -27
- package/ios/Flir/Framework/ThermalSDK/FLIRPalette.h +60 -60
- package/ios/Flir/Framework/ThermalSDK/FLIRPaletteController.h +36 -36
- package/ios/Flir/Framework/ThermalSDK/FLIRPaletteManager.h +97 -97
- package/ios/Flir/Framework/ThermalSDK/FLIRQuantification.h +55 -55
- package/ios/Flir/Framework/ThermalSDK/FLIRRemoteControl.h +393 -393
- package/ios/Flir/Framework/ThermalSDK/FLIRRenderer.h +35 -35
- package/ios/Flir/Framework/ThermalSDK/FLIRRendererImpl.h +17 -17
- package/ios/Flir/Framework/ThermalSDK/FLIRScale.h +99 -99
- package/ios/Flir/Framework/ThermalSDK/FLIRScaleController.h +44 -44
- package/ios/Flir/Framework/ThermalSDK/FLIRStream.h +109 -109
- package/ios/Flir/Framework/ThermalSDK/FLIRStreamer.h +124 -124
- package/ios/Flir/Framework/ThermalSDK/FLIRSystem.h +40 -40
- package/ios/Flir/Framework/ThermalSDK/FLIRTemperatureRange.h +43 -43
- package/ios/Flir/Framework/ThermalSDK/FLIRThermalDelta.h +77 -77
- package/ios/Flir/Framework/ThermalSDK/FLIRThermalImage.h +331 -331
- package/ios/Flir/Framework/ThermalSDK/FLIRThermalImageFile.h +56 -56
- package/ios/Flir/Framework/ThermalSDK/FLIRThermalParameters.h +31 -31
- package/ios/Flir/Framework/ThermalSDK/FLIRThermalValue.h +92 -92
- package/ios/Flir/Framework/ThermalSDK/FLIRWirelessCameraDetails.h +88 -88
- package/ios/Flir/Framework/ThermalSDK/ThermalSDK.h +73 -73
- package/ios/Flir/SDKLoader/FlirSDKLoader.m +13 -13
- package/ios/Flir/SDKLoader/FlirSDKLoader.swift +175 -175
- package/ios/Flir/src/FlirEventEmitter.h +12 -12
- package/ios/Flir/src/FlirEventEmitter.m +33 -33
- package/ios/Flir/src/FlirModule.h +10 -10
- package/ios/Flir/src/FlirModule.m +381 -381
- package/ios/Flir/src/FlirPreviewView.h +13 -13
- package/ios/Flir/src/FlirPreviewView.m +24 -24
- package/ios/Flir/src/FlirState.h +20 -20
- package/ios/Flir/src/FlirState.m +79 -79
- package/ios/Flir/src/FlirViewManager.h +9 -9
- package/ios/Flir/src/FlirViewManager.m +16 -16
- package/package.json +60 -60
- package/react-native.config.js +14 -14
- package/scripts/copy_ios_libs.sh +32 -32
- package/scripts/create_stubs.py +174 -174
- package/scripts/download-sdk.js +62 -62
- package/scripts/prepare-binaries.sh +171 -171
- package/sdk-manifest.json +30 -30
- package/src/FlirDownload.ts +78 -78
- package/src/index.d.ts +17 -17
- package/src/index.js +7 -7
- package/src/index.ts +7 -7
|
@@ -1,381 +1,381 @@
|
|
|
1
|
-
#import "FlirModule.h"
|
|
2
|
-
#import "FlirEventEmitter.h"
|
|
3
|
-
#import "FlirState.h"
|
|
4
|
-
#import <ThermalSDK/ThermalSDK.h>
|
|
5
|
-
#import <React/RCTLog.h>
|
|
6
|
-
|
|
7
|
-
#ifndef F1_gen3
|
|
8
|
-
#define F1_gen3 FLIRCameraType_flirOne
|
|
9
|
-
#endif
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@interface FlirModule() <FLIRDiscoveryEventDelegate>
|
|
13
|
-
@property (nonatomic, strong) FLIRDiscovery *discovery;
|
|
14
|
-
@property (nonatomic, strong) FLIRCamera *camera;
|
|
15
|
-
@property (nonatomic, strong) FLIRIdentity *connectedIdentity;
|
|
16
|
-
@property (nonatomic, assign) BOOL isEmulatorMode;
|
|
17
|
-
@property (nonatomic, assign) BOOL isPhysicalDeviceConnected;
|
|
18
|
-
@end
|
|
19
|
-
|
|
20
|
-
@implementation FlirModule
|
|
21
|
-
|
|
22
|
-
RCT_EXPORT_MODULE(FlirIOS);
|
|
23
|
-
|
|
24
|
-
RCT_EXPORT_METHOD(startDiscovery)
|
|
25
|
-
{
|
|
26
|
-
// Hook into ThermalSDK discovery when ready. For now, emit an event to JS.
|
|
27
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
28
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"msg": @"discovery-started" }];
|
|
29
|
-
RCTLogInfo(@"FLIR discovery started (placeholder)");
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
RCT_EXPORT_METHOD(stopDiscovery)
|
|
34
|
-
{
|
|
35
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
36
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{ @"msg": @"discovery-stopped" }];
|
|
37
|
-
RCTLogInfo(@"FLIR discovery stopped (placeholder)");
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
RCT_EXPORT_METHOD(connect:(NSDictionary *)identity resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
42
|
-
{
|
|
43
|
-
// TODO: implement real connect using ThermalSDK and identity info
|
|
44
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
45
|
-
RCTLogInfo(@"Flir connect called (placeholder)");
|
|
46
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"identity": identity ?: @{} }];
|
|
47
|
-
resolve(@(YES));
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
RCT_EXPORT_METHOD(disconnect)
|
|
52
|
-
{
|
|
53
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
54
|
-
RCTLogInfo(@"Flir disconnect called (placeholder)");
|
|
55
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{}];
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
RCT_EXPORT_METHOD(getTemperatureAt:(nonnull NSNumber *)x y:(nonnull NSNumber *)y resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
60
|
-
// Return the last sampled temperature from the preview/state singleton
|
|
61
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
62
|
-
double t = [FlirState shared].lastTemperature;
|
|
63
|
-
if (isnan(t)) {
|
|
64
|
-
resolve([NSNull null]);
|
|
65
|
-
} else {
|
|
66
|
-
resolve(@(t));
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
RCT_EXPORT_METHOD(isEmulator:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
72
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
73
|
-
resolve(@(self.isEmulatorMode));
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
RCT_EXPORT_METHOD(isDeviceConnected:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
78
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
79
|
-
resolve(@(self.isPhysicalDeviceConnected));
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
RCT_EXPORT_METHOD(getConnectedDeviceInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
84
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
85
|
-
if (self.connectedIdentity == nil) {
|
|
86
|
-
resolve(@"Not connected");
|
|
87
|
-
} else if (self.isEmulatorMode) {
|
|
88
|
-
resolve([NSString stringWithFormat:@"Emulator (%@)", [self.connectedIdentity deviceId]]);
|
|
89
|
-
} else {
|
|
90
|
-
resolve([NSString stringWithFormat:@"Physical device (%@)", [self.connectedIdentity deviceId]]);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
RCT_EXPORT_METHOD(startEmulatorMode:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
96
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
97
|
-
[self initializeEmulatorMode];
|
|
98
|
-
resolve(@(YES));
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
- (void)initializeEmulatorMode
|
|
103
|
-
{
|
|
104
|
-
if (!self.discovery) {
|
|
105
|
-
self.discovery = [[FLIRDiscovery alloc] init];
|
|
106
|
-
self.discovery.delegate = self;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Create emulator identity for testing; use FLIRCameraType for compatibility
|
|
110
|
-
FLIRIdentity *emulatorIdentity = [[FLIRIdentity alloc] initWithEmulatorType:FLIRCameraType_flirOne];
|
|
111
|
-
if (emulatorIdentity) {
|
|
112
|
-
self.connectedIdentity = emulatorIdentity;
|
|
113
|
-
self.isEmulatorMode = YES;
|
|
114
|
-
self.isPhysicalDeviceConnected = NO;
|
|
115
|
-
|
|
116
|
-
// Start discovery for emulator
|
|
117
|
-
[self.discovery start:FLIRCommunicationInterfaceEmulator cameraType:FLIRCameraType_flirOne];
|
|
118
|
-
|
|
119
|
-
// Emit connection event
|
|
120
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
121
|
-
@"identity": @{
|
|
122
|
-
@"deviceId": [emulatorIdentity deviceId] ?: @"Emulator",
|
|
123
|
-
@"isEmulator": @(YES)
|
|
124
|
-
},
|
|
125
|
-
@"deviceType": @"emulator",
|
|
126
|
-
@"isEmulator": @(YES)
|
|
127
|
-
}];
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
#pragma mark - FLIRDiscoveryEventDelegate
|
|
132
|
-
|
|
133
|
-
- (void)cameraDiscovered:(FLIRDiscoveredCamera *)discoveredCamera {
|
|
134
|
-
FLIRIdentity *identity = discoveredCamera.identity;
|
|
135
|
-
|
|
136
|
-
BOOL isRealDevice = ([identity communicationInterface] != FLIRCommunicationInterfaceEmulator);
|
|
137
|
-
|
|
138
|
-
if (isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
139
|
-
self.connectedIdentity = identity;
|
|
140
|
-
self.isEmulatorMode = NO;
|
|
141
|
-
self.isPhysicalDeviceConnected = YES;
|
|
142
|
-
[self connectToDevice:identity];
|
|
143
|
-
} else if (!isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
144
|
-
self.connectedIdentity = identity;
|
|
145
|
-
self.isEmulatorMode = YES;
|
|
146
|
-
self.isPhysicalDeviceConnected = NO;
|
|
147
|
-
[self connectToDevice:identity];
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
#pragma mark - Helper Methods
|
|
152
|
-
|
|
153
|
-
- (void)connectToDevice:(FLIRIdentity *)identity {
|
|
154
|
-
if (!self.camera) {
|
|
155
|
-
self.camera = [[FLIRCamera alloc] init];
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
NSError *error;
|
|
159
|
-
BOOL connected = [self.camera connect:identity error:&error];
|
|
160
|
-
|
|
161
|
-
if (connected) {
|
|
162
|
-
NSString *deviceType = self.isEmulatorMode ? @"emulator" : @"device";
|
|
163
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
164
|
-
@"identity": @{
|
|
165
|
-
@"deviceId": [identity deviceId] ?: @"Unknown",
|
|
166
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
167
|
-
},
|
|
168
|
-
@"deviceType": deviceType,
|
|
169
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
170
|
-
}];
|
|
171
|
-
} else {
|
|
172
|
-
RCTLogError(@"Failed to connect to FLIR device: %@", error.localizedDescription);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
#pragma mark - FLIRDiscoveryEventDelegate
|
|
177
|
-
|
|
178
|
-
- (void)cameraFound:(FLIRIdentity *)identity
|
|
179
|
-
{
|
|
180
|
-
self.connectedIdentity = identity;
|
|
181
|
-
self.isEmulatorMode = ([identity communicationInterface] == FLIRCommunicationInterfaceEmulator);
|
|
182
|
-
self.isPhysicalDeviceConnected = !self.isEmulatorMode;
|
|
183
|
-
|
|
184
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
185
|
-
@"identity": @{
|
|
186
|
-
@"deviceId": [identity deviceId] ?: @"Unknown",
|
|
187
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
188
|
-
},
|
|
189
|
-
@"deviceType": self.isEmulatorMode ? @"emulator" : @"physical",
|
|
190
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
191
|
-
}];
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
- (void)cameraLost:(FLIRIdentity *)identity
|
|
195
|
-
{
|
|
196
|
-
self.connectedIdentity = nil;
|
|
197
|
-
self.isEmulatorMode = NO;
|
|
198
|
-
self.isPhysicalDeviceConnected = NO;
|
|
199
|
-
|
|
200
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{
|
|
201
|
-
@"identity": @{
|
|
202
|
-
@"deviceId": [identity deviceId] ?: @"Unknown",
|
|
203
|
-
@"isEmulator": @([identity communicationInterface] == FLIRCommunicationInterfaceEmulator)
|
|
204
|
-
},
|
|
205
|
-
@"wasEmulator": @([identity communicationInterface] == FLIRCommunicationInterfaceEmulator)
|
|
206
|
-
}];
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
- (void)discoveryError:(NSString *)error netServiceError:(int)nsnetserviceserror on:(FLIRCommunicationInterface)iface
|
|
210
|
-
{
|
|
211
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirError" body:@{
|
|
212
|
-
@"error": error ?: @"Unknown discovery error",
|
|
213
|
-
@"type": @"discovery",
|
|
214
|
-
@"interface": @(iface)
|
|
215
|
-
}];
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
@end
|
|
219
|
-
#import "FlirModule.h"
|
|
220
|
-
#import "FlirEventEmitter.h"
|
|
221
|
-
#import "FlirState.h"
|
|
222
|
-
#import <ThermalSDK/ThermalSDK.h>
|
|
223
|
-
#ifndef F1_gen3
|
|
224
|
-
#define F1_gen3 FLIRCameraType_flirOne
|
|
225
|
-
#endif
|
|
226
|
-
#import <React/RCTLog.h>
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
@interface FlirModule()
|
|
230
|
-
<FLIRDiscoveryEventDelegate>
|
|
231
|
-
@property (nonatomic, strong) FLIRDiscovery *discovery;
|
|
232
|
-
@property (nonatomic, strong) FLIRCamera *camera;
|
|
233
|
-
@property (nonatomic, strong) FLIRIdentity *connectedIdentity;
|
|
234
|
-
@property (nonatomic, assign) BOOL isEmulatorMode;
|
|
235
|
-
@property (nonatomic, assign) BOOL isPhysicalDeviceConnected;
|
|
236
|
-
@end
|
|
237
|
-
|
|
238
|
-
@implementation FlirModule
|
|
239
|
-
|
|
240
|
-
RCT_EXPORT_MODULE(FlirIOS);
|
|
241
|
-
|
|
242
|
-
RCT_EXPORT_METHOD(startDiscovery)
|
|
243
|
-
{
|
|
244
|
-
// Hook into ThermalSDK discovery when ready. For now, emit an event to JS.
|
|
245
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
246
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"msg": @"discovery-started" }];
|
|
247
|
-
RCTLogInfo(@"FLIR discovery started (placeholder)");
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
RCT_EXPORT_METHOD(stopDiscovery)
|
|
252
|
-
{
|
|
253
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
254
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{ @"msg": @"discovery-stopped" }];
|
|
255
|
-
RCTLogInfo(@"FLIR discovery stopped (placeholder)");
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
RCT_EXPORT_METHOD(connect:(NSDictionary *)identity resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
260
|
-
{
|
|
261
|
-
// TODO: implement real connect using ThermalSDK and identity info
|
|
262
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
263
|
-
RCTLogInfo(@"Flir connect called (placeholder)");
|
|
264
|
-
// emit a connected event
|
|
265
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"identity": identity ?: @{} }];
|
|
266
|
-
resolve(@(YES));
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
RCT_EXPORT_METHOD(disconnect)
|
|
271
|
-
{
|
|
272
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
273
|
-
RCTLogInfo(@"Flir disconnect called (placeholder)");
|
|
274
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{}];
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
RCT_EXPORT_METHOD(getTemperatureAt:(nonnull NSNumber *)x y:(nonnull NSNumber *)y resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n // Return the last sampled temperature from the preview/state singleton\n dispatch_async(dispatch_get_main_queue(), ^{\n double t = [FlirState shared].lastTemperature;\n if (isnan(t)) {\n resolve([NSNull null]);\n } else {\n resolve(@(t));\n }\n });\n}\n\nRCT_EXPORT_METHOD(isEmulator:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n resolve(@(self.isEmulatorMode));\n });\n}\n\nRCT_EXPORT_METHOD(isDeviceConnected:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n resolve(@(self.isPhysicalDeviceConnected));\n });\n}\n\nRCT_EXPORT_METHOD(getConnectedDeviceInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n if (self.connectedIdentity == nil) {\n resolve(@\"Not connected\");\n } else if (self.isEmulatorMode) {\n resolve([NSString stringWithFormat:@\"Emulator (%@)\", self.connectedIdentity.deviceId]);\n } else {\n resolve([NSString stringWithFormat:@\"Physical device (%@)\", self.connectedIdentity.deviceId]);\n }\n });\n}\n\nRCT_EXPORT_METHOD(startEmulatorMode:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n [self initializeEmulatorMode];\n resolve(@(YES));\n });\n}\n\n- (void)initializeEmulatorMode\n{\n if (!self.discovery) {\n self.discovery = [[FLIRDiscovery alloc] init];\n self.discovery.delegate = self;\n }\n \n // Create emulator identity for testing\n FLIRIdentity *emulatorIdentity = [[FLIRIdentity alloc] initWithEmulatorType:F1_gen3];\n if (emulatorIdentity) {\n self.connectedIdentity = emulatorIdentity;\n self.isEmulatorMode = YES;\n self.isPhysicalDeviceConnected = NO;\n \n // Start discovery for emulator\n [self.discovery start:FLIRCommunicationInterfaceEmulator cameraType:F1_gen3];\n \n // Emit connection event\n [[FlirEventEmitter shared] sendDeviceEvent:@\"FlirDeviceConnected\" body:@{\n @\"identity\": @{\n @\"deviceId\": emulatorIdentity.deviceId ?: @\"Emulator\",\n @\"isEmulator\": @(YES)\n },\n @\"deviceType\": @\"emulator\",\n @\"isEmulator\": @(YES)\n }];\n }\n}
|
|
279
|
-
|
|
280
|
-
#pragma mark - FLIRDiscoveryEventDelegate
|
|
281
|
-
|
|
282
|
-
- (void)cameraDiscovered:(FLIRDiscoveredCamera *)discoveredCamera {
|
|
283
|
-
FLIRIdentity *identity = discoveredCamera.identity;
|
|
284
|
-
|
|
285
|
-
// Check if this is a real device or emulator
|
|
286
|
-
BOOL isRealDevice = (identity.communicationInterface != FLIRCommunicationInterfaceEmulator);
|
|
287
|
-
|
|
288
|
-
if (isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
289
|
-
// Prioritize real device over emulator
|
|
290
|
-
self.connectedIdentity = identity;
|
|
291
|
-
self.isEmulatorMode = NO;
|
|
292
|
-
self.isPhysicalDeviceConnected = YES;
|
|
293
|
-
|
|
294
|
-
// Connect to real device
|
|
295
|
-
[self connectToDevice:identity];
|
|
296
|
-
} else if (!isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
297
|
-
// Use emulator if no real device found
|
|
298
|
-
self.connectedIdentity = identity;
|
|
299
|
-
self.isEmulatorMode = YES;
|
|
300
|
-
self.isPhysicalDeviceConnected = NO;
|
|
301
|
-
|
|
302
|
-
// Connect to emulator
|
|
303
|
-
[self connectToDevice:identity];
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
#pragma mark - Helper Methods
|
|
308
|
-
|
|
309
|
-
- (void)connectToDevice:(FLIRIdentity *)identity {
|
|
310
|
-
if (!self.camera) {
|
|
311
|
-
self.camera = [[FLIRCamera alloc] init];
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
NSError *error;
|
|
315
|
-
BOOL connected = [self.camera connect:identity error:&error];
|
|
316
|
-
|
|
317
|
-
if (connected) {
|
|
318
|
-
NSString *deviceType = self.isEmulatorMode ? @"emulator" : @"device";
|
|
319
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
320
|
-
@"identity": @{
|
|
321
|
-
@"deviceId": identity.deviceId ?: @"Unknown",
|
|
322
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
323
|
-
},
|
|
324
|
-
@"deviceType": deviceType,
|
|
325
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
326
|
-
}];
|
|
327
|
-
} else {
|
|
328
|
-
RCTLogError(@"Failed to connect to FLIR device: %@", error.localizedDescription);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
#pragma mark - FLIRDiscoveryEventDelegate
|
|
333
|
-
|
|
334
|
-
- (void)cameraFound:(FLIRIdentity *)identity
|
|
335
|
-
{
|
|
336
|
-
// Store the found camera identity
|
|
337
|
-
self.connectedIdentity = identity;
|
|
338
|
-
|
|
339
|
-
// Check if this is an emulator
|
|
340
|
-
self.isEmulatorMode = (identity.communicationInterface == FLIRCommunicationInterfaceEmulator);
|
|
341
|
-
self.isPhysicalDeviceConnected = !self.isEmulatorMode;
|
|
342
|
-
|
|
343
|
-
// Emit connection event
|
|
344
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
345
|
-
@"identity": @{
|
|
346
|
-
@"deviceId": identity.deviceId ?: @"Unknown",
|
|
347
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
348
|
-
},
|
|
349
|
-
@"deviceType": self.isEmulatorMode ? @"emulator" : @"physical",
|
|
350
|
-
@"isEmulator": @(self.isEmulatorMode)
|
|
351
|
-
}];
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
- (void)cameraLost:(FLIRIdentity *)identity
|
|
355
|
-
{
|
|
356
|
-
// Clear connection state
|
|
357
|
-
self.connectedIdentity = nil;
|
|
358
|
-
self.isEmulatorMode = NO;
|
|
359
|
-
self.isPhysicalDeviceConnected = NO;
|
|
360
|
-
|
|
361
|
-
// Emit disconnection event
|
|
362
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{
|
|
363
|
-
@"identity": @{
|
|
364
|
-
@"deviceId": identity.deviceId ?: @"Unknown",
|
|
365
|
-
@"isEmulator": @(identity.communicationInterface == FLIRCommunicationInterfaceEmulator)
|
|
366
|
-
},
|
|
367
|
-
@"wasEmulator": @(identity.communicationInterface == FLIRCommunicationInterfaceEmulator)
|
|
368
|
-
}];
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
- (void)discoveryError:(NSString *)error netServiceError:(int)nsnetserviceserror on:(FLIRCommunicationInterface)iface
|
|
372
|
-
{
|
|
373
|
-
// Emit error event
|
|
374
|
-
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirError" body:@{
|
|
375
|
-
@"error": error ?: @"Unknown discovery error",
|
|
376
|
-
@"type": @"discovery",
|
|
377
|
-
@"interface": @(iface)
|
|
378
|
-
}];
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
@end
|
|
1
|
+
#import "FlirModule.h"
|
|
2
|
+
#import "FlirEventEmitter.h"
|
|
3
|
+
#import "FlirState.h"
|
|
4
|
+
#import <ThermalSDK/ThermalSDK.h>
|
|
5
|
+
#import <React/RCTLog.h>
|
|
6
|
+
|
|
7
|
+
#ifndef F1_gen3
|
|
8
|
+
#define F1_gen3 FLIRCameraType_flirOne
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@interface FlirModule() <FLIRDiscoveryEventDelegate>
|
|
13
|
+
@property (nonatomic, strong) FLIRDiscovery *discovery;
|
|
14
|
+
@property (nonatomic, strong) FLIRCamera *camera;
|
|
15
|
+
@property (nonatomic, strong) FLIRIdentity *connectedIdentity;
|
|
16
|
+
@property (nonatomic, assign) BOOL isEmulatorMode;
|
|
17
|
+
@property (nonatomic, assign) BOOL isPhysicalDeviceConnected;
|
|
18
|
+
@end
|
|
19
|
+
|
|
20
|
+
@implementation FlirModule
|
|
21
|
+
|
|
22
|
+
RCT_EXPORT_MODULE(FlirIOS);
|
|
23
|
+
|
|
24
|
+
RCT_EXPORT_METHOD(startDiscovery)
|
|
25
|
+
{
|
|
26
|
+
// Hook into ThermalSDK discovery when ready. For now, emit an event to JS.
|
|
27
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
28
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"msg": @"discovery-started" }];
|
|
29
|
+
RCTLogInfo(@"FLIR discovery started (placeholder)");
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
RCT_EXPORT_METHOD(stopDiscovery)
|
|
34
|
+
{
|
|
35
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
36
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{ @"msg": @"discovery-stopped" }];
|
|
37
|
+
RCTLogInfo(@"FLIR discovery stopped (placeholder)");
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
RCT_EXPORT_METHOD(connect:(NSDictionary *)identity resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
42
|
+
{
|
|
43
|
+
// TODO: implement real connect using ThermalSDK and identity info
|
|
44
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
45
|
+
RCTLogInfo(@"Flir connect called (placeholder)");
|
|
46
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"identity": identity ?: @{} }];
|
|
47
|
+
resolve(@(YES));
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
RCT_EXPORT_METHOD(disconnect)
|
|
52
|
+
{
|
|
53
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
54
|
+
RCTLogInfo(@"Flir disconnect called (placeholder)");
|
|
55
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{}];
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
RCT_EXPORT_METHOD(getTemperatureAt:(nonnull NSNumber *)x y:(nonnull NSNumber *)y resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
60
|
+
// Return the last sampled temperature from the preview/state singleton
|
|
61
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
62
|
+
double t = [FlirState shared].lastTemperature;
|
|
63
|
+
if (isnan(t)) {
|
|
64
|
+
resolve([NSNull null]);
|
|
65
|
+
} else {
|
|
66
|
+
resolve(@(t));
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
RCT_EXPORT_METHOD(isEmulator:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
72
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
73
|
+
resolve(@(self.isEmulatorMode));
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
RCT_EXPORT_METHOD(isDeviceConnected:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
78
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
79
|
+
resolve(@(self.isPhysicalDeviceConnected));
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
RCT_EXPORT_METHOD(getConnectedDeviceInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
84
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
85
|
+
if (self.connectedIdentity == nil) {
|
|
86
|
+
resolve(@"Not connected");
|
|
87
|
+
} else if (self.isEmulatorMode) {
|
|
88
|
+
resolve([NSString stringWithFormat:@"Emulator (%@)", [self.connectedIdentity deviceId]]);
|
|
89
|
+
} else {
|
|
90
|
+
resolve([NSString stringWithFormat:@"Physical device (%@)", [self.connectedIdentity deviceId]]);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
RCT_EXPORT_METHOD(startEmulatorMode:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
96
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
97
|
+
[self initializeEmulatorMode];
|
|
98
|
+
resolve(@(YES));
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
- (void)initializeEmulatorMode
|
|
103
|
+
{
|
|
104
|
+
if (!self.discovery) {
|
|
105
|
+
self.discovery = [[FLIRDiscovery alloc] init];
|
|
106
|
+
self.discovery.delegate = self;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Create emulator identity for testing; use FLIRCameraType for compatibility
|
|
110
|
+
FLIRIdentity *emulatorIdentity = [[FLIRIdentity alloc] initWithEmulatorType:FLIRCameraType_flirOne];
|
|
111
|
+
if (emulatorIdentity) {
|
|
112
|
+
self.connectedIdentity = emulatorIdentity;
|
|
113
|
+
self.isEmulatorMode = YES;
|
|
114
|
+
self.isPhysicalDeviceConnected = NO;
|
|
115
|
+
|
|
116
|
+
// Start discovery for emulator
|
|
117
|
+
[self.discovery start:FLIRCommunicationInterfaceEmulator cameraType:FLIRCameraType_flirOne];
|
|
118
|
+
|
|
119
|
+
// Emit connection event
|
|
120
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
121
|
+
@"identity": @{
|
|
122
|
+
@"deviceId": [emulatorIdentity deviceId] ?: @"Emulator",
|
|
123
|
+
@"isEmulator": @(YES)
|
|
124
|
+
},
|
|
125
|
+
@"deviceType": @"emulator",
|
|
126
|
+
@"isEmulator": @(YES)
|
|
127
|
+
}];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#pragma mark - FLIRDiscoveryEventDelegate
|
|
132
|
+
|
|
133
|
+
- (void)cameraDiscovered:(FLIRDiscoveredCamera *)discoveredCamera {
|
|
134
|
+
FLIRIdentity *identity = discoveredCamera.identity;
|
|
135
|
+
|
|
136
|
+
BOOL isRealDevice = ([identity communicationInterface] != FLIRCommunicationInterfaceEmulator);
|
|
137
|
+
|
|
138
|
+
if (isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
139
|
+
self.connectedIdentity = identity;
|
|
140
|
+
self.isEmulatorMode = NO;
|
|
141
|
+
self.isPhysicalDeviceConnected = YES;
|
|
142
|
+
[self connectToDevice:identity];
|
|
143
|
+
} else if (!isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
144
|
+
self.connectedIdentity = identity;
|
|
145
|
+
self.isEmulatorMode = YES;
|
|
146
|
+
self.isPhysicalDeviceConnected = NO;
|
|
147
|
+
[self connectToDevice:identity];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#pragma mark - Helper Methods
|
|
152
|
+
|
|
153
|
+
- (void)connectToDevice:(FLIRIdentity *)identity {
|
|
154
|
+
if (!self.camera) {
|
|
155
|
+
self.camera = [[FLIRCamera alloc] init];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
NSError *error;
|
|
159
|
+
BOOL connected = [self.camera connect:identity error:&error];
|
|
160
|
+
|
|
161
|
+
if (connected) {
|
|
162
|
+
NSString *deviceType = self.isEmulatorMode ? @"emulator" : @"device";
|
|
163
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
164
|
+
@"identity": @{
|
|
165
|
+
@"deviceId": [identity deviceId] ?: @"Unknown",
|
|
166
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
167
|
+
},
|
|
168
|
+
@"deviceType": deviceType,
|
|
169
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
170
|
+
}];
|
|
171
|
+
} else {
|
|
172
|
+
RCTLogError(@"Failed to connect to FLIR device: %@", error.localizedDescription);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
#pragma mark - FLIRDiscoveryEventDelegate
|
|
177
|
+
|
|
178
|
+
- (void)cameraFound:(FLIRIdentity *)identity
|
|
179
|
+
{
|
|
180
|
+
self.connectedIdentity = identity;
|
|
181
|
+
self.isEmulatorMode = ([identity communicationInterface] == FLIRCommunicationInterfaceEmulator);
|
|
182
|
+
self.isPhysicalDeviceConnected = !self.isEmulatorMode;
|
|
183
|
+
|
|
184
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
185
|
+
@"identity": @{
|
|
186
|
+
@"deviceId": [identity deviceId] ?: @"Unknown",
|
|
187
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
188
|
+
},
|
|
189
|
+
@"deviceType": self.isEmulatorMode ? @"emulator" : @"physical",
|
|
190
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
191
|
+
}];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
- (void)cameraLost:(FLIRIdentity *)identity
|
|
195
|
+
{
|
|
196
|
+
self.connectedIdentity = nil;
|
|
197
|
+
self.isEmulatorMode = NO;
|
|
198
|
+
self.isPhysicalDeviceConnected = NO;
|
|
199
|
+
|
|
200
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{
|
|
201
|
+
@"identity": @{
|
|
202
|
+
@"deviceId": [identity deviceId] ?: @"Unknown",
|
|
203
|
+
@"isEmulator": @([identity communicationInterface] == FLIRCommunicationInterfaceEmulator)
|
|
204
|
+
},
|
|
205
|
+
@"wasEmulator": @([identity communicationInterface] == FLIRCommunicationInterfaceEmulator)
|
|
206
|
+
}];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
- (void)discoveryError:(NSString *)error netServiceError:(int)nsnetserviceserror on:(FLIRCommunicationInterface)iface
|
|
210
|
+
{
|
|
211
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirError" body:@{
|
|
212
|
+
@"error": error ?: @"Unknown discovery error",
|
|
213
|
+
@"type": @"discovery",
|
|
214
|
+
@"interface": @(iface)
|
|
215
|
+
}];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@end
|
|
219
|
+
#import "FlirModule.h"
|
|
220
|
+
#import "FlirEventEmitter.h"
|
|
221
|
+
#import "FlirState.h"
|
|
222
|
+
#import <ThermalSDK/ThermalSDK.h>
|
|
223
|
+
#ifndef F1_gen3
|
|
224
|
+
#define F1_gen3 FLIRCameraType_flirOne
|
|
225
|
+
#endif
|
|
226
|
+
#import <React/RCTLog.h>
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@interface FlirModule()
|
|
230
|
+
<FLIRDiscoveryEventDelegate>
|
|
231
|
+
@property (nonatomic, strong) FLIRDiscovery *discovery;
|
|
232
|
+
@property (nonatomic, strong) FLIRCamera *camera;
|
|
233
|
+
@property (nonatomic, strong) FLIRIdentity *connectedIdentity;
|
|
234
|
+
@property (nonatomic, assign) BOOL isEmulatorMode;
|
|
235
|
+
@property (nonatomic, assign) BOOL isPhysicalDeviceConnected;
|
|
236
|
+
@end
|
|
237
|
+
|
|
238
|
+
@implementation FlirModule
|
|
239
|
+
|
|
240
|
+
RCT_EXPORT_MODULE(FlirIOS);
|
|
241
|
+
|
|
242
|
+
RCT_EXPORT_METHOD(startDiscovery)
|
|
243
|
+
{
|
|
244
|
+
// Hook into ThermalSDK discovery when ready. For now, emit an event to JS.
|
|
245
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
246
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"msg": @"discovery-started" }];
|
|
247
|
+
RCTLogInfo(@"FLIR discovery started (placeholder)");
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
RCT_EXPORT_METHOD(stopDiscovery)
|
|
252
|
+
{
|
|
253
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
254
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{ @"msg": @"discovery-stopped" }];
|
|
255
|
+
RCTLogInfo(@"FLIR discovery stopped (placeholder)");
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
RCT_EXPORT_METHOD(connect:(NSDictionary *)identity resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
260
|
+
{
|
|
261
|
+
// TODO: implement real connect using ThermalSDK and identity info
|
|
262
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
263
|
+
RCTLogInfo(@"Flir connect called (placeholder)");
|
|
264
|
+
// emit a connected event
|
|
265
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{ @"identity": identity ?: @{} }];
|
|
266
|
+
resolve(@(YES));
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
RCT_EXPORT_METHOD(disconnect)
|
|
271
|
+
{
|
|
272
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
273
|
+
RCTLogInfo(@"Flir disconnect called (placeholder)");
|
|
274
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{}];
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
RCT_EXPORT_METHOD(getTemperatureAt:(nonnull NSNumber *)x y:(nonnull NSNumber *)y resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n // Return the last sampled temperature from the preview/state singleton\n dispatch_async(dispatch_get_main_queue(), ^{\n double t = [FlirState shared].lastTemperature;\n if (isnan(t)) {\n resolve([NSNull null]);\n } else {\n resolve(@(t));\n }\n });\n}\n\nRCT_EXPORT_METHOD(isEmulator:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n resolve(@(self.isEmulatorMode));\n });\n}\n\nRCT_EXPORT_METHOD(isDeviceConnected:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n resolve(@(self.isPhysicalDeviceConnected));\n });\n}\n\nRCT_EXPORT_METHOD(getConnectedDeviceInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n if (self.connectedIdentity == nil) {\n resolve(@\"Not connected\");\n } else if (self.isEmulatorMode) {\n resolve([NSString stringWithFormat:@\"Emulator (%@)\", self.connectedIdentity.deviceId]);\n } else {\n resolve([NSString stringWithFormat:@\"Physical device (%@)\", self.connectedIdentity.deviceId]);\n }\n });\n}\n\nRCT_EXPORT_METHOD(startEmulatorMode:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)\n{\n dispatch_async(dispatch_get_main_queue(), ^{\n [self initializeEmulatorMode];\n resolve(@(YES));\n });\n}\n\n- (void)initializeEmulatorMode\n{\n if (!self.discovery) {\n self.discovery = [[FLIRDiscovery alloc] init];\n self.discovery.delegate = self;\n }\n \n // Create emulator identity for testing\n FLIRIdentity *emulatorIdentity = [[FLIRIdentity alloc] initWithEmulatorType:F1_gen3];\n if (emulatorIdentity) {\n self.connectedIdentity = emulatorIdentity;\n self.isEmulatorMode = YES;\n self.isPhysicalDeviceConnected = NO;\n \n // Start discovery for emulator\n [self.discovery start:FLIRCommunicationInterfaceEmulator cameraType:F1_gen3];\n \n // Emit connection event\n [[FlirEventEmitter shared] sendDeviceEvent:@\"FlirDeviceConnected\" body:@{\n @\"identity\": @{\n @\"deviceId\": emulatorIdentity.deviceId ?: @\"Emulator\",\n @\"isEmulator\": @(YES)\n },\n @\"deviceType\": @\"emulator\",\n @\"isEmulator\": @(YES)\n }];\n }\n}
|
|
279
|
+
|
|
280
|
+
#pragma mark - FLIRDiscoveryEventDelegate
|
|
281
|
+
|
|
282
|
+
- (void)cameraDiscovered:(FLIRDiscoveredCamera *)discoveredCamera {
|
|
283
|
+
FLIRIdentity *identity = discoveredCamera.identity;
|
|
284
|
+
|
|
285
|
+
// Check if this is a real device or emulator
|
|
286
|
+
BOOL isRealDevice = (identity.communicationInterface != FLIRCommunicationInterfaceEmulator);
|
|
287
|
+
|
|
288
|
+
if (isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
289
|
+
// Prioritize real device over emulator
|
|
290
|
+
self.connectedIdentity = identity;
|
|
291
|
+
self.isEmulatorMode = NO;
|
|
292
|
+
self.isPhysicalDeviceConnected = YES;
|
|
293
|
+
|
|
294
|
+
// Connect to real device
|
|
295
|
+
[self connectToDevice:identity];
|
|
296
|
+
} else if (!isRealDevice && !self.isPhysicalDeviceConnected) {
|
|
297
|
+
// Use emulator if no real device found
|
|
298
|
+
self.connectedIdentity = identity;
|
|
299
|
+
self.isEmulatorMode = YES;
|
|
300
|
+
self.isPhysicalDeviceConnected = NO;
|
|
301
|
+
|
|
302
|
+
// Connect to emulator
|
|
303
|
+
[self connectToDevice:identity];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
#pragma mark - Helper Methods
|
|
308
|
+
|
|
309
|
+
- (void)connectToDevice:(FLIRIdentity *)identity {
|
|
310
|
+
if (!self.camera) {
|
|
311
|
+
self.camera = [[FLIRCamera alloc] init];
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
NSError *error;
|
|
315
|
+
BOOL connected = [self.camera connect:identity error:&error];
|
|
316
|
+
|
|
317
|
+
if (connected) {
|
|
318
|
+
NSString *deviceType = self.isEmulatorMode ? @"emulator" : @"device";
|
|
319
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
320
|
+
@"identity": @{
|
|
321
|
+
@"deviceId": identity.deviceId ?: @"Unknown",
|
|
322
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
323
|
+
},
|
|
324
|
+
@"deviceType": deviceType,
|
|
325
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
326
|
+
}];
|
|
327
|
+
} else {
|
|
328
|
+
RCTLogError(@"Failed to connect to FLIR device: %@", error.localizedDescription);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
#pragma mark - FLIRDiscoveryEventDelegate
|
|
333
|
+
|
|
334
|
+
- (void)cameraFound:(FLIRIdentity *)identity
|
|
335
|
+
{
|
|
336
|
+
// Store the found camera identity
|
|
337
|
+
self.connectedIdentity = identity;
|
|
338
|
+
|
|
339
|
+
// Check if this is an emulator
|
|
340
|
+
self.isEmulatorMode = (identity.communicationInterface == FLIRCommunicationInterfaceEmulator);
|
|
341
|
+
self.isPhysicalDeviceConnected = !self.isEmulatorMode;
|
|
342
|
+
|
|
343
|
+
// Emit connection event
|
|
344
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceConnected" body:@{
|
|
345
|
+
@"identity": @{
|
|
346
|
+
@"deviceId": identity.deviceId ?: @"Unknown",
|
|
347
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
348
|
+
},
|
|
349
|
+
@"deviceType": self.isEmulatorMode ? @"emulator" : @"physical",
|
|
350
|
+
@"isEmulator": @(self.isEmulatorMode)
|
|
351
|
+
}];
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
- (void)cameraLost:(FLIRIdentity *)identity
|
|
355
|
+
{
|
|
356
|
+
// Clear connection state
|
|
357
|
+
self.connectedIdentity = nil;
|
|
358
|
+
self.isEmulatorMode = NO;
|
|
359
|
+
self.isPhysicalDeviceConnected = NO;
|
|
360
|
+
|
|
361
|
+
// Emit disconnection event
|
|
362
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirDeviceDisconnected" body:@{
|
|
363
|
+
@"identity": @{
|
|
364
|
+
@"deviceId": identity.deviceId ?: @"Unknown",
|
|
365
|
+
@"isEmulator": @(identity.communicationInterface == FLIRCommunicationInterfaceEmulator)
|
|
366
|
+
},
|
|
367
|
+
@"wasEmulator": @(identity.communicationInterface == FLIRCommunicationInterfaceEmulator)
|
|
368
|
+
}];
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
- (void)discoveryError:(NSString *)error netServiceError:(int)nsnetserviceserror on:(FLIRCommunicationInterface)iface
|
|
372
|
+
{
|
|
373
|
+
// Emit error event
|
|
374
|
+
[[FlirEventEmitter shared] sendDeviceEvent:@"FlirError" body:@{
|
|
375
|
+
@"error": error ?: @"Unknown discovery error",
|
|
376
|
+
@"type": @"discovery",
|
|
377
|
+
@"interface": @(iface)
|
|
378
|
+
}];
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
@end
|