@neurosity/sdk 6.3.0 → 6.4.0-next.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.
- package/dist/browser/neurosity.iife.js +1550 -1536
- package/dist/browser/neurosity.js +15 -15
- package/dist/browser/neurosity.js.map +1 -1
- package/dist/cjs/Neurosity.d.ts +5 -0
- package/dist/cjs/Neurosity.js +20 -6
- package/dist/cjs/api/bluetooth/BluetoothClient.d.ts +2 -0
- package/dist/cjs/api/bluetooth/BluetoothClient.js +35 -30
- package/dist/cjs/api/bluetooth/BluetoothTransport.d.ts +2 -2
- package/dist/cjs/api/bluetooth/react-native/ReactNativeTransport.d.ts +2 -3
- package/dist/cjs/api/bluetooth/react-native/ReactNativeTransport.js +37 -45
- package/dist/cjs/api/bluetooth/utils/osHasBluetoothSupport.d.ts +2 -2
- package/dist/cjs/api/bluetooth/utils/osHasBluetoothSupport.js +4 -2
- package/dist/cjs/api/bluetooth/web/WebBluetoothTransport.d.ts +2 -3
- package/dist/cjs/api/bluetooth/web/WebBluetoothTransport.js +35 -41
- package/dist/cjs/api/index.d.ts +3 -1
- package/dist/cjs/api/index.js +4 -0
- package/dist/electron/index.js +10 -10
- package/dist/electron/index.js.map +1 -1
- package/dist/esm/Neurosity.d.ts +5 -0
- package/dist/esm/Neurosity.js +20 -6
- package/dist/esm/api/bluetooth/BluetoothClient.d.ts +2 -0
- package/dist/esm/api/bluetooth/BluetoothClient.js +36 -31
- package/dist/esm/api/bluetooth/BluetoothTransport.d.ts +2 -2
- package/dist/esm/api/bluetooth/react-native/ReactNativeTransport.d.ts +2 -3
- package/dist/esm/api/bluetooth/react-native/ReactNativeTransport.js +33 -41
- package/dist/esm/api/bluetooth/utils/osHasBluetoothSupport.d.ts +2 -2
- package/dist/esm/api/bluetooth/utils/osHasBluetoothSupport.js +4 -2
- package/dist/esm/api/bluetooth/web/WebBluetoothTransport.d.ts +2 -3
- package/dist/esm/api/bluetooth/web/WebBluetoothTransport.js +33 -39
- package/dist/esm/api/index.d.ts +3 -1
- package/dist/esm/api/index.js +4 -0
- package/dist/esm/neurosity.mjs +1550 -1536
- package/dist/examples/neurosity.iife.js +1550 -1536
- package/dist/examples/neurosity.js +15 -15
- package/dist/examples/neurosity.mjs +1550 -1536
- package/package.json +1 -1
package/dist/esm/Neurosity.d.ts
CHANGED
|
@@ -80,6 +80,11 @@ export declare class Neurosity {
|
|
|
80
80
|
* @hidden
|
|
81
81
|
*/
|
|
82
82
|
_initStreamingMode(streamingMode: STREAMING_MODE, hasBluetoothTransport: boolean): void;
|
|
83
|
+
/**
|
|
84
|
+
*
|
|
85
|
+
* @hidden
|
|
86
|
+
*/
|
|
87
|
+
_osHasBluetoothSupport(): Observable<any>;
|
|
83
88
|
/**
|
|
84
89
|
* Subscribe to the device's streaming state changes and the current strategy
|
|
85
90
|
*
|
package/dist/esm/Neurosity.js
CHANGED
|
@@ -9,7 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { combineLatest, of, throwError } from "rxjs";
|
|
11
11
|
import { ReplaySubject, firstValueFrom, EMPTY } from "rxjs";
|
|
12
|
-
import {
|
|
12
|
+
import { map, startWith, switchMap } from "rxjs/operators";
|
|
13
|
+
import { distinctUntilChanged } from "rxjs/operators";
|
|
13
14
|
import isEqual from "fast-deep-equal";
|
|
14
15
|
import { CloudClient, createUser } from "./api/index";
|
|
15
16
|
import { credentialWithLink, SERVER_TIMESTAMP } from "./api/index";
|
|
@@ -70,6 +71,7 @@ export class Neurosity {
|
|
|
70
71
|
if (!!bluetoothTransport) {
|
|
71
72
|
this.bluetoothClient = new BluetoothClient({
|
|
72
73
|
selectedDevice$: this.onDeviceChange(),
|
|
74
|
+
osHasBluetoothSupport$: this._osHasBluetoothSupport(),
|
|
73
75
|
createBluetoothToken: this.createBluetoothToken.bind(this),
|
|
74
76
|
transport: bluetoothTransport
|
|
75
77
|
});
|
|
@@ -100,6 +102,16 @@ export class Neurosity {
|
|
|
100
102
|
this.streamingMode$.next(streamingMode);
|
|
101
103
|
}
|
|
102
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* @hidden
|
|
108
|
+
*/
|
|
109
|
+
_osHasBluetoothSupport() {
|
|
110
|
+
return combineLatest({
|
|
111
|
+
selectedDevice: this.onDeviceChange(),
|
|
112
|
+
osVersion: this.osVersion().pipe(startWith(null))
|
|
113
|
+
}).pipe(map(({ selectedDevice, osVersion }) => osHasBluetoothSupport(selectedDevice, osVersion)));
|
|
114
|
+
}
|
|
103
115
|
/**
|
|
104
116
|
* Subscribe to the device's streaming state changes and the current strategy
|
|
105
117
|
*
|
|
@@ -115,12 +127,14 @@ export class Neurosity {
|
|
|
115
127
|
streamingState() {
|
|
116
128
|
const isWifiOnline = (state) => [STATUS.ONLINE, STATUS.UPDATING].includes(state);
|
|
117
129
|
return this.streamingMode$.pipe(switchMap((streamingMode) => {
|
|
118
|
-
return
|
|
119
|
-
|
|
130
|
+
return combineLatest({
|
|
131
|
+
selectedDevice: this.onDeviceChange(),
|
|
132
|
+
osHasBluetoothSupport: this._osHasBluetoothSupport()
|
|
133
|
+
}).pipe(switchMap(({ selectedDevice, osHasBluetoothSupport }) => {
|
|
134
|
+
if (!selectedDevice) {
|
|
120
135
|
return EMPTY;
|
|
121
136
|
}
|
|
122
|
-
const isUnableToUseBluetooth = this.isMissingBluetoothTransport ||
|
|
123
|
-
!osHasBluetoothSupport(selectDevice);
|
|
137
|
+
const isUnableToUseBluetooth = this.isMissingBluetoothTransport || !osHasBluetoothSupport;
|
|
124
138
|
if (isUnableToUseBluetooth) {
|
|
125
139
|
return this.cloudClient.status().pipe(map(({ state }) => ({
|
|
126
140
|
connected: isWifiOnline(state),
|
|
@@ -786,7 +800,7 @@ export class Neurosity {
|
|
|
786
800
|
if (hasOAuthError) {
|
|
787
801
|
return throwError(() => OAuthError);
|
|
788
802
|
}
|
|
789
|
-
return this.cloudClient.
|
|
803
|
+
return this.cloudClient.osVersion();
|
|
790
804
|
}
|
|
791
805
|
/**
|
|
792
806
|
* <StreamingModes wifi={true} bluetooth={true} />
|
|
@@ -16,12 +16,14 @@ declare type CreateBluetoothToken = () => Promise<string>;
|
|
|
16
16
|
declare type Options = {
|
|
17
17
|
transport: BluetoothTransport;
|
|
18
18
|
selectedDevice$: Observable<DeviceInfo>;
|
|
19
|
+
osHasBluetoothSupport$: Observable<boolean>;
|
|
19
20
|
createBluetoothToken: CreateBluetoothToken;
|
|
20
21
|
};
|
|
21
22
|
export declare class BluetoothClient {
|
|
22
23
|
transport: BluetoothTransport;
|
|
23
24
|
deviceInfo: DeviceInfo;
|
|
24
25
|
selectedDevice$: ReplaySubject<DeviceInfo>;
|
|
26
|
+
osHasBluetoothSupport$: ReplaySubject<boolean>;
|
|
25
27
|
isAuthenticated$: ReplaySubject<boolean>;
|
|
26
28
|
_focus$: Observable<any>;
|
|
27
29
|
_calm$: Observable<any>;
|
|
@@ -7,20 +7,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { defer,
|
|
11
|
-
import { ReplaySubject, EMPTY } from "rxjs";
|
|
12
|
-
import { switchMap, share, tap } from "rxjs/operators";
|
|
13
|
-
import { distinctUntilChanged } from "rxjs/operators";
|
|
10
|
+
import { defer, timer } from "rxjs";
|
|
11
|
+
import { ReplaySubject, firstValueFrom, EMPTY } from "rxjs";
|
|
12
|
+
import { switchMap, share, tap, distinctUntilChanged } from "rxjs/operators";
|
|
14
13
|
import { WebBluetoothTransport } from "./web/WebBluetoothTransport";
|
|
15
14
|
import { ReactNativeTransport } from "./react-native/ReactNativeTransport";
|
|
16
15
|
import { csvBufferToEpoch } from "./utils/csvBufferToEpoch";
|
|
17
16
|
import { BLUETOOTH_CONNECTION } from "./types";
|
|
18
|
-
import { osHasBluetoothSupport } from "./utils/osHasBluetoothSupport";
|
|
19
17
|
export class BluetoothClient {
|
|
20
18
|
constructor(options) {
|
|
21
19
|
this.selectedDevice$ = new ReplaySubject(1);
|
|
20
|
+
this.osHasBluetoothSupport$ = new ReplaySubject(1);
|
|
22
21
|
this.isAuthenticated$ = new ReplaySubject(1);
|
|
23
|
-
const { transport, selectedDevice$, createBluetoothToken } = options !== null && options !== void 0 ? options : {};
|
|
22
|
+
const { transport, selectedDevice$, osHasBluetoothSupport$, createBluetoothToken } = options !== null && options !== void 0 ? options : {};
|
|
24
23
|
if (!transport) {
|
|
25
24
|
throw new Error(`No bluetooth transport provided.`);
|
|
26
25
|
}
|
|
@@ -29,8 +28,15 @@ export class BluetoothClient {
|
|
|
29
28
|
if (selectedDevice$) {
|
|
30
29
|
selectedDevice$.subscribe(this.selectedDevice$);
|
|
31
30
|
}
|
|
32
|
-
//
|
|
33
|
-
|
|
31
|
+
// Pass events to the internal osHasBluetoothSupport$ if osHasBluetoothSupport$ is passed via options
|
|
32
|
+
if (osHasBluetoothSupport$) {
|
|
33
|
+
osHasBluetoothSupport$.subscribe(this.osHasBluetoothSupport$);
|
|
34
|
+
}
|
|
35
|
+
this.osHasBluetoothSupport$
|
|
36
|
+
.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport
|
|
37
|
+
? this.transport._autoConnect(this.selectedDevice$)
|
|
38
|
+
: EMPTY))
|
|
39
|
+
.subscribe({
|
|
34
40
|
error: (error) => {
|
|
35
41
|
var _a;
|
|
36
42
|
this.transport.addLog(`Auto connect: error -> ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
@@ -45,7 +51,11 @@ export class BluetoothClient {
|
|
|
45
51
|
this.transport.addLog("Auto authentication not enabled");
|
|
46
52
|
}
|
|
47
53
|
// Auto manage action notifications
|
|
48
|
-
this.
|
|
54
|
+
this.osHasBluetoothSupport$
|
|
55
|
+
.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport
|
|
56
|
+
? this.transport._autoToggleActionNotifications()
|
|
57
|
+
: EMPTY))
|
|
58
|
+
.subscribe();
|
|
49
59
|
// Multicast metrics (share)
|
|
50
60
|
this._focus$ = this._subscribeWhileAuthenticated("focus");
|
|
51
61
|
this._calm$ = this._subscribeWhileAuthenticated("calm");
|
|
@@ -69,27 +79,24 @@ export class BluetoothClient {
|
|
|
69
79
|
const reauthenticateInterval$ = timer(0, REAUTHENTICATE_INTERVAL).pipe(tap(() => {
|
|
70
80
|
this.transport.addLog(`Auto authentication in progress...`);
|
|
71
81
|
}));
|
|
72
|
-
return this.
|
|
73
|
-
?
|
|
74
|
-
: this
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
})))));
|
|
82
|
+
return this.osHasBluetoothSupport$.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport ? this.connection() : EMPTY), switchMap((connection) => connection === BLUETOOTH_CONNECTION.CONNECTED
|
|
83
|
+
? reauthenticateInterval$
|
|
84
|
+
: EMPTY), switchMap(() => __awaiter(this, void 0, void 0, function* () { return yield this.isAuthenticated(); })), tap(([isAuthenticated]) => __awaiter(this, void 0, void 0, function* () {
|
|
85
|
+
if (!isAuthenticated) {
|
|
86
|
+
const token = yield createBluetoothToken();
|
|
87
|
+
yield this.authenticate(token);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
this.transport.addLog(`Already authenticated`);
|
|
91
|
+
}
|
|
92
|
+
})));
|
|
85
93
|
}
|
|
86
94
|
enableAutoConnect(autoConnect) {
|
|
87
95
|
this.transport.enableAutoConnect(autoConnect);
|
|
88
96
|
}
|
|
89
97
|
_hasBluetoothSupport() {
|
|
90
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
|
|
92
|
-
return osHasBluetoothSupport(selectedDevice);
|
|
99
|
+
return yield firstValueFrom(this.osHasBluetoothSupport$);
|
|
93
100
|
});
|
|
94
101
|
}
|
|
95
102
|
authenticate(token) {
|
|
@@ -170,13 +177,11 @@ export class BluetoothClient {
|
|
|
170
177
|
});
|
|
171
178
|
}
|
|
172
179
|
_subscribeWhileAuthenticated(characteristicName) {
|
|
173
|
-
return this.
|
|
174
|
-
?
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
})
|
|
179
|
-
: EMPTY))), share());
|
|
180
|
+
return this.osHasBluetoothSupport$.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport ? this.isAuthenticated$ : EMPTY), distinctUntilChanged(), switchMap((isAuthenticated) => isAuthenticated
|
|
181
|
+
? this.transport.subscribeToCharacteristic({
|
|
182
|
+
characteristicName
|
|
183
|
+
})
|
|
184
|
+
: EMPTY), share());
|
|
180
185
|
}
|
|
181
186
|
focus() {
|
|
182
187
|
return this._focus$;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Observable, Subject } from "rxjs";
|
|
2
2
|
import { BLUETOOTH_CONNECTION, TRANSPORT_TYPE } from "./types";
|
|
3
3
|
import { Action } from "../../types/actions";
|
|
4
|
-
import { DeviceInfo } from "../../types/deviceInfo";
|
|
4
|
+
import { DeviceInfo, OSVersion } from "../../types/deviceInfo";
|
|
5
5
|
import { Peripheral } from "./react-native/types/BleManagerTypes";
|
|
6
6
|
export declare type DeviceNicknameOrPeripheral = string | Peripheral;
|
|
7
7
|
/**
|
|
@@ -10,7 +10,7 @@ export declare type DeviceNicknameOrPeripheral = string | Peripheral;
|
|
|
10
10
|
export interface BluetoothTransport {
|
|
11
11
|
type: TRANSPORT_TYPE;
|
|
12
12
|
connect(deviceNicknameORPeripheral?: DeviceNicknameOrPeripheral): Promise<void>;
|
|
13
|
-
_autoConnect(selectedDevice$: Observable<DeviceInfo>): Observable<void>;
|
|
13
|
+
_autoConnect(selectedDevice$: Observable<DeviceInfo>, osVersion: Observable<OSVersion>): Observable<void>;
|
|
14
14
|
disconnect(): Promise<void>;
|
|
15
15
|
connection(): Observable<BLUETOOTH_CONNECTION>;
|
|
16
16
|
requestDevice?(): any;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { BehaviorSubject, ReplaySubject } from "rxjs";
|
|
2
|
-
import { Observable } from "rxjs";
|
|
1
|
+
import { Observable, BehaviorSubject, ReplaySubject } from "rxjs";
|
|
3
2
|
import { BluetoothTransport } from "../BluetoothTransport";
|
|
4
3
|
import { ActionOptions, SubscribeOptions } from "../types";
|
|
5
4
|
import { TRANSPORT_TYPE, BLUETOOTH_CONNECTION } from "../types";
|
|
@@ -65,7 +64,7 @@ export declare class ReactNativeTransport implements BluetoothTransport {
|
|
|
65
64
|
writeCharacteristic(characteristicName: string, data: string): Promise<void>;
|
|
66
65
|
_addPendingAction(actionId: number): void;
|
|
67
66
|
_removePendingAction(actionId: number): void;
|
|
68
|
-
_autoToggleActionNotifications(
|
|
67
|
+
_autoToggleActionNotifications(): Observable<any>;
|
|
69
68
|
dispatchAction({ characteristicName, action }: ActionOptions): Promise<any>;
|
|
70
69
|
}
|
|
71
70
|
export {};
|
|
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { BLUETOOTH_PRIMARY_SERVICE_UUID_STRING } from "@neurosity/ipk";
|
|
11
11
|
import { BLUETOOTH_CHUNK_DELIMITER } from "@neurosity/ipk";
|
|
12
12
|
import { BLUETOOTH_DEVICE_NAME_PREFIXES } from "@neurosity/ipk";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { Observable, BehaviorSubject, ReplaySubject, NEVER } from "rxjs";
|
|
14
|
+
import { defer, merge, of, timer, fromEventPattern } from "rxjs";
|
|
15
15
|
import { switchMap, map, filter, takeUntil, tap } from "rxjs/operators";
|
|
16
16
|
import { shareReplay, distinctUntilChanged, finalize } from "rxjs/operators";
|
|
17
17
|
import { take, share, scan, distinct } from "rxjs/operators";
|
|
@@ -23,7 +23,6 @@ import { DEFAULT_ACTION_RESPONSE_TIMEOUT } from "../constants";
|
|
|
23
23
|
import { CHARACTERISTIC_UUIDS_TO_NAMES } from "../constants";
|
|
24
24
|
import { ANDROID_MAX_MTU } from "../constants";
|
|
25
25
|
import { REACT_NATIVE_MAX_BYTE_SIZE } from "../constants";
|
|
26
|
-
import { osHasBluetoothSupport } from "../utils/osHasBluetoothSupport";
|
|
27
26
|
const defaultOptions = {
|
|
28
27
|
autoConnect: true
|
|
29
28
|
};
|
|
@@ -105,12 +104,10 @@ export class ReactNativeTransport {
|
|
|
105
104
|
const selectedDeviceAfterDisconnect$ = this.onDisconnected$.pipe(switchMap(() => selectedDevice$));
|
|
106
105
|
return this._isAutoConnectEnabled$.pipe(switchMap((isAutoConnectEnabled) => isAutoConnectEnabled
|
|
107
106
|
? merge(selectedDevice$, selectedDeviceAfterDisconnect$)
|
|
108
|
-
: NEVER), switchMap((selectedDevice) =>
|
|
109
|
-
?
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return peripheralMatch ? of(peripheralMatch) : NEVER;
|
|
113
|
-
}), distinct((peripheral) => peripheral.id), take(1))), switchMap((peripheral) => __awaiter(this, void 0, void 0, function* () {
|
|
107
|
+
: NEVER), switchMap((selectedDevice) => this.scan().pipe(switchMap((peripherals) => {
|
|
108
|
+
const peripheralMatch = peripherals.find((peripheral) => peripheral.name === (selectedDevice === null || selectedDevice === void 0 ? void 0 : selectedDevice.deviceNickname));
|
|
109
|
+
return peripheralMatch ? of(peripheralMatch) : NEVER;
|
|
110
|
+
}), distinct((peripheral) => peripheral.id), take(1))), switchMap((peripheral) => __awaiter(this, void 0, void 0, function* () {
|
|
114
111
|
return yield this.connect(peripheral);
|
|
115
112
|
})));
|
|
116
113
|
}
|
|
@@ -333,40 +330,35 @@ export class ReactNativeTransport {
|
|
|
333
330
|
const actions = this.pendingActions$.getValue();
|
|
334
331
|
this.pendingActions$.next(actions.filter((id) => id !== actionId));
|
|
335
332
|
}
|
|
336
|
-
_autoToggleActionNotifications(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.addLog(`Started notifications for [actions] characteristic`);
|
|
350
|
-
}
|
|
351
|
-
catch (error) {
|
|
352
|
-
this.addLog(`Attemped to start notifications for [actions] characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
353
|
-
}
|
|
333
|
+
_autoToggleActionNotifications() {
|
|
334
|
+
let started = false;
|
|
335
|
+
return this.connection$.asObservable().pipe(switchMap((connection) => connection === BLUETOOTH_CONNECTION.CONNECTED
|
|
336
|
+
? this.pendingActions$
|
|
337
|
+
: NEVER), tap((pendingActions) => __awaiter(this, void 0, void 0, function* () {
|
|
338
|
+
var _a, _b;
|
|
339
|
+
const { peripheralId, serviceUUID, characteristicUUID } = this.getCharacteristicByName("actions");
|
|
340
|
+
const hasPendingActions = !!pendingActions.length;
|
|
341
|
+
if (hasPendingActions && !started) {
|
|
342
|
+
started = true;
|
|
343
|
+
try {
|
|
344
|
+
yield this.BleManager.startNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
345
|
+
this.addLog(`Started notifications for [actions] characteristic`);
|
|
354
346
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
try {
|
|
358
|
-
yield this.BleManager.stopNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
359
|
-
this.addLog(`Stopped notifications for actions characteristic`);
|
|
360
|
-
}
|
|
361
|
-
catch (error) {
|
|
362
|
-
this.addLog(`Attemped to stop notifications for [actions] characteristic: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);
|
|
363
|
-
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
this.addLog(`Attemped to start notifications for [actions] characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
364
349
|
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
350
|
+
}
|
|
351
|
+
if (!hasPendingActions && started) {
|
|
352
|
+
started = false;
|
|
353
|
+
try {
|
|
354
|
+
yield this.BleManager.stopNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
355
|
+
this.addLog(`Stopped notifications for actions characteristic`);
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
this.addLog(`Attemped to stop notifications for [actions] characteristic: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
})));
|
|
370
362
|
}
|
|
371
363
|
dispatchAction({ characteristicName, action }) {
|
|
372
364
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { DeviceInfo } from "../../../types/deviceInfo";
|
|
2
|
-
export declare function osHasBluetoothSupport(selectedDevice: DeviceInfo): any;
|
|
1
|
+
import { DeviceInfo, OSVersion } from "../../../types/deviceInfo";
|
|
2
|
+
export declare function osHasBluetoothSupport(selectedDevice: DeviceInfo, osVersion?: OSVersion): any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import semverGte from "semver/functions/gte";
|
|
2
|
-
export function osHasBluetoothSupport(selectedDevice) {
|
|
2
|
+
export function osHasBluetoothSupport(selectedDevice, osVersion) {
|
|
3
3
|
if (!selectedDevice) {
|
|
4
4
|
return false;
|
|
5
5
|
}
|
|
@@ -12,5 +12,7 @@ export function osHasBluetoothSupport(selectedDevice) {
|
|
|
12
12
|
if (isEmulator) {
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
// `osVersion` is updated in real time,
|
|
16
|
+
// unlike accessing via `selectedDevice.osVersion`
|
|
17
|
+
return semverGte(osVersion !== null && osVersion !== void 0 ? osVersion : selectedDevice.osVersion, "16.0.0");
|
|
16
18
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/// <reference types="web-bluetooth" />
|
|
2
|
-
import { BehaviorSubject, ReplaySubject } from "rxjs";
|
|
3
|
-
import { Observable } from "rxjs";
|
|
2
|
+
import { Observable, BehaviorSubject, ReplaySubject } from "rxjs";
|
|
4
3
|
import { BluetoothTransport } from "../BluetoothTransport";
|
|
5
4
|
import { ActionOptions, SubscribeOptions } from "../types";
|
|
6
5
|
import { TRANSPORT_TYPE, BLUETOOTH_CONNECTION } from "../types";
|
|
@@ -48,7 +47,7 @@ export declare class WebBluetoothTransport implements BluetoothTransport {
|
|
|
48
47
|
writeCharacteristic(characteristicName: string, data: string): Promise<void>;
|
|
49
48
|
_addPendingAction(actionId: number): void;
|
|
50
49
|
_removePendingAction(actionId: number): void;
|
|
51
|
-
_autoToggleActionNotifications(
|
|
50
|
+
_autoToggleActionNotifications(): Observable<any>;
|
|
52
51
|
dispatchAction({ characteristicName, action }: ActionOptions): Promise<any>;
|
|
53
52
|
}
|
|
54
53
|
export {};
|
|
@@ -11,8 +11,8 @@ import { BLUETOOTH_PRIMARY_SERVICE_UUID_HEX } from "@neurosity/ipk";
|
|
|
11
11
|
import { BLUETOOTH_CHUNK_DELIMITER } from "@neurosity/ipk";
|
|
12
12
|
import { BLUETOOTH_DEVICE_NAME_PREFIXES } from "@neurosity/ipk";
|
|
13
13
|
import { BLUETOOTH_COMPANY_IDENTIFIER_HEX } from "@neurosity/ipk";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { Observable, BehaviorSubject, ReplaySubject } from "rxjs";
|
|
15
|
+
import { defer, merge, timer, fromEventPattern, NEVER } from "rxjs";
|
|
16
16
|
import { switchMap, map, filter, tap } from "rxjs/operators";
|
|
17
17
|
import { shareReplay, distinctUntilChanged } from "rxjs/operators";
|
|
18
18
|
import { take, share } from "rxjs/operators";
|
|
@@ -23,7 +23,6 @@ import { encode, decode } from "../utils/encoding";
|
|
|
23
23
|
import { TRANSPORT_TYPE, BLUETOOTH_CONNECTION } from "../types";
|
|
24
24
|
import { DEFAULT_ACTION_RESPONSE_TIMEOUT } from "../constants";
|
|
25
25
|
import { CHARACTERISTIC_UUIDS_TO_NAMES } from "../constants";
|
|
26
|
-
import { osHasBluetoothSupport } from "../utils/osHasBluetoothSupport";
|
|
27
26
|
const defaultOptions = {
|
|
28
27
|
autoConnect: true
|
|
29
28
|
};
|
|
@@ -64,7 +63,7 @@ export class WebBluetoothTransport {
|
|
|
64
63
|
_autoConnect(selectedDevice$) {
|
|
65
64
|
return this._isAutoConnectEnabled$.pipe(switchMap((isAutoConnectEnabled) => isAutoConnectEnabled
|
|
66
65
|
? merge(selectedDevice$, this.onDisconnected$.pipe(switchMap(() => selectedDevice$)))
|
|
67
|
-
: NEVER), switchMap((selectedDevice) =>
|
|
66
|
+
: NEVER), switchMap((selectedDevice) => __awaiter(this, void 0, void 0, function* () {
|
|
68
67
|
var _a;
|
|
69
68
|
const { deviceNickname } = selectedDevice;
|
|
70
69
|
if (this.isConnected()) {
|
|
@@ -304,43 +303,38 @@ export class WebBluetoothTransport {
|
|
|
304
303
|
const actions = this.pendingActions$.getValue();
|
|
305
304
|
this.pendingActions$.next(actions.filter((id) => id !== actionId));
|
|
306
305
|
}
|
|
307
|
-
_autoToggleActionNotifications(
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
this.addLog(`Started notifications for [actions] characteristic`);
|
|
324
|
-
}
|
|
325
|
-
catch (error) {
|
|
326
|
-
this.addLog(`Attemped to start notifications for [actions] characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
327
|
-
}
|
|
306
|
+
_autoToggleActionNotifications() {
|
|
307
|
+
let actionsCharacteristic;
|
|
308
|
+
let started = false;
|
|
309
|
+
return this.connection$.asObservable().pipe(switchMap((connection) => connection === BLUETOOTH_CONNECTION.CONNECTED
|
|
310
|
+
? defer(() => this.getCharacteristicByName("actions")).pipe(switchMap((characteristic) => {
|
|
311
|
+
actionsCharacteristic = characteristic;
|
|
312
|
+
return this.pendingActions$;
|
|
313
|
+
}))
|
|
314
|
+
: NEVER), tap((pendingActions) => __awaiter(this, void 0, void 0, function* () {
|
|
315
|
+
var _a, _b;
|
|
316
|
+
const hasPendingActions = !!pendingActions.length;
|
|
317
|
+
if (hasPendingActions && !started) {
|
|
318
|
+
started = true;
|
|
319
|
+
try {
|
|
320
|
+
yield actionsCharacteristic.startNotifications();
|
|
321
|
+
this.addLog(`Started notifications for [actions] characteristic`);
|
|
328
322
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
try {
|
|
332
|
-
yield actionsCharacteristic.stopNotifications();
|
|
333
|
-
this.addLog(`Stopped notifications for actions characteristic`);
|
|
334
|
-
}
|
|
335
|
-
catch (error) {
|
|
336
|
-
this.addLog(`Attemped to stop notifications for [actions] characteristic: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);
|
|
337
|
-
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
this.addLog(`Attemped to start notifications for [actions] characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
338
325
|
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
326
|
+
}
|
|
327
|
+
if (!hasPendingActions && started) {
|
|
328
|
+
started = false;
|
|
329
|
+
try {
|
|
330
|
+
yield actionsCharacteristic.stopNotifications();
|
|
331
|
+
this.addLog(`Stopped notifications for actions characteristic`);
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
this.addLog(`Attemped to stop notifications for [actions] characteristic: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
})));
|
|
344
338
|
}
|
|
345
339
|
dispatchAction({ characteristicName, action }) {
|
|
346
340
|
return __awaiter(this, void 0, void 0, function* () {
|
package/dist/esm/api/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { Credentials, CustomToken } from "../types/credentials";
|
|
|
11
11
|
import { EmailAndPassword } from "../types/credentials";
|
|
12
12
|
import { ChangeSettings } from "../types/settings";
|
|
13
13
|
import { DeviceStatus } from "../types/status";
|
|
14
|
-
import { DeviceInfo, DeviceSelector } from "../types/deviceInfo";
|
|
14
|
+
import { DeviceInfo, DeviceSelector, OSVersion } from "../types/deviceInfo";
|
|
15
15
|
import { UserClaims } from "../types/user";
|
|
16
16
|
import { OAuthRemoveResponse } from "../types/oauth";
|
|
17
17
|
import { Experiment } from "../types/experiment";
|
|
@@ -30,8 +30,10 @@ export declare class CloudClient implements Client {
|
|
|
30
30
|
protected timesync: Timesync;
|
|
31
31
|
protected subscriptionManager: SubscriptionManager;
|
|
32
32
|
protected status$: Observable<DeviceStatus>;
|
|
33
|
+
protected osVersion$: Observable<OSVersion>;
|
|
33
34
|
constructor(options: SDKOptions);
|
|
34
35
|
onDeviceChange(): Observable<DeviceInfo>;
|
|
36
|
+
osVersion(): Observable<OSVersion>;
|
|
35
37
|
private setAutoSelectedDevice;
|
|
36
38
|
get actions(): Actions;
|
|
37
39
|
dispatchAction(action: Action): Promise<any>;
|
package/dist/esm/api/index.js
CHANGED
|
@@ -31,6 +31,7 @@ export class CloudClient {
|
|
|
31
31
|
this.firebaseUser = new FirebaseUser(this.firebaseApp);
|
|
32
32
|
this._selectedDevice.next(undefined);
|
|
33
33
|
this.status$ = heartbeatAwareStatus(this.observeNamespace("status").pipe(share())).pipe(filterInternalKeys(), shareReplay(1));
|
|
34
|
+
this.osVersion$ = this.observeNamespace("info/osVersion").pipe(shareReplay(1));
|
|
34
35
|
this.firebaseUser.onAuthStateChanged().subscribe((user) => {
|
|
35
36
|
this.user = user;
|
|
36
37
|
});
|
|
@@ -64,6 +65,9 @@ export class CloudClient {
|
|
|
64
65
|
.asObservable()
|
|
65
66
|
.pipe(filter((value) => value !== undefined));
|
|
66
67
|
}
|
|
68
|
+
osVersion() {
|
|
69
|
+
return this.osVersion$;
|
|
70
|
+
}
|
|
67
71
|
// Automatically select device when user logs in
|
|
68
72
|
setAutoSelectedDevice() {
|
|
69
73
|
return __awaiter(this, void 0, void 0, function* () {
|