react-native-polar-bridge 0.1.5 → 0.2.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.
- package/PolarBridge.podspec +1 -1
- package/README.md +34 -1
- package/android/generated/java/com/polarbridge/NativePolarBridgeSpec.java +4 -0
- package/android/generated/jni/RNPolarBridgeSpec-generated.cpp +6 -0
- package/android/generated/jni/react/renderer/components/RNPolarBridgeSpec/RNPolarBridgeSpecJSI-generated.cpp +8 -0
- package/android/generated/jni/react/renderer/components/RNPolarBridgeSpec/RNPolarBridgeSpecJSI.h +9 -0
- package/android/src/main/java/com/polarbridge/PolarBridgeModule.kt +18 -0
- package/ios/PolarBridge-Bridging-Header.h +3 -0
- package/ios/PolarBridge.m +31 -0
- package/ios/PolarBridge.swift +695 -0
- package/ios/generated/RNPolarBridgeSpec/RNPolarBridgeSpec-generated.mm +7 -0
- package/ios/generated/RNPolarBridgeSpec/RNPolarBridgeSpec.h +1 -0
- package/ios/generated/RNPolarBridgeSpecJSI-generated.cpp +8 -0
- package/ios/generated/RNPolarBridgeSpecJSI.h +9 -0
- package/lib/module/NativePolarBridge.ts +1 -0
- package/lib/module/index.js +5 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativePolarBridge.d.ts +1 -0
- package/lib/typescript/src/NativePolarBridge.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/NativePolarBridge.ts +1 -0
- package/src/index.tsx +5 -0
- package/ios/PolarBridge.h +0 -6
- package/ios/PolarBridge.mm +0 -18
package/PolarBridge.podspec
CHANGED
|
@@ -13,7 +13,7 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.platforms = { :ios => min_ios_version_supported }
|
|
14
14
|
s.source = { :git => "https://github.com/omatt/react-native-polar-bridge.git", :tag => "#{s.version}" }
|
|
15
15
|
|
|
16
|
-
s.source_files = "ios/**/*.{h,m,mm,cpp}"
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
|
|
17
17
|
s.private_header_files = "ios/**/*.h"
|
|
18
18
|
|
|
19
19
|
s.dependency 'PolarBleSdk', '~> 5.9.0'
|
package/README.md
CHANGED
|
@@ -12,7 +12,31 @@ npm install react-native-polar-bridge
|
|
|
12
12
|
|
|
13
13
|
This React Native library uses the [polar-ble-sdk](https://github.com/polarofficial/polar-ble-sdk).
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Supported Functions
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
| Polar SDK Feature | Android | iOS |
|
|
19
|
+
|----------------------------|---------|-----|
|
|
20
|
+
| connectToDevice |✅|✅|
|
|
21
|
+
| disconnectFromDevice |✅|✅|
|
|
22
|
+
| scanDevices() |✅|✅|
|
|
23
|
+
| fetchHrData |✅|✅|
|
|
24
|
+
| fetchAccData |✅|✅|
|
|
25
|
+
| fetchGyrData |✅|✅|
|
|
26
|
+
| fetchPpgData |✅|✅|
|
|
27
|
+
| enableSdkMode |✅|❌|
|
|
28
|
+
| disableSdkMode |✅|❌|
|
|
29
|
+
| getDeviceTime |✅|✅|
|
|
30
|
+
| setDeviceTime |✅|✅|
|
|
31
|
+
| getDiskSpace |✅|✅|
|
|
32
|
+
| startOfflineRecording |✅|❌|
|
|
33
|
+
| stopOfflineRecording |✅|❌|
|
|
34
|
+
| setPolarRecordingTrigger |✅|❌|
|
|
35
|
+
| fetchOfflineRecordings |⚠️|❌|
|
|
36
|
+
| downloadOfflineRecordings |⚠️|❌|
|
|
37
|
+
| deleteAllOfflineRecordings |✅|❌|
|
|
38
|
+
|
|
39
|
+
✅ - Implemented ❌ - Not yet implemented ⚠️ - Not fully implemented
|
|
16
40
|
|
|
17
41
|
### Connecting to Device
|
|
18
42
|
|
|
@@ -38,6 +62,15 @@ export default function App(){
|
|
|
38
62
|
disconnectFromDevice(deviceId);
|
|
39
63
|
```
|
|
40
64
|
|
|
65
|
+
### Initialize NativeModules
|
|
66
|
+
|
|
67
|
+
Import `NativeModules` from react-native to expose native code to be able to listen to emitted events.
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
const {PolarBridge} = NativeModules;
|
|
71
|
+
const polarEmitter = new NativeEventEmitter(PolarBridge);
|
|
72
|
+
```
|
|
73
|
+
|
|
41
74
|
### Scan Devices
|
|
42
75
|
|
|
43
76
|
Use `scanDevices()` to scan for nearby Polar devices
|
|
@@ -81,6 +81,10 @@ public abstract class NativePolarBridgeSpec extends ReactContextBaseJavaModule i
|
|
|
81
81
|
@DoNotStrip
|
|
82
82
|
public abstract void getDiskSpace(String deviceId, Promise promise);
|
|
83
83
|
|
|
84
|
+
@ReactMethod
|
|
85
|
+
@DoNotStrip
|
|
86
|
+
public abstract void doFactoryReset(String deviceId);
|
|
87
|
+
|
|
84
88
|
@ReactMethod
|
|
85
89
|
@DoNotStrip
|
|
86
90
|
public abstract void startOfflineRecording(String deviceId, ReadableArray features, Promise promise);
|
|
@@ -72,6 +72,11 @@ static facebook::jsi::Value __hostFunction_NativePolarBridgeSpecJSI_getDiskSpace
|
|
|
72
72
|
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, PromiseKind, "getDiskSpace", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count, cachedMethodId);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
static facebook::jsi::Value __hostFunction_NativePolarBridgeSpecJSI_doFactoryReset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
76
|
+
static jmethodID cachedMethodId = nullptr;
|
|
77
|
+
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, VoidKind, "doFactoryReset", "(Ljava/lang/String;)V", args, count, cachedMethodId);
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
static facebook::jsi::Value __hostFunction_NativePolarBridgeSpecJSI_startOfflineRecording(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
76
81
|
static jmethodID cachedMethodId = nullptr;
|
|
77
82
|
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, PromiseKind, "startOfflineRecording", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Promise;)V", args, count, cachedMethodId);
|
|
@@ -141,6 +146,7 @@ NativePolarBridgeSpecJSI::NativePolarBridgeSpecJSI(const JavaTurboModule::InitPa
|
|
|
141
146
|
methodMap_["getDeviceTime"] = MethodMetadata {1, __hostFunction_NativePolarBridgeSpecJSI_getDeviceTime};
|
|
142
147
|
methodMap_["setDeviceTime"] = MethodMetadata {1, __hostFunction_NativePolarBridgeSpecJSI_setDeviceTime};
|
|
143
148
|
methodMap_["getDiskSpace"] = MethodMetadata {1, __hostFunction_NativePolarBridgeSpecJSI_getDiskSpace};
|
|
149
|
+
methodMap_["doFactoryReset"] = MethodMetadata {1, __hostFunction_NativePolarBridgeSpecJSI_doFactoryReset};
|
|
144
150
|
methodMap_["startOfflineRecording"] = MethodMetadata {2, __hostFunction_NativePolarBridgeSpecJSI_startOfflineRecording};
|
|
145
151
|
methodMap_["stopOfflineRecording"] = MethodMetadata {2, __hostFunction_NativePolarBridgeSpecJSI_stopOfflineRecording};
|
|
146
152
|
methodMap_["setPolarRecordingTrigger"] = MethodMetadata {3, __hostFunction_NativePolarBridgeSpecJSI_setPolarRecordingTrigger};
|
|
@@ -92,6 +92,13 @@ static jsi::Value __hostFunction_NativePolarBridgeCxxSpecJSI_getDiskSpace(jsi::R
|
|
|
92
92
|
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
|
+
static jsi::Value __hostFunction_NativePolarBridgeCxxSpecJSI_doFactoryReset(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
96
|
+
static_cast<NativePolarBridgeCxxSpecJSI *>(&turboModule)->doFactoryReset(
|
|
97
|
+
rt,
|
|
98
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
|
|
99
|
+
);
|
|
100
|
+
return jsi::Value::undefined();
|
|
101
|
+
}
|
|
95
102
|
static jsi::Value __hostFunction_NativePolarBridgeCxxSpecJSI_startOfflineRecording(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
96
103
|
return static_cast<NativePolarBridgeCxxSpecJSI *>(&turboModule)->startOfflineRecording(
|
|
97
104
|
rt,
|
|
@@ -180,6 +187,7 @@ NativePolarBridgeCxxSpecJSI::NativePolarBridgeCxxSpecJSI(std::shared_ptr<CallInv
|
|
|
180
187
|
methodMap_["getDeviceTime"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_getDeviceTime};
|
|
181
188
|
methodMap_["setDeviceTime"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_setDeviceTime};
|
|
182
189
|
methodMap_["getDiskSpace"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_getDiskSpace};
|
|
190
|
+
methodMap_["doFactoryReset"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_doFactoryReset};
|
|
183
191
|
methodMap_["startOfflineRecording"] = MethodMetadata {2, __hostFunction_NativePolarBridgeCxxSpecJSI_startOfflineRecording};
|
|
184
192
|
methodMap_["stopOfflineRecording"] = MethodMetadata {2, __hostFunction_NativePolarBridgeCxxSpecJSI_stopOfflineRecording};
|
|
185
193
|
methodMap_["setPolarRecordingTrigger"] = MethodMetadata {3, __hostFunction_NativePolarBridgeCxxSpecJSI_setPolarRecordingTrigger};
|
package/android/generated/jni/react/renderer/components/RNPolarBridgeSpec/RNPolarBridgeSpecJSI.h
CHANGED
|
@@ -32,6 +32,7 @@ public:
|
|
|
32
32
|
virtual jsi::Value getDeviceTime(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
33
33
|
virtual void setDeviceTime(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
34
34
|
virtual jsi::Value getDiskSpace(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
35
|
+
virtual void doFactoryReset(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
35
36
|
virtual jsi::Value startOfflineRecording(jsi::Runtime &rt, jsi::String deviceId, jsi::Array features) = 0;
|
|
36
37
|
virtual jsi::Value stopOfflineRecording(jsi::Runtime &rt, jsi::String deviceId, jsi::Array features) = 0;
|
|
37
38
|
virtual void setPolarRecordingTrigger(jsi::Runtime &rt, jsi::String deviceId, double recordingMode, jsi::Array features) = 0;
|
|
@@ -169,6 +170,14 @@ private:
|
|
|
169
170
|
return bridging::callFromJs<jsi::Value>(
|
|
170
171
|
rt, &T::getDiskSpace, jsInvoker_, instance_, std::move(deviceId));
|
|
171
172
|
}
|
|
173
|
+
void doFactoryReset(jsi::Runtime &rt, jsi::String deviceId) override {
|
|
174
|
+
static_assert(
|
|
175
|
+
bridging::getParameterCount(&T::doFactoryReset) == 2,
|
|
176
|
+
"Expected doFactoryReset(...) to have 2 parameters");
|
|
177
|
+
|
|
178
|
+
return bridging::callFromJs<void>(
|
|
179
|
+
rt, &T::doFactoryReset, jsInvoker_, instance_, std::move(deviceId));
|
|
180
|
+
}
|
|
172
181
|
jsi::Value startOfflineRecording(jsi::Runtime &rt, jsi::String deviceId, jsi::Array features) override {
|
|
173
182
|
static_assert(
|
|
174
183
|
bridging::getParameterCount(&T::startOfflineRecording) == 3,
|
|
@@ -564,6 +564,24 @@ class PolarBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
564
564
|
)
|
|
565
565
|
}
|
|
566
566
|
|
|
567
|
+
override fun doFactoryReset(deviceId: String) {
|
|
568
|
+
val calendar = Calendar.getInstance()
|
|
569
|
+
calendar.time = Date()
|
|
570
|
+
Log.e(TAG, "Set device: $deviceId time to ${calendar.time}")
|
|
571
|
+
try {
|
|
572
|
+
api.doFactoryReset(deviceId, preservePairingInformation = true)
|
|
573
|
+
.observeOn(AndroidSchedulers.mainThread())
|
|
574
|
+
.subscribe(
|
|
575
|
+
{
|
|
576
|
+
Log.d(TAG, "send do factory reset to device")
|
|
577
|
+
},
|
|
578
|
+
{ error: Throwable -> Log.e(TAG, "doFactoryReset() failed: $error") }
|
|
579
|
+
)
|
|
580
|
+
} catch(polarInvalidArgument: PolarInvalidArgument){
|
|
581
|
+
Log.e(TAG, "Failed to do factory reset. Reason $polarInvalidArgument ")
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
567
585
|
override fun scanDevices() {
|
|
568
586
|
Log.e(TAG, "Scan Devices")
|
|
569
587
|
val isDisposed = scanDisposable?.isDisposed ?: true
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(PolarBridge, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(multiply:(nonnull NSNumber *)a withB:(nonnull NSNumber *)b)
|
|
7
|
+
|
|
8
|
+
RCT_EXTERN_METHOD(connectToDevice:(NSString *)deviceId
|
|
9
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
10
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
11
|
+
|
|
12
|
+
RCT_EXTERN_METHOD(disconnectFromDevice:(NSString *)deviceId)
|
|
13
|
+
RCT_EXTERN_METHOD(scanDevices)
|
|
14
|
+
RCT_EXTERN_METHOD(fetchHrData:(NSString *)deviceId)
|
|
15
|
+
RCT_EXTERN_METHOD(disposeHrStream)
|
|
16
|
+
RCT_EXTERN_METHOD(fetchAccData:(NSString *)deviceId)
|
|
17
|
+
RCT_EXTERN_METHOD(disposeAccStream)
|
|
18
|
+
RCT_EXTERN_METHOD(fetchGyrData:(NSString *)deviceId)
|
|
19
|
+
RCT_EXTERN_METHOD(disposeGyrStream)
|
|
20
|
+
RCT_EXTERN_METHOD(fetchPpgData:(NSString *)deviceId)
|
|
21
|
+
RCT_EXTERN_METHOD(disposePpgStream)
|
|
22
|
+
RCT_EXTERN_METHOD(setDeviceTime:(NSString *)deviceId)
|
|
23
|
+
RCT_EXTERN_METHOD(getDeviceTime:(NSString *)deviceId
|
|
24
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
25
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
26
|
+
RCT_EXTERN_METHOD(getDiskSpace:(NSString *)deviceId
|
|
27
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
28
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
29
|
+
RCT_EXTERN_METHOD(doFactoryReset:(NSString *)deviceId)
|
|
30
|
+
|
|
31
|
+
@end
|
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
import CoreBluetooth
|
|
2
|
+
import PolarBleSdk
|
|
3
|
+
import React
|
|
4
|
+
import RxSwift
|
|
5
|
+
|
|
6
|
+
enum PolarEvent: String, CaseIterable {
|
|
7
|
+
case onDeviceFound
|
|
8
|
+
case onScanError
|
|
9
|
+
case onScanComplete
|
|
10
|
+
case PolarHrData
|
|
11
|
+
case PolarHrError
|
|
12
|
+
case PolarHrComplete
|
|
13
|
+
case PolarAccData
|
|
14
|
+
case PolarAccError
|
|
15
|
+
case PolarAccComplete
|
|
16
|
+
case PolarGyrData
|
|
17
|
+
case PolarGyrError
|
|
18
|
+
case PolarGyrComplete
|
|
19
|
+
case PolarPpgData
|
|
20
|
+
case PolarPpgError
|
|
21
|
+
case PolarPpgComplete
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
enum PolarBleError: Error {
|
|
25
|
+
case unconfigured
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@objc(PolarBridge)
|
|
29
|
+
class PolarBridge: RCTEventEmitter, ObservableObject
|
|
30
|
+
{
|
|
31
|
+
private var api: PolarBleApi?
|
|
32
|
+
private var deviceConnected = false
|
|
33
|
+
private var batteryReceived = false
|
|
34
|
+
private var connectionData: [String: Any] = [:]
|
|
35
|
+
private var pendingResolver: RCTPromiseResolveBlock?
|
|
36
|
+
private var pendingRejecter: RCTPromiseRejectBlock?
|
|
37
|
+
|
|
38
|
+
private var scanDisposable: Disposable?
|
|
39
|
+
private var hrDisposable: Disposable?
|
|
40
|
+
private var isHrStreaming = false
|
|
41
|
+
private var accDisposable: Disposable?
|
|
42
|
+
private var isAccStreaming = false
|
|
43
|
+
private var gyrDisposable: Disposable?
|
|
44
|
+
private var isGyrStreaming = false
|
|
45
|
+
private var ppgDisposable: Disposable?
|
|
46
|
+
private var isPpgStreaming = false
|
|
47
|
+
private let disposeBag = DisposeBag()
|
|
48
|
+
|
|
49
|
+
@objc
|
|
50
|
+
func multiply(_ a: NSNumber,withB b: NSNumber) -> NSNumber {
|
|
51
|
+
let result = a.doubleValue * b.doubleValue
|
|
52
|
+
NSLog("Hello from Swift! Result: \(result)")
|
|
53
|
+
return NSNumber(value: result)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
override init() {
|
|
57
|
+
super.init()
|
|
58
|
+
api = PolarBleApiDefaultImpl.polarImplementation(DispatchQueue.main, features: [PolarBleSdkFeature.feature_hr,
|
|
59
|
+
PolarBleSdkFeature.feature_polar_sdk_mode,
|
|
60
|
+
PolarBleSdkFeature.feature_battery_info,
|
|
61
|
+
PolarBleSdkFeature.feature_device_info,
|
|
62
|
+
PolarBleSdkFeature.feature_polar_online_streaming,
|
|
63
|
+
PolarBleSdkFeature.feature_polar_offline_recording,
|
|
64
|
+
PolarBleSdkFeature.feature_polar_device_time_setup,
|
|
65
|
+
PolarBleSdkFeature.feature_polar_h10_exercise_recording])
|
|
66
|
+
|
|
67
|
+
setObservers()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private func setObservers() {
|
|
71
|
+
api?.observer = self
|
|
72
|
+
api?.deviceInfoObserver = self
|
|
73
|
+
// api?.powerStateObserver = self
|
|
74
|
+
// api?.deviceHrObserver = self
|
|
75
|
+
// api?.deviceFeaturesObserver = self
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@objc(connectToDevice:resolver:rejecter:)
|
|
79
|
+
func connectToDevice(
|
|
80
|
+
_ identifier: String,
|
|
81
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
82
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
83
|
+
) {
|
|
84
|
+
do {
|
|
85
|
+
guard let api = api else {
|
|
86
|
+
// throw PolarBleError.unconfigured
|
|
87
|
+
reject("UNCONFIGURED", "Polar API not initialized", nil)
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
pendingResolver = resolve
|
|
92
|
+
pendingRejecter = reject
|
|
93
|
+
deviceConnected = false
|
|
94
|
+
batteryReceived = false
|
|
95
|
+
connectionData = [:]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
try api.connectToDevice(identifier)
|
|
99
|
+
NSLog("PolarBridge: Connecting to device \(identifier)")
|
|
100
|
+
} catch {
|
|
101
|
+
NSLog("PolarBridge: Failed to connect \(error.localizedDescription)")
|
|
102
|
+
reject("INVALID_ARGUMENT", "Invalid device ID", error)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@objc(disconnectFromDevice:)
|
|
107
|
+
func disconnectFromDevice(_ identifier: String) {
|
|
108
|
+
guard let api = api else { return }
|
|
109
|
+
do {
|
|
110
|
+
try api.disconnectFromDevice(identifier)
|
|
111
|
+
NSLog("PolarBridge: Disconnected from \(identifier)")
|
|
112
|
+
} catch {
|
|
113
|
+
NSLog("PolarBridge: Failed to disconnect \(error.localizedDescription)")
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
func requestStreamSettings(_ identifier: String,
|
|
118
|
+
feature: PolarDeviceDataType
|
|
119
|
+
) -> Observable<PolarSensorSetting> {
|
|
120
|
+
|
|
121
|
+
guard let api = api else {
|
|
122
|
+
return Observable.error(NSError(domain: "PolarBridge", code: -1, userInfo: [
|
|
123
|
+
NSLocalizedDescriptionKey: "Polar API not initialized"
|
|
124
|
+
]))
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let availableSettings = api.requestStreamSettings(identifier, feature: feature)
|
|
128
|
+
|
|
129
|
+
let allSettings = api.requestFullStreamSettings(identifier, feature: feature)
|
|
130
|
+
.catch { error in
|
|
131
|
+
NSLog("Full stream settings NOT available for \(feature). Reason: \(error.localizedDescription)")
|
|
132
|
+
return Single.just(PolarSensorSetting([:]))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return Single.zip(availableSettings, allSettings)
|
|
136
|
+
.flatMap { available, all -> Single<PolarSensorSetting> in
|
|
137
|
+
|
|
138
|
+
if available.settings.isEmpty {
|
|
139
|
+
return Single.error(NSError(domain: "PolarBridge", code: -2, userInfo: [
|
|
140
|
+
NSLocalizedDescriptionKey: "Settings are not available"
|
|
141
|
+
]))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
NSLog("Feature \(feature) available settings: \(available.settings)")
|
|
145
|
+
NSLog("Feature \(feature) all settings: \(all.settings)")
|
|
146
|
+
|
|
147
|
+
for setting in available.settings {
|
|
148
|
+
NSLog("Available Setting: \(setting)")
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
for setting in all.settings {
|
|
152
|
+
NSLog("All Setting: \(setting)")
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Return default settings (same as Kotlin: sensorSettings.first)
|
|
156
|
+
return Single.just(available)
|
|
157
|
+
}
|
|
158
|
+
.asObservable()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@objc(fetchHrData:)
|
|
162
|
+
func fetchHrData(_ deviceId: String) {
|
|
163
|
+
NSLog("PolarBridge: Fetch HR Data called on: \(deviceId)")
|
|
164
|
+
|
|
165
|
+
guard let api = api else {
|
|
166
|
+
NSLog("PolarBridge: Polar API not initialized")
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Dispose previous subscription if running
|
|
171
|
+
if isHrStreaming {
|
|
172
|
+
disposeHrStream()
|
|
173
|
+
NSLog("PolarBridge: HR Stream stopped")
|
|
174
|
+
sendEvent(withName: PolarEvent.PolarHrComplete.rawValue, body: ["message": "HR Stream stopped"])
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
isHrStreaming = true
|
|
179
|
+
|
|
180
|
+
// Start HR streaming
|
|
181
|
+
hrDisposable = api.startHrStreaming(deviceId)
|
|
182
|
+
.observe(on: MainScheduler.instance)
|
|
183
|
+
.subscribe(
|
|
184
|
+
onNext: { [weak self] hrData in
|
|
185
|
+
guard let self = self else { return }
|
|
186
|
+
NSLog("PolarBridge: HR data samples count: \(hrData.count)")
|
|
187
|
+
|
|
188
|
+
for sample in hrData {
|
|
189
|
+
NSLog("HR bpm: \(sample.hr), rrs: \(sample.rrsMs), rrAvailable: \(sample.rrAvailable), contactStatus: \(sample.contactStatus), contactStatusSupported: \(sample.contactStatusSupported)")
|
|
190
|
+
|
|
191
|
+
// Create dictionary to send as event
|
|
192
|
+
var event: [String: Any] = [:]
|
|
193
|
+
event["hr"] = sample.hr
|
|
194
|
+
event["rrsMs"] = sample.rrsMs
|
|
195
|
+
event["rrAvailable"] = sample.rrAvailable
|
|
196
|
+
event["contactStatus"] = sample.contactStatus
|
|
197
|
+
event["contactStatusSupported"] = sample.contactStatusSupported
|
|
198
|
+
|
|
199
|
+
self.sendEvent(withName: PolarEvent.PolarHrData.rawValue, body: event)
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
onError: { [weak self] error in
|
|
203
|
+
guard let self = self else { return }
|
|
204
|
+
NSLog("PolarBridge: HR stream failed: \(error.localizedDescription)")
|
|
205
|
+
self.sendEvent(withName: PolarEvent.PolarHrError.rawValue, body: ["error": error.localizedDescription])
|
|
206
|
+
},
|
|
207
|
+
onCompleted: { [weak self] in
|
|
208
|
+
guard let self = self else { return }
|
|
209
|
+
NSLog("PolarBridge: HR stream complete")
|
|
210
|
+
self.sendEvent(withName: PolarEvent.PolarHrComplete.rawValue, body: ["message": "HR stream complete"])
|
|
211
|
+
}
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
hrDisposable?.disposed(by: disposeBag)
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@objc(fetchAccData:)
|
|
219
|
+
func fetchAccData(_ deviceId: String) {
|
|
220
|
+
NSLog("PolarBridge: Fetch ACC Data called on: \(deviceId)")
|
|
221
|
+
|
|
222
|
+
guard let api = api else {
|
|
223
|
+
NSLog("PolarBridge: Polar API not initialized")
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Stop existing ACC stream if running
|
|
228
|
+
if isAccStreaming {
|
|
229
|
+
disposeAccStream()
|
|
230
|
+
NSLog("PolarBridge: ACC Stream stopped")
|
|
231
|
+
sendEvent(withName: PolarEvent.PolarAccComplete.rawValue, body: ["message": "ACC Stream stopped"])
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
isAccStreaming = true
|
|
236
|
+
|
|
237
|
+
accDisposable = requestStreamSettings(deviceId, feature: .acc)
|
|
238
|
+
.flatMap { settings in
|
|
239
|
+
api.startAccStreaming(deviceId, settings: settings)
|
|
240
|
+
}
|
|
241
|
+
.observe(on: MainScheduler.instance)
|
|
242
|
+
.subscribe(
|
|
243
|
+
onNext: { [weak self] accData in
|
|
244
|
+
guard let self = self else { return }
|
|
245
|
+
|
|
246
|
+
for sample in accData.samples {
|
|
247
|
+
NSLog("ACC x: \(sample.x) y: \(sample.y) z: \(sample.z) timestamp: \(sample.timeStamp)")
|
|
248
|
+
|
|
249
|
+
var event: [String: Any] = [:]
|
|
250
|
+
event["accX"] = sample.x
|
|
251
|
+
event["accY"] = sample.y
|
|
252
|
+
event["accZ"] = sample.z
|
|
253
|
+
event["accTimestamp"] = Double(sample.timeStamp) // RN doesn’t support int64
|
|
254
|
+
|
|
255
|
+
self.sendEvent(withName: PolarEvent.PolarAccData.rawValue, body: event)
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
onError: { [weak self] error in
|
|
259
|
+
guard let self = self else { return }
|
|
260
|
+
|
|
261
|
+
NSLog("PolarBridge: ACC stream failed: \(error.localizedDescription)")
|
|
262
|
+
|
|
263
|
+
self.sendEvent(
|
|
264
|
+
withName: PolarEvent.PolarAccError.rawValue,
|
|
265
|
+
body: ["error": error.localizedDescription]
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
self.accDisposable = nil
|
|
269
|
+
},
|
|
270
|
+
onCompleted: { [weak self] in
|
|
271
|
+
guard let self = self else { return }
|
|
272
|
+
|
|
273
|
+
NSLog("PolarBridge: ACC stream complete")
|
|
274
|
+
|
|
275
|
+
self.sendEvent(
|
|
276
|
+
withName: PolarEvent.PolarAccComplete.rawValue,
|
|
277
|
+
body: ["message": "ACC stream complete"]
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
self.accDisposable = nil
|
|
281
|
+
}
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
accDisposable?.disposed(by: disposeBag)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
@objc(fetchGyrData:)
|
|
288
|
+
func fetchGyrData(_ deviceId: String) {
|
|
289
|
+
NSLog("PolarBridge: Fetch Gyroscope Data called on: \(deviceId)")
|
|
290
|
+
|
|
291
|
+
guard let api = api else {
|
|
292
|
+
NSLog("PolarBridge: Polar API not initialized")
|
|
293
|
+
return
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if isGyrStreaming {
|
|
297
|
+
disposeGyrStream()
|
|
298
|
+
NSLog("PolarBridge: GYR Stream stopped")
|
|
299
|
+
sendEvent(withName: PolarEvent.PolarAccComplete.rawValue, body: ["message": "GYR Stream stopped"])
|
|
300
|
+
return
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
isGyrStreaming = true
|
|
304
|
+
|
|
305
|
+
gyrDisposable = requestStreamSettings(deviceId, feature: .gyro)
|
|
306
|
+
.flatMap { settings in
|
|
307
|
+
api.startGyroStreaming(deviceId, settings: settings).asObservable()
|
|
308
|
+
}
|
|
309
|
+
.observe(on: MainScheduler.instance)
|
|
310
|
+
.subscribe(
|
|
311
|
+
onNext: { [weak self] gyrData in
|
|
312
|
+
guard let self = self else { return }
|
|
313
|
+
|
|
314
|
+
for sample in gyrData.samples {
|
|
315
|
+
NSLog("GYR x: \(sample.x) y: \(sample.y) z: \(sample.z) timestamp: \(sample.timeStamp)")
|
|
316
|
+
|
|
317
|
+
var event: [String: Any] = [:]
|
|
318
|
+
|
|
319
|
+
// JS does NOT support Float — convert to String
|
|
320
|
+
event["gyrX"] = "\(sample.x)"
|
|
321
|
+
event["gyrY"] = "\(sample.y)"
|
|
322
|
+
event["gyrZ"] = "\(sample.z)"
|
|
323
|
+
|
|
324
|
+
// JS does NOT support Int64 — convert to Double
|
|
325
|
+
event["gyrTimestamp"] = Double(sample.timeStamp)
|
|
326
|
+
|
|
327
|
+
self.sendEvent(
|
|
328
|
+
withName: PolarEvent.PolarGyrData.rawValue,
|
|
329
|
+
body: event
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
onError: { [weak self] error in
|
|
334
|
+
guard let self = self else { return }
|
|
335
|
+
|
|
336
|
+
NSLog("PolarBridge: GYR stream failed: \(error.localizedDescription)")
|
|
337
|
+
|
|
338
|
+
self.sendEvent(
|
|
339
|
+
withName: PolarEvent.PolarGyrError.rawValue,
|
|
340
|
+
body: ["error": error.localizedDescription]
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
self.gyrDisposable = nil
|
|
344
|
+
},
|
|
345
|
+
onCompleted: { [weak self] in
|
|
346
|
+
guard let self = self else { return }
|
|
347
|
+
|
|
348
|
+
NSLog("PolarBridge: GYR stream complete")
|
|
349
|
+
|
|
350
|
+
self.sendEvent(
|
|
351
|
+
withName: PolarEvent.PolarGyrComplete.rawValue,
|
|
352
|
+
body: ["message": "GYR stream complete"]
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
self.gyrDisposable = nil
|
|
356
|
+
}
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
gyrDisposable?.disposed(by: disposeBag)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
@objc(fetchPpgData:)
|
|
363
|
+
func fetchPpgData(_ deviceId: String) {
|
|
364
|
+
NSLog("PolarBridge: Fetch PPG Data called on: \(deviceId)")
|
|
365
|
+
|
|
366
|
+
guard let api = api else {
|
|
367
|
+
NSLog("PolarBridge: Polar API not initialized")
|
|
368
|
+
return
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if isPpgStreaming {
|
|
372
|
+
disposePpgStream()
|
|
373
|
+
NSLog("PolarBridge: PPG Stream stopped")
|
|
374
|
+
sendEvent(withName: PolarEvent.PolarAccComplete.rawValue, body: ["message": "PPG Stream stopped"])
|
|
375
|
+
return
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
isPpgStreaming = true
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
ppgDisposable = requestStreamSettings(deviceId, feature: .ppg)
|
|
382
|
+
.flatMap { settings in
|
|
383
|
+
api.startPpgStreaming(deviceId, settings: settings).asObservable()
|
|
384
|
+
}
|
|
385
|
+
.observe(on: MainScheduler.instance)
|
|
386
|
+
.subscribe(
|
|
387
|
+
onNext: { [weak self] ppgData in
|
|
388
|
+
guard let self = self else { return }
|
|
389
|
+
|
|
390
|
+
// Only handle PPG3_AMBIENT1 type (just like Kotlin)
|
|
391
|
+
if ppgData.type == PpgDataType.ppg3_ambient1 {
|
|
392
|
+
for sample in ppgData.samples {
|
|
393
|
+
|
|
394
|
+
NSLog("PPG ppg0: \(sample.channelSamples[0]) ppg1: \(sample.channelSamples[1]) ppg2: \(sample.channelSamples[2]) ambient: \(sample.channelSamples[3]) ts: \(sample.timeStamp)")
|
|
395
|
+
|
|
396
|
+
var event: [String: Any] = [:]
|
|
397
|
+
|
|
398
|
+
// Float → String (React Native cannot handle Float)
|
|
399
|
+
event["ppg0"] = "\(sample.channelSamples[0])"
|
|
400
|
+
event["ppg1"] = "\(sample.channelSamples[1])"
|
|
401
|
+
event["ppg2"] = "\(sample.channelSamples[2])"
|
|
402
|
+
event["ambient"] = "\(sample.channelSamples[3])"
|
|
403
|
+
|
|
404
|
+
// Int64 timestamp → Double
|
|
405
|
+
event["ppgTimestamp"] = Double(sample.timeStamp)
|
|
406
|
+
|
|
407
|
+
self.sendEvent(
|
|
408
|
+
withName: PolarEvent.PolarPpgData.rawValue,
|
|
409
|
+
body: event
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
onError: { [weak self] error in
|
|
415
|
+
guard let self = self else { return }
|
|
416
|
+
|
|
417
|
+
NSLog("PolarBridge: PPG stream failed: \(error.localizedDescription)")
|
|
418
|
+
|
|
419
|
+
self.sendEvent(
|
|
420
|
+
withName: PolarEvent.PolarPpgError.rawValue,
|
|
421
|
+
body: ["error": error.localizedDescription]
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
self.ppgDisposable = nil
|
|
425
|
+
},
|
|
426
|
+
onCompleted: { [weak self] in
|
|
427
|
+
guard let self = self else { return }
|
|
428
|
+
|
|
429
|
+
NSLog("PolarBridge: PPG stream complete")
|
|
430
|
+
|
|
431
|
+
self.sendEvent(
|
|
432
|
+
withName: PolarEvent.PolarPpgComplete.rawValue,
|
|
433
|
+
body: ["message": "PPG stream complete"]
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
self.ppgDisposable = nil
|
|
437
|
+
}
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
ppgDisposable?.disposed(by: disposeBag)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
@objc func disposeHrStream(){
|
|
444
|
+
isHrStreaming = false
|
|
445
|
+
hrDisposable?.dispose()
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
@objc func disposeAccStream(){
|
|
449
|
+
isAccStreaming = false
|
|
450
|
+
accDisposable?.dispose()
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
@objc func disposeGyrStream(){
|
|
454
|
+
isGyrStreaming = false
|
|
455
|
+
gyrDisposable?.dispose()
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
@objc func disposePpgStream(){
|
|
459
|
+
isPpgStreaming = false
|
|
460
|
+
ppgDisposable?.dispose()
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
private func disposeAllStreams() {
|
|
464
|
+
disposeHrStream()
|
|
465
|
+
disposeAccStream()
|
|
466
|
+
disposeGyrStream()
|
|
467
|
+
disposeAccStream()
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
@objc(setDeviceTime:)
|
|
471
|
+
func setDeviceTime(_ deviceId: String) {
|
|
472
|
+
NSLog("PolarBridge: Set device time for: \(deviceId)")
|
|
473
|
+
|
|
474
|
+
guard let api = api else {
|
|
475
|
+
NSLog("PolarBridge: Polar API not initialized")
|
|
476
|
+
return
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
let now = Date()
|
|
480
|
+
let timeZone = TimeZone.current
|
|
481
|
+
NSLog("PolarBridge: Set device: \(deviceId) time to \(now)")
|
|
482
|
+
|
|
483
|
+
api.setLocalTime(deviceId, time: now, zone: timeZone)
|
|
484
|
+
.observe(on: MainScheduler.instance)
|
|
485
|
+
.subscribe(
|
|
486
|
+
onCompleted: {
|
|
487
|
+
let timeSetString = "Time \(now) set to device"
|
|
488
|
+
NSLog("PolarBridge: \(timeSetString)")
|
|
489
|
+
},
|
|
490
|
+
onError: { error in
|
|
491
|
+
NSLog("PolarBridge: Set time failed: \(error.localizedDescription)")
|
|
492
|
+
}
|
|
493
|
+
)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
@objc(getDeviceTime:resolver:rejecter:)
|
|
497
|
+
func getDeviceTime(
|
|
498
|
+
_ deviceId: String,
|
|
499
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
500
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
501
|
+
) {
|
|
502
|
+
NSLog("PolarBridge: Get device time for: \(deviceId)")
|
|
503
|
+
|
|
504
|
+
guard let api = api else {
|
|
505
|
+
reject("UNCONFIGURED", "Polar API not initialized", nil)
|
|
506
|
+
return
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
api.getLocalTime(deviceId)
|
|
510
|
+
.observe(on: MainScheduler.instance)
|
|
511
|
+
.subscribe(
|
|
512
|
+
onSuccess: { date in
|
|
513
|
+
let timeGetString = "\(date) read from the device"
|
|
514
|
+
NSLog("PolarBridge: \(timeGetString)")
|
|
515
|
+
|
|
516
|
+
let result: [String: Any] = [
|
|
517
|
+
"time": "\(date)",
|
|
518
|
+
"timeMs": Double(date.timeIntervalSince1970 * 1000)
|
|
519
|
+
]
|
|
520
|
+
|
|
521
|
+
resolve(result)
|
|
522
|
+
},
|
|
523
|
+
onFailure: { error in
|
|
524
|
+
NSLog("PolarBridge: Get time failed: \(error.localizedDescription)")
|
|
525
|
+
reject("GET_DEVICE_TIME_ERROR", "Failed to get device time", error)
|
|
526
|
+
}
|
|
527
|
+
)
|
|
528
|
+
.disposed(by: disposeBag)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
@objc(getDiskSpace:resolver:rejecter:)
|
|
532
|
+
func getDiskSpace(
|
|
533
|
+
_ deviceId: String,
|
|
534
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
535
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
536
|
+
) {
|
|
537
|
+
NSLog("PolarBridge: Get Disk Space")
|
|
538
|
+
|
|
539
|
+
guard let api = api else {
|
|
540
|
+
reject("UNCONFIGURED", "Polar API not initialized", nil)
|
|
541
|
+
return
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
api.getDiskSpace(deviceId)
|
|
545
|
+
.observe(on: MainScheduler.instance)
|
|
546
|
+
.subscribe(
|
|
547
|
+
onSuccess: { diskSpace in
|
|
548
|
+
NSLog("Disk space left: \(diskSpace.freeSpace)/\(diskSpace.totalSpace) Bytes")
|
|
549
|
+
|
|
550
|
+
// React Native doesn't support Int64: convert to Double
|
|
551
|
+
let result: [String: Any] = [
|
|
552
|
+
"freeSpace": Double(diskSpace.freeSpace),
|
|
553
|
+
"totalSpace": Double(diskSpace.totalSpace)
|
|
554
|
+
]
|
|
555
|
+
|
|
556
|
+
resolve(result)
|
|
557
|
+
},
|
|
558
|
+
onFailure: { error in
|
|
559
|
+
NSLog("Get disk space failed: \(error.localizedDescription)")
|
|
560
|
+
reject("GET_DISK_SPACE_ERROR", "Failed to get device disk space", error)
|
|
561
|
+
}
|
|
562
|
+
)
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
@objc(doFactoryReset:)
|
|
566
|
+
func doFactoryReset(_ deviceId: String) {
|
|
567
|
+
NSLog("PolarBridge: do factory reset for: \(deviceId)")
|
|
568
|
+
|
|
569
|
+
guard let api = api else {
|
|
570
|
+
NSLog("PolarBridge: Polar API not initialized")
|
|
571
|
+
return
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
api.doFactoryReset(deviceId, preservePairingInformation: true)
|
|
575
|
+
.observe(on: MainScheduler.instance)
|
|
576
|
+
.subscribe(
|
|
577
|
+
onCompleted: {
|
|
578
|
+
NSLog("PolarBridge: send do factory reset to device")
|
|
579
|
+
},
|
|
580
|
+
onError: { error in
|
|
581
|
+
NSLog("PolarBridge: do factory reset failed: \(error.localizedDescription)")
|
|
582
|
+
}
|
|
583
|
+
)
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Returns promise for connecting to the device
|
|
587
|
+
private func maybeResolve() {
|
|
588
|
+
if deviceConnected && batteryReceived {
|
|
589
|
+
pendingResolver?(connectionData)
|
|
590
|
+
pendingResolver = nil
|
|
591
|
+
pendingRejecter = nil
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Emit events
|
|
596
|
+
override func sendEvent(withName name: String!, body: Any!) {
|
|
597
|
+
super.sendEvent(withName: name, body: body)
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
override func supportedEvents() -> [String]! {
|
|
601
|
+
return PolarEvent.allCases.map { $0.rawValue }
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
605
|
+
return true
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
@objc func scanDevices() {
|
|
609
|
+
NSLog("PolarBridge: Scan Devices triggered")
|
|
610
|
+
|
|
611
|
+
// If already scanning, stop and complete
|
|
612
|
+
if let disposable = scanDisposable {
|
|
613
|
+
disposable.dispose()
|
|
614
|
+
scanDisposable = nil
|
|
615
|
+
NSLog("PolarBridge: Scan stopped")
|
|
616
|
+
sendEvent(withName: PolarEvent.onScanComplete.rawValue, body: ["message": "Scan stopped"])
|
|
617
|
+
return
|
|
618
|
+
} else {
|
|
619
|
+
// scanDisposable is nil
|
|
620
|
+
NSLog("PolarBridge: No active scan")
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
guard let api = api else {
|
|
624
|
+
NSLog("PolarBridge API not initialized")
|
|
625
|
+
return
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Start scanning
|
|
629
|
+
scanDisposable = api.searchForDevice()
|
|
630
|
+
.observe(on: MainScheduler.instance)
|
|
631
|
+
.subscribe(
|
|
632
|
+
onNext: { [weak self] polarDeviceInfo in
|
|
633
|
+
guard let self = self else { return }
|
|
634
|
+
NSLog("PolarBridge: Device found \(polarDeviceInfo.deviceId)")
|
|
635
|
+
|
|
636
|
+
let device: [String: Any] = [
|
|
637
|
+
"deviceId": polarDeviceInfo.deviceId,
|
|
638
|
+
"address": polarDeviceInfo.address ?? "",
|
|
639
|
+
"rssi": polarDeviceInfo.rssi,
|
|
640
|
+
"name": polarDeviceInfo.name ?? "",
|
|
641
|
+
"isConnectable": polarDeviceInfo.connectable
|
|
642
|
+
]
|
|
643
|
+
|
|
644
|
+
self.sendEvent(withName: PolarEvent.onDeviceFound.rawValue, body: device)
|
|
645
|
+
},
|
|
646
|
+
onError: { [weak self] error in
|
|
647
|
+
guard let self = self else { return }
|
|
648
|
+
NSLog("PolarBridge: Scan failed \(error.localizedDescription)")
|
|
649
|
+
self.sendEvent(withName: PolarEvent.onScanError.rawValue, body: ["message": error.localizedDescription])
|
|
650
|
+
},
|
|
651
|
+
onCompleted: { [weak self] in
|
|
652
|
+
guard let self = self else { return }
|
|
653
|
+
NSLog("PolarBridge: Scan complete")
|
|
654
|
+
self.sendEvent(withName: PolarEvent.onScanComplete.rawValue, body: ["message": "Scan complete"])
|
|
655
|
+
}
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
scanDisposable?.disposed(by: disposeBag)
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// MARK: - PolarBleApiObserver
|
|
663
|
+
extension PolarBridge : PolarBleApiObserver {
|
|
664
|
+
func deviceConnecting(_ polarDeviceInfo: PolarDeviceInfo) {
|
|
665
|
+
NSLog("Polar: Device connecting: \(polarDeviceInfo)")
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
func deviceConnected(_ polarDeviceInfo: PolarDeviceInfo) {
|
|
669
|
+
NSLog("Polar: Device connected: \(polarDeviceInfo.deviceId)")
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
func deviceDisconnected(_ polarDeviceInfo: PolarDeviceInfo, pairingError: Bool) {
|
|
673
|
+
NSLog("Polar: Device disconnected: \(polarDeviceInfo.deviceId) Pairing error: \(pairingError)")
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// MARK: - PolarBleApiDeviceInfoObserver
|
|
678
|
+
extension PolarBridge: PolarBleApiDeviceInfoObserver {
|
|
679
|
+
func disInformationReceivedWithKeysAsStrings(_ identifier: String, key: String, value: String) {
|
|
680
|
+
// NSLog("Polar: disInfoKeys: \(identifier) value: \(key)")
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
func disInformationReceived(_ identifier: String, uuid: CBUUID, value: String) {
|
|
684
|
+
// NSLog("Polar: dis info: \(uuid.uuidString) value: \(value)")
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
func batteryLevelReceived(_ identifier: String, batteryLevel: UInt) {
|
|
688
|
+
NSLog("Polar: Battery for \(identifier): \(batteryLevel)%")
|
|
689
|
+
connectionData["batteryLevel"] = Int(batteryLevel)
|
|
690
|
+
connectionData["connectedDeviceId"] = identifier
|
|
691
|
+
deviceConnected = true
|
|
692
|
+
batteryReceived = true
|
|
693
|
+
maybeResolve()
|
|
694
|
+
}
|
|
695
|
+
}
|
|
@@ -74,6 +74,10 @@ namespace facebook::react {
|
|
|
74
74
|
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "getDiskSpace", @selector(getDiskSpace:resolve:reject:), args, count);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
static facebook::jsi::Value __hostFunction_NativePolarBridgeSpecJSI_doFactoryReset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
78
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "doFactoryReset", @selector(doFactoryReset:), args, count);
|
|
79
|
+
}
|
|
80
|
+
|
|
77
81
|
static facebook::jsi::Value __hostFunction_NativePolarBridgeSpecJSI_startOfflineRecording(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
78
82
|
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "startOfflineRecording", @selector(startOfflineRecording:features:resolve:reject:), args, count);
|
|
79
83
|
}
|
|
@@ -157,6 +161,9 @@ namespace facebook::react {
|
|
|
157
161
|
methodMap_["getDiskSpace"] = MethodMetadata {1, __hostFunction_NativePolarBridgeSpecJSI_getDiskSpace};
|
|
158
162
|
|
|
159
163
|
|
|
164
|
+
methodMap_["doFactoryReset"] = MethodMetadata {1, __hostFunction_NativePolarBridgeSpecJSI_doFactoryReset};
|
|
165
|
+
|
|
166
|
+
|
|
160
167
|
methodMap_["startOfflineRecording"] = MethodMetadata {2, __hostFunction_NativePolarBridgeSpecJSI_startOfflineRecording};
|
|
161
168
|
|
|
162
169
|
|
|
@@ -54,6 +54,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
54
54
|
- (void)getDiskSpace:(NSString *)deviceId
|
|
55
55
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
56
56
|
reject:(RCTPromiseRejectBlock)reject;
|
|
57
|
+
- (void)doFactoryReset:(NSString *)deviceId;
|
|
57
58
|
- (void)startOfflineRecording:(NSString *)deviceId
|
|
58
59
|
features:(NSArray *)features
|
|
59
60
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
@@ -92,6 +92,13 @@ static jsi::Value __hostFunction_NativePolarBridgeCxxSpecJSI_getDiskSpace(jsi::R
|
|
|
92
92
|
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
|
+
static jsi::Value __hostFunction_NativePolarBridgeCxxSpecJSI_doFactoryReset(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
96
|
+
static_cast<NativePolarBridgeCxxSpecJSI *>(&turboModule)->doFactoryReset(
|
|
97
|
+
rt,
|
|
98
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
|
|
99
|
+
);
|
|
100
|
+
return jsi::Value::undefined();
|
|
101
|
+
}
|
|
95
102
|
static jsi::Value __hostFunction_NativePolarBridgeCxxSpecJSI_startOfflineRecording(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
96
103
|
return static_cast<NativePolarBridgeCxxSpecJSI *>(&turboModule)->startOfflineRecording(
|
|
97
104
|
rt,
|
|
@@ -180,6 +187,7 @@ NativePolarBridgeCxxSpecJSI::NativePolarBridgeCxxSpecJSI(std::shared_ptr<CallInv
|
|
|
180
187
|
methodMap_["getDeviceTime"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_getDeviceTime};
|
|
181
188
|
methodMap_["setDeviceTime"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_setDeviceTime};
|
|
182
189
|
methodMap_["getDiskSpace"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_getDiskSpace};
|
|
190
|
+
methodMap_["doFactoryReset"] = MethodMetadata {1, __hostFunction_NativePolarBridgeCxxSpecJSI_doFactoryReset};
|
|
183
191
|
methodMap_["startOfflineRecording"] = MethodMetadata {2, __hostFunction_NativePolarBridgeCxxSpecJSI_startOfflineRecording};
|
|
184
192
|
methodMap_["stopOfflineRecording"] = MethodMetadata {2, __hostFunction_NativePolarBridgeCxxSpecJSI_stopOfflineRecording};
|
|
185
193
|
methodMap_["setPolarRecordingTrigger"] = MethodMetadata {3, __hostFunction_NativePolarBridgeCxxSpecJSI_setPolarRecordingTrigger};
|
|
@@ -32,6 +32,7 @@ public:
|
|
|
32
32
|
virtual jsi::Value getDeviceTime(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
33
33
|
virtual void setDeviceTime(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
34
34
|
virtual jsi::Value getDiskSpace(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
35
|
+
virtual void doFactoryReset(jsi::Runtime &rt, jsi::String deviceId) = 0;
|
|
35
36
|
virtual jsi::Value startOfflineRecording(jsi::Runtime &rt, jsi::String deviceId, jsi::Array features) = 0;
|
|
36
37
|
virtual jsi::Value stopOfflineRecording(jsi::Runtime &rt, jsi::String deviceId, jsi::Array features) = 0;
|
|
37
38
|
virtual void setPolarRecordingTrigger(jsi::Runtime &rt, jsi::String deviceId, double recordingMode, jsi::Array features) = 0;
|
|
@@ -169,6 +170,14 @@ private:
|
|
|
169
170
|
return bridging::callFromJs<jsi::Value>(
|
|
170
171
|
rt, &T::getDiskSpace, jsInvoker_, instance_, std::move(deviceId));
|
|
171
172
|
}
|
|
173
|
+
void doFactoryReset(jsi::Runtime &rt, jsi::String deviceId) override {
|
|
174
|
+
static_assert(
|
|
175
|
+
bridging::getParameterCount(&T::doFactoryReset) == 2,
|
|
176
|
+
"Expected doFactoryReset(...) to have 2 parameters");
|
|
177
|
+
|
|
178
|
+
return bridging::callFromJs<void>(
|
|
179
|
+
rt, &T::doFactoryReset, jsInvoker_, instance_, std::move(deviceId));
|
|
180
|
+
}
|
|
172
181
|
jsi::Value startOfflineRecording(jsi::Runtime &rt, jsi::String deviceId, jsi::Array features) override {
|
|
173
182
|
static_assert(
|
|
174
183
|
bridging::getParameterCount(&T::startOfflineRecording) == 3,
|
|
@@ -15,6 +15,7 @@ export interface Spec extends TurboModule {
|
|
|
15
15
|
getDeviceTime(deviceId: string): Promise<DeviceTime>;
|
|
16
16
|
setDeviceTime(deviceId: string): void;
|
|
17
17
|
getDiskSpace(deviceId: string): Promise<DiskSpace>;
|
|
18
|
+
doFactoryReset(deviceId: string): void;
|
|
18
19
|
startOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
19
20
|
stopOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
20
21
|
setPolarRecordingTrigger(deviceId: string, recordingMode: number, features: string[]): void;
|
package/lib/module/index.js
CHANGED
|
@@ -40,6 +40,9 @@ export function getDeviceTime(deviceId) {
|
|
|
40
40
|
export function getDiskSpace(deviceId) {
|
|
41
41
|
return PolarBridge.getDiskSpace(deviceId);
|
|
42
42
|
}
|
|
43
|
+
export function doFactoryReset(deviceId) {
|
|
44
|
+
return PolarBridge.doFactoryReset(deviceId);
|
|
45
|
+
}
|
|
43
46
|
export function startOfflineRecording(deviceId, features) {
|
|
44
47
|
return PolarBridge.startOfflineRecording(deviceId, features);
|
|
45
48
|
}
|
|
@@ -87,7 +90,8 @@ export const emittedEventId = Object.freeze({
|
|
|
87
90
|
POLAR_PPG_DATA: 'PolarPpgData',
|
|
88
91
|
POLAR_PPG_ERROR: 'PolarPpgError',
|
|
89
92
|
POLAR_PPG_COMPLETE: 'PolarPpgComplete',
|
|
90
|
-
POLAR_DISK_SPACE: 'PolarDiskSpace'
|
|
93
|
+
POLAR_DISK_SPACE: 'PolarDiskSpace',
|
|
94
|
+
POLAR_OFFLINE_RECORDING: 'PolarOfflineRecording'
|
|
91
95
|
});
|
|
92
96
|
export const OfflineRecordingFeature = Object.freeze({
|
|
93
97
|
OFFLINE_HR: 'OfflineHR',
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["PolarBridge","multiply","a","b","connectToDevice","deviceId","disconnectFromDevice","scanDevices","fetchHrData","fetchAccData","fetchGyrData","fetchPpgData","enableSdkMode","disableSdkMode","setDeviceTime","getDeviceTime","getDiskSpace","startOfflineRecording","features","stopOfflineRecording","setPolarRecordingTrigger","recordingMode","fetchOfflineRecordings","downloadOfflineRecordings","deleteAllOfflineRecordings","disposeHrStream","disposeAccStream","disposeGyrStream","disposePpgStream","emittedEventId","Object","freeze","SCAN_DEVICE_FOUND","SCAN_DEVICE_ERROR","SCAN_DEVICE_COMPLETE","POLAR_DEVICE_TIME","POLAR_HR_DATA","POLAR_HR_ERROR","POLAR_HR_COMPLETE","POLAR_ACC_DATA","POLAR_ACC_ERROR","POLAR_ACC_COMPLETE","POLAR_GYR_DATA","POLAR_GYR_ERROR","POLAR_GYR_COMPLETE","POLAR_PPG_DATA","POLAR_PPG_ERROR","POLAR_PPG_COMPLETE","POLAR_DISK_SPACE","OfflineRecordingFeature","OFFLINE_HR","OFFLINE_ACC","OFFLINE_GYR","OFFLINE_PPG","OFFLINE_MAG","OFFLINE_PPI","OfflineRecordingTriggerMode","TRIGGER_DISABLED","TRIGGER_SYSTEM_START","TRIGGER_EXERCISE_START"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,WAAW,MAAM,qBAAqB;AAE7C,OAAO,SAASC,QAAQA,CAACC,CAAS,EAAEC,CAAS,EAAU;EACrD,OAAOH,WAAW,CAACC,QAAQ,CAACC,CAAC,EAAEC,CAAC,CAAC;AACnC;AAEA,OAAO,SAASC,eAAeA,CAACC,QAAgB,EAAE;EAChD,OAAOL,WAAW,CAACI,eAAe,CAACC,QAAQ,CAAC;AAC9C;AAEA,OAAO,SAASC,oBAAoBA,CAACD,QAAgB,EAAE;EACrD,OAAOL,WAAW,CAACM,oBAAoB,CAACD,QAAQ,CAAC;AACnD;AAEA,OAAO,SAASE,WAAWA,CAAA,EAAG;EAC5B,OAAOP,WAAW,CAACO,WAAW,CAAC,CAAC;AAClC;AAEA,OAAO,SAASC,WAAWA,CAACH,QAAgB,EAAE;EAC5C,OAAOL,WAAW,CAACQ,WAAW,CAACH,QAAQ,CAAC;AAC1C;AAEA,OAAO,SAASI,YAAYA,CAACJ,QAAgB,EAAE;EAC7C,OAAOL,WAAW,CAACS,YAAY,CAACJ,QAAQ,CAAC;AAC3C;AAEA,OAAO,SAASK,YAAYA,CAACL,QAAgB,EAAE;EAC7C,OAAOL,WAAW,CAACU,YAAY,CAACL,QAAQ,CAAC;AAC3C;AAEA,OAAO,SAASM,YAAYA,CAACN,QAAgB,EAAE;EAC7C,OAAOL,WAAW,CAACW,YAAY,CAACN,QAAQ,CAAC;AAC3C;AAEA,OAAO,SAASO,aAAaA,CAACP,QAAgB,EAAE;EAC9C,OAAOL,WAAW,CAACY,aAAa,CAACP,QAAQ,CAAC;AAC5C;AAEA,OAAO,SAASQ,cAAcA,CAACR,QAAgB,EAAE;EAC/C,OAAOL,WAAW,CAACa,cAAc,CAACR,QAAQ,CAAC;AAC7C;AAEA,OAAO,SAASS,aAAaA,CAACT,QAAgB,EAAE;EAC9C,OAAOL,WAAW,CAACc,aAAa,CAACT,QAAQ,CAAC;AAC5C;AAEA,OAAO,SAASU,aAAaA,CAACV,QAAgB,EAAE;EAC9C,OAAOL,WAAW,CAACe,aAAa,CAACV,QAAQ,CAAC;AAC5C;AAEA,OAAO,SAASW,YAAYA,CAACX,QAAgB,EAAE;EAC7C,OAAOL,WAAW,CAACgB,YAAY,CAACX,QAAQ,CAAC;AAC3C;AAEA,OAAO,SAASY,
|
|
1
|
+
{"version":3,"names":["PolarBridge","multiply","a","b","connectToDevice","deviceId","disconnectFromDevice","scanDevices","fetchHrData","fetchAccData","fetchGyrData","fetchPpgData","enableSdkMode","disableSdkMode","setDeviceTime","getDeviceTime","getDiskSpace","doFactoryReset","startOfflineRecording","features","stopOfflineRecording","setPolarRecordingTrigger","recordingMode","fetchOfflineRecordings","downloadOfflineRecordings","deleteAllOfflineRecordings","disposeHrStream","disposeAccStream","disposeGyrStream","disposePpgStream","emittedEventId","Object","freeze","SCAN_DEVICE_FOUND","SCAN_DEVICE_ERROR","SCAN_DEVICE_COMPLETE","POLAR_DEVICE_TIME","POLAR_HR_DATA","POLAR_HR_ERROR","POLAR_HR_COMPLETE","POLAR_ACC_DATA","POLAR_ACC_ERROR","POLAR_ACC_COMPLETE","POLAR_GYR_DATA","POLAR_GYR_ERROR","POLAR_GYR_COMPLETE","POLAR_PPG_DATA","POLAR_PPG_ERROR","POLAR_PPG_COMPLETE","POLAR_DISK_SPACE","POLAR_OFFLINE_RECORDING","OfflineRecordingFeature","OFFLINE_HR","OFFLINE_ACC","OFFLINE_GYR","OFFLINE_PPG","OFFLINE_MAG","OFFLINE_PPI","OfflineRecordingTriggerMode","TRIGGER_DISABLED","TRIGGER_SYSTEM_START","TRIGGER_EXERCISE_START"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -13,6 +13,7 @@ export interface Spec extends TurboModule {
|
|
|
13
13
|
getDeviceTime(deviceId: string): Promise<DeviceTime>;
|
|
14
14
|
setDeviceTime(deviceId: string): void;
|
|
15
15
|
getDiskSpace(deviceId: string): Promise<DiskSpace>;
|
|
16
|
+
doFactoryReset(deviceId: string): void;
|
|
16
17
|
startOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
17
18
|
stopOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
18
19
|
setPolarRecordingTrigger(deviceId: string, recordingMode: number, features: string[]): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativePolarBridge.d.ts","sourceRoot":"","sources":["../../../src/NativePolarBridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEjG,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5D,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACnD,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1E,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACzE,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5F,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACtE,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAClD,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACnD,WAAW,IAAI,IAAI,CAAC;IACpB,eAAe,IAAI,IAAI,CAAC;IACxB,gBAAgB,IAAI,IAAI,CAAC;IACzB,gBAAgB,IAAI,IAAI,CAAC;IACzB,gBAAgB,IAAI,IAAI,CAAC;CAC1B;;AAED,wBAAqE"}
|
|
1
|
+
{"version":3,"file":"NativePolarBridge.d.ts","sourceRoot":"","sources":["../../../src/NativePolarBridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEjG,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5D,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACnD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1E,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACzE,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5F,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACtE,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAClD,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACnD,WAAW,IAAI,IAAI,CAAC;IACpB,eAAe,IAAI,IAAI,CAAC;IACxB,gBAAgB,IAAI,IAAI,CAAC;IACzB,gBAAgB,IAAI,IAAI,CAAC;IACzB,gBAAgB,IAAI,IAAI,CAAC;CAC1B;;AAED,wBAAqE"}
|
|
@@ -11,6 +11,7 @@ export declare function disableSdkMode(deviceId: string): void;
|
|
|
11
11
|
export declare function setDeviceTime(deviceId: string): void;
|
|
12
12
|
export declare function getDeviceTime(deviceId: string): Promise<import("./PolarDataModel").DeviceTime>;
|
|
13
13
|
export declare function getDiskSpace(deviceId: string): Promise<import("./PolarDataModel").DiskSpace>;
|
|
14
|
+
export declare function doFactoryReset(deviceId: string): void;
|
|
14
15
|
export declare function startOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
15
16
|
export declare function stopOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
16
17
|
export declare function setPolarRecordingTrigger(deviceId: string, recordingMode: number, features: string[]): void;
|
|
@@ -39,6 +40,7 @@ export declare const emittedEventId: Readonly<{
|
|
|
39
40
|
POLAR_PPG_ERROR: "PolarPpgError";
|
|
40
41
|
POLAR_PPG_COMPLETE: "PolarPpgComplete";
|
|
41
42
|
POLAR_DISK_SPACE: "PolarDiskSpace";
|
|
43
|
+
POLAR_OFFLINE_RECORDING: "PolarOfflineRecording";
|
|
42
44
|
}>;
|
|
43
45
|
export declare const OfflineRecordingFeature: Readonly<{
|
|
44
46
|
OFFLINE_HR: "OfflineHR";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,uDAE/C;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,QAEpD;AAED,wBAAgB,WAAW,SAE1B;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,QAE3C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,QAE5C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,QAE5C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,QAE5C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,QAE7C;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,QAE9C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,QAE7C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,kDAE7C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,iDAE5C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAEzE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAExE;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAEnG;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,0DAEtD;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,QAEzD;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,QAE1D;AAED,wBAAgB,eAAe,SAE9B;AAED,wBAAgB,gBAAgB,SAE/B;AAED,wBAAgB,gBAAgB,SAE/B;AAED,wBAAgB,gBAAgB,SAE/B;AAED,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,uDAE/C;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,QAEpD;AAED,wBAAgB,WAAW,SAE1B;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,QAE3C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,QAE5C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,QAE5C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,QAE5C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,QAE7C;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,QAE9C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,QAE7C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,kDAE7C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,iDAE5C;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,QAE9C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAEzE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAExE;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAEnG;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,0DAEtD;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,QAEzD;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,QAE1D;AAED,wBAAgB,eAAe,SAE9B;AAED,wBAAgB,gBAAgB,SAE/B;AAED,wBAAgB,gBAAgB,SAE/B;AAED,wBAAgB,gBAAgB,SAE/B;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;EAmBzB,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;EAOlC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;EAItC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-polar-bridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Polar SDK for React Native",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"keywords": [
|
|
44
44
|
"react-native",
|
|
45
45
|
"android",
|
|
46
|
+
"ios",
|
|
46
47
|
"polar",
|
|
47
48
|
"polar-ble-sdk"
|
|
48
49
|
],
|
package/src/NativePolarBridge.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface Spec extends TurboModule {
|
|
|
15
15
|
getDeviceTime(deviceId: string): Promise<DeviceTime>;
|
|
16
16
|
setDeviceTime(deviceId: string): void;
|
|
17
17
|
getDiskSpace(deviceId: string): Promise<DiskSpace>;
|
|
18
|
+
doFactoryReset(deviceId: string): void;
|
|
18
19
|
startOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
19
20
|
stopOfflineRecording(deviceId: string, features: string[]): Promise<any>;
|
|
20
21
|
setPolarRecordingTrigger(deviceId: string, recordingMode: number, features: string[]): void;
|
package/src/index.tsx
CHANGED
|
@@ -52,6 +52,10 @@ export function getDiskSpace(deviceId: string) {
|
|
|
52
52
|
return PolarBridge.getDiskSpace(deviceId);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export function doFactoryReset(deviceId: string) {
|
|
56
|
+
return PolarBridge.doFactoryReset(deviceId);
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
export function startOfflineRecording(deviceId: string, features: string[]) {
|
|
56
60
|
return PolarBridge.startOfflineRecording(deviceId, features);
|
|
57
61
|
}
|
|
@@ -110,6 +114,7 @@ export const emittedEventId = Object.freeze({
|
|
|
110
114
|
POLAR_PPG_ERROR: 'PolarPpgError',
|
|
111
115
|
POLAR_PPG_COMPLETE: 'PolarPpgComplete',
|
|
112
116
|
POLAR_DISK_SPACE: 'PolarDiskSpace',
|
|
117
|
+
POLAR_OFFLINE_RECORDING : 'PolarOfflineRecording',
|
|
113
118
|
});
|
|
114
119
|
|
|
115
120
|
export const OfflineRecordingFeature = Object.freeze({
|
package/ios/PolarBridge.h
DELETED
package/ios/PolarBridge.mm
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#import "PolarBridge.h"
|
|
2
|
-
|
|
3
|
-
@implementation PolarBridge
|
|
4
|
-
RCT_EXPORT_MODULE()
|
|
5
|
-
|
|
6
|
-
- (NSNumber *)multiply:(double)a b:(double)b {
|
|
7
|
-
NSNumber *result = @(a * b);
|
|
8
|
-
|
|
9
|
-
return result;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
13
|
-
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
14
|
-
{
|
|
15
|
-
return std::make_shared<facebook::react::NativePolarBridgeSpecJSI>(params);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
@end
|