@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
|
@@ -43007,6 +43007,7 @@ var Neurosity = (function (exports) {
|
|
|
43007
43007
|
this.firebaseUser = new FirebaseUser(this.firebaseApp);
|
|
43008
43008
|
this._selectedDevice.next(undefined);
|
|
43009
43009
|
this.status$ = heartbeatAwareStatus(this.observeNamespace("status").pipe(share())).pipe(filterInternalKeys(), shareReplay(1));
|
|
43010
|
+
this.osVersion$ = this.observeNamespace("info/osVersion").pipe(shareReplay(1));
|
|
43010
43011
|
this.firebaseUser.onAuthStateChanged().subscribe((user) => {
|
|
43011
43012
|
this.user = user;
|
|
43012
43013
|
});
|
|
@@ -43040,6 +43041,9 @@ var Neurosity = (function (exports) {
|
|
|
43040
43041
|
.asObservable()
|
|
43041
43042
|
.pipe(filter((value) => value !== undefined));
|
|
43042
43043
|
}
|
|
43044
|
+
osVersion() {
|
|
43045
|
+
return this.osVersion$;
|
|
43046
|
+
}
|
|
43043
43047
|
// Automatically select device when user logs in
|
|
43044
43048
|
setAutoSelectedDevice() {
|
|
43045
43049
|
return __awaiter$b(this, void 0, void 0, function* () {
|
|
@@ -45750,577 +45754,412 @@ var Neurosity = (function (exports) {
|
|
|
45750
45754
|
// Reverse BLUETOOTH_CHARACTERISTICS key/values for easy lookup
|
|
45751
45755
|
const CHARACTERISTIC_UUIDS_TO_NAMES = Object.fromEntries(Object.entries(BLUETOOTH_CHARACTERISTICS).map((entries) => entries.reverse()));
|
|
45752
45756
|
|
|
45753
|
-
|
|
45754
|
-
|
|
45755
|
-
|
|
45756
|
-
|
|
45757
|
-
|
|
45758
|
-
|
|
45759
|
-
|
|
45760
|
-
|
|
45761
|
-
var debug_1 = debug;
|
|
45762
|
-
|
|
45763
|
-
// Note: this is the semver.org version of the spec that it implements
|
|
45764
|
-
// Not necessarily the package version of this code.
|
|
45765
|
-
const SEMVER_SPEC_VERSION = '2.0.0';
|
|
45766
|
-
|
|
45767
|
-
const MAX_LENGTH = 256;
|
|
45768
|
-
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
|
|
45769
|
-
/* istanbul ignore next */ 9007199254740991;
|
|
45770
|
-
|
|
45771
|
-
// Max safe segment length for coercion.
|
|
45772
|
-
const MAX_SAFE_COMPONENT_LENGTH = 16;
|
|
45773
|
-
|
|
45774
|
-
var constants = {
|
|
45775
|
-
SEMVER_SPEC_VERSION,
|
|
45776
|
-
MAX_LENGTH,
|
|
45777
|
-
MAX_SAFE_INTEGER,
|
|
45778
|
-
MAX_SAFE_COMPONENT_LENGTH,
|
|
45757
|
+
var __awaiter$d = function (thisArg, _arguments, P, generator) {
|
|
45758
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
45759
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
45760
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
45761
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
45762
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
45763
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
45764
|
+
});
|
|
45779
45765
|
};
|
|
45780
|
-
|
|
45781
|
-
|
|
45782
|
-
return module = { exports: {} }, fn(module, module.exports), module.exports;
|
|
45783
|
-
}
|
|
45784
|
-
|
|
45785
|
-
var re_1 = createCommonjsModule(function (module, exports) {
|
|
45786
|
-
const { MAX_SAFE_COMPONENT_LENGTH } = constants;
|
|
45787
|
-
|
|
45788
|
-
exports = module.exports = {};
|
|
45789
|
-
|
|
45790
|
-
// The actual regexps go on exports.re
|
|
45791
|
-
const re = exports.re = [];
|
|
45792
|
-
const src = exports.src = [];
|
|
45793
|
-
const t = exports.t = {};
|
|
45794
|
-
let R = 0;
|
|
45795
|
-
|
|
45796
|
-
const createToken = (name, value, isGlobal) => {
|
|
45797
|
-
const index = R++;
|
|
45798
|
-
debug_1(name, index, value);
|
|
45799
|
-
t[name] = index;
|
|
45800
|
-
src[index] = value;
|
|
45801
|
-
re[index] = new RegExp(value, isGlobal ? 'g' : undefined);
|
|
45766
|
+
const defaultOptions$1 = {
|
|
45767
|
+
autoConnect: true
|
|
45802
45768
|
};
|
|
45803
|
-
|
|
45804
|
-
|
|
45805
|
-
|
|
45806
|
-
|
|
45807
|
-
|
|
45808
|
-
|
|
45809
|
-
|
|
45810
|
-
|
|
45811
|
-
|
|
45812
|
-
|
|
45813
|
-
|
|
45814
|
-
|
|
45815
|
-
|
|
45816
|
-
|
|
45817
|
-
|
|
45818
|
-
|
|
45819
|
-
|
|
45820
|
-
|
|
45821
|
-
|
|
45822
|
-
|
|
45823
|
-
|
|
45824
|
-
|
|
45825
|
-
|
|
45826
|
-
|
|
45827
|
-
|
|
45828
|
-
|
|
45829
|
-
|
|
45830
|
-
|
|
45831
|
-
// A numeric identifier, or a non-numeric identifier.
|
|
45832
|
-
|
|
45833
|
-
createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER]
|
|
45834
|
-
}|${src[t.NONNUMERICIDENTIFIER]})`);
|
|
45835
|
-
|
|
45836
|
-
createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE]
|
|
45837
|
-
}|${src[t.NONNUMERICIDENTIFIER]})`);
|
|
45838
|
-
|
|
45839
|
-
// ## Pre-release Version
|
|
45840
|
-
// Hyphen, followed by one or more dot-separated pre-release version
|
|
45841
|
-
// identifiers.
|
|
45842
|
-
|
|
45843
|
-
createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
|
|
45844
|
-
}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`);
|
|
45845
|
-
|
|
45846
|
-
createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
|
|
45847
|
-
}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`);
|
|
45848
|
-
|
|
45849
|
-
// ## Build Metadata Identifier
|
|
45850
|
-
// Any combination of digits, letters, or hyphens.
|
|
45851
|
-
|
|
45852
|
-
createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+');
|
|
45853
|
-
|
|
45854
|
-
// ## Build Metadata
|
|
45855
|
-
// Plus sign, followed by one or more period-separated build metadata
|
|
45856
|
-
// identifiers.
|
|
45857
|
-
|
|
45858
|
-
createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
|
|
45859
|
-
}(?:\\.${src[t.BUILDIDENTIFIER]})*))`);
|
|
45860
|
-
|
|
45861
|
-
// ## Full Version String
|
|
45862
|
-
// A main version, followed optionally by a pre-release version and
|
|
45863
|
-
// build metadata.
|
|
45864
|
-
|
|
45865
|
-
// Note that the only major, minor, patch, and pre-release sections of
|
|
45866
|
-
// the version string are capturing groups. The build metadata is not a
|
|
45867
|
-
// capturing group, because it should not ever be used in version
|
|
45868
|
-
// comparison.
|
|
45869
|
-
|
|
45870
|
-
createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
|
|
45871
|
-
}${src[t.PRERELEASE]}?${
|
|
45872
|
-
src[t.BUILD]}?`);
|
|
45873
|
-
|
|
45874
|
-
createToken('FULL', `^${src[t.FULLPLAIN]}$`);
|
|
45875
|
-
|
|
45876
|
-
// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
|
|
45877
|
-
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
|
|
45878
|
-
// common in the npm registry.
|
|
45879
|
-
createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
|
|
45880
|
-
}${src[t.PRERELEASELOOSE]}?${
|
|
45881
|
-
src[t.BUILD]}?`);
|
|
45882
|
-
|
|
45883
|
-
createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`);
|
|
45884
|
-
|
|
45885
|
-
createToken('GTLT', '((?:<|>)?=?)');
|
|
45886
|
-
|
|
45887
|
-
// Something like "2.*" or "1.2.x".
|
|
45888
|
-
// Note that "x.x" is a valid xRange identifer, meaning "any version"
|
|
45889
|
-
// Only the first item is strictly required.
|
|
45890
|
-
createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);
|
|
45891
|
-
createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`);
|
|
45892
|
-
|
|
45893
|
-
createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
|
|
45894
|
-
`(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
|
|
45895
|
-
`(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
|
|
45896
|
-
`(?:${src[t.PRERELEASE]})?${
|
|
45897
|
-
src[t.BUILD]}?` +
|
|
45898
|
-
`)?)?`);
|
|
45899
|
-
|
|
45900
|
-
createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
|
45901
|
-
`(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
|
45902
|
-
`(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
|
45903
|
-
`(?:${src[t.PRERELEASELOOSE]})?${
|
|
45904
|
-
src[t.BUILD]}?` +
|
|
45905
|
-
`)?)?`);
|
|
45906
|
-
|
|
45907
|
-
createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`);
|
|
45908
|
-
createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`);
|
|
45909
|
-
|
|
45910
|
-
// Coercion.
|
|
45911
|
-
// Extract anything that could conceivably be a part of a valid semver
|
|
45912
|
-
createToken('COERCE', `${'(^|[^\\d])' +
|
|
45913
|
-
'(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
|
|
45914
|
-
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
|
|
45915
|
-
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
|
|
45916
|
-
`(?:$|[^\\d])`);
|
|
45917
|
-
createToken('COERCERTL', src[t.COERCE], true);
|
|
45918
|
-
|
|
45919
|
-
// Tilde ranges.
|
|
45920
|
-
// Meaning is "reasonably at or greater than"
|
|
45921
|
-
createToken('LONETILDE', '(?:~>?)');
|
|
45922
|
-
|
|
45923
|
-
createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true);
|
|
45924
|
-
exports.tildeTrimReplace = '$1~';
|
|
45925
|
-
|
|
45926
|
-
createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`);
|
|
45927
|
-
createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`);
|
|
45928
|
-
|
|
45929
|
-
// Caret ranges.
|
|
45930
|
-
// Meaning is "at least and backwards compatible with"
|
|
45931
|
-
createToken('LONECARET', '(?:\\^)');
|
|
45932
|
-
|
|
45933
|
-
createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true);
|
|
45934
|
-
exports.caretTrimReplace = '$1^';
|
|
45935
|
-
|
|
45936
|
-
createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`);
|
|
45937
|
-
createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`);
|
|
45938
|
-
|
|
45939
|
-
// A simple gt/lt/eq thing, or just "" to indicate "any version"
|
|
45940
|
-
createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`);
|
|
45941
|
-
createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`);
|
|
45942
|
-
|
|
45943
|
-
// An expression to strip any whitespace between the gtlt and the thing
|
|
45944
|
-
// it modifies, so that `> 1.2.3` ==> `>1.2.3`
|
|
45945
|
-
createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
|
|
45946
|
-
}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true);
|
|
45947
|
-
exports.comparatorTrimReplace = '$1$2$3';
|
|
45948
|
-
|
|
45949
|
-
// Something like `1.2.3 - 1.2.4`
|
|
45950
|
-
// Note that these all use the loose form, because they'll be
|
|
45951
|
-
// checked against either the strict or loose comparator form
|
|
45952
|
-
// later.
|
|
45953
|
-
createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
|
|
45954
|
-
`\\s+-\\s+` +
|
|
45955
|
-
`(${src[t.XRANGEPLAIN]})` +
|
|
45956
|
-
`\\s*$`);
|
|
45957
|
-
|
|
45958
|
-
createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
|
|
45959
|
-
`\\s+-\\s+` +
|
|
45960
|
-
`(${src[t.XRANGEPLAINLOOSE]})` +
|
|
45961
|
-
`\\s*$`);
|
|
45962
|
-
|
|
45963
|
-
// Star ranges basically just allow anything at all.
|
|
45964
|
-
createToken('STAR', '(<|>)?=?\\s*\\*');
|
|
45965
|
-
// >=0.0.0 is like a star
|
|
45966
|
-
createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$');
|
|
45967
|
-
createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$');
|
|
45968
|
-
});
|
|
45969
|
-
var re_2 = re_1.re;
|
|
45970
|
-
var re_3 = re_1.src;
|
|
45971
|
-
var re_4 = re_1.t;
|
|
45972
|
-
var re_5 = re_1.tildeTrimReplace;
|
|
45973
|
-
var re_6 = re_1.caretTrimReplace;
|
|
45974
|
-
var re_7 = re_1.comparatorTrimReplace;
|
|
45975
|
-
|
|
45976
|
-
// parse out just the options we care about so we always get a consistent
|
|
45977
|
-
// obj with keys in a consistent order.
|
|
45978
|
-
const opts = ['includePrerelease', 'loose', 'rtl'];
|
|
45979
|
-
const parseOptions = options =>
|
|
45980
|
-
!options ? {}
|
|
45981
|
-
: typeof options !== 'object' ? { loose: true }
|
|
45982
|
-
: opts.filter(k => options[k]).reduce((o, k) => {
|
|
45983
|
-
o[k] = true;
|
|
45984
|
-
return o
|
|
45985
|
-
}, {});
|
|
45986
|
-
var parseOptions_1 = parseOptions;
|
|
45987
|
-
|
|
45988
|
-
const numeric = /^[0-9]+$/;
|
|
45989
|
-
const compareIdentifiers = (a, b) => {
|
|
45990
|
-
const anum = numeric.test(a);
|
|
45991
|
-
const bnum = numeric.test(b);
|
|
45992
|
-
|
|
45993
|
-
if (anum && bnum) {
|
|
45994
|
-
a = +a;
|
|
45995
|
-
b = +b;
|
|
45996
|
-
}
|
|
45997
|
-
|
|
45998
|
-
return a === b ? 0
|
|
45999
|
-
: (anum && !bnum) ? -1
|
|
46000
|
-
: (bnum && !anum) ? 1
|
|
46001
|
-
: a < b ? -1
|
|
46002
|
-
: 1
|
|
46003
|
-
};
|
|
46004
|
-
|
|
46005
|
-
const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a);
|
|
46006
|
-
|
|
46007
|
-
var identifiers = {
|
|
46008
|
-
compareIdentifiers,
|
|
46009
|
-
rcompareIdentifiers,
|
|
46010
|
-
};
|
|
46011
|
-
|
|
46012
|
-
const { MAX_LENGTH: MAX_LENGTH$1, MAX_SAFE_INTEGER: MAX_SAFE_INTEGER$1 } = constants;
|
|
46013
|
-
const { re: re$1, t: t$1 } = re_1;
|
|
46014
|
-
|
|
46015
|
-
|
|
46016
|
-
const { compareIdentifiers: compareIdentifiers$1 } = identifiers;
|
|
46017
|
-
class SemVer {
|
|
46018
|
-
constructor (version, options) {
|
|
46019
|
-
options = parseOptions_1(options);
|
|
46020
|
-
|
|
46021
|
-
if (version instanceof SemVer) {
|
|
46022
|
-
if (version.loose === !!options.loose &&
|
|
46023
|
-
version.includePrerelease === !!options.includePrerelease) {
|
|
46024
|
-
return version
|
|
46025
|
-
} else {
|
|
46026
|
-
version = version.version;
|
|
46027
|
-
}
|
|
46028
|
-
} else if (typeof version !== 'string') {
|
|
46029
|
-
throw new TypeError(`Invalid Version: ${version}`)
|
|
46030
|
-
}
|
|
46031
|
-
|
|
46032
|
-
if (version.length > MAX_LENGTH$1) {
|
|
46033
|
-
throw new TypeError(
|
|
46034
|
-
`version is longer than ${MAX_LENGTH$1} characters`
|
|
46035
|
-
)
|
|
45769
|
+
class WebBluetoothTransport {
|
|
45770
|
+
constructor(options = {}) {
|
|
45771
|
+
this.type = exports.TRANSPORT_TYPE.WEB;
|
|
45772
|
+
this.characteristicsByName = {};
|
|
45773
|
+
this.connection$ = new BehaviorSubject(exports.BLUETOOTH_CONNECTION.DISCONNECTED);
|
|
45774
|
+
this.pendingActions$ = new BehaviorSubject([]);
|
|
45775
|
+
this.logs$ = new ReplaySubject(10);
|
|
45776
|
+
this.onDisconnected$ = this._onDisconnected().pipe(share());
|
|
45777
|
+
this.connectionStream$ = this.connection$
|
|
45778
|
+
.asObservable()
|
|
45779
|
+
.pipe(filter((connection) => !!connection), distinctUntilChanged(), shareReplay(1));
|
|
45780
|
+
this._isAutoConnectEnabled$ = new ReplaySubject(1);
|
|
45781
|
+
this.options = Object.assign(Object.assign({}, defaultOptions$1), options);
|
|
45782
|
+
if (!isWebBluetoothSupported()) {
|
|
45783
|
+
const errorMessage = "Web Bluetooth is not supported";
|
|
45784
|
+
this.addLog(errorMessage);
|
|
45785
|
+
throw new Error(errorMessage);
|
|
45786
|
+
}
|
|
45787
|
+
this._isAutoConnectEnabled$.subscribe((autoConnect) => {
|
|
45788
|
+
this.addLog(`Auto connect: ${autoConnect ? "enabled" : "disabled"}`);
|
|
45789
|
+
});
|
|
45790
|
+
this._isAutoConnectEnabled$.next(this.options.autoConnect);
|
|
45791
|
+
this.connection$.asObservable().subscribe((connection) => {
|
|
45792
|
+
this.addLog(`connection status is ${connection}`);
|
|
45793
|
+
});
|
|
45794
|
+
this.onDisconnected$.subscribe(() => {
|
|
45795
|
+
this.connection$.next(exports.BLUETOOTH_CONNECTION.DISCONNECTED);
|
|
45796
|
+
});
|
|
46036
45797
|
}
|
|
46037
|
-
|
|
46038
|
-
|
|
46039
|
-
|
|
46040
|
-
|
|
46041
|
-
// this isn't actually relevant for versions, but keep it so that we
|
|
46042
|
-
// don't run into trouble passing this.options around.
|
|
46043
|
-
this.includePrerelease = !!options.includePrerelease;
|
|
46044
|
-
|
|
46045
|
-
const m = version.trim().match(options.loose ? re$1[t$1.LOOSE] : re$1[t$1.FULL]);
|
|
46046
|
-
|
|
46047
|
-
if (!m) {
|
|
46048
|
-
throw new TypeError(`Invalid Version: ${version}`)
|
|
45798
|
+
_getPairedDevices() {
|
|
45799
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
45800
|
+
return yield navigator.bluetooth.getDevices();
|
|
45801
|
+
});
|
|
46049
45802
|
}
|
|
46050
|
-
|
|
46051
|
-
|
|
46052
|
-
|
|
46053
|
-
|
|
46054
|
-
|
|
46055
|
-
|
|
46056
|
-
|
|
46057
|
-
|
|
46058
|
-
|
|
46059
|
-
|
|
45803
|
+
_autoConnect(selectedDevice$) {
|
|
45804
|
+
return this._isAutoConnectEnabled$.pipe(switchMap((isAutoConnectEnabled) => isAutoConnectEnabled
|
|
45805
|
+
? merge(selectedDevice$, this.onDisconnected$.pipe(switchMap(() => selectedDevice$)))
|
|
45806
|
+
: NEVER), switchMap((selectedDevice) => __awaiter$d(this, void 0, void 0, function* () {
|
|
45807
|
+
var _a;
|
|
45808
|
+
const { deviceNickname } = selectedDevice;
|
|
45809
|
+
if (this.isConnected()) {
|
|
45810
|
+
this.addLog(`Auto connect: ${deviceNickname} is already connected. Skipping auto connect.`);
|
|
45811
|
+
return;
|
|
45812
|
+
}
|
|
45813
|
+
const [devicesError, devices] = yield this._getPairedDevices()
|
|
45814
|
+
.then((devices) => [null, devices])
|
|
45815
|
+
.catch((error) => [error, null]);
|
|
45816
|
+
if (devicesError) {
|
|
45817
|
+
throw new Error(`failed to get devices: ${(_a = devicesError === null || devicesError === void 0 ? void 0 : devicesError.message) !== null && _a !== void 0 ? _a : devicesError}`);
|
|
45818
|
+
}
|
|
45819
|
+
this.addLog(`Auto connect: found ${devices.length} devices ${devices
|
|
45820
|
+
.map(({ name }) => name)
|
|
45821
|
+
.join(", ")}`);
|
|
45822
|
+
// @important - Using `findLast` instead of `find` because somehow the browser
|
|
45823
|
+
// is finding multiple peripherals with the same name
|
|
45824
|
+
const device = devices.findLast((device) => device.name === deviceNickname);
|
|
45825
|
+
if (!device) {
|
|
45826
|
+
throw new Error(`couldn't find selected device in the list of paired devices.`);
|
|
45827
|
+
}
|
|
45828
|
+
this.addLog(`Auto connect: ${deviceNickname} was detected and previously paired`);
|
|
45829
|
+
return device;
|
|
45830
|
+
})), tap(() => {
|
|
45831
|
+
this.connection$.next(exports.BLUETOOTH_CONNECTION.SCANNING);
|
|
45832
|
+
}), switchMap((device) => onAdvertisementReceived(device)), switchMap((advertisement) => __awaiter$d(this, void 0, void 0, function* () {
|
|
45833
|
+
this.addLog(`Advertisement received for ${advertisement.device.name}`);
|
|
45834
|
+
return yield this.getServerServiceAndCharacteristics(advertisement.device);
|
|
45835
|
+
})));
|
|
46060
45836
|
}
|
|
46061
|
-
|
|
46062
|
-
|
|
46063
|
-
throw new TypeError('Invalid minor version')
|
|
45837
|
+
enableAutoConnect(autoConnect) {
|
|
45838
|
+
this._isAutoConnectEnabled$.next(autoConnect);
|
|
46064
45839
|
}
|
|
46065
|
-
|
|
46066
|
-
|
|
46067
|
-
throw new TypeError('Invalid patch version')
|
|
45840
|
+
addLog(log) {
|
|
45841
|
+
this.logs$.next(log);
|
|
46068
45842
|
}
|
|
46069
|
-
|
|
46070
|
-
|
|
46071
|
-
|
|
46072
|
-
this.prerelease = [];
|
|
46073
|
-
} else {
|
|
46074
|
-
this.prerelease = m[4].split('.').map((id) => {
|
|
46075
|
-
if (/^[0-9]+$/.test(id)) {
|
|
46076
|
-
const num = +id;
|
|
46077
|
-
if (num >= 0 && num < MAX_SAFE_INTEGER$1) {
|
|
46078
|
-
return num
|
|
46079
|
-
}
|
|
46080
|
-
}
|
|
46081
|
-
return id
|
|
46082
|
-
});
|
|
45843
|
+
isConnected() {
|
|
45844
|
+
const connection = this.connection$.getValue();
|
|
45845
|
+
return connection === exports.BLUETOOTH_CONNECTION.CONNECTED;
|
|
46083
45846
|
}
|
|
46084
|
-
|
|
46085
|
-
|
|
46086
|
-
this.format();
|
|
46087
|
-
}
|
|
46088
|
-
|
|
46089
|
-
format () {
|
|
46090
|
-
this.version = `${this.major}.${this.minor}.${this.patch}`;
|
|
46091
|
-
if (this.prerelease.length) {
|
|
46092
|
-
this.version += `-${this.prerelease.join('.')}`;
|
|
45847
|
+
connection() {
|
|
45848
|
+
return this.connectionStream$;
|
|
46093
45849
|
}
|
|
46094
|
-
|
|
46095
|
-
|
|
46096
|
-
|
|
46097
|
-
|
|
46098
|
-
|
|
46099
|
-
|
|
46100
|
-
|
|
46101
|
-
|
|
46102
|
-
|
|
46103
|
-
|
|
46104
|
-
|
|
46105
|
-
return 0
|
|
46106
|
-
}
|
|
46107
|
-
other = new SemVer(other, this.options);
|
|
45850
|
+
connect(deviceNickname) {
|
|
45851
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
45852
|
+
try {
|
|
45853
|
+
// requires user gesture
|
|
45854
|
+
const device = yield this.requestDevice(deviceNickname);
|
|
45855
|
+
yield this.getServerServiceAndCharacteristics(device);
|
|
45856
|
+
}
|
|
45857
|
+
catch (error) {
|
|
45858
|
+
return Promise.reject(error);
|
|
45859
|
+
}
|
|
45860
|
+
});
|
|
46108
45861
|
}
|
|
46109
|
-
|
|
46110
|
-
|
|
46111
|
-
|
|
45862
|
+
requestDevice(deviceNickname) {
|
|
45863
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
45864
|
+
try {
|
|
45865
|
+
this.addLog("Requesting Bluetooth Device...");
|
|
45866
|
+
const prefixes = BLUETOOTH_DEVICE_NAME_PREFIXES.map((namePrefix) => ({
|
|
45867
|
+
namePrefix
|
|
45868
|
+
}));
|
|
45869
|
+
// Ability to only show selectedDevice if provided
|
|
45870
|
+
const filters = deviceNickname
|
|
45871
|
+
? [
|
|
45872
|
+
{
|
|
45873
|
+
name: deviceNickname
|
|
45874
|
+
}
|
|
45875
|
+
]
|
|
45876
|
+
: prefixes;
|
|
45877
|
+
const device = yield window.navigator.bluetooth.requestDevice({
|
|
45878
|
+
filters: [
|
|
45879
|
+
...filters,
|
|
45880
|
+
{
|
|
45881
|
+
manufacturerData: [
|
|
45882
|
+
{
|
|
45883
|
+
companyIdentifier: BLUETOOTH_COMPANY_IDENTIFIER_HEX
|
|
45884
|
+
}
|
|
45885
|
+
]
|
|
45886
|
+
}
|
|
45887
|
+
],
|
|
45888
|
+
optionalServices: [BLUETOOTH_PRIMARY_SERVICE_UUID_HEX]
|
|
45889
|
+
});
|
|
45890
|
+
return device;
|
|
45891
|
+
}
|
|
45892
|
+
catch (error) {
|
|
45893
|
+
return Promise.reject(error);
|
|
45894
|
+
}
|
|
45895
|
+
});
|
|
46112
45896
|
}
|
|
46113
|
-
|
|
46114
|
-
|
|
46115
|
-
|
|
46116
|
-
|
|
46117
|
-
|
|
46118
|
-
|
|
46119
|
-
|
|
45897
|
+
getServerServiceAndCharacteristics(device) {
|
|
45898
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
45899
|
+
try {
|
|
45900
|
+
this.device = device;
|
|
45901
|
+
const isConnecting = this.connection$.getValue() === exports.BLUETOOTH_CONNECTION.CONNECTING;
|
|
45902
|
+
if (!isConnecting) {
|
|
45903
|
+
this.connection$.next(exports.BLUETOOTH_CONNECTION.CONNECTING);
|
|
45904
|
+
}
|
|
45905
|
+
this.server = yield device.gatt.connect();
|
|
45906
|
+
this.addLog(`Getting service...`);
|
|
45907
|
+
this.service = yield this.server.getPrimaryService(BLUETOOTH_PRIMARY_SERVICE_UUID_HEX);
|
|
45908
|
+
this.addLog(`Got service ${this.service.uuid}, getting characteristics...`);
|
|
45909
|
+
const characteristicsList = yield this.service.getCharacteristics();
|
|
45910
|
+
this.addLog(`Got characteristics`);
|
|
45911
|
+
this.characteristicsByName = Object.fromEntries(characteristicsList.map((characteristic) => [
|
|
45912
|
+
CHARACTERISTIC_UUIDS_TO_NAMES[characteristic.uuid],
|
|
45913
|
+
characteristic
|
|
45914
|
+
]));
|
|
45915
|
+
this.connection$.next(exports.BLUETOOTH_CONNECTION.CONNECTED);
|
|
45916
|
+
}
|
|
45917
|
+
catch (error) {
|
|
45918
|
+
return Promise.reject(error);
|
|
45919
|
+
}
|
|
45920
|
+
});
|
|
46120
45921
|
}
|
|
46121
|
-
|
|
46122
|
-
|
|
46123
|
-
|
|
46124
|
-
|
|
46125
|
-
|
|
46126
|
-
|
|
46127
|
-
}
|
|
46128
|
-
|
|
46129
|
-
comparePre (other) {
|
|
46130
|
-
if (!(other instanceof SemVer)) {
|
|
46131
|
-
other = new SemVer(other, this.options);
|
|
45922
|
+
_onDisconnected() {
|
|
45923
|
+
return this.connection$
|
|
45924
|
+
.asObservable()
|
|
45925
|
+
.pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED
|
|
45926
|
+
? fromDOMEvent(this.device, "gattserverdisconnected")
|
|
45927
|
+
: NEVER));
|
|
46132
45928
|
}
|
|
46133
|
-
|
|
46134
|
-
|
|
46135
|
-
|
|
46136
|
-
|
|
46137
|
-
|
|
46138
|
-
|
|
46139
|
-
|
|
46140
|
-
|
|
45929
|
+
disconnect() {
|
|
45930
|
+
var _a, _b;
|
|
45931
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
45932
|
+
const isDeviceConnected = (_b = (_a = this === null || this === void 0 ? void 0 : this.device) === null || _a === void 0 ? void 0 : _a.gatt) === null || _b === void 0 ? void 0 : _b.connected;
|
|
45933
|
+
if (isDeviceConnected) {
|
|
45934
|
+
this.device.gatt.disconnect();
|
|
45935
|
+
}
|
|
45936
|
+
});
|
|
46141
45937
|
}
|
|
46142
|
-
|
|
46143
|
-
|
|
46144
|
-
|
|
46145
|
-
|
|
46146
|
-
|
|
46147
|
-
|
|
46148
|
-
|
|
46149
|
-
|
|
46150
|
-
|
|
46151
|
-
return
|
|
46152
|
-
|
|
46153
|
-
|
|
46154
|
-
} else if (a === b) {
|
|
46155
|
-
continue
|
|
46156
|
-
} else {
|
|
46157
|
-
return compareIdentifiers$1(a, b)
|
|
46158
|
-
}
|
|
46159
|
-
} while (++i)
|
|
46160
|
-
}
|
|
46161
|
-
|
|
46162
|
-
compareBuild (other) {
|
|
46163
|
-
if (!(other instanceof SemVer)) {
|
|
46164
|
-
other = new SemVer(other, this.options);
|
|
45938
|
+
/**
|
|
45939
|
+
*
|
|
45940
|
+
* Bluetooth GATT attributes, services, characteristics, etc. are invalidated
|
|
45941
|
+
* when a device disconnects. This means your code should always retrieve
|
|
45942
|
+
* (through getPrimaryService(s), getCharacteristic(s), etc.) these attributes
|
|
45943
|
+
* after reconnecting.
|
|
45944
|
+
*/
|
|
45945
|
+
getCharacteristicByName(characteristicName) {
|
|
45946
|
+
var _a;
|
|
45947
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
45948
|
+
return (_a = this.characteristicsByName) === null || _a === void 0 ? void 0 : _a[characteristicName];
|
|
45949
|
+
});
|
|
46165
45950
|
}
|
|
46166
|
-
|
|
46167
|
-
|
|
46168
|
-
|
|
46169
|
-
|
|
46170
|
-
|
|
46171
|
-
|
|
46172
|
-
|
|
46173
|
-
|
|
46174
|
-
|
|
46175
|
-
|
|
46176
|
-
|
|
46177
|
-
return -1
|
|
46178
|
-
} else if (a === b) {
|
|
46179
|
-
continue
|
|
46180
|
-
} else {
|
|
46181
|
-
return compareIdentifiers$1(a, b)
|
|
46182
|
-
}
|
|
46183
|
-
} while (++i)
|
|
46184
|
-
}
|
|
46185
|
-
|
|
46186
|
-
// preminor will bump the version up to the next minor release, and immediately
|
|
46187
|
-
// down to pre-release. premajor and prepatch work the same way.
|
|
46188
|
-
inc (release, identifier) {
|
|
46189
|
-
switch (release) {
|
|
46190
|
-
case 'premajor':
|
|
46191
|
-
this.prerelease.length = 0;
|
|
46192
|
-
this.patch = 0;
|
|
46193
|
-
this.minor = 0;
|
|
46194
|
-
this.major++;
|
|
46195
|
-
this.inc('pre', identifier);
|
|
46196
|
-
break
|
|
46197
|
-
case 'preminor':
|
|
46198
|
-
this.prerelease.length = 0;
|
|
46199
|
-
this.patch = 0;
|
|
46200
|
-
this.minor++;
|
|
46201
|
-
this.inc('pre', identifier);
|
|
46202
|
-
break
|
|
46203
|
-
case 'prepatch':
|
|
46204
|
-
// If this is already a prerelease, it will bump to the next version
|
|
46205
|
-
// drop any prereleases that might already exist, since they are not
|
|
46206
|
-
// relevant at this point.
|
|
46207
|
-
this.prerelease.length = 0;
|
|
46208
|
-
this.inc('patch', identifier);
|
|
46209
|
-
this.inc('pre', identifier);
|
|
46210
|
-
break
|
|
46211
|
-
// If the input is a non-prerelease version, this acts the same as
|
|
46212
|
-
// prepatch.
|
|
46213
|
-
case 'prerelease':
|
|
46214
|
-
if (this.prerelease.length === 0) {
|
|
46215
|
-
this.inc('patch', identifier);
|
|
46216
|
-
}
|
|
46217
|
-
this.inc('pre', identifier);
|
|
46218
|
-
break
|
|
46219
|
-
|
|
46220
|
-
case 'major':
|
|
46221
|
-
// If this is a pre-major version, bump up to the same major version.
|
|
46222
|
-
// Otherwise increment major.
|
|
46223
|
-
// 1.0.0-5 bumps to 1.0.0
|
|
46224
|
-
// 1.1.0 bumps to 2.0.0
|
|
46225
|
-
if (
|
|
46226
|
-
this.minor !== 0 ||
|
|
46227
|
-
this.patch !== 0 ||
|
|
46228
|
-
this.prerelease.length === 0
|
|
46229
|
-
) {
|
|
46230
|
-
this.major++;
|
|
46231
|
-
}
|
|
46232
|
-
this.minor = 0;
|
|
46233
|
-
this.patch = 0;
|
|
46234
|
-
this.prerelease = [];
|
|
46235
|
-
break
|
|
46236
|
-
case 'minor':
|
|
46237
|
-
// If this is a pre-minor version, bump up to the same minor version.
|
|
46238
|
-
// Otherwise increment minor.
|
|
46239
|
-
// 1.2.0-5 bumps to 1.2.0
|
|
46240
|
-
// 1.2.1 bumps to 1.3.0
|
|
46241
|
-
if (this.patch !== 0 || this.prerelease.length === 0) {
|
|
46242
|
-
this.minor++;
|
|
46243
|
-
}
|
|
46244
|
-
this.patch = 0;
|
|
46245
|
-
this.prerelease = [];
|
|
46246
|
-
break
|
|
46247
|
-
case 'patch':
|
|
46248
|
-
// If this is not a pre-release version, it will increment the patch.
|
|
46249
|
-
// If it is a pre-release it will bump up to the same patch version.
|
|
46250
|
-
// 1.2.0-5 patches to 1.2.0
|
|
46251
|
-
// 1.2.0 patches to 1.2.1
|
|
46252
|
-
if (this.prerelease.length === 0) {
|
|
46253
|
-
this.patch++;
|
|
46254
|
-
}
|
|
46255
|
-
this.prerelease = [];
|
|
46256
|
-
break
|
|
46257
|
-
// This probably shouldn't be used publicly.
|
|
46258
|
-
// 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
|
|
46259
|
-
case 'pre':
|
|
46260
|
-
if (this.prerelease.length === 0) {
|
|
46261
|
-
this.prerelease = [0];
|
|
46262
|
-
} else {
|
|
46263
|
-
let i = this.prerelease.length;
|
|
46264
|
-
while (--i >= 0) {
|
|
46265
|
-
if (typeof this.prerelease[i] === 'number') {
|
|
46266
|
-
this.prerelease[i]++;
|
|
46267
|
-
i = -2;
|
|
45951
|
+
subscribeToCharacteristic({ characteristicName, manageNotifications = true }) {
|
|
45952
|
+
const data$ = defer(() => this.getCharacteristicByName(characteristicName)).pipe(switchMap((characteristic) => __awaiter$d(this, void 0, void 0, function* () {
|
|
45953
|
+
var _a;
|
|
45954
|
+
if (this.isConnected() && manageNotifications) {
|
|
45955
|
+
try {
|
|
45956
|
+
yield characteristic.startNotifications();
|
|
45957
|
+
this.addLog(`Started notifications for ${characteristicName} characteristic`);
|
|
45958
|
+
}
|
|
45959
|
+
catch (error) {
|
|
45960
|
+
this.addLog(`Attemped to stop notifications for ${characteristicName} characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
45961
|
+
}
|
|
46268
45962
|
}
|
|
46269
|
-
|
|
46270
|
-
|
|
46271
|
-
|
|
46272
|
-
|
|
46273
|
-
|
|
46274
|
-
|
|
46275
|
-
|
|
46276
|
-
|
|
46277
|
-
|
|
46278
|
-
|
|
46279
|
-
|
|
46280
|
-
|
|
45963
|
+
return characteristic;
|
|
45964
|
+
})), switchMap((characteristic) => {
|
|
45965
|
+
return fromDOMEvent(characteristic, "characteristicvaluechanged", () => __awaiter$d(this, void 0, void 0, function* () {
|
|
45966
|
+
var _a;
|
|
45967
|
+
if (this.isConnected() && manageNotifications) {
|
|
45968
|
+
try {
|
|
45969
|
+
yield characteristic.stopNotifications();
|
|
45970
|
+
this.addLog(`Stopped notifications for ${characteristicName} characteristic`);
|
|
45971
|
+
}
|
|
45972
|
+
catch (error) {
|
|
45973
|
+
this.addLog(`Attemped to stop notifications for ${characteristicName} characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
45974
|
+
}
|
|
45975
|
+
}
|
|
45976
|
+
}));
|
|
45977
|
+
}), map((event) => {
|
|
45978
|
+
const buffer$$1 = event.target.value;
|
|
45979
|
+
const decoded = decode$1(this.type, buffer$$1);
|
|
45980
|
+
this.addLog(`Received chunk with buffer size of ${buffer$$1.byteLength} and decoded size ${decoded.length} for ${characteristicName} characteristic: \n${decoded}`);
|
|
45981
|
+
return decoded;
|
|
45982
|
+
}), stitchChunks({ delimiter: BLUETOOTH_CHUNK_DELIMITER }), map((payload) => {
|
|
45983
|
+
var _a;
|
|
45984
|
+
try {
|
|
45985
|
+
return JSON.parse(payload);
|
|
46281
45986
|
}
|
|
46282
|
-
|
|
46283
|
-
|
|
46284
|
-
|
|
46285
|
-
|
|
46286
|
-
|
|
46287
|
-
|
|
46288
|
-
|
|
46289
|
-
|
|
45987
|
+
catch (error) {
|
|
45988
|
+
this.addLog(`Failed to parse JSON for ${characteristicName} characteristic. Falling back to unparsed string. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
45989
|
+
return payload;
|
|
45990
|
+
}
|
|
45991
|
+
})
|
|
45992
|
+
// when streaming at ultra-low latency, the logs will slow down rendering
|
|
45993
|
+
// tap((data) => {
|
|
45994
|
+
// this.addLog(
|
|
45995
|
+
// `Received data for ${characteristicName} characteristic: \n${JSON.stringify(
|
|
45996
|
+
// data,
|
|
45997
|
+
// null,
|
|
45998
|
+
// 2
|
|
45999
|
+
// )}`
|
|
46000
|
+
// );
|
|
46001
|
+
// })
|
|
46002
|
+
);
|
|
46003
|
+
return this.connection$.pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED ? data$ : NEVER));
|
|
46290
46004
|
}
|
|
46291
|
-
|
|
46292
|
-
|
|
46293
|
-
|
|
46294
|
-
|
|
46295
|
-
|
|
46296
|
-
|
|
46297
|
-
|
|
46298
|
-
|
|
46299
|
-
|
|
46300
|
-
|
|
46301
|
-
|
|
46302
|
-
|
|
46303
|
-
|
|
46304
|
-
|
|
46305
|
-
|
|
46306
|
-
|
|
46307
|
-
|
|
46308
|
-
|
|
46309
|
-
|
|
46005
|
+
readCharacteristic(characteristicName, parse = false) {
|
|
46006
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
46007
|
+
try {
|
|
46008
|
+
this.addLog(`Reading characteristic: ${characteristicName}`);
|
|
46009
|
+
const characteristic = yield this.getCharacteristicByName(characteristicName);
|
|
46010
|
+
if (!characteristic) {
|
|
46011
|
+
this.addLog(`Did not fund ${characteristicName} characteristic`);
|
|
46012
|
+
return Promise.reject(`Did not find characteristic by the name: ${characteristicName}`);
|
|
46013
|
+
}
|
|
46014
|
+
const value = yield characteristic.readValue();
|
|
46015
|
+
const uint8Array = value;
|
|
46016
|
+
const decodedValue = decode$1(this.type, uint8Array);
|
|
46017
|
+
const data = parse ? JSON.parse(decodedValue) : decodedValue;
|
|
46018
|
+
this.addLog(`Received read data from ${characteristicName} characteristic: \n${data}`);
|
|
46019
|
+
return data;
|
|
46020
|
+
}
|
|
46021
|
+
catch (error) {
|
|
46022
|
+
return Promise.reject(`Error reading characteristic: ${error.message}`);
|
|
46023
|
+
}
|
|
46024
|
+
});
|
|
46310
46025
|
}
|
|
46311
|
-
|
|
46312
|
-
|
|
46313
|
-
|
|
46314
|
-
|
|
46026
|
+
writeCharacteristic(characteristicName, data) {
|
|
46027
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
46028
|
+
this.addLog(`Writing characteristic: ${characteristicName}`);
|
|
46029
|
+
const characteristic = yield this.getCharacteristicByName(characteristicName);
|
|
46030
|
+
if (!characteristic) {
|
|
46031
|
+
this.addLog(`Did not fund ${characteristicName} characteristic`);
|
|
46032
|
+
return Promise.reject(`Did not find characteristic by the name: ${characteristicName}`);
|
|
46033
|
+
}
|
|
46034
|
+
const encoded = encode$1(this.type, data);
|
|
46035
|
+
yield characteristic.writeValueWithResponse(encoded);
|
|
46036
|
+
});
|
|
46315
46037
|
}
|
|
46316
|
-
|
|
46317
|
-
|
|
46318
|
-
|
|
46038
|
+
_addPendingAction(actionId) {
|
|
46039
|
+
const actions = this.pendingActions$.getValue();
|
|
46040
|
+
this.pendingActions$.next([...actions, actionId]);
|
|
46041
|
+
}
|
|
46042
|
+
_removePendingAction(actionId) {
|
|
46043
|
+
const actions = this.pendingActions$.getValue();
|
|
46044
|
+
this.pendingActions$.next(actions.filter((id) => id !== actionId));
|
|
46045
|
+
}
|
|
46046
|
+
_autoToggleActionNotifications() {
|
|
46047
|
+
let actionsCharacteristic;
|
|
46048
|
+
let started = false;
|
|
46049
|
+
return this.connection$.asObservable().pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED
|
|
46050
|
+
? defer(() => this.getCharacteristicByName("actions")).pipe(switchMap((characteristic) => {
|
|
46051
|
+
actionsCharacteristic = characteristic;
|
|
46052
|
+
return this.pendingActions$;
|
|
46053
|
+
}))
|
|
46054
|
+
: NEVER), tap((pendingActions) => __awaiter$d(this, void 0, void 0, function* () {
|
|
46055
|
+
var _a, _b;
|
|
46056
|
+
const hasPendingActions = !!pendingActions.length;
|
|
46057
|
+
if (hasPendingActions && !started) {
|
|
46058
|
+
started = true;
|
|
46059
|
+
try {
|
|
46060
|
+
yield actionsCharacteristic.startNotifications();
|
|
46061
|
+
this.addLog(`Started notifications for [actions] characteristic`);
|
|
46062
|
+
}
|
|
46063
|
+
catch (error) {
|
|
46064
|
+
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}`);
|
|
46065
|
+
}
|
|
46066
|
+
}
|
|
46067
|
+
if (!hasPendingActions && started) {
|
|
46068
|
+
started = false;
|
|
46069
|
+
try {
|
|
46070
|
+
yield actionsCharacteristic.stopNotifications();
|
|
46071
|
+
this.addLog(`Stopped notifications for actions characteristic`);
|
|
46072
|
+
}
|
|
46073
|
+
catch (error) {
|
|
46074
|
+
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}`);
|
|
46075
|
+
}
|
|
46076
|
+
}
|
|
46077
|
+
})));
|
|
46078
|
+
}
|
|
46079
|
+
dispatchAction({ characteristicName, action }) {
|
|
46080
|
+
return __awaiter$d(this, void 0, void 0, function* () {
|
|
46081
|
+
const { responseRequired = false, responseTimeout = DEFAULT_ACTION_RESPONSE_TIMEOUT } = action;
|
|
46082
|
+
return new Promise((resolve, reject) => __awaiter$d(this, void 0, void 0, function* () {
|
|
46083
|
+
const characteristic = yield this.getCharacteristicByName(characteristicName).catch(() => {
|
|
46084
|
+
reject(`Did not find characteristic by the name: ${characteristicName}`);
|
|
46085
|
+
});
|
|
46086
|
+
if (!characteristic) {
|
|
46087
|
+
return;
|
|
46088
|
+
}
|
|
46089
|
+
const actionId = create6DigitPin(); // use to later identify and filter response
|
|
46090
|
+
const payload = JSON.stringify(Object.assign({ actionId }, action)); // add the response id to the action
|
|
46091
|
+
this.addLog(`Dispatched action with id ${actionId}`);
|
|
46092
|
+
if (responseRequired && responseTimeout) {
|
|
46093
|
+
this._addPendingAction(actionId);
|
|
46094
|
+
const timeout$$1 = timer(responseTimeout).subscribe(() => {
|
|
46095
|
+
this._removePendingAction(actionId);
|
|
46096
|
+
reject(`Action with id ${actionId} timed out after ${responseTimeout}ms`);
|
|
46097
|
+
});
|
|
46098
|
+
// listen for a response before writing
|
|
46099
|
+
this.subscribeToCharacteristic({
|
|
46100
|
+
characteristicName,
|
|
46101
|
+
manageNotifications: false
|
|
46102
|
+
})
|
|
46103
|
+
.pipe(filter((response) => (response === null || response === void 0 ? void 0 : response.actionId) === actionId), take(1))
|
|
46104
|
+
.subscribe((response) => {
|
|
46105
|
+
timeout$$1.unsubscribe();
|
|
46106
|
+
this._removePendingAction(actionId);
|
|
46107
|
+
resolve(response);
|
|
46108
|
+
});
|
|
46109
|
+
// register action by writing
|
|
46110
|
+
this.writeCharacteristic(characteristicName, payload).catch((error) => {
|
|
46111
|
+
this._removePendingAction(actionId);
|
|
46112
|
+
reject(error.message);
|
|
46113
|
+
});
|
|
46114
|
+
}
|
|
46115
|
+
else {
|
|
46116
|
+
this.writeCharacteristic(characteristicName, payload)
|
|
46117
|
+
.then(() => {
|
|
46118
|
+
resolve(null);
|
|
46119
|
+
})
|
|
46120
|
+
.catch((error) => {
|
|
46121
|
+
reject(error.message);
|
|
46122
|
+
});
|
|
46123
|
+
}
|
|
46124
|
+
}));
|
|
46125
|
+
});
|
|
46319
46126
|
}
|
|
46320
|
-
|
|
46127
|
+
}
|
|
46128
|
+
function fromDOMEvent(target, eventName, beforeRemove) {
|
|
46129
|
+
return fromEventPattern((addHandler) => {
|
|
46130
|
+
target.addEventListener(eventName, addHandler);
|
|
46131
|
+
}, (removeHandler) => __awaiter$d(this, void 0, void 0, function* () {
|
|
46132
|
+
if (beforeRemove) {
|
|
46133
|
+
yield beforeRemove();
|
|
46134
|
+
}
|
|
46135
|
+
target.removeEventListener(eventName, removeHandler);
|
|
46136
|
+
}));
|
|
46137
|
+
}
|
|
46138
|
+
function onAdvertisementReceived(device) {
|
|
46139
|
+
return new Observable((subscriber) => {
|
|
46140
|
+
const abortController = new AbortController();
|
|
46141
|
+
const { signal } = abortController;
|
|
46142
|
+
const listener = device.addEventListener("advertisementreceived", (advertisement) => {
|
|
46143
|
+
abortController.abort();
|
|
46144
|
+
subscriber.next(advertisement);
|
|
46145
|
+
subscriber.complete();
|
|
46146
|
+
}, {
|
|
46147
|
+
once: true
|
|
46148
|
+
});
|
|
46149
|
+
try {
|
|
46150
|
+
device.watchAdvertisements({ signal });
|
|
46151
|
+
}
|
|
46152
|
+
catch (error) {
|
|
46153
|
+
subscriber.error(error);
|
|
46154
|
+
}
|
|
46155
|
+
return () => {
|
|
46156
|
+
abortController.abort();
|
|
46157
|
+
device.removeEventListener("advertisementreceived", listener);
|
|
46158
|
+
};
|
|
46159
|
+
});
|
|
46321
46160
|
}
|
|
46322
46161
|
|
|
46323
|
-
var __awaiter$
|
|
46162
|
+
var __awaiter$e = function (thisArg, _arguments, P, generator) {
|
|
46324
46163
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
46325
46164
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
46326
46165
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
@@ -46329,31 +46168,69 @@ var Neurosity = (function (exports) {
|
|
|
46329
46168
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
46330
46169
|
});
|
|
46331
46170
|
};
|
|
46332
|
-
const defaultOptions$
|
|
46171
|
+
const defaultOptions$2 = {
|
|
46333
46172
|
autoConnect: true
|
|
46334
46173
|
};
|
|
46335
|
-
class
|
|
46336
|
-
constructor(options
|
|
46337
|
-
this.type = exports.TRANSPORT_TYPE.
|
|
46174
|
+
class ReactNativeTransport {
|
|
46175
|
+
constructor(options) {
|
|
46176
|
+
this.type = exports.TRANSPORT_TYPE.REACT_NATIVE;
|
|
46338
46177
|
this.characteristicsByName = {};
|
|
46339
46178
|
this.connection$ = new BehaviorSubject(exports.BLUETOOTH_CONNECTION.DISCONNECTED);
|
|
46340
46179
|
this.pendingActions$ = new BehaviorSubject([]);
|
|
46341
46180
|
this.logs$ = new ReplaySubject(10);
|
|
46342
|
-
this.onDisconnected$ = this._onDisconnected().pipe(share());
|
|
46343
46181
|
this.connectionStream$ = this.connection$
|
|
46344
46182
|
.asObservable()
|
|
46345
46183
|
.pipe(filter((connection) => !!connection), distinctUntilChanged(), shareReplay(1));
|
|
46346
46184
|
this._isAutoConnectEnabled$ = new ReplaySubject(1);
|
|
46347
|
-
|
|
46348
|
-
|
|
46349
|
-
|
|
46185
|
+
if (!options) {
|
|
46186
|
+
const errorMessage = "React Native transport: missing options.";
|
|
46187
|
+
this.addLog(errorMessage);
|
|
46188
|
+
throw new Error(errorMessage);
|
|
46189
|
+
}
|
|
46190
|
+
this.options = Object.assign(Object.assign({}, defaultOptions$2), options);
|
|
46191
|
+
const { BleManager, bleManagerEmitter, platform, autoConnect } = this.options;
|
|
46192
|
+
if (!BleManager) {
|
|
46193
|
+
const errorMessage = "React Native option: BleManager not provided.";
|
|
46194
|
+
this.addLog(errorMessage);
|
|
46195
|
+
throw new Error(errorMessage);
|
|
46196
|
+
}
|
|
46197
|
+
if (!bleManagerEmitter) {
|
|
46198
|
+
const errorMessage = "React Native option: bleManagerEmitter not provided.";
|
|
46350
46199
|
this.addLog(errorMessage);
|
|
46351
46200
|
throw new Error(errorMessage);
|
|
46352
46201
|
}
|
|
46202
|
+
if (!platform) {
|
|
46203
|
+
const errorMessage = "React Native option: platform not provided.";
|
|
46204
|
+
this.addLog(errorMessage);
|
|
46205
|
+
throw new Error(errorMessage);
|
|
46206
|
+
}
|
|
46207
|
+
this.BleManager = BleManager;
|
|
46208
|
+
this.bleManagerEmitter = bleManagerEmitter;
|
|
46209
|
+
this.platform = platform;
|
|
46210
|
+
this._isAutoConnectEnabled$.next(autoConnect);
|
|
46353
46211
|
this._isAutoConnectEnabled$.subscribe((autoConnect) => {
|
|
46354
46212
|
this.addLog(`Auto connect: ${autoConnect ? "enabled" : "disabled"}`);
|
|
46355
46213
|
});
|
|
46356
|
-
|
|
46214
|
+
// We create a single listener per event type to
|
|
46215
|
+
// avoid missing events when multiple listeners are attached.
|
|
46216
|
+
this.bleEvents = {
|
|
46217
|
+
stopScan$: this._fromEvent("BleManagerStopScan"),
|
|
46218
|
+
discoverPeripheral$: this._fromEvent("BleManagerDiscoverPeripheral"),
|
|
46219
|
+
connectPeripheral$: this._fromEvent("BleManagerConnectPeripheral"),
|
|
46220
|
+
disconnectPeripheral$: this._fromEvent("BleManagerDisconnectPeripheral"),
|
|
46221
|
+
didUpdateValueForCharacteristic$: this._fromEvent("BleManagerDidUpdateValueForCharacteristic"),
|
|
46222
|
+
didUpdateState$: this._fromEvent("BleManagerDidUpdateState")
|
|
46223
|
+
};
|
|
46224
|
+
this.onDisconnected$ = this.bleEvents.disconnectPeripheral$.pipe(share());
|
|
46225
|
+
// Initializes the module. This can only be called once.
|
|
46226
|
+
this.BleManager.start({ showAlert: false })
|
|
46227
|
+
.then(() => {
|
|
46228
|
+
this.addLog(`BleManger started`);
|
|
46229
|
+
})
|
|
46230
|
+
.catch((error) => {
|
|
46231
|
+
var _a;
|
|
46232
|
+
this.addLog(`BleManger failed to start. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46233
|
+
});
|
|
46357
46234
|
this.connection$.asObservable().subscribe((connection) => {
|
|
46358
46235
|
this.addLog(`connection status is ${connection}`);
|
|
46359
46236
|
});
|
|
@@ -46361,191 +46238,191 @@ var Neurosity = (function (exports) {
|
|
|
46361
46238
|
this.connection$.next(exports.BLUETOOTH_CONNECTION.DISCONNECTED);
|
|
46362
46239
|
});
|
|
46363
46240
|
}
|
|
46364
|
-
|
|
46365
|
-
|
|
46366
|
-
|
|
46367
|
-
|
|
46241
|
+
addLog(log) {
|
|
46242
|
+
this.logs$.next(log);
|
|
46243
|
+
}
|
|
46244
|
+
isConnected() {
|
|
46245
|
+
const connection = this.connection$.getValue();
|
|
46246
|
+
return connection === exports.BLUETOOTH_CONNECTION.CONNECTED;
|
|
46368
46247
|
}
|
|
46369
46248
|
_autoConnect(selectedDevice$) {
|
|
46249
|
+
const selectedDeviceAfterDisconnect$ = this.onDisconnected$.pipe(switchMap(() => selectedDevice$));
|
|
46370
46250
|
return this._isAutoConnectEnabled$.pipe(switchMap((isAutoConnectEnabled) => isAutoConnectEnabled
|
|
46371
|
-
? merge(selectedDevice$,
|
|
46372
|
-
: NEVER), switchMap((selectedDevice) =>
|
|
46373
|
-
|
|
46374
|
-
|
|
46375
|
-
|
|
46376
|
-
|
|
46377
|
-
return;
|
|
46378
|
-
}
|
|
46379
|
-
const [devicesError, devices] = yield this._getPairedDevices()
|
|
46380
|
-
.then((devices) => [null, devices])
|
|
46381
|
-
.catch((error) => [error, null]);
|
|
46382
|
-
if (devicesError) {
|
|
46383
|
-
throw new Error(`failed to get devices: ${(_a = devicesError === null || devicesError === void 0 ? void 0 : devicesError.message) !== null && _a !== void 0 ? _a : devicesError}`);
|
|
46384
|
-
}
|
|
46385
|
-
this.addLog(`Auto connect: found ${devices.length} devices ${devices
|
|
46386
|
-
.map(({ name }) => name)
|
|
46387
|
-
.join(", ")}`);
|
|
46388
|
-
// @important - Using `findLast` instead of `find` because somehow the browser
|
|
46389
|
-
// is finding multiple peripherals with the same name
|
|
46390
|
-
const device = devices.findLast((device) => device.name === deviceNickname);
|
|
46391
|
-
if (!device) {
|
|
46392
|
-
throw new Error(`couldn't find selected device in the list of paired devices.`);
|
|
46393
|
-
}
|
|
46394
|
-
this.addLog(`Auto connect: ${deviceNickname} was detected and previously paired`);
|
|
46395
|
-
return device;
|
|
46396
|
-
})), tap(() => {
|
|
46397
|
-
this.connection$.next(exports.BLUETOOTH_CONNECTION.SCANNING);
|
|
46398
|
-
}), switchMap((device) => onAdvertisementReceived(device)), switchMap((advertisement) => __awaiter$d(this, void 0, void 0, function* () {
|
|
46399
|
-
this.addLog(`Advertisement received for ${advertisement.device.name}`);
|
|
46400
|
-
return yield this.getServerServiceAndCharacteristics(advertisement.device);
|
|
46251
|
+
? merge(selectedDevice$, selectedDeviceAfterDisconnect$)
|
|
46252
|
+
: NEVER), switchMap((selectedDevice) => this.scan().pipe(switchMap((peripherals) => {
|
|
46253
|
+
const peripheralMatch = peripherals.find((peripheral) => peripheral.name === (selectedDevice === null || selectedDevice === void 0 ? void 0 : selectedDevice.deviceNickname));
|
|
46254
|
+
return peripheralMatch ? of(peripheralMatch) : NEVER;
|
|
46255
|
+
}), distinct((peripheral) => peripheral.id), take(1))), switchMap((peripheral) => __awaiter$e(this, void 0, void 0, function* () {
|
|
46256
|
+
return yield this.connect(peripheral);
|
|
46401
46257
|
})));
|
|
46402
46258
|
}
|
|
46403
46259
|
enableAutoConnect(autoConnect) {
|
|
46404
46260
|
this._isAutoConnectEnabled$.next(autoConnect);
|
|
46405
46261
|
}
|
|
46406
|
-
addLog(log) {
|
|
46407
|
-
this.logs$.next(log);
|
|
46408
|
-
}
|
|
46409
|
-
isConnected() {
|
|
46410
|
-
const connection = this.connection$.getValue();
|
|
46411
|
-
return connection === exports.BLUETOOTH_CONNECTION.CONNECTED;
|
|
46412
|
-
}
|
|
46413
46262
|
connection() {
|
|
46414
46263
|
return this.connectionStream$;
|
|
46415
46264
|
}
|
|
46416
|
-
|
|
46417
|
-
return
|
|
46418
|
-
|
|
46419
|
-
|
|
46420
|
-
|
|
46421
|
-
|
|
46422
|
-
|
|
46423
|
-
|
|
46424
|
-
|
|
46425
|
-
}
|
|
46426
|
-
});
|
|
46265
|
+
_fromEvent(eventName) {
|
|
46266
|
+
return fromEventPattern((addHandler) => {
|
|
46267
|
+
this.bleManagerEmitter.addListener(eventName, addHandler);
|
|
46268
|
+
}, () => {
|
|
46269
|
+
this.bleManagerEmitter.removeAllListeners(eventName);
|
|
46270
|
+
}).pipe(
|
|
46271
|
+
// @important: we need to share the subscription
|
|
46272
|
+
// to avoid missing events
|
|
46273
|
+
share());
|
|
46427
46274
|
}
|
|
46428
|
-
|
|
46429
|
-
|
|
46275
|
+
scan(options) {
|
|
46276
|
+
var _a, _b, _c;
|
|
46277
|
+
const RESCAN_INTERVAL = 10000; // 10 seconds
|
|
46278
|
+
const seconds = (_a = options === null || options === void 0 ? void 0 : options.seconds) !== null && _a !== void 0 ? _a : RESCAN_INTERVAL / 1000;
|
|
46279
|
+
const once = (_b = options === null || options === void 0 ? void 0 : options.once) !== null && _b !== void 0 ? _b : false;
|
|
46280
|
+
// If we are already connected to a peripheral and start scanning,
|
|
46281
|
+
// be default, it will set the connection status to SCANNING and not
|
|
46282
|
+
// update it back if no device is connected to
|
|
46283
|
+
const skipConnectionUpdate = (_c = options === null || options === void 0 ? void 0 : options.skipConnectionUpdate) !== null && _c !== void 0 ? _c : false;
|
|
46284
|
+
const serviceUUIDs = [BLUETOOTH_PRIMARY_SERVICE_UUID_STRING];
|
|
46285
|
+
const allowDuplicates = true;
|
|
46286
|
+
const scanOptions = {};
|
|
46287
|
+
const scanOnce$ = new Observable((subscriber) => {
|
|
46288
|
+
var _a;
|
|
46430
46289
|
try {
|
|
46431
|
-
this.
|
|
46432
|
-
|
|
46433
|
-
|
|
46434
|
-
}));
|
|
46435
|
-
// Ability to only show selectedDevice if provided
|
|
46436
|
-
const filters = deviceNickname
|
|
46437
|
-
? [
|
|
46438
|
-
{
|
|
46439
|
-
name: deviceNickname
|
|
46440
|
-
}
|
|
46441
|
-
]
|
|
46442
|
-
: prefixes;
|
|
46443
|
-
const device = yield window.navigator.bluetooth.requestDevice({
|
|
46444
|
-
filters: [
|
|
46445
|
-
...filters,
|
|
46446
|
-
{
|
|
46447
|
-
manufacturerData: [
|
|
46448
|
-
{
|
|
46449
|
-
companyIdentifier: BLUETOOTH_COMPANY_IDENTIFIER_HEX
|
|
46450
|
-
}
|
|
46451
|
-
]
|
|
46452
|
-
}
|
|
46453
|
-
],
|
|
46454
|
-
optionalServices: [BLUETOOTH_PRIMARY_SERVICE_UUID_HEX]
|
|
46290
|
+
this.BleManager.scan(serviceUUIDs, seconds, allowDuplicates, scanOptions).then(() => {
|
|
46291
|
+
this.addLog(`BleManger scanning ${once ? "once" : "indefintely"}`);
|
|
46292
|
+
subscriber.next();
|
|
46455
46293
|
});
|
|
46456
|
-
return device;
|
|
46457
46294
|
}
|
|
46458
46295
|
catch (error) {
|
|
46459
|
-
|
|
46296
|
+
this.addLog(`BleManger scanning ${once ? "once" : "indefintely"} failed. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46297
|
+
subscriber.error(error);
|
|
46460
46298
|
}
|
|
46299
|
+
return () => {
|
|
46300
|
+
this.BleManager.stopScan();
|
|
46301
|
+
};
|
|
46461
46302
|
});
|
|
46303
|
+
const scan$ = once
|
|
46304
|
+
? scanOnce$
|
|
46305
|
+
: timer(0, RESCAN_INTERVAL).pipe(switchMap(() => scanOnce$));
|
|
46306
|
+
const peripherals$ = scan$.pipe(tap(() => {
|
|
46307
|
+
if (!skipConnectionUpdate) {
|
|
46308
|
+
this.connection$.next(exports.BLUETOOTH_CONNECTION.SCANNING);
|
|
46309
|
+
}
|
|
46310
|
+
}), takeUntil(this.onDisconnected$), switchMap(() => this.bleEvents.discoverPeripheral$),
|
|
46311
|
+
// Filter out devices that are not Neurosity devices
|
|
46312
|
+
filter((peripheral) => {
|
|
46313
|
+
var _a, _b, _c;
|
|
46314
|
+
const peripheralName = (_c = (_b = (_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertising) === null || _a === void 0 ? void 0 : _a.localName) !== null && _b !== void 0 ? _b : peripheral.name) !== null && _c !== void 0 ? _c : "";
|
|
46315
|
+
if (!peripheralName) {
|
|
46316
|
+
return false;
|
|
46317
|
+
}
|
|
46318
|
+
const startsWithPrefix = BLUETOOTH_DEVICE_NAME_PREFIXES.findIndex((prefix) => peripheralName.startsWith(prefix)) !== -1;
|
|
46319
|
+
return startsWithPrefix;
|
|
46320
|
+
}), scan((acc, peripheral) => {
|
|
46321
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
46322
|
+
// normalized peripheral name for backwards compatibility
|
|
46323
|
+
// Neurosity OS v15 doesn't have peripheral.name as deviceNickname
|
|
46324
|
+
// it only has peripheral.advertising.localName as deviceNickname
|
|
46325
|
+
// and OS v16 has both as deviceNickname
|
|
46326
|
+
const peripheralName = (_c = (_b = (_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertising) === null || _a === void 0 ? void 0 : _a.localName) !== null && _b !== void 0 ? _b : peripheral.name) !== null && _c !== void 0 ? _c : "";
|
|
46327
|
+
const manufactureDataString = (_h = (_g = decode$1(this.type, (_f = (_e = (_d = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertising) === null || _d === void 0 ? void 0 : _d.manufacturerData) === null || _e === void 0 ? void 0 : _e.bytes) !== null && _f !== void 0 ? _f : [])) === null || _g === void 0 ? void 0 : _g.slice) === null || _h === void 0 ? void 0 : _h.call(_g, 2); // First 2 bytes are reserved for the Neurosity company code
|
|
46328
|
+
return Object.assign(Object.assign({}, acc), { [peripheral.id]: Object.assign(Object.assign({}, peripheral), { name: peripheralName, manufactureDataString }) });
|
|
46329
|
+
}, {}), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), map((peripheralMap) => Object.values(peripheralMap)), share());
|
|
46330
|
+
return peripherals$;
|
|
46462
46331
|
}
|
|
46463
|
-
|
|
46464
|
-
return __awaiter$
|
|
46465
|
-
|
|
46466
|
-
|
|
46467
|
-
|
|
46468
|
-
|
|
46332
|
+
connect(peripheral) {
|
|
46333
|
+
return __awaiter$e(this, void 0, void 0, function* () {
|
|
46334
|
+
return new Promise((resolve, reject) => __awaiter$e(this, void 0, void 0, function* () {
|
|
46335
|
+
try {
|
|
46336
|
+
if (!peripheral) {
|
|
46337
|
+
this.addLog("Peripheral not found");
|
|
46338
|
+
return;
|
|
46339
|
+
}
|
|
46469
46340
|
this.connection$.next(exports.BLUETOOTH_CONNECTION.CONNECTING);
|
|
46341
|
+
yield this.BleManager.connect(peripheral.id);
|
|
46342
|
+
this.addLog(`Getting service...`);
|
|
46343
|
+
const peripheralInfo = yield this.BleManager.retrieveServices(peripheral.id, [
|
|
46344
|
+
BLUETOOTH_PRIMARY_SERVICE_UUID_STRING
|
|
46345
|
+
]);
|
|
46346
|
+
if (!peripheralInfo) {
|
|
46347
|
+
this.addLog("Could not retreive services");
|
|
46348
|
+
reject(new Error(`Could not retreive services`));
|
|
46349
|
+
return;
|
|
46350
|
+
}
|
|
46351
|
+
this.addLog(`Got service ${BLUETOOTH_PRIMARY_SERVICE_UUID_STRING}, getting characteristics...`);
|
|
46352
|
+
this.device = peripheral;
|
|
46353
|
+
this.characteristicsByName = Object.fromEntries(peripheralInfo.characteristics.map((characteristic) => [
|
|
46354
|
+
CHARACTERISTIC_UUIDS_TO_NAMES[characteristic.characteristic.toLowerCase() // react native uses uppercase
|
|
46355
|
+
],
|
|
46356
|
+
{
|
|
46357
|
+
characteristicUUID: characteristic.characteristic,
|
|
46358
|
+
serviceUUID: characteristic.service,
|
|
46359
|
+
peripheralId: peripheral.id
|
|
46360
|
+
}
|
|
46361
|
+
]));
|
|
46362
|
+
this.addLog(`Got characteristics.`);
|
|
46363
|
+
if (this.platform === "android") {
|
|
46364
|
+
yield this.BleManager.requestMTU(peripheral.id, ANDROID_MAX_MTU)
|
|
46365
|
+
.then((updatedMTU) => {
|
|
46366
|
+
this.addLog(`Successfully updated Android MTU to ${updatedMTU} bytes. Requested MTU: ${ANDROID_MAX_MTU} bytes.`);
|
|
46367
|
+
})
|
|
46368
|
+
.catch((error) => {
|
|
46369
|
+
this.addLog(`Failed to set Android MTU of ${ANDROID_MAX_MTU} bytes. Error: ${error}`);
|
|
46370
|
+
});
|
|
46371
|
+
}
|
|
46372
|
+
this.addLog(`Successfully connected to peripheral ${peripheral.id}`);
|
|
46373
|
+
this.connection$.next(exports.BLUETOOTH_CONNECTION.CONNECTED);
|
|
46374
|
+
resolve();
|
|
46470
46375
|
}
|
|
46471
|
-
|
|
46472
|
-
|
|
46473
|
-
|
|
46474
|
-
|
|
46475
|
-
const characteristicsList = yield this.service.getCharacteristics();
|
|
46476
|
-
this.addLog(`Got characteristics`);
|
|
46477
|
-
this.characteristicsByName = Object.fromEntries(characteristicsList.map((characteristic) => [
|
|
46478
|
-
CHARACTERISTIC_UUIDS_TO_NAMES[characteristic.uuid],
|
|
46479
|
-
characteristic
|
|
46480
|
-
]));
|
|
46481
|
-
this.connection$.next(exports.BLUETOOTH_CONNECTION.CONNECTED);
|
|
46482
|
-
}
|
|
46483
|
-
catch (error) {
|
|
46484
|
-
return Promise.reject(error);
|
|
46485
|
-
}
|
|
46376
|
+
catch (error) {
|
|
46377
|
+
reject(error);
|
|
46378
|
+
}
|
|
46379
|
+
}));
|
|
46486
46380
|
});
|
|
46487
46381
|
}
|
|
46488
|
-
_onDisconnected() {
|
|
46489
|
-
return this.connection$
|
|
46490
|
-
.asObservable()
|
|
46491
|
-
.pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED
|
|
46492
|
-
? fromDOMEvent(this.device, "gattserverdisconnected")
|
|
46493
|
-
: NEVER));
|
|
46494
|
-
}
|
|
46495
46382
|
disconnect() {
|
|
46496
|
-
var _a
|
|
46497
|
-
return __awaiter$
|
|
46498
|
-
|
|
46499
|
-
|
|
46500
|
-
|
|
46383
|
+
var _a;
|
|
46384
|
+
return __awaiter$e(this, void 0, void 0, function* () {
|
|
46385
|
+
try {
|
|
46386
|
+
if (this.isConnected() && ((_a = this === null || this === void 0 ? void 0 : this.device) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
46387
|
+
yield this.BleManager.disconnect(this.device.id);
|
|
46388
|
+
}
|
|
46389
|
+
}
|
|
46390
|
+
catch (error) {
|
|
46391
|
+
return Promise.reject(error);
|
|
46501
46392
|
}
|
|
46502
46393
|
});
|
|
46503
46394
|
}
|
|
46504
|
-
/**
|
|
46505
|
-
*
|
|
46506
|
-
* Bluetooth GATT attributes, services, characteristics, etc. are invalidated
|
|
46507
|
-
* when a device disconnects. This means your code should always retrieve
|
|
46508
|
-
* (through getPrimaryService(s), getCharacteristic(s), etc.) these attributes
|
|
46509
|
-
* after reconnecting.
|
|
46510
|
-
*/
|
|
46511
46395
|
getCharacteristicByName(characteristicName) {
|
|
46512
46396
|
var _a;
|
|
46513
|
-
|
|
46514
|
-
|
|
46515
|
-
}
|
|
46397
|
+
if (!(characteristicName in this.characteristicsByName)) {
|
|
46398
|
+
throw new Error(`Characteristic by name ${characteristicName} is not found`);
|
|
46399
|
+
}
|
|
46400
|
+
return (_a = this.characteristicsByName) === null || _a === void 0 ? void 0 : _a[characteristicName];
|
|
46516
46401
|
}
|
|
46517
46402
|
subscribeToCharacteristic({ characteristicName, manageNotifications = true }) {
|
|
46518
|
-
const
|
|
46403
|
+
const getData = ({ peripheralId, serviceUUID, characteristicUUID }) => defer(() => __awaiter$e(this, void 0, void 0, function* () {
|
|
46519
46404
|
var _a;
|
|
46520
|
-
if (
|
|
46405
|
+
if (manageNotifications) {
|
|
46521
46406
|
try {
|
|
46522
|
-
yield
|
|
46407
|
+
yield this.BleManager.startNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
46523
46408
|
this.addLog(`Started notifications for ${characteristicName} characteristic`);
|
|
46524
46409
|
}
|
|
46525
46410
|
catch (error) {
|
|
46526
46411
|
this.addLog(`Attemped to stop notifications for ${characteristicName} characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46527
46412
|
}
|
|
46528
46413
|
}
|
|
46529
|
-
|
|
46530
|
-
|
|
46531
|
-
|
|
46532
|
-
|
|
46533
|
-
|
|
46534
|
-
|
|
46535
|
-
yield characteristic.stopNotifications();
|
|
46536
|
-
this.addLog(`Stopped notifications for ${characteristicName} characteristic`);
|
|
46537
|
-
}
|
|
46538
|
-
catch (error) {
|
|
46539
|
-
this.addLog(`Attemped to stop notifications for ${characteristicName} characteristic: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46540
|
-
}
|
|
46414
|
+
})).pipe(switchMap(() => this.bleEvents.didUpdateValueForCharacteristic$), finalize(() => __awaiter$e(this, void 0, void 0, function* () {
|
|
46415
|
+
var _b;
|
|
46416
|
+
if (manageNotifications) {
|
|
46417
|
+
try {
|
|
46418
|
+
yield this.BleManager.stopNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
46419
|
+
this.addLog(`Stopped notifications for ${characteristicName} characteristic`);
|
|
46541
46420
|
}
|
|
46542
|
-
|
|
46543
|
-
|
|
46544
|
-
|
|
46545
|
-
|
|
46546
|
-
|
|
46547
|
-
return decoded;
|
|
46548
|
-
}), stitchChunks({ delimiter: BLUETOOTH_CHUNK_DELIMITER }), map((payload) => {
|
|
46421
|
+
catch (error) {
|
|
46422
|
+
this.addLog(`Attemped to stop notifications for ${characteristicName} characteristic: ${(_b = error === null || error === void 0 ? void 0 : error.message) !== null && _b !== void 0 ? _b : error}`);
|
|
46423
|
+
}
|
|
46424
|
+
}
|
|
46425
|
+
})), filter(({ characteristic }) => characteristic === characteristicUUID), map(({ value }) => decode$1(this.type, value)), stitchChunks({ delimiter: BLUETOOTH_CHUNK_DELIMITER }), map((payload) => {
|
|
46549
46426
|
var _a;
|
|
46550
46427
|
try {
|
|
46551
46428
|
return JSON.parse(payload);
|
|
@@ -46554,51 +46431,40 @@ var Neurosity = (function (exports) {
|
|
|
46554
46431
|
this.addLog(`Failed to parse JSON for ${characteristicName} characteristic. Falling back to unparsed string. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46555
46432
|
return payload;
|
|
46556
46433
|
}
|
|
46557
|
-
})
|
|
46558
|
-
|
|
46559
|
-
|
|
46560
|
-
|
|
46561
|
-
// `Received data for ${characteristicName} characteristic: \n${JSON.stringify(
|
|
46562
|
-
// data,
|
|
46563
|
-
// null,
|
|
46564
|
-
// 2
|
|
46565
|
-
// )}`
|
|
46566
|
-
// );
|
|
46567
|
-
// })
|
|
46568
|
-
);
|
|
46569
|
-
return this.connection$.pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED ? data$ : NEVER));
|
|
46434
|
+
}));
|
|
46435
|
+
return this.connection$.pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED
|
|
46436
|
+
? getData(this.getCharacteristicByName(characteristicName))
|
|
46437
|
+
: NEVER));
|
|
46570
46438
|
}
|
|
46571
46439
|
readCharacteristic(characteristicName, parse = false) {
|
|
46572
|
-
|
|
46440
|
+
var _a;
|
|
46441
|
+
return __awaiter$e(this, void 0, void 0, function* () {
|
|
46442
|
+
this.addLog(`Reading characteristic: ${characteristicName}`);
|
|
46443
|
+
const { peripheralId, serviceUUID, characteristicUUID } = this.getCharacteristicByName(characteristicName);
|
|
46444
|
+
if (!characteristicUUID) {
|
|
46445
|
+
return Promise.reject(new Error(`Did not find characteristic matching ${characteristicName}`));
|
|
46446
|
+
}
|
|
46573
46447
|
try {
|
|
46574
|
-
this.
|
|
46575
|
-
const
|
|
46576
|
-
if (!characteristic) {
|
|
46577
|
-
this.addLog(`Did not fund ${characteristicName} characteristic`);
|
|
46578
|
-
return Promise.reject(`Did not find characteristic by the name: ${characteristicName}`);
|
|
46579
|
-
}
|
|
46580
|
-
const value = yield characteristic.readValue();
|
|
46581
|
-
const uint8Array = value;
|
|
46582
|
-
const decodedValue = decode$1(this.type, uint8Array);
|
|
46448
|
+
const value = yield this.BleManager.read(peripheralId, serviceUUID, characteristicUUID);
|
|
46449
|
+
const decodedValue = decode$1(this.type, value);
|
|
46583
46450
|
const data = parse ? JSON.parse(decodedValue) : decodedValue;
|
|
46584
46451
|
this.addLog(`Received read data from ${characteristicName} characteristic: \n${data}`);
|
|
46585
46452
|
return data;
|
|
46586
46453
|
}
|
|
46587
46454
|
catch (error) {
|
|
46588
|
-
return Promise.reject(`
|
|
46455
|
+
return Promise.reject(new Error(`readCharacteristic ${characteristicName} error. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`));
|
|
46589
46456
|
}
|
|
46590
46457
|
});
|
|
46591
46458
|
}
|
|
46592
46459
|
writeCharacteristic(characteristicName, data) {
|
|
46593
|
-
return __awaiter$
|
|
46460
|
+
return __awaiter$e(this, void 0, void 0, function* () {
|
|
46594
46461
|
this.addLog(`Writing characteristic: ${characteristicName}`);
|
|
46595
|
-
const
|
|
46596
|
-
if (!
|
|
46597
|
-
|
|
46598
|
-
return Promise.reject(`Did not find characteristic by the name: ${characteristicName}`);
|
|
46462
|
+
const { peripheralId, serviceUUID, characteristicUUID } = this.getCharacteristicByName(characteristicName);
|
|
46463
|
+
if (!characteristicUUID) {
|
|
46464
|
+
return Promise.reject(new Error(`Did not find characteristic matching ${characteristicName}`));
|
|
46599
46465
|
}
|
|
46600
46466
|
const encoded = encode$1(this.type, data);
|
|
46601
|
-
yield
|
|
46467
|
+
yield this.BleManager.write(peripheralId, serviceUUID, characteristicUUID, encoded, REACT_NATIVE_MAX_BYTE_SIZE);
|
|
46602
46468
|
});
|
|
46603
46469
|
}
|
|
46604
46470
|
_addPendingAction(actionId) {
|
|
@@ -46609,54 +46475,40 @@ var Neurosity = (function (exports) {
|
|
|
46609
46475
|
const actions = this.pendingActions$.getValue();
|
|
46610
46476
|
this.pendingActions$.next(actions.filter((id) => id !== actionId));
|
|
46611
46477
|
}
|
|
46612
|
-
_autoToggleActionNotifications(
|
|
46613
|
-
|
|
46614
|
-
|
|
46615
|
-
|
|
46616
|
-
|
|
46617
|
-
|
|
46618
|
-
|
|
46619
|
-
|
|
46620
|
-
|
|
46621
|
-
|
|
46622
|
-
|
|
46623
|
-
|
|
46624
|
-
|
|
46625
|
-
started = true;
|
|
46626
|
-
try {
|
|
46627
|
-
yield actionsCharacteristic.startNotifications();
|
|
46628
|
-
this.addLog(`Started notifications for [actions] characteristic`);
|
|
46629
|
-
}
|
|
46630
|
-
catch (error) {
|
|
46631
|
-
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}`);
|
|
46632
|
-
}
|
|
46478
|
+
_autoToggleActionNotifications() {
|
|
46479
|
+
let started = false;
|
|
46480
|
+
return this.connection$.asObservable().pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED
|
|
46481
|
+
? this.pendingActions$
|
|
46482
|
+
: NEVER), tap((pendingActions) => __awaiter$e(this, void 0, void 0, function* () {
|
|
46483
|
+
var _a, _b;
|
|
46484
|
+
const { peripheralId, serviceUUID, characteristicUUID } = this.getCharacteristicByName("actions");
|
|
46485
|
+
const hasPendingActions = !!pendingActions.length;
|
|
46486
|
+
if (hasPendingActions && !started) {
|
|
46487
|
+
started = true;
|
|
46488
|
+
try {
|
|
46489
|
+
yield this.BleManager.startNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
46490
|
+
this.addLog(`Started notifications for [actions] characteristic`);
|
|
46633
46491
|
}
|
|
46634
|
-
|
|
46635
|
-
|
|
46636
|
-
try {
|
|
46637
|
-
yield actionsCharacteristic.stopNotifications();
|
|
46638
|
-
this.addLog(`Stopped notifications for actions characteristic`);
|
|
46639
|
-
}
|
|
46640
|
-
catch (error) {
|
|
46641
|
-
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}`);
|
|
46642
|
-
}
|
|
46492
|
+
catch (error) {
|
|
46493
|
+
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}`);
|
|
46643
46494
|
}
|
|
46644
|
-
}
|
|
46645
|
-
|
|
46646
|
-
|
|
46647
|
-
|
|
46648
|
-
|
|
46495
|
+
}
|
|
46496
|
+
if (!hasPendingActions && started) {
|
|
46497
|
+
started = false;
|
|
46498
|
+
try {
|
|
46499
|
+
yield this.BleManager.stopNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
46500
|
+
this.addLog(`Stopped notifications for actions characteristic`);
|
|
46501
|
+
}
|
|
46502
|
+
catch (error) {
|
|
46503
|
+
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}`);
|
|
46504
|
+
}
|
|
46505
|
+
}
|
|
46506
|
+
})));
|
|
46649
46507
|
}
|
|
46650
46508
|
dispatchAction({ characteristicName, action }) {
|
|
46651
|
-
return __awaiter$
|
|
46509
|
+
return __awaiter$e(this, void 0, void 0, function* () {
|
|
46652
46510
|
const { responseRequired = false, responseTimeout = DEFAULT_ACTION_RESPONSE_TIMEOUT } = action;
|
|
46653
|
-
return new Promise((resolve, reject) => __awaiter$
|
|
46654
|
-
const characteristic = yield this.getCharacteristicByName(characteristicName).catch(() => {
|
|
46655
|
-
reject(`Did not find characteristic by the name: ${characteristicName}`);
|
|
46656
|
-
});
|
|
46657
|
-
if (!characteristic) {
|
|
46658
|
-
return;
|
|
46659
|
-
}
|
|
46511
|
+
return new Promise((resolve, reject) => __awaiter$e(this, void 0, void 0, function* () {
|
|
46660
46512
|
const actionId = create6DigitPin(); // use to later identify and filter response
|
|
46661
46513
|
const payload = JSON.stringify(Object.assign({ actionId }, action)); // add the response id to the action
|
|
46662
46514
|
this.addLog(`Dispatched action with id ${actionId}`);
|
|
@@ -46664,7 +46516,7 @@ var Neurosity = (function (exports) {
|
|
|
46664
46516
|
this._addPendingAction(actionId);
|
|
46665
46517
|
const timeout$$1 = timer(responseTimeout).subscribe(() => {
|
|
46666
46518
|
this._removePendingAction(actionId);
|
|
46667
|
-
reject(`Action with id ${actionId} timed out after ${responseTimeout}ms`);
|
|
46519
|
+
reject(new Error(`Action with id ${actionId} timed out after ${responseTimeout}ms`));
|
|
46668
46520
|
});
|
|
46669
46521
|
// listen for a response before writing
|
|
46670
46522
|
this.subscribeToCharacteristic({
|
|
@@ -46680,7 +46532,7 @@ var Neurosity = (function (exports) {
|
|
|
46680
46532
|
// register action by writing
|
|
46681
46533
|
this.writeCharacteristic(characteristicName, payload).catch((error) => {
|
|
46682
46534
|
this._removePendingAction(actionId);
|
|
46683
|
-
reject(error
|
|
46535
|
+
reject(error);
|
|
46684
46536
|
});
|
|
46685
46537
|
}
|
|
46686
46538
|
else {
|
|
@@ -46689,48 +46541,108 @@ var Neurosity = (function (exports) {
|
|
|
46689
46541
|
resolve(null);
|
|
46690
46542
|
})
|
|
46691
46543
|
.catch((error) => {
|
|
46692
|
-
reject(error
|
|
46544
|
+
reject(error);
|
|
46693
46545
|
});
|
|
46694
46546
|
}
|
|
46695
46547
|
}));
|
|
46696
46548
|
});
|
|
46697
46549
|
}
|
|
46698
46550
|
}
|
|
46699
|
-
|
|
46700
|
-
|
|
46701
|
-
|
|
46702
|
-
|
|
46703
|
-
|
|
46704
|
-
|
|
46705
|
-
|
|
46706
|
-
|
|
46551
|
+
|
|
46552
|
+
const defaultDataProp = "data";
|
|
46553
|
+
const defaultSamplingRate = 256;
|
|
46554
|
+
const isObject$2 = (object) => object instanceof Object && object === Object(object);
|
|
46555
|
+
const isFunction$2 = (object) => typeof object === "function";
|
|
46556
|
+
const patch = (sample$$1) => (info) => {
|
|
46557
|
+
var _a;
|
|
46558
|
+
return (Object.assign(Object.assign({}, sample$$1), { info: Object.assign(Object.assign({}, ((_a = sample$$1 === null || sample$$1 === void 0 ? void 0 : sample$$1.info) !== null && _a !== void 0 ? _a : {})), (info || {})) }));
|
|
46559
|
+
};
|
|
46560
|
+
/**
|
|
46561
|
+
* Annotates stream with user-defined metadata
|
|
46562
|
+
* @method addInfo
|
|
46563
|
+
* @example eeg$.pipe(addinfo({ samplingRate: 256, channelNames: ["Af7", "Fp1", "Fp2", "Af8"] })
|
|
46564
|
+
* @param {Object} info Info to be added to the EEG stream. Relevant info may include: `samplingRate` and `channelNames`
|
|
46565
|
+
* @returns {Observable<Sample|Epoch|PSD>}
|
|
46566
|
+
*/
|
|
46567
|
+
const addInfo = (infoValue) => pipe(map((sample$$1) => {
|
|
46568
|
+
if (!isObject$2(sample$$1) ||
|
|
46569
|
+
(!isObject$2(infoValue) && !isFunction$2(infoValue))) {
|
|
46570
|
+
return sample$$1;
|
|
46571
|
+
}
|
|
46572
|
+
const info = isFunction$2(infoValue) ? infoValue(sample$$1) : infoValue;
|
|
46573
|
+
return patch(sample$$1)(info);
|
|
46574
|
+
}));
|
|
46575
|
+
/**
|
|
46576
|
+
* Get a 2D data array organized by channel from an array of Samples. Credit to Ken from Seattle's elegant transposition
|
|
46577
|
+
* http://www.codesuck.com/2012/02/transpose-javascript-array-in-one-line.html
|
|
46578
|
+
* @method groupByChannel
|
|
46579
|
+
* @param {Array<Sample>} samplesBuffer Array of Samples to be grouped
|
|
46580
|
+
* @param {string} [dataProp] Name of the key associated with EEG data
|
|
46581
|
+
* @returns {Array<Array<number>>}
|
|
46582
|
+
*/
|
|
46583
|
+
const groupByChannel = (samplesBuffer, dataProp = defaultDataProp) => samplesBuffer[0][dataProp].map((_, channelIndex) => samplesBuffer.map((sample$$1) => sample$$1[dataProp][channelIndex]));
|
|
46584
|
+
/**
|
|
46585
|
+
* Takes an array or RxJS buffer of EEG Samples and returns an Epoch.
|
|
46586
|
+
* @method bufferToEpoch
|
|
46587
|
+
* @example eeg$.pipe(bufferTime(1000), bufferToEpoch({ samplingRate: 256 }))
|
|
46588
|
+
*
|
|
46589
|
+
* @param {Object} options - Data structure options
|
|
46590
|
+
* @param {number} [options.samplingRate] Sampling rate
|
|
46591
|
+
* @param {string} [options.dataProp='data'] Name of the key associated with eeg data
|
|
46592
|
+
*
|
|
46593
|
+
* @returns {Observable<Epoch>}
|
|
46594
|
+
*/
|
|
46595
|
+
const bufferToEpoch = ({ samplingRate = defaultSamplingRate, dataProp = defaultDataProp } = {}) => pipe(map((samplesArray) => ({
|
|
46596
|
+
[dataProp]: groupByChannel(samplesArray, dataProp),
|
|
46597
|
+
info: Object.assign(Object.assign({}, (samplesArray[0] && samplesArray[0].info
|
|
46598
|
+
? samplesArray[0].info
|
|
46599
|
+
: {})), { startTime: samplesArray[0].timestamp, samplingRate: samplesArray[0].info && samplesArray[0].info.samplingRate
|
|
46600
|
+
? samplesArray[0].info.samplingRate
|
|
46601
|
+
: samplingRate })
|
|
46602
|
+
})));
|
|
46603
|
+
/**
|
|
46604
|
+
* Converts a stream of individual Samples of EEG data into a stream of Epochs of a given duration emitted at specified interval. This operator functions similarly to a circular buffer internally and allows overlapping Epochs of data to be emitted (e.g. emitting the last one second of data every 100ms).
|
|
46605
|
+
* @method epoch
|
|
46606
|
+
* @example eeg$.pipe(epoch({ duration: 1024, interval: 100, samplingRate: 256 }))
|
|
46607
|
+
* @param {Object} options - Epoching options
|
|
46608
|
+
* @param {number} [options.duration=256] Number of samples to include in each epoch
|
|
46609
|
+
* @param {number} [options.interval=100] Time (ms) between emitted Epochs
|
|
46610
|
+
* @param {number} [options.samplingRate=256] Sampling rate
|
|
46611
|
+
* @param {string} [options.dataProp='data'] Name of the key associated with eeg data
|
|
46612
|
+
* @returns {Observable} Epoch
|
|
46613
|
+
*/
|
|
46614
|
+
const epoch = ({ duration, interval: interval$$1, samplingRate, dataProp = defaultDataProp }) => pipe(bufferCount(interval$$1), scan((acc, val) => acc.concat(val).slice(acc.length < duration ? 0 : -duration)), filter((samplesArray) => samplesArray.length === duration), bufferToEpoch({ samplingRate, dataProp }));
|
|
46615
|
+
|
|
46616
|
+
const EPOCH_BUFFER_SIZE = 16;
|
|
46617
|
+
const SAMPLING_RATE_FALLBACK = 256; // Crown's sampling rate
|
|
46618
|
+
/**
|
|
46619
|
+
* @hidden
|
|
46620
|
+
*/
|
|
46621
|
+
function csvBufferToEpoch(deviceInfo) {
|
|
46622
|
+
var _a;
|
|
46623
|
+
if (!(deviceInfo === null || deviceInfo === void 0 ? void 0 : deviceInfo.samplingRate)) {
|
|
46624
|
+
console.warn(`Didn't receive a sampling rate, defaulting to ${SAMPLING_RATE_FALLBACK}`);
|
|
46625
|
+
}
|
|
46626
|
+
return pipe(csvBufferToSamples(), epoch({
|
|
46627
|
+
duration: EPOCH_BUFFER_SIZE,
|
|
46628
|
+
interval: EPOCH_BUFFER_SIZE,
|
|
46629
|
+
samplingRate: (_a = deviceInfo === null || deviceInfo === void 0 ? void 0 : deviceInfo.samplingRate) !== null && _a !== void 0 ? _a : SAMPLING_RATE_FALLBACK
|
|
46630
|
+
}), addInfo({
|
|
46631
|
+
channelNames: deviceInfo.channelNames,
|
|
46632
|
+
samplingRate: deviceInfo.samplingRate
|
|
46707
46633
|
}));
|
|
46708
46634
|
}
|
|
46709
|
-
|
|
46710
|
-
|
|
46711
|
-
|
|
46712
|
-
|
|
46713
|
-
|
|
46714
|
-
|
|
46715
|
-
|
|
46716
|
-
|
|
46717
|
-
}, {
|
|
46718
|
-
once: true
|
|
46719
|
-
});
|
|
46720
|
-
try {
|
|
46721
|
-
device.watchAdvertisements({ signal });
|
|
46722
|
-
}
|
|
46723
|
-
catch (error) {
|
|
46724
|
-
subscriber.error(error);
|
|
46725
|
-
}
|
|
46726
|
-
return () => {
|
|
46727
|
-
abortController.abort();
|
|
46728
|
-
device.removeEventListener("advertisementreceived", listener);
|
|
46729
|
-
};
|
|
46730
|
-
});
|
|
46635
|
+
/**
|
|
46636
|
+
* @hidden
|
|
46637
|
+
*/
|
|
46638
|
+
function csvBufferToSamples() {
|
|
46639
|
+
return pipe(mergeMap((samples) => from(samples)), map(([timestamp$$1, marker, ...data]) => ({
|
|
46640
|
+
timestamp: timestamp$$1,
|
|
46641
|
+
data
|
|
46642
|
+
})));
|
|
46731
46643
|
}
|
|
46732
46644
|
|
|
46733
|
-
var __awaiter$
|
|
46645
|
+
var __awaiter$f = function (thisArg, _arguments, P, generator) {
|
|
46734
46646
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
46735
46647
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
46736
46648
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
@@ -46739,783 +46651,872 @@ var Neurosity = (function (exports) {
|
|
|
46739
46651
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
46740
46652
|
});
|
|
46741
46653
|
};
|
|
46742
|
-
|
|
46743
|
-
autoConnect: true
|
|
46744
|
-
};
|
|
46745
|
-
class ReactNativeTransport {
|
|
46654
|
+
class BluetoothClient {
|
|
46746
46655
|
constructor(options) {
|
|
46747
|
-
this.
|
|
46748
|
-
this.
|
|
46749
|
-
this.
|
|
46750
|
-
|
|
46751
|
-
|
|
46752
|
-
|
|
46753
|
-
.asObservable()
|
|
46754
|
-
.pipe(filter((connection) => !!connection), distinctUntilChanged(), shareReplay(1));
|
|
46755
|
-
this._isAutoConnectEnabled$ = new ReplaySubject(1);
|
|
46756
|
-
if (!options) {
|
|
46757
|
-
const errorMessage = "React Native transport: missing options.";
|
|
46758
|
-
this.addLog(errorMessage);
|
|
46759
|
-
throw new Error(errorMessage);
|
|
46760
|
-
}
|
|
46761
|
-
this.options = Object.assign(Object.assign({}, defaultOptions$2), options);
|
|
46762
|
-
const { BleManager, bleManagerEmitter, platform, autoConnect } = this.options;
|
|
46763
|
-
if (!BleManager) {
|
|
46764
|
-
const errorMessage = "React Native option: BleManager not provided.";
|
|
46765
|
-
this.addLog(errorMessage);
|
|
46766
|
-
throw new Error(errorMessage);
|
|
46656
|
+
this.selectedDevice$ = new ReplaySubject(1);
|
|
46657
|
+
this.osHasBluetoothSupport$ = new ReplaySubject(1);
|
|
46658
|
+
this.isAuthenticated$ = new ReplaySubject(1);
|
|
46659
|
+
const { transport, selectedDevice$, osHasBluetoothSupport$, createBluetoothToken } = options !== null && options !== void 0 ? options : {};
|
|
46660
|
+
if (!transport) {
|
|
46661
|
+
throw new Error(`No bluetooth transport provided.`);
|
|
46767
46662
|
}
|
|
46768
|
-
|
|
46769
|
-
|
|
46770
|
-
|
|
46771
|
-
|
|
46663
|
+
this.transport = transport;
|
|
46664
|
+
// Pass events to the internal selectedDevice$ if selectedDevice$ is passed via options
|
|
46665
|
+
if (selectedDevice$) {
|
|
46666
|
+
selectedDevice$.subscribe(this.selectedDevice$);
|
|
46772
46667
|
}
|
|
46773
|
-
if
|
|
46774
|
-
|
|
46775
|
-
this.
|
|
46776
|
-
throw new Error(errorMessage);
|
|
46668
|
+
// Pass events to the internal osHasBluetoothSupport$ if osHasBluetoothSupport$ is passed via options
|
|
46669
|
+
if (osHasBluetoothSupport$) {
|
|
46670
|
+
osHasBluetoothSupport$.subscribe(this.osHasBluetoothSupport$);
|
|
46777
46671
|
}
|
|
46778
|
-
this.
|
|
46779
|
-
|
|
46780
|
-
|
|
46781
|
-
|
|
46782
|
-
|
|
46783
|
-
|
|
46784
|
-
|
|
46785
|
-
|
|
46786
|
-
|
|
46787
|
-
this.bleEvents = {
|
|
46788
|
-
stopScan$: this._fromEvent("BleManagerStopScan"),
|
|
46789
|
-
discoverPeripheral$: this._fromEvent("BleManagerDiscoverPeripheral"),
|
|
46790
|
-
connectPeripheral$: this._fromEvent("BleManagerConnectPeripheral"),
|
|
46791
|
-
disconnectPeripheral$: this._fromEvent("BleManagerDisconnectPeripheral"),
|
|
46792
|
-
didUpdateValueForCharacteristic$: this._fromEvent("BleManagerDidUpdateValueForCharacteristic"),
|
|
46793
|
-
didUpdateState$: this._fromEvent("BleManagerDidUpdateState")
|
|
46794
|
-
};
|
|
46795
|
-
this.onDisconnected$ = this.bleEvents.disconnectPeripheral$.pipe(share());
|
|
46796
|
-
// Initializes the module. This can only be called once.
|
|
46797
|
-
this.BleManager.start({ showAlert: false })
|
|
46798
|
-
.then(() => {
|
|
46799
|
-
this.addLog(`BleManger started`);
|
|
46800
|
-
})
|
|
46801
|
-
.catch((error) => {
|
|
46802
|
-
var _a;
|
|
46803
|
-
this.addLog(`BleManger failed to start. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46804
|
-
});
|
|
46805
|
-
this.connection$.asObservable().subscribe((connection) => {
|
|
46806
|
-
this.addLog(`connection status is ${connection}`);
|
|
46672
|
+
this.osHasBluetoothSupport$
|
|
46673
|
+
.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport
|
|
46674
|
+
? this.transport._autoConnect(this.selectedDevice$)
|
|
46675
|
+
: EMPTY))
|
|
46676
|
+
.subscribe({
|
|
46677
|
+
error: (error) => {
|
|
46678
|
+
var _a;
|
|
46679
|
+
this.transport.addLog(`Auto connect: error -> ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46680
|
+
}
|
|
46807
46681
|
});
|
|
46808
|
-
|
|
46809
|
-
|
|
46810
|
-
|
|
46811
|
-
|
|
46812
|
-
|
|
46813
|
-
|
|
46814
|
-
|
|
46815
|
-
|
|
46816
|
-
|
|
46817
|
-
|
|
46682
|
+
// Auto authentication
|
|
46683
|
+
if (typeof createBluetoothToken === "function") {
|
|
46684
|
+
this.transport.addLog("Auto authentication enabled");
|
|
46685
|
+
this._autoAuthenticate(createBluetoothToken).subscribe();
|
|
46686
|
+
}
|
|
46687
|
+
else {
|
|
46688
|
+
this.transport.addLog("Auto authentication not enabled");
|
|
46689
|
+
}
|
|
46690
|
+
// Auto manage action notifications
|
|
46691
|
+
this.osHasBluetoothSupport$
|
|
46692
|
+
.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport
|
|
46693
|
+
? this.transport._autoToggleActionNotifications()
|
|
46694
|
+
: EMPTY))
|
|
46695
|
+
.subscribe();
|
|
46696
|
+
// Multicast metrics (share)
|
|
46697
|
+
this._focus$ = this._subscribeWhileAuthenticated("focus");
|
|
46698
|
+
this._calm$ = this._subscribeWhileAuthenticated("calm");
|
|
46699
|
+
this._accelerometer$ = this._subscribeWhileAuthenticated("accelerometer");
|
|
46700
|
+
this._brainwavesRaw$ = this._subscribeWhileAuthenticated("raw");
|
|
46701
|
+
this._brainwavesRawUnfiltered$ =
|
|
46702
|
+
this._subscribeWhileAuthenticated("rawUnfiltered");
|
|
46703
|
+
this._brainwavesPSD$ = this._subscribeWhileAuthenticated("psd");
|
|
46704
|
+
this._brainwavesPowerByBand$ =
|
|
46705
|
+
this._subscribeWhileAuthenticated("powerByBand");
|
|
46706
|
+
this._signalQuality$ = this._subscribeWhileAuthenticated("signalQuality");
|
|
46707
|
+
this._status$ = this._subscribeWhileAuthenticated("status");
|
|
46708
|
+
this._settings$ = this._subscribeWhileAuthenticated("settings");
|
|
46709
|
+
this._wifiNearbyNetworks$ =
|
|
46710
|
+
this._subscribeWhileAuthenticated("wifiNearbyNetworks");
|
|
46711
|
+
this._wifiConnections$ =
|
|
46712
|
+
this._subscribeWhileAuthenticated("wifiConnections");
|
|
46818
46713
|
}
|
|
46819
|
-
|
|
46820
|
-
const
|
|
46821
|
-
|
|
46822
|
-
|
|
46823
|
-
|
|
46824
|
-
|
|
46825
|
-
|
|
46826
|
-
|
|
46827
|
-
|
|
46828
|
-
|
|
46829
|
-
|
|
46714
|
+
_autoAuthenticate(createBluetoothToken) {
|
|
46715
|
+
const REAUTHENTICATE_INTERVAL = 3600000; // 1 hour
|
|
46716
|
+
const reauthenticateInterval$ = timer(0, REAUTHENTICATE_INTERVAL).pipe(tap(() => {
|
|
46717
|
+
this.transport.addLog(`Auto authentication in progress...`);
|
|
46718
|
+
}));
|
|
46719
|
+
return this.osHasBluetoothSupport$.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport ? this.connection() : EMPTY), switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED
|
|
46720
|
+
? reauthenticateInterval$
|
|
46721
|
+
: EMPTY), switchMap(() => __awaiter$f(this, void 0, void 0, function* () { return yield this.isAuthenticated(); })), tap(([isAuthenticated]) => __awaiter$f(this, void 0, void 0, function* () {
|
|
46722
|
+
if (!isAuthenticated) {
|
|
46723
|
+
const token = yield createBluetoothToken();
|
|
46724
|
+
yield this.authenticate(token);
|
|
46725
|
+
}
|
|
46726
|
+
else {
|
|
46727
|
+
this.transport.addLog(`Already authenticated`);
|
|
46728
|
+
}
|
|
46830
46729
|
})));
|
|
46831
46730
|
}
|
|
46832
46731
|
enableAutoConnect(autoConnect) {
|
|
46833
|
-
this.
|
|
46834
|
-
}
|
|
46835
|
-
connection() {
|
|
46836
|
-
return this.connectionStream$;
|
|
46732
|
+
this.transport.enableAutoConnect(autoConnect);
|
|
46837
46733
|
}
|
|
46838
|
-
|
|
46839
|
-
return
|
|
46840
|
-
this.
|
|
46841
|
-
}
|
|
46842
|
-
this.bleManagerEmitter.removeAllListeners(eventName);
|
|
46843
|
-
}).pipe(
|
|
46844
|
-
// @important: we need to share the subscription
|
|
46845
|
-
// to avoid missing events
|
|
46846
|
-
share());
|
|
46734
|
+
_hasBluetoothSupport() {
|
|
46735
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46736
|
+
return yield firstValueFrom(this.osHasBluetoothSupport$);
|
|
46737
|
+
});
|
|
46847
46738
|
}
|
|
46848
|
-
|
|
46849
|
-
|
|
46850
|
-
|
|
46851
|
-
|
|
46852
|
-
|
|
46853
|
-
|
|
46854
|
-
|
|
46855
|
-
// update it back if no device is connected to
|
|
46856
|
-
const skipConnectionUpdate = (_c = options === null || options === void 0 ? void 0 : options.skipConnectionUpdate) !== null && _c !== void 0 ? _c : false;
|
|
46857
|
-
const serviceUUIDs = [BLUETOOTH_PRIMARY_SERVICE_UUID_STRING];
|
|
46858
|
-
const allowDuplicates = true;
|
|
46859
|
-
const scanOptions = {};
|
|
46860
|
-
const scanOnce$ = new Observable((subscriber) => {
|
|
46861
|
-
var _a;
|
|
46862
|
-
try {
|
|
46863
|
-
this.BleManager.scan(serviceUUIDs, seconds, allowDuplicates, scanOptions).then(() => {
|
|
46864
|
-
this.addLog(`BleManger scanning ${once ? "once" : "indefintely"}`);
|
|
46865
|
-
subscriber.next();
|
|
46866
|
-
});
|
|
46867
|
-
}
|
|
46868
|
-
catch (error) {
|
|
46869
|
-
this.addLog(`BleManger scanning ${once ? "once" : "indefintely"} failed. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
46870
|
-
subscriber.error(error);
|
|
46739
|
+
authenticate(token) {
|
|
46740
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46741
|
+
const hasBluetoothSupport = yield this._hasBluetoothSupport();
|
|
46742
|
+
if (!hasBluetoothSupport) {
|
|
46743
|
+
const errorMessage = `authenticate method: The OS version does not support Bluetooth.`;
|
|
46744
|
+
this.transport.addLog(errorMessage);
|
|
46745
|
+
return Promise.reject(errorMessage);
|
|
46871
46746
|
}
|
|
46872
|
-
|
|
46873
|
-
|
|
46874
|
-
|
|
46747
|
+
yield this.transport.writeCharacteristic("auth", token);
|
|
46748
|
+
const isAuthenticatedResponse = yield this.isAuthenticated();
|
|
46749
|
+
const [isAuthenticated] = isAuthenticatedResponse;
|
|
46750
|
+
this.transport.addLog(`Authentication ${isAuthenticated ? "succeeded" : "failed"}`);
|
|
46751
|
+
this.isAuthenticated$.next(isAuthenticated);
|
|
46752
|
+
return isAuthenticatedResponse;
|
|
46875
46753
|
});
|
|
46876
|
-
const scan$ = once
|
|
46877
|
-
? scanOnce$
|
|
46878
|
-
: timer(0, RESCAN_INTERVAL).pipe(switchMap(() => scanOnce$));
|
|
46879
|
-
const peripherals$ = scan$.pipe(tap(() => {
|
|
46880
|
-
if (!skipConnectionUpdate) {
|
|
46881
|
-
this.connection$.next(exports.BLUETOOTH_CONNECTION.SCANNING);
|
|
46882
|
-
}
|
|
46883
|
-
}), takeUntil(this.onDisconnected$), switchMap(() => this.bleEvents.discoverPeripheral$),
|
|
46884
|
-
// Filter out devices that are not Neurosity devices
|
|
46885
|
-
filter((peripheral) => {
|
|
46886
|
-
var _a, _b, _c;
|
|
46887
|
-
const peripheralName = (_c = (_b = (_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertising) === null || _a === void 0 ? void 0 : _a.localName) !== null && _b !== void 0 ? _b : peripheral.name) !== null && _c !== void 0 ? _c : "";
|
|
46888
|
-
if (!peripheralName) {
|
|
46889
|
-
return false;
|
|
46890
|
-
}
|
|
46891
|
-
const startsWithPrefix = BLUETOOTH_DEVICE_NAME_PREFIXES.findIndex((prefix) => peripheralName.startsWith(prefix)) !== -1;
|
|
46892
|
-
return startsWithPrefix;
|
|
46893
|
-
}), scan((acc, peripheral) => {
|
|
46894
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
46895
|
-
// normalized peripheral name for backwards compatibility
|
|
46896
|
-
// Neurosity OS v15 doesn't have peripheral.name as deviceNickname
|
|
46897
|
-
// it only has peripheral.advertising.localName as deviceNickname
|
|
46898
|
-
// and OS v16 has both as deviceNickname
|
|
46899
|
-
const peripheralName = (_c = (_b = (_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertising) === null || _a === void 0 ? void 0 : _a.localName) !== null && _b !== void 0 ? _b : peripheral.name) !== null && _c !== void 0 ? _c : "";
|
|
46900
|
-
const manufactureDataString = (_h = (_g = decode$1(this.type, (_f = (_e = (_d = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertising) === null || _d === void 0 ? void 0 : _d.manufacturerData) === null || _e === void 0 ? void 0 : _e.bytes) !== null && _f !== void 0 ? _f : [])) === null || _g === void 0 ? void 0 : _g.slice) === null || _h === void 0 ? void 0 : _h.call(_g, 2); // First 2 bytes are reserved for the Neurosity company code
|
|
46901
|
-
return Object.assign(Object.assign({}, acc), { [peripheral.id]: Object.assign(Object.assign({}, peripheral), { name: peripheralName, manufactureDataString }) });
|
|
46902
|
-
}, {}), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), map((peripheralMap) => Object.values(peripheralMap)), share());
|
|
46903
|
-
return peripherals$;
|
|
46904
46754
|
}
|
|
46905
|
-
|
|
46906
|
-
return __awaiter$
|
|
46907
|
-
|
|
46908
|
-
|
|
46909
|
-
|
|
46910
|
-
this.addLog("Peripheral not found");
|
|
46911
|
-
return;
|
|
46912
|
-
}
|
|
46913
|
-
this.connection$.next(exports.BLUETOOTH_CONNECTION.CONNECTING);
|
|
46914
|
-
yield this.BleManager.connect(peripheral.id);
|
|
46915
|
-
this.addLog(`Getting service...`);
|
|
46916
|
-
const peripheralInfo = yield this.BleManager.retrieveServices(peripheral.id, [
|
|
46917
|
-
BLUETOOTH_PRIMARY_SERVICE_UUID_STRING
|
|
46918
|
-
]);
|
|
46919
|
-
if (!peripheralInfo) {
|
|
46920
|
-
this.addLog("Could not retreive services");
|
|
46921
|
-
reject(new Error(`Could not retreive services`));
|
|
46922
|
-
return;
|
|
46923
|
-
}
|
|
46924
|
-
this.addLog(`Got service ${BLUETOOTH_PRIMARY_SERVICE_UUID_STRING}, getting characteristics...`);
|
|
46925
|
-
this.device = peripheral;
|
|
46926
|
-
this.characteristicsByName = Object.fromEntries(peripheralInfo.characteristics.map((characteristic) => [
|
|
46927
|
-
CHARACTERISTIC_UUIDS_TO_NAMES[characteristic.characteristic.toLowerCase() // react native uses uppercase
|
|
46928
|
-
],
|
|
46929
|
-
{
|
|
46930
|
-
characteristicUUID: characteristic.characteristic,
|
|
46931
|
-
serviceUUID: characteristic.service,
|
|
46932
|
-
peripheralId: peripheral.id
|
|
46933
|
-
}
|
|
46934
|
-
]));
|
|
46935
|
-
this.addLog(`Got characteristics.`);
|
|
46936
|
-
if (this.platform === "android") {
|
|
46937
|
-
yield this.BleManager.requestMTU(peripheral.id, ANDROID_MAX_MTU)
|
|
46938
|
-
.then((updatedMTU) => {
|
|
46939
|
-
this.addLog(`Successfully updated Android MTU to ${updatedMTU} bytes. Requested MTU: ${ANDROID_MAX_MTU} bytes.`);
|
|
46940
|
-
})
|
|
46941
|
-
.catch((error) => {
|
|
46942
|
-
this.addLog(`Failed to set Android MTU of ${ANDROID_MAX_MTU} bytes. Error: ${error}`);
|
|
46943
|
-
});
|
|
46944
|
-
}
|
|
46945
|
-
this.addLog(`Successfully connected to peripheral ${peripheral.id}`);
|
|
46946
|
-
this.connection$.next(exports.BLUETOOTH_CONNECTION.CONNECTED);
|
|
46947
|
-
resolve();
|
|
46948
|
-
}
|
|
46949
|
-
catch (error) {
|
|
46950
|
-
reject(error);
|
|
46951
|
-
}
|
|
46952
|
-
}));
|
|
46755
|
+
isAuthenticated() {
|
|
46756
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46757
|
+
const [isAuthenticated, expiresIn] = yield this.transport.readCharacteristic("auth", true);
|
|
46758
|
+
this.isAuthenticated$.next(isAuthenticated);
|
|
46759
|
+
return [isAuthenticated, expiresIn];
|
|
46953
46760
|
});
|
|
46954
46761
|
}
|
|
46762
|
+
// Method for React Native only
|
|
46763
|
+
scan(options) {
|
|
46764
|
+
if (this.transport instanceof ReactNativeTransport) {
|
|
46765
|
+
return this.transport.scan(options);
|
|
46766
|
+
}
|
|
46767
|
+
if (this.transport instanceof WebBluetoothTransport) {
|
|
46768
|
+
throw new Error(`scan method is compatibly with the React Native transport only`);
|
|
46769
|
+
}
|
|
46770
|
+
throw new Error(`unknown transport`);
|
|
46771
|
+
}
|
|
46772
|
+
// Argument for React Native only
|
|
46773
|
+
connect(deviceNicknameORPeripheral) {
|
|
46774
|
+
if (this.transport instanceof ReactNativeTransport) {
|
|
46775
|
+
return this.transport.connect(deviceNicknameORPeripheral);
|
|
46776
|
+
}
|
|
46777
|
+
if (this.transport instanceof WebBluetoothTransport) {
|
|
46778
|
+
return deviceNicknameORPeripheral
|
|
46779
|
+
? this.transport.connect(deviceNicknameORPeripheral)
|
|
46780
|
+
: this.transport.connect();
|
|
46781
|
+
}
|
|
46782
|
+
}
|
|
46955
46783
|
disconnect() {
|
|
46956
|
-
|
|
46957
|
-
|
|
46958
|
-
|
|
46959
|
-
|
|
46960
|
-
|
|
46961
|
-
|
|
46784
|
+
return this.transport.disconnect();
|
|
46785
|
+
}
|
|
46786
|
+
connection() {
|
|
46787
|
+
return this.transport.connection();
|
|
46788
|
+
}
|
|
46789
|
+
logs() {
|
|
46790
|
+
return this.transport.logs$.asObservable();
|
|
46791
|
+
}
|
|
46792
|
+
getDeviceId() {
|
|
46793
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46794
|
+
// This is a public characteristic and does not require authentication
|
|
46795
|
+
return this.transport.readCharacteristic("deviceId");
|
|
46796
|
+
});
|
|
46797
|
+
}
|
|
46798
|
+
_withAuthentication(getter) {
|
|
46799
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46800
|
+
// First check if the OS supports Bluetooth before checking if the device is authenticated
|
|
46801
|
+
const hasBluetoothSupport = yield this._hasBluetoothSupport();
|
|
46802
|
+
if (!hasBluetoothSupport) {
|
|
46803
|
+
const errorMessage = `The OS version does not support Bluetooth.`;
|
|
46804
|
+
this.transport.addLog(errorMessage);
|
|
46805
|
+
return Promise.reject(errorMessage);
|
|
46962
46806
|
}
|
|
46963
|
-
|
|
46964
|
-
|
|
46807
|
+
const isAuthenticated = yield firstValueFrom(this.isAuthenticated$);
|
|
46808
|
+
if (!isAuthenticated) {
|
|
46809
|
+
const errorMessage = `Authentication required.`;
|
|
46810
|
+
this.transport.addLog(errorMessage);
|
|
46811
|
+
return Promise.reject(errorMessage);
|
|
46965
46812
|
}
|
|
46813
|
+
return yield getter();
|
|
46966
46814
|
});
|
|
46967
46815
|
}
|
|
46968
|
-
|
|
46969
|
-
|
|
46970
|
-
|
|
46971
|
-
|
|
46972
|
-
|
|
46973
|
-
|
|
46816
|
+
_subscribeWhileAuthenticated(characteristicName) {
|
|
46817
|
+
return this.osHasBluetoothSupport$.pipe(switchMap((osHasBluetoothSupport) => osHasBluetoothSupport ? this.isAuthenticated$ : EMPTY), distinctUntilChanged(), switchMap((isAuthenticated) => isAuthenticated
|
|
46818
|
+
? this.transport.subscribeToCharacteristic({
|
|
46819
|
+
characteristicName
|
|
46820
|
+
})
|
|
46821
|
+
: EMPTY), share());
|
|
46974
46822
|
}
|
|
46975
|
-
|
|
46976
|
-
|
|
46977
|
-
|
|
46978
|
-
|
|
46979
|
-
|
|
46980
|
-
|
|
46981
|
-
|
|
46982
|
-
|
|
46983
|
-
|
|
46984
|
-
|
|
46985
|
-
|
|
46986
|
-
|
|
46987
|
-
|
|
46988
|
-
|
|
46989
|
-
|
|
46990
|
-
|
|
46991
|
-
|
|
46992
|
-
|
|
46993
|
-
|
|
46994
|
-
|
|
46995
|
-
|
|
46823
|
+
focus() {
|
|
46824
|
+
return this._focus$;
|
|
46825
|
+
}
|
|
46826
|
+
calm() {
|
|
46827
|
+
return this._calm$;
|
|
46828
|
+
}
|
|
46829
|
+
accelerometer() {
|
|
46830
|
+
return this._accelerometer$;
|
|
46831
|
+
}
|
|
46832
|
+
brainwaves(label) {
|
|
46833
|
+
switch (label) {
|
|
46834
|
+
default:
|
|
46835
|
+
case "raw":
|
|
46836
|
+
return defer(() => this.getInfo()).pipe(switchMap((deviceInfo) => this._brainwavesRaw$.pipe(csvBufferToEpoch(deviceInfo))));
|
|
46837
|
+
case "rawUnfiltered":
|
|
46838
|
+
return defer(() => this.getInfo()).pipe(switchMap((deviceInfo) => this._brainwavesRawUnfiltered$.pipe(csvBufferToEpoch(deviceInfo))));
|
|
46839
|
+
case "psd":
|
|
46840
|
+
return this._brainwavesPSD$;
|
|
46841
|
+
case "powerByBand":
|
|
46842
|
+
return this._brainwavesPowerByBand$;
|
|
46843
|
+
}
|
|
46844
|
+
}
|
|
46845
|
+
signalQuality() {
|
|
46846
|
+
return this._signalQuality$;
|
|
46847
|
+
}
|
|
46848
|
+
addMarker(label) {
|
|
46849
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46850
|
+
yield this.dispatchAction({
|
|
46851
|
+
action: "marker",
|
|
46852
|
+
command: "add",
|
|
46853
|
+
message: {
|
|
46854
|
+
timestamp: Date.now(),
|
|
46855
|
+
label
|
|
46996
46856
|
}
|
|
46997
|
-
}
|
|
46998
|
-
})
|
|
46999
|
-
var _a;
|
|
47000
|
-
try {
|
|
47001
|
-
return JSON.parse(payload);
|
|
47002
|
-
}
|
|
47003
|
-
catch (error) {
|
|
47004
|
-
this.addLog(`Failed to parse JSON for ${characteristicName} characteristic. Falling back to unparsed string. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
47005
|
-
return payload;
|
|
47006
|
-
}
|
|
47007
|
-
}));
|
|
47008
|
-
return this.connection$.pipe(switchMap((connection) => connection === exports.BLUETOOTH_CONNECTION.CONNECTED
|
|
47009
|
-
? getData(this.getCharacteristicByName(characteristicName))
|
|
47010
|
-
: NEVER));
|
|
46857
|
+
});
|
|
46858
|
+
});
|
|
47011
46859
|
}
|
|
47012
|
-
|
|
47013
|
-
|
|
47014
|
-
|
|
47015
|
-
|
|
47016
|
-
|
|
47017
|
-
if (!characteristicUUID) {
|
|
47018
|
-
return Promise.reject(new Error(`Did not find characteristic matching ${characteristicName}`));
|
|
47019
|
-
}
|
|
47020
|
-
try {
|
|
47021
|
-
const value = yield this.BleManager.read(peripheralId, serviceUUID, characteristicUUID);
|
|
47022
|
-
const decodedValue = decode$1(this.type, value);
|
|
47023
|
-
const data = parse ? JSON.parse(decodedValue) : decodedValue;
|
|
47024
|
-
this.addLog(`Received read data from ${characteristicName} characteristic: \n${data}`);
|
|
47025
|
-
return data;
|
|
47026
|
-
}
|
|
47027
|
-
catch (error) {
|
|
47028
|
-
return Promise.reject(new Error(`readCharacteristic ${characteristicName} error. ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`));
|
|
47029
|
-
}
|
|
46860
|
+
getInfo() {
|
|
46861
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46862
|
+
return yield this._withAuthentication(() => firstValueFrom(this.transport.subscribeToCharacteristic({
|
|
46863
|
+
characteristicName: "deviceInfo"
|
|
46864
|
+
})));
|
|
47030
46865
|
});
|
|
47031
46866
|
}
|
|
47032
|
-
|
|
47033
|
-
return
|
|
47034
|
-
|
|
47035
|
-
|
|
47036
|
-
|
|
47037
|
-
|
|
47038
|
-
|
|
47039
|
-
|
|
47040
|
-
|
|
46867
|
+
status() {
|
|
46868
|
+
return this._status$;
|
|
46869
|
+
}
|
|
46870
|
+
dispatchAction(action) {
|
|
46871
|
+
return __awaiter$f(this, void 0, void 0, function* () {
|
|
46872
|
+
return yield this._withAuthentication(() => this.transport.dispatchAction({
|
|
46873
|
+
characteristicName: "actions",
|
|
46874
|
+
action
|
|
46875
|
+
}));
|
|
47041
46876
|
});
|
|
47042
46877
|
}
|
|
47043
|
-
|
|
47044
|
-
|
|
47045
|
-
|
|
46878
|
+
settings() {
|
|
46879
|
+
return this._settings$;
|
|
46880
|
+
}
|
|
46881
|
+
haptics(effects) {
|
|
46882
|
+
const metric = "haptics";
|
|
46883
|
+
return this.dispatchAction({
|
|
46884
|
+
action: metric,
|
|
46885
|
+
command: "queue",
|
|
46886
|
+
responseRequired: true,
|
|
46887
|
+
responseTimeout: 4000,
|
|
46888
|
+
// @TODO: implement validation logic as per SDK
|
|
46889
|
+
message: { effects }
|
|
46890
|
+
});
|
|
46891
|
+
}
|
|
46892
|
+
get wifi() {
|
|
46893
|
+
return {
|
|
46894
|
+
nearbyNetworks: () => this._wifiNearbyNetworks$,
|
|
46895
|
+
connections: () => this._wifiConnections$,
|
|
46896
|
+
connect: (ssid, password) => {
|
|
46897
|
+
if (!ssid) {
|
|
46898
|
+
return Promise.reject(`Missing ssid`);
|
|
46899
|
+
}
|
|
46900
|
+
return this.dispatchAction({
|
|
46901
|
+
action: "wifi",
|
|
46902
|
+
command: "connect",
|
|
46903
|
+
responseRequired: true,
|
|
46904
|
+
responseTimeout: 1000 * 60 * 2,
|
|
46905
|
+
message: {
|
|
46906
|
+
ssid,
|
|
46907
|
+
password: password !== null && password !== void 0 ? password : null
|
|
46908
|
+
}
|
|
46909
|
+
});
|
|
46910
|
+
},
|
|
46911
|
+
forgetConnection: (ssid) => {
|
|
46912
|
+
if (!ssid) {
|
|
46913
|
+
return Promise.reject(`Missing ssid`);
|
|
46914
|
+
}
|
|
46915
|
+
return this.dispatchAction({
|
|
46916
|
+
action: "wifi",
|
|
46917
|
+
command: "forget-connection",
|
|
46918
|
+
responseRequired: true,
|
|
46919
|
+
responseTimeout: 1000 * 15,
|
|
46920
|
+
message: {
|
|
46921
|
+
ssid
|
|
46922
|
+
}
|
|
46923
|
+
});
|
|
46924
|
+
},
|
|
46925
|
+
reset: () => {
|
|
46926
|
+
return this.dispatchAction({
|
|
46927
|
+
action: "wifi",
|
|
46928
|
+
command: "reset",
|
|
46929
|
+
responseRequired: true,
|
|
46930
|
+
responseTimeout: 1000 * 30,
|
|
46931
|
+
message: {
|
|
46932
|
+
// without this, the action will resolve as soon as the
|
|
46933
|
+
// action is received by the OS
|
|
46934
|
+
respondOnSuccess: true
|
|
46935
|
+
}
|
|
46936
|
+
});
|
|
46937
|
+
},
|
|
46938
|
+
speedTest: () => {
|
|
46939
|
+
return this.dispatchAction({
|
|
46940
|
+
action: "wifi",
|
|
46941
|
+
command: "speed-test",
|
|
46942
|
+
responseRequired: true,
|
|
46943
|
+
responseTimeout: 1000 * 60 * 1 // 1 minute
|
|
46944
|
+
});
|
|
46945
|
+
}
|
|
46946
|
+
};
|
|
46947
|
+
}
|
|
46948
|
+
}
|
|
46949
|
+
|
|
46950
|
+
const debug = (
|
|
46951
|
+
typeof process === 'object' &&
|
|
46952
|
+
process.env &&
|
|
46953
|
+
process.env.NODE_DEBUG &&
|
|
46954
|
+
/\bsemver\b/i.test(process.env.NODE_DEBUG)
|
|
46955
|
+
) ? (...args) => console.error('SEMVER', ...args)
|
|
46956
|
+
: () => {};
|
|
46957
|
+
|
|
46958
|
+
var debug_1 = debug;
|
|
46959
|
+
|
|
46960
|
+
// Note: this is the semver.org version of the spec that it implements
|
|
46961
|
+
// Not necessarily the package version of this code.
|
|
46962
|
+
const SEMVER_SPEC_VERSION = '2.0.0';
|
|
46963
|
+
|
|
46964
|
+
const MAX_LENGTH = 256;
|
|
46965
|
+
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
|
|
46966
|
+
/* istanbul ignore next */ 9007199254740991;
|
|
46967
|
+
|
|
46968
|
+
// Max safe segment length for coercion.
|
|
46969
|
+
const MAX_SAFE_COMPONENT_LENGTH = 16;
|
|
46970
|
+
|
|
46971
|
+
var constants = {
|
|
46972
|
+
SEMVER_SPEC_VERSION,
|
|
46973
|
+
MAX_LENGTH,
|
|
46974
|
+
MAX_SAFE_INTEGER,
|
|
46975
|
+
MAX_SAFE_COMPONENT_LENGTH,
|
|
46976
|
+
};
|
|
46977
|
+
|
|
46978
|
+
function createCommonjsModule(fn, module) {
|
|
46979
|
+
return module = { exports: {} }, fn(module, module.exports), module.exports;
|
|
46980
|
+
}
|
|
46981
|
+
|
|
46982
|
+
var re_1 = createCommonjsModule(function (module, exports) {
|
|
46983
|
+
const { MAX_SAFE_COMPONENT_LENGTH } = constants;
|
|
46984
|
+
|
|
46985
|
+
exports = module.exports = {};
|
|
46986
|
+
|
|
46987
|
+
// The actual regexps go on exports.re
|
|
46988
|
+
const re = exports.re = [];
|
|
46989
|
+
const src = exports.src = [];
|
|
46990
|
+
const t = exports.t = {};
|
|
46991
|
+
let R = 0;
|
|
46992
|
+
|
|
46993
|
+
const createToken = (name, value, isGlobal) => {
|
|
46994
|
+
const index = R++;
|
|
46995
|
+
debug_1(name, index, value);
|
|
46996
|
+
t[name] = index;
|
|
46997
|
+
src[index] = value;
|
|
46998
|
+
re[index] = new RegExp(value, isGlobal ? 'g' : undefined);
|
|
46999
|
+
};
|
|
47000
|
+
|
|
47001
|
+
// The following Regular Expressions can be used for tokenizing,
|
|
47002
|
+
// validating, and parsing SemVer version strings.
|
|
47003
|
+
|
|
47004
|
+
// ## Numeric Identifier
|
|
47005
|
+
// A single `0`, or a non-zero digit followed by zero or more digits.
|
|
47006
|
+
|
|
47007
|
+
createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*');
|
|
47008
|
+
createToken('NUMERICIDENTIFIERLOOSE', '[0-9]+');
|
|
47009
|
+
|
|
47010
|
+
// ## Non-numeric Identifier
|
|
47011
|
+
// Zero or more digits, followed by a letter or hyphen, and then zero or
|
|
47012
|
+
// more letters, digits, or hyphens.
|
|
47013
|
+
|
|
47014
|
+
createToken('NONNUMERICIDENTIFIER', '\\d*[a-zA-Z-][a-zA-Z0-9-]*');
|
|
47015
|
+
|
|
47016
|
+
// ## Main Version
|
|
47017
|
+
// Three dot-separated numeric identifiers.
|
|
47018
|
+
|
|
47019
|
+
createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
|
|
47020
|
+
`(${src[t.NUMERICIDENTIFIER]})\\.` +
|
|
47021
|
+
`(${src[t.NUMERICIDENTIFIER]})`);
|
|
47022
|
+
|
|
47023
|
+
createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
|
|
47024
|
+
`(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
|
|
47025
|
+
`(${src[t.NUMERICIDENTIFIERLOOSE]})`);
|
|
47026
|
+
|
|
47027
|
+
// ## Pre-release Version Identifier
|
|
47028
|
+
// A numeric identifier, or a non-numeric identifier.
|
|
47029
|
+
|
|
47030
|
+
createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER]
|
|
47031
|
+
}|${src[t.NONNUMERICIDENTIFIER]})`);
|
|
47032
|
+
|
|
47033
|
+
createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE]
|
|
47034
|
+
}|${src[t.NONNUMERICIDENTIFIER]})`);
|
|
47035
|
+
|
|
47036
|
+
// ## Pre-release Version
|
|
47037
|
+
// Hyphen, followed by one or more dot-separated pre-release version
|
|
47038
|
+
// identifiers.
|
|
47039
|
+
|
|
47040
|
+
createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
|
|
47041
|
+
}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`);
|
|
47042
|
+
|
|
47043
|
+
createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
|
|
47044
|
+
}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`);
|
|
47045
|
+
|
|
47046
|
+
// ## Build Metadata Identifier
|
|
47047
|
+
// Any combination of digits, letters, or hyphens.
|
|
47048
|
+
|
|
47049
|
+
createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+');
|
|
47050
|
+
|
|
47051
|
+
// ## Build Metadata
|
|
47052
|
+
// Plus sign, followed by one or more period-separated build metadata
|
|
47053
|
+
// identifiers.
|
|
47054
|
+
|
|
47055
|
+
createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
|
|
47056
|
+
}(?:\\.${src[t.BUILDIDENTIFIER]})*))`);
|
|
47057
|
+
|
|
47058
|
+
// ## Full Version String
|
|
47059
|
+
// A main version, followed optionally by a pre-release version and
|
|
47060
|
+
// build metadata.
|
|
47061
|
+
|
|
47062
|
+
// Note that the only major, minor, patch, and pre-release sections of
|
|
47063
|
+
// the version string are capturing groups. The build metadata is not a
|
|
47064
|
+
// capturing group, because it should not ever be used in version
|
|
47065
|
+
// comparison.
|
|
47066
|
+
|
|
47067
|
+
createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
|
|
47068
|
+
}${src[t.PRERELEASE]}?${
|
|
47069
|
+
src[t.BUILD]}?`);
|
|
47070
|
+
|
|
47071
|
+
createToken('FULL', `^${src[t.FULLPLAIN]}$`);
|
|
47072
|
+
|
|
47073
|
+
// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
|
|
47074
|
+
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
|
|
47075
|
+
// common in the npm registry.
|
|
47076
|
+
createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
|
|
47077
|
+
}${src[t.PRERELEASELOOSE]}?${
|
|
47078
|
+
src[t.BUILD]}?`);
|
|
47079
|
+
|
|
47080
|
+
createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`);
|
|
47081
|
+
|
|
47082
|
+
createToken('GTLT', '((?:<|>)?=?)');
|
|
47083
|
+
|
|
47084
|
+
// Something like "2.*" or "1.2.x".
|
|
47085
|
+
// Note that "x.x" is a valid xRange identifer, meaning "any version"
|
|
47086
|
+
// Only the first item is strictly required.
|
|
47087
|
+
createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);
|
|
47088
|
+
createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`);
|
|
47089
|
+
|
|
47090
|
+
createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
|
|
47091
|
+
`(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
|
|
47092
|
+
`(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
|
|
47093
|
+
`(?:${src[t.PRERELEASE]})?${
|
|
47094
|
+
src[t.BUILD]}?` +
|
|
47095
|
+
`)?)?`);
|
|
47096
|
+
|
|
47097
|
+
createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
|
47098
|
+
`(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
|
47099
|
+
`(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
|
|
47100
|
+
`(?:${src[t.PRERELEASELOOSE]})?${
|
|
47101
|
+
src[t.BUILD]}?` +
|
|
47102
|
+
`)?)?`);
|
|
47103
|
+
|
|
47104
|
+
createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`);
|
|
47105
|
+
createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`);
|
|
47106
|
+
|
|
47107
|
+
// Coercion.
|
|
47108
|
+
// Extract anything that could conceivably be a part of a valid semver
|
|
47109
|
+
createToken('COERCE', `${'(^|[^\\d])' +
|
|
47110
|
+
'(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
|
|
47111
|
+
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
|
|
47112
|
+
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
|
|
47113
|
+
`(?:$|[^\\d])`);
|
|
47114
|
+
createToken('COERCERTL', src[t.COERCE], true);
|
|
47115
|
+
|
|
47116
|
+
// Tilde ranges.
|
|
47117
|
+
// Meaning is "reasonably at or greater than"
|
|
47118
|
+
createToken('LONETILDE', '(?:~>?)');
|
|
47119
|
+
|
|
47120
|
+
createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true);
|
|
47121
|
+
exports.tildeTrimReplace = '$1~';
|
|
47122
|
+
|
|
47123
|
+
createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`);
|
|
47124
|
+
createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`);
|
|
47125
|
+
|
|
47126
|
+
// Caret ranges.
|
|
47127
|
+
// Meaning is "at least and backwards compatible with"
|
|
47128
|
+
createToken('LONECARET', '(?:\\^)');
|
|
47129
|
+
|
|
47130
|
+
createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true);
|
|
47131
|
+
exports.caretTrimReplace = '$1^';
|
|
47132
|
+
|
|
47133
|
+
createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`);
|
|
47134
|
+
createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`);
|
|
47135
|
+
|
|
47136
|
+
// A simple gt/lt/eq thing, or just "" to indicate "any version"
|
|
47137
|
+
createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`);
|
|
47138
|
+
createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`);
|
|
47139
|
+
|
|
47140
|
+
// An expression to strip any whitespace between the gtlt and the thing
|
|
47141
|
+
// it modifies, so that `> 1.2.3` ==> `>1.2.3`
|
|
47142
|
+
createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
|
|
47143
|
+
}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true);
|
|
47144
|
+
exports.comparatorTrimReplace = '$1$2$3';
|
|
47145
|
+
|
|
47146
|
+
// Something like `1.2.3 - 1.2.4`
|
|
47147
|
+
// Note that these all use the loose form, because they'll be
|
|
47148
|
+
// checked against either the strict or loose comparator form
|
|
47149
|
+
// later.
|
|
47150
|
+
createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
|
|
47151
|
+
`\\s+-\\s+` +
|
|
47152
|
+
`(${src[t.XRANGEPLAIN]})` +
|
|
47153
|
+
`\\s*$`);
|
|
47154
|
+
|
|
47155
|
+
createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
|
|
47156
|
+
`\\s+-\\s+` +
|
|
47157
|
+
`(${src[t.XRANGEPLAINLOOSE]})` +
|
|
47158
|
+
`\\s*$`);
|
|
47159
|
+
|
|
47160
|
+
// Star ranges basically just allow anything at all.
|
|
47161
|
+
createToken('STAR', '(<|>)?=?\\s*\\*');
|
|
47162
|
+
// >=0.0.0 is like a star
|
|
47163
|
+
createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$');
|
|
47164
|
+
createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$');
|
|
47165
|
+
});
|
|
47166
|
+
var re_2 = re_1.re;
|
|
47167
|
+
var re_3 = re_1.src;
|
|
47168
|
+
var re_4 = re_1.t;
|
|
47169
|
+
var re_5 = re_1.tildeTrimReplace;
|
|
47170
|
+
var re_6 = re_1.caretTrimReplace;
|
|
47171
|
+
var re_7 = re_1.comparatorTrimReplace;
|
|
47172
|
+
|
|
47173
|
+
// parse out just the options we care about so we always get a consistent
|
|
47174
|
+
// obj with keys in a consistent order.
|
|
47175
|
+
const opts = ['includePrerelease', 'loose', 'rtl'];
|
|
47176
|
+
const parseOptions = options =>
|
|
47177
|
+
!options ? {}
|
|
47178
|
+
: typeof options !== 'object' ? { loose: true }
|
|
47179
|
+
: opts.filter(k => options[k]).reduce((o, k) => {
|
|
47180
|
+
o[k] = true;
|
|
47181
|
+
return o
|
|
47182
|
+
}, {});
|
|
47183
|
+
var parseOptions_1 = parseOptions;
|
|
47184
|
+
|
|
47185
|
+
const numeric = /^[0-9]+$/;
|
|
47186
|
+
const compareIdentifiers = (a, b) => {
|
|
47187
|
+
const anum = numeric.test(a);
|
|
47188
|
+
const bnum = numeric.test(b);
|
|
47189
|
+
|
|
47190
|
+
if (anum && bnum) {
|
|
47191
|
+
a = +a;
|
|
47192
|
+
b = +b;
|
|
47193
|
+
}
|
|
47194
|
+
|
|
47195
|
+
return a === b ? 0
|
|
47196
|
+
: (anum && !bnum) ? -1
|
|
47197
|
+
: (bnum && !anum) ? 1
|
|
47198
|
+
: a < b ? -1
|
|
47199
|
+
: 1
|
|
47200
|
+
};
|
|
47201
|
+
|
|
47202
|
+
const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a);
|
|
47203
|
+
|
|
47204
|
+
var identifiers = {
|
|
47205
|
+
compareIdentifiers,
|
|
47206
|
+
rcompareIdentifiers,
|
|
47207
|
+
};
|
|
47208
|
+
|
|
47209
|
+
const { MAX_LENGTH: MAX_LENGTH$1, MAX_SAFE_INTEGER: MAX_SAFE_INTEGER$1 } = constants;
|
|
47210
|
+
const { re: re$1, t: t$1 } = re_1;
|
|
47211
|
+
|
|
47212
|
+
|
|
47213
|
+
const { compareIdentifiers: compareIdentifiers$1 } = identifiers;
|
|
47214
|
+
class SemVer {
|
|
47215
|
+
constructor (version, options) {
|
|
47216
|
+
options = parseOptions_1(options);
|
|
47217
|
+
|
|
47218
|
+
if (version instanceof SemVer) {
|
|
47219
|
+
if (version.loose === !!options.loose &&
|
|
47220
|
+
version.includePrerelease === !!options.includePrerelease) {
|
|
47221
|
+
return version
|
|
47222
|
+
} else {
|
|
47223
|
+
version = version.version;
|
|
47224
|
+
}
|
|
47225
|
+
} else if (typeof version !== 'string') {
|
|
47226
|
+
throw new TypeError(`Invalid Version: ${version}`)
|
|
47046
47227
|
}
|
|
47047
|
-
|
|
47048
|
-
|
|
47049
|
-
|
|
47228
|
+
|
|
47229
|
+
if (version.length > MAX_LENGTH$1) {
|
|
47230
|
+
throw new TypeError(
|
|
47231
|
+
`version is longer than ${MAX_LENGTH$1} characters`
|
|
47232
|
+
)
|
|
47050
47233
|
}
|
|
47051
|
-
|
|
47052
|
-
|
|
47053
|
-
|
|
47054
|
-
|
|
47055
|
-
|
|
47056
|
-
|
|
47057
|
-
|
|
47058
|
-
|
|
47059
|
-
|
|
47060
|
-
|
|
47061
|
-
|
|
47062
|
-
|
|
47063
|
-
yield this.BleManager.startNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
47064
|
-
this.addLog(`Started notifications for [actions] characteristic`);
|
|
47065
|
-
}
|
|
47066
|
-
catch (error) {
|
|
47067
|
-
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}`);
|
|
47068
|
-
}
|
|
47069
|
-
}
|
|
47070
|
-
if (!hasPendingActions && started) {
|
|
47071
|
-
started = false;
|
|
47072
|
-
try {
|
|
47073
|
-
yield this.BleManager.stopNotification(peripheralId, serviceUUID, characteristicUUID);
|
|
47074
|
-
this.addLog(`Stopped notifications for actions characteristic`);
|
|
47075
|
-
}
|
|
47076
|
-
catch (error) {
|
|
47077
|
-
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}`);
|
|
47078
|
-
}
|
|
47079
|
-
}
|
|
47080
|
-
})));
|
|
47081
|
-
selectedDevice$
|
|
47082
|
-
.pipe(switchMap((selectedDevice) => !osHasBluetoothSupport(selectedDevice) ? EMPTY : sideEffects$))
|
|
47083
|
-
.subscribe();
|
|
47084
|
-
});
|
|
47234
|
+
|
|
47235
|
+
debug_1('SemVer', version, options);
|
|
47236
|
+
this.options = options;
|
|
47237
|
+
this.loose = !!options.loose;
|
|
47238
|
+
// this isn't actually relevant for versions, but keep it so that we
|
|
47239
|
+
// don't run into trouble passing this.options around.
|
|
47240
|
+
this.includePrerelease = !!options.includePrerelease;
|
|
47241
|
+
|
|
47242
|
+
const m = version.trim().match(options.loose ? re$1[t$1.LOOSE] : re$1[t$1.FULL]);
|
|
47243
|
+
|
|
47244
|
+
if (!m) {
|
|
47245
|
+
throw new TypeError(`Invalid Version: ${version}`)
|
|
47085
47246
|
}
|
|
47086
|
-
|
|
47087
|
-
|
|
47088
|
-
|
|
47089
|
-
|
|
47090
|
-
|
|
47091
|
-
|
|
47092
|
-
|
|
47093
|
-
|
|
47094
|
-
|
|
47095
|
-
|
|
47096
|
-
this._removePendingAction(actionId);
|
|
47097
|
-
reject(new Error(`Action with id ${actionId} timed out after ${responseTimeout}ms`));
|
|
47098
|
-
});
|
|
47099
|
-
// listen for a response before writing
|
|
47100
|
-
this.subscribeToCharacteristic({
|
|
47101
|
-
characteristicName,
|
|
47102
|
-
manageNotifications: false
|
|
47103
|
-
})
|
|
47104
|
-
.pipe(filter((response) => (response === null || response === void 0 ? void 0 : response.actionId) === actionId), take(1))
|
|
47105
|
-
.subscribe((response) => {
|
|
47106
|
-
timeout$$1.unsubscribe();
|
|
47107
|
-
this._removePendingAction(actionId);
|
|
47108
|
-
resolve(response);
|
|
47109
|
-
});
|
|
47110
|
-
// register action by writing
|
|
47111
|
-
this.writeCharacteristic(characteristicName, payload).catch((error) => {
|
|
47112
|
-
this._removePendingAction(actionId);
|
|
47113
|
-
reject(error);
|
|
47114
|
-
});
|
|
47115
|
-
}
|
|
47116
|
-
else {
|
|
47117
|
-
this.writeCharacteristic(characteristicName, payload)
|
|
47118
|
-
.then(() => {
|
|
47119
|
-
resolve(null);
|
|
47120
|
-
})
|
|
47121
|
-
.catch((error) => {
|
|
47122
|
-
reject(error);
|
|
47123
|
-
});
|
|
47124
|
-
}
|
|
47125
|
-
}));
|
|
47126
|
-
});
|
|
47247
|
+
|
|
47248
|
+
this.raw = version;
|
|
47249
|
+
|
|
47250
|
+
// these are actually numbers
|
|
47251
|
+
this.major = +m[1];
|
|
47252
|
+
this.minor = +m[2];
|
|
47253
|
+
this.patch = +m[3];
|
|
47254
|
+
|
|
47255
|
+
if (this.major > MAX_SAFE_INTEGER$1 || this.major < 0) {
|
|
47256
|
+
throw new TypeError('Invalid major version')
|
|
47127
47257
|
}
|
|
47128
|
-
}
|
|
47129
47258
|
|
|
47130
|
-
|
|
47131
|
-
|
|
47132
|
-
const isObject$2 = (object) => object instanceof Object && object === Object(object);
|
|
47133
|
-
const isFunction$2 = (object) => typeof object === "function";
|
|
47134
|
-
const patch = (sample$$1) => (info) => {
|
|
47135
|
-
var _a;
|
|
47136
|
-
return (Object.assign(Object.assign({}, sample$$1), { info: Object.assign(Object.assign({}, ((_a = sample$$1 === null || sample$$1 === void 0 ? void 0 : sample$$1.info) !== null && _a !== void 0 ? _a : {})), (info || {})) }));
|
|
47137
|
-
};
|
|
47138
|
-
/**
|
|
47139
|
-
* Annotates stream with user-defined metadata
|
|
47140
|
-
* @method addInfo
|
|
47141
|
-
* @example eeg$.pipe(addinfo({ samplingRate: 256, channelNames: ["Af7", "Fp1", "Fp2", "Af8"] })
|
|
47142
|
-
* @param {Object} info Info to be added to the EEG stream. Relevant info may include: `samplingRate` and `channelNames`
|
|
47143
|
-
* @returns {Observable<Sample|Epoch|PSD>}
|
|
47144
|
-
*/
|
|
47145
|
-
const addInfo = (infoValue) => pipe(map((sample$$1) => {
|
|
47146
|
-
if (!isObject$2(sample$$1) ||
|
|
47147
|
-
(!isObject$2(infoValue) && !isFunction$2(infoValue))) {
|
|
47148
|
-
return sample$$1;
|
|
47259
|
+
if (this.minor > MAX_SAFE_INTEGER$1 || this.minor < 0) {
|
|
47260
|
+
throw new TypeError('Invalid minor version')
|
|
47149
47261
|
}
|
|
47150
|
-
const info = isFunction$2(infoValue) ? infoValue(sample$$1) : infoValue;
|
|
47151
|
-
return patch(sample$$1)(info);
|
|
47152
|
-
}));
|
|
47153
|
-
/**
|
|
47154
|
-
* Get a 2D data array organized by channel from an array of Samples. Credit to Ken from Seattle's elegant transposition
|
|
47155
|
-
* http://www.codesuck.com/2012/02/transpose-javascript-array-in-one-line.html
|
|
47156
|
-
* @method groupByChannel
|
|
47157
|
-
* @param {Array<Sample>} samplesBuffer Array of Samples to be grouped
|
|
47158
|
-
* @param {string} [dataProp] Name of the key associated with EEG data
|
|
47159
|
-
* @returns {Array<Array<number>>}
|
|
47160
|
-
*/
|
|
47161
|
-
const groupByChannel = (samplesBuffer, dataProp = defaultDataProp) => samplesBuffer[0][dataProp].map((_, channelIndex) => samplesBuffer.map((sample$$1) => sample$$1[dataProp][channelIndex]));
|
|
47162
|
-
/**
|
|
47163
|
-
* Takes an array or RxJS buffer of EEG Samples and returns an Epoch.
|
|
47164
|
-
* @method bufferToEpoch
|
|
47165
|
-
* @example eeg$.pipe(bufferTime(1000), bufferToEpoch({ samplingRate: 256 }))
|
|
47166
|
-
*
|
|
47167
|
-
* @param {Object} options - Data structure options
|
|
47168
|
-
* @param {number} [options.samplingRate] Sampling rate
|
|
47169
|
-
* @param {string} [options.dataProp='data'] Name of the key associated with eeg data
|
|
47170
|
-
*
|
|
47171
|
-
* @returns {Observable<Epoch>}
|
|
47172
|
-
*/
|
|
47173
|
-
const bufferToEpoch = ({ samplingRate = defaultSamplingRate, dataProp = defaultDataProp } = {}) => pipe(map((samplesArray) => ({
|
|
47174
|
-
[dataProp]: groupByChannel(samplesArray, dataProp),
|
|
47175
|
-
info: Object.assign(Object.assign({}, (samplesArray[0] && samplesArray[0].info
|
|
47176
|
-
? samplesArray[0].info
|
|
47177
|
-
: {})), { startTime: samplesArray[0].timestamp, samplingRate: samplesArray[0].info && samplesArray[0].info.samplingRate
|
|
47178
|
-
? samplesArray[0].info.samplingRate
|
|
47179
|
-
: samplingRate })
|
|
47180
|
-
})));
|
|
47181
|
-
/**
|
|
47182
|
-
* Converts a stream of individual Samples of EEG data into a stream of Epochs of a given duration emitted at specified interval. This operator functions similarly to a circular buffer internally and allows overlapping Epochs of data to be emitted (e.g. emitting the last one second of data every 100ms).
|
|
47183
|
-
* @method epoch
|
|
47184
|
-
* @example eeg$.pipe(epoch({ duration: 1024, interval: 100, samplingRate: 256 }))
|
|
47185
|
-
* @param {Object} options - Epoching options
|
|
47186
|
-
* @param {number} [options.duration=256] Number of samples to include in each epoch
|
|
47187
|
-
* @param {number} [options.interval=100] Time (ms) between emitted Epochs
|
|
47188
|
-
* @param {number} [options.samplingRate=256] Sampling rate
|
|
47189
|
-
* @param {string} [options.dataProp='data'] Name of the key associated with eeg data
|
|
47190
|
-
* @returns {Observable} Epoch
|
|
47191
|
-
*/
|
|
47192
|
-
const epoch = ({ duration, interval: interval$$1, samplingRate, dataProp = defaultDataProp }) => pipe(bufferCount(interval$$1), scan((acc, val) => acc.concat(val).slice(acc.length < duration ? 0 : -duration)), filter((samplesArray) => samplesArray.length === duration), bufferToEpoch({ samplingRate, dataProp }));
|
|
47193
47262
|
|
|
47194
|
-
|
|
47195
|
-
|
|
47196
|
-
/**
|
|
47197
|
-
* @hidden
|
|
47198
|
-
*/
|
|
47199
|
-
function csvBufferToEpoch(deviceInfo) {
|
|
47200
|
-
var _a;
|
|
47201
|
-
if (!(deviceInfo === null || deviceInfo === void 0 ? void 0 : deviceInfo.samplingRate)) {
|
|
47202
|
-
console.warn(`Didn't receive a sampling rate, defaulting to ${SAMPLING_RATE_FALLBACK}`);
|
|
47263
|
+
if (this.patch > MAX_SAFE_INTEGER$1 || this.patch < 0) {
|
|
47264
|
+
throw new TypeError('Invalid patch version')
|
|
47203
47265
|
}
|
|
47204
|
-
return pipe(csvBufferToSamples(), epoch({
|
|
47205
|
-
duration: EPOCH_BUFFER_SIZE,
|
|
47206
|
-
interval: EPOCH_BUFFER_SIZE,
|
|
47207
|
-
samplingRate: (_a = deviceInfo === null || deviceInfo === void 0 ? void 0 : deviceInfo.samplingRate) !== null && _a !== void 0 ? _a : SAMPLING_RATE_FALLBACK
|
|
47208
|
-
}), addInfo({
|
|
47209
|
-
channelNames: deviceInfo.channelNames,
|
|
47210
|
-
samplingRate: deviceInfo.samplingRate
|
|
47211
|
-
}));
|
|
47212
|
-
}
|
|
47213
|
-
/**
|
|
47214
|
-
* @hidden
|
|
47215
|
-
*/
|
|
47216
|
-
function csvBufferToSamples() {
|
|
47217
|
-
return pipe(mergeMap((samples) => from(samples)), map(([timestamp$$1, marker, ...data]) => ({
|
|
47218
|
-
timestamp: timestamp$$1,
|
|
47219
|
-
data
|
|
47220
|
-
})));
|
|
47221
|
-
}
|
|
47222
47266
|
|
|
47223
|
-
|
|
47224
|
-
|
|
47225
|
-
|
|
47226
|
-
|
|
47227
|
-
|
|
47228
|
-
|
|
47229
|
-
|
|
47230
|
-
|
|
47231
|
-
|
|
47232
|
-
|
|
47233
|
-
constructor(options) {
|
|
47234
|
-
this.selectedDevice$ = new ReplaySubject(1);
|
|
47235
|
-
this.isAuthenticated$ = new ReplaySubject(1);
|
|
47236
|
-
const { transport, selectedDevice$, createBluetoothToken } = options !== null && options !== void 0 ? options : {};
|
|
47237
|
-
if (!transport) {
|
|
47238
|
-
throw new Error(`No bluetooth transport provided.`);
|
|
47239
|
-
}
|
|
47240
|
-
this.transport = transport;
|
|
47241
|
-
// Pass events to the internal selectedDevice$ if selectedDevice$ is passed via options
|
|
47242
|
-
if (selectedDevice$) {
|
|
47243
|
-
selectedDevice$.subscribe(this.selectedDevice$);
|
|
47244
|
-
}
|
|
47245
|
-
// Auto Connect
|
|
47246
|
-
this.transport._autoConnect(this.selectedDevice$).subscribe({
|
|
47247
|
-
error: (error) => {
|
|
47248
|
-
var _a;
|
|
47249
|
-
this.transport.addLog(`Auto connect: error -> ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
|
|
47250
|
-
}
|
|
47251
|
-
});
|
|
47252
|
-
// Auto authentication
|
|
47253
|
-
if (typeof createBluetoothToken === "function") {
|
|
47254
|
-
this.transport.addLog("Auto authentication enabled");
|
|
47255
|
-
this._autoAuthenticate(createBluetoothToken).subscribe();
|
|
47256
|
-
}
|
|
47257
|
-
else {
|
|
47258
|
-
this.transport.addLog("Auto authentication not enabled");
|
|
47267
|
+
// numberify any prerelease numeric ids
|
|
47268
|
+
if (!m[4]) {
|
|
47269
|
+
this.prerelease = [];
|
|
47270
|
+
} else {
|
|
47271
|
+
this.prerelease = m[4].split('.').map((id) => {
|
|
47272
|
+
if (/^[0-9]+$/.test(id)) {
|
|
47273
|
+
const num = +id;
|
|
47274
|
+
if (num >= 0 && num < MAX_SAFE_INTEGER$1) {
|
|
47275
|
+
return num
|
|
47276
|
+
}
|
|
47259
47277
|
}
|
|
47260
|
-
|
|
47261
|
-
|
|
47262
|
-
// Multicast metrics (share)
|
|
47263
|
-
this._focus$ = this._subscribeWhileAuthenticated("focus");
|
|
47264
|
-
this._calm$ = this._subscribeWhileAuthenticated("calm");
|
|
47265
|
-
this._accelerometer$ = this._subscribeWhileAuthenticated("accelerometer");
|
|
47266
|
-
this._brainwavesRaw$ = this._subscribeWhileAuthenticated("raw");
|
|
47267
|
-
this._brainwavesRawUnfiltered$ =
|
|
47268
|
-
this._subscribeWhileAuthenticated("rawUnfiltered");
|
|
47269
|
-
this._brainwavesPSD$ = this._subscribeWhileAuthenticated("psd");
|
|
47270
|
-
this._brainwavesPowerByBand$ =
|
|
47271
|
-
this._subscribeWhileAuthenticated("powerByBand");
|
|
47272
|
-
this._signalQuality$ = this._subscribeWhileAuthenticated("signalQuality");
|
|
47273
|
-
this._status$ = this._subscribeWhileAuthenticated("status");
|
|
47274
|
-
this._settings$ = this._subscribeWhileAuthenticated("settings");
|
|
47275
|
-
this._wifiNearbyNetworks$ =
|
|
47276
|
-
this._subscribeWhileAuthenticated("wifiNearbyNetworks");
|
|
47277
|
-
this._wifiConnections$ =
|
|
47278
|
-
this._subscribeWhileAuthenticated("wifiConnections");
|
|
47278
|
+
return id
|
|
47279
|
+
});
|
|
47279
47280
|
}
|
|
47280
|
-
|
|
47281
|
-
|
|
47282
|
-
|
|
47283
|
-
|
|
47284
|
-
|
|
47285
|
-
|
|
47286
|
-
|
|
47287
|
-
|
|
47288
|
-
|
|
47289
|
-
: EMPTY), switchMap(() => __awaiter$f(this, void 0, void 0, function* () { return yield this.isAuthenticated(); })), tap(([isAuthenticated]) => __awaiter$f(this, void 0, void 0, function* () {
|
|
47290
|
-
if (!isAuthenticated) {
|
|
47291
|
-
const token = yield createBluetoothToken();
|
|
47292
|
-
yield this.authenticate(token);
|
|
47293
|
-
}
|
|
47294
|
-
else {
|
|
47295
|
-
this.transport.addLog(`Already authenticated`);
|
|
47296
|
-
}
|
|
47297
|
-
})))));
|
|
47281
|
+
|
|
47282
|
+
this.build = m[5] ? m[5].split('.') : [];
|
|
47283
|
+
this.format();
|
|
47284
|
+
}
|
|
47285
|
+
|
|
47286
|
+
format () {
|
|
47287
|
+
this.version = `${this.major}.${this.minor}.${this.patch}`;
|
|
47288
|
+
if (this.prerelease.length) {
|
|
47289
|
+
this.version += `-${this.prerelease.join('.')}`;
|
|
47298
47290
|
}
|
|
47299
|
-
|
|
47300
|
-
|
|
47291
|
+
return this.version
|
|
47292
|
+
}
|
|
47293
|
+
|
|
47294
|
+
toString () {
|
|
47295
|
+
return this.version
|
|
47296
|
+
}
|
|
47297
|
+
|
|
47298
|
+
compare (other) {
|
|
47299
|
+
debug_1('SemVer.compare', this.version, this.options, other);
|
|
47300
|
+
if (!(other instanceof SemVer)) {
|
|
47301
|
+
if (typeof other === 'string' && other === this.version) {
|
|
47302
|
+
return 0
|
|
47303
|
+
}
|
|
47304
|
+
other = new SemVer(other, this.options);
|
|
47301
47305
|
}
|
|
47302
|
-
|
|
47303
|
-
|
|
47304
|
-
|
|
47305
|
-
return osHasBluetoothSupport(selectedDevice);
|
|
47306
|
-
});
|
|
47306
|
+
|
|
47307
|
+
if (other.version === this.version) {
|
|
47308
|
+
return 0
|
|
47307
47309
|
}
|
|
47308
|
-
|
|
47309
|
-
|
|
47310
|
-
|
|
47311
|
-
|
|
47312
|
-
|
|
47313
|
-
|
|
47314
|
-
|
|
47315
|
-
}
|
|
47316
|
-
yield this.transport.writeCharacteristic("auth", token);
|
|
47317
|
-
const isAuthenticatedResponse = yield this.isAuthenticated();
|
|
47318
|
-
const [isAuthenticated] = isAuthenticatedResponse;
|
|
47319
|
-
this.transport.addLog(`Authentication ${isAuthenticated ? "succeeded" : "failed"}`);
|
|
47320
|
-
this.isAuthenticated$.next(isAuthenticated);
|
|
47321
|
-
return isAuthenticatedResponse;
|
|
47322
|
-
});
|
|
47310
|
+
|
|
47311
|
+
return this.compareMain(other) || this.comparePre(other)
|
|
47312
|
+
}
|
|
47313
|
+
|
|
47314
|
+
compareMain (other) {
|
|
47315
|
+
if (!(other instanceof SemVer)) {
|
|
47316
|
+
other = new SemVer(other, this.options);
|
|
47323
47317
|
}
|
|
47324
|
-
|
|
47325
|
-
|
|
47326
|
-
|
|
47327
|
-
|
|
47328
|
-
|
|
47329
|
-
|
|
47318
|
+
|
|
47319
|
+
return (
|
|
47320
|
+
compareIdentifiers$1(this.major, other.major) ||
|
|
47321
|
+
compareIdentifiers$1(this.minor, other.minor) ||
|
|
47322
|
+
compareIdentifiers$1(this.patch, other.patch)
|
|
47323
|
+
)
|
|
47324
|
+
}
|
|
47325
|
+
|
|
47326
|
+
comparePre (other) {
|
|
47327
|
+
if (!(other instanceof SemVer)) {
|
|
47328
|
+
other = new SemVer(other, this.options);
|
|
47330
47329
|
}
|
|
47331
|
-
|
|
47332
|
-
|
|
47333
|
-
|
|
47334
|
-
|
|
47330
|
+
|
|
47331
|
+
// NOT having a prerelease is > having one
|
|
47332
|
+
if (this.prerelease.length && !other.prerelease.length) {
|
|
47333
|
+
return -1
|
|
47334
|
+
} else if (!this.prerelease.length && other.prerelease.length) {
|
|
47335
|
+
return 1
|
|
47336
|
+
} else if (!this.prerelease.length && !other.prerelease.length) {
|
|
47337
|
+
return 0
|
|
47338
|
+
}
|
|
47339
|
+
|
|
47340
|
+
let i = 0;
|
|
47341
|
+
do {
|
|
47342
|
+
const a = this.prerelease[i];
|
|
47343
|
+
const b = other.prerelease[i];
|
|
47344
|
+
debug_1('prerelease compare', i, a, b);
|
|
47345
|
+
if (a === undefined && b === undefined) {
|
|
47346
|
+
return 0
|
|
47347
|
+
} else if (b === undefined) {
|
|
47348
|
+
return 1
|
|
47349
|
+
} else if (a === undefined) {
|
|
47350
|
+
return -1
|
|
47351
|
+
} else if (a === b) {
|
|
47352
|
+
continue
|
|
47353
|
+
} else {
|
|
47354
|
+
return compareIdentifiers$1(a, b)
|
|
47355
|
+
}
|
|
47356
|
+
} while (++i)
|
|
47357
|
+
}
|
|
47358
|
+
|
|
47359
|
+
compareBuild (other) {
|
|
47360
|
+
if (!(other instanceof SemVer)) {
|
|
47361
|
+
other = new SemVer(other, this.options);
|
|
47362
|
+
}
|
|
47363
|
+
|
|
47364
|
+
let i = 0;
|
|
47365
|
+
do {
|
|
47366
|
+
const a = this.build[i];
|
|
47367
|
+
const b = other.build[i];
|
|
47368
|
+
debug_1('prerelease compare', i, a, b);
|
|
47369
|
+
if (a === undefined && b === undefined) {
|
|
47370
|
+
return 0
|
|
47371
|
+
} else if (b === undefined) {
|
|
47372
|
+
return 1
|
|
47373
|
+
} else if (a === undefined) {
|
|
47374
|
+
return -1
|
|
47375
|
+
} else if (a === b) {
|
|
47376
|
+
continue
|
|
47377
|
+
} else {
|
|
47378
|
+
return compareIdentifiers$1(a, b)
|
|
47379
|
+
}
|
|
47380
|
+
} while (++i)
|
|
47381
|
+
}
|
|
47382
|
+
|
|
47383
|
+
// preminor will bump the version up to the next minor release, and immediately
|
|
47384
|
+
// down to pre-release. premajor and prepatch work the same way.
|
|
47385
|
+
inc (release, identifier) {
|
|
47386
|
+
switch (release) {
|
|
47387
|
+
case 'premajor':
|
|
47388
|
+
this.prerelease.length = 0;
|
|
47389
|
+
this.patch = 0;
|
|
47390
|
+
this.minor = 0;
|
|
47391
|
+
this.major++;
|
|
47392
|
+
this.inc('pre', identifier);
|
|
47393
|
+
break
|
|
47394
|
+
case 'preminor':
|
|
47395
|
+
this.prerelease.length = 0;
|
|
47396
|
+
this.patch = 0;
|
|
47397
|
+
this.minor++;
|
|
47398
|
+
this.inc('pre', identifier);
|
|
47399
|
+
break
|
|
47400
|
+
case 'prepatch':
|
|
47401
|
+
// If this is already a prerelease, it will bump to the next version
|
|
47402
|
+
// drop any prereleases that might already exist, since they are not
|
|
47403
|
+
// relevant at this point.
|
|
47404
|
+
this.prerelease.length = 0;
|
|
47405
|
+
this.inc('patch', identifier);
|
|
47406
|
+
this.inc('pre', identifier);
|
|
47407
|
+
break
|
|
47408
|
+
// If the input is a non-prerelease version, this acts the same as
|
|
47409
|
+
// prepatch.
|
|
47410
|
+
case 'prerelease':
|
|
47411
|
+
if (this.prerelease.length === 0) {
|
|
47412
|
+
this.inc('patch', identifier);
|
|
47335
47413
|
}
|
|
47336
|
-
|
|
47337
|
-
|
|
47414
|
+
this.inc('pre', identifier);
|
|
47415
|
+
break
|
|
47416
|
+
|
|
47417
|
+
case 'major':
|
|
47418
|
+
// If this is a pre-major version, bump up to the same major version.
|
|
47419
|
+
// Otherwise increment major.
|
|
47420
|
+
// 1.0.0-5 bumps to 1.0.0
|
|
47421
|
+
// 1.1.0 bumps to 2.0.0
|
|
47422
|
+
if (
|
|
47423
|
+
this.minor !== 0 ||
|
|
47424
|
+
this.patch !== 0 ||
|
|
47425
|
+
this.prerelease.length === 0
|
|
47426
|
+
) {
|
|
47427
|
+
this.major++;
|
|
47338
47428
|
}
|
|
47339
|
-
|
|
47340
|
-
|
|
47341
|
-
|
|
47342
|
-
|
|
47343
|
-
|
|
47344
|
-
|
|
47429
|
+
this.minor = 0;
|
|
47430
|
+
this.patch = 0;
|
|
47431
|
+
this.prerelease = [];
|
|
47432
|
+
break
|
|
47433
|
+
case 'minor':
|
|
47434
|
+
// If this is a pre-minor version, bump up to the same minor version.
|
|
47435
|
+
// Otherwise increment minor.
|
|
47436
|
+
// 1.2.0-5 bumps to 1.2.0
|
|
47437
|
+
// 1.2.1 bumps to 1.3.0
|
|
47438
|
+
if (this.patch !== 0 || this.prerelease.length === 0) {
|
|
47439
|
+
this.minor++;
|
|
47345
47440
|
}
|
|
47346
|
-
|
|
47347
|
-
|
|
47348
|
-
|
|
47349
|
-
|
|
47441
|
+
this.patch = 0;
|
|
47442
|
+
this.prerelease = [];
|
|
47443
|
+
break
|
|
47444
|
+
case 'patch':
|
|
47445
|
+
// If this is not a pre-release version, it will increment the patch.
|
|
47446
|
+
// If it is a pre-release it will bump up to the same patch version.
|
|
47447
|
+
// 1.2.0-5 patches to 1.2.0
|
|
47448
|
+
// 1.2.0 patches to 1.2.1
|
|
47449
|
+
if (this.prerelease.length === 0) {
|
|
47450
|
+
this.patch++;
|
|
47350
47451
|
}
|
|
47351
|
-
|
|
47352
|
-
|
|
47353
|
-
|
|
47354
|
-
|
|
47355
|
-
|
|
47356
|
-
|
|
47357
|
-
|
|
47358
|
-
|
|
47359
|
-
|
|
47360
|
-
|
|
47361
|
-
|
|
47362
|
-
|
|
47363
|
-
|
|
47364
|
-
return this.transport.readCharacteristic("deviceId");
|
|
47365
|
-
});
|
|
47366
|
-
}
|
|
47367
|
-
_withAuthentication(getter) {
|
|
47368
|
-
return __awaiter$f(this, void 0, void 0, function* () {
|
|
47369
|
-
// First check if the OS supports Bluetooth before checking if the device is authenticated
|
|
47370
|
-
const hasBluetoothSupport = yield this._hasBluetoothSupport();
|
|
47371
|
-
if (!hasBluetoothSupport) {
|
|
47372
|
-
const errorMessage = `The OS version does not support Bluetooth.`;
|
|
47373
|
-
this.transport.addLog(errorMessage);
|
|
47374
|
-
return Promise.reject(errorMessage);
|
|
47452
|
+
this.prerelease = [];
|
|
47453
|
+
break
|
|
47454
|
+
// This probably shouldn't be used publicly.
|
|
47455
|
+
// 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
|
|
47456
|
+
case 'pre':
|
|
47457
|
+
if (this.prerelease.length === 0) {
|
|
47458
|
+
this.prerelease = [0];
|
|
47459
|
+
} else {
|
|
47460
|
+
let i = this.prerelease.length;
|
|
47461
|
+
while (--i >= 0) {
|
|
47462
|
+
if (typeof this.prerelease[i] === 'number') {
|
|
47463
|
+
this.prerelease[i]++;
|
|
47464
|
+
i = -2;
|
|
47375
47465
|
}
|
|
47376
|
-
|
|
47377
|
-
|
|
47378
|
-
|
|
47379
|
-
|
|
47380
|
-
|
|
47466
|
+
}
|
|
47467
|
+
if (i === -1) {
|
|
47468
|
+
// didn't increment anything
|
|
47469
|
+
this.prerelease.push(0);
|
|
47470
|
+
}
|
|
47471
|
+
}
|
|
47472
|
+
if (identifier) {
|
|
47473
|
+
// 1.2.0-beta.1 bumps to 1.2.0-beta.2,
|
|
47474
|
+
// 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
|
|
47475
|
+
if (compareIdentifiers$1(this.prerelease[0], identifier) === 0) {
|
|
47476
|
+
if (isNaN(this.prerelease[1])) {
|
|
47477
|
+
this.prerelease = [identifier, 0];
|
|
47381
47478
|
}
|
|
47382
|
-
|
|
47383
|
-
|
|
47384
|
-
|
|
47385
|
-
_subscribeWhileAuthenticated(characteristicName) {
|
|
47386
|
-
return this.selectedDevice$.pipe(switchMap((selectedDevice) => !osHasBluetoothSupport(selectedDevice)
|
|
47387
|
-
? EMPTY
|
|
47388
|
-
: this.isAuthenticated$.pipe(distinctUntilChanged(), switchMap((isAuthenticated) => isAuthenticated
|
|
47389
|
-
? this.transport.subscribeToCharacteristic({
|
|
47390
|
-
characteristicName
|
|
47391
|
-
})
|
|
47392
|
-
: EMPTY))), share());
|
|
47393
|
-
}
|
|
47394
|
-
focus() {
|
|
47395
|
-
return this._focus$;
|
|
47396
|
-
}
|
|
47397
|
-
calm() {
|
|
47398
|
-
return this._calm$;
|
|
47399
|
-
}
|
|
47400
|
-
accelerometer() {
|
|
47401
|
-
return this._accelerometer$;
|
|
47402
|
-
}
|
|
47403
|
-
brainwaves(label) {
|
|
47404
|
-
switch (label) {
|
|
47405
|
-
default:
|
|
47406
|
-
case "raw":
|
|
47407
|
-
return defer(() => this.getInfo()).pipe(switchMap((deviceInfo) => this._brainwavesRaw$.pipe(csvBufferToEpoch(deviceInfo))));
|
|
47408
|
-
case "rawUnfiltered":
|
|
47409
|
-
return defer(() => this.getInfo()).pipe(switchMap((deviceInfo) => this._brainwavesRawUnfiltered$.pipe(csvBufferToEpoch(deviceInfo))));
|
|
47410
|
-
case "psd":
|
|
47411
|
-
return this._brainwavesPSD$;
|
|
47412
|
-
case "powerByBand":
|
|
47413
|
-
return this._brainwavesPowerByBand$;
|
|
47479
|
+
} else {
|
|
47480
|
+
this.prerelease = [identifier, 0];
|
|
47481
|
+
}
|
|
47414
47482
|
}
|
|
47483
|
+
break
|
|
47484
|
+
|
|
47485
|
+
default:
|
|
47486
|
+
throw new Error(`invalid increment argument: ${release}`)
|
|
47415
47487
|
}
|
|
47416
|
-
|
|
47417
|
-
|
|
47418
|
-
|
|
47419
|
-
|
|
47420
|
-
|
|
47421
|
-
|
|
47422
|
-
|
|
47423
|
-
|
|
47424
|
-
|
|
47425
|
-
|
|
47426
|
-
|
|
47427
|
-
|
|
47428
|
-
|
|
47429
|
-
|
|
47430
|
-
|
|
47431
|
-
|
|
47432
|
-
|
|
47433
|
-
|
|
47434
|
-
|
|
47435
|
-
})));
|
|
47436
|
-
});
|
|
47437
|
-
}
|
|
47438
|
-
status() {
|
|
47439
|
-
return this._status$;
|
|
47440
|
-
}
|
|
47441
|
-
dispatchAction(action) {
|
|
47442
|
-
return __awaiter$f(this, void 0, void 0, function* () {
|
|
47443
|
-
return yield this._withAuthentication(() => this.transport.dispatchAction({
|
|
47444
|
-
characteristicName: "actions",
|
|
47445
|
-
action
|
|
47446
|
-
}));
|
|
47447
|
-
});
|
|
47448
|
-
}
|
|
47449
|
-
settings() {
|
|
47450
|
-
return this._settings$;
|
|
47488
|
+
this.format();
|
|
47489
|
+
this.raw = this.version;
|
|
47490
|
+
return this
|
|
47491
|
+
}
|
|
47492
|
+
}
|
|
47493
|
+
|
|
47494
|
+
var semver = SemVer;
|
|
47495
|
+
|
|
47496
|
+
const compare = (a, b, loose) =>
|
|
47497
|
+
new semver(a, loose).compare(new semver(b, loose));
|
|
47498
|
+
|
|
47499
|
+
var compare_1 = compare;
|
|
47500
|
+
|
|
47501
|
+
const gte = (a, b, loose) => compare_1(a, b, loose) >= 0;
|
|
47502
|
+
var gte_1 = gte;
|
|
47503
|
+
|
|
47504
|
+
function osHasBluetoothSupport(selectedDevice, osVersion) {
|
|
47505
|
+
if (!selectedDevice) {
|
|
47506
|
+
return false;
|
|
47451
47507
|
}
|
|
47452
|
-
|
|
47453
|
-
|
|
47454
|
-
|
|
47455
|
-
|
|
47456
|
-
command: "queue",
|
|
47457
|
-
responseRequired: true,
|
|
47458
|
-
responseTimeout: 4000,
|
|
47459
|
-
// @TODO: implement validation logic as per SDK
|
|
47460
|
-
message: { effects }
|
|
47461
|
-
});
|
|
47508
|
+
// Only the Crown supports Bluetooth
|
|
47509
|
+
const isCrown = Number(selectedDevice.modelVersion) >= 3;
|
|
47510
|
+
if (!isCrown) {
|
|
47511
|
+
return false;
|
|
47462
47512
|
}
|
|
47463
|
-
|
|
47464
|
-
|
|
47465
|
-
|
|
47466
|
-
connections: () => this._wifiConnections$,
|
|
47467
|
-
connect: (ssid, password) => {
|
|
47468
|
-
if (!ssid) {
|
|
47469
|
-
return Promise.reject(`Missing ssid`);
|
|
47470
|
-
}
|
|
47471
|
-
return this.dispatchAction({
|
|
47472
|
-
action: "wifi",
|
|
47473
|
-
command: "connect",
|
|
47474
|
-
responseRequired: true,
|
|
47475
|
-
responseTimeout: 1000 * 60 * 2,
|
|
47476
|
-
message: {
|
|
47477
|
-
ssid,
|
|
47478
|
-
password: password !== null && password !== void 0 ? password : null
|
|
47479
|
-
}
|
|
47480
|
-
});
|
|
47481
|
-
},
|
|
47482
|
-
forgetConnection: (ssid) => {
|
|
47483
|
-
if (!ssid) {
|
|
47484
|
-
return Promise.reject(`Missing ssid`);
|
|
47485
|
-
}
|
|
47486
|
-
return this.dispatchAction({
|
|
47487
|
-
action: "wifi",
|
|
47488
|
-
command: "forget-connection",
|
|
47489
|
-
responseRequired: true,
|
|
47490
|
-
responseTimeout: 1000 * 15,
|
|
47491
|
-
message: {
|
|
47492
|
-
ssid
|
|
47493
|
-
}
|
|
47494
|
-
});
|
|
47495
|
-
},
|
|
47496
|
-
reset: () => {
|
|
47497
|
-
return this.dispatchAction({
|
|
47498
|
-
action: "wifi",
|
|
47499
|
-
command: "reset",
|
|
47500
|
-
responseRequired: true,
|
|
47501
|
-
responseTimeout: 1000 * 30,
|
|
47502
|
-
message: {
|
|
47503
|
-
// without this, the action will resolve as soon as the
|
|
47504
|
-
// action is received by the OS
|
|
47505
|
-
respondOnSuccess: true
|
|
47506
|
-
}
|
|
47507
|
-
});
|
|
47508
|
-
},
|
|
47509
|
-
speedTest: () => {
|
|
47510
|
-
return this.dispatchAction({
|
|
47511
|
-
action: "wifi",
|
|
47512
|
-
command: "speed-test",
|
|
47513
|
-
responseRequired: true,
|
|
47514
|
-
responseTimeout: 1000 * 60 * 1 // 1 minute
|
|
47515
|
-
});
|
|
47516
|
-
}
|
|
47517
|
-
};
|
|
47513
|
+
const isEmulator = !!(selectedDevice === null || selectedDevice === void 0 ? void 0 : selectedDevice.emulator);
|
|
47514
|
+
if (isEmulator) {
|
|
47515
|
+
return false;
|
|
47518
47516
|
}
|
|
47517
|
+
// `osVersion` is updated in real time,
|
|
47518
|
+
// unlike accessing via `selectedDevice.osVersion`
|
|
47519
|
+
return gte_1(osVersion !== null && osVersion !== void 0 ? osVersion : selectedDevice.osVersion, "16.0.0");
|
|
47519
47520
|
}
|
|
47520
47521
|
|
|
47521
47522
|
var __awaiter$g = function (thisArg, _arguments, P, generator) {
|
|
@@ -47570,6 +47571,7 @@ var Neurosity = (function (exports) {
|
|
|
47570
47571
|
if (!!bluetoothTransport) {
|
|
47571
47572
|
this.bluetoothClient = new BluetoothClient({
|
|
47572
47573
|
selectedDevice$: this.onDeviceChange(),
|
|
47574
|
+
osHasBluetoothSupport$: this._osHasBluetoothSupport(),
|
|
47573
47575
|
createBluetoothToken: this.createBluetoothToken.bind(this),
|
|
47574
47576
|
transport: bluetoothTransport
|
|
47575
47577
|
});
|
|
@@ -47600,6 +47602,16 @@ var Neurosity = (function (exports) {
|
|
|
47600
47602
|
this.streamingMode$.next(streamingMode);
|
|
47601
47603
|
}
|
|
47602
47604
|
}
|
|
47605
|
+
/**
|
|
47606
|
+
*
|
|
47607
|
+
* @hidden
|
|
47608
|
+
*/
|
|
47609
|
+
_osHasBluetoothSupport() {
|
|
47610
|
+
return combineLatest({
|
|
47611
|
+
selectedDevice: this.onDeviceChange(),
|
|
47612
|
+
osVersion: this.osVersion().pipe(startWith(null))
|
|
47613
|
+
}).pipe(map(({ selectedDevice, osVersion }) => osHasBluetoothSupport(selectedDevice, osVersion)));
|
|
47614
|
+
}
|
|
47603
47615
|
/**
|
|
47604
47616
|
* Subscribe to the device's streaming state changes and the current strategy
|
|
47605
47617
|
*
|
|
@@ -47615,12 +47627,14 @@ var Neurosity = (function (exports) {
|
|
|
47615
47627
|
streamingState() {
|
|
47616
47628
|
const isWifiOnline = (state) => [STATUS.ONLINE, STATUS.UPDATING].includes(state);
|
|
47617
47629
|
return this.streamingMode$.pipe(switchMap((streamingMode) => {
|
|
47618
|
-
return
|
|
47619
|
-
|
|
47630
|
+
return combineLatest({
|
|
47631
|
+
selectedDevice: this.onDeviceChange(),
|
|
47632
|
+
osHasBluetoothSupport: this._osHasBluetoothSupport()
|
|
47633
|
+
}).pipe(switchMap(({ selectedDevice, osHasBluetoothSupport: osHasBluetoothSupport$$1 }) => {
|
|
47634
|
+
if (!selectedDevice) {
|
|
47620
47635
|
return EMPTY;
|
|
47621
47636
|
}
|
|
47622
|
-
const isUnableToUseBluetooth = this.isMissingBluetoothTransport ||
|
|
47623
|
-
!osHasBluetoothSupport(selectDevice);
|
|
47637
|
+
const isUnableToUseBluetooth = this.isMissingBluetoothTransport || !osHasBluetoothSupport$$1;
|
|
47624
47638
|
if (isUnableToUseBluetooth) {
|
|
47625
47639
|
return this.cloudClient.status().pipe(map(({ state }) => ({
|
|
47626
47640
|
connected: isWifiOnline(state),
|
|
@@ -48286,7 +48300,7 @@ var Neurosity = (function (exports) {
|
|
|
48286
48300
|
if (hasOAuthError) {
|
|
48287
48301
|
return throwError(() => OAuthError);
|
|
48288
48302
|
}
|
|
48289
|
-
return this.cloudClient.
|
|
48303
|
+
return this.cloudClient.osVersion();
|
|
48290
48304
|
}
|
|
48291
48305
|
/**
|
|
48292
48306
|
* <StreamingModes wifi={true} bluetooth={true} />
|