ilabs-flir 1.0.0

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.
Files changed (97) hide show
  1. package/Flir.podspec +31 -0
  2. package/README.md +1271 -0
  3. package/android/Flir/build.gradle.kts +80 -0
  4. package/android/Flir/libs/flir-stubs.jar +0 -0
  5. package/android/Flir/src/main/AndroidManifest.xml +31 -0
  6. package/android/Flir/src/main/java/flir/android/CameraHandler.java +194 -0
  7. package/android/Flir/src/main/java/flir/android/FlirController.kt +11 -0
  8. package/android/Flir/src/main/java/flir/android/FlirDownloadManager.kt +75 -0
  9. package/android/Flir/src/main/java/flir/android/FlirDownloadPackage.kt +16 -0
  10. package/android/Flir/src/main/java/flir/android/FlirFrameCache.kt +6 -0
  11. package/android/Flir/src/main/java/flir/android/FlirManager.kt +248 -0
  12. package/android/Flir/src/main/java/flir/android/FlirModule.kt +74 -0
  13. package/android/Flir/src/main/java/flir/android/FlirPackage.kt +16 -0
  14. package/android/Flir/src/main/java/flir/android/FlirSDKLoader.kt +191 -0
  15. package/android/Flir/src/main/java/flir/android/FlirStatus.kt +12 -0
  16. package/android/Flir/src/main/java/flir/android/FlirView.kt +48 -0
  17. package/android/Flir/src/main/java/flir/android/FlirViewManager.kt +13 -0
  18. package/android/Flir/src/main/java/flir/android/FrameDataHolder.java +14 -0
  19. package/app.plugin.js +264 -0
  20. package/expo-module.config.json +6 -0
  21. package/ios/Flir/Framework/ThermalSDK/FLIRBattery.h +76 -0
  22. package/ios/Flir/Framework/ThermalSDK/FLIRCalibration.h +108 -0
  23. package/ios/Flir/Framework/ThermalSDK/FLIRCamera.h +156 -0
  24. package/ios/Flir/Framework/ThermalSDK/FLIRCameraDeviceInfo.h +53 -0
  25. package/ios/Flir/Framework/ThermalSDK/FLIRCameraEvent.h +132 -0
  26. package/ios/Flir/Framework/ThermalSDK/FLIRCameraImport.h +204 -0
  27. package/ios/Flir/Framework/ThermalSDK/FLIRColorDistributionSettings.h +204 -0
  28. package/ios/Flir/Framework/ThermalSDK/FLIRColorizer.h +82 -0
  29. package/ios/Flir/Framework/ThermalSDK/FLIRDiscoveredCamera.h +44 -0
  30. package/ios/Flir/Framework/ThermalSDK/FLIRDiscovery.h +132 -0
  31. package/ios/Flir/Framework/ThermalSDK/FLIRDisplaySettings.h +29 -0
  32. package/ios/Flir/Framework/ThermalSDK/FLIRFocus.h +70 -0
  33. package/ios/Flir/Framework/ThermalSDK/FLIRFusion.h +192 -0
  34. package/ios/Flir/Framework/ThermalSDK/FLIRFusionController.h +136 -0
  35. package/ios/Flir/Framework/ThermalSDK/FLIRFusionTransformation.h +35 -0
  36. package/ios/Flir/Framework/ThermalSDK/FLIRIdentity.h +264 -0
  37. package/ios/Flir/Framework/ThermalSDK/FLIRImageBase.h +196 -0
  38. package/ios/Flir/Framework/ThermalSDK/FLIRImageColorizer.h +26 -0
  39. package/ios/Flir/Framework/ThermalSDK/FLIRImageStatistics.h +61 -0
  40. package/ios/Flir/Framework/ThermalSDK/FLIRIsotherms.h +208 -0
  41. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementArea.h +38 -0
  42. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementCollection.h +147 -0
  43. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementDelta.h +62 -0
  44. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementDimensions.h +33 -0
  45. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementEllipse.h +49 -0
  46. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementLine.h +66 -0
  47. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementMarker.h +69 -0
  48. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementParameters.h +41 -0
  49. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementRectangle.h +36 -0
  50. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementReference.h +27 -0
  51. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementShape.h +46 -0
  52. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementSpot.h +33 -0
  53. package/ios/Flir/Framework/ThermalSDK/FLIRMeasurementsController.h +160 -0
  54. package/ios/Flir/Framework/ThermalSDK/FLIRMeterLinkSensorPoll.h +247 -0
  55. package/ios/Flir/Framework/ThermalSDK/FLIROverlayController.h +27 -0
  56. package/ios/Flir/Framework/ThermalSDK/FLIRPalette.h +60 -0
  57. package/ios/Flir/Framework/ThermalSDK/FLIRPaletteController.h +36 -0
  58. package/ios/Flir/Framework/ThermalSDK/FLIRPaletteManager.h +97 -0
  59. package/ios/Flir/Framework/ThermalSDK/FLIRQuantification.h +55 -0
  60. package/ios/Flir/Framework/ThermalSDK/FLIRRemoteControl.h +393 -0
  61. package/ios/Flir/Framework/ThermalSDK/FLIRRenderer.h +35 -0
  62. package/ios/Flir/Framework/ThermalSDK/FLIRRendererImpl.h +17 -0
  63. package/ios/Flir/Framework/ThermalSDK/FLIRScale.h +99 -0
  64. package/ios/Flir/Framework/ThermalSDK/FLIRScaleController.h +44 -0
  65. package/ios/Flir/Framework/ThermalSDK/FLIRStream.h +109 -0
  66. package/ios/Flir/Framework/ThermalSDK/FLIRStreamer.h +124 -0
  67. package/ios/Flir/Framework/ThermalSDK/FLIRSystem.h +40 -0
  68. package/ios/Flir/Framework/ThermalSDK/FLIRTemperatureRange.h +43 -0
  69. package/ios/Flir/Framework/ThermalSDK/FLIRThermalDelta.h +77 -0
  70. package/ios/Flir/Framework/ThermalSDK/FLIRThermalImage.h +331 -0
  71. package/ios/Flir/Framework/ThermalSDK/FLIRThermalImageFile.h +56 -0
  72. package/ios/Flir/Framework/ThermalSDK/FLIRThermalParameters.h +31 -0
  73. package/ios/Flir/Framework/ThermalSDK/FLIRThermalValue.h +92 -0
  74. package/ios/Flir/Framework/ThermalSDK/FLIRWirelessCameraDetails.h +88 -0
  75. package/ios/Flir/Framework/ThermalSDK/ThermalSDK.h +73 -0
  76. package/ios/Flir/SDKLoader/FlirSDKLoader.m +13 -0
  77. package/ios/Flir/SDKLoader/FlirSDKLoader.swift +175 -0
  78. package/ios/Flir/src/FlirEventEmitter.h +12 -0
  79. package/ios/Flir/src/FlirEventEmitter.m +33 -0
  80. package/ios/Flir/src/FlirModule.h +10 -0
  81. package/ios/Flir/src/FlirModule.m +381 -0
  82. package/ios/Flir/src/FlirPreviewView.h +13 -0
  83. package/ios/Flir/src/FlirPreviewView.m +24 -0
  84. package/ios/Flir/src/FlirState.h +20 -0
  85. package/ios/Flir/src/FlirState.m +79 -0
  86. package/ios/Flir/src/FlirViewManager.h +9 -0
  87. package/ios/Flir/src/FlirViewManager.m +16 -0
  88. package/package.json +61 -0
  89. package/react-native.config.js +14 -0
  90. package/scripts/copy_ios_libs.sh +32 -0
  91. package/scripts/download-sdk.js +62 -0
  92. package/scripts/prepare-binaries.sh +171 -0
  93. package/sdk-manifest.json +30 -0
  94. package/src/FlirDownload.ts +78 -0
  95. package/src/index.d.ts +17 -0
  96. package/src/index.js +7 -0
  97. package/src/index.ts +7 -0
@@ -0,0 +1,92 @@
1
+ //
2
+ // ThermalValue.h
3
+ // FLIR Thermal SDK
4
+ //
5
+ // Copyright © 2019 Teledyne FLIR. All rights reserved.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+
10
+ /** Specifies the supported temperature units. */
11
+ typedef NS_ENUM(NSUInteger, TemperatureUnit)
12
+ {
13
+ /** The Celsius temperature scale was previously known as the centigrade scale. */
14
+ CELSIUS,
15
+ /** Units in Fahrenheit. */
16
+ FAHRENHEIT,
17
+ /** The Kelvin scale is a thermodynamic (absolute) temperature scale where absolute zero, the theoretical absence of all thermal energy, is zero (0 K). */
18
+ KELVIN
19
+ };
20
+
21
+ /**
22
+ * The possible ThermalValueStates.
23
+ */
24
+ typedef NS_ENUM(NSUInteger, ThermalValueState) {
25
+ /** Value is invalid. Usually happens when calculation mask for the particular measure type (i.e. min, max, average) is not enabled. */
26
+ Invalid,
27
+ /** Value is OK. */
28
+ Ok,
29
+ /** Value is too high. */
30
+ Overflow,
31
+ /** Value is too low. */
32
+ Underflow,
33
+ /** Value is outside image. */
34
+ Outside,
35
+ /** Value is unreliable. */
36
+ Warning,
37
+ /** Value is not yet calculated, unstable image after restart/case change. */
38
+ Unstable,
39
+ /** Value is OK + compensated with a reference temperature delta. */
40
+ Delta,
41
+ }; // ThermalValueState;
42
+
43
+ /**
44
+ * This class represents an IR value with additional information.
45
+ */
46
+ @interface FLIRThermalValue : NSObject
47
+
48
+ /**
49
+ * Initialize an "OK" thermal value with specified temperature value and unit
50
+ *
51
+ * @param value Temperature value.
52
+ * @param unit Temperature unit.
53
+ */
54
+ - (instancetype)initWithValue:(double) value andUnit:(TemperatureUnit) unit;
55
+
56
+ /**
57
+ * Gets the value.
58
+ */
59
+ @property (readonly) double value;
60
+
61
+ /**
62
+ * Gets the temperature unit of the value.
63
+ */
64
+ @property (readonly) TemperatureUnit unit;
65
+
66
+ /**
67
+ * Gets the state of the value.
68
+ */
69
+ @property (readonly) ThermalValueState state;
70
+
71
+ /**
72
+ * Gets a nicely formatted string representing the value.
73
+ */
74
+ - (NSString *)description;
75
+
76
+ /** @brief Convenience function to test if two @ref FLIRThermalValue "ThermalValues" practically the same temperature with imprecise floating-point comparison.
77
+ * @param other The second (right hand side) value to compare.
78
+ * @param absError The margin of error in degrees Kelvin.
79
+ */
80
+ - (BOOL)areNear:(id)other absError: (double)absError;
81
+
82
+ /** @brief Return the corresponding thermal value in another unit */
83
+ - (FLIRThermalValue*)asCelsius;
84
+
85
+ /** @brief Return the corresponding thermal value in another unit */
86
+ - (FLIRThermalValue*)asKelvin;
87
+
88
+ /** @brief Return the corresponding thermal value in another unit */
89
+ - (FLIRThermalValue*)asFahrenheit;
90
+
91
+
92
+ @end
@@ -0,0 +1,88 @@
1
+ //
2
+ // FLIRWirelessCameraDetails.h
3
+ // ThermalSDK
4
+ //
5
+ // Created by Teledyne on 2022-08-24.
6
+ // Copyright © 2022 Teledyne FLIR. All rights reserved.
7
+ //
8
+
9
+ #import <Foundation/Foundation.h>
10
+
11
+ #import "FLIRIdentity.h"
12
+
13
+ NS_ASSUME_NONNULL_BEGIN
14
+ @class FLIRWirelessCameraDetails;
15
+
16
+ @protocol FLIRWirelessCameraDetailsEventDelegate <NSObject>
17
+ -(void) detailsUpdated:(FLIRWirelessCameraDetails *) wcd;
18
+ @end
19
+
20
+ typedef NS_ENUM(NSInteger, FLIRSignalStrength) {
21
+ /**
22
+ * @brief State in which it is possible to discover the camera.
23
+ * @note after discovery phrase camera can be moved further away from the phone and still it will be possible to connect and stream.
24
+ */
25
+ discoverable,
26
+ /** @brief Good signal, allows to live stream and interact with the camera. */
27
+ excellent,
28
+ /** @brief Signal strength is fair enough for live streaming and interaction with the camera. Minor frame drops or lag/delay may occur. */
29
+ fair,
30
+ /** @brief Weak signal may result in significant frame drops and delays in communication with the camera. */
31
+ weak,
32
+ /** @brief Bad signal will eventually result in a connection break or timeout and it will most likely be impossible to get a live stream or interact with the camera. */
33
+ bad_distance
34
+ };
35
+
36
+ @interface FLIRWirelessCameraDetails : NSObject
37
+
38
+ /// SSID/name of the FLIR ONE WiFi network.
39
+ @property (nonatomic, readonly) NSString* ssid;
40
+
41
+ /// Password for the FLIR ONE WiFi network.
42
+ @property (nonatomic, readonly) NSString* password;
43
+
44
+ /// The IP address of the F1 wireless camera i.e. 192.168.1.1.
45
+ @property (nonatomic, readonly) NSString* ipAddress;
46
+
47
+ /// Camera's firmware version.
48
+ @property (nonatomic, readonly) NSString* firmwareVersion;
49
+
50
+ /// Camera's serial number.
51
+ @property (nonatomic, readonly) NSString* serialNumber;
52
+
53
+ /// Flag determining if this is the first time setup/connection.
54
+ @property (nonatomic, readonly) BOOL firstTimeSetupFlag;
55
+
56
+ /// The transmit power in dBm. Valid range is [-127, 126]. A value of 127 (0x7F) indicates that the TX power is not present.
57
+ @property (nonatomic, readonly) NSInteger txPowerLevel;
58
+
59
+ /// Returns the received signal strength in dBm. The valid range is [-127, 126].
60
+ @property (nonatomic, readonly) NSInteger rssi;
61
+
62
+ /// Returns the distance.
63
+ @property (nonatomic, readonly) FLIRSignalStrength signal;
64
+
65
+ /// Flag determining if the default password has changed.
66
+ @property (nonatomic, readonly) BOOL passwordChangedFlag;
67
+
68
+ /// Camera's current battery level.
69
+ @property (nonatomic, readonly) NSInteger batteryLevel;
70
+
71
+ /// Camera's current battery state - charging or not.
72
+ @property (nonatomic, readonly) NSInteger batteryCharging;
73
+
74
+ /// Determines if there are active connections to the camera's WiFi network.
75
+ @property (nonatomic, readonly) NSInteger ConnectedFlag;
76
+
77
+ /// Delegate that will receive changes, useful to check distance between device and camera
78
+ @property (nonatomic, retain, nullable) id<FLIRWirelessCameraDetailsEventDelegate> delegate;
79
+
80
+ @property (nonatomic, readonly) NSInteger wifiMode;
81
+
82
+ @property (nonatomic, readonly) FLIRCameraType cameraType;
83
+
84
+ @end
85
+
86
+
87
+
88
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,73 @@
1
+ //
2
+ // ThermalSDK.h
3
+ // FLIR Thermal SDK
4
+ //
5
+ // Copyright © 2019-2024 Teledyne FLIR. All rights reserved.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+ #import <UIKit/UIKit.h>
10
+
11
+ //! Project version number for ThermalSDK.
12
+ FOUNDATION_EXPORT const double ThermalSDKVersionNumber;
13
+
14
+ //! Project version string for ThermalSDK.
15
+ FOUNDATION_EXPORT const char *ThermalSDKVersionString;
16
+
17
+ //! Project commit hash string for ThermalSDK.
18
+ FOUNDATION_EXPORT const char *ThermalSDKCommitHash;
19
+
20
+
21
+ // In this header, you should import all the public headers of your framework using statements like #import <ThermalSDK/PublicHeader.h>
22
+
23
+ #import <ThermalSDK/FLIRCamera.h>
24
+ #import <ThermalSDK/FLIRCameraDeviceInfo.h>
25
+ #import <ThermalSDK/FLIRDiscovery.h>
26
+ #import <ThermalSDK/FLIRCameraImport.h>
27
+ #import <ThermalSDK/FLIRThermalImage.h>
28
+ #import <ThermalSDK/FLIRImageBase.h>
29
+ #import <ThermalSDK/FLIRThermalImageFile.h>
30
+ #import <ThermalSDK/FLIRScale.h>
31
+ #import <ThermalSDK/FLIRFusion.h>
32
+ #import <ThermalSDK/FLIRImageStatistics.h>
33
+ #import <ThermalSDK/FLIRMeasurementSpot.h>
34
+ #import <ThermalSDK/FLIRMeasurementShape.h>
35
+ #import <ThermalSDK/FLIRMeasurementArea.h>
36
+ #import <ThermalSDK/FLIRMeasurementMarker.h>
37
+ #import <ThermalSDK/FLIRMeasurementParameters.h>
38
+ #import <ThermalSDK/FLIRThermalValue.h>
39
+ #import <ThermalSDK/FLIRThermalDelta.h>
40
+ #import <ThermalSDK/FLIRMeasurementCollection.h>
41
+ #import <ThermalSDK/FLIRMeasurementRectangle.h>
42
+ #import <ThermalSDK/FLIRMeasurementEllipse.h>
43
+ #import <ThermalSDK/FLIRMeasurementDimensions.h>
44
+ #import <ThermalSDK/FLIRMeasurementLine.h>
45
+ #import <ThermalSDK/FLIRMeasurementDelta.h>
46
+ #import <ThermalSDK/FLIRPalette.h>
47
+ #import <ThermalSDK/FLIRPaletteManager.h>
48
+ #import <ThermalSDK/FLIRCameraEvent.h>
49
+ #import <ThermalSDK/FLIRDiscoveredCamera.h>
50
+ #import <ThermalSDK/FLIRIdentity.h>
51
+ #import <ThermalSDK/FLIRRemoteControl.h>
52
+ #import <ThermalSDK/FLIRMeasurementsController.h>
53
+ #import <ThermalSDK/FLIRPaletteController.h>
54
+ #import <ThermalSDK/FLIRSystem.h>
55
+ #import <ThermalSDK/FLIRFocus.h>
56
+ #import <ThermalSDK/FLIRTemperatureRange.h>
57
+ #import <ThermalSDK/FLIRFusionController.h>
58
+ #import <ThermalSDK/FLIRCalibration.h>
59
+ #import <ThermalSDK/FLIRBattery.h>
60
+ #import <ThermalSDK/FLIRScaleController.h>
61
+ #import <ThermalSDK/FLIROverlayController.h>
62
+ #import <ThermalSDK/FLIRDisplaySettings.h>
63
+ #import <ThermalSDK/FLIRMeterLinkSensorPoll.h>
64
+ #import <ThermalSDK/FLIRColorDistributionSettings.h>
65
+ #import <ThermalSDK/FLIRStream.h>
66
+ #import <ThermalSDK/FLIRStreamer.h>
67
+ #import <ThermalSDK/FLIRRenderer.h>
68
+ #import <ThermalSDK/FLIRColorizer.h>
69
+ #import <ThermalSDK/FLIRImageColorizer.h>
70
+ #import <ThermalSDK/FLIRRendererImpl.h>
71
+ #import <ThermalSDK/FLIRWirelessCameraDetails.h>
72
+ #import <ThermalSDK/FLIRQuantification.h>
73
+
@@ -0,0 +1,13 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTEventEmitter.h>
3
+
4
+ @interface RCT_EXTERN_MODULE(FlirDownloadManager, RCTEventEmitter)
5
+
6
+ RCT_EXTERN_METHOD(isFlirAvailable:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
7
+ RCT_EXTERN_METHOD(getDownloadSize:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
8
+ RCT_EXTERN_METHOD(downloadFlirSDK:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
9
+ RCT_EXTERN_METHOD(cancelDownload)
10
+ RCT_EXTERN_METHOD(loadFlirFramework:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
11
+ RCT_EXTERN_METHOD(deleteSDK:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
12
+
13
+ @end
@@ -0,0 +1,175 @@
1
+ import Foundation
2
+ import CommonCrypto
3
+
4
+ @objc(FlirSDKLoader)
5
+ public class FlirSDKLoader: RCTEventEmitter {
6
+
7
+ private var downloadTask: URLSessionDownloadTask?
8
+ private var progressObservation: NSKeyValueObservation?
9
+
10
+ // MARK: - SDK Paths
11
+
12
+ private static var sdkDirectory: URL {
13
+ FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
14
+ .appendingPathComponent("FlirSDK", isDirectory: true)
15
+ }
16
+
17
+ private static var thermalSDKPath: URL {
18
+ sdkDirectory.appendingPathComponent("ThermalSDK.framework")
19
+ }
20
+
21
+ // MARK: - RCTEventEmitter
22
+
23
+ override public static func moduleName() -> String! { "FlirDownloadManager" }
24
+ override public static func requiresMainQueueSetup() -> Bool { false }
25
+ override public func supportedEvents() -> [String]! {
26
+ ["FlirDownloadProgress", "FlirDownloadComplete", "FlirDownloadError"]
27
+ }
28
+
29
+ // MARK: - Public API
30
+
31
+ @objc func isFlirAvailable(_ resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
32
+ resolve(FileManager.default.fileExists(atPath: Self.thermalSDKPath.path))
33
+ }
34
+
35
+ @objc func getDownloadSize(_ resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
36
+ guard let manifest = loadManifest() else {
37
+ resolve(104_857_600)
38
+ return
39
+ }
40
+ resolve(manifest.ios.sizeBytes)
41
+ }
42
+
43
+ @objc func downloadFlirSDK(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
44
+ guard let manifest = loadManifest() else {
45
+ reject("E_MANIFEST", "Failed to load SDK manifest", nil)
46
+ return
47
+ }
48
+
49
+ guard let url = URL(string: manifest.ios.downloadUrl) else {
50
+ reject("E_URL", "Invalid download URL", nil)
51
+ return
52
+ }
53
+
54
+ let session = URLSession(configuration: .default)
55
+ downloadTask = session.downloadTask(with: url) { [weak self] tempURL, response, error in
56
+ guard let self = self else { return }
57
+
58
+ if let error = error {
59
+ self.sendEvent(withName: "FlirDownloadError", body: ["error": error.localizedDescription])
60
+ reject("E_DOWNLOAD", error.localizedDescription, error)
61
+ return
62
+ }
63
+
64
+ guard let tempURL = tempURL else {
65
+ self.sendEvent(withName: "FlirDownloadError", body: ["error": "No data received"])
66
+ reject("E_NODATA", "No data received", nil)
67
+ return
68
+ }
69
+
70
+ do {
71
+ // Verify checksum
72
+ let data = try Data(contentsOf: tempURL)
73
+ let hash = self.sha256(data)
74
+ guard hash == manifest.ios.sha256 else {
75
+ throw NSError(domain: "FlirSDK", code: -1,
76
+ userInfo: [NSLocalizedDescriptionKey: "Checksum verification failed"])
77
+ }
78
+
79
+ // Create SDK directory
80
+ try FileManager.default.createDirectory(at: Self.sdkDirectory,
81
+ withIntermediateDirectories: true)
82
+
83
+ // Unzip
84
+ try self.unzip(tempURL, to: Self.sdkDirectory)
85
+
86
+ self.sendEvent(withName: "FlirDownloadComplete", body: [:])
87
+ resolve(true)
88
+ } catch {
89
+ self.sendEvent(withName: "FlirDownloadError", body: ["error": error.localizedDescription])
90
+ reject("E_INSTALL", error.localizedDescription, error)
91
+ }
92
+ }
93
+
94
+ // Observe progress
95
+ progressObservation = downloadTask?.progress.observe(\.fractionCompleted) { [weak self] progress, _ in
96
+ let totalBytes = Int64(104_857_600)
97
+ let downloaded = Int64(Double(totalBytes) * progress.fractionCompleted)
98
+ self?.sendEvent(withName: "FlirDownloadProgress", body: [
99
+ "bytesDownloaded": downloaded,
100
+ "totalBytes": totalBytes,
101
+ "percent": progress.fractionCompleted * 100
102
+ ])
103
+ }
104
+
105
+ downloadTask?.resume()
106
+ }
107
+
108
+ @objc func cancelDownload() {
109
+ downloadTask?.cancel()
110
+ progressObservation?.invalidate()
111
+ }
112
+
113
+ @objc func loadFlirFramework(_ resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
114
+ let binaryPath = Self.thermalSDKPath.appendingPathComponent("ThermalSDK").path
115
+
116
+ guard let handle = dlopen(binaryPath, RTLD_NOW | RTLD_GLOBAL) else {
117
+ let error = String(cString: dlerror())
118
+ reject("E_LOAD", "Failed to load SDK: \(error)", nil)
119
+ return
120
+ }
121
+
122
+ resolve(true)
123
+ }
124
+
125
+ @objc func deleteSDK(_ resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
126
+ do {
127
+ try FileManager.default.removeItem(at: Self.sdkDirectory)
128
+ resolve(true)
129
+ } catch {
130
+ reject("E_DELETE", error.localizedDescription, error)
131
+ }
132
+ }
133
+
134
+ // MARK: - Helpers
135
+
136
+ private func loadManifest() -> SDKManifest? {
137
+ guard let bundle = Bundle(identifier: "org.cocoapods.Flir"),
138
+ let url = bundle.url(forResource: "sdk-manifest", withExtension: "json"),
139
+ let data = try? Data(contentsOf: url),
140
+ let manifest = try? JSONDecoder().decode(SDKManifest.self, from: data)
141
+ else { return nil }
142
+ return manifest
143
+ }
144
+
145
+ private func sha256(_ data: Data) -> String {
146
+ var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
147
+ data.withUnsafeBytes { _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash) }
148
+ return hash.map { String(format: "%02x", $0) }.joined()
149
+ }
150
+
151
+ private func unzip(_ source: URL, to destination: URL) throws {
152
+ let process = Process()
153
+ process.executableURL = URL(fileURLWithPath: "/usr/bin/unzip")
154
+ process.arguments = ["-o", "-q", source.path, "-d", destination.path]
155
+ try process.run()
156
+ process.waitUntilExit()
157
+ guard process.terminationStatus == 0 else {
158
+ throw NSError(domain: "FlirSDK", code: Int(process.terminationStatus),
159
+ userInfo: [NSLocalizedDescriptionKey: "Unzip failed"])
160
+ }
161
+ }
162
+ }
163
+
164
+ // MARK: - Models
165
+
166
+ private struct SDKManifest: Codable {
167
+ let version: String
168
+ let ios: IOSManifest
169
+
170
+ struct IOSManifest: Codable {
171
+ let downloadUrl: String
172
+ let sha256: String
173
+ let sizeBytes: Int64
174
+ }
175
+ }
@@ -0,0 +1,12 @@
1
+ #import <React/RCTEventEmitter.h>
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ @interface FlirEventEmitter : RCTEventEmitter <RCTBridgeModule>
6
+
7
+ + (instancetype)shared;
8
+ - (void)sendDeviceEvent:(NSString *)name body:(id)body;
9
+
10
+ @end
11
+
12
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,33 @@
1
+ #import "FlirEventEmitter.h"
2
+
3
+ static FlirEventEmitter *_sharedEmitter = nil;
4
+
5
+ @implementation FlirEventEmitter
6
+
7
+ RCT_EXPORT_MODULE();
8
+
9
+ - (instancetype)init
10
+ {
11
+ if (self = [super init]) {
12
+ _sharedEmitter = self;
13
+ }
14
+ return self;
15
+ }
16
+
17
+ + (instancetype)shared
18
+ {
19
+ return _sharedEmitter;
20
+ }
21
+
22
+ - (NSArray<NSString *> *)supportedEvents
23
+ {
24
+ return @[@"FlirDeviceConnected", @"FlirDeviceDisconnected", @"FlirFrame"];
25
+ }
26
+
27
+ - (void)sendDeviceEvent:(NSString *)name body:(id)body
28
+ {
29
+ if (!_sharedEmitter) return;
30
+ [_sharedEmitter sendEventWithName:name body:body];
31
+ }
32
+
33
+ @end
@@ -0,0 +1,10 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <React/RCTBridgeModule.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ @interface FlirModule : NSObject <RCTBridgeModule>
7
+
8
+ @end
9
+
10
+ NS_ASSUME_NONNULL_END