@neurosity/sdk 6.0.0-next.11
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/LICENSE +21 -0
- package/README.md +46 -0
- package/dist/browser/neurosity.iife.js +48736 -0
- package/dist/browser/neurosity.js +672 -0
- package/dist/browser/neurosity.js.map +1 -0
- package/dist/cjs/Notion.d.ts +619 -0
- package/dist/cjs/Notion.js +1291 -0
- package/dist/cjs/api/bluetooth/BluetoothClient.d.ts +59 -0
- package/dist/cjs/api/bluetooth/BluetoothClient.js +287 -0
- package/dist/cjs/api/bluetooth/BluetoothTransport.d.ts +32 -0
- package/dist/cjs/api/bluetooth/BluetoothTransport.js +2 -0
- package/dist/cjs/api/bluetooth/constants.d.ts +4 -0
- package/dist/cjs/api/bluetooth/constants.js +9 -0
- package/dist/cjs/api/bluetooth/index.d.ts +4 -0
- package/dist/cjs/api/bluetooth/index.js +20 -0
- package/dist/cjs/api/bluetooth/react-native/ReactNativeTransport.d.ts +65 -0
- package/dist/cjs/api/bluetooth/react-native/ReactNativeTransport.js +386 -0
- package/dist/cjs/api/bluetooth/react-native/types/BleManagerTypes.d.ts +63 -0
- package/dist/cjs/api/bluetooth/react-native/types/BleManagerTypes.js +11 -0
- package/dist/cjs/api/bluetooth/react-native/types/ReactNativeTypes.d.ts +180 -0
- package/dist/cjs/api/bluetooth/react-native/types/ReactNativeTypes.js +10 -0
- package/dist/cjs/api/bluetooth/types/index.d.ts +31 -0
- package/dist/cjs/api/bluetooth/types/index.js +22 -0
- package/dist/cjs/api/bluetooth/utils/create6DigitPin.d.ts +1 -0
- package/dist/cjs/api/bluetooth/utils/create6DigitPin.js +8 -0
- package/dist/cjs/api/bluetooth/utils/csvBufferToEpoch.d.ts +11 -0
- package/dist/cjs/api/bluetooth/utils/csvBufferToEpoch.js +36 -0
- package/dist/cjs/api/bluetooth/utils/encoding.d.ts +3 -0
- package/dist/cjs/api/bluetooth/utils/encoding.js +22 -0
- package/dist/cjs/api/bluetooth/utils/osHasBluetoothSupport.d.ts +2 -0
- package/dist/cjs/api/bluetooth/utils/osHasBluetoothSupport.js +23 -0
- package/dist/cjs/api/bluetooth/utils/stitch.d.ts +5 -0
- package/dist/cjs/api/bluetooth/utils/stitch.js +22 -0
- package/dist/cjs/api/bluetooth/web/WebBluetoothTransport.d.ts +47 -0
- package/dist/cjs/api/bluetooth/web/WebBluetoothTransport.js +412 -0
- package/dist/cjs/api/bluetooth/web/isMaybeWebWorkerContext.d.ts +1 -0
- package/dist/cjs/api/bluetooth/web/isMaybeWebWorkerContext.js +8 -0
- package/dist/cjs/api/bluetooth/web/isWebBluetoothSupported.d.ts +1 -0
- package/dist/cjs/api/bluetooth/web/isWebBluetoothSupported.js +11 -0
- package/dist/cjs/api/firebase/FirebaseApp.d.ts +20 -0
- package/dist/cjs/api/firebase/FirebaseApp.js +70 -0
- package/dist/cjs/api/firebase/FirebaseDevice.d.ts +68 -0
- package/dist/cjs/api/firebase/FirebaseDevice.js +146 -0
- package/dist/cjs/api/firebase/FirebaseUser.d.ts +53 -0
- package/dist/cjs/api/firebase/FirebaseUser.js +434 -0
- package/dist/cjs/api/firebase/config.d.ts +8 -0
- package/dist/cjs/api/firebase/config.js +11 -0
- package/dist/cjs/api/firebase/deviceStore.d.ts +26 -0
- package/dist/cjs/api/firebase/deviceStore.js +191 -0
- package/dist/cjs/api/firebase/index.d.ts +3 -0
- package/dist/cjs/api/firebase/index.js +19 -0
- package/dist/cjs/api/https/config.d.ts +1 -0
- package/dist/cjs/api/https/config.js +4 -0
- package/dist/cjs/api/https/createOAuthURL.d.ts +3 -0
- package/dist/cjs/api/https/createOAuthURL.js +18 -0
- package/dist/cjs/api/https/getOAuthToken.d.ts +3 -0
- package/dist/cjs/api/https/getOAuthToken.js +34 -0
- package/dist/cjs/api/https/utils.d.ts +2 -0
- package/dist/cjs/api/https/utils.js +13 -0
- package/dist/cjs/api/index.d.ts +108 -0
- package/dist/cjs/api/index.js +306 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/skills/NotionOnDevice.d.ts +7 -0
- package/dist/cjs/skills/NotionOnDevice.js +25 -0
- package/dist/cjs/skills/createSkill.d.ts +7 -0
- package/dist/cjs/skills/createSkill.js +40 -0
- package/dist/cjs/skills/index.d.ts +2 -0
- package/dist/cjs/skills/index.js +18 -0
- package/dist/cjs/subscriptions/SubscriptionManager.d.ts +11 -0
- package/dist/cjs/subscriptions/SubscriptionManager.js +27 -0
- package/dist/cjs/timesync/Timesync.d.ts +20 -0
- package/dist/cjs/timesync/Timesync.js +78 -0
- package/dist/cjs/timesync/index.d.ts +1 -0
- package/dist/cjs/timesync/index.js +17 -0
- package/dist/cjs/types/accelerometer.d.ts +10 -0
- package/dist/cjs/types/accelerometer.js +2 -0
- package/dist/cjs/types/actions.d.ts +16 -0
- package/dist/cjs/types/actions.js +2 -0
- package/dist/cjs/types/awareness.d.ts +1 -0
- package/dist/cjs/types/awareness.js +2 -0
- package/dist/cjs/types/brainwaves.d.ts +26 -0
- package/dist/cjs/types/brainwaves.js +2 -0
- package/dist/cjs/types/calm.d.ts +6 -0
- package/dist/cjs/types/calm.js +2 -0
- package/dist/cjs/types/client.d.ts +22 -0
- package/dist/cjs/types/client.js +2 -0
- package/dist/cjs/types/credentials.d.ts +12 -0
- package/dist/cjs/types/credentials.js +2 -0
- package/dist/cjs/types/deviceInfo.d.ts +18 -0
- package/dist/cjs/types/deviceInfo.js +2 -0
- package/dist/cjs/types/epoch.d.ts +12 -0
- package/dist/cjs/types/epoch.js +2 -0
- package/dist/cjs/types/experiment.d.ts +9 -0
- package/dist/cjs/types/experiment.js +2 -0
- package/dist/cjs/types/focus.d.ts +6 -0
- package/dist/cjs/types/focus.js +2 -0
- package/dist/cjs/types/hapticEffects.d.ts +125 -0
- package/dist/cjs/types/hapticEffects.js +2 -0
- package/dist/cjs/types/kinesis.d.ts +6 -0
- package/dist/cjs/types/kinesis.js +2 -0
- package/dist/cjs/types/marker.d.ts +7 -0
- package/dist/cjs/types/marker.js +2 -0
- package/dist/cjs/types/metrics.d.ts +21 -0
- package/dist/cjs/types/metrics.js +2 -0
- package/dist/cjs/types/oauth.d.ts +20 -0
- package/dist/cjs/types/oauth.js +2 -0
- package/dist/cjs/types/options.d.ts +51 -0
- package/dist/cjs/types/options.js +2 -0
- package/dist/cjs/types/sample.d.ts +15 -0
- package/dist/cjs/types/sample.js +2 -0
- package/dist/cjs/types/settings.d.ts +13 -0
- package/dist/cjs/types/settings.js +2 -0
- package/dist/cjs/types/signalQuality.d.ts +13 -0
- package/dist/cjs/types/signalQuality.js +2 -0
- package/dist/cjs/types/skill.d.ts +68 -0
- package/dist/cjs/types/skill.js +2 -0
- package/dist/cjs/types/status.d.ts +26 -0
- package/dist/cjs/types/status.js +22 -0
- package/dist/cjs/types/streaming.d.ts +15 -0
- package/dist/cjs/types/streaming.js +20 -0
- package/dist/cjs/types/subscriptions.d.ts +23 -0
- package/dist/cjs/types/subscriptions.js +2 -0
- package/dist/cjs/types/training.d.ts +19 -0
- package/dist/cjs/types/training.js +2 -0
- package/dist/cjs/types/user.d.ts +12 -0
- package/dist/cjs/types/user.js +2 -0
- package/dist/cjs/utils/errors.d.ts +5 -0
- package/dist/cjs/utils/errors.js +17 -0
- package/dist/cjs/utils/filterInternalKeys.d.ts +3 -0
- package/dist/cjs/utils/filterInternalKeys.js +21 -0
- package/dist/cjs/utils/hapticEffects.d.ts +123 -0
- package/dist/cjs/utils/hapticEffects.js +130 -0
- package/dist/cjs/utils/heartbeat.d.ts +4 -0
- package/dist/cjs/utils/heartbeat.js +34 -0
- package/dist/cjs/utils/is-node.d.ts +1 -0
- package/dist/cjs/utils/is-node.js +9 -0
- package/dist/cjs/utils/metrics.d.ts +1 -0
- package/dist/cjs/utils/metrics.js +56 -0
- package/dist/cjs/utils/oauth.d.ts +9 -0
- package/dist/cjs/utils/oauth.js +92 -0
- package/dist/cjs/utils/pick.d.ts +1 -0
- package/dist/cjs/utils/pick.js +5 -0
- package/dist/cjs/utils/pipes.d.ts +46 -0
- package/dist/cjs/utils/pipes.js +71 -0
- package/dist/cjs/utils/platform.d.ts +30 -0
- package/dist/cjs/utils/platform.js +47 -0
- package/dist/cjs/utils/subscription.d.ts +6 -0
- package/dist/cjs/utils/subscription.js +55 -0
- package/dist/cjs/utils/transferDevice.d.ts +9 -0
- package/dist/cjs/utils/transferDevice.js +2 -0
- package/dist/cjs/utils/whileOnline.d.ts +8 -0
- package/dist/cjs/utils/whileOnline.js +15 -0
- package/dist/electron/index.js +92 -0
- package/dist/electron/index.js.map +1 -0
- package/dist/esm/Notion.d.ts +619 -0
- package/dist/esm/Notion.js +1260 -0
- package/dist/esm/api/bluetooth/BluetoothClient.d.ts +59 -0
- package/dist/esm/api/bluetooth/BluetoothClient.js +283 -0
- package/dist/esm/api/bluetooth/BluetoothTransport.d.ts +32 -0
- package/dist/esm/api/bluetooth/BluetoothTransport.js +1 -0
- package/dist/esm/api/bluetooth/constants.d.ts +4 -0
- package/dist/esm/api/bluetooth/constants.js +6 -0
- package/dist/esm/api/bluetooth/index.d.ts +4 -0
- package/dist/esm/api/bluetooth/index.js +4 -0
- package/dist/esm/api/bluetooth/react-native/ReactNativeTransport.d.ts +65 -0
- package/dist/esm/api/bluetooth/react-native/ReactNativeTransport.js +382 -0
- package/dist/esm/api/bluetooth/react-native/types/BleManagerTypes.d.ts +63 -0
- package/dist/esm/api/bluetooth/react-native/types/BleManagerTypes.js +8 -0
- package/dist/esm/api/bluetooth/react-native/types/ReactNativeTypes.d.ts +180 -0
- package/dist/esm/api/bluetooth/react-native/types/ReactNativeTypes.js +9 -0
- package/dist/esm/api/bluetooth/types/index.d.ts +31 -0
- package/dist/esm/api/bluetooth/types/index.js +19 -0
- package/dist/esm/api/bluetooth/utils/create6DigitPin.d.ts +1 -0
- package/dist/esm/api/bluetooth/utils/create6DigitPin.js +4 -0
- package/dist/esm/api/bluetooth/utils/csvBufferToEpoch.d.ts +11 -0
- package/dist/esm/api/bluetooth/utils/csvBufferToEpoch.js +31 -0
- package/dist/esm/api/bluetooth/utils/encoding.d.ts +3 -0
- package/dist/esm/api/bluetooth/utils/encoding.js +17 -0
- package/dist/esm/api/bluetooth/utils/osHasBluetoothSupport.d.ts +2 -0
- package/dist/esm/api/bluetooth/utils/osHasBluetoothSupport.js +16 -0
- package/dist/esm/api/bluetooth/utils/stitch.d.ts +5 -0
- package/dist/esm/api/bluetooth/utils/stitch.js +18 -0
- package/dist/esm/api/bluetooth/web/WebBluetoothTransport.d.ts +47 -0
- package/dist/esm/api/bluetooth/web/WebBluetoothTransport.js +408 -0
- package/dist/esm/api/bluetooth/web/isMaybeWebWorkerContext.d.ts +1 -0
- package/dist/esm/api/bluetooth/web/isMaybeWebWorkerContext.js +4 -0
- package/dist/esm/api/bluetooth/web/isWebBluetoothSupported.d.ts +1 -0
- package/dist/esm/api/bluetooth/web/isWebBluetoothSupported.js +7 -0
- package/dist/esm/api/firebase/FirebaseApp.d.ts +20 -0
- package/dist/esm/api/firebase/FirebaseApp.js +63 -0
- package/dist/esm/api/firebase/FirebaseDevice.d.ts +68 -0
- package/dist/esm/api/firebase/FirebaseDevice.js +139 -0
- package/dist/esm/api/firebase/FirebaseUser.d.ts +53 -0
- package/dist/esm/api/firebase/FirebaseUser.js +426 -0
- package/dist/esm/api/firebase/config.d.ts +8 -0
- package/dist/esm/api/firebase/config.js +8 -0
- package/dist/esm/api/firebase/deviceStore.d.ts +26 -0
- package/dist/esm/api/firebase/deviceStore.js +184 -0
- package/dist/esm/api/firebase/index.d.ts +3 -0
- package/dist/esm/api/firebase/index.js +3 -0
- package/dist/esm/api/https/config.d.ts +1 -0
- package/dist/esm/api/https/config.js +1 -0
- package/dist/esm/api/https/createOAuthURL.d.ts +3 -0
- package/dist/esm/api/https/createOAuthURL.js +11 -0
- package/dist/esm/api/https/getOAuthToken.d.ts +3 -0
- package/dist/esm/api/https/getOAuthToken.js +27 -0
- package/dist/esm/api/https/utils.d.ts +2 -0
- package/dist/esm/api/https/utils.js +9 -0
- package/dist/esm/api/index.d.ts +108 -0
- package/dist/esm/api/index.js +299 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/neurosity.mjs +48722 -0
- package/dist/esm/skills/NotionOnDevice.d.ts +7 -0
- package/dist/esm/skills/NotionOnDevice.js +21 -0
- package/dist/esm/skills/createSkill.d.ts +7 -0
- package/dist/esm/skills/createSkill.js +36 -0
- package/dist/esm/skills/index.d.ts +2 -0
- package/dist/esm/skills/index.js +2 -0
- package/dist/esm/subscriptions/SubscriptionManager.d.ts +11 -0
- package/dist/esm/subscriptions/SubscriptionManager.js +23 -0
- package/dist/esm/timesync/Timesync.d.ts +20 -0
- package/dist/esm/timesync/Timesync.js +71 -0
- package/dist/esm/timesync/index.d.ts +1 -0
- package/dist/esm/timesync/index.js +1 -0
- package/dist/esm/types/accelerometer.d.ts +10 -0
- package/dist/esm/types/accelerometer.js +1 -0
- package/dist/esm/types/actions.d.ts +16 -0
- package/dist/esm/types/actions.js +1 -0
- package/dist/esm/types/awareness.d.ts +1 -0
- package/dist/esm/types/awareness.js +1 -0
- package/dist/esm/types/brainwaves.d.ts +26 -0
- package/dist/esm/types/brainwaves.js +1 -0
- package/dist/esm/types/calm.d.ts +6 -0
- package/dist/esm/types/calm.js +1 -0
- package/dist/esm/types/client.d.ts +22 -0
- package/dist/esm/types/client.js +1 -0
- package/dist/esm/types/credentials.d.ts +12 -0
- package/dist/esm/types/credentials.js +1 -0
- package/dist/esm/types/deviceInfo.d.ts +18 -0
- package/dist/esm/types/deviceInfo.js +1 -0
- package/dist/esm/types/epoch.d.ts +12 -0
- package/dist/esm/types/epoch.js +1 -0
- package/dist/esm/types/experiment.d.ts +9 -0
- package/dist/esm/types/experiment.js +1 -0
- package/dist/esm/types/focus.d.ts +6 -0
- package/dist/esm/types/focus.js +1 -0
- package/dist/esm/types/hapticEffects.d.ts +125 -0
- package/dist/esm/types/hapticEffects.js +1 -0
- package/dist/esm/types/kinesis.d.ts +6 -0
- package/dist/esm/types/kinesis.js +1 -0
- package/dist/esm/types/marker.d.ts +7 -0
- package/dist/esm/types/marker.js +1 -0
- package/dist/esm/types/metrics.d.ts +21 -0
- package/dist/esm/types/metrics.js +1 -0
- package/dist/esm/types/oauth.d.ts +20 -0
- package/dist/esm/types/oauth.js +1 -0
- package/dist/esm/types/options.d.ts +51 -0
- package/dist/esm/types/options.js +1 -0
- package/dist/esm/types/sample.d.ts +15 -0
- package/dist/esm/types/sample.js +1 -0
- package/dist/esm/types/settings.d.ts +13 -0
- package/dist/esm/types/settings.js +1 -0
- package/dist/esm/types/signalQuality.d.ts +13 -0
- package/dist/esm/types/signalQuality.js +1 -0
- package/dist/esm/types/skill.d.ts +68 -0
- package/dist/esm/types/skill.js +1 -0
- package/dist/esm/types/status.d.ts +26 -0
- package/dist/esm/types/status.js +19 -0
- package/dist/esm/types/streaming.d.ts +15 -0
- package/dist/esm/types/streaming.js +17 -0
- package/dist/esm/types/subscriptions.d.ts +23 -0
- package/dist/esm/types/subscriptions.js +1 -0
- package/dist/esm/types/training.d.ts +19 -0
- package/dist/esm/types/training.js +1 -0
- package/dist/esm/types/user.d.ts +12 -0
- package/dist/esm/types/user.js +1 -0
- package/dist/esm/utils/errors.d.ts +5 -0
- package/dist/esm/utils/errors.js +11 -0
- package/dist/esm/utils/filterInternalKeys.d.ts +3 -0
- package/dist/esm/utils/filterInternalKeys.js +17 -0
- package/dist/esm/utils/hapticEffects.d.ts +123 -0
- package/dist/esm/utils/hapticEffects.js +125 -0
- package/dist/esm/utils/heartbeat.d.ts +4 -0
- package/dist/esm/utils/heartbeat.js +29 -0
- package/dist/esm/utils/is-node.d.ts +1 -0
- package/dist/esm/utils/is-node.js +5 -0
- package/dist/esm/utils/metrics.d.ts +1 -0
- package/dist/esm/utils/metrics.js +52 -0
- package/dist/esm/utils/oauth.d.ts +9 -0
- package/dist/esm/utils/oauth.js +64 -0
- package/dist/esm/utils/pick.d.ts +1 -0
- package/dist/esm/utils/pick.js +1 -0
- package/dist/esm/utils/pipes.d.ts +46 -0
- package/dist/esm/utils/pipes.js +65 -0
- package/dist/esm/utils/platform.d.ts +30 -0
- package/dist/esm/utils/platform.js +41 -0
- package/dist/esm/utils/subscription.d.ts +6 -0
- package/dist/esm/utils/subscription.js +24 -0
- package/dist/esm/utils/transferDevice.d.ts +9 -0
- package/dist/esm/utils/transferDevice.js +1 -0
- package/dist/esm/utils/whileOnline.d.ts +8 -0
- package/dist/esm/utils/whileOnline.js +11 -0
- package/dist/examples/auth.html +32 -0
- package/dist/examples/cloud.html +17 -0
- package/dist/examples/index.html +1 -0
- package/dist/examples/neurosity.iife.js +48736 -0
- package/dist/examples/neurosity.js +672 -0
- package/dist/examples/neurosity.mjs +48722 -0
- package/dist/examples/training.html +49 -0
- package/package.json +78 -0
|
@@ -0,0 +1,1260 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { combineLatest, Observable, of, throwError } from "rxjs";
|
|
11
|
+
import { ReplaySubject, firstValueFrom, EMPTY } from "rxjs";
|
|
12
|
+
import { distinctUntilChanged, map, switchMap } from "rxjs/operators";
|
|
13
|
+
import isEqual from "fast-deep-equal";
|
|
14
|
+
import { CloudClient, createUser } from "./api/index";
|
|
15
|
+
import { credentialWithLink, SERVER_TIMESTAMP } from "./api/index";
|
|
16
|
+
import { STREAMING_MODE, STREAMING_TYPE } from "./types/streaming";
|
|
17
|
+
import { getLabels } from "./utils/subscription";
|
|
18
|
+
import { STATUS } from "./types/status";
|
|
19
|
+
import * as errors from "./utils/errors";
|
|
20
|
+
import * as platform from "./utils/platform";
|
|
21
|
+
import * as hapticEffects from "./utils/hapticEffects";
|
|
22
|
+
import { validateOAuthScopeForFunctionName } from "./utils/oauth";
|
|
23
|
+
import { validateOAuthScopeForAction } from "./utils/oauth";
|
|
24
|
+
import { createOAuthURL } from "./api/https/createOAuthURL";
|
|
25
|
+
import { getOAuthToken } from "./api/https/getOAuthToken";
|
|
26
|
+
import { isNode } from "./utils/is-node";
|
|
27
|
+
import { getCloudMetric } from "./utils/metrics";
|
|
28
|
+
import { BluetoothClient } from "./api/bluetooth";
|
|
29
|
+
import { BLUETOOTH_CONNECTION } from "./api/bluetooth/types";
|
|
30
|
+
const defaultOptions = {
|
|
31
|
+
timesync: false,
|
|
32
|
+
autoSelectDevice: true,
|
|
33
|
+
streamingMode: STREAMING_MODE.WIFI_ONLY,
|
|
34
|
+
emulator: false,
|
|
35
|
+
emulatorHost: "localhost",
|
|
36
|
+
emulatorAuthPort: 9099,
|
|
37
|
+
emulatorDatabasePort: 9000,
|
|
38
|
+
emulatorFunctionsPort: 5001,
|
|
39
|
+
emulatorFirestorePort: 8080,
|
|
40
|
+
emulatorOptions: {}
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* import StreamingModes from "@site/src/components/StreamingModes";
|
|
44
|
+
*
|
|
45
|
+
* Example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import { Neurosity } from "@neurosity/sdk";
|
|
48
|
+
*
|
|
49
|
+
* const neurosity = new Neurosity();
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export class Neurosity {
|
|
53
|
+
/**
|
|
54
|
+
* Creates new instance of the Neurosity SDK
|
|
55
|
+
*
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const neurosity = new Neurosity();
|
|
58
|
+
* ```
|
|
59
|
+
|
|
60
|
+
* @param options
|
|
61
|
+
*/
|
|
62
|
+
constructor(options = {}) {
|
|
63
|
+
/**
|
|
64
|
+
* @hidden
|
|
65
|
+
*/
|
|
66
|
+
this.streamingMode$ = new ReplaySubject(1);
|
|
67
|
+
const { streamingMode, bluetoothTransport } = options;
|
|
68
|
+
this.options = Object.freeze(Object.assign(Object.assign({}, defaultOptions), options));
|
|
69
|
+
this.cloudClient = new CloudClient(this.options);
|
|
70
|
+
if (!!bluetoothTransport) {
|
|
71
|
+
this.bluetoothClient = new BluetoothClient({
|
|
72
|
+
selectedDevice$: this.onDeviceChange(),
|
|
73
|
+
createBluetoothToken: this.createBluetoothToken.bind(this),
|
|
74
|
+
transport: bluetoothTransport
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
this._initStreamingMode(streamingMode, !!bluetoothTransport);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @hidden
|
|
82
|
+
*/
|
|
83
|
+
_initStreamingMode(streamingMode, hasBluetoothTransport) {
|
|
84
|
+
const streamingModeFeaturesBluetooth = [
|
|
85
|
+
STREAMING_MODE.BLUETOOTH_WITH_WIFI_FALLBACK,
|
|
86
|
+
STREAMING_MODE.WIFI_WITH_BLUETOOTH_FALLBACK
|
|
87
|
+
].includes(streamingMode);
|
|
88
|
+
const isInvalidStreamingMode = !Object.values(STREAMING_MODE).includes(streamingMode);
|
|
89
|
+
const isMissingBluetoothTransport = streamingModeFeaturesBluetooth && !hasBluetoothTransport;
|
|
90
|
+
this.isMissingBluetoothTransport = isMissingBluetoothTransport;
|
|
91
|
+
const shouldDefaultToCloud = !streamingMode || isInvalidStreamingMode || isMissingBluetoothTransport;
|
|
92
|
+
// Default to backwards compatible cloud streaming mode if:
|
|
93
|
+
// 1. No streaming mode is provided
|
|
94
|
+
// 2. An invalid streaming mode is provided
|
|
95
|
+
// 3. A streaming mode containing bluetooth is provided, but without a bluetooth transport
|
|
96
|
+
if (shouldDefaultToCloud) {
|
|
97
|
+
this.streamingMode$.next(STREAMING_MODE.WIFI_ONLY);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
this.streamingMode$.next(streamingMode);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Subscribe to the device's streaming state changes and the current strategy
|
|
105
|
+
*
|
|
106
|
+
* Streams the current mode of streaming (wifi or bluetooth).
|
|
107
|
+
*
|
|
108
|
+
* ```typescript
|
|
109
|
+
* neurosity.streamingState().subscribe((streamingState) => {
|
|
110
|
+
* console.log(streamingState);
|
|
111
|
+
* // { streamingMode: "wifi-only", activeMode: "wifi", connected: true }
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
streamingState() {
|
|
116
|
+
const isWifiOnline = (state) => [STATUS.ONLINE, STATUS.UPDATING].includes(state);
|
|
117
|
+
return this.streamingMode$.pipe(switchMap((streamingMode) => {
|
|
118
|
+
if (this.isMissingBluetoothTransport) {
|
|
119
|
+
return this.cloudClient.status().pipe(map(({ state }) => ({
|
|
120
|
+
connected: isWifiOnline(state),
|
|
121
|
+
streamingMode,
|
|
122
|
+
activeMode: STREAMING_TYPE.WIFI
|
|
123
|
+
})));
|
|
124
|
+
}
|
|
125
|
+
return this.onDeviceChange().pipe(switchMap((selectDevice) => !selectDevice
|
|
126
|
+
? EMPTY
|
|
127
|
+
: combineLatest({
|
|
128
|
+
wifiStatus: this.cloudClient.status(),
|
|
129
|
+
bluetoothConnection: !!(this === null || this === void 0 ? void 0 : this.bluetoothClient)
|
|
130
|
+
? this.bluetoothClient.connection()
|
|
131
|
+
: of(BLUETOOTH_CONNECTION.DISCONNECTED)
|
|
132
|
+
}).pipe(map(({ wifiStatus, bluetoothConnection }) => {
|
|
133
|
+
const isBluetoothConnected = bluetoothConnection === BLUETOOTH_CONNECTION.CONNECTED;
|
|
134
|
+
switch (streamingMode) {
|
|
135
|
+
default:
|
|
136
|
+
case STREAMING_MODE.WIFI_ONLY:
|
|
137
|
+
return {
|
|
138
|
+
connected: isWifiOnline(wifiStatus.state),
|
|
139
|
+
streamingMode,
|
|
140
|
+
activeMode: STREAMING_TYPE.WIFI
|
|
141
|
+
};
|
|
142
|
+
case STREAMING_MODE.WIFI_WITH_BLUETOOTH_FALLBACK:
|
|
143
|
+
return {
|
|
144
|
+
connected: isWifiOnline(wifiStatus.state) ||
|
|
145
|
+
!isBluetoothConnected
|
|
146
|
+
? isWifiOnline(wifiStatus.state)
|
|
147
|
+
: isBluetoothConnected,
|
|
148
|
+
streamingMode,
|
|
149
|
+
activeMode: isWifiOnline(wifiStatus.state) ||
|
|
150
|
+
!isBluetoothConnected
|
|
151
|
+
? STREAMING_TYPE.WIFI
|
|
152
|
+
: STREAMING_TYPE.BLUETOOTH
|
|
153
|
+
};
|
|
154
|
+
case STREAMING_MODE.BLUETOOTH_WITH_WIFI_FALLBACK:
|
|
155
|
+
return {
|
|
156
|
+
connected: isBluetoothConnected
|
|
157
|
+
? true
|
|
158
|
+
: isWifiOnline(wifiStatus.state),
|
|
159
|
+
streamingMode,
|
|
160
|
+
activeMode: isBluetoothConnected
|
|
161
|
+
? STREAMING_TYPE.BLUETOOTH
|
|
162
|
+
: STREAMING_TYPE.WIFI
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}), distinctUntilChanged((a, b) => isEqual(a, b)))));
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
*
|
|
170
|
+
* @hidden
|
|
171
|
+
*/
|
|
172
|
+
_withStreamingModeObservable(streams) {
|
|
173
|
+
const { wifi, bluetooth } = streams;
|
|
174
|
+
return this.streamingState().pipe(switchMap(({ activeMode }) => {
|
|
175
|
+
switch (activeMode) {
|
|
176
|
+
case STREAMING_TYPE.WIFI:
|
|
177
|
+
return wifi();
|
|
178
|
+
case STREAMING_TYPE.BLUETOOTH:
|
|
179
|
+
return bluetooth();
|
|
180
|
+
default:
|
|
181
|
+
return wifi();
|
|
182
|
+
}
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
*
|
|
187
|
+
* @hidden
|
|
188
|
+
*/
|
|
189
|
+
_withStreamingModePromise(promises) {
|
|
190
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
191
|
+
const { wifi, bluetooth } = promises;
|
|
192
|
+
const { activeMode } = yield firstValueFrom(this.streamingState());
|
|
193
|
+
switch (activeMode) {
|
|
194
|
+
case STREAMING_TYPE.WIFI:
|
|
195
|
+
return yield wifi();
|
|
196
|
+
case STREAMING_TYPE.BLUETOOTH:
|
|
197
|
+
return yield bluetooth();
|
|
198
|
+
default:
|
|
199
|
+
return yield wifi();
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
*
|
|
205
|
+
* @hidden
|
|
206
|
+
*/
|
|
207
|
+
get bluetooth() {
|
|
208
|
+
return this === null || this === void 0 ? void 0 : this.bluetoothClient;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
*
|
|
212
|
+
* @hidden
|
|
213
|
+
*/
|
|
214
|
+
_getCloudMetricDependencies() {
|
|
215
|
+
return {
|
|
216
|
+
options: this.options,
|
|
217
|
+
cloudClient: this.cloudClient,
|
|
218
|
+
onDeviceChange: this.onDeviceChange.bind(this),
|
|
219
|
+
status: this.status.bind(this)
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Starts user session
|
|
224
|
+
*
|
|
225
|
+
* ```typescript
|
|
226
|
+
* await neurosity.login({
|
|
227
|
+
* email: "...",
|
|
228
|
+
* password: "..."
|
|
229
|
+
* });
|
|
230
|
+
* ```
|
|
231
|
+
*
|
|
232
|
+
* @param credentials
|
|
233
|
+
*/
|
|
234
|
+
login(credentials) {
|
|
235
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
236
|
+
return yield this.cloudClient.login(credentials);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Ends user session
|
|
241
|
+
*
|
|
242
|
+
* ```typescript
|
|
243
|
+
* await neurosity.logout();
|
|
244
|
+
* // session has ended
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
*/
|
|
248
|
+
logout() {
|
|
249
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
250
|
+
return yield this.cloudClient.logout();
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* @internal
|
|
255
|
+
* Not user facing.
|
|
256
|
+
*/
|
|
257
|
+
__getApp() {
|
|
258
|
+
return this.cloudClient.__getApp();
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Subscribe to auth state changes
|
|
262
|
+
*
|
|
263
|
+
* Streams the state of the auth session. If user has logged in, the user object will be set. When logged out, the user object will be null.
|
|
264
|
+
*
|
|
265
|
+
* ```typescript
|
|
266
|
+
* neurosity.onAuthStateChanged().subscribe((user) => {
|
|
267
|
+
* console.log(user);
|
|
268
|
+
* });
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
onAuthStateChanged() {
|
|
272
|
+
return this.cloudClient.onAuthStateChanged();
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* @internal
|
|
276
|
+
* Not user facing yet
|
|
277
|
+
*/
|
|
278
|
+
addDevice(deviceId) {
|
|
279
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "addDevice");
|
|
280
|
+
if (hasOAuthError) {
|
|
281
|
+
return Promise.reject(OAuthError);
|
|
282
|
+
}
|
|
283
|
+
return this.cloudClient.addDevice(deviceId);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* @internal
|
|
287
|
+
* Not user facing yet
|
|
288
|
+
*/
|
|
289
|
+
removeDevice(deviceId) {
|
|
290
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "removeDevice");
|
|
291
|
+
if (hasOAuthError) {
|
|
292
|
+
return Promise.reject(OAuthError);
|
|
293
|
+
}
|
|
294
|
+
return this.cloudClient.removeDevice(deviceId);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* @internal
|
|
298
|
+
* Not user facing yet
|
|
299
|
+
*/
|
|
300
|
+
transferDevice(options) {
|
|
301
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "transferDevice");
|
|
302
|
+
if (hasOAuthError) {
|
|
303
|
+
return Promise.reject(OAuthError);
|
|
304
|
+
}
|
|
305
|
+
return this.cloudClient.transferDevice(options);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* @internal
|
|
309
|
+
* Not user facing yet
|
|
310
|
+
*/
|
|
311
|
+
onUserDevicesChange() {
|
|
312
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "onUserDevicesChange");
|
|
313
|
+
if (hasOAuthError) {
|
|
314
|
+
return throwError(() => OAuthError);
|
|
315
|
+
}
|
|
316
|
+
return this.cloudClient.onUserDevicesChange();
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* @internal
|
|
320
|
+
* Not user facing yet
|
|
321
|
+
*/
|
|
322
|
+
onUserClaimsChange() {
|
|
323
|
+
return this.cloudClient.onUserClaimsChange();
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Get user devices
|
|
327
|
+
*
|
|
328
|
+
* Returns a list of devices claimed by the user authenticated.
|
|
329
|
+
*
|
|
330
|
+
* ```typescript
|
|
331
|
+
* const devices = await neurosity.getDevices();
|
|
332
|
+
* console.log(devices);
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
getDevices() {
|
|
336
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
337
|
+
return yield this.cloudClient.getDevices();
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Select Device
|
|
342
|
+
*
|
|
343
|
+
* Rarely necessary, but useful when the user owns multiple devices.
|
|
344
|
+
*
|
|
345
|
+
* A common use case for manually selecting a device is when you wish to build a device dropdown a user can select from, instead of collecting the Device Id from the user ahead of time.
|
|
346
|
+
*
|
|
347
|
+
* The 3 steps to manually selecting a device are:
|
|
348
|
+
*
|
|
349
|
+
* - Set `autoSelectDevice` to false when instantiating the `Neurosity` class.
|
|
350
|
+
* - Authenticate with your Neurosity account to access your devices by calling the `neurosity.login(...)` function.
|
|
351
|
+
* - Call the `neurosity.selectDevice(...)` function with a device selector function.
|
|
352
|
+
*
|
|
353
|
+
* ```typescript
|
|
354
|
+
* const devices = await neurosity.selectDevice((devices) =>
|
|
355
|
+
* devices.find((device) => device.deviceNickname === "Crown-A1B")
|
|
356
|
+
* );
|
|
357
|
+
*
|
|
358
|
+
* console.log(devices);
|
|
359
|
+
* ```
|
|
360
|
+
*
|
|
361
|
+
* > If you own multiple devices, and don't pass `autoSelectDevice`, then the first device on the list will be automatically selected.
|
|
362
|
+
*
|
|
363
|
+
* For more info, check out the "Device Selection" guide.
|
|
364
|
+
*/
|
|
365
|
+
selectDevice(deviceSelector) {
|
|
366
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
367
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "selectDevice");
|
|
368
|
+
if (hasOAuthError) {
|
|
369
|
+
return Promise.reject(OAuthError);
|
|
370
|
+
}
|
|
371
|
+
return yield this.cloudClient.selectDevice(deviceSelector);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Get selected device
|
|
376
|
+
*
|
|
377
|
+
* ```typescript
|
|
378
|
+
* const selectedDevice = await neurosity.getSelectedDevice();
|
|
379
|
+
* console.log(selectedDevice);
|
|
380
|
+
* ```
|
|
381
|
+
*/
|
|
382
|
+
getSelectedDevice() {
|
|
383
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
384
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "getSelectedDevice");
|
|
385
|
+
if (hasOAuthError) {
|
|
386
|
+
return Promise.reject(OAuthError);
|
|
387
|
+
}
|
|
388
|
+
return yield this.cloudClient.getSelectedDevice();
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* ```typescript
|
|
393
|
+
* const info = await neurosity.getInfo();
|
|
394
|
+
* ```
|
|
395
|
+
*/
|
|
396
|
+
getInfo() {
|
|
397
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
398
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
399
|
+
return Promise.reject(errors.mustSelectDevice);
|
|
400
|
+
}
|
|
401
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "getInfo");
|
|
402
|
+
if (hasOAuthError) {
|
|
403
|
+
return Promise.reject(OAuthError);
|
|
404
|
+
}
|
|
405
|
+
return yield this._withStreamingModePromise({
|
|
406
|
+
wifi: () => this.cloudClient.getInfo(),
|
|
407
|
+
bluetooth: () => this.bluetoothClient.getInfo()
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Observes selected device
|
|
413
|
+
*
|
|
414
|
+
* ```typescript
|
|
415
|
+
* neurosity.onDeviceChange().subscribe(device => {
|
|
416
|
+
* console.log(device);
|
|
417
|
+
* });
|
|
418
|
+
* ```
|
|
419
|
+
*/
|
|
420
|
+
onDeviceChange() {
|
|
421
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "onDeviceChange");
|
|
422
|
+
if (hasOAuthError) {
|
|
423
|
+
return throwError(() => OAuthError);
|
|
424
|
+
}
|
|
425
|
+
return this.cloudClient.onDeviceChange();
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
429
|
+
*
|
|
430
|
+
* Ends database connection
|
|
431
|
+
*
|
|
432
|
+
* ```typescript
|
|
433
|
+
* await neurosity.disconnect();
|
|
434
|
+
* ```
|
|
435
|
+
*/
|
|
436
|
+
disconnect() {
|
|
437
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
438
|
+
return yield this._withStreamingModePromise({
|
|
439
|
+
wifi: () => this.cloudClient.disconnect(),
|
|
440
|
+
bluetooth: () => this.bluetoothClient.disconnect()
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
446
|
+
*
|
|
447
|
+
* @internal
|
|
448
|
+
* Not user facing
|
|
449
|
+
*/
|
|
450
|
+
dispatchAction(action) {
|
|
451
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
452
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
453
|
+
return Promise.reject(errors.mustSelectDevice);
|
|
454
|
+
}
|
|
455
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForAction(this.cloudClient.userClaims, action);
|
|
456
|
+
if (hasOAuthError) {
|
|
457
|
+
return Promise.reject(OAuthError);
|
|
458
|
+
}
|
|
459
|
+
return yield this._withStreamingModePromise({
|
|
460
|
+
wifi: () => this.cloudClient.dispatchAction(action),
|
|
461
|
+
bluetooth: () => this.bluetoothClient.dispatchAction(action)
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
467
|
+
*
|
|
468
|
+
* Injects an EEG marker to data stream
|
|
469
|
+
*
|
|
470
|
+
* ```typescript
|
|
471
|
+
* neurosity.addMarker("eyes-closed");
|
|
472
|
+
*
|
|
473
|
+
* // later...
|
|
474
|
+
*
|
|
475
|
+
* neurosity.addMarker("eyes-open");
|
|
476
|
+
* ```
|
|
477
|
+
*
|
|
478
|
+
* @param label Name the label to inject
|
|
479
|
+
*/
|
|
480
|
+
addMarker(label) {
|
|
481
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
482
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
483
|
+
throw errors.mustSelectDevice;
|
|
484
|
+
}
|
|
485
|
+
if (!label) {
|
|
486
|
+
throw new Error(`${errors.prefix}A label is required for addMarker`);
|
|
487
|
+
}
|
|
488
|
+
return yield this._withStreamingModePromise({
|
|
489
|
+
wifi: () => this.cloudClient.dispatchAction({
|
|
490
|
+
command: "marker",
|
|
491
|
+
action: "add",
|
|
492
|
+
message: {
|
|
493
|
+
label,
|
|
494
|
+
timestamp: this.cloudClient.timestamp
|
|
495
|
+
}
|
|
496
|
+
}),
|
|
497
|
+
bluetooth: () => this.bluetoothClient.addMarker(label)
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
503
|
+
*
|
|
504
|
+
* Queue haptic motor commands
|
|
505
|
+
*
|
|
506
|
+
* To queue haptic P7 only,
|
|
507
|
+
* ```typescript
|
|
508
|
+
* await neurosity.haptics({
|
|
509
|
+
* P7: ["tripleClick100"]
|
|
510
|
+
* });
|
|
511
|
+
* ```
|
|
512
|
+
*
|
|
513
|
+
* To queue both motors at the same time
|
|
514
|
+
* ```typescript
|
|
515
|
+
* await neurosity.haptics({
|
|
516
|
+
* P7: [neurosity.getHapticEffects().strongClick100],
|
|
517
|
+
* P8: [neurosity.getHapticEffects().strongClick100]
|
|
518
|
+
* });
|
|
519
|
+
* ```
|
|
520
|
+
*
|
|
521
|
+
* You can queue different commands to the motors too
|
|
522
|
+
* ```typescript
|
|
523
|
+
* const effects = neurosity.getHapticEffects();
|
|
524
|
+
* await neurosity.haptics({
|
|
525
|
+
* P7: [effects.transitionRampUpLongSmooth1_0_to_100,
|
|
526
|
+
* effects.transitionRampDownLongSmooth1_100_to_0],
|
|
527
|
+
* P8: [effects.strongClick100]
|
|
528
|
+
* });
|
|
529
|
+
* ```
|
|
530
|
+
*
|
|
531
|
+
* @param effects Effects to queue. The key of the object passed should be the location of the motor
|
|
532
|
+
* to queue. Each key can be an array of up to 7 commands. There is no haptic support for model
|
|
533
|
+
* version 1, Notion DK1. The Haptic motor's location is positioned in reference to the 10-10 EEG
|
|
534
|
+
* system used to label the channels of the Crown's EEG sensors. Notion 2 and Crown have haptics
|
|
535
|
+
* at P7 and P8. A list of haptic commands can be found on ./utils/hapticCodes.ts - there
|
|
536
|
+
* are about 127 of them!
|
|
537
|
+
*/
|
|
538
|
+
haptics(effects) {
|
|
539
|
+
var _a;
|
|
540
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
541
|
+
const metric = "haptics";
|
|
542
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
543
|
+
return Promise.reject(errors.mustSelectDevice);
|
|
544
|
+
}
|
|
545
|
+
const modelVersion = (_a = (yield this.getSelectedDevice())) === null || _a === void 0 ? void 0 : _a.modelVersion;
|
|
546
|
+
const supportsHaptics = platform.supportsHaptics(modelVersion);
|
|
547
|
+
if (!supportsHaptics) {
|
|
548
|
+
return Promise.reject(errors.metricNotSupportedByModel(metric, modelVersion));
|
|
549
|
+
}
|
|
550
|
+
const newPlatformHapticRequest = platform.getPlatformHapticMotors(modelVersion);
|
|
551
|
+
for (const key in effects) {
|
|
552
|
+
if (!Object.keys(newPlatformHapticRequest).includes(key)) {
|
|
553
|
+
return Promise.reject(errors.locationNotFound(key, modelVersion));
|
|
554
|
+
}
|
|
555
|
+
const singleMotorEffects = effects[key];
|
|
556
|
+
const maxItems = 7;
|
|
557
|
+
if (singleMotorEffects.length > maxItems) {
|
|
558
|
+
return Promise.reject(errors.exceededMaxItems(maxItems));
|
|
559
|
+
}
|
|
560
|
+
newPlatformHapticRequest[key] = singleMotorEffects;
|
|
561
|
+
}
|
|
562
|
+
const payload = {
|
|
563
|
+
command: metric,
|
|
564
|
+
action: "queue",
|
|
565
|
+
responseRequired: true,
|
|
566
|
+
responseTimeout: 1000,
|
|
567
|
+
message: { effects: newPlatformHapticRequest }
|
|
568
|
+
};
|
|
569
|
+
return yield this._withStreamingModePromise({
|
|
570
|
+
wifi: () => this.cloudClient.dispatchAction(payload),
|
|
571
|
+
bluetooth: () => this.bluetoothClient.dispatchAction(payload)
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* ```typescript
|
|
577
|
+
* const effects = neurosity.getHapticEffects();
|
|
578
|
+
* ```
|
|
579
|
+
*/
|
|
580
|
+
getHapticEffects() {
|
|
581
|
+
return hapticEffects;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
585
|
+
*
|
|
586
|
+
* Observes accelerometer data
|
|
587
|
+
* Supported by the Crown and Notion 2 devices.
|
|
588
|
+
*
|
|
589
|
+
* ```typescript
|
|
590
|
+
* neurosity.accelerometer().subscribe(accelerometer => {
|
|
591
|
+
* console.log(accelerometer);
|
|
592
|
+
* });
|
|
593
|
+
*
|
|
594
|
+
* // { acceleration: ..., inclination: ..., orientation: ..., pitch: ..., roll: ..., x: ..., y: ..., z: ... }
|
|
595
|
+
* ```
|
|
596
|
+
*
|
|
597
|
+
* @returns Observable of accelerometer metric events
|
|
598
|
+
*/
|
|
599
|
+
accelerometer() {
|
|
600
|
+
const metric = "accelerometer";
|
|
601
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, metric);
|
|
602
|
+
if (hasOAuthError) {
|
|
603
|
+
return throwError(() => OAuthError);
|
|
604
|
+
}
|
|
605
|
+
return this.onDeviceChange().pipe(switchMap((selectedDevice) => {
|
|
606
|
+
const modelVersion = (selectedDevice === null || selectedDevice === void 0 ? void 0 : selectedDevice.modelVersion) || platform.MODEL_VERSION_1;
|
|
607
|
+
const supportsAccel = platform.supportsAccel(modelVersion);
|
|
608
|
+
if (!supportsAccel) {
|
|
609
|
+
return throwError(() => errors.metricNotSupportedByModel(metric, modelVersion));
|
|
610
|
+
}
|
|
611
|
+
return this._withStreamingModeObservable({
|
|
612
|
+
wifi: () => getCloudMetric(this._getCloudMetricDependencies(), {
|
|
613
|
+
metric,
|
|
614
|
+
labels: getLabels(metric),
|
|
615
|
+
atomic: true
|
|
616
|
+
}),
|
|
617
|
+
bluetooth: () => this.bluetoothClient.accelerometer()
|
|
618
|
+
});
|
|
619
|
+
}));
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
623
|
+
*
|
|
624
|
+
* The `raw` brainwaves parameter emits epochs of 16 samples for Crown and 25 for Notion 1 and 2.
|
|
625
|
+
*
|
|
626
|
+
* Example
|
|
627
|
+
* ```typescript
|
|
628
|
+
* neurosity.brainwaves("raw").subscribe(brainwaves => {
|
|
629
|
+
* console.log(brainwaves);
|
|
630
|
+
* });
|
|
631
|
+
* ```
|
|
632
|
+
*
|
|
633
|
+
* Raw Unfiltered - The `rawUnfiltered` brainwaves parameter emits epochs of 16 samples for Crown and 25 for Notion 1 and 2.
|
|
634
|
+
|
|
635
|
+
* Example
|
|
636
|
+
* ```typescript
|
|
637
|
+
* neurosity.brainwaves("rawUnfiltered").subscribe(brainwaves => {
|
|
638
|
+
* console.log(brainwaves);
|
|
639
|
+
* });
|
|
640
|
+
* ```
|
|
641
|
+
*
|
|
642
|
+
* Power By Band - The `powerByBand` brainwaves parameter emits epochs 4 times a second. Every frequency label (e.g. beta) contains an average power value per channel.
|
|
643
|
+
*
|
|
644
|
+
* Example
|
|
645
|
+
* ```typescript
|
|
646
|
+
* neurosity.brainwaves("powerByBand").subscribe(brainwaves => {
|
|
647
|
+
* console.log(brainwaves);
|
|
648
|
+
* });
|
|
649
|
+
* ```
|
|
650
|
+
*
|
|
651
|
+
* Power Spectral Density (PSD) - The `psd` brainwaves parameter emits epochs 4 times a second. Every frequency label (e.g. alpha) contains the computed FFT (Fast Fourier transform) value per channel (see the `psd` property), as well as the frequency ranges (see the `freqs` property).
|
|
652
|
+
*
|
|
653
|
+
* Example
|
|
654
|
+
* ```typescript
|
|
655
|
+
* neurosity.brainwaves("psd").subscribe(brainwaves => {
|
|
656
|
+
* console.log(brainwaves);
|
|
657
|
+
* });
|
|
658
|
+
* ```
|
|
659
|
+
*
|
|
660
|
+
* @param label Name of metric properties to filter by
|
|
661
|
+
* @returns Observable of brainwaves metric events
|
|
662
|
+
*/
|
|
663
|
+
brainwaves(label) {
|
|
664
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "brainwaves");
|
|
665
|
+
if (hasOAuthError) {
|
|
666
|
+
return throwError(() => OAuthError);
|
|
667
|
+
}
|
|
668
|
+
return this._withStreamingModeObservable({
|
|
669
|
+
wifi: () => getCloudMetric(this._getCloudMetricDependencies(), {
|
|
670
|
+
metric: "brainwaves",
|
|
671
|
+
labels: label ? [label] : [],
|
|
672
|
+
atomic: false
|
|
673
|
+
}),
|
|
674
|
+
// @TODO: doesn't support multiple labels, we should make the higher
|
|
675
|
+
// order function only support one label
|
|
676
|
+
bluetooth: () => this.bluetoothClient.brainwaves(label)
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
681
|
+
*
|
|
682
|
+
* Example
|
|
683
|
+
* ```typescript
|
|
684
|
+
* neurosity.calm().subscribe(calm => {
|
|
685
|
+
* console.log(calm.probability);
|
|
686
|
+
* });
|
|
687
|
+
*
|
|
688
|
+
* // 0.45
|
|
689
|
+
* // 0.47
|
|
690
|
+
* // 0.53
|
|
691
|
+
* // 0.51
|
|
692
|
+
* // ...
|
|
693
|
+
* ```
|
|
694
|
+
*
|
|
695
|
+
* @returns Observable of calm events - awareness/calm alias
|
|
696
|
+
*/
|
|
697
|
+
calm() {
|
|
698
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "calm");
|
|
699
|
+
if (hasOAuthError) {
|
|
700
|
+
return throwError(() => OAuthError);
|
|
701
|
+
}
|
|
702
|
+
return this._withStreamingModeObservable({
|
|
703
|
+
wifi: () => getCloudMetric(this._getCloudMetricDependencies(), {
|
|
704
|
+
metric: "awareness",
|
|
705
|
+
labels: ["calm"],
|
|
706
|
+
atomic: false
|
|
707
|
+
}),
|
|
708
|
+
bluetooth: () => this.bluetoothClient.calm()
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
713
|
+
*
|
|
714
|
+
* Observes signal quality data where each property is the name
|
|
715
|
+
* of the channel and the value includes the standard deviation and
|
|
716
|
+
* a status set by the device
|
|
717
|
+
*
|
|
718
|
+
* ```typescript
|
|
719
|
+
* neurosity.signalQuality().subscribe(signalQuality => {
|
|
720
|
+
* console.log(signalQuality);
|
|
721
|
+
* });
|
|
722
|
+
*
|
|
723
|
+
* // { FC6: { standardDeviation: 3.5, status: "good" }, C3: {...}, ... }
|
|
724
|
+
* ```
|
|
725
|
+
*
|
|
726
|
+
* @returns Observable of signalQuality metric events
|
|
727
|
+
*/
|
|
728
|
+
signalQuality() {
|
|
729
|
+
const metric = "signalQuality";
|
|
730
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, metric);
|
|
731
|
+
if (hasOAuthError) {
|
|
732
|
+
return throwError(() => OAuthError);
|
|
733
|
+
}
|
|
734
|
+
return this._withStreamingModeObservable({
|
|
735
|
+
wifi: () => getCloudMetric(this._getCloudMetricDependencies(), {
|
|
736
|
+
metric,
|
|
737
|
+
labels: getLabels(metric),
|
|
738
|
+
atomic: true
|
|
739
|
+
}),
|
|
740
|
+
bluetooth: () => this.bluetoothClient.signalQuality()
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* <StreamingModes wifi={true} />
|
|
745
|
+
*
|
|
746
|
+
* Observes last state of `settings` and all subsequent `settings` changes
|
|
747
|
+
*
|
|
748
|
+
* ```typescript
|
|
749
|
+
* neurosity.settings().subscribe(settings => {
|
|
750
|
+
* console.log(settings.lsl);
|
|
751
|
+
* });
|
|
752
|
+
*
|
|
753
|
+
* // true
|
|
754
|
+
* // ...
|
|
755
|
+
* ```
|
|
756
|
+
*
|
|
757
|
+
* @returns Observable of `settings` metric events
|
|
758
|
+
*/
|
|
759
|
+
settings() {
|
|
760
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "settings");
|
|
761
|
+
if (hasOAuthError) {
|
|
762
|
+
return throwError(() => OAuthError);
|
|
763
|
+
}
|
|
764
|
+
return this.cloudClient.observeNamespace("settings");
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
768
|
+
*
|
|
769
|
+
* Example
|
|
770
|
+
* ```typescript
|
|
771
|
+
* neurosity.focus().subscribe(focus => {
|
|
772
|
+
* console.log(focus.probability);
|
|
773
|
+
* });
|
|
774
|
+
*
|
|
775
|
+
* // 0.56
|
|
776
|
+
* // 0.46
|
|
777
|
+
* // 0.31
|
|
778
|
+
* // 0.39
|
|
779
|
+
* // ...
|
|
780
|
+
* ```
|
|
781
|
+
*
|
|
782
|
+
* @returns Observable of focus events - awareness/focus alias
|
|
783
|
+
*/
|
|
784
|
+
focus() {
|
|
785
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "focus");
|
|
786
|
+
if (hasOAuthError) {
|
|
787
|
+
return throwError(() => OAuthError);
|
|
788
|
+
}
|
|
789
|
+
return this._withStreamingModeObservable({
|
|
790
|
+
wifi: () => getCloudMetric(this._getCloudMetricDependencies(), {
|
|
791
|
+
metric: "awareness",
|
|
792
|
+
labels: ["focus"],
|
|
793
|
+
atomic: false
|
|
794
|
+
}),
|
|
795
|
+
bluetooth: () => this.bluetoothClient.focus()
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* <StreamingModes wifi={true} />
|
|
800
|
+
*
|
|
801
|
+
* @param label Name of metric properties to filter by
|
|
802
|
+
* @returns Observable of kinesis metric events
|
|
803
|
+
*/
|
|
804
|
+
kinesis(label) {
|
|
805
|
+
const metric = "kinesis";
|
|
806
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, metric);
|
|
807
|
+
if (hasOAuthError) {
|
|
808
|
+
return throwError(() => OAuthError);
|
|
809
|
+
}
|
|
810
|
+
return getCloudMetric(this._getCloudMetricDependencies(), {
|
|
811
|
+
metric,
|
|
812
|
+
labels: label ? [label] : [],
|
|
813
|
+
atomic: false
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* <StreamingModes wifi={true} />
|
|
818
|
+
*
|
|
819
|
+
* @param label Name of metric properties to filter by
|
|
820
|
+
* @returns Observable of predictions metric events
|
|
821
|
+
*/
|
|
822
|
+
predictions(label) {
|
|
823
|
+
const metric = "predictions";
|
|
824
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, metric);
|
|
825
|
+
if (hasOAuthError) {
|
|
826
|
+
return throwError(() => OAuthError);
|
|
827
|
+
}
|
|
828
|
+
return getCloudMetric(this._getCloudMetricDependencies(), {
|
|
829
|
+
metric,
|
|
830
|
+
labels: label ? [label] : [],
|
|
831
|
+
atomic: false
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* <StreamingModes wifi={true} bluetooth={true} />
|
|
836
|
+
*
|
|
837
|
+
* Observes last state of `status` and all subsequent `status` changes
|
|
838
|
+
*
|
|
839
|
+
* ```typescript
|
|
840
|
+
* neurosity.status().subscribe(status => {
|
|
841
|
+
* console.log(status.state);
|
|
842
|
+
* });
|
|
843
|
+
*
|
|
844
|
+
* // "online"
|
|
845
|
+
* // ...
|
|
846
|
+
* ```
|
|
847
|
+
*
|
|
848
|
+
* @returns Observable of `status` metric events
|
|
849
|
+
*/
|
|
850
|
+
status() {
|
|
851
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "status");
|
|
852
|
+
if (hasOAuthError) {
|
|
853
|
+
return throwError(() => OAuthError);
|
|
854
|
+
}
|
|
855
|
+
return this._withStreamingModeObservable({
|
|
856
|
+
wifi: () => this.cloudClient.status(),
|
|
857
|
+
bluetooth: () => this.bluetoothClient.status()
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* @internal
|
|
862
|
+
* Not user facing yet
|
|
863
|
+
*
|
|
864
|
+
* <StreamingModes wifi={true} />
|
|
865
|
+
*
|
|
866
|
+
* Changes device settings programmatically. These settings can be
|
|
867
|
+
* also changed from the developer console under device settings.
|
|
868
|
+
*
|
|
869
|
+
* Available settings [[ChangeSettings]]
|
|
870
|
+
*
|
|
871
|
+
* Example
|
|
872
|
+
* ```typescript
|
|
873
|
+
* neurosity.changeSettings({
|
|
874
|
+
* lsl: true
|
|
875
|
+
* });
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
changeSettings(settings) {
|
|
879
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
880
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
881
|
+
return Promise.reject(errors.mustSelectDevice);
|
|
882
|
+
}
|
|
883
|
+
const [hasOAuthError, OAuthError] = validateOAuthScopeForFunctionName(this.cloudClient.userClaims, "changeSettings");
|
|
884
|
+
if (hasOAuthError) {
|
|
885
|
+
return Promise.reject(OAuthError);
|
|
886
|
+
}
|
|
887
|
+
return yield this.cloudClient.changeSettings(settings);
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* <StreamingModes wifi={true} />
|
|
892
|
+
*
|
|
893
|
+
* ```typescript
|
|
894
|
+
* neurosity.training.record({
|
|
895
|
+
* metric: "kinesis",
|
|
896
|
+
* label: "push"
|
|
897
|
+
* });
|
|
898
|
+
*
|
|
899
|
+
* neurosity.training.stop({
|
|
900
|
+
* metric: "kinesis",
|
|
901
|
+
* label: "push"
|
|
902
|
+
* });
|
|
903
|
+
* ```
|
|
904
|
+
*
|
|
905
|
+
* @returns Training methods
|
|
906
|
+
*/
|
|
907
|
+
get training() {
|
|
908
|
+
return {
|
|
909
|
+
/**
|
|
910
|
+
* <StreamingModes wifi={true} />
|
|
911
|
+
*
|
|
912
|
+
* Records a training for a metric/label pair
|
|
913
|
+
* @category Training
|
|
914
|
+
*/
|
|
915
|
+
record: (training) => __awaiter(this, void 0, void 0, function* () {
|
|
916
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
917
|
+
throw errors.mustSelectDevice;
|
|
918
|
+
}
|
|
919
|
+
const userId = this.cloudClient.user && "uid" in this.cloudClient.user
|
|
920
|
+
? this.cloudClient.user.uid
|
|
921
|
+
: null;
|
|
922
|
+
const message = Object.assign(Object.assign({ fit: false, baseline: false, timestamp: this.cloudClient.timestamp }, training), { userId });
|
|
923
|
+
yield this.cloudClient.actions.dispatch({
|
|
924
|
+
command: "training",
|
|
925
|
+
action: "record",
|
|
926
|
+
message
|
|
927
|
+
});
|
|
928
|
+
}),
|
|
929
|
+
/**
|
|
930
|
+
* <StreamingModes wifi={true} />
|
|
931
|
+
*
|
|
932
|
+
* Stops the training for a metric/label pair
|
|
933
|
+
* @category Training
|
|
934
|
+
*/
|
|
935
|
+
stop: (training) => __awaiter(this, void 0, void 0, function* () {
|
|
936
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
937
|
+
throw errors.mustSelectDevice;
|
|
938
|
+
}
|
|
939
|
+
yield this.cloudClient.actions.dispatch({
|
|
940
|
+
command: "training",
|
|
941
|
+
action: "stop",
|
|
942
|
+
message: Object.assign({}, training)
|
|
943
|
+
});
|
|
944
|
+
}),
|
|
945
|
+
/**
|
|
946
|
+
* <StreamingModes wifi={true} />
|
|
947
|
+
*
|
|
948
|
+
* Stops all trainings
|
|
949
|
+
* @category Training
|
|
950
|
+
*/
|
|
951
|
+
stopAll: () => __awaiter(this, void 0, void 0, function* () {
|
|
952
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
953
|
+
throw errors.mustSelectDevice;
|
|
954
|
+
}
|
|
955
|
+
yield this.cloudClient.actions.dispatch({
|
|
956
|
+
command: "training",
|
|
957
|
+
action: "stopAll",
|
|
958
|
+
message: {}
|
|
959
|
+
});
|
|
960
|
+
})
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* @internal
|
|
965
|
+
* Proof of Concept for disconnecting db
|
|
966
|
+
*/
|
|
967
|
+
goOffline() {
|
|
968
|
+
this.cloudClient.goOffline();
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* @internal
|
|
972
|
+
* Proof of Concept for resuming db connection
|
|
973
|
+
*/
|
|
974
|
+
goOnline() {
|
|
975
|
+
this.cloudClient.goOnline();
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* @internal
|
|
979
|
+
* Not user facing yet
|
|
980
|
+
*
|
|
981
|
+
* Creates user account and automatically signs in with same credentials
|
|
982
|
+
*
|
|
983
|
+
* @param emailAndPasswordObject
|
|
984
|
+
* @returns user credential
|
|
985
|
+
*/
|
|
986
|
+
createAccount(credentials) {
|
|
987
|
+
return this.cloudClient.createAccount(credentials);
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* @internal
|
|
991
|
+
* Not user facing yet
|
|
992
|
+
*
|
|
993
|
+
* Removes all devices from an account and then deletes the account
|
|
994
|
+
*/
|
|
995
|
+
deleteAccount() {
|
|
996
|
+
return this.cloudClient.deleteAccount();
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* @internal
|
|
1000
|
+
* Not user facing
|
|
1001
|
+
*
|
|
1002
|
+
* Creates token (JWT) designed to authenticate and authorize Bluetooth clients/centrals.
|
|
1003
|
+
*
|
|
1004
|
+
* @returns token
|
|
1005
|
+
*/
|
|
1006
|
+
createBluetoothToken() {
|
|
1007
|
+
return this.cloudClient.createBluetoothToken();
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* @internal
|
|
1011
|
+
* Not user facing yet
|
|
1012
|
+
*
|
|
1013
|
+
* Creates custom token (JWT) to use to login with `{ customToken }`.
|
|
1014
|
+
*
|
|
1015
|
+
* @returns custom token
|
|
1016
|
+
*/
|
|
1017
|
+
createCustomToken() {
|
|
1018
|
+
return this.cloudClient.createCustomToken();
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* @internal
|
|
1022
|
+
* Not user facing yet
|
|
1023
|
+
*
|
|
1024
|
+
* Gets the offset between the device's clock and the client's clock
|
|
1025
|
+
* Requires option.timesync to be true
|
|
1026
|
+
*
|
|
1027
|
+
* @returns timesyncOffset
|
|
1028
|
+
*/
|
|
1029
|
+
getTimesyncOffset() {
|
|
1030
|
+
if (!this.options.timesync) {
|
|
1031
|
+
console.warn(`getTimesyncOffset() requires options.timesync to be true.`);
|
|
1032
|
+
}
|
|
1033
|
+
return this.options.timesync ? this.cloudClient.getTimesyncOffset() : 0;
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Create OAuth URL
|
|
1037
|
+
* 💡 OAuth requires developers to register their apps with Neurosity
|
|
1038
|
+
* [Read full OAuth guide](/docs/oauth)
|
|
1039
|
+
*
|
|
1040
|
+
* Creates client-specific OAuth URL. This is the first step of the OAuth workflow. Use this function to create a URL you can use to redirect users to the Neurosity sign-in page.
|
|
1041
|
+
* 💡 This function is designed to only run on the server side for security reasons, as it requires your client secret.
|
|
1042
|
+
*
|
|
1043
|
+
* ```typescript
|
|
1044
|
+
* const { Neurosity } = require("@neurosity/sdk");
|
|
1045
|
+
*
|
|
1046
|
+
* const neurosity = new Neurosity({
|
|
1047
|
+
* autoSelectDevice: false
|
|
1048
|
+
* });
|
|
1049
|
+
*
|
|
1050
|
+
* exports.handler = async function (event) {
|
|
1051
|
+
* return neurosity
|
|
1052
|
+
* .createOAuthURL({
|
|
1053
|
+
* clientId: process.env.NEUROSITY_OAUTH_CLIENT_ID,
|
|
1054
|
+
* clientSecret: process.env.NEUROSITY_OAUTH_CLIENT_SECRET,
|
|
1055
|
+
* redirectUri: process.env.NEUROSITY_OAUTH_CLIENT_REDIRECT_URI,
|
|
1056
|
+
* responseType: "token",
|
|
1057
|
+
* state: Math.random().toString().split(".")[1],
|
|
1058
|
+
* scope: [
|
|
1059
|
+
* "read:devices-info",
|
|
1060
|
+
* "read:devices-status",
|
|
1061
|
+
* "read:signal-quality",
|
|
1062
|
+
* "read:brainwaves"
|
|
1063
|
+
* ]
|
|
1064
|
+
* })
|
|
1065
|
+
* .then((url) => ({
|
|
1066
|
+
* statusCode: 200,
|
|
1067
|
+
* body: JSON.stringify({ url })
|
|
1068
|
+
* }))
|
|
1069
|
+
* .catch((error) => ({
|
|
1070
|
+
* statusCode: 400,
|
|
1071
|
+
* body: JSON.stringify(error.response.data)
|
|
1072
|
+
* }));
|
|
1073
|
+
* };
|
|
1074
|
+
* ```
|
|
1075
|
+
* @returns custom token
|
|
1076
|
+
*/
|
|
1077
|
+
createOAuthURL(config) {
|
|
1078
|
+
if (!isNode) {
|
|
1079
|
+
return Promise.reject(new Error(`${errors.prefix}the createOAuthURL method must be used on the server side (node.js) for security reasons.`));
|
|
1080
|
+
}
|
|
1081
|
+
return createOAuthURL(config, this.options);
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Get OAuth Token
|
|
1085
|
+
* 💡 OAuth requires developers to register their apps with Neurosity
|
|
1086
|
+
* [Read full OAuth guide](/docs/oauth)
|
|
1087
|
+
*
|
|
1088
|
+
* Gets client-specific OAuth token for a given userId.
|
|
1089
|
+
*
|
|
1090
|
+
* 💡 This function is designed to only run on the server side for security reasons, as it requires your client secret.
|
|
1091
|
+
* Here's an example of a cloud function that receives a `userId` via query params and loads the client id and client secret securely via environment variables.
|
|
1092
|
+
*
|
|
1093
|
+
*
|
|
1094
|
+
* ```typescript
|
|
1095
|
+
* const { Neurosity } = require("@neurosity/sdk");
|
|
1096
|
+
*
|
|
1097
|
+
* const neurosity = new Neurosity({
|
|
1098
|
+
* autoSelectDevice: false
|
|
1099
|
+
* });
|
|
1100
|
+
*
|
|
1101
|
+
* exports.handler = async function (event) {
|
|
1102
|
+
* const userId = event.queryStringParameters?.userId;
|
|
1103
|
+
*
|
|
1104
|
+
* return neurosity
|
|
1105
|
+
* .getOAuthToken({
|
|
1106
|
+
* clientId: process.env.NEUROSITY_OAUTH_CLIENT_ID,
|
|
1107
|
+
* clientSecret: process.env.NEUROSITY_OAUTH_CLIENT_SECRET,
|
|
1108
|
+
* userId
|
|
1109
|
+
* })
|
|
1110
|
+
* .then((token) => ({
|
|
1111
|
+
* statusCode: 200,
|
|
1112
|
+
* body: JSON.stringify(token)
|
|
1113
|
+
* }))
|
|
1114
|
+
* .catch((error) => ({
|
|
1115
|
+
* statusCode: 200,
|
|
1116
|
+
* body: JSON.stringify(error.response.data)
|
|
1117
|
+
* }));
|
|
1118
|
+
* };
|
|
1119
|
+
* ```
|
|
1120
|
+
* @returns custom token
|
|
1121
|
+
*/
|
|
1122
|
+
getOAuthToken(query) {
|
|
1123
|
+
if (!isNode) {
|
|
1124
|
+
return Promise.reject(new Error(`${errors.prefix}the getOAuthToken method must be used on the server side (node.js) for security reasons.`));
|
|
1125
|
+
}
|
|
1126
|
+
return getOAuthToken(query, this.options);
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Remove OAuth Access
|
|
1130
|
+
* 💡 OAuth requires developers to register their apps with Neurosity
|
|
1131
|
+
* [Read full OAuth guide](/docs/oauth)
|
|
1132
|
+
*
|
|
1133
|
+
* Removes client-specific OAuth token for a given userId. Requires SDK to be signed in with OAuth custom token.
|
|
1134
|
+
*
|
|
1135
|
+
* ```typescript
|
|
1136
|
+
* await neurosity.removeOAuthAccess().catch((error) => {
|
|
1137
|
+
* // handle error here...
|
|
1138
|
+
* });
|
|
1139
|
+
* ```
|
|
1140
|
+
* @returns custom token
|
|
1141
|
+
*/
|
|
1142
|
+
removeOAuthAccess() {
|
|
1143
|
+
return this.cloudClient.removeOAuthAccess();
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* @internal
|
|
1147
|
+
* Proof of Concept for Skills - Not user facing yet
|
|
1148
|
+
*
|
|
1149
|
+
* Accesses a skill by Bundle ID. Additionally, allows to observe
|
|
1150
|
+
* and push skill metrics
|
|
1151
|
+
*
|
|
1152
|
+
* @param bundleId Bundle ID of skill
|
|
1153
|
+
* @returns Skill instance
|
|
1154
|
+
*/
|
|
1155
|
+
skill(bundleId) {
|
|
1156
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1157
|
+
if (!(yield this.cloudClient.didSelectDevice())) {
|
|
1158
|
+
return Promise.reject(errors.mustSelectDevice);
|
|
1159
|
+
}
|
|
1160
|
+
const skillData = yield this.cloudClient.skills.get(bundleId);
|
|
1161
|
+
if (skillData === null) {
|
|
1162
|
+
return Promise.reject(new Error(`${errors.prefix}Access denied for: ${bundleId}. Make sure the skill is installed.`));
|
|
1163
|
+
}
|
|
1164
|
+
return {
|
|
1165
|
+
metric: (label) => {
|
|
1166
|
+
const metricName = `skill~${skillData.id}~${label}`;
|
|
1167
|
+
const subscription = new Observable((observer) => {
|
|
1168
|
+
const subscription = this.cloudClient.metrics.subscribe({
|
|
1169
|
+
metric: metricName,
|
|
1170
|
+
labels: [label],
|
|
1171
|
+
atomic: true
|
|
1172
|
+
});
|
|
1173
|
+
const listener = this.cloudClient.metrics.on(subscription, (...data) => {
|
|
1174
|
+
observer.next(...data);
|
|
1175
|
+
});
|
|
1176
|
+
return () => {
|
|
1177
|
+
this.cloudClient.metrics.unsubscribe(subscription, listener);
|
|
1178
|
+
};
|
|
1179
|
+
}).pipe(map((metric) => metric[label]));
|
|
1180
|
+
Object.defineProperty(subscription, "next", {
|
|
1181
|
+
value: (metricValue) => {
|
|
1182
|
+
this.cloudClient.metrics.next(metricName, {
|
|
1183
|
+
[label]: metricValue
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
return subscription;
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* <StreamingModes wifi={true} />
|
|
1194
|
+
*
|
|
1195
|
+
* Observes and returns a list of all Kinesis `experiments` and all subsequent experiment changes.
|
|
1196
|
+
* Here's an example of how to get a list of all Kinesis labels that have been trained:
|
|
1197
|
+
*
|
|
1198
|
+
* ```typescript
|
|
1199
|
+
*
|
|
1200
|
+
* const getUniqueLabels = (experiments) => {
|
|
1201
|
+
* const labels = experiments.flatMap((experiment) => experiment.labels);
|
|
1202
|
+
* // only return unique labels
|
|
1203
|
+
* return [...new Set(labels)];
|
|
1204
|
+
* }
|
|
1205
|
+
*
|
|
1206
|
+
* neurosity.onUserExperiments().subscribe((experiments) => {
|
|
1207
|
+
* console.log(experiments);
|
|
1208
|
+
* console.log("labels", getUniqueLabels(experiments));
|
|
1209
|
+
* });
|
|
1210
|
+
*
|
|
1211
|
+
* // [{ id: '...', deviceId: '...', labels: [ 'drop' ], name: 'Lightgray cheetah', timestamp: 1577908381552, totalTrials: 16, userId: '...' }]
|
|
1212
|
+
* // ["drop", "lift", "push"]
|
|
1213
|
+
* ```
|
|
1214
|
+
*
|
|
1215
|
+
* @returns Observable of `experiments` events
|
|
1216
|
+
*/
|
|
1217
|
+
onUserExperiments() {
|
|
1218
|
+
return this.cloudClient.onUserExperiments();
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* <StreamingModes wifi={true} />
|
|
1222
|
+
*
|
|
1223
|
+
* Deletes a specific experiment provided an experiment ID
|
|
1224
|
+
*
|
|
1225
|
+
* ```typescript
|
|
1226
|
+
* await neurosity.deleteUserExperiment(experiment.id);
|
|
1227
|
+
* ```
|
|
1228
|
+
*
|
|
1229
|
+
* @param experimentId The ID of the Experiment
|
|
1230
|
+
* @returns void
|
|
1231
|
+
*/
|
|
1232
|
+
deleteUserExperiment(experimentId) {
|
|
1233
|
+
return this.cloudClient.deleteUserExperiment(experimentId);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
*
|
|
1238
|
+
* @hidden
|
|
1239
|
+
*/
|
|
1240
|
+
Neurosity.credentialWithLink = credentialWithLink;
|
|
1241
|
+
/**
|
|
1242
|
+
*
|
|
1243
|
+
* @hidden
|
|
1244
|
+
*/
|
|
1245
|
+
Neurosity.createUser = createUser;
|
|
1246
|
+
/**
|
|
1247
|
+
*
|
|
1248
|
+
* @hidden
|
|
1249
|
+
*/
|
|
1250
|
+
Neurosity.SERVER_TIMESTAMP = SERVER_TIMESTAMP;
|
|
1251
|
+
/**
|
|
1252
|
+
* @hidden
|
|
1253
|
+
* Deprecated class kept for backwards compatibility purposes.
|
|
1254
|
+
*/
|
|
1255
|
+
export class Notion extends Neurosity {
|
|
1256
|
+
constructor(options = {}) {
|
|
1257
|
+
super(options);
|
|
1258
|
+
console.log(`The Notion class is deprecated and will be removed in the next version of the SDK. Please use the Neurosity class instead. e.g. new Notion() => new Neurosity()`);
|
|
1259
|
+
}
|
|
1260
|
+
}
|