wouterbulten/slacjs

View on GitHub
src/app/device/motion-sensor.js

Summary

Maintainability
A
3 hrs
Test Coverage
import { clockwiseToCounterClockwise } from '../util/motion';

class MotionSensor {

    /**
     * Motion sensor
     * @param {Number} frequency Update rate of sensor
     * @param {Boolean} enableCompassUpdate Set to true to be notified of compass updates
     * @param {Boolean} enableAccUpdate Set to true to be notified of accelerometer updates
     * @param {Boolean} convertToCw Set to true to convert headings to counter clockwise
     * @return {MotionSensor}
     */
    constructor(frequency = 100, enableCompassUpdate = false, enableAccUpdate = true, compassFilter = undefined, convertToCw = false) {

        this.accelerometerId = undefined;
        this.compassId = undefined;
        this.frequency = frequency;
        this.listenerOptions = {frequency};
        this.compassOptions = {frequency, filter: compassFilter};
        this.listeners = [];

        this.enableAccUpdate = enableAccUpdate;
        this.enableCompassUpdate = enableCompassUpdate;
        this.convertToCw = convertToCw;

        this.x = 0.0;
        this.y = 0.0;
        this.z = 0.0;
        this.heading = 0.0;
    }

    /**
     * Start listening for changes
     * @return {Boolean} True when listeners have been started
     */
    startListening() {
        if (this.accelerometerId === undefined) {
            this.accelerometerId = navigator.accelerometer.watchAcceleration(
                (data) => this._updateAccelerometer(data),
                (error) => this._onError(error),
                this.listenerOptions
            );
        }

        if (this.compassId === undefined) {
            this.compassId = navigator.compass.watchHeading(
                (data) => this._updateCompass(data),
                (error)    =>this._onError(error),
                this.compassOptions
            );
        }

        return {compass: this.compassId !== undefined, accelerometer: this.accelerometerId !== undefined};
    }

    /**
     * Add a new listener function
     * @param {Function} callback
     */
    onChange(callback) {
        this.listeners.push(callback);
    }

    /**
     * Process accelerometer data
     * @param  {object} acceleration x,y,z
     * @return {void}
     */
    _updateAccelerometer(acceleration) {
        this.x = acceleration.x;
        this.y = acceleration.y;
        this.z = acceleration.z;

        if (this.enableAccUpdate) {
            this._changed();
        }
    }

    /**
     * Process compass data
     * @param  {object} heading
     * @return {void}
     */
    _updateCompass(heading) {

        if (this.convertToCw) {
            this.heading = clockwiseToCounterClockwise(heading.magneticHeading);
        }
        else {
            this.heading = heading.magneticHeading;
        }

        if (this.enableCompassUpdate) {
            this._changed();
        }
    }

    /**
     * Process an error message
     * @param  {Object} error
     * @return {void}
     */
    _onError(error) {
        console.error('Error occured: ' + error.code);

        navigator.notification.alert(
            'An error occured in the motion sensor: ' + error.code,
            undefined,
            'Error in Motion Sensor',
            'Ok');
    }

    /**
     * Call all the listeners
     * @return {void}
     */
    _changed() {
        this.listeners.forEach((listener) => {
            listener({
                x: this.x,
                y: this.y,
                z: this.z,
                heading: this.heading
            });
        });
    }
}

export default MotionSensor;