/** Copyright 2015 Tim Engler, Rareventure LLC This file is part of Tiny Travel Tracker. Tiny Travel Tracker is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Tiny Travel Tracker is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Tiny Travel Tracker. If not, see <http://www.gnu.org/licenses/>. */ package com.rareventure.android; import java.io.DataOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.List; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.SystemClock; public class SensorReader implements DataReader { private SensorEventListener mListener; private ProcessThread processThread; private SensorDataBuffer sensorDataBuffer; private SensorProcessor sensorProcessor; private SensorManager sm; private Object lock = new Object(); private int[] sensorTypeSensorDelay; private DataOutputStream os; /** * * @param os * @param sensorProcessor * @param context * @param adb * @param sensorTypeSensorDelay Sensor.TYPE_*, SensorManager.*DELAY. Note that the first argument is not SensorManager.SENSOR_*, * which sucks when you mistaken one for the other. */ public SensorReader(DataOutputStream os, SensorProcessor sensorProcessor, Context context, SensorDataBuffer adb, int ... sensorTypeSensorDelay) { this.os = os; this.sensorProcessor = sensorProcessor; this.sensorDataBuffer = adb; mListener = new SensorEventListener() { public void onAccuracyChanged(Sensor sensor, int accuracy) { } public void onSensorChanged(SensorEvent event) { //write to queue and update the read index synchronized(processThread.lock) { sensorDataBuffer.type[sensorDataBuffer.rawReadIndex] = event.sensor.getType(); sensorDataBuffer.v1[sensorDataBuffer.rawReadIndex] = event.values[0]; sensorDataBuffer.v2[sensorDataBuffer.rawReadIndex] = event.values[1]; sensorDataBuffer.v3[sensorDataBuffer.rawReadIndex] = event.values[2]; sensorDataBuffer.timeRead[sensorDataBuffer.rawReadIndex] = System.currentTimeMillis(); sensorDataBuffer.updateReadIndex(); processThread.lock.notify(); //notify there is some new data to read } } }; this.sm = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); this.sensorTypeSensorDelay = sensorTypeSensorDelay; } public void turnOn() { for(int i = 0; i < sensorTypeSensorDelay.length; i+= 2) { List<Sensor> sensors = sm.getSensorList(sensorTypeSensorDelay[i]); sm.registerListener(mListener, sensors.get(0), sensorTypeSensorDelay[i+1]); } } public void turnOff() { sm.unregisterListener(mListener); } @Override public boolean canProcess() { return sensorDataBuffer.rawProcessIndex != sensorDataBuffer.rawReadIndex; } @Override public void process() { sensorProcessor.processSensorData(sensorDataBuffer.type[sensorDataBuffer.rawProcessIndex], sensorDataBuffer.v1[sensorDataBuffer.rawProcessIndex], sensorDataBuffer.v2[sensorDataBuffer.rawProcessIndex], sensorDataBuffer.v3[sensorDataBuffer.rawProcessIndex], sensorDataBuffer.timeRead[sensorDataBuffer.rawProcessIndex]); if(os != null) writeTestData(); synchronized(processThread.lock) { sensorDataBuffer.updateProcessIndex(); } } @Override public void setProcessThread(ProcessThread processThread) { this.processThread = processThread; } public interface SensorProcessor { void processSensorData(int type, float v1, float v2, float v3, long time); } @Override public void notifyShutdown() { turnOff(); } private void writeTestData() { //TODO x1: hack to see if the strategy thread is starving // synchronized(TestUtil.class) // { // try { // TestUtil.writeMode(os, WriteConstants.MODE_WRITE_SENSOR_DATA); // // TestUtil.writeInt("type", os, sensorDataBuffer.type[sensorDataBuffer.rawProcessIndex]); // TestUtil.writeFloat("v1", os, sensorDataBuffer.v1[sensorDataBuffer.rawProcessIndex]); // TestUtil.writeFloat("v2", os, sensorDataBuffer.v2[sensorDataBuffer.rawProcessIndex]); // TestUtil.writeFloat("v3", os, sensorDataBuffer.v3[sensorDataBuffer.rawProcessIndex]); // TestUtil.writeTime("timeRead", os, sensorDataBuffer.timeRead[sensorDataBuffer.rawProcessIndex]); // } // catch(IOException e) // { // throw new IllegalStateException(e); //punt but not a todo because this is test code // } // } } }