summaryrefslogtreecommitdiffstats
path: root/sl4a/Common/src/com/googlecode/android_scripting/facade/SensorManagerFacade.java
diff options
context:
space:
mode:
Diffstat (limited to 'sl4a/Common/src/com/googlecode/android_scripting/facade/SensorManagerFacade.java')
-rw-r--r--sl4a/Common/src/com/googlecode/android_scripting/facade/SensorManagerFacade.java496
1 files changed, 0 insertions, 496 deletions
diff --git a/sl4a/Common/src/com/googlecode/android_scripting/facade/SensorManagerFacade.java b/sl4a/Common/src/com/googlecode/android_scripting/facade/SensorManagerFacade.java
deleted file mode 100644
index 6c4c7b7..0000000
--- a/sl4a/Common/src/com/googlecode/android_scripting/facade/SensorManagerFacade.java
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * Copyright (C) 2016 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.googlecode.android_scripting.facade;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.Bundle;
-
-import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
-import com.googlecode.android_scripting.rpc.Rpc;
-import com.googlecode.android_scripting.rpc.RpcDefault;
-import com.googlecode.android_scripting.rpc.RpcDeprecated;
-import com.googlecode.android_scripting.rpc.RpcParameter;
-import com.googlecode.android_scripting.rpc.RpcStartEvent;
-import com.googlecode.android_scripting.rpc.RpcStopEvent;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Exposes the SensorManager related functionality. <br>
- * <br>
- * <b>Guidance notes</b> <br>
- * For reasons of economy the sensors on smart phones are usually low cost and, therefore, low
- * accuracy (usually represented by 10 bit data). The floating point data values obtained from
- * sensor readings have up to 16 decimal places, the majority of which are noise. On many phones the
- * accelerometer is limited (by the phone manufacturer) to a maximum reading of 2g. The magnetometer
- * (which also provides orientation readings) is strongly affected by the presence of ferrous metals
- * and can give large errors in vehicles, on board ship etc.
- *
- * Following a startSensingTimed(A,B) api call sensor events are entered into the Event Queue (see
- * EventFacade). For the A parameter: 1 = All Sensors, 2 = Accelerometer, 3 = Magnetometer and 4 =
- * Light. The B parameter is the minimum delay between recordings in milliseconds. To avoid
- * duplicate readings the minimum delay should be 20 milliseconds. The light sensor will probably be
- * much slower (taking about 1 second to register a change in light level). Note that if the light
- * level is constant no sensor events will be registered by the light sensor.
- *
- * Following a startSensingThreshold(A,B,C) api call sensor events greater than a given threshold
- * are entered into the Event Queue. For the A parameter: 1 = Orientation, 2 = Accelerometer, 3 =
- * Magnetometer and 4 = Light. The B parameter is the integer value of the required threshold level.
- * For orientation sensing the integer threshold value is in milliradians. Since orientation events
- * can exceed the threshold value for long periods only crossing and return events are recorded. The
- * C parameter is the required axis (XYZ) of the sensor: 0 = No axis, 1 = X, 2 = Y, 3 = X+Y, 4 = Z,
- * 5= X+Z, 6 = Y+Z, 7 = X+Y+Z. For orientation X = azimuth, Y = pitch and Z = roll. <br>
- *
- * <br>
- * <b>Example (python)</b>
- *
- * <pre>
- * import android, time
- * droid = android.Android()
- * droid.startSensingTimed(1, 250)
- * time.sleep(1)
- * s1 = droid.readSensors().result
- * s2 = droid.sensorsGetAccuracy().result
- * s3 = droid.sensorsGetLight().result
- * s4 = droid.sensorsReadAccelerometer().result
- * s5 = droid.sensorsReadMagnetometer().result
- * s6 = droid.sensorsReadOrientation().result
- * droid.stopSensing()
- * </pre>
- *
- * Returns:<br>
- * s1 = {u'accuracy': 3, u'pitch': -0.47323511242866517, u'xmag': 1.75, u'azimuth':
- * -0.26701245009899138, u'zforce': 8.4718560000000007, u'yforce': 4.2495484000000001, u'time':
- * 1297160391.2820001, u'ymag': -8.9375, u'zmag': -41.0625, u'roll': -0.031366908922791481,
- * u'xforce': 0.23154590999999999}<br>
- * s2 = 3 (Highest accuracy)<br>
- * s3 = None ---(not available on many phones)<br>
- * s4 = [0.23154590999999999, 4.2495484000000001, 8.4718560000000007] ----(x, y, z accelerations)<br>
- * s5 = [1.75, -8.9375, -41.0625] -----(x, y, z magnetic readings)<br>
- * s6 = [-0.26701245009899138, -0.47323511242866517, -0.031366908922791481] ---(azimuth, pitch, roll
- * in radians)<br>
- *
- * @author Damon Kohler (damonkohler@gmail.com)
- * @author Felix Arends (felix.arends@gmail.com)
- * @author Alexey Reznichenko (alexey.reznichenko@gmail.com)
- * @author Robbie Mathews (rjmatthews62@gmail.com)
- * @author John Karwatzki (jokar49@gmail.com)
- */
-public class SensorManagerFacade extends RpcReceiver {
- private final EventFacade mEventFacade;
- private final SensorManager mSensorManager;
-
- private volatile Bundle mSensorReadings;
-
- private volatile Integer mAccuracy;
- private volatile Integer mSensorNumber;
- private volatile Integer mXAxis = 0;
- private volatile Integer mYAxis = 0;
- private volatile Integer mZAxis = 0;
- private volatile Integer mThreshing = 0;
- private volatile Integer mThreshOrientation = 0;
- private volatile Integer mXCrossed = 0;
- private volatile Integer mYCrossed = 0;
- private volatile Integer mZCrossed = 0;
-
- private volatile Float mThreshold;
- private volatile Float mXForce;
- private volatile Float mYForce;
- private volatile Float mZForce;
-
- private volatile Float mXMag;
- private volatile Float mYMag;
- private volatile Float mZMag;
-
- private volatile Float mLight;
-
- private volatile Double mAzimuth;
- private volatile Double mPitch;
- private volatile Double mRoll;
-
- private volatile Long mLastTime;
- private volatile Long mDelayTime;
-
- private SensorEventListener mSensorListener;
-
- public SensorManagerFacade(FacadeManager manager) {
- super(manager);
- mEventFacade = manager.getReceiver(EventFacade.class);
- mSensorManager = (SensorManager) manager.getService().getSystemService(Context.SENSOR_SERVICE);
- }
-
- @Rpc(description = "Starts recording sensor data to be available for polling.")
- @RpcStartEvent("sensors")
- public void startSensingTimed(
- @RpcParameter(name = "sensorNumber", description = "1 = All, 2 = Accelerometer, 3 = Magnetometer and 4 = Light") Integer sensorNumber,
- @RpcParameter(name = "delayTime", description = "Minimum time between readings in milliseconds") Integer delayTime) {
- mSensorNumber = sensorNumber;
- if (delayTime < 20) {
- delayTime = 20;
- }
- mDelayTime = (long) (delayTime);
- mLastTime = System.currentTimeMillis();
- if (mSensorListener == null) {
- mSensorListener = new SensorValuesCollector();
- mSensorReadings = new Bundle();
- switch (mSensorNumber) {
- case 1:
- for (Sensor sensor : mSensorManager.getSensorList(Sensor.TYPE_ALL)) {
- mSensorManager.registerListener(mSensorListener, sensor,
- SensorManager.SENSOR_DELAY_FASTEST);
- }
- break;
- case 2:
- for (Sensor sensor : mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER)) {
- mSensorManager.registerListener(mSensorListener, sensor,
- SensorManager.SENSOR_DELAY_FASTEST);
- }
- break;
- case 3:
- for (Sensor sensor : mSensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD)) {
- mSensorManager.registerListener(mSensorListener, sensor,
- SensorManager.SENSOR_DELAY_FASTEST);
- }
- break;
- case 4:
- for (Sensor sensor : mSensorManager.getSensorList(Sensor.TYPE_LIGHT)) {
- mSensorManager.registerListener(mSensorListener, sensor,
- SensorManager.SENSOR_DELAY_FASTEST);
- }
- }
- }
- }
-
- @Rpc(description = "Records to the Event Queue sensor data exceeding a chosen threshold.")
- @RpcStartEvent("threshold")
- public void startSensingThreshold(
-
- @RpcParameter(name = "sensorNumber", description = "1 = Orientation, 2 = Accelerometer, 3 = Magnetometer and 4 = Light") Integer sensorNumber,
- @RpcParameter(name = "threshold", description = "Threshold level for chosen sensor (integer)") Integer threshold,
- @RpcParameter(name = "axis", description = "0 = No axis, 1 = X, 2 = Y, 3 = X+Y, 4 = Z, 5= X+Z, 6 = Y+Z, 7 = X+Y+Z") Integer axis) {
- mSensorNumber = sensorNumber;
- mXAxis = axis & 1;
- mYAxis = axis & 2;
- mZAxis = axis & 4;
- if (mSensorNumber == 1) {
- mThreshing = 0;
- mThreshOrientation = 1;
- mThreshold = ((float) threshold) / ((float) 1000);
- } else {
- mThreshing = 1;
- mThreshold = (float) threshold;
- }
- startSensingTimed(mSensorNumber, 20);
- }
-
- @Rpc(description = "Returns the most recently recorded sensor data.")
- public Bundle readSensors() {
- if (mSensorReadings == null) {
- return null;
- }
- synchronized (mSensorReadings) {
- return new Bundle(mSensorReadings);
- }
- }
-
- @Rpc(description = "Stops collecting sensor data.")
- @RpcStopEvent("sensors")
- public void stopSensing() {
- mSensorManager.unregisterListener(mSensorListener);
- mSensorListener = null;
- mSensorReadings = null;
- mThreshing = 0;
- mThreshOrientation = 0;
- }
-
- @Rpc(description = "Returns the most recently received accuracy value.")
- public Integer sensorsGetAccuracy() {
- return mAccuracy;
- }
-
- @Rpc(description = "Returns the most recently received light value.")
- public Float sensorsGetLight() {
- return mLight;
- }
-
- @Rpc(description = "Returns the most recently received accelerometer values.", returns = "a List of Floats [(acceleration on the) X axis, Y axis, Z axis].")
- public List<Float> sensorsReadAccelerometer() {
- synchronized (mSensorReadings) {
- return Arrays.asList(mXForce, mYForce, mZForce);
- }
- }
-
- @Rpc(description = "Returns the most recently received magnetic field values.", returns = "a List of Floats [(magnetic field value for) X axis, Y axis, Z axis].")
- public List<Float> sensorsReadMagnetometer() {
- synchronized (mSensorReadings) {
- return Arrays.asList(mXMag, mYMag, mZMag);
- }
- }
-
- @Rpc(description = "Returns the most recently received orientation values.", returns = "a List of Doubles [azimuth, pitch, roll].")
- public List<Double> sensorsReadOrientation() {
- synchronized (mSensorReadings) {
- return Arrays.asList(mAzimuth, mPitch, mRoll);
- }
- }
-
- @Rpc(description = "Starts recording sensor data to be available for polling.")
- @RpcDeprecated(value = "startSensingTimed or startSensingThreshhold", release = "4")
- public void startSensing(
- @RpcParameter(name = "sampleSize", description = "number of samples for calculating average readings") @RpcDefault("5") Integer sampleSize) {
- if (mSensorListener == null) {
- startSensingTimed(1, 220);
- }
- }
-
- @Override
- public void shutdown() {
- stopSensing();
- }
-
- private class SensorValuesCollector implements SensorEventListener {
- private final static int MATRIX_SIZE = 9;
-
- private final RollingAverage mmAzimuth;
- private final RollingAverage mmPitch;
- private final RollingAverage mmRoll;
-
- private float[] mmGeomagneticValues;
- private float[] mmGravityValues;
- private float[] mmR;
- private float[] mmOrientation;
-
- public SensorValuesCollector() {
- mmAzimuth = new RollingAverage();
- mmPitch = new RollingAverage();
- mmRoll = new RollingAverage();
- }
-
- private void postEvent() {
- mSensorReadings.putDouble("time", System.currentTimeMillis() / 1000.0);
- mEventFacade.postEvent("sensors", mSensorReadings.clone());
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- if (mSensorReadings == null) {
- return;
- }
- synchronized (mSensorReadings) {
- mSensorReadings.putInt("accuracy", accuracy);
- mAccuracy = accuracy;
-
- }
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- if (mSensorReadings == null) {
- return;
- }
- synchronized (mSensorReadings) {
- switch (event.sensor.getType()) {
- case Sensor.TYPE_ACCELEROMETER:
- mXForce = event.values[0];
- mYForce = event.values[1];
- mZForce = event.values[2];
- if (mThreshing == 0) {
- mSensorReadings.putFloat("xforce", mXForce);
- mSensorReadings.putFloat("yforce", mYForce);
- mSensorReadings.putFloat("zforce", mZForce);
- if ((mSensorNumber == 2) && (System.currentTimeMillis() > (mDelayTime + mLastTime))) {
- mLastTime = System.currentTimeMillis();
- postEvent();
- }
- }
- if ((mThreshing == 1) && (mSensorNumber == 2)) {
- if ((Math.abs(mXForce) > mThreshold) && (mXAxis == 1)) {
- mSensorReadings.putFloat("xforce", mXForce);
- postEvent();
- }
-
- if ((Math.abs(mYForce) > mThreshold) && (mYAxis == 2)) {
- mSensorReadings.putFloat("yforce", mYForce);
- postEvent();
- }
-
- if ((Math.abs(mZForce) > mThreshold) && (mZAxis == 4)) {
- mSensorReadings.putFloat("zforce", mZForce);
- postEvent();
- }
- }
-
- mmGravityValues = event.values.clone();
- break;
- case Sensor.TYPE_MAGNETIC_FIELD:
- mXMag = event.values[0];
- mYMag = event.values[1];
- mZMag = event.values[2];
- if (mThreshing == 0) {
- mSensorReadings.putFloat("xMag", mXMag);
- mSensorReadings.putFloat("yMag", mYMag);
- mSensorReadings.putFloat("zMag", mZMag);
- if ((mSensorNumber == 3) && (System.currentTimeMillis() > (mDelayTime + mLastTime))) {
- mLastTime = System.currentTimeMillis();
- postEvent();
- }
- }
- if ((mThreshing == 1) && (mSensorNumber == 3)) {
- if ((Math.abs(mXMag) > mThreshold) && (mXAxis == 1)) {
- mSensorReadings.putFloat("xforce", mXMag);
- postEvent();
- }
- if ((Math.abs(mYMag) > mThreshold) && (mYAxis == 2)) {
- mSensorReadings.putFloat("yforce", mYMag);
- postEvent();
- }
- if ((Math.abs(mZMag) > mThreshold) && (mZAxis == 4)) {
- mSensorReadings.putFloat("zforce", mZMag);
- postEvent();
- }
- }
- mmGeomagneticValues = event.values.clone();
- break;
- case Sensor.TYPE_LIGHT:
- mLight = event.values[0];
- if (mThreshing == 0) {
- mSensorReadings.putFloat("light", mLight);
- if ((mSensorNumber == 4) && (System.currentTimeMillis() > (mDelayTime + mLastTime))) {
- mLastTime = System.currentTimeMillis();
- postEvent();
- }
- }
- if ((mThreshing == 1) && (mSensorNumber == 4)) {
- if (mLight > mThreshold) {
- mSensorReadings.putFloat("light", mLight);
- postEvent();
- }
- }
- break;
-
- }
- if (mSensorNumber == 1) {
- if (mmGeomagneticValues != null && mmGravityValues != null) {
- if (mmR == null) {
- mmR = new float[MATRIX_SIZE];
- }
- if (SensorManager.getRotationMatrix(mmR, null, mmGravityValues, mmGeomagneticValues)) {
- if (mmOrientation == null) {
- mmOrientation = new float[3];
- }
- SensorManager.getOrientation(mmR, mmOrientation);
- mmAzimuth.add(mmOrientation[0]);
- mmPitch.add(mmOrientation[1]);
- mmRoll.add(mmOrientation[2]);
-
- mAzimuth = mmAzimuth.get();
- mPitch = mmPitch.get();
- mRoll = mmRoll.get();
- if (mThreshOrientation == 0) {
- mSensorReadings.putDouble("azimuth", mAzimuth);
- mSensorReadings.putDouble("pitch", mPitch);
- mSensorReadings.putDouble("roll", mRoll);
- if ((mSensorNumber == 1) && (System.currentTimeMillis() > (mDelayTime + mLastTime))) {
- mLastTime = System.currentTimeMillis();
- postEvent();
- }
- }
- if ((mThreshOrientation == 1) && (mSensorNumber == 1)) {
- if ((mXAxis == 1) && (mXCrossed == 0)) {
- if (Math.abs(mAzimuth) > ((double) mThreshold)) {
- mSensorReadings.putDouble("azimuth", mAzimuth);
- postEvent();
- mXCrossed = 1;
- }
- }
- if ((mXAxis == 1) && (mXCrossed == 1)) {
- if (Math.abs(mAzimuth) < ((double) mThreshold)) {
- mSensorReadings.putDouble("azimuth", mAzimuth);
- postEvent();
- mXCrossed = 0;
- }
- }
- if ((mYAxis == 2) && (mYCrossed == 0)) {
- if (Math.abs(mPitch) > ((double) mThreshold)) {
- mSensorReadings.putDouble("pitch", mPitch);
- postEvent();
- mYCrossed = 1;
- }
- }
- if ((mYAxis == 2) && (mYCrossed == 1)) {
- if (Math.abs(mPitch) < ((double) mThreshold)) {
- mSensorReadings.putDouble("pitch", mPitch);
- postEvent();
- mYCrossed = 0;
- }
- }
- if ((mZAxis == 4) && (mZCrossed == 0)) {
- if (Math.abs(mRoll) > ((double) mThreshold)) {
- mSensorReadings.putDouble("roll", mRoll);
- postEvent();
- mZCrossed = 1;
- }
- }
- if ((mZAxis == 4) && (mZCrossed == 1)) {
- if (Math.abs(mRoll) < ((double) mThreshold)) {
- mSensorReadings.putDouble("roll", mRoll);
- postEvent();
- mZCrossed = 0;
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- static class RollingAverage {
- private final int mmSampleSize;
- private final double mmData[];
- private int mmIndex = 0;
- private boolean mmFilled = false;
- private double mmSum = 0.0;
-
- public RollingAverage() {
- mmSampleSize = 5;
- mmData = new double[mmSampleSize];
- }
-
- public void add(double value) {
- mmSum -= mmData[mmIndex];
- mmData[mmIndex] = value;
- mmSum += mmData[mmIndex];
- ++mmIndex;
- mmIndex %= mmSampleSize;
- mmFilled = (!mmFilled) ? mmIndex == 0 : mmFilled;
- }
-
- public double get() throws IllegalStateException {
- if (!mmFilled && mmIndex == 0) {
- throw new IllegalStateException("No values to average.");
- }
- return (mmFilled) ? (mmSum / mmSampleSize) : (mmSum / mmIndex);
- }
- }
-}