diff options
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.java | 496 |
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); - } - } -} |