package org.witness.informacam.informa.suckers;
import java.util.List;
import java.util.TimerTask;
import org.witness.informacam.informa.SensorLogger;
import org.witness.informacam.json.JSONException;
import org.witness.informacam.models.j3m.ILogPack;
import org.witness.informacam.models.utils.PressureServiceUpdater;
import org.witness.informacam.utils.Constants.Suckers;
import org.witness.informacam.utils.Constants.Suckers.Environment;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.AsyncTask;
import android.util.Log;
@SuppressWarnings("rawtypes")
public class EnvironmentalSucker extends SensorLogger implements SensorEventListener {
SensorManager sm;
List<Sensor> availableSensors;
org.witness.informacam.models.j3m.ILogPack currentAmbientTemp, currentDeviceTemp, currentHumidity, currentPressure, currentLight;
float mPressureSeaLevel = SensorManager.PRESSURE_STANDARD_ATMOSPHERE;
private final static String LOG = Suckers.LOG;
@SuppressWarnings({ "unchecked", "deprecation" })
public EnvironmentalSucker(Context context) {
super(context);
setSucker(this);
sm = (SensorManager)context.getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
availableSensors = sm.getSensorList(Sensor.TYPE_ALL);
for(Sensor s : availableSensors) {
switch(s.getType()) {
case Sensor.TYPE_AMBIENT_TEMPERATURE:
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
break;
case Sensor.TYPE_RELATIVE_HUMIDITY:
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
break;
case Sensor.TYPE_PRESSURE:
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
break;
case Sensor.TYPE_LIGHT:
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
break;
case Sensor.TYPE_TEMPERATURE:
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
break;
}
}
setTask(new TimerTask() {
@Override
public void run() {
if(currentAmbientTemp != null)
sendToBuffer(currentAmbientTemp);
if(currentDeviceTemp != null)
sendToBuffer(currentDeviceTemp);
if(currentHumidity != null)
sendToBuffer(currentHumidity);
if(currentPressure != null)
sendToBuffer(currentPressure);
if(currentLight != null)
sendToBuffer(currentLight);
}
});
getTimer().schedule(getTask(), 0, Environment.LOG_RATE);
}
public ILogPack forceReturn() throws JSONException {
ILogPack fr = new ILogPack();
if (currentAmbientTemp != null)
fr.put(Environment.Keys.AMBIENT_TEMP, currentAmbientTemp);
if (currentDeviceTemp != null)
fr.put(Environment.Keys.DEVICE_TEMP, currentDeviceTemp);
if (currentHumidity != null)
fr.put(Environment.Keys.HUMIDITY, currentHumidity);
if (currentPressure != null)
fr.put(Environment.Keys.PRESSURE, currentPressure);
if (currentLight != null)
fr.put(Environment.Keys.LIGHT, currentLight);
return fr;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
/**
*
Sensor Sensor event data Units of measure Data description
TYPE_AMBIENT_TEMPERATURE event.values[0] °C Ambient air temperature.
TYPE_LIGHT event.values[0] lx Illuminance.
TYPE_PRESSURE event.values[0] hPa or mbar Ambient air pressure.
TYPE_RELATIVE_HUMIDITY event.values[0] % Ambient relative humidity.
TYPE_TEMPERATURE event.values[0] °C Device temperature.1
*/
@SuppressWarnings("deprecation")
@Override
public void onSensorChanged(SensorEvent event) {
synchronized(this) {
if(getIsRunning()) {
ILogPack sVals = new ILogPack();
try {
switch(event.sensor.getType()) {
case Sensor.TYPE_AMBIENT_TEMPERATURE:
sVals.put(Environment.Keys.AMBIENT_TEMP_CELSIUS, event.values[0]);
currentAmbientTemp = sVals;
break;
case Sensor.TYPE_TEMPERATURE:
sVals.put(Environment.Keys.DEVICE_TEMP_CELSIUS, event.values[0]);
currentDeviceTemp = sVals;
break;
case Sensor.TYPE_RELATIVE_HUMIDITY:
sVals.put(Environment.Keys.HUMIDITY_PERC,event.values[0]);
currentHumidity = sVals;
break;
case Sensor.TYPE_PRESSURE:
sVals.put(Environment.Keys.PRESSURE_MBAR, event.values[0]);
//TODO we need to get real local sea level pressure here from a dynamic source
//as the default value doesn't cut it
float altitudeFromPressure = SensorManager.getAltitude(mPressureSeaLevel, event.values[0]);
sVals.put(Environment.Keys.PRESSURE_ALTITUDE, altitudeFromPressure);
currentPressure = sVals;
break;
case Sensor.TYPE_LIGHT:
sVals.put(Environment.Keys.LIGHT_METER_VALUE, event.values[0]);
currentLight = sVals;
break;
}
} catch(JSONException e) {}
}
}
}
public void stopUpdates() {
setIsRunning(false);
sm.unregisterListener(this);
Log.d(LOG, "shutting down EnviroSucker...");
}
public void updateSeaLevelPressure (final double latitude, final double longitude)
{
new AsyncTask<Double, Void, Float>() {
@Override
protected Float doInBackground(Double... params) {
return PressureServiceUpdater.GetRefPressure(params[0],params[1]);
}
@Override
protected void onPostExecute(Float result) {
mPressureSeaLevel = result.floatValue();
Log.d("Pressure","got updated sea level pressure: " + mPressureSeaLevel);
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}.execute(latitude, longitude);
}
}