UNPKG

@openhps/web-sensors

Version:

Open Hybrid Positioning System - Web Sensors API

171 lines 7.73 kB
/// <reference types="web" /> import { SourceNode, Acceleration, Orientation, Quaternion, DataFrame, LinearAccelerationSensor as LinearAccelerationSensorObject, AbsoluteOrientationSensor as AbsoluteOrientationSensorObject, RelativeOrientationSensor as RelativeOrientationSensorObject, Magnetometer as MagnetometerObject, Gyroscope as GyroscopeObject, Accelerometer as AccelerometerObject, AngularVelocity, AngularVelocityUnit, Magnetism, AccelerationUnit, MagnetismUnit, } from '@openhps/core'; /** * Sensor source node using Web Sensor API. */ export class SensorSourceNode extends SourceNode { constructor(options) { super(options); this._subscriptions = new Map(); this._values = new Map(); this._lastPush = 0; this._running = false; this.options.interval = this.options.interval || 100; if (this.options.autoStart) { this.once('build', this.start.bind(this)); } this.once('destroy', this.stop.bind(this)); } static checkPermissions(sensors) { return this.requestPermissions(sensors); } static requestPermissions(sensors) { return new Promise((resolve, reject) => { if (navigator.permissions === undefined) { return resolve(true); } Promise.all(sensors .map((sensor) => this.getPermissions(sensor).map((permission) => navigator.permissions.query({ name: permission }))) .reduce((a, b) => [...a, ...b])) .then((results) => { if (results.every((result) => result.state === 'granted')) { resolve(true); } else { resolve(false); } }) .catch(reject); }); } requestPermissions() { return SensorSourceNode.requestPermissions(this.options.sensors); } start() { return new Promise((resolve) => { this._running = true; if (this._subscriptions.size > 0) { return resolve(); } this.options.sensors.forEach((sensor) => { const SensorType = this.findSensor(sensor); if (SensorType === undefined) { // Not supported return; } const sensorInstance = new SensorType({ frequency: Math.round(1000 / this.options.interval), }); sensorInstance.addEventListener('reading', (event) => { if (!this._running) return; this._values.set(sensor, event.target); if (this._isUpdated()) { this._lastPush = event.timeStamp; this.createFrame().catch((ex) => { this.logger('error', 'Unable to create sensor data frame!', ex); }); } }); sensorInstance.start(); this._subscriptions.set(sensor, sensorInstance); }); resolve(); }); } _isUpdated() { return (Array.from(this._values.values()).filter((sensor) => sensor.timestamp > this._lastPush).length === Array.from(this._subscriptions.values()).filter((sensor) => sensor.activated).length); } stop() { return new Promise((resolve) => { if (this.options.softStop) { this._running = false; } else { this._subscriptions.forEach((value) => value.stop()); this._subscriptions = new Map(); this._values = new Map(); } resolve(); }); } createFrame() { return new Promise((resolve) => { const dataFrame = new DataFrame(); dataFrame.source = this.source; const acceleration = this._values.get(AccelerometerObject); const linearAcceleration = this._values.get(LinearAccelerationSensorObject); const gyroscope = this._values.get(GyroscopeObject); const orientation = this._values.get(AbsoluteOrientationSensorObject); const relativeOrientation = this._values.get(RelativeOrientationSensorObject); const magnetometer = this._values.get(MagnetometerObject); const sourceUID = this.source ? this.source.uid : this.uid; const frequency = 1000 / this.options.interval; if (acceleration) { dataFrame.addSensor(new AccelerometerObject(sourceUID + '_accel', new Acceleration(acceleration.x, acceleration.y, acceleration.z, AccelerationUnit.METER_PER_SECOND_SQUARE), frequency)); } if (linearAcceleration) { dataFrame.addSensor(new LinearAccelerationSensorObject(sourceUID + '_linearaccel', new Acceleration(linearAcceleration.x, linearAcceleration.y, linearAcceleration.z, AccelerationUnit.METER_PER_SECOND_SQUARE), frequency)); } if (gyroscope) { dataFrame.addSensor(new GyroscopeObject(sourceUID + '_gyro', new AngularVelocity(gyroscope.x, gyroscope.y, gyroscope.z, AngularVelocityUnit.RADIAN_PER_SECOND), frequency)); } if (orientation) { dataFrame.addSensor(new AbsoluteOrientationSensorObject(sourceUID + '_absoluteorientation', Orientation.fromQuaternion(new Quaternion(...orientation.quaternion)), frequency)); } if (relativeOrientation) { dataFrame.addSensor(new RelativeOrientationSensorObject(sourceUID + '_relativeorientation', Orientation.fromQuaternion(new Quaternion(...relativeOrientation.quaternion)), frequency)); } if (magnetometer) { dataFrame.addSensor(new MagnetometerObject(sourceUID + '_mag', new Magnetism(magnetometer.x, magnetometer.y, magnetometer.z, MagnetismUnit.MICROTESLA), frequency)); } this.push(dataFrame); resolve(); }); } onPull() { return new Promise((resolve) => { resolve(undefined); }); } findSensor(sensor) { switch (sensor) { case RelativeOrientationSensorObject: return RelativeOrientationSensor; case AbsoluteOrientationSensorObject: return AbsoluteOrientationSensor; case LinearAccelerationSensorObject: return LinearAccelerationSensor; // case SensorType.AMBIENT_LIGHT: // return AmbientLightSensor; case GyroscopeObject: return Gyroscope; case MagnetometerObject: return window.Magnetometer; // Experimental case AccelerometerObject: return Accelerometer; default: return undefined; } } static getPermissions(sensor) { switch (sensor) { // case SensorType.AMBIENT_LIGHT: // return ["ambient-light-sensor"]; case RelativeOrientationSensorObject: case AbsoluteOrientationSensorObject: return ['gyroscope', 'accelerometer', 'magnetometer']; case GyroscopeObject: return ['gyroscope']; case MagnetometerObject: return ['magnetometer']; case LinearAccelerationSensorObject: case AccelerometerObject: return ['accelerometer']; default: return undefined; } } } //# sourceMappingURL=SensorSourceNode.js.map