package com.PP.StompDetector;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import com.PP.LunarTabsAndroid.Activities.MainActivity;
import com.PP.LunarTabsAndroid.UI.SerializedParams;
public class StompDetector implements SensorEventListener {
//const
public static final int START_WAIT_DEFAULT = 5000;
public static final int UNTRIGGER_DELAY_DEFAULT = 2000;
public static final float DEFAULT_SENSITIVITY = 0.1f;
//user params
protected float sensitivity;
protected int start_wait;
protected int untrigger_delay;
//state
protected volatile boolean enabled;
protected volatile boolean active;
protected volatile boolean prevTriggered;
protected float lastVal;
//stop/resume state
protected volatile boolean onStop_state = false;
//sensor managers and parent
protected SensorManager mSensorManager;
protected Sensor mAccel;
protected Activity parent;
//list of stomp listeners
protected List<StompListener> stompListeners;
public StompDetector(Activity parent) {
this.parent = parent;
enabled = false;
active = false;
prevTriggered = false;
start_wait = START_WAIT_DEFAULT;
untrigger_delay = UNTRIGGER_DELAY_DEFAULT;
sensitivity = DEFAULT_SENSITIVITY;
lastVal = -1;
stompListeners = new ArrayList<StompListener>();
//init sensors
mSensorManager = (SensorManager) parent.getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
mAccel = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccel,SensorManager.SENSOR_DELAY_NORMAL);
}
/**
* start function
*/
public void start() {
//look up and set params
this.setSensitivity(SerializedParams.getInstance().getStomperSensitivity());
this.setUntrigger_delay(SerializedParams.getInstance().getStomperDelay());
//make inactive for start wait
enabled = true;
deactiveFor(start_wait);
}
/**
* stop function
*/
public void stop() {
enabled = false;
active = false;
}
/**
*
* @param wait
*/
protected void deactiveFor(final int wait) {
//make triggering mechanism inactive and
//make reactive after wait
Thread t = new Thread() {
@Override
public void run() {
try {
active = false;
Thread.sleep(wait);
active = true;
}
catch(Exception e) {
e.printStackTrace();
}
}
};
t.start();
}
protected boolean trigger(float val) {
//if active, do trigger rule.
if(active) {
//diff rule
float diff = Math.abs(lastVal-val);
boolean triggered = (diff >= sensitivity);
//we've triggered and not previously triggered -- set inactive for delay time
if(!prevTriggered && triggered) {
prevTriggered = true;
if(untrigger_delay > 0) {
deactiveFor(untrigger_delay);
}
lastVal = val;
return true;
}
//not triggered and previously triggered and not in deactivate loop
//allow triggering again.
if(!triggered && prevTriggered) {
prevTriggered = false;
}
}
//update
lastVal = val;
//return false by default
return false;
}
@Override
public void onSensorChanged(SensorEvent event) {
if(enabled) {
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER) {
float accZ = event.values[2];
if(trigger(accZ)) {
double timestamp = System.currentTimeMillis();
for(StompListener l : stompListeners) {
l.trigger_callback(timestamp);
}
}
}
}
}
//unused
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
/**
* @return the enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* @param enabled the enabled to set
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* @return the sensitivity
*/
public float getSensitivity() {
return sensitivity;
}
/**
* @param sensitivity the sensitivity to set
*/
public void setSensitivity(float sensitivity) {
this.sensitivity = sensitivity;
}
/**
* @return the start_wait
*/
public int getStart_wait() {
return start_wait;
}
/**
* @param start_wait the start_wait to set
*/
public void setStart_wait(int start_wait) {
this.start_wait = start_wait;
}
/**
* @return the untrigger_delay
*/
public int getUntrigger_delay() {
return untrigger_delay;
}
/**
* @param untrigger_delay the untrigger_delay to set
*/
public void setUntrigger_delay(int untrigger_delay) {
this.untrigger_delay = untrigger_delay;
}
//interface methods
public void addStompListener(StompListener l) {
stompListeners.add(l);
}
public void removeStompListener(StompListener l) {
stompListeners.remove(l);
}
public void clearStompListeners() {
stompListeners.clear();
}
/**
* On stop
*/
public void onStop() {
onStop_state = this.isEnabled();
if(onStop_state) {
this.stop();
}
}
/**
* On resume
*/
public void onResume() {
if(onStop_state) {
this.start();
}
}
/**
* @param mainActivity the mainActivity to set
*/
public void setMainActivity(MainActivity mainActivity) {
this.parent = mainActivity;
for(StompListener l : stompListeners) {
if(l instanceof InstructionStomp) {
InstructionStomp is = (InstructionStomp) l;
is.setMainActivity(mainActivity);
}
}
}
}