@shenai/react-native-sdk 3.1.1

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.
@@ -0,0 +1,1325 @@
1
+ package ai.mxlabs.shenai_sdk_react_native;
2
+
3
+ // ShenaiSdkModule.java
4
+ import ai.mxlabs.shenai_sdk.ShenAIAndroidSDK;
5
+
6
+ import com.facebook.react.bridge.ReactApplicationContext;
7
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
8
+ import com.facebook.react.bridge.ReactMethod;
9
+ import com.facebook.react.bridge.Promise;
10
+ import com.facebook.react.bridge.Arguments;
11
+ import com.facebook.react.bridge.ReadableArray;
12
+ import com.facebook.react.bridge.ReadableMap;
13
+ import com.facebook.react.bridge.WritableArray;
14
+ import com.facebook.react.bridge.WritableMap;
15
+ import com.facebook.react.bridge.UiThreadUtil;
16
+ import com.facebook.react.modules.core.DeviceEventManagerModule;
17
+ import android.app.Activity;
18
+ import androidx.annotation.NonNull;
19
+ import androidx.annotation.Nullable;
20
+ import android.util.Base64;
21
+ import java.util.Optional;
22
+ import java.util.List;
23
+ import java.util.ArrayList;
24
+
25
+ public class ShenaiSdkModule extends ReactContextBaseJavaModule {
26
+ private static final ShenAIAndroidSDK shenai_sdk = new ShenAIAndroidSDK();
27
+
28
+ public static ShenAIAndroidSDK getSdkInstance() {
29
+ return shenai_sdk;
30
+ }
31
+
32
+ ShenaiSdkModule(ReactApplicationContext context) {
33
+ super(context);
34
+ }
35
+
36
+ @NonNull
37
+ @Override
38
+ public String getName() {
39
+ return "ShenaiSdkNativeModule";
40
+ }
41
+
42
+ @ReactMethod
43
+ public void addListener(String eventName) {}
44
+
45
+ @ReactMethod
46
+ public void removeListeners(Integer count) {}
47
+
48
+ private void emitShenaiEvent(String jsEvent) {
49
+ final ReactApplicationContext reactContext = getReactApplicationContext();
50
+ if (!reactContext.hasActiveCatalystInstance()) {
51
+ return;
52
+ }
53
+
54
+ reactContext.runOnJSQueueThread(() -> {
55
+ if (!reactContext.hasActiveCatalystInstance()) {
56
+ return;
57
+ }
58
+ WritableMap params = Arguments.createMap();
59
+ params.putString("EventName", jsEvent);
60
+ reactContext
61
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
62
+ .emit("ShenAIEvent", params);
63
+ });
64
+ }
65
+
66
+ @ReactMethod
67
+ public void initialize(String apiKey, String userId, ReadableMap settings, Promise promise) {
68
+ Activity currentActivity = getCurrentActivity();
69
+ if (currentActivity == null) {
70
+ promise.reject("E_ACTIVITY_DOES_NOT_EXIST", "Activity doesn't exist");
71
+ return;
72
+ }
73
+
74
+ ShenAIAndroidSDK.InitializationSettings shenaiSettings = shenai_sdk.getDefaultInitializationSettings();
75
+
76
+ if (settings != null) {
77
+ if (settings.hasKey("showUserInterface")) {
78
+ shenaiSettings.showUserInterface = settings.getBoolean("showUserInterface");
79
+ }
80
+ if (settings.hasKey("precisionMode")) {
81
+ shenaiSettings.precisionMode = ShenAIAndroidSDK.PrecisionMode.values()[settings.getInt("precisionMode")];
82
+ }
83
+ if (settings.hasKey("operatingMode")) {
84
+ shenaiSettings.operatingMode = ShenAIAndroidSDK.OperatingMode.values()[settings.getInt("operatingMode")];
85
+ }
86
+ if (settings.hasKey("measurementPreset")) {
87
+ shenaiSettings.measurementPreset = ShenAIAndroidSDK.MeasurementPreset.values()[settings.getInt("measurementPreset")];
88
+ }
89
+ if (settings.hasKey("cameraMode")) {
90
+ shenaiSettings.cameraMode = ShenAIAndroidSDK.CameraMode.values()[settings.getInt("cameraMode")];
91
+ }
92
+ if (settings.hasKey("onboardingMode")) {
93
+ shenaiSettings.onboardingMode = ShenAIAndroidSDK.OnboardingMode.values()[settings.getInt("onboardingMode")];
94
+ }
95
+ if (settings.hasKey("initializationMode")) {
96
+ shenaiSettings.initializationMode = ShenAIAndroidSDK.InitializationMode.values()[settings.getInt("initializationMode")];
97
+ }
98
+ if (settings.hasKey("offlineProcessing")) {
99
+ shenaiSettings.offlineProcessing = settings.getBoolean("offlineProcessing");
100
+ }
101
+ if (settings.hasKey("showFacePositioningOverlay")) {
102
+ shenaiSettings.showFacePositioningOverlay = settings.getBoolean("showFacePositioningOverlay");
103
+ }
104
+ if (settings.hasKey("showVisualWarnings")) {
105
+ shenaiSettings.showVisualWarnings = settings.getBoolean("showVisualWarnings");
106
+ }
107
+ if (settings.hasKey("enableCameraSwap")) {
108
+ shenaiSettings.enableCameraSwap = settings.getBoolean("enableCameraSwap");
109
+ }
110
+ if (settings.hasKey("showFaceMask")) {
111
+ shenaiSettings.showFaceMask = settings.getBoolean("showFaceMask");
112
+ }
113
+ if (settings.hasKey("showBloodFlow")) {
114
+ shenaiSettings.showBloodFlow = settings.getBoolean("showBloodFlow");
115
+ }
116
+ if (settings.hasKey("hideShenaiLogo")) {
117
+ shenaiSettings.hideShenaiLogo = settings.getBoolean("hideShenaiLogo");
118
+ }
119
+ if (settings.hasKey("includeTimestampInPdf")) {
120
+ shenaiSettings.includeTimestampInPdf = settings.getBoolean("includeTimestampInPdf");
121
+ }
122
+ if (settings.hasKey("pdfEmailSubject")) {
123
+ shenaiSettings.pdfEmailSubject = settings.getString("pdfEmailSubject");
124
+ }
125
+ if (settings.hasKey("pdfEmailBody")) {
126
+ shenaiSettings.pdfEmailBody = settings.getString("pdfEmailBody");
127
+ }
128
+ if (settings.hasKey("enableStartAfterSuccess")) {
129
+ shenaiSettings.enableStartAfterSuccess = settings.getBoolean("enableStartAfterSuccess");
130
+ }
131
+ if (settings.hasKey("enableSummaryScreen")) {
132
+ shenaiSettings.enableSummaryScreen = settings.getBoolean("enableSummaryScreen");
133
+ }
134
+ if (settings.hasKey("showResultsFinishButton")) {
135
+ shenaiSettings.showResultsFinishButton = settings.getBoolean("showResultsFinishButton");
136
+ }
137
+ if (settings.hasKey("enableHealthRisks")) {
138
+ shenaiSettings.enableHealthRisks = settings.getBoolean("enableHealthRisks");
139
+ }
140
+ if (settings.hasKey("showHealthIndicesFinishButton")) {
141
+ shenaiSettings.showHealthIndicesFinishButton =
142
+ settings.getBoolean("showHealthIndicesFinishButton");
143
+ }
144
+ if (settings.hasKey("saveHealthRisksFactors")) {
145
+ shenaiSettings.saveHealthRisksFactors = settings.getBoolean("saveHealthRisksFactors");
146
+ }
147
+ if (settings.hasKey("showOutOfRangeResultIndicators")) {
148
+ shenaiSettings.showOutOfRangeResultIndicators = settings.getBoolean("showOutOfRangeResultIndicators");
149
+ }
150
+ if (settings.hasKey("showSignalQualityIndicator")) {
151
+ shenaiSettings.showSignalQualityIndicator = settings.getBoolean("showSignalQualityIndicator");
152
+ }
153
+ if (settings.hasKey("showSignalTile")) {
154
+ shenaiSettings.showSignalTile = settings.getBoolean("showSignalTile");
155
+ }
156
+ if (settings.hasKey("showStartStopButton")) {
157
+ shenaiSettings.showStartStopButton = settings.getBoolean("showStartStopButton");
158
+ }
159
+ if (settings.hasKey("showInfoButton")) {
160
+ shenaiSettings.showInfoButton = settings.getBoolean("showInfoButton");
161
+ }
162
+ if (settings.hasKey("showDisclaimer")) {
163
+ shenaiSettings.showDisclaimer = settings.getBoolean("showDisclaimer");
164
+ }
165
+ if (settings.hasKey("enableMeasurementsDashboard")) {
166
+ shenaiSettings.enableMeasurementsDashboard = settings.getBoolean("enableMeasurementsDashboard");
167
+ }
168
+ if (settings.hasKey("uiVersion")) {
169
+ int rawVersion = settings.getInt("uiVersion");
170
+ shenaiSettings.uiVersion = ShenAIAndroidSDK.UiVersion.values()[rawVersion];
171
+ }
172
+ if (settings.hasKey("showTrialMetricLabels")) {
173
+ shenaiSettings.showTrialMetricLabels = settings.getBoolean("showTrialMetricLabels");
174
+ }
175
+ if (settings.hasKey("applyPrecisionModeToBloodPressure")) {
176
+ shenaiSettings.applyPrecisionModeToBloodPressure =
177
+ settings.getBoolean("applyPrecisionModeToBloodPressure");
178
+ }
179
+ if (settings.hasKey("blockingMeasurementConditions")) {
180
+ ReadableArray array = settings.getArray("blockingMeasurementConditions");
181
+ shenaiSettings.blockingMeasurementConditions.clear();
182
+ for (int i = 0; i < array.size(); i++) {
183
+ shenaiSettings.blockingMeasurementConditions.add(
184
+ ShenAIAndroidSDK.MeasurementEnvironmentCondition.values()[array.getInt(i)]);
185
+ }
186
+ }
187
+ if (settings.hasKey("warningMeasurementConditions")) {
188
+ ReadableArray array = settings.getArray("warningMeasurementConditions");
189
+ shenaiSettings.warningMeasurementConditions.clear();
190
+ for (int i = 0; i < array.size(); i++) {
191
+ shenaiSettings.warningMeasurementConditions.add(
192
+ ShenAIAndroidSDK.MeasurementEnvironmentCondition.values()[array.getInt(i)]);
193
+ }
194
+ }
195
+ if (settings.hasKey("uiFlowScreens")) {
196
+ ReadableArray array = settings.getArray("uiFlowScreens");
197
+ shenaiSettings.uiFlowScreens.clear();
198
+ for (int i = 0; i < array.size(); i++) {
199
+ shenaiSettings.uiFlowScreens.add(ShenAIAndroidSDK.Screen.values()[array.getInt(i)]);
200
+ }
201
+ }
202
+ if (settings.hasKey("frameWidth")) {
203
+ shenaiSettings.frameWidth = settings.getInt("frameWidth");
204
+ }
205
+ if (settings.hasKey("frameHeight")) {
206
+ shenaiSettings.frameHeight = settings.getInt("frameHeight");
207
+ }
208
+ if (settings.hasKey("rotation")) {
209
+ shenaiSettings.rotation = settings.getInt("rotation");
210
+ }
211
+ if (settings.hasKey("risksFactors")) {
212
+ ReadableMap factorsMap = settings.getMap("risksFactors");
213
+ shenaiSettings.risksFactors = risksFactorsFromReadableMap(factorsMap);
214
+ }
215
+ shenaiSettings.eventCallback = new ShenAIAndroidSDK.EventCallback() {
216
+ @Override
217
+ public void onEvent(ShenAIAndroidSDK.Event event) {
218
+ String jsEvent;
219
+ switch (event) {
220
+ case START_BUTTON_CLICKED:
221
+ jsEvent = "START_BUTTON_CLICKED";
222
+ break;
223
+ case STOP_BUTTON_CLICKED:
224
+ jsEvent = "STOP_BUTTON_CLICKED";
225
+ break;
226
+ case MEASUREMENT_FINISHED:
227
+ jsEvent = "MEASUREMENT_FINISHED";
228
+ break;
229
+ case USER_FLOW_FINISHED:
230
+ jsEvent = "USER_FLOW_FINISHED";
231
+ break;
232
+ case SCREEN_CHANGED:
233
+ jsEvent = "SCREEN_CHANGED";
234
+ break;
235
+ default:
236
+ jsEvent = "UNKNOWN";
237
+ }
238
+ emitShenaiEvent(jsEvent);
239
+ }
240
+ };
241
+ // Add mappings for other settings as needed
242
+ }
243
+
244
+ ShenAIAndroidSDK.InitializationResult result = shenai_sdk.initialize(currentActivity, apiKey, userId, shenaiSettings);
245
+ promise.resolve(result.ordinal());
246
+ }
247
+
248
+ @ReactMethod
249
+ public void setCustomMeasurementConfig(ReadableMap config, Promise promise) {
250
+ ShenAIAndroidSDK.CustomMeasurementConfig shenaiConfig = shenai_sdk.new CustomMeasurementConfig();
251
+
252
+ if (config.hasKey("durationSeconds")) {
253
+ shenaiConfig.durationSeconds = Optional.of((float) config.getDouble("durationSeconds"));
254
+ }
255
+ if (config.hasKey("infiniteMeasurement")) {
256
+ shenaiConfig.infiniteMeasurement = Optional.of(config.getBoolean("infiniteMeasurement"));
257
+ }
258
+ if (config.hasKey("instantMetrics")) {
259
+ ReadableArray array = config.getArray("instantMetrics");
260
+ List<ShenAIAndroidSDK.Metric> metricsList = new ArrayList<>();
261
+ for (int i = 0; i < array.size(); i++) {
262
+ String metricStr = array.getString(i);
263
+ try {
264
+ ShenAIAndroidSDK.Metric metric = ShenAIAndroidSDK.Metric.valueOf(metricStr);
265
+ metricsList.add(metric);
266
+ } catch (IllegalArgumentException e) {
267
+ // Handle the case where the enum value is not found
268
+ promise.reject("Invalid metric value: " + metricStr);
269
+ return;
270
+ }
271
+ }
272
+ shenaiConfig.instantMetrics = Optional.of(metricsList);
273
+ }
274
+ if (config.hasKey("summaryMetrics")) {
275
+ ReadableArray array = config.getArray("summaryMetrics");
276
+ List<ShenAIAndroidSDK.Metric> metricsList = new ArrayList<>();
277
+ for (int i = 0; i < array.size(); i++) {
278
+ String metricStr = array.getString(i);
279
+ try {
280
+ ShenAIAndroidSDK.Metric metric = ShenAIAndroidSDK.Metric.valueOf(metricStr);
281
+ metricsList.add(metric);
282
+ } catch (IllegalArgumentException e) {
283
+ // Handle the case where the enum value is not found
284
+ promise.reject("Invalid metric value: " + metricStr);
285
+ return;
286
+ }
287
+ }
288
+ shenaiConfig.summaryMetrics = Optional.of(metricsList);
289
+ }
290
+ if (config.hasKey("healthIndices")) {
291
+ ReadableArray array = config.getArray("healthIndices");
292
+ List<ShenAIAndroidSDK.HealthIndex> healthIndicesList = new ArrayList<>();
293
+ for (int i = 0; i < array.size(); i++) {
294
+ String healthIndexStr = array.getString(i);
295
+ try {
296
+ ShenAIAndroidSDK.HealthIndex healthIndex = ShenAIAndroidSDK.HealthIndex.valueOf(healthIndexStr);
297
+ healthIndicesList.add(healthIndex);
298
+ } catch (IllegalArgumentException e) {
299
+ // Handle the case where the enum value is not found
300
+ promise.reject("Invalid health index value: " + healthIndexStr);
301
+ return;
302
+ }
303
+ }
304
+ shenaiConfig.healthIndices = Optional.of(healthIndicesList);
305
+ }
306
+ if (config.hasKey("realtimeHrPeriodSeconds")) {
307
+ shenaiConfig.realtimeHrPeriodSeconds = Optional.of((float) config.getDouble("realtimeHrPeriodSeconds"));
308
+ }
309
+ if (config.hasKey("realtimeHrvPeriodSeconds")) {
310
+ shenaiConfig.realtimeHrvPeriodSeconds = Optional.of((float) config.getDouble("realtimeHrvPeriodSeconds"));
311
+ }
312
+ if (config.hasKey("realtimeCardiacStressPeriodSeconds")) {
313
+ shenaiConfig.realtimeCardiacStressPeriodSeconds = Optional.of((float) config.getDouble("realtimeCardiacStressPeriodSeconds"));
314
+ }
315
+ shenai_sdk.setCustomMeasurementConfig(shenaiConfig);
316
+ promise.resolve(null);
317
+ }
318
+
319
+ @ReactMethod
320
+ public void setCustomColorTheme(ReadableMap theme, Promise promise) {
321
+ ShenAIAndroidSDK.CustomColorTheme shenaiTheme = shenai_sdk.new CustomColorTheme();
322
+
323
+ if (theme.hasKey("themeColor")) {
324
+ shenaiTheme.themeColor = theme.getString("themeColor");
325
+ }
326
+ if (theme.hasKey("textColor")) {
327
+ shenaiTheme.textColor = theme.getString("textColor");
328
+ }
329
+ if (theme.hasKey("backgroundColor")) {
330
+ shenaiTheme.backgroundColor = theme.getString("backgroundColor");
331
+ }
332
+ if (theme.hasKey("tileColor")) {
333
+ shenaiTheme.tileColor = theme.getString("tileColor");
334
+ }
335
+ if (theme.hasKey("buttonMainColor")) {
336
+ shenaiTheme.buttonMainColor = theme.getString("buttonMainColor");
337
+ }
338
+ if (theme.hasKey("buttonSecondaryColor")) {
339
+ shenaiTheme.buttonSecondaryColor = theme.getString("buttonSecondaryColor");
340
+ }
341
+ shenai_sdk.setCustomColorTheme(shenaiTheme);
342
+ promise.resolve(null);
343
+ }
344
+
345
+ @ReactMethod
346
+ public void isInitialized(Promise promise) {
347
+ boolean result = shenai_sdk.isInitialized();
348
+ promise.resolve(result);
349
+ }
350
+
351
+ @ReactMethod
352
+ public void deinitialize(Promise promise) {
353
+ shenai_sdk.deinitialize();
354
+ promise.resolve(null);
355
+ }
356
+
357
+ @ReactMethod
358
+ public void setOperatingMode(int operatingMode, Promise promise) {
359
+ shenai_sdk.setOperatingMode(ShenAIAndroidSDK.OperatingMode.values()[operatingMode]);
360
+ promise.resolve(null);
361
+ }
362
+
363
+ @ReactMethod
364
+ public void startMeasurement(Promise promise) {
365
+ shenai_sdk.startMeasurement();
366
+ promise.resolve(null);
367
+ }
368
+
369
+ @ReactMethod
370
+ public void stopMeasurement(Promise promise) {
371
+ shenai_sdk.stopMeasurement();
372
+ promise.resolve(null);
373
+ }
374
+
375
+ @ReactMethod
376
+ public void resetMeasurementSession(Promise promise) {
377
+ shenai_sdk.resetMeasurementSession();
378
+ promise.resolve(null);
379
+ }
380
+
381
+ @ReactMethod
382
+ public void getOperatingMode(Promise promise) {
383
+ ShenAIAndroidSDK.OperatingMode result = shenai_sdk.getOperatingMode();
384
+ promise.resolve(result.ordinal());
385
+ }
386
+
387
+ @ReactMethod
388
+ public void getCalibrationState(Promise promise) {
389
+ ShenAIAndroidSDK.CalibrationState result = shenai_sdk.getCalibrationState();
390
+ promise.resolve(result.ordinal());
391
+ }
392
+
393
+ @ReactMethod
394
+ public void setPrecisionMode(int precisionMode, Promise promise) {
395
+ shenai_sdk.setPrecisionMode(ShenAIAndroidSDK.PrecisionMode.values()[precisionMode]);
396
+ promise.resolve(null);
397
+ }
398
+
399
+ @ReactMethod
400
+ public void getPrecisionMode(Promise promise) {
401
+ ShenAIAndroidSDK.PrecisionMode result = shenai_sdk.getPrecisionMode();
402
+ promise.resolve(result.ordinal());
403
+ }
404
+
405
+ @ReactMethod
406
+ public void setApplyPrecisionModeToBloodPressure(boolean apply, Promise promise) {
407
+ shenai_sdk.setApplyPrecisionModeToBloodPressure(apply);
408
+ promise.resolve(null);
409
+ }
410
+
411
+ @ReactMethod
412
+ public void getApplyPrecisionModeToBloodPressure(Promise promise) {
413
+ promise.resolve(shenai_sdk.getApplyPrecisionModeToBloodPressure());
414
+ }
415
+
416
+ @ReactMethod
417
+ public void setBlockingMeasurementConditions(ReadableArray conditions, Promise promise) {
418
+ ShenAIAndroidSDK.MeasurementEnvironmentCondition[] values =
419
+ new ShenAIAndroidSDK.MeasurementEnvironmentCondition[conditions == null ? 0 : conditions.size()];
420
+ if (conditions != null) {
421
+ for (int i = 0; i < conditions.size(); i++) {
422
+ values[i] = ShenAIAndroidSDK.MeasurementEnvironmentCondition.values()[conditions.getInt(i)];
423
+ }
424
+ }
425
+ shenai_sdk.setBlockingMeasurementConditions(values);
426
+ promise.resolve(null);
427
+ }
428
+
429
+ @ReactMethod
430
+ public void getBlockingMeasurementConditions(Promise promise) {
431
+ ShenAIAndroidSDK.MeasurementEnvironmentCondition[] values = shenai_sdk.getBlockingMeasurementConditions();
432
+ WritableArray array = Arguments.createArray();
433
+ for (ShenAIAndroidSDK.MeasurementEnvironmentCondition value : values) {
434
+ array.pushInt(value.ordinal());
435
+ }
436
+ promise.resolve(array);
437
+ }
438
+
439
+ @ReactMethod
440
+ public void setWarningMeasurementConditions(ReadableArray conditions, Promise promise) {
441
+ ShenAIAndroidSDK.MeasurementEnvironmentCondition[] values =
442
+ new ShenAIAndroidSDK.MeasurementEnvironmentCondition[conditions == null ? 0 : conditions.size()];
443
+ if (conditions != null) {
444
+ for (int i = 0; i < conditions.size(); i++) {
445
+ values[i] = ShenAIAndroidSDK.MeasurementEnvironmentCondition.values()[conditions.getInt(i)];
446
+ }
447
+ }
448
+ shenai_sdk.setWarningMeasurementConditions(values);
449
+ promise.resolve(null);
450
+ }
451
+
452
+ @ReactMethod
453
+ public void getWarningMeasurementConditions(Promise promise) {
454
+ ShenAIAndroidSDK.MeasurementEnvironmentCondition[] values = shenai_sdk.getWarningMeasurementConditions();
455
+ WritableArray array = Arguments.createArray();
456
+ for (ShenAIAndroidSDK.MeasurementEnvironmentCondition value : values) {
457
+ array.pushInt(value.ordinal());
458
+ }
459
+ promise.resolve(array);
460
+ }
461
+
462
+ @ReactMethod
463
+ public void getCurrentViolatedMeasurementEnvironmentCondition(Promise promise) {
464
+ ShenAIAndroidSDK.MeasurementEnvironmentCondition value =
465
+ shenai_sdk.getCurrentViolatedMeasurementEnvironmentCondition();
466
+ promise.resolve(value == null ? null : value.ordinal());
467
+ }
468
+
469
+ @ReactMethod
470
+ public void setMeasurementPreset(int measurementPreset, Promise promise) {
471
+ shenai_sdk.setMeasurementPreset(ShenAIAndroidSDK.MeasurementPreset.values()[measurementPreset]);
472
+ promise.resolve(null);
473
+ }
474
+
475
+ @ReactMethod
476
+ public void getMeasurementPreset(Promise promise) {
477
+ ShenAIAndroidSDK.MeasurementPreset result = shenai_sdk.getMeasurementPreset();
478
+ promise.resolve(result.ordinal());
479
+ }
480
+
481
+ @ReactMethod
482
+ public void setCameraMode(int cameraMode, Promise promise) {
483
+ shenai_sdk.setCameraMode(ShenAIAndroidSDK.CameraMode.values()[cameraMode]);
484
+ promise.resolve(null);
485
+ }
486
+
487
+ @ReactMethod
488
+ public void getCameraMode(Promise promise) {
489
+ ShenAIAndroidSDK.CameraMode result = shenai_sdk.getCameraMode();
490
+ promise.resolve(result.ordinal());
491
+ }
492
+
493
+ @ReactMethod
494
+ public void getLastCameraError(Promise promise) {
495
+ ShenAIAndroidSDK.CameraError result = shenai_sdk.getLastCameraError();
496
+ promise.resolve(result == null ? null : result.ordinal());
497
+ }
498
+
499
+ @ReactMethod
500
+ public void setScreen(int screen, Promise promise) {
501
+ shenai_sdk.setScreen(ShenAIAndroidSDK.Screen.values()[screen]);
502
+ promise.resolve(null);
503
+ }
504
+
505
+ @ReactMethod
506
+ public void getScreen(Promise promise) {
507
+ ShenAIAndroidSDK.Screen result = shenai_sdk.getScreen();
508
+ promise.resolve(result.ordinal());
509
+ }
510
+
511
+
512
+ @ReactMethod
513
+ public void setShowUserInterface(boolean showUserInterface, Promise promise) {
514
+ shenai_sdk.setShowUserInterface(showUserInterface);
515
+ promise.resolve(null);
516
+ }
517
+
518
+ @ReactMethod
519
+ public void getShowUserInterface(Promise promise) {
520
+ boolean result = shenai_sdk.getShowUserInterface();
521
+ promise.resolve(result);
522
+ }
523
+
524
+ @ReactMethod
525
+ public void setShowFacePositioningOverlay(boolean showFacePositioningOverlay, Promise promise) {
526
+ shenai_sdk.setShowFacePositioningOverlay(showFacePositioningOverlay);
527
+ promise.resolve(null);
528
+ }
529
+
530
+ @ReactMethod
531
+ public void getShowFacePositioningOverlay(Promise promise) {
532
+ boolean result = shenai_sdk.getShowFacePositioningOverlay();
533
+ promise.resolve(result);
534
+ }
535
+
536
+ @ReactMethod
537
+ public void setShowVisualWarnings(boolean showVisualWarnings, Promise promise) {
538
+ shenai_sdk.setShowVisualWarnings(showVisualWarnings);
539
+ promise.resolve(null);
540
+ }
541
+
542
+ @ReactMethod
543
+ public void getShowVisualWarnings(Promise promise) {
544
+ boolean result = shenai_sdk.getShowVisualWarnings();
545
+ promise.resolve(result);
546
+ }
547
+
548
+ @ReactMethod
549
+ public void setEnableCameraSwap(boolean enableCameraSwap, Promise promise) {
550
+ shenai_sdk.setEnableCameraSwap(enableCameraSwap);
551
+ promise.resolve(null);
552
+ }
553
+
554
+ @ReactMethod
555
+ public void getEnableCameraSwap(Promise promise) {
556
+ boolean result = shenai_sdk.getEnableCameraSwap();
557
+ promise.resolve(result);
558
+ }
559
+
560
+ @ReactMethod
561
+ public void setShowFaceMask(boolean showFaceMask, Promise promise) {
562
+ shenai_sdk.setShowFaceMask(showFaceMask);
563
+ promise.resolve(null);
564
+ }
565
+
566
+ @ReactMethod
567
+ public void getShowFaceMask(Promise promise) {
568
+ boolean result = shenai_sdk.getShowFaceMask();
569
+ promise.resolve(result);
570
+ }
571
+
572
+ @ReactMethod
573
+ public void setShowBloodFlow(boolean showBloodFlow, Promise promise) {
574
+ shenai_sdk.setShowBloodFlow(showBloodFlow);
575
+ promise.resolve(null);
576
+ }
577
+
578
+ @ReactMethod
579
+ public void getShowBloodFlow(Promise promise) {
580
+ boolean result = shenai_sdk.getShowBloodFlow();
581
+ promise.resolve(result);
582
+ }
583
+
584
+ @ReactMethod
585
+ public void setIncludeTimestampInPdf(boolean include, Promise promise) {
586
+ shenai_sdk.setIncludeTimestampInPdf(include);
587
+ promise.resolve(null);
588
+ }
589
+
590
+ @ReactMethod
591
+ public void getIncludeTimestampInPdf(Promise promise) {
592
+ boolean result = shenai_sdk.getIncludeTimestampInPdf();
593
+ promise.resolve(result);
594
+ }
595
+
596
+ @ReactMethod
597
+ public void setPdfEmailSubject(String subject, Promise promise) {
598
+ shenai_sdk.setPdfEmailSubject(subject);
599
+ promise.resolve(null);
600
+ }
601
+
602
+ @ReactMethod
603
+ public void setPdfEmailBody(String body, Promise promise) {
604
+ shenai_sdk.setPdfEmailBody(body);
605
+ promise.resolve(null);
606
+ }
607
+
608
+ @ReactMethod
609
+ public void setShowStartStopButton(boolean showStartStopButton, Promise promise) {
610
+ shenai_sdk.setShowStartStopButton(showStartStopButton);
611
+ promise.resolve(null);
612
+ }
613
+
614
+ @ReactMethod
615
+ public void getShowStartStopButton(Promise promise) {
616
+ boolean result = shenai_sdk.getShowStartStopButton();
617
+ promise.resolve(result);
618
+ }
619
+
620
+ @ReactMethod
621
+ public void setEnableMeasurementsDashboard(boolean enableMeasurementsDashboard, Promise promise) {
622
+ shenai_sdk.setEnableMeasurementsDashboard(enableMeasurementsDashboard);
623
+ promise.resolve(null);
624
+ }
625
+
626
+ @ReactMethod
627
+ public void getEnableMeasurementsDashboard(Promise promise) {
628
+ boolean result = shenai_sdk.getEnableMeasurementsDashboard();
629
+ promise.resolve(result);
630
+ }
631
+
632
+ @ReactMethod
633
+ public void setShowInfoButton(boolean showInfoButton, Promise promise) {
634
+ shenai_sdk.setShowInfoButton(showInfoButton);
635
+ promise.resolve(null);
636
+ }
637
+
638
+ @ReactMethod
639
+ public void getShowInfoButton(Promise promise) {
640
+ boolean result = shenai_sdk.getShowInfoButton();
641
+ promise.resolve(result);
642
+ }
643
+
644
+ @ReactMethod
645
+ public void getShowDisclaimer(Promise promise) {
646
+ boolean result = shenai_sdk.getShowDisclaimer();
647
+ promise.resolve(result);
648
+ }
649
+
650
+ @ReactMethod
651
+ public void setEnableStartAfterSuccess(boolean enableStartAfterSuccess, Promise promise) {
652
+ shenai_sdk.setEnableStartAfterSuccess(enableStartAfterSuccess);
653
+ promise.resolve(null);
654
+ }
655
+
656
+ @ReactMethod
657
+ public void getEnableStartAfterSuccess(Promise promise) {
658
+ boolean result = shenai_sdk.getEnableStartAfterSuccess();
659
+ promise.resolve(result);
660
+ }
661
+
662
+
663
+ @ReactMethod
664
+ public void getFaceState(Promise promise) {
665
+ ShenAIAndroidSDK.FaceState result = shenai_sdk.getFaceState();
666
+ promise.resolve(result.ordinal());
667
+ }
668
+
669
+ @ReactMethod
670
+ public void getNormalizedFaceBbox(Promise promise) {
671
+ ShenAIAndroidSDK.NormalizedFaceBbox bbox = shenai_sdk.getNormalizedFaceBbox();
672
+ if (bbox != null) {
673
+ WritableMap bboxMap = Arguments.createMap();
674
+ bboxMap.putDouble("x", bbox.x);
675
+ bboxMap.putDouble("y", bbox.y);
676
+ bboxMap.putDouble("width", bbox.width);
677
+ bboxMap.putDouble("height", bbox.height);
678
+ promise.resolve(bboxMap);
679
+ } else {
680
+ promise.resolve(null);
681
+ }
682
+ }
683
+
684
+ @ReactMethod
685
+ public void getMeasurementState(Promise promise) {
686
+ ShenAIAndroidSDK.MeasurementState result = shenai_sdk.getMeasurementState();
687
+ promise.resolve(result.ordinal());
688
+ }
689
+
690
+ @ReactMethod
691
+ public void isReadyToStartMeasurement(Promise promise) {
692
+ promise.resolve(shenai_sdk.isReadyToStartMeasurement());
693
+ }
694
+
695
+ @ReactMethod
696
+ public void areRequiredModelsDownloaded(Promise promise) {
697
+ promise.resolve(shenai_sdk.areRequiredModelsDownloaded());
698
+ }
699
+
700
+ @ReactMethod
701
+ public void getMeasurementProgressPercentage(Promise promise) {
702
+ float result = shenai_sdk.getMeasurementProgressPercentage();
703
+ promise.resolve((double) result);
704
+ }
705
+
706
+
707
+ @ReactMethod
708
+ public void getHeartRate10s(Promise promise) {
709
+ int result = shenai_sdk.getHeartRate10s();
710
+ if (result < 0) {
711
+ promise.resolve(null); // Assuming negative values indicate no data
712
+ } else {
713
+ promise.resolve(result);
714
+ }
715
+ }
716
+
717
+ @ReactMethod
718
+ public void getHeartRate4s(Promise promise) {
719
+ int result = shenai_sdk.getHeartRate4s();
720
+ if (result < 0) {
721
+ promise.resolve(null); // Assuming negative values indicate no data
722
+ } else {
723
+ promise.resolve(result);
724
+ }
725
+ }
726
+
727
+ private void resolveMeasurementResults(Promise promise, ShenAIAndroidSDK.MeasurementResults results) {
728
+ try {
729
+ if (results != null) {
730
+ WritableMap resultMap = convertMeasurementResultsToMap(results);
731
+ promise.resolve(resultMap);
732
+ } else {
733
+ promise.resolve(null);
734
+ }
735
+ } catch (RuntimeException e) {
736
+ promise.reject("ERROR_MEASUREMENT_RESULTS", "Failed to convert measurement results", e);
737
+ }
738
+ }
739
+
740
+ private WritableMap convertMeasurementResultsWithMetadataToMap(ShenAIAndroidSDK.MeasurementResultsWithMetadata nativeObj) {
741
+ if (nativeObj == null) {
742
+ return null;
743
+ }
744
+
745
+ WritableMap mdMap = Arguments.createMap();
746
+
747
+ WritableMap resultsMap = convertMeasurementResultsToMap(nativeObj.measurementResults);
748
+ if (resultsMap != null) {
749
+ mdMap.putMap("measurementResults", resultsMap);
750
+ } else {
751
+ mdMap.putNull("measurementResults");
752
+ }
753
+ mdMap.putDouble("epochTimestamp", nativeObj.epochTimestamp);
754
+ mdMap.putBoolean("isCalibration", nativeObj.isCalibration);
755
+
756
+ return mdMap;
757
+ }
758
+
759
+ private WritableMap convertMeasurementQualityMetricsToMap(ShenAIAndroidSDK.MeasurementQualityMetrics metrics) {
760
+ if (metrics == null) {
761
+ return null;
762
+ }
763
+ WritableMap map = Arguments.createMap();
764
+ if (metrics.ppgQualityIndex != null && metrics.ppgQualityIndex.isPresent()) {
765
+ map.putDouble("ppgQualityIndex", metrics.ppgQualityIndex.get());
766
+ } else {
767
+ map.putNull("ppgQualityIndex");
768
+ }
769
+ if (metrics.bcgQualityIndex != null && metrics.bcgQualityIndex.isPresent()) {
770
+ map.putDouble("bcgQualityIndex", metrics.bcgQualityIndex.get());
771
+ } else {
772
+ map.putNull("bcgQualityIndex");
773
+ }
774
+ if (metrics.breathingQualityIndex != null && metrics.breathingQualityIndex.isPresent()) {
775
+ map.putDouble("breathingQualityIndex", metrics.breathingQualityIndex.get());
776
+ } else {
777
+ map.putNull("breathingQualityIndex");
778
+ }
779
+ if (metrics.bloodPressureQualityIndex != null && metrics.bloodPressureQualityIndex.isPresent()) {
780
+ map.putDouble("bloodPressureQualityIndex", metrics.bloodPressureQualityIndex.get());
781
+ } else {
782
+ map.putNull("bloodPressureQualityIndex");
783
+ }
784
+ if (metrics.expectedSbpMedianAbsErrorMmhg != null && metrics.expectedSbpMedianAbsErrorMmhg.isPresent()) {
785
+ map.putDouble("expectedSbpMedianAbsErrorMmhg", metrics.expectedSbpMedianAbsErrorMmhg.get());
786
+ } else {
787
+ map.putNull("expectedSbpMedianAbsErrorMmhg");
788
+ }
789
+ if (metrics.expectedSbpP80AbsErrorMmhg != null && metrics.expectedSbpP80AbsErrorMmhg.isPresent()) {
790
+ map.putDouble("expectedSbpP80AbsErrorMmhg", metrics.expectedSbpP80AbsErrorMmhg.get());
791
+ } else {
792
+ map.putNull("expectedSbpP80AbsErrorMmhg");
793
+ }
794
+ if (metrics.expectedSbpMeanAbsErrorMmhg != null && metrics.expectedSbpMeanAbsErrorMmhg.isPresent()) {
795
+ map.putDouble("expectedSbpMeanAbsErrorMmhg", metrics.expectedSbpMeanAbsErrorMmhg.get());
796
+ } else {
797
+ map.putNull("expectedSbpMeanAbsErrorMmhg");
798
+ }
799
+ if (metrics.expectedSbpBalancedMaeMmhg != null && metrics.expectedSbpBalancedMaeMmhg.isPresent()) {
800
+ map.putDouble("expectedSbpBalancedMaeMmhg", metrics.expectedSbpBalancedMaeMmhg.get());
801
+ } else {
802
+ map.putNull("expectedSbpBalancedMaeMmhg");
803
+ }
804
+ if (metrics.expectedDbpMedianAbsErrorMmhg != null && metrics.expectedDbpMedianAbsErrorMmhg.isPresent()) {
805
+ map.putDouble("expectedDbpMedianAbsErrorMmhg", metrics.expectedDbpMedianAbsErrorMmhg.get());
806
+ } else {
807
+ map.putNull("expectedDbpMedianAbsErrorMmhg");
808
+ }
809
+ if (metrics.expectedDbpP80AbsErrorMmhg != null && metrics.expectedDbpP80AbsErrorMmhg.isPresent()) {
810
+ map.putDouble("expectedDbpP80AbsErrorMmhg", metrics.expectedDbpP80AbsErrorMmhg.get());
811
+ } else {
812
+ map.putNull("expectedDbpP80AbsErrorMmhg");
813
+ }
814
+ if (metrics.expectedDbpMeanAbsErrorMmhg != null && metrics.expectedDbpMeanAbsErrorMmhg.isPresent()) {
815
+ map.putDouble("expectedDbpMeanAbsErrorMmhg", metrics.expectedDbpMeanAbsErrorMmhg.get());
816
+ } else {
817
+ map.putNull("expectedDbpMeanAbsErrorMmhg");
818
+ }
819
+ if (metrics.expectedDbpBalancedMaeMmhg != null && metrics.expectedDbpBalancedMaeMmhg.isPresent()) {
820
+ map.putDouble("expectedDbpBalancedMaeMmhg", metrics.expectedDbpBalancedMaeMmhg.get());
821
+ } else {
822
+ map.putNull("expectedDbpBalancedMaeMmhg");
823
+ }
824
+ return map;
825
+ }
826
+
827
+ private WritableMap convertMeasurementResultsToMap(ShenAIAndroidSDK.MeasurementResults results) {
828
+ if (results == null) {
829
+ return null;
830
+ }
831
+
832
+ WritableMap resultMap = Arguments.createMap();
833
+
834
+ resultMap.putDouble("heartRateBpm", results.hrBpm);
835
+ resultMap.putDouble("averageSignalQuality", results.averageSignalQuality);
836
+
837
+ resultMap.putArray("heartbeats", convertHeartbeatsToArray(results.heartbeats));
838
+
839
+ if (results.brBpm.isPresent()) {
840
+ resultMap.putDouble("breathingRateBpm", results.brBpm.get());
841
+ } else {
842
+ resultMap.putNull("breathingRateBpm");
843
+ }
844
+
845
+ if (results.hrvLnrmssdMs.isPresent()) {
846
+ resultMap.putDouble("hrvLnrmssdMs", results.hrvLnrmssdMs.get());
847
+ } else {
848
+ resultMap.putNull("hrvLnrmssdMs");
849
+ }
850
+
851
+ if (results.hrvSdnnMs.isPresent()) {
852
+ resultMap.putDouble("hrvSdnnMs", results.hrvSdnnMs.get());
853
+ } else {
854
+ resultMap.putNull("hrvSdnnMs");
855
+ }
856
+
857
+ if (results.stressIndex.isPresent()) {
858
+ resultMap.putDouble("stressIndex", results.stressIndex.get());
859
+ } else {
860
+ resultMap.putNull("stressIndex");
861
+ }
862
+
863
+ if (results.parasympatheticActivity.isPresent()) {
864
+ resultMap.putDouble("parasympatheticActivity", results.parasympatheticActivity.get());
865
+ } else {
866
+ resultMap.putNull("parasympatheticActivity");
867
+ }
868
+
869
+ if (results.systolicBloodPressureMmhg.isPresent()) {
870
+ resultMap.putDouble("systolicBloodPressureMmhg", results.systolicBloodPressureMmhg.get());
871
+ } else {
872
+ resultMap.putNull("systolicBloodPressureMmhg");
873
+ }
874
+
875
+ if (results.diastolicBloodPressureMmhg.isPresent()) {
876
+ resultMap.putDouble("diastolicBloodPressureMmhg", results.diastolicBloodPressureMmhg.get());
877
+ } else {
878
+ resultMap.putNull("diastolicBloodPressureMmhg");
879
+ }
880
+
881
+ if (results.cardiacWorkloadMmhgPerSec.isPresent()) {
882
+ resultMap.putDouble("cardiacWorkloadMmhgPerSec", results.cardiacWorkloadMmhgPerSec.get());
883
+ } else {
884
+ resultMap.putNull("cardiacWorkloadMmhgPerSec");
885
+ }
886
+
887
+ if (results.ageYears.isPresent()) {
888
+ resultMap.putDouble("ageYears", results.ageYears.get());
889
+ } else {
890
+ resultMap.putNull("ageYears");
891
+ }
892
+
893
+ if (results.bmiKgPerM2.isPresent()) {
894
+ resultMap.putDouble("bmiKgPerM2", results.bmiKgPerM2.get());
895
+ } else {
896
+ resultMap.putNull("bmiKgPerM2");
897
+ }
898
+
899
+ if (results.bmiCategory.isPresent()) {
900
+ results.bmiCategory.ifPresent(bmiCategory -> resultMap.putInt("bmiCategory", bmiCategory.ordinal()));
901
+ } else {
902
+ resultMap.putNull("bmiCategory");
903
+ }
904
+
905
+ if (results.weightKg.isPresent()) {
906
+ resultMap.putDouble("weightKg", results.weightKg.get());
907
+ } else {
908
+ resultMap.putNull("weightKg");
909
+ }
910
+
911
+ if (results.heightCm.isPresent()) {
912
+ resultMap.putDouble("heightCm", results.heightCm.get());
913
+ } else {
914
+ resultMap.putNull("heightCm");
915
+ }
916
+
917
+ WritableMap qualityMetricsMap = convertMeasurementQualityMetricsToMap(results.qualityMetrics);
918
+ if (qualityMetricsMap != null) {
919
+ resultMap.putMap("qualityMetrics", qualityMetricsMap);
920
+ } else {
921
+ resultMap.putNull("qualityMetrics");
922
+ }
923
+
924
+ return resultMap;
925
+ }
926
+
927
+ private void resolveMeasurementResultsHistory(Promise promise, ShenAIAndroidSDK.MeasurementResultsHistory history) {
928
+ if (history == null) {
929
+ promise.resolve(null);
930
+ return;
931
+ }
932
+
933
+ WritableMap topLevelMap = Arguments.createMap();
934
+ WritableArray itemsArray = Arguments.createArray();
935
+
936
+ if (history.history != null) {
937
+ for (ShenAIAndroidSDK.MeasurementResultsWithMetadata item : history.history) {
938
+ WritableMap itemMap = convertMeasurementResultsWithMetadataToMap(item);
939
+ itemsArray.pushMap(itemMap);
940
+ }
941
+ }
942
+
943
+ topLevelMap.putArray("history", itemsArray);
944
+ promise.resolve(topLevelMap);
945
+ }
946
+
947
+ @ReactMethod
948
+ public void getRealtimeMetrics(float periodSec, Promise promise) {
949
+ resolveMeasurementResults(promise, shenai_sdk.getRealtimeMetrics(periodSec));
950
+ }
951
+
952
+ @ReactMethod
953
+ public void getMeasurementResults(Promise promise) {
954
+ resolveMeasurementResults(promise, shenai_sdk.getMeasurementResults());
955
+ }
956
+
957
+ @ReactMethod
958
+ public void getMeasurementResultsHistory(Promise promise) {
959
+ resolveMeasurementResultsHistory(promise, shenai_sdk.getMeasurementResultsHistory());
960
+ }
961
+
962
+ @ReactMethod
963
+ public void getRealtimeHeartbeats(@Nullable Float periodSec, Promise promise) {
964
+ ShenAIAndroidSDK.Heartbeat[] heartbeats = shenai_sdk.getRealtimeHeartbeats(periodSec);
965
+ promise.resolve(convertHeartbeatsToArray(heartbeats));
966
+ }
967
+
968
+ private WritableArray convertHeartbeatsToArray(ShenAIAndroidSDK.Heartbeat[] heartbeats) {
969
+ WritableArray array = Arguments.createArray();
970
+ if (heartbeats == null) {
971
+ return array;
972
+ }
973
+ for (ShenAIAndroidSDK.Heartbeat hb : heartbeats) {
974
+ WritableMap hbMap = Arguments.createMap();
975
+ hbMap.putDouble("startLocationSec", hb.startLocationSec);
976
+ hbMap.putDouble("endLocationSec", hb.endLocationSec);
977
+ hbMap.putDouble("durationMs", hb.durationMs);
978
+ array.pushMap(hbMap);
979
+ }
980
+ return array;
981
+ }
982
+
983
+ @ReactMethod
984
+ public void getFullPpgSignal(Promise promise) {
985
+ double[] ppgSignal = shenai_sdk.getFullPpgSignal();
986
+ WritableArray array = Arguments.createArray();
987
+ for (double value : ppgSignal) {
988
+ array.pushDouble(value);
989
+ }
990
+ promise.resolve(array);
991
+ }
992
+
993
+ @ReactMethod
994
+ public void setRecordingEnabled(boolean recordingEnabled, Promise promise) {
995
+ shenai_sdk.setRecordingEnabled(recordingEnabled);
996
+ promise.resolve(null);
997
+ }
998
+
999
+ @ReactMethod
1000
+ public void getRecordingEnabled(Promise promise) {
1001
+ boolean isEnabled = shenai_sdk.getRecordingEnabled();
1002
+ promise.resolve(isEnabled);
1003
+ }
1004
+
1005
+ @ReactMethod
1006
+ public void getTotalBadSignalSeconds(Promise promise) {
1007
+ float totalSeconds = shenai_sdk.getTotalBadSignalSeconds();
1008
+ promise.resolve((double) totalSeconds);
1009
+ }
1010
+
1011
+ @ReactMethod
1012
+ public void getCurrentSignalQualityMetric(Promise promise) {
1013
+ float qualityMetric = shenai_sdk.getCurrentSignalQualityMetric();
1014
+ promise.resolve((double) qualityMetric);
1015
+ }
1016
+
1017
+ @ReactMethod
1018
+ public void getSignalQualityMapPng(Promise promise) {
1019
+ byte[] signalQualityMap = shenai_sdk.getSignalQualityMapPng();
1020
+ WritableArray array = Arguments.createArray();
1021
+ for (byte b : signalQualityMap) {
1022
+ array.pushInt(b & 0xFF); // Converting byte to unsigned int
1023
+ }
1024
+ promise.resolve(array);
1025
+ }
1026
+
1027
+ @ReactMethod
1028
+ public void getFaceTexturePng(Promise promise) {
1029
+ byte[] faceTexture = shenai_sdk.getFaceTexturePng();
1030
+ WritableArray array = Arguments.createArray();
1031
+ for (byte b : faceTexture) {
1032
+ array.pushInt(b & 0xFF); // Converting byte to unsigned int
1033
+ }
1034
+ promise.resolve(array);
1035
+ }
1036
+
1037
+ @ReactMethod
1038
+ public void setLanguage(String language, Promise promise) {
1039
+ shenai_sdk.setLanguage(language);
1040
+ promise.resolve(null);
1041
+ }
1042
+
1043
+ private ShenAIAndroidSDK.RisksFactors risksFactorsFromReadableMap(ReadableMap map) {
1044
+ ShenAIAndroidSDK.RisksFactors factors = shenai_sdk.new RisksFactors();
1045
+ if (map.hasKey("age")) factors.age = Optional.of(map.getInt("age"));
1046
+ if (map.hasKey("cholesterol")) factors.cholesterol = Optional.of((float) map.getDouble("cholesterol"));
1047
+ if (map.hasKey("cholesterolHdl")) factors.cholesterolHdl = Optional.of((float) map.getDouble("cholesterolHdl"));
1048
+ if (map.hasKey("sbp")) factors.sbp = Optional.of((float) map.getDouble("sbp"));
1049
+ if (map.hasKey("dbp")) factors.dbp = Optional.of((float) map.getDouble("dbp"));
1050
+ if (map.hasKey("isSmoker")) factors.isSmoker = Optional.of(map.getBoolean("isSmoker"));
1051
+ if (map.hasKey("hasDiabetes")) factors.hasDiabetes = Optional.of(map.getBoolean("hasDiabetes"));
1052
+ if (map.hasKey("bodyHeight")) factors.bodyHeight = Optional.of((float) map.getDouble("bodyHeight"));
1053
+ if (map.hasKey("bodyWeight")) factors.bodyWeight = Optional.of((float) map.getDouble("bodyWeight"));
1054
+ if (map.hasKey("waistCircumference")) factors.waistCircumference = Optional.of((float) map.getDouble("waistCircumference"));
1055
+ if (map.hasKey("neckCircumference")) factors.neckCircumference = Optional.of((float) map.getDouble("neckCircumference"));
1056
+ if (map.hasKey("hipCircumference")) factors.hipCircumference = Optional.of((float) map.getDouble("hipCircumference"));
1057
+ if (map.hasKey("gender")) {
1058
+ int genderIndex = map.getInt("gender");
1059
+ ShenAIAndroidSDK.Gender gender = ShenAIAndroidSDK.Gender.values()[genderIndex];
1060
+ factors.gender = Optional.of(gender);
1061
+ }
1062
+ if (map.hasKey("physicalActivity")) {
1063
+ int activityIndex = map.getInt("physicalActivity");
1064
+ ShenAIAndroidSDK.PhysicalActivity physicalActivity = ShenAIAndroidSDK.PhysicalActivity.values()[activityIndex];
1065
+ factors.physicalActivity = Optional.of(physicalActivity);
1066
+ }
1067
+ if (map.hasKey("country")) factors.country = map.getString("country");
1068
+ if (map.hasKey("race")) {
1069
+ int raceIndex = map.getInt("race");
1070
+ ShenAIAndroidSDK.Race race = ShenAIAndroidSDK.Race.values()[raceIndex];
1071
+ factors.race = Optional.of(race);
1072
+ }
1073
+ if (map.hasKey("historyOfHighGlucose")) factors.historyOfHighGlucose = Optional.of(map.getBoolean("historyOfHighGlucose"));
1074
+ if (map.hasKey("historyOfHypertension")) factors.historyOfHypertension = Optional.of(map.getBoolean("historyOfHypertension"));
1075
+ if (map.hasKey("vegetableFruitDiet")) factors.vegetableFruitDiet = Optional.of(map.getBoolean("vegetableFruitDiet"));
1076
+ if (map.hasKey("fastingGlucose")) factors.fastingGlucose = Optional.of((float) map.getDouble("fastingGlucose"));
1077
+ if (map.hasKey("triglyceride")) factors.triglyceride = Optional.of((float) map.getDouble("triglyceride"));
1078
+ if (map.hasKey("familyDiabetes")) {
1079
+ int familyDiabetesIndex = map.getInt("familyDiabetes");
1080
+ ShenAIAndroidSDK.FamilyHistory familyDiabetes = ShenAIAndroidSDK.FamilyHistory.values()[familyDiabetesIndex];
1081
+ factors.familyDiabetes = Optional.of(familyDiabetes);
1082
+ }
1083
+ if (map.hasKey("parentalHypertension")) {
1084
+ int parentalHypertensionIndex = map.getInt("parentalHypertension");
1085
+ ShenAIAndroidSDK.ParentalHistory parentalHypertension = ShenAIAndroidSDK.ParentalHistory.values()[parentalHypertensionIndex];
1086
+ factors.parentalHypertension = Optional.of(parentalHypertension);
1087
+ }
1088
+ if (map.hasKey("hypertensionTreatment")) {
1089
+ int hypertensionTreatmentIndex = map.getInt("hypertensionTreatment");
1090
+ ShenAIAndroidSDK.HypertensionTreatment hypertensionTreatment = ShenAIAndroidSDK.HypertensionTreatment.values()[hypertensionTreatmentIndex];
1091
+ factors.hypertensionTreatment = Optional.of(hypertensionTreatment);
1092
+ }
1093
+ return factors;
1094
+ }
1095
+
1096
+ private WritableMap writableMapFromRisksFactors(ShenAIAndroidSDK.RisksFactors factors) {
1097
+ WritableMap map = Arguments.createMap();
1098
+
1099
+ factors.age.ifPresent(value -> map.putInt("age", value));
1100
+ factors.cholesterol.ifPresent(value -> map.putDouble("cholesterol", value));
1101
+ factors.cholesterolHdl.ifPresent(value -> map.putDouble("cholesterolHdl", value));
1102
+ factors.sbp.ifPresent(value -> map.putDouble("sbp", value));
1103
+ factors.dbp.ifPresent(value -> map.putDouble("dbp", value));
1104
+ factors.isSmoker.ifPresent(value -> map.putBoolean("isSmoker", value));
1105
+ factors.hypertensionTreatment.ifPresent(hypertensionTreatment -> map.putInt("hypertensionTreatment", hypertensionTreatment.ordinal()));
1106
+ factors.hasDiabetes.ifPresent(value -> map.putBoolean("hasDiabetes", value));
1107
+ factors.bodyHeight.ifPresent(value -> map.putDouble("bodyHeight", value));
1108
+ factors.bodyWeight.ifPresent(value -> map.putDouble("bodyWeight", value));
1109
+ factors.waistCircumference.ifPresent(value -> map.putDouble("waistCircumference", value));
1110
+ factors.neckCircumference.ifPresent(value -> map.putDouble("neckCircumference", value));
1111
+ factors.hipCircumference.ifPresent(value -> map.putDouble("hipCircumference", value));
1112
+ factors.gender.ifPresent(gender -> map.putInt("gender", gender.ordinal()));
1113
+ factors.physicalActivity.ifPresent(physicalActivity -> map.putInt("physicalActivity", physicalActivity.ordinal()));
1114
+ map.putString("country", factors.country);
1115
+ factors.race.ifPresent(race -> map.putInt("race", race.ordinal()));
1116
+ factors.fastingGlucose.ifPresent(value -> map.putDouble("fastingGlucose", value));
1117
+ factors.triglyceride.ifPresent(value -> map.putDouble("triglyceride", value));
1118
+ factors.historyOfHighGlucose.ifPresent(value -> map.putBoolean("historyOfHighGlucose", value));
1119
+ factors.historyOfHypertension.ifPresent(value -> map.putBoolean("historyOfHypertension", value));
1120
+ factors.vegetableFruitDiet.ifPresent(value -> map.putBoolean("vegetableFruitDiet", value));
1121
+ factors.familyDiabetes.ifPresent(familyDiabetes -> map.putInt("familyDiabetes", familyDiabetes.ordinal()));
1122
+ factors.parentalHypertension.ifPresent(parentalHypertension -> map.putInt("parentalHypertension", parentalHypertension.ordinal()));
1123
+ return map;
1124
+ }
1125
+
1126
+ private WritableMap writableMapFromHealthRisks(ShenAIAndroidSDK.HealthRisks risks) {
1127
+ WritableMap map = Arguments.createMap();
1128
+
1129
+ // HardAndFatalEventsRisks
1130
+ WritableMap hardAndFatalEventsMap = Arguments.createMap();
1131
+ risks.hardAndFatalEvents.coronaryDeathEventRisk.ifPresent(value -> hardAndFatalEventsMap.putDouble("coronaryDeathEventRisk", value));
1132
+ risks.hardAndFatalEvents.fatalStrokeEventRisk.ifPresent(value -> hardAndFatalEventsMap.putDouble("fatalStrokeEventRisk", value));
1133
+ risks.hardAndFatalEvents.totalCVMortalityRisk.ifPresent(value -> hardAndFatalEventsMap.putDouble("totalCVMortalityRisk", value));
1134
+ risks.hardAndFatalEvents.hardCVEventRisk.ifPresent(value -> hardAndFatalEventsMap.putDouble("hardCVEventRisk", value));
1135
+ map.putMap("hardAndFatalEvents", hardAndFatalEventsMap);
1136
+
1137
+ // CVDiseasesRisks
1138
+ WritableMap cvDiseasesMap = Arguments.createMap();
1139
+ risks.cvDiseases.overallRisk.ifPresent(value -> cvDiseasesMap.putDouble("overallRisk", value));
1140
+ risks.cvDiseases.coronaryHeartDiseaseRisk.ifPresent(value -> cvDiseasesMap.putDouble("coronaryHeartDiseaseRisk", value));
1141
+ risks.cvDiseases.strokeRisk.ifPresent(value -> cvDiseasesMap.putDouble("strokeRisk", value));
1142
+ risks.cvDiseases.heartFailureRisk.ifPresent(value -> cvDiseasesMap.putDouble("heartFailureRisk", value));
1143
+ risks.cvDiseases.peripheralVascularDiseaseRisk.ifPresent(value -> cvDiseasesMap.putDouble("peripheralVascularDiseaseRisk", value));
1144
+ map.putMap("cvDiseases", cvDiseasesMap);
1145
+
1146
+ // RisksFactorsScores
1147
+ WritableMap scoresMap = Arguments.createMap();
1148
+ risks.scores.ageScore.ifPresent(value -> scoresMap.putInt("ageScore", value));
1149
+ risks.scores.sbpScore.ifPresent(value -> scoresMap.putInt("sbpScore", value));
1150
+ risks.scores.smokingScore.ifPresent(value -> scoresMap.putInt("smokingScore", value));
1151
+ risks.scores.diabetesScore.ifPresent(value -> scoresMap.putInt("diabetesScore", value));
1152
+ risks.scores.bmiScore.ifPresent(value -> scoresMap.putInt("bmiScore", value));
1153
+ risks.scores.cholesterolScore.ifPresent(value -> scoresMap.putInt("cholesterolScore", value));
1154
+ risks.scores.cholesterolHdlScore.ifPresent(value -> scoresMap.putInt("cholesterolHdlScore", value));
1155
+ risks.scores.totalScore.ifPresent(value -> scoresMap.putInt("totalScore", value));
1156
+ map.putMap("scores", scoresMap);
1157
+
1158
+ // Vascular Age
1159
+ risks.vascularAge.ifPresent(value -> map.putInt("vascularAge", value));
1160
+
1161
+ // Wellness Score
1162
+ risks.wellnessScore.ifPresent(value -> map.putDouble("wellnessScore", value));
1163
+
1164
+ // WHtR, BFP, BMR
1165
+ risks.waistToHeightRatio.ifPresent(value -> map.putDouble("waistToHeightRatio", value));
1166
+ risks.bodyFatPercentage.ifPresent(value -> map.putDouble("bodyFatPercentage", value));
1167
+ risks.basalMetabolicRate.ifPresent(value -> map.putDouble("basalMetabolicRate", value));
1168
+
1169
+ // BRI, CI, TDEE, ABSI
1170
+ risks.bodyRoundnessIndex.ifPresent(value -> map.putDouble("bodyRoundnessIndex", value));
1171
+ risks.conicityIndex.ifPresent(value -> map.putDouble("conicityIndex", value));
1172
+ risks.aBodyShapeIndex.ifPresent(value -> map.putDouble("aBodyShapeIndex", value));
1173
+ risks.totalDailyEnergyExpenditure.ifPresent(value -> map.putDouble("totalDailyEnergyExpenditure", value));
1174
+
1175
+ // HR, DR, NAFLDR
1176
+ risks.hypertensionRisk.ifPresent(value -> map.putDouble("hypertensionRisk", value));
1177
+ risks.diabetesRisk.ifPresent(value -> map.putDouble("diabetesRisk", value));
1178
+ risks.nonAlcoholicFattyLiverDiseaseRisk.ifPresent(value -> map.putInt("nonAlcoholicFattyLiverDiseaseRisk", value.ordinal()));
1179
+
1180
+ return map;
1181
+ }
1182
+
1183
+ @ReactMethod
1184
+ public void getHealthRisksFactors(Promise promise) {
1185
+ try {
1186
+ ShenAIAndroidSDK.RisksFactors factors = shenai_sdk.getHealthRisksFactors();
1187
+ WritableMap result = writableMapFromRisksFactors(factors);
1188
+ promise.resolve(result);
1189
+ } catch (Exception e) {
1190
+ promise.reject("ERROR_GET_RISKS_FACTORS", e.getMessage());
1191
+ }
1192
+ }
1193
+
1194
+ @ReactMethod
1195
+ public void clearHealthRisksFactors(Promise promise) {
1196
+ try {
1197
+ shenai_sdk.clearHealthRisksFactors();
1198
+ promise.resolve(null);
1199
+ } catch (Exception e) {
1200
+ promise.reject("ERROR_CLEAR_RISKS_FACTORS", e.getMessage());
1201
+ }
1202
+ }
1203
+
1204
+ @ReactMethod
1205
+ public void getHealthRisks(Promise promise) {
1206
+ try {
1207
+ ShenAIAndroidSDK.HealthRisks risks = shenai_sdk.getHealthRisks();
1208
+ WritableMap result = writableMapFromHealthRisks(risks);
1209
+ promise.resolve(result);
1210
+ } catch (Exception e) {
1211
+ promise.reject("ERROR_GET_RISKS", e.getMessage());
1212
+ }
1213
+ }
1214
+
1215
+ @ReactMethod
1216
+ public void computeHealthRisks(ReadableMap factorsMap, Promise promise) {
1217
+ ShenAIAndroidSDK.RisksFactors factors = risksFactorsFromReadableMap(factorsMap);
1218
+ try {
1219
+ ShenAIAndroidSDK.HealthRisks risks = shenai_sdk.computeHealthRisks(factors);
1220
+ WritableMap result = writableMapFromHealthRisks(risks);
1221
+ promise.resolve(result);
1222
+ } catch (Exception e) {
1223
+ promise.reject("ERROR_COMPUTE_RISKS", e.getMessage());
1224
+ }
1225
+ }
1226
+
1227
+ @ReactMethod
1228
+ public void getMaximalRisks(ReadableMap factorsMap, Promise promise) {
1229
+ ShenAIAndroidSDK.RisksFactors factors = risksFactorsFromReadableMap(factorsMap);
1230
+ try {
1231
+ ShenAIAndroidSDK.HealthRisks risks = shenai_sdk.getMaximalHealthRisks(factors);
1232
+ WritableMap result = writableMapFromHealthRisks(risks);
1233
+ promise.resolve(result);
1234
+ } catch (Exception e) {
1235
+ promise.reject("ERROR_MAXIMAL_RISKS", e.getMessage());
1236
+ }
1237
+ }
1238
+
1239
+ @ReactMethod
1240
+ public void getMinimalRisks(ReadableMap factorsMap, Promise promise) {
1241
+ ShenAIAndroidSDK.RisksFactors factors = risksFactorsFromReadableMap(factorsMap);
1242
+ try {
1243
+ ShenAIAndroidSDK.HealthRisks risks = shenai_sdk.getMinimalHealthRisks(factors);
1244
+ WritableMap result = writableMapFromHealthRisks(risks);
1245
+ promise.resolve(result);
1246
+ } catch (Exception e) {
1247
+ promise.reject("ERROR_MINIMAL_RISKS", e.getMessage());
1248
+ }
1249
+ }
1250
+
1251
+ @ReactMethod
1252
+ public void getReferenceRisks(ReadableMap factorsMap, Promise promise) {
1253
+ ShenAIAndroidSDK.RisksFactors factors = risksFactorsFromReadableMap(factorsMap);
1254
+ try {
1255
+ ShenAIAndroidSDK.HealthRisks risks = shenai_sdk.getReferenceHealthRisks(factors);
1256
+ WritableMap result = writableMapFromHealthRisks(risks);
1257
+ promise.resolve(result);
1258
+ } catch (Exception e) {
1259
+ promise.reject("ERROR_REFERENCE_RISKS", e.getMessage());
1260
+ }
1261
+ }
1262
+
1263
+
1264
+ @ReactMethod
1265
+ public void openMeasurementResultsPdfInBrowser(Promise promise) {
1266
+ shenai_sdk.openMeasurementResultsPdfInBrowser();
1267
+ promise.resolve(null);
1268
+ }
1269
+
1270
+ @ReactMethod
1271
+ public void sendMeasurementResultsPdfToEmail(String email, Promise promise) {
1272
+ shenai_sdk.sendMeasurementResultsPdfToEmail(email);
1273
+ promise.resolve(null);
1274
+ }
1275
+
1276
+ @ReactMethod
1277
+ public void requestMeasurementResultsPdfUrl(Promise promise) {
1278
+ shenai_sdk.requestMeasurementResultsPdfUrl();
1279
+ promise.resolve(null);
1280
+ }
1281
+
1282
+ @ReactMethod
1283
+ public void getMeasurementResultsPdfUrl(Promise promise) {
1284
+ String url = shenai_sdk.getMeasurementResultsPdfUrl();
1285
+ if (url == null || url.isEmpty()) {
1286
+ promise.resolve(null);
1287
+ } else {
1288
+ promise.resolve(url);
1289
+ }
1290
+ }
1291
+
1292
+ @ReactMethod
1293
+ public void requestMeasurementResultsPdfBytes(Promise promise) {
1294
+ shenai_sdk.requestMeasurementResultsPdfBytes();
1295
+ promise.resolve(null);
1296
+ }
1297
+
1298
+ @ReactMethod
1299
+ public void getMeasurementResultsPdfBytes(Promise promise) {
1300
+ byte[] bytes = shenai_sdk.getMeasurementResultsPdfBytes();
1301
+ if (bytes == null) {
1302
+ promise.resolve(null);
1303
+ return;
1304
+ }
1305
+ promise.resolve(Base64.encodeToString(bytes, Base64.NO_WRAP));
1306
+ }
1307
+
1308
+ @ReactMethod
1309
+ public void getResultAsFhirObservation(Promise promise) {
1310
+ String observation = shenai_sdk.getResultAsFhirObservation();
1311
+ if (observation == null || observation.isEmpty()) {
1312
+ promise.resolve(null);
1313
+ } else {
1314
+ promise.resolve(observation);
1315
+ }
1316
+ }
1317
+
1318
+ @ReactMethod
1319
+ public void sendResultFhirObservation(String url, Promise promise) {
1320
+ shenai_sdk.sendResultFhirObservation(url, response -> {
1321
+ final String result = (response == null || response.isEmpty()) ? null : response;
1322
+ UiThreadUtil.runOnUiThread(() -> promise.resolve(result));
1323
+ });
1324
+ }
1325
+ }