diff --git a/gpii/node_modules/sensors/index.js b/gpii/node_modules/sensors/index.js
new file mode 100644
index 0000000..33c9fda
--- /dev/null
+++ b/gpii/node_modules/sensors/index.js
@@ -0,0 +1,17 @@
+/*!
+GPII Android Sensors
+
+Copyright 2013, 2014 Emergya
+
+Licensed under the New BSD license. You may not use this file except in
+compliance with this License.
+
+You may obtain a copy of the License at
+https://github.com/gpii/universal/LICENSE.txt
+*/
+
+var fluid = require("universal");
+
+var loader = fluid.getLoader(__dirname);
+
+loader.require("./sensors.js");
diff --git a/gpii/node_modules/sensors/package.json b/gpii/node_modules/sensors/package.json
new file mode 100644
index 0000000..ce07eff
--- /dev/null
+++ b/gpii/node_modules/sensors/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "sensors",
+ "description": "Used for interacting with built-in sensors.",
+ "version": "0.1",
+ "author": "Javier Hernández",
+ "bugs": "http://wiki.gpii.net/index.php/Main_Page",
+ "homepage": "http://gpii.net/",
+ "dependencies": {},
+ "licenses": [
+ {
+ "type": "BSD-3-Clause",
+ "url": "http://www.opensource.org/licenses/BSD-3-Clause"
+ }
+ ],
+ "keywords": ["gpii", "accessibility", "settings", "fluid"],
+ "repository": "git://github.com:GPII/android.git",
+ "main": "./index.js",
+ "engines": { "node" : ">=0.1.9" }
+}
diff --git a/gpii/node_modules/sensors/sensors.js b/gpii/node_modules/sensors/sensors.js
new file mode 100644
index 0000000..e3361a3
--- /dev/null
+++ b/gpii/node_modules/sensors/sensors.js
@@ -0,0 +1,140 @@
+/*!
+GPII Android Sensors
+
+Copyright 2013 Emergya
+
+Licensed under the New BSD license. You may not use this file except in
+compliance with this License.
+
+You may obtain a copy of the License at
+https://github.com/gpii/universal/LICENSE.txt
+*/
+
+// Currently we need to do this in order to work correctly with
+// Anode's JS bridge
+var thatall = this;
+
+(function () {
+ "use strict";
+
+ var http = require("http");
+ var fluid = require("universal");
+ var gpii = fluid.registerNamespace("gpii");
+
+ var bridge = require("bridge");
+ bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+
+ fluid.registerNamespace("gpii.androidSensors");
+
+ gpii.androidSensors.getEndPoint = function () {
+ var androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+ return androidSensors.getEndPoint();
+ };
+
+ gpii.androidSensors.setEndPoint = function (value) {
+ var androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+ androidSensors.setEndPoint(value);
+ };
+
+ fluid.defaults("gpii.androidSensors.getSensors", {
+ gradeNames: "fluid.function"
+ });
+
+ gpii.androidSensors.getSensors = function() {
+ var androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+
+ // TODO: Provide the full list of available sensors
+ // and some useful info about them, ie:
+ //
+ // [{
+ // id: xyz,
+ // name: getName,
+ // type: getType,
+ // maxRange: getMaximumRange,
+ // minDelay: getMinDelay,
+ // maxDelay: getMaxDelay,
+ // resolution: getResolution,
+ // version: getVerºsion,
+ // vendor: getVendor,
+ // power: getPower
+ // }]
+ //
+ // There's an initial implementation of it (in the Java side)
+ // but requires some work. Check AndroidSensorsImpl for details
+ //
+
+ var sensors = androidSensors.listSensors();
+ return sensors;
+ };
+
+ // Light sensor
+ //
+ gpii.androidSensors.startLightSensor = function () {
+ var androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+ androidSensors.startLightSensor();
+ };
+
+ gpii.androidSensors.stopLightSensor = function () {
+ var androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+ androidSensors.stopLightSensor();
+ };
+
+ // Noise sensor
+ //
+ gpii.androidSensors.noiseIntervalId = null;
+
+ gpii.androidSensors.startNoiseSensor = function () {
+ var androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+
+ gpii.androidSensors.noiseIntervalId = setInterval(function () {
+ var data = {
+ "http://registry.gpii.net/common/environment/auditory.noise": androidSensors.getAmplitudeEMA()
+ };
+
+ var headers = {
+ "Content-Type": 'application/json',
+ "Content-Length": JSON.stringify(data).length
+ };
+
+ var options = {
+ host: "localhost",
+ port: 8081,
+ path: "/environmentChanged",
+ method: "PUT",
+ headers: headers
+ };
+
+ var req = http.request(options, function(res) {
+ res.setEncoding("utf-8");
+
+ var responseString = "";
+
+ res.on("data", function(data) {
+ responseString += data;
+ });
+
+ //res.on("end", function() {
+ // TODO: handle the end event
+ //});
+ });
+
+ req.on("error", function(e) {
+ // TODO: handle error
+ });
+
+ req.write(JSON.stringify(data));
+ req.end();
+
+ }, 2000);
+
+ androidSensors.startNoiseSensor();
+ };
+
+ gpii.androidSensors.stopNoiseSensor = function () {
+ var androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+
+ clearInterval(gpii.androidSensors.noiseIntervalId);
+ androidSensors.stopNoiseSensor();
+ };
+
+})();
diff --git a/gpii/node_modules/sensors/sensorsTests.js b/gpii/node_modules/sensors/sensorsTests.js
new file mode 100644
index 0000000..a17ac5c
--- /dev/null
+++ b/gpii/node_modules/sensors/sensorsTests.js
@@ -0,0 +1,24 @@
+/*
+GPII Android Sensors Tests
+
+Copyright 2014 Emergya
+
+Licensed under the New BSD license. You may not use this file except in
+compliance with this License.
+
+You may obtain a copy of the License at
+https://github.com/gpii/universal/LICENSE.txt
+*/
+
+var thatall = this;
+
+var fluid = require("universal"),
+ jqUnit = fluid.require("jqUnit"),
+ gpii = fluid.registerNamespace("gpii"),
+ bridge = require("bridge"),
+ androidSensors = bridge.load("net.gpii.AndroidSensorsImpl", thatall);
+
+// TODO: Add tests
+
+//var sensors = androidSensors.listSensors();
+
diff --git a/index.js b/index.js
index ba02fff..1058fda 100644
--- a/index.js
+++ b/index.js
@@ -3,6 +3,7 @@
*
* Copyright 2012 OCAD University
* Copyright 2014 Lucendo Development Ltd.
+ * Copyright 2014 Emergya
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
@@ -19,7 +20,31 @@ var fluid = require("universal");
fluid.module.register("gpii-android", __dirname, require);
+// Native modules for settings handlers
+//
fluid.require("activitymanager", require);
fluid.require("androidSettings", require);
fluid.require("audioManager", require);
fluid.require("persistentConfiguration", require);
+
+// Native module for sensors
+//
+fluid.require("sensors", require);
+
+// Enable sensors and tell where the changes should be reported
+//
+androidSensors = fluid.registerNamespace("gpii.androidSensors");
+
+// This approach produces random crashes, as a workaround the endPoint is being
+// set in the Java side of code but it would be better to be able to configure
+// it from the javascript side
+//
+//androidSensors.setEndPoint("http://localhost:8081/environmentChanged");
+
+// Enable environmental light sensor
+//
+androidSensors.startLightSensor();
+
+// Enable environmental noise detection
+//
+androidSensors.startNoiseSensor();
diff --git a/platform/app/AndroidManifest.xml b/platform/app/AndroidManifest.xml
index 6ec2fd6..e54171f 100644
--- a/platform/app/AndroidManifest.xml
+++ b/platform/app/AndroidManifest.xml
@@ -16,6 +16,7 @@
+
diff --git a/platform/app/ant.properties b/platform/app/ant.properties
index d530201..9c65d16 100644
--- a/platform/app/ant.properties
+++ b/platform/app/ant.properties
@@ -16,4 +16,4 @@
# The password will be asked during the build when you use the 'release' target.
#source.dir=src;${env.ANODE_ROOT}/bridge-java/src;${env.ANODE_ROOT}/libnode/src;../anodeshare/src;../intents/src;../a11yservices/src
-source.dir=src;${env.ANODE_ROOT}/bridge-java/src;${env.ANODE_ROOT}/libnode/src;../anodeshare/src;../intents/src;../a11yservices/src;../androidSettings/src;../audioManager/src;../persistentconfig/src;libs
+source.dir=src;${env.ANODE_ROOT}/bridge-java/src;${env.ANODE_ROOT}/libnode/src;../anodeshare/src;../intents/src;../a11yservices/src;../androidSettings/src;../audioManager/src;../sensors/src;../persistentconfig/src;libs
diff --git a/platform/makestubs.sh b/platform/makestubs.sh
index 76b66c4..95213db 100644
--- a/platform/makestubs.sh
+++ b/platform/makestubs.sh
@@ -6,3 +6,4 @@ java -jar ./anode/sdk/java/tools/stubgen.jar --verbose --out ./androidSettings/s
java -jar ./anode/sdk/java/tools/stubgen.jar --verbose --out ./androidSettings/src --classpath ./app/bin/classes net.gpii.AndroidSettings
java -jar ./anode/sdk/java/tools/stubgen.jar --verbose --out ./audioManager/src --classpath ./app/bin/classes net.gpii.AndroidAudioManager
java -jar ./anode/sdk/java/tools/stubgen.jar --verbose --out ./persistentconfig/src --classpath ./app/bin/classes net.gpii.AndroidPersistentConfiguration
+java -jar ./anode/sdk/java/tools/stubgen.jar --verbose --out ./sensors/src --classpath ./app/bin/classes net.gpii.AndroidSensors
diff --git a/platform/sensors/src/net/gpii/AndroidSensors.java b/platform/sensors/src/net/gpii/AndroidSensors.java
new file mode 100644
index 0000000..a17015c
--- /dev/null
+++ b/platform/sensors/src/net/gpii/AndroidSensors.java
@@ -0,0 +1,29 @@
+package net.gpii;
+
+import org.meshpoint.anode.bridge.Env;
+import org.meshpoint.anode.java.Base;
+
+import java.util.List;
+
+public abstract class AndroidSensors extends Base {
+ private static short classId = Env.getInterfaceId(AndroidSensors.class);
+ public AndroidSensors() { super(classId); }
+
+ // This is the way we tell the android environmental reporter where the
+ // changes on the context should be reported.
+ //
+ public abstract String getEndPoint();
+ public abstract void setEndPoint(String value);
+
+ // Light sensor
+ //
+ public abstract String getLightSensor();
+ public abstract void startLightSensor();
+ public abstract void stopLightSensor();
+
+ // Noise sensor
+ //
+ public abstract void startNoiseSensor();
+ public abstract void stopNoiseSensor();
+ public abstract double getAmplitudeEMA();
+}
diff --git a/platform/sensors/src/net/gpii/AndroidSensorsImpl.java b/platform/sensors/src/net/gpii/AndroidSensorsImpl.java
new file mode 100644
index 0000000..08599c7
--- /dev/null
+++ b/platform/sensors/src/net/gpii/AndroidSensorsImpl.java
@@ -0,0 +1,355 @@
+package net.gpii;
+
+import net.gpii.SensorDict;
+
+import org.meshpoint.anode.AndroidContext;
+import org.meshpoint.anode.module.IModule;
+import org.meshpoint.anode.module.IModuleContext;
+import org.meshpoint.anode.idl.Dictionary;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.ConnectException;
+import java.text.DecimalFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.HttpResponse;
+
+import org.json.JSONObject;
+
+
+public class AndroidSensorsImpl extends AndroidSensors implements IModule {
+ private static final String TAG = "net.gpii.AndroidSensorsImpl";
+
+ IModuleContext ctx;
+ private Context androidContext;
+ private SensorManager sensorManager;
+ private float currentLightValue;
+
+ // For the noise sensor
+ //
+ private MediaRecorder mRecorder;
+ private Thread runner = null;
+
+ private static double mEMA = 0.0;
+ static final private double EMA_FILTER = 0.6;
+
+ final Runnable updater = new Runnable() {
+ public void run() {
+ updateNoiseValue();
+ }
+ };
+
+ private Handler mHandler;
+
+ // Common terms for environmental data
+ //
+ private static final String LUMINANCE = "http://registry.gpii.net/common/environment/visual.luminance";
+ private static final String NOISE = "http://registry.gpii.net/common/environment/auditory.noise";
+
+ // endPoint where sensors must report their values when they change
+ //
+ private String endPoint = "http://localhost:8081/environmentChanged";
+
+ private final Map SENSOR_TYPE =
+ new HashMap() {{
+ put("TYPE_ACCELEROMETER", Sensor.TYPE_ACCELEROMETER);
+ put("TYPE_ALL", Sensor.TYPE_ALL);
+ put("TYPE_AMBIENT_TEMPERATURE", Sensor.TYPE_AMBIENT_TEMPERATURE);
+ put("TYPE_GAME_ROTATION_VECTOR", Sensor.TYPE_GAME_ROTATION_VECTOR);
+ // API Level 19
+ //put("TYPE_GEOMAGNETIC_ROTATION_VECTOR", Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
+ put("TYPE_GRAVITY", Sensor.TYPE_GRAVITY);
+ put("TYPE_GYROSCOPE", Sensor.TYPE_GYROSCOPE);
+ put("TYPE_GYROSCOPE_UNCALIBRATED", Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
+ // API Level 20
+ //put("TYPE_HEART_RATE", Sensor.TYPE_HEART_RATE);
+ put("TYPE_LIGHT", Sensor.TYPE_LIGHT);
+ put("TYPE_LINEAR_ACCELERATION", Sensor.TYPE_LINEAR_ACCELERATION);
+ put("TYPE_MAGNETIC_FIELD", Sensor.TYPE_MAGNETIC_FIELD);
+ put("TYPE_MAGNETIC_FIELD_UNCALIBRATED", Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
+ put("TYPE_ORIENTATION", Sensor.TYPE_ORIENTATION);
+ put("TYPE_PRESSURE", Sensor.TYPE_PRESSURE);
+ put("TYPE_PROXIMITY", Sensor.TYPE_PROXIMITY);
+ put("TYPE_RELATIVE_HUMIDITY", Sensor.TYPE_RELATIVE_HUMIDITY);
+ put("TYPE_ROTATION_VECTOR", Sensor.TYPE_ROTATION_VECTOR);
+ put("TYPE_SIGNIFICANT_MOTION", Sensor.TYPE_SIGNIFICANT_MOTION);
+ // API Level 19
+ //put("TYPE_STEP_COUNTER", Sensor.TYPE_STEP_COUNTER);
+ //put("TYPE_STEP_DETECTOR", Sensor.TYPE_STEP_DETECTOR);
+ put("TYPE_TEMPERATURE", Sensor.TYPE_TEMPERATURE);
+ }};
+
+ @Override
+ public Object startModule(IModuleContext ctx) {
+ Log.v(TAG, "AndroidSensorsImpl.startModule");
+ try {
+ this.ctx = ctx;
+ androidContext = ((AndroidContext) ctx).getAndroidContext();
+ sensorManager = (SensorManager) androidContext.getSystemService(Context.SENSOR_SERVICE);
+ }
+ catch (Exception e) {
+ Log.v(TAG, "AndroidSensorsImpl error starting module: " + e);
+ }
+ return this;
+ }
+
+ @Override
+ public void stopModule() {
+ Log.v(TAG, "AndroidSensorsImpl.stopModule");
+ }
+
+ // TODO: Transform this into JSON
+ //
+ //@Override
+ //public List listSensors () {
+ // List sensorsList = new ArrayList();
+
+ // List sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
+ // for (Sensor sensor: sensors) {
+ // SensorDict s = new SensorDict();
+
+ // s.name = sensor.getName();
+ // s.type = getSensorType(sensor.getType());
+ // s.maximumRange = sensor.getMaximumRange();
+ // s.minDelay = sensor.getMinDelay();
+ // // Commented because this was introduced in API level 21
+ // //s.maxDelay = sensor.getMaxDelay();
+ // s.resolution = sensor.getResolution();
+ // s.version = sensor.getVersion();
+ // s.vendor = sensor.getVendor();
+ // s.power = sensor.getPower();
+
+ // sensorsList.add(s);
+ // }
+
+ // return sensorsList;
+ //}
+
+ SensorEventListener lightSensorEventListener = new SensorEventListener() {
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ //Log.d("### ACCURACY CHANGED: ", String.valueOf(accuracy));
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ //Log.d("[node] ### VALUE CHANGED: ", String.valueOf(event.values[0]));
+ if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
+ final float currentReading = event.values[0];
+ //Log.d("### VALUES: ", String.valueOf(currentReading));
+ currentLightValue = currentReading;
+
+ JSONObject lightValue = new JSONObject();
+ try {
+ lightValue.put(LUMINANCE, currentReading);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ reportChanges(lightValue);
+ }
+ }
+ };
+
+ @Override
+ public void startLightSensor() {
+ Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+ sensorManager.registerListener(lightSensorEventListener,
+ sensor,
+ 99999999);
+ }
+
+ @Override
+ public void stopLightSensor() {
+ Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+ sensorManager.unregisterListener(lightSensorEventListener, sensor);
+ }
+
+ @Override
+ public String getLightSensor () {
+ Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+
+ JSONObject sensorJSON = new JSONObject();
+ try {
+ sensorJSON.put("name", sensor.getName());
+ sensorJSON.put("type", getSensorType(sensor.getType()));
+ sensorJSON.put("maximumRange", sensor.getMaximumRange());
+ sensorJSON.put("minDelay", sensor.getMinDelay());
+ sensorJSON.put("resolution", sensor.getResolution());
+ sensorJSON.put("version", sensor.getVersion());
+ sensorJSON.put("vendor", sensor.getVendor());
+ sensorJSON.put("power", sensor.getPower());
+ sensorJSON.put("currentValue", currentLightValue);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return sensorJSON.toString();
+ }
+
+ private String getSensorType (int value) {
+ for (String key: SENSOR_TYPE.keySet()) {
+ if (SENSOR_TYPE.get(key).equals(value)) {
+ return key;
+ }
+ }
+ return "TYPE_UNKNOWN";
+ }
+
+ // This function is where we make a PUT reuest to the flow manager
+ // telling the new value for a concrete sensor
+ //
+ public void reportChanges (JSONObject change) {
+ Log.d(TAG, "[node] on reportChanges");
+
+ HttpClient client = new DefaultHttpClient();
+ HttpPut put = new HttpPut(endPoint.toString());
+ StringEntity se = null;
+
+ try {
+ se = new StringEntity(change.toString());
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ };
+
+ se.setContentType("application/json;charset=UTF-8");
+ se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8"));
+ put.setEntity(se);
+
+ // TODO: Improve the handling of exceptions
+ //
+ try {
+ HttpResponse response = client.execute(put);
+ Log.d(TAG, "[node] after client.execute");
+ } catch (ConnectException e) {
+ //e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void setEndPoint(String value) {
+ endPoint = value;
+ }
+
+ @Override
+ public String getEndPoint() {
+ return endPoint;
+ }
+
+ @Override
+ public void startNoiseSensor() {
+ Log.d(TAG, "[node] Starting noise sensor ....");
+ // This approach didn't work, so we're scheduling reads from the
+ // javascript side of the code by using node's setInterval
+ //
+ //mHandler = new Handler();
+ //if (runner == null) {
+ // Not working - is AsyncTask the solution?
+ //runner = new Thread() {
+ // public void run() {
+ // Log.d("NOISE", "[node] RUNNING the Thread");
+ // while (runner != null) {
+ // try {
+ // Thread.sleep(500);
+ // Log.d("Noise", "Tick");
+ // } catch (InterruptedException e) {
+ // Log.e("Noise", "" + e.getMessage());
+ // }
+ // mHandler.post(updater);
+ // }
+ // }
+ //};
+ //runner.start();
+ //Log.d("Noise", "start runner()");
+ //}
+ startRecorder();
+ }
+
+ @Override
+ public void stopNoiseSensor() {
+ stopRecorder();
+ }
+
+ public void startRecorder() {
+ Log.d(TAG, "[node] on startRecorder");
+ if (mRecorder == null) {
+ mRecorder = new MediaRecorder();
+ mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+ mRecorder.setOutputFile("/dev/null");
+
+ try {
+ mRecorder.prepare();
+ } catch (java.io.IOException ioe) {
+ android.util.Log.e("[Monkey]", "IOException: " + android.util.Log.getStackTraceString(ioe));
+ } catch (java.lang.SecurityException e) {
+ android.util.Log.e("[Monkey]", "SecurityException: " + android.util.Log.getStackTraceString(e));
+ }
+
+ try {
+ mRecorder.start();
+ } catch (java.lang.SecurityException e) {
+ android.util.Log.e("[Monkey]", "SecurityException: " + android.util.Log.getStackTraceString(e));
+ }
+ }
+ }
+
+ public void stopRecorder() {
+ if (mRecorder != null) {
+ mRecorder.stop();
+ mRecorder.release();
+ mRecorder = null;
+ }
+ }
+
+ public void updateNoiseValue() {
+ DecimalFormat df = new DecimalFormat("#.##");
+ float currentReading = Float.parseFloat(df.format(getAmplitudeEMA()));
+
+ JSONObject noiseValue = new JSONObject();
+ try {
+ noiseValue.put(NOISE, currentReading);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ reportChanges(noiseValue);
+ }
+
+ public double getAmplitude() {
+ if (mRecorder != null)
+ return (mRecorder.getMaxAmplitude());
+ else
+ return 0;
+ }
+
+ @Override
+ public double getAmplitudeEMA() {
+ double amp = getAmplitude();
+ mEMA = EMA_FILTER * amp + (1.0 - EMA_FILTER) * mEMA;
+ return mEMA;
+ }
+
+}
diff --git a/platform/sensors/src/net/gpii/SensorDict.java b/platform/sensors/src/net/gpii/SensorDict.java
new file mode 100644
index 0000000..82cd71a
--- /dev/null
+++ b/platform/sensors/src/net/gpii/SensorDict.java
@@ -0,0 +1,16 @@
+package net.gpii;
+
+import org.meshpoint.anode.idl.Dictionary;
+
+public class SensorDict implements Dictionary {
+ public String name;
+ public String type; // This is a float const, but we will use a string
+ public float maximumRange;
+ public int minDelay;
+ // Commented because it's from API level 21
+ //public int maxDelay;
+ public float resolution;
+ public float version;
+ public String vendor;
+ public float power;
+}
diff --git a/platform/sensors/src/org/meshpoint/anode/stub/gen/platform/Net_gpii_AndroidSensors.java b/platform/sensors/src/org/meshpoint/anode/stub/gen/platform/Net_gpii_AndroidSensors.java
new file mode 100644
index 0000000..235d155
--- /dev/null
+++ b/platform/sensors/src/org/meshpoint/anode/stub/gen/platform/Net_gpii_AndroidSensors.java
@@ -0,0 +1,45 @@
+/* This file has been automatically generated; do not edit */
+
+package org.meshpoint.anode.stub.gen.platform;
+
+public final class Net_gpii_AndroidSensors {
+
+ private static Object[] __args = new Object[1];
+
+ public static Object[] __getArgs() { return __args; }
+
+ static Object __invoke(net.gpii.AndroidSensors inst, int opIdx, Object[] args) {
+ Object result = null;
+ switch(opIdx) {
+ case 0: /* getAmplitudeEMA */
+ result = org.meshpoint.anode.js.JSValue.asJSNumber(inst.getAmplitudeEMA());
+ break;
+ case 1: /* getEndPoint */
+ result = inst.getEndPoint();
+ break;
+ case 2: /* getLightSensor */
+ result = inst.getLightSensor();
+ break;
+ case 3: /* setEndPoint */
+ inst.setEndPoint(
+ (String)args[0]
+ );
+ break;
+ case 4: /* startLightSensor */
+ inst.startLightSensor();
+ break;
+ case 5: /* startNoiseSensor */
+ inst.startNoiseSensor();
+ break;
+ case 6: /* stopLightSensor */
+ inst.stopLightSensor();
+ break;
+ case 7: /* stopNoiseSensor */
+ inst.stopNoiseSensor();
+ break;
+ default:
+ }
+ return result;
+ }
+
+}