UNPKG

6.78 kBJavaScriptView Raw
1/*
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20*/
21
22/**
23 * This class provides access to device accelerometer data.
24 * @constructor
25 */
26var argscheck = require('cordova/argscheck'),
27 utils = require("cordova/utils"),
28 exec = require("cordova/exec"),
29 Acceleration = require('./Acceleration');
30
31// Is the accel sensor running?
32var running = false;
33
34// Keeps reference to watchAcceleration calls.
35var timers = {};
36
37// Array of listeners; used to keep track of when we should call start and stop.
38var listeners = [];
39
40// Last returned acceleration object from native
41var accel = null;
42
43// Timer used when faking up devicemotion events
44var eventTimerId = null;
45
46// Tells native to start.
47function start() {
48 exec(function (a) {
49 var tempListeners = listeners.slice(0);
50 accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
51 for (var i = 0, l = tempListeners.length; i < l; i++) {
52 tempListeners[i].win(accel);
53 }
54 }, function (e) {
55 var tempListeners = listeners.slice(0);
56 for (var i = 0, l = tempListeners.length; i < l; i++) {
57 tempListeners[i].fail(e);
58 }
59 }, "Accelerometer", "start", []);
60 running = true;
61}
62
63// Tells native to stop.
64function stop() {
65 exec(null, null, "Accelerometer", "stop", []);
66 accel = null;
67 running = false;
68}
69
70// Adds a callback pair to the listeners array
71function createCallbackPair(win, fail) {
72 return { win: win, fail: fail };
73}
74
75// Removes a win/fail listener pair from the listeners array
76function removeListeners(l) {
77 var idx = listeners.indexOf(l);
78 if (idx > -1) {
79 listeners.splice(idx, 1);
80 if (listeners.length === 0) {
81 stop();
82 }
83 }
84}
85
86var accelerometer = {
87 /**
88 * Asynchronously acquires the current acceleration.
89 *
90 * @param {Function} successCallback The function to call when the acceleration data is available
91 * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
92 * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
93 */
94 getCurrentAcceleration: function (successCallback, errorCallback, options) {
95 argscheck.checkArgs('fFO', 'accelerometer.getCurrentAcceleration', arguments);
96
97 if (cordova.platformId === "windowsphone") {
98 exec(function (a) {
99 accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
100 successCallback(accel);
101 }, function (e) {
102 errorCallback(e);
103 }, "Accelerometer", "getCurrentAcceleration", []);
104
105 return;
106 }
107
108 var p;
109 var win = function (a) {
110 removeListeners(p);
111 successCallback(a);
112 };
113 var fail = function (e) {
114 removeListeners(p);
115 if (errorCallback) {
116 errorCallback(e);
117 }
118 };
119
120 p = createCallbackPair(win, fail);
121 listeners.push(p);
122
123 if (!running) {
124 start();
125 }
126 },
127
128 /**
129 * Asynchronously acquires the acceleration repeatedly at a given interval.
130 *
131 * @param {Function} successCallback The function to call each time the acceleration data is available
132 * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
133 * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
134 * @return String The watch id that must be passed to #clearWatch to stop watching.
135 */
136 watchAcceleration: function (successCallback, errorCallback, options) {
137 argscheck.checkArgs('fFO', 'accelerometer.watchAcceleration', arguments);
138 // Default interval (10 sec)
139 var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000;
140
141 // Keep reference to watch id, and report accel readings as often as defined in frequency
142 var id = utils.createUUID();
143
144 var p = createCallbackPair(function () { }, function (e) {
145 removeListeners(p);
146 if (errorCallback) {
147 errorCallback(e);
148 }
149 });
150 listeners.push(p);
151
152 timers[id] = {
153 timer: window.setInterval(function () {
154 if (accel) {
155 successCallback(accel);
156 }
157 }, frequency),
158 listeners: p
159 };
160
161 if (running) {
162 // If we're already running then immediately invoke the success callback
163 // but only if we have retrieved a value, sample code does not check for null ...
164 if (accel) {
165 successCallback(accel);
166 }
167 } else {
168 start();
169 }
170
171 if (cordova.platformId === "browser" && !eventTimerId) {
172 // Start firing devicemotion events if we haven't already
173 var devicemotionEvent = new Event('devicemotion');
174 eventTimerId = window.setInterval(function() {
175 window.dispatchEvent(devicemotionEvent);
176 }, 200);
177 }
178
179 return id;
180 },
181
182 /**
183 * Clears the specified accelerometer watch.
184 *
185 * @param {String} id The id of the watch returned from #watchAcceleration.
186 */
187 clearWatch: function (id) {
188 // Stop javascript timer & remove from timer list
189 if (id && timers[id]) {
190 window.clearInterval(timers[id].timer);
191 removeListeners(timers[id].listeners);
192 delete timers[id];
193
194 if (eventTimerId && Object.keys(timers).length === 0) {
195 // No more watchers, so stop firing 'devicemotion' events
196 window.clearInterval(eventTimerId);
197 eventTimerId = null;
198 }
199 }
200 }
201};
202module.exports = accelerometer;