@wemap/providers 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/babel.config.js +11 -0
- package/config.json +4 -0
- package/debug/absolute-attitude.html +16 -0
- package/debug/absolute-position.html +16 -0
- package/debug/attitude.html +16 -0
- package/debug/components/AbsoluteAttitudeComponent.jsx +142 -0
- package/debug/components/AbsolutePositionComponent.jsx +79 -0
- package/debug/components/AttitudeComponent.jsx +40 -0
- package/debug/components/Common.css +27 -0
- package/debug/components/GnssWifiComponent.jsx +53 -0
- package/debug/components/ImuComponent.jsx +53 -0
- package/debug/components/InclinationComponent.jsx +68 -0
- package/debug/components/MapComponent.jsx +366 -0
- package/debug/components/NavigationConfig.js +112 -0
- package/debug/components/PoseComponent.jsx +168 -0
- package/debug/components/RelativeAttitudeComponent.jsx +85 -0
- package/debug/components/StartStopComponent.jsx +45 -0
- package/debug/components/StepDetectionComponent.jsx +39 -0
- package/debug/components/Utils.js +216 -0
- package/debug/components/index.js +30 -0
- package/debug/components/old/PositioningComponent.jsx +29 -0
- package/debug/components/old/PositioningInclinationComponent.jsx +82 -0
- package/debug/components/old/PositioningPoseComponent.jsx +117 -0
- package/debug/gnss-wifi.html +16 -0
- package/debug/imu.html +16 -0
- package/debug/inclination.html +16 -0
- package/debug/pose.html +16 -0
- package/debug/positioning-legacy.html +16 -0
- package/debug/relative-attitude.html +16 -0
- package/debug/step-detection.html +16 -0
- package/index.js +7 -0
- package/package.json +67 -0
- package/src/Providers.js +80 -0
- package/src/ProvidersInterface.js +125 -0
- package/src/ProvidersOptions.js +29 -0
- package/src/errors/AskImuOnDesktopError.js +9 -0
- package/src/errors/ContainsIgnoredProviderError.js +9 -0
- package/src/errors/GeolocationApiMissingError.js +9 -0
- package/src/errors/GeolocationPermissionDeniedError.js +9 -0
- package/src/errors/GeolocationPositionUnavailableError.js +9 -0
- package/src/errors/IpResolveServerError.js +9 -0
- package/src/errors/MissingAccelerometerError.js +11 -0
- package/src/errors/MissingArCoreError.js +9 -0
- package/src/errors/MissingGyroscopeError.js +11 -0
- package/src/errors/MissingMagnetometerError.js +9 -0
- package/src/errors/MissingNativeInterfaceError.js +9 -0
- package/src/errors/MissingSensorError.js +14 -0
- package/src/errors/NoProviderFoundError.js +9 -0
- package/src/events/Availability.js +44 -0
- package/src/events/EventType.js +33 -0
- package/src/events/ProviderEvent.js +32 -0
- package/src/events/ProvidersLogger.js +83 -0
- package/src/providers/Constants.js +5 -0
- package/src/providers/FakeProvider.spec.js +57 -0
- package/src/providers/MetaProvider.js +42 -0
- package/src/providers/Provider.js +314 -0
- package/src/providers/Provider.spec.js +136 -0
- package/src/providers/ProviderState.js +5 -0
- package/src/providers/attitude/AttitudeProvider.js +63 -0
- package/src/providers/attitude/EkfAttitude.js +224 -0
- package/src/providers/attitude/EkfAttitude.spec.js +114 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.js +224 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeFromRelAttProvider.js +134 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeProvider.js +143 -0
- package/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.js +89 -0
- package/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.js +114 -0
- package/src/providers/attitude/relative/RelativeAttitudeProvider.js +103 -0
- package/src/providers/imu/AccelerometerProvider.js +61 -0
- package/src/providers/imu/GyroscopeProvider.js +61 -0
- package/src/providers/imu/ImuProvider.js +122 -0
- package/src/providers/inclination/InclinationFromAccProvider.js +87 -0
- package/src/providers/inclination/InclinationFromAttitudeProvider.js +77 -0
- package/src/providers/inclination/InclinationProvider.js +69 -0
- package/src/providers/legacy/AbsolutePdrProvider.js +258 -0
- package/src/providers/legacy/ArCoreAbsoluteProvider.js +230 -0
- package/src/providers/legacy/GnssWifiPdrProvider.js +217 -0
- package/src/providers/legacy/MapMatchingProvider.js +65 -0
- package/src/providers/legacy/PdrProvider.old.js +300 -0
- package/src/providers/legacy/PoseProvider.js +68 -0
- package/src/providers/legacy/helpers/HeadingUnlocker.js +47 -0
- package/src/providers/legacy/helpers/HeadingUnlocker.spec.js +53 -0
- package/src/providers/legacy/helpers/Smoother.js +92 -0
- package/src/providers/legacy/helpers/Smoother.spec.js +426 -0
- package/src/providers/legacy/helpers/ThugDetector.js +37 -0
- package/src/providers/others/CameraNativeProvider.js +44 -0
- package/src/providers/position/absolute/AbsolutePositionFromRelProvider.js +109 -0
- package/src/providers/position/absolute/AbsolutePositionProvider.js +172 -0
- package/src/providers/position/absolute/GnssWifiProvider.js +122 -0
- package/src/providers/position/absolute/IpProvider.js +68 -0
- package/src/providers/position/relative/ArCoreProvider.js +197 -0
- package/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.js +85 -0
- package/src/providers/position/relative/GeoRelativePositionProvider.js +66 -0
- package/src/providers/position/relative/PdrProvider.js +132 -0
- package/src/providers/steps/StepDetectionLadetto.js +67 -0
- package/src/providers/steps/StepDetectionMinMaxPeaks.js +80 -0
- package/src/providers/steps/StepDetectionMinMaxPeaks2.js +108 -0
- package/src/providers/steps/StepDetectionProvider.js +100 -0
- package/src/smoothers/PositionSmoother.js +86 -0
- package/src/smoothers/PositionSmoother.spec.js +55 -0
- package/webpack/webpack.common.js +20 -0
- package/webpack/webpack.dev.js +24 -0
- package/webpack/webpack.prod.js +15 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import Logger from '@wemap/logger';
|
|
2
|
+
|
|
3
|
+
let currentId = 0;
|
|
4
|
+
const objectsIdMap = new WeakMap();
|
|
5
|
+
|
|
6
|
+
let pushEvents = {};
|
|
7
|
+
let pushEventsRef = {};
|
|
8
|
+
|
|
9
|
+
let interval;
|
|
10
|
+
let initDate;
|
|
11
|
+
|
|
12
|
+
class ProvidersLogger {
|
|
13
|
+
|
|
14
|
+
static _enabled = false;
|
|
15
|
+
|
|
16
|
+
static get enabled() {
|
|
17
|
+
return this._enabled;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static set enabled(_newVal) {
|
|
21
|
+
this._enabled = _newVal;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static initializeInterval() {
|
|
25
|
+
|
|
26
|
+
if (interval) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interval = setInterval(() => {
|
|
31
|
+
|
|
32
|
+
for (const [key, value] of Object.entries(pushEvents)) {
|
|
33
|
+
Logger.debug('Received ' + value + ' notifications from ' + pushEventsRef[key].constructor.name + ' last second');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pushEvents = {};
|
|
37
|
+
pushEventsRef = {};
|
|
38
|
+
}, 1000);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static getObjectId(object) {
|
|
42
|
+
if (!objectsIdMap.has(object)) {
|
|
43
|
+
objectsIdMap.set(object, ++currentId);
|
|
44
|
+
}
|
|
45
|
+
return objectsIdMap.get(object);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static addEvent(object, method) {
|
|
49
|
+
|
|
50
|
+
if (!ProvidersLogger.enabled) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!initDate) {
|
|
55
|
+
initDate = Date.now();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ProvidersLogger.initializeInterval();
|
|
59
|
+
|
|
60
|
+
const objectId = ProvidersLogger.getObjectId(object);
|
|
61
|
+
const objectClassName = object.constructor.name;
|
|
62
|
+
|
|
63
|
+
Logger.debug(objectClassName + '[' + objectId + '].' + method);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static incrementNotifications(object) {
|
|
67
|
+
|
|
68
|
+
if (!ProvidersLogger.enabled) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const objectId = ProvidersLogger.getObjectId(object);
|
|
73
|
+
|
|
74
|
+
let counter = pushEvents[objectId];
|
|
75
|
+
if (!counter) {
|
|
76
|
+
counter = 0;
|
|
77
|
+
pushEventsRef[objectId] = object;
|
|
78
|
+
}
|
|
79
|
+
pushEvents[objectId] = counter + 1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
export default ProvidersLogger;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { UserPosition } from '@wemap/geo';
|
|
2
|
+
|
|
3
|
+
import Provider from './Provider';
|
|
4
|
+
import Availability from '../events/Availability';
|
|
5
|
+
|
|
6
|
+
import EventType from '../events/EventType';
|
|
7
|
+
import { TimeUtils } from '@wemap/utils';
|
|
8
|
+
|
|
9
|
+
class FakeProvider1 extends Provider { }
|
|
10
|
+
|
|
11
|
+
class FakeProvider5 extends Provider {
|
|
12
|
+
start() {}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class FakeProvider2 extends Provider {
|
|
16
|
+
get _availability() {
|
|
17
|
+
return Availability.no(new Error());
|
|
18
|
+
}
|
|
19
|
+
start() { }
|
|
20
|
+
stop() { }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class FakeProvider3 extends Provider {
|
|
24
|
+
start() {
|
|
25
|
+
this.intervalId = setInterval(() => {
|
|
26
|
+
const fakePosition = new UserPosition(Math.random() * 45, Math.random() * 180);
|
|
27
|
+
this.notify(this.createEvent(EventType.AbsolutePosition, fakePosition));
|
|
28
|
+
this.notify(this.createEvent(EventType.AbsolutePosition, fakePosition, TimeUtils.preciseTime));
|
|
29
|
+
}, 1);
|
|
30
|
+
}
|
|
31
|
+
stop() {
|
|
32
|
+
clearInterval(this.intervalId);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class FakeProvider4 extends Provider {
|
|
37
|
+
constructor() {
|
|
38
|
+
super();
|
|
39
|
+
this.fp3 = FakeProvider3.instance;
|
|
40
|
+
}
|
|
41
|
+
get _availability() {
|
|
42
|
+
return this.fp3.availability;
|
|
43
|
+
}
|
|
44
|
+
start() {
|
|
45
|
+
this.fp3id = this.fp3.addEventListener(
|
|
46
|
+
events => this.notify(events[0].clone()),
|
|
47
|
+
this.notifyError.bind(this),
|
|
48
|
+
this.name);
|
|
49
|
+
}
|
|
50
|
+
stop() {
|
|
51
|
+
this.fp3.removeEventListener(this.fp3id);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
FakeProvider1, FakeProvider2, FakeProvider3, FakeProvider4, FakeProvider5
|
|
57
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import Provider from './Provider';
|
|
2
|
+
import ProviderEvent from '../events/ProviderEvent';
|
|
3
|
+
|
|
4
|
+
class MetaProvider extends Provider {
|
|
5
|
+
|
|
6
|
+
_lastEvent = null;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Singleton pattern using reflection.
|
|
10
|
+
* @returns {MetaProvider}
|
|
11
|
+
*/
|
|
12
|
+
static get instance() {
|
|
13
|
+
if (!this._instance) {
|
|
14
|
+
this._instance = Reflect.construct(this, []);
|
|
15
|
+
}
|
|
16
|
+
return this._instance;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @override
|
|
21
|
+
* @param {ProviderEvent} event
|
|
22
|
+
*/
|
|
23
|
+
notify(event) {
|
|
24
|
+
super.notify(event);
|
|
25
|
+
this._lastEvent = event;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get lastEvent() {
|
|
29
|
+
return this._lastEvent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Input data from external interface
|
|
34
|
+
* @param {ProviderEvent} event
|
|
35
|
+
*/
|
|
36
|
+
// eslint-disable-next-line no-unused-vars
|
|
37
|
+
feed(event) {
|
|
38
|
+
throw new Error('Not implemented');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default MetaProvider;
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import isNumber from 'lodash.isnumber';
|
|
2
|
+
import noop from 'lodash.noop';
|
|
3
|
+
|
|
4
|
+
import { TimeUtils } from '@wemap/utils';
|
|
5
|
+
|
|
6
|
+
import EventType from '../events/EventType';
|
|
7
|
+
import ProviderEvent from '../events/ProviderEvent';
|
|
8
|
+
import ProvidersLogger from '../events/ProvidersLogger';
|
|
9
|
+
import Availability from '../events/Availability';
|
|
10
|
+
import ContainsIgnoredProviderError from '../errors/ContainsIgnoredProviderError';
|
|
11
|
+
import ProvidersOptions from '../ProvidersOptions';
|
|
12
|
+
import ProviderState from './ProviderState';
|
|
13
|
+
|
|
14
|
+
let uniqueId = 1;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A provider is a meta class to define an entity which can be
|
|
18
|
+
* started / stopped and provides a data of {@link ProviderEvent#DataType}
|
|
19
|
+
*/
|
|
20
|
+
class Provider {
|
|
21
|
+
|
|
22
|
+
static _callbackUniqueId = 0;
|
|
23
|
+
|
|
24
|
+
state = ProviderState.STOPPPED;
|
|
25
|
+
|
|
26
|
+
_eventsCallbacks = [];
|
|
27
|
+
_monitoringCallbacks = [];
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Singleton pattern using reflection.
|
|
32
|
+
* @returns {Provider}
|
|
33
|
+
*/
|
|
34
|
+
static get instance() {
|
|
35
|
+
if (!this._instance) {
|
|
36
|
+
this._instance = Reflect.construct(this, []);
|
|
37
|
+
}
|
|
38
|
+
return this._instance;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Provider constructor
|
|
44
|
+
*/
|
|
45
|
+
constructor() {
|
|
46
|
+
|
|
47
|
+
if (this.constructor === Provider) {
|
|
48
|
+
throw new Error('Can\'t instantiate Provider directly');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (this._instance) {
|
|
52
|
+
throw new Error(`Cannot instantiate ${this.constructor.name} twice`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.id = uniqueId++;
|
|
56
|
+
|
|
57
|
+
ProvidersLogger.addEvent(this, 'constructor');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get name() {
|
|
61
|
+
return this.constructor.name;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get the provider name
|
|
66
|
+
* @public
|
|
67
|
+
* @abstract
|
|
68
|
+
*/
|
|
69
|
+
static get displayName() {
|
|
70
|
+
return this.name;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get displayName() {
|
|
74
|
+
return this.constructor.displayName;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get the list of events type which can be returned by the provider
|
|
79
|
+
* @returns {EventType[]} the list of events type
|
|
80
|
+
* @public
|
|
81
|
+
* @abstract
|
|
82
|
+
*/
|
|
83
|
+
get eventsType() {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @returns {Availability} returns an availability
|
|
89
|
+
*/
|
|
90
|
+
get availability() {
|
|
91
|
+
if (ProvidersOptions.ignoreProviders.includes(this.name)) {
|
|
92
|
+
return Availability.no(new ContainsIgnoredProviderError());
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return this._availability;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get _availability() {
|
|
99
|
+
return Availability.yes();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Create an event from current provider
|
|
104
|
+
* @param {ProviderEvent#DataType} dataType type of ProviderEvent
|
|
105
|
+
* @param {Object} data data exported to ProviderEvent
|
|
106
|
+
* @param {Number} timestamp event timestamp
|
|
107
|
+
* @returns {ProviderEvent}
|
|
108
|
+
* @protected
|
|
109
|
+
*/
|
|
110
|
+
static createEvent(dataType, data, timestamp, fromEvents = []) {
|
|
111
|
+
const event = new ProviderEvent(dataType, data);
|
|
112
|
+
event.timestamp = isNumber(timestamp) ? timestamp : TimeUtils.preciseTime / 1e3;
|
|
113
|
+
const newStack = fromEvents.reduce((acc, _event) => acc.concat(_event.providersStack), []);
|
|
114
|
+
// Remove duplicates and keep lasts
|
|
115
|
+
event.providersStack = [...new Set(newStack.reverse())].reverse();
|
|
116
|
+
return event;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Create an event from current provider
|
|
121
|
+
* @param {EventType} dataType type of ProviderEvent
|
|
122
|
+
* @param {Object} data data exported to ProviderEvent
|
|
123
|
+
* @param {Number} timestamp event timestamp
|
|
124
|
+
* @param {ProviderEvent[]} fromEvents events used for the creation of the new one
|
|
125
|
+
* @returns {ProviderEvent}
|
|
126
|
+
* @protected
|
|
127
|
+
*/
|
|
128
|
+
createEvent(dataType, data, timestamp, fromEvents) {
|
|
129
|
+
return this.constructor.createEvent(dataType, data, timestamp, fromEvents);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
get hasNativeInterface() {
|
|
133
|
+
return Boolean(this.nativeInterface);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
get nativeInterface() {
|
|
137
|
+
return global.WemapProvidersAndroid || null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
get useCameraNatively() {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
*
|
|
146
|
+
* @param {Function} onEvents
|
|
147
|
+
* @param {Function} onError
|
|
148
|
+
* @param {Object} callerName
|
|
149
|
+
* @param {Boolean} startIfNecessary
|
|
150
|
+
* @returns {Number}
|
|
151
|
+
*/
|
|
152
|
+
addEventListener(onEvents = noop, onError = noop, callerName = null, startIfNecessary = true) {
|
|
153
|
+
const id = ++Provider._callbackUniqueId;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Build callback
|
|
157
|
+
*/
|
|
158
|
+
this._eventsCallbacks.push({
|
|
159
|
+
id,
|
|
160
|
+
onEvents,
|
|
161
|
+
onError,
|
|
162
|
+
optional: !startIfNecessary,
|
|
163
|
+
callerName
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
// The caller just want to have callbacks without starting the provider,
|
|
168
|
+
// the routine can be stopped here
|
|
169
|
+
if (!startIfNecessary) {
|
|
170
|
+
return id;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
// If the provider is already started do not go further
|
|
175
|
+
if (this.state !== ProviderState.STOPPPED) {
|
|
176
|
+
return id;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check availability on start if defined in options
|
|
180
|
+
if (ProvidersOptions.checkAvailabilityOnStart) {
|
|
181
|
+
if (!this.availability.isSupported) {
|
|
182
|
+
this.notifyError(this.availability.reason);
|
|
183
|
+
return id;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.state = ProviderState.STARTING;
|
|
188
|
+
|
|
189
|
+
ProvidersLogger.addEvent(this, 'start');
|
|
190
|
+
// Call the child start function
|
|
191
|
+
this.start();
|
|
192
|
+
|
|
193
|
+
this.state = ProviderState.STARTED;
|
|
194
|
+
|
|
195
|
+
this._monitoringCallbacks.forEach(({ onStarted }) => onStarted());
|
|
196
|
+
|
|
197
|
+
return id;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
*
|
|
202
|
+
* @param {Number} callbackUniqueId
|
|
203
|
+
*/
|
|
204
|
+
removeEventListener(callbackUniqueId) {
|
|
205
|
+
|
|
206
|
+
// Search the caller object in callbacks list
|
|
207
|
+
const callback = this._eventsCallbacks.find(_callback => _callback.id === callbackUniqueId);
|
|
208
|
+
if (!callback) {
|
|
209
|
+
// The callback object is not found. Maybe it is already stopped.
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Remove the current callback from the list of the callbacks
|
|
214
|
+
this._eventsCallbacks = this._eventsCallbacks.filter(_callback => _callback !== callback);
|
|
215
|
+
|
|
216
|
+
// If this callback was optional, do not go further to stop the provider
|
|
217
|
+
if (callback.optional) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// If there is callbacks that are not optionals for start, do not stop the provider
|
|
222
|
+
if (this._eventsCallbacks.find(_callback => !_callback.optional)) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// If the provider is already stopped, do not stop it again.
|
|
227
|
+
// This condition can be true if checkAvailabilityOnStart is true and returns an error
|
|
228
|
+
if (this.state === ProviderState.STOPPPED) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
ProvidersLogger.addEvent(this, 'stop');
|
|
233
|
+
// Call the child stop function
|
|
234
|
+
this.stop();
|
|
235
|
+
|
|
236
|
+
this.state = ProviderState.STOPPPED;
|
|
237
|
+
|
|
238
|
+
this._monitoringCallbacks.forEach(({ onStopped }) => onStopped());
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
*
|
|
244
|
+
* @param {Function} onStarted
|
|
245
|
+
* @param {Function} onStopped
|
|
246
|
+
* @returns {Number}
|
|
247
|
+
*/
|
|
248
|
+
addMonitoringListener(onStarted = noop, onStopped = noop) {
|
|
249
|
+
const id = ++this.constructor._callbackUniqueId;
|
|
250
|
+
this._monitoringCallbacks.push({
|
|
251
|
+
id,
|
|
252
|
+
onStarted,
|
|
253
|
+
onStopped
|
|
254
|
+
});
|
|
255
|
+
return id;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
*
|
|
260
|
+
* @param {Number} callbackUniqueId
|
|
261
|
+
*/
|
|
262
|
+
removeMonitoringListener(callbackUniqueId) {
|
|
263
|
+
this._monitoringCallbacks = this._monitoringCallbacks.filter(
|
|
264
|
+
_callback => _callback.id !== callbackUniqueId
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @abstract
|
|
270
|
+
*/
|
|
271
|
+
start() {
|
|
272
|
+
throw new Error('Provider "' + this.name + '" does not @override start()');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @abstract
|
|
277
|
+
*/
|
|
278
|
+
stop() {
|
|
279
|
+
throw new Error('Provider "' + this.name + '" does not @override stop()');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Notify the subscriber defined in {@link addEventListener}
|
|
285
|
+
* @param {ProviderEvent[]} events events to send to subscriber
|
|
286
|
+
*/
|
|
287
|
+
notify(...events) {
|
|
288
|
+
// Logging
|
|
289
|
+
ProvidersLogger.incrementNotifications(this);
|
|
290
|
+
|
|
291
|
+
// Add current provider to the list of providers for this event.
|
|
292
|
+
events.forEach(event => event.providersStack.unshift(this.name));
|
|
293
|
+
|
|
294
|
+
// Notify callbacks
|
|
295
|
+
this._eventsCallbacks.forEach(({ onEvents }) => onEvents(events));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Notify the subscriber defined in {@link addEventListener}
|
|
300
|
+
* @param {Error} error The error raised
|
|
301
|
+
*/
|
|
302
|
+
notifyError(error) {
|
|
303
|
+
this._eventsCallbacks.forEach(({
|
|
304
|
+
id, onError
|
|
305
|
+
}) => {
|
|
306
|
+
if (ProvidersOptions.stopOnError) {
|
|
307
|
+
this.removeEventListener(id);
|
|
308
|
+
}
|
|
309
|
+
onError(error);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export default Provider;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/* eslint-disable max-nested-callbacks */
|
|
2
|
+
import chai from 'chai';
|
|
3
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
4
|
+
import noop from 'lodash.noop';
|
|
5
|
+
|
|
6
|
+
import Logger from '@wemap/logger';
|
|
7
|
+
|
|
8
|
+
import Provider from './Provider';
|
|
9
|
+
|
|
10
|
+
import ContainsIgnoredProviderError from '../errors/ContainsIgnoredProviderError';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
FakeProvider1, FakeProvider2, FakeProvider3, FakeProvider4, FakeProvider5
|
|
14
|
+
} from './FakeProvider.spec';
|
|
15
|
+
import ProvidersOptions from '../ProvidersOptions';
|
|
16
|
+
import ProviderState from './ProviderState';
|
|
17
|
+
|
|
18
|
+
chai.use(chaiAsPromised);
|
|
19
|
+
Logger.enable(false);
|
|
20
|
+
|
|
21
|
+
const { expect } = chai;
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
describe('Provider', () => {
|
|
25
|
+
|
|
26
|
+
it('creation/singleton', () => {
|
|
27
|
+
expect(() => new Provider()).throw(Error);
|
|
28
|
+
expect(() => Provider.instance).throw(Error);
|
|
29
|
+
expect(() => FakeProvider1.instance).not.throw(Error);
|
|
30
|
+
expect(() => FakeProvider2.instance).not.throw(Error);
|
|
31
|
+
expect(() => FakeProvider3.instance).not.throw(Error);
|
|
32
|
+
expect(() => FakeProvider4.instance).not.throw(Error);
|
|
33
|
+
expect(FakeProvider1.instance).equals(FakeProvider1.instance);
|
|
34
|
+
expect(FakeProvider4.instance).equals(FakeProvider4.instance);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
it('default getter', () => {
|
|
39
|
+
const provider = FakeProvider1.instance;
|
|
40
|
+
expect(provider.name).equals(FakeProvider1.name);
|
|
41
|
+
expect(provider.displayName).equals(FakeProvider1.name);
|
|
42
|
+
expect(provider.eventsType).is.empty;
|
|
43
|
+
expect(provider.hasNativeInterface).is.false;
|
|
44
|
+
expect(provider.nativeInterface).is.null;
|
|
45
|
+
expect(provider.useCameraNatively).is.false;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('availability', () => {
|
|
49
|
+
|
|
50
|
+
const fakeProvider1 = FakeProvider1.instance;
|
|
51
|
+
expect(fakeProvider1.availability.isSupported).is.true;
|
|
52
|
+
ProvidersOptions.ignoreProviders.push(FakeProvider1.name);
|
|
53
|
+
expect(fakeProvider1.availability.isSupported).is.false;
|
|
54
|
+
expect(fakeProvider1.availability.reason).instanceOf(ContainsIgnoredProviderError);
|
|
55
|
+
ProvidersOptions.ignoreProviders = [];
|
|
56
|
+
|
|
57
|
+
expect(FakeProvider2.instance.availability.isSupported).is.false;
|
|
58
|
+
expect(FakeProvider2.instance.availability.reason).instanceOf(Error);
|
|
59
|
+
|
|
60
|
+
expect(FakeProvider3.instance.availability.isSupported).is.true;
|
|
61
|
+
expect(FakeProvider4.instance.availability.isSupported).is.true;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('checkAvailability on start', () => {
|
|
65
|
+
|
|
66
|
+
const fp2 = FakeProvider2.instance;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* checkAvailabilityOnStart = true
|
|
70
|
+
*/
|
|
71
|
+
let errored = false;
|
|
72
|
+
fp2.addEventListener(noop, () => (errored = true));
|
|
73
|
+
|
|
74
|
+
expect(errored).is.true;
|
|
75
|
+
expect(fp2.state).equals(ProviderState.STOPPPED);
|
|
76
|
+
expect(fp2._eventsCallbacks.length).equals(0);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* checkAvailabilityOnStart = false
|
|
80
|
+
*/
|
|
81
|
+
ProvidersOptions.checkAvailabilityOnStart = false;
|
|
82
|
+
|
|
83
|
+
errored = false;
|
|
84
|
+
const id = fp2.addEventListener(noop, () => (errored = true));
|
|
85
|
+
|
|
86
|
+
expect(errored).is.false;
|
|
87
|
+
expect(fp2.state).equals(ProviderState.STARTED);
|
|
88
|
+
|
|
89
|
+
fp2.removeEventListener(id);
|
|
90
|
+
expect(fp2.state).equals(ProviderState.STOPPPED);
|
|
91
|
+
expect(fp2._eventsCallbacks.length).equals(0);
|
|
92
|
+
|
|
93
|
+
ProvidersOptions.checkAvailabilityOnStart = true;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const startStop = (provider) => {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
let isStopped = false;
|
|
99
|
+
let fail = false;
|
|
100
|
+
|
|
101
|
+
const listenerId = provider.addEventListener(() => {
|
|
102
|
+
if (isStopped) {
|
|
103
|
+
fail = true;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
isStopped = true;
|
|
109
|
+
provider.removeEventListener(listenerId);
|
|
110
|
+
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
if (fail) {
|
|
113
|
+
reject('Provider did not stop');
|
|
114
|
+
} else {
|
|
115
|
+
resolve();
|
|
116
|
+
}
|
|
117
|
+
}, 5);
|
|
118
|
+
}, 7);
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
it('start/stop', () => {
|
|
124
|
+
expect(() => FakeProvider1.instance.addEventListener()).throw(Error);
|
|
125
|
+
|
|
126
|
+
const idFp5 = FakeProvider5.instance.addEventListener();
|
|
127
|
+
expect(() => FakeProvider5.instance.removeEventListener(idFp5)).throw(Error);
|
|
128
|
+
|
|
129
|
+
return Promise.all([
|
|
130
|
+
expect(startStop(FakeProvider2.instance)).to.be.fulfilled,
|
|
131
|
+
expect(startStop(FakeProvider3.instance)).to.be.fulfilled,
|
|
132
|
+
expect(startStop(FakeProvider4.instance)).to.be.fulfilled
|
|
133
|
+
]);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import Provider from '../Provider';
|
|
2
|
+
import EventType from '../../events/EventType';
|
|
3
|
+
import Availability from '../../events/Availability';
|
|
4
|
+
import {
|
|
5
|
+
RelativeAttitude, AbsoluteAttitude
|
|
6
|
+
} from '../../Providers';
|
|
7
|
+
|
|
8
|
+
class AttitudeProvider extends Provider {
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @override
|
|
16
|
+
*/
|
|
17
|
+
static get displayName() {
|
|
18
|
+
return 'Attitude';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @override
|
|
23
|
+
*/
|
|
24
|
+
static get eventsType() {
|
|
25
|
+
return [EventType.Attitude];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @override
|
|
30
|
+
*/
|
|
31
|
+
get _availability() {
|
|
32
|
+
return Availability.union(
|
|
33
|
+
RelativeAttitude.availability,
|
|
34
|
+
AbsoluteAttitude.availability
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @override
|
|
40
|
+
*/
|
|
41
|
+
start() {
|
|
42
|
+
|
|
43
|
+
if (RelativeAttitude.availability.isSupported) {
|
|
44
|
+
this.provider = RelativeAttitude;
|
|
45
|
+
} else {
|
|
46
|
+
this.provider = AbsoluteAttitude;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this.providerId = this.provider.addEventListener(
|
|
50
|
+
events => this.notify(events[0].clone()),
|
|
51
|
+
this.notifyError,
|
|
52
|
+
this.name);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @override
|
|
57
|
+
*/
|
|
58
|
+
stop() {
|
|
59
|
+
this.provider.removeEventListener(this.providerId);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default AttitudeProvider;
|