@neurosity/sdk 6.4.0-next.0 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/neurosity.iife.js +777 -806
- package/dist/browser/neurosity.js +13 -13
- package/dist/browser/neurosity.js.map +1 -1
- package/dist/cjs/Neurosity.d.ts +5 -0
- package/dist/cjs/Neurosity.js +18 -6
- package/dist/cjs/api/bluetooth/BluetoothClient.d.ts +3 -3
- package/dist/cjs/api/bluetooth/BluetoothClient.js +34 -33
- package/dist/cjs/api/bluetooth/react-native/ReactNativeTransport.d.ts +4 -5
- package/dist/cjs/api/bluetooth/react-native/ReactNativeTransport.js +38 -48
- package/dist/cjs/api/bluetooth/web/WebBluetoothTransport.d.ts +4 -5
- package/dist/cjs/api/bluetooth/web/WebBluetoothTransport.js +36 -46
- package/dist/electron/index.js +9 -9
- package/dist/electron/index.js.map +1 -1
- package/dist/esm/Neurosity.d.ts +5 -0
- package/dist/esm/Neurosity.js +19 -7
- package/dist/esm/api/bluetooth/BluetoothClient.d.ts +3 -3
- package/dist/esm/api/bluetooth/BluetoothClient.js +35 -34
- package/dist/esm/api/bluetooth/react-native/ReactNativeTransport.d.ts +4 -5
- package/dist/esm/api/bluetooth/react-native/ReactNativeTransport.js +35 -45
- package/dist/esm/api/bluetooth/web/WebBluetoothTransport.d.ts +4 -5
- package/dist/esm/api/bluetooth/web/WebBluetoothTransport.js +35 -45
- package/dist/esm/neurosity.mjs +777 -806
- package/dist/examples/neurosity.iife.js +777 -806
- package/dist/examples/neurosity.js +13 -13
- package/dist/examples/neurosity.mjs +777 -806
- 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,8 +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 {
|
|
13
|
-
import {
|
|
12
|
+
import { map, startWith, switchMap } from "rxjs/operators";
|
|
13
|
+
import { distinctUntilChanged } from "rxjs/operators";
|
|
14
14
|
import isEqual from "fast-deep-equal";
|
|
15
15
|
import { CloudClient, createUser } from "./api/index";
|
|
16
16
|
import { credentialWithLink, SERVER_TIMESTAMP } from "./api/index";
|
|
@@ -71,7 +71,7 @@ export class Neurosity {
|
|
|
71
71
|
if (!!bluetoothTransport) {
|
|
72
72
|
this.bluetoothClient = new BluetoothClient({
|
|
73
73
|
selectedDevice$: this.onDeviceChange(),
|
|
74
|
-
|
|
74
|
+
osHasBluetoothSupport$: this._osHasBluetoothSupport(),
|
|
75
75
|
createBluetoothToken: this.createBluetoothToken.bind(this),
|
|
76
76
|
transport: bluetoothTransport
|
|
77
77
|
});
|
|
@@ -102,6 +102,16 @@ export class Neurosity {
|
|
|
102
102
|
this.streamingMode$.next(streamingMode);
|
|
103
103
|
}
|
|
104
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
|
+
}
|
|
105
115
|
/**
|
|
106
116
|
* Subscribe to the device's streaming state changes and the current strategy
|
|
107
117
|
*
|
|
@@ -117,12 +127,14 @@ export class Neurosity {
|
|
|
117
127
|
streamingState() {
|
|
118
128
|
const isWifiOnline = (state) => [STATUS.ONLINE, STATUS.UPDATING].includes(state);
|
|
119
129
|
return this.streamingMode$.pipe(switchMap((streamingMode) => {
|
|
120
|
-
return
|
|
121
|
-
|
|
130
|
+
return combineLatest({
|
|
131
|
+
selectedDevice: this.onDeviceChange(),
|
|
132
|
+
osHasBluetoothSupport: this._osHasBluetoothSupport()
|
|
133
|
+
}).pipe(switchMap(({ selectedDevice, osHasBluetoothSupport }) => {
|
|
134
|
+
if (!selectedDevice) {
|
|
122
135
|
return EMPTY;
|
|
123
136
|
}
|
|
124
|
-
const isUnableToUseBluetooth = this.isMissingBluetoothTransport ||
|
|
125
|
-
!osHasBluetoothSupport(selectDevice, osVersion);
|
|
137
|
+
const isUnableToUseBluetooth = this.isMissingBluetoothTransport || !osHasBluetoothSupport;
|
|
126
138
|
if (isUnableToUseBluetooth) {
|
|
127
139
|
return this.cloudClient.status().pipe(map(({ state }) => ({
|
|
128
140
|
connected: isWifiOnline(state),
|
|
@@ -2,7 +2,7 @@ import { Observable } from "rxjs";
|
|
|
2
2
|
import { ReplaySubject } from "rxjs";
|
|
3
3
|
import { WebBluetoothTransport } from "./web/WebBluetoothTransport";
|
|
4
4
|
import { ReactNativeTransport } from "./react-native/ReactNativeTransport";
|
|
5
|
-
import { DeviceInfo
|
|
5
|
+
import { DeviceInfo } from "../../types/deviceInfo";
|
|
6
6
|
import { Action } from "../../types/actions";
|
|
7
7
|
import { Epoch } from "../../types/epoch";
|
|
8
8
|
import { BLUETOOTH_CONNECTION } from "./types";
|
|
@@ -16,14 +16,14 @@ declare type CreateBluetoothToken = () => Promise<string>;
|
|
|
16
16
|
declare type Options = {
|
|
17
17
|
transport: BluetoothTransport;
|
|
18
18
|
selectedDevice$: Observable<DeviceInfo>;
|
|
19
|
-
|
|
19
|
+
osHasBluetoothSupport$: Observable<boolean>;
|
|
20
20
|
createBluetoothToken: CreateBluetoothToken;
|
|
21
21
|
};
|
|
22
22
|
export declare class BluetoothClient {
|
|
23
23
|
transport: BluetoothTransport;
|
|
24
24
|
deviceInfo: DeviceInfo;
|
|
25
25
|
selectedDevice$: ReplaySubject<DeviceInfo>;
|
|
26
|
-
|
|
26
|
+
osHasBluetoothSupport$: ReplaySubject<boolean>;
|
|
27
27
|
isAuthenticated$: ReplaySubject<boolean>;
|
|
28
28
|
_focus$: Observable<any>;
|
|
29
29
|
_calm$: Observable<any>;
|
|
@@ -7,21 +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,
|
|
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);
|
|
22
|
-
this.
|
|
20
|
+
this.osHasBluetoothSupport$ = new ReplaySubject(1);
|
|
23
21
|
this.isAuthenticated$ = new ReplaySubject(1);
|
|
24
|
-
const { transport, selectedDevice$, createBluetoothToken } = options !== null && options !== void 0 ? options : {};
|
|
22
|
+
const { transport, selectedDevice$, osHasBluetoothSupport$, createBluetoothToken } = options !== null && options !== void 0 ? options : {};
|
|
25
23
|
if (!transport) {
|
|
26
24
|
throw new Error(`No bluetooth transport provided.`);
|
|
27
25
|
}
|
|
@@ -30,9 +28,14 @@ export class BluetoothClient {
|
|
|
30
28
|
if (selectedDevice$) {
|
|
31
29
|
selectedDevice$.subscribe(this.selectedDevice$);
|
|
32
30
|
}
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
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))
|
|
36
39
|
.subscribe({
|
|
37
40
|
error: (error) => {
|
|
38
41
|
var _a;
|
|
@@ -48,7 +51,11 @@ export class BluetoothClient {
|
|
|
48
51
|
this.transport.addLog("Auto authentication not enabled");
|
|
49
52
|
}
|
|
50
53
|
// Auto manage action notifications
|
|
51
|
-
this.
|
|
54
|
+
this.osHasBluetoothSupport$
|
|
55
|
+
.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport
|
|
56
|
+
? this.transport._autoToggleActionNotifications()
|
|
57
|
+
: EMPTY))
|
|
58
|
+
.subscribe();
|
|
52
59
|
// Multicast metrics (share)
|
|
53
60
|
this._focus$ = this._subscribeWhileAuthenticated("focus");
|
|
54
61
|
this._calm$ = this._subscribeWhileAuthenticated("calm");
|
|
@@ -72,28 +79,24 @@ export class BluetoothClient {
|
|
|
72
79
|
const reauthenticateInterval$ = timer(0, REAUTHENTICATE_INTERVAL).pipe(tap(() => {
|
|
73
80
|
this.transport.addLog(`Auto authentication in progress...`);
|
|
74
81
|
}));
|
|
75
|
-
return this.
|
|
76
|
-
?
|
|
77
|
-
: this
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
})))));
|
|
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
|
+
})));
|
|
88
93
|
}
|
|
89
94
|
enableAutoConnect(autoConnect) {
|
|
90
95
|
this.transport.enableAutoConnect(autoConnect);
|
|
91
96
|
}
|
|
92
97
|
_hasBluetoothSupport() {
|
|
93
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
-
|
|
95
|
-
const osVersion = yield firstValueFrom(this.osVersion$);
|
|
96
|
-
return osHasBluetoothSupport(selectedDevice, osVersion);
|
|
99
|
+
return yield firstValueFrom(this.osHasBluetoothSupport$);
|
|
97
100
|
});
|
|
98
101
|
}
|
|
99
102
|
authenticate(token) {
|
|
@@ -174,13 +177,11 @@ export class BluetoothClient {
|
|
|
174
177
|
});
|
|
175
178
|
}
|
|
176
179
|
_subscribeWhileAuthenticated(characteristicName) {
|
|
177
|
-
return this.
|
|
178
|
-
?
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
})
|
|
183
|
-
: 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());
|
|
184
185
|
}
|
|
185
186
|
focus() {
|
|
186
187
|
return this._focus$;
|
|
@@ -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";
|
|
@@ -7,7 +6,7 @@ import { BleManager } from "./types/BleManagerTypes";
|
|
|
7
6
|
import { Peripheral } from "./types/BleManagerTypes";
|
|
8
7
|
import { NativeEventEmitter } from "./types/ReactNativeTypes";
|
|
9
8
|
import { PlatformOSType } from "./types/ReactNativeTypes";
|
|
10
|
-
import { DeviceInfo
|
|
9
|
+
import { DeviceInfo } from "../../../types/deviceInfo";
|
|
11
10
|
declare type Characteristic = {
|
|
12
11
|
characteristicUUID: string;
|
|
13
12
|
serviceUUID: string;
|
|
@@ -48,7 +47,7 @@ export declare class ReactNativeTransport implements BluetoothTransport {
|
|
|
48
47
|
constructor(options: Options);
|
|
49
48
|
addLog(log: string): void;
|
|
50
49
|
isConnected(): boolean;
|
|
51
|
-
_autoConnect(selectedDevice$: Observable<DeviceInfo
|
|
50
|
+
_autoConnect(selectedDevice$: Observable<DeviceInfo>): Observable<void>;
|
|
52
51
|
enableAutoConnect(autoConnect: boolean): void;
|
|
53
52
|
connection(): Observable<BLUETOOTH_CONNECTION>;
|
|
54
53
|
_fromEvent(eventName: string): Observable<any>;
|
|
@@ -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,11 +10,11 @@ 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
|
-
import { take, share, scan, distinct
|
|
17
|
+
import { take, share, scan, distinct } from "rxjs/operators";
|
|
18
18
|
import { create6DigitPin } from "../utils/create6DigitPin";
|
|
19
19
|
import { stitchChunks } from "../utils/stitch";
|
|
20
20
|
import { encode, decode } from "../utils/encoding";
|
|
@@ -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
|
};
|
|
@@ -101,16 +100,14 @@ export class ReactNativeTransport {
|
|
|
101
100
|
const connection = this.connection$.getValue();
|
|
102
101
|
return connection === BLUETOOTH_CONNECTION.CONNECTED;
|
|
103
102
|
}
|
|
104
|
-
_autoConnect(selectedDevice
|
|
103
|
+
_autoConnect(selectedDevice$) {
|
|
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),
|
|
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,42 +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
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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
|
+
})));
|
|
372
362
|
}
|
|
373
363
|
dispatchAction({ characteristicName, action }) {
|
|
374
364
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1,10 +1,9 @@
|
|
|
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";
|
|
7
|
-
import { DeviceInfo
|
|
6
|
+
import { DeviceInfo } from "../../../types/deviceInfo";
|
|
8
7
|
declare type Options = {
|
|
9
8
|
autoConnect?: boolean;
|
|
10
9
|
};
|
|
@@ -25,7 +24,7 @@ export declare class WebBluetoothTransport implements BluetoothTransport {
|
|
|
25
24
|
_isAutoConnectEnabled$: ReplaySubject<boolean>;
|
|
26
25
|
constructor(options?: Options);
|
|
27
26
|
_getPairedDevices(): Promise<BluetoothDevice[]>;
|
|
28
|
-
_autoConnect(selectedDevice$: Observable<DeviceInfo
|
|
27
|
+
_autoConnect(selectedDevice$: Observable<DeviceInfo>): Observable<void>;
|
|
29
28
|
enableAutoConnect(autoConnect: boolean): void;
|
|
30
29
|
addLog(log: string): void;
|
|
31
30
|
isConnected(): boolean;
|
|
@@ -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,9 +11,9 @@ 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 {
|
|
16
|
-
import { switchMap, map, filter, tap
|
|
14
|
+
import { Observable, BehaviorSubject, ReplaySubject } from "rxjs";
|
|
15
|
+
import { defer, merge, timer, fromEventPattern, NEVER } from "rxjs";
|
|
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";
|
|
19
19
|
import { isWebBluetoothSupported } from "./isWebBluetoothSupported";
|
|
@@ -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
|
};
|
|
@@ -61,12 +60,10 @@ export class WebBluetoothTransport {
|
|
|
61
60
|
return yield navigator.bluetooth.getDevices();
|
|
62
61
|
});
|
|
63
62
|
}
|
|
64
|
-
_autoConnect(selectedDevice
|
|
63
|
+
_autoConnect(selectedDevice$) {
|
|
65
64
|
return this._isAutoConnectEnabled$.pipe(switchMap((isAutoConnectEnabled) => isAutoConnectEnabled
|
|
66
65
|
? merge(selectedDevice$, this.onDisconnected$.pipe(switchMap(() => selectedDevice$)))
|
|
67
|
-
: NEVER),
|
|
68
|
-
? of(selectedDevice)
|
|
69
|
-
: EMPTY), switchMap((selectedDevice) => __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
: NEVER), switchMap((selectedDevice) => __awaiter(this, void 0, void 0, function* () {
|
|
70
67
|
var _a;
|
|
71
68
|
const { deviceNickname } = selectedDevice;
|
|
72
69
|
if (this.isConnected()) {
|
|
@@ -306,45 +303,38 @@ export class WebBluetoothTransport {
|
|
|
306
303
|
const actions = this.pendingActions$.getValue();
|
|
307
304
|
this.pendingActions$.next(actions.filter((id) => id !== actionId));
|
|
308
305
|
}
|
|
309
|
-
_autoToggleActionNotifications(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
this.addLog(`Started notifications for [actions] characteristic`);
|
|
326
|
-
}
|
|
327
|
-
catch (error) {
|
|
328
|
-
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}`);
|
|
329
|
-
}
|
|
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`);
|
|
330
322
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
try {
|
|
334
|
-
yield actionsCharacteristic.stopNotifications();
|
|
335
|
-
this.addLog(`Stopped notifications for actions characteristic`);
|
|
336
|
-
}
|
|
337
|
-
catch (error) {
|
|
338
|
-
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}`);
|
|
339
|
-
}
|
|
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}`);
|
|
340
325
|
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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
|
+
})));
|
|
348
338
|
}
|
|
349
339
|
dispatchAction({ characteristicName, action }) {
|
|
350
340
|
return __awaiter(this, void 0, void 0, function* () {
|