diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1cca200..aaaf61d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,6 +20,16 @@
android:label="@string/app_name"
android:theme="@style/AppTheme" >
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+ android:text="@string/label_data_sampling" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/res/layout/fragment_accelerometer_settings.xml b/res/layout/fragment_accelerometer_settings.xml
new file mode 100644
index 0000000..e7b7ab0
--- /dev/null
+++ b/res/layout/fragment_accelerometer_settings.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/fragment_data_plot.xml b/res/layout/fragment_data_plot.xml
new file mode 100644
index 0000000..fcd3d5e
--- /dev/null
+++ b/res/layout/fragment_data_plot.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/res/layout/fragment_device_info.xml b/res/layout/fragment_device_info.xml
index 621de64..960970c 100644
--- a/res/layout/fragment_device_info.xml
+++ b/res/layout/fragment_device_info.xml
@@ -142,21 +142,38 @@ contact MbientLab Inc, at www.mbientlab.com.
android:orientation="horizontal" >
+
+
+
-
+ android:layout_weight="1"
+ android:textColor="@color/action_text"
+ android:text="@string/label_battery_level" />
+
+
+
diff --git a/res/values/color.xml b/res/values/color.xml
index b72fe2b..ea03438 100644
--- a/res/values/color.xml
+++ b/res/values/color.xml
@@ -16,4 +16,5 @@
#BBBDC0
#AAABAF
+ #3D3AB0
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cd943d5..19b4faf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -43,7 +43,8 @@ contact MbientLab Inc, at www.mbientlab.com.
Manufacturer
Firmware Version
Hardware Version
- Temperature
+ Temperature
+ Battery Level
Accelerometer Data
In Free Fall
Red
@@ -129,4 +130,19 @@ contact MbientLab Inc, at www.mbientlab.com.
Color Channel
High Intensity
Low Intensity
+ Tap Detection
+ Shake Detection
+ Orientation Detection
+ Movement Detection
+ Movement Axes
+ Data Sampling
+ Enable
+ Start
+ Stop
+ Tap Type
+ Tap Axis
+ Shake Axis
+ Movement Type
+ Data Range
+ Sampling Rate
diff --git a/res/xml/filepaths.xml b/res/xml/filepaths.xml
new file mode 100644
index 0000000..c99a743
--- /dev/null
+++ b/res/xml/filepaths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/com/mbientlab/metawear/app/AccelerometerFragment.java b/src/com/mbientlab/metawear/app/AccelerometerFragment.java
index 827aa05..8b5513d 100644
--- a/src/com/mbientlab/metawear/app/AccelerometerFragment.java
+++ b/src/com/mbientlab/metawear/app/AccelerometerFragment.java
@@ -31,32 +31,45 @@
package com.mbientlab.metawear.app;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.concurrent.ConcurrentLinkedQueue;
-import com.androidplot.xy.LineAndPointFormatter;
-import com.androidplot.xy.SimpleXYSeries;
-import com.androidplot.xy.XYPlot;
-import com.androidplot.xy.SimpleXYSeries.ArrayFormat;
+import com.jjoe64.graphview.GraphViewDataInterface;
+import com.jjoe64.graphview.GraphView.GraphViewData;
import com.mbientlab.metawear.api.Module;
import com.mbientlab.metawear.api.controller.Accelerometer;
-import com.mbientlab.metawear.api.controller.Accelerometer.Component;
+import com.mbientlab.metawear.api.controller.Accelerometer.*;
+import com.mbientlab.metawear.api.controller.Accelerometer.SamplingConfig.FullScaleRange;
+import com.mbientlab.metawear.api.controller.Accelerometer.SamplingConfig.OutputDataRate;
+import com.mbientlab.metawear.api.util.BytesInterpreter;
+import com.mbientlab.metawear.app.popup.AccelerometerSettings;
+import com.mbientlab.metawear.app.popup.DataPlotFragment;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
+import android.support.v4.content.FileProvider;
+import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.widget.CheckBox;
import android.widget.Button;
-import android.widget.Toast;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.TextView;
+import android.widget.ToggleButton;
/**
* @author etsai
@@ -75,17 +88,77 @@ public AxisData(long tick, short x, short y, short z) {
public final long tick;
public final short[] data;
}
+
+ private interface ProcessedAxisData {
+ public Collection xData();
+ public Collection yData();
+ public Collection zData();
+ }
+
private long start;
+ private ConcurrentLinkedQueue polledData;
+ private ProcessedAxisData processedData;
private Accelerometer accelController;
+
+ private static final AlphaAnimation fadeOut= new AlphaAnimation(1.0f , 0.0f);
+ static {
+ fadeOut.setDuration(2000);
+ fadeOut.setFillAfter(true);
+ }
+
private Accelerometer.Callbacks mCallback= new Accelerometer.Callbacks() {
+
+ @Override
+ public void movementDetected(MovementData moveData) {
+ TextView shakeText= (TextView) getView().findViewById(R.id.textView8);
+ if (ffMovement) {
+ shakeText.setText("Falling Skies");
+ } else {
+ shakeText.setText("Move your body");
+ }
+ shakeText.startAnimation(fadeOut);
+ }
+
+ @Override
+ public void orientationChanged(Orientation accelOrientation) {
+ TextView shakeText= (TextView) getView().findViewById(R.id.textView6);
+ shakeText.setText(String.format(Locale.US, "%s", accelOrientation.toString()));
+ }
+
+ @Override
+ public void shakeDetected(MovementData moveData) {
+ TextView shakeText= (TextView) getView().findViewById(R.id.textView4);
+ shakeText.setText("Shake it like a polariod picture");
+ shakeText.startAnimation(fadeOut);
+ }
+
+ @Override
+ public void doubleTapDetected(MovementData moveData) {
+ TextView tapText= (TextView) getView().findViewById(R.id.textView2);
+ tapText.setText("Double Beer Taps");
+ tapText.startAnimation(fadeOut);
+ }
+
+ @Override
+ public void singleTapDetected(MovementData moveData) {
+ TextView tapText= (TextView) getView().findViewById(R.id.textView2);
+ tapText.setText("Beer Tap");
+ tapText.startAnimation(fadeOut);
+ }
+
+ @Override
public void receivedDataValue(short x, short y, short z) {
if (polledData != null) {
- polledData.add(new AxisData(System.currentTimeMillis() - start, x, y, z));
+ if (start == 0) {
+ polledData.add(new AxisData(0, x, y, z));
+ start= System.currentTimeMillis();
+ } else {
+ polledData.add(new AxisData(System.currentTimeMillis() - start, x, y, z));
+ }
}
-
}
};
-
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -108,134 +181,205 @@ public void onServiceConnected(ComponentName name, IBinder service) {
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putBoolean("RECORDING", recording);
- outState.putBoolean("PLOT_READY", plotReady);
}
- private boolean recording= false, plotReady= false;
- private XYPlot accelHistoryPlot;
- private SimpleXYSeries xAxis, yAxis, zAxis;
- private ConcurrentLinkedQueue polledData;
-
- private FileOutputStream fos= null;
- private static final String FILENAME= "metawear_accelerometer_data_50hz_2g.csv",
- CSV_HEADER= String.format("time,xAxis,yAxis,zAxis%n");
+ private static final String CSV_HEADER= String.format("time,xAxis,yAxis,zAxis%n");
+ private String dataFilename;
+
+ private enum CheckBoxName {
+ TAP, SHAKE, ORIENTATION, FREE_FALL, SAMPLING;
+ }
+ private HashMap checkboxes;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
- if (savedInstanceState != null) {
- recording= savedInstanceState.getBoolean("RECORDING");
- plotReady= savedInstanceState.getBoolean("PLOT_READY");
- }
-
- xAxis= new SimpleXYSeries("X Axis");
- xAxis.useImplicitXVals();
- yAxis= new SimpleXYSeries("Y Axis");
- yAxis.useImplicitXVals();
- zAxis= new SimpleXYSeries("Z Axis");
- zAxis.useImplicitXVals();
+ checkboxes= new HashMap<>();
+ checkboxes.put(CheckBoxName.TAP, (CheckBox) view.findViewById(R.id.checkBox1));
+ checkboxes.put(CheckBoxName.SHAKE, (CheckBox) view.findViewById(R.id.checkBox2));
+ checkboxes.put(CheckBoxName.ORIENTATION, (CheckBox) view.findViewById(R.id.checkBox3));
+ checkboxes.put(CheckBoxName.FREE_FALL, (CheckBox) view.findViewById(R.id.checkBox4));
+ checkboxes.put(CheckBoxName.SAMPLING, (CheckBox) view.findViewById(R.id.checkBox5));
- accelHistoryPlot= (XYPlot) view.findViewById(R.id.aprHistoryPlot);
- accelHistoryPlot.addSeries(xAxis, new LineAndPointFormatter(Color.RED, Color.TRANSPARENT, Color.TRANSPARENT, null));
- accelHistoryPlot.addSeries(yAxis, new LineAndPointFormatter(Color.GREEN, Color.TRANSPARENT, Color.TRANSPARENT, null));
- accelHistoryPlot.addSeries(zAxis, new LineAndPointFormatter(Color.BLUE, Color.TRANSPARENT, Color.TRANSPARENT, null));
- accelHistoryPlot.setTicksPerRangeLabel(3);
- accelHistoryPlot.getGraphWidget().getDomainLabelPaint().setColor(Color.TRANSPARENT);
- accelHistoryPlot.setRangeLabel("Measured g's");
- accelHistoryPlot.getRangeLabelWidget().pack();
-
- final Button recordButton= (Button) view.findViewById(R.id.button1);
- recordButton.setOnClickListener(new OnClickListener() {
+ ((ToggleButton) view.findViewById(R.id.toggleButton1)).setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
- public void onClick(View v) {
- if (!recording) {
- accelController.setComponentConfiguration(Component.DATA,
- new byte[] {0, 0, 0x20, 0, 0});
-
- polledData= new ConcurrentLinkedQueue();
- start= System.currentTimeMillis();
- accelController.enableNotification(Component.DATA);
- recording= true;
- recordButton.setText(R.string.label_accelerometer_data_stop);
- } else {
- accelController.disableNotification(Component.DATA);
- plotReady= false;
- new Thread(new Runnable() {
- public void run() {
- try {
- ArrayList xVals= new ArrayList<>(),
- yVals= new ArrayList<>(), zVals= new ArrayList<>();
-
- fos= AccelerometerFragment.this.getActivity().openFileOutput(FILENAME, Context.MODE_WORLD_READABLE);
- fos.write(CSV_HEADER.getBytes());
- for(AxisData it: polledData) {
- double xG= it.data[0] / 1024.0, yG= it.data[1] / 1024.0,
- zG= it.data[2] / 1024.0;
-
- fos.write(String.format("%.3f,%.3f,%.3f,%.3f%n", it.tick / 1000.0, xG, yG, zG).getBytes());
-
- xVals.add(xG);
- yVals.add(yG);
- zVals.add(zG);
- }
- xAxis.setModel(xVals, ArrayFormat.Y_VALS_ONLY);
- yAxis.setModel(yVals, ArrayFormat.Y_VALS_ONLY);
- zAxis.setModel(zVals, ArrayFormat.Y_VALS_ONLY);
-
- fos.close();
- fos= null;
- } catch (IOException e) {
- e.printStackTrace();
- }
- plotReady= true;
+ public void onCheckedChanged(CompoundButton buttonView,
+ boolean isChecked) {
+ if (isChecked) {
+ if (checkboxes.get(CheckBoxName.TAP).isChecked()) {
+ accelController.enableTapDetection(TapType.values()[tapType],
+ Axis.values()[tapAxis]);
+ }
+ if (checkboxes.get(CheckBoxName.SHAKE).isChecked()) {
+ accelController.enableShakeDetection(Axis.values()[shakeAxis]);
+ }
+ if (checkboxes.get(CheckBoxName.ORIENTATION).isChecked()) {
+ accelController.enableOrientationDetection();
+ }
+ if (checkboxes.get(CheckBoxName.FREE_FALL).isChecked()) {
+ if (ffMovement) {
+ accelController.enableFreeFallDetection();
+ } else {
+ accelController.enableMotionDetection(Axis.values());
}
- }).start();
- recordButton.setText(R.string.label_accelerometer_data_record);
- recording= false;
+ }
+ if (checkboxes.get(CheckBoxName.SAMPLING).isChecked()) {
+ processedData= null;
+ polledData= new ConcurrentLinkedQueue<>();
+ samplingConfig= accelController.enableXYZSampling();
+ samplingConfig.withFullScaleRange(FullScaleRange.values()[dataRange])
+ .withOutputDataRate(OutputDataRate.values()[samplingRate]);
+ start= 0;
+ }
+ for(CheckBox box: checkboxes.values()) {
+ box.setEnabled(false);
+ }
+ accelController.startComponents();
+ } else {
+ accelController.stopComponents();
+ accelController.disableAllDetection(true);
+ for(CheckBox box: checkboxes.values()) {
+ box.setEnabled(true);
+ }
}
+
}
});
- if (recording) {
- recordButton.setText(R.string.label_accelerometer_data_stop);
- } else {
- recordButton.setText(R.string.label_accelerometer_data_record);
- }
-
((Button) view.findViewById(R.id.button2)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- if (recording) {
- Toast.makeText(AccelerometerFragment.this.getActivity(), "Stop data recording before plotting",
- Toast.LENGTH_SHORT).show();
- } else if (!plotReady) {
- Toast.makeText(AccelerometerFragment.this.getActivity(), "Plot data not ready yet, please wait a few more seconds",
- Toast.LENGTH_SHORT).show();
- } else if (accelHistoryPlot != null) {
- accelHistoryPlot.redraw();
- }
+ final FragmentManager fm = getActivity().getSupportFragmentManager();
+ final AccelerometerSettings dialog= new AccelerometerSettings();
+
+ dialog.setConfigEditor(new Configuration(), new ConfigEditor());
+ dialog.show(fm, "resistance_graph_fragment");
+ }
+ });
+ ((Button) view.findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final FragmentManager fm = getActivity().getSupportFragmentManager();
+ final DataPlotFragment dialog= new DataPlotFragment();
+
+ dataSampleToGs();
+
+ dialog.addDataSeries("X Axis", processedData.xData());
+ dialog.addDataSeries("Y Axis", processedData.yData());
+ dialog.addDataSeries("Z Axis", processedData.zData());
+ dialog.show(fm, "resistance_graph_fragment");
}
});
((Button) view.findViewById(R.id.button3)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_SEND);
+ Intent intent= new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
- intent.putExtra(Intent.EXTRA_SUBJECT, "subject here");
- intent.putExtra(Intent.EXTRA_TEXT, "body text");
- File file = AccelerometerFragment.this.getActivity().getFileStreamPath(FILENAME);
+ intent.putExtra(Intent.EXTRA_SUBJECT, "Logged Accelerometer Data");
- if (!file.exists()) {
- Toast.makeText(AccelerometerFragment.this.getActivity(), "Record data before emailing",
- Toast.LENGTH_SHORT).show();
- } else if (recording) {
- Toast.makeText(AccelerometerFragment.this.getActivity(), "Stop recording before emailing the data",
- Toast.LENGTH_SHORT).show();
- } else {
- Uri uri = Uri.fromFile(file);
- intent.putExtra(Intent.EXTRA_STREAM, uri);
- startActivity(Intent.createChooser(intent, "Send email..."));
- }
+ File file= getActivity().getFileStreamPath(dataFilename);
+ Uri uri= FileProvider.getUriForFile(getActivity(),
+ "com.mbientlab.metawear.app.fileprovider", file);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ startActivity(Intent.createChooser(intent, "Send email..."));
}
});
}
+
+ private void dataSampleToGs() {
+ if (processedData != null) return;
+
+ final Collection convertedX= new ArrayList<>(),
+ convertedY= new ArrayList<>(), convertedZ= new ArrayList<>();
+ byte[] config= samplingConfig.getBytes();
+
+ dataFilename= String.format(Locale.US, "metawear_accelerometer_data-%s-%s.csv",
+ FullScaleRange.values()[dataRange].toString(),
+ OutputDataRate.values()[samplingRate].toString());
+ try {
+ FileOutputStream fos= getActivity().openFileOutput(dataFilename, Context.MODE_PRIVATE);
+ fos.write(CSV_HEADER.getBytes());
+
+ double index= 0;
+ for(AxisData data: polledData) {
+ float xAccel= BytesInterpreter.bytesToGs(config, data.data[0]),
+ yAccel= BytesInterpreter.bytesToGs(config, data.data[1]),
+ zAccel= BytesInterpreter.bytesToGs(config, data.data[2]);
+
+ convertedX.add(new GraphViewData(index, xAccel));
+ convertedY.add(new GraphViewData(index, yAccel));
+ convertedZ.add(new GraphViewData(index, zAccel));
+
+ fos.write(String.format(Locale.US, "%.3f,%.3f,%.3f,%.3f%n", data.tick / 1000.0,
+ xAccel, yAccel, zAccel).getBytes());
+
+ index++;
+ }
+
+ fos.close();
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+ processedData= new ProcessedAxisData() {
+ @Override
+ public Collection xData() {
+ return convertedX;
+ }
+
+ @Override
+ public Collection yData() {
+ return convertedY;
+ }
+
+ @Override
+ public Collection zData() {
+ return convertedZ;
+ }
+ };
+ }
+
+ public class ConfigEditor {
+ public ConfigEditor modifyTapType(int newIndex) {
+ AccelerometerFragment.this.tapType= newIndex;
+ return this;
+ }
+ public ConfigEditor modifyTapAxis(int newIndex) {
+ AccelerometerFragment.this.tapAxis= newIndex;
+ return this;
+ }
+ public ConfigEditor modifyShakeAxis(int newIndex) {
+ AccelerometerFragment.this.shakeAxis= newIndex;
+ return this;
+ }
+ public ConfigEditor modifyMovementType(int newIndex) {
+ AccelerometerFragment.this.ffMovement= newIndex == 0;
+ return this;
+ }
+ public ConfigEditor modifyDataRange(int newIndex) {
+ AccelerometerFragment.this.dataRange= newIndex;
+ return this;
+ }
+ public ConfigEditor modifySamplingRate(int newIndex) {
+ AccelerometerFragment.this.samplingRate= newIndex;
+ return this;
+ }
+ };
+
+ public class Configuration {
+ public int tapTypePos() { return tapType; }
+ public int tapAxisPos() { return tapAxis; }
+ public int movementPos() { return ffMovement ? 0 : 1; }
+ public int shakeAxisPos() { return shakeAxis; }
+ public int fsrPos() { return dataRange; }
+ public int odrPos() { return samplingRate; }
+ }
+
+ private int tapType= 0, tapAxis= 2, shakeAxis= 0, dataRange= 2, samplingRate= 3;
+ private boolean ffMovement= true;
+
+ private SamplingConfig samplingConfig;
}
diff --git a/src/com/mbientlab/metawear/app/DeviceInfoFragment.java b/src/com/mbientlab/metawear/app/DeviceInfoFragment.java
index 58f7a8b..6160a31 100644
--- a/src/com/mbientlab/metawear/app/DeviceInfoFragment.java
+++ b/src/com/mbientlab/metawear/app/DeviceInfoFragment.java
@@ -39,6 +39,7 @@
import com.mbientlab.metawear.api.MetaWearController.DeviceCallbacks;
import com.mbientlab.metawear.api.GATT.GATTCharacteristic;
import com.mbientlab.metawear.api.MetaWearController.ModuleCallbacks;
+import com.mbientlab.metawear.api.characteristic.Battery;
import com.mbientlab.metawear.api.characteristic.DeviceInformation;
import com.mbientlab.metawear.api.controller.Debug;
import com.mbientlab.metawear.api.controller.MechanicalSwitch;
@@ -91,7 +92,11 @@ public void connected() {
@Override
public void receivedGATTCharacteristic(
GATTCharacteristic characteristic, byte[] data) {
- values.put(characteristic, new String(data));
+ if (characteristic == Battery.BATTERY_LEVEL) {
+ values.put(characteristic, String.format(Locale.US, "%s", data[0]));
+ } else {
+ values.put(characteristic, new String(data));
+ }
final Integer viewId= views.get(characteristic);
if (viewId != null && isVisible()) {
((TextView) getView().findViewById(viewId)).setText(values.get(characteristic));
@@ -129,6 +134,7 @@ public void receivedTemperature(float degrees) {
views.put(DeviceInformation.SERIAL_NUMBER, R.id.serial_number);
views.put(DeviceInformation.FIRMWARE_VERSION, R.id.firmware_version);
views.put(DeviceInformation.HARDWARE_VERSION, R.id.hardware_version);
+ views.put(Battery.BATTERY_LEVEL, R.id.battery_level);
}
@Override
@@ -157,7 +163,7 @@ public void onClick(View v) {
}
});
- ((Button) view.findViewById(R.id.button1)).setOnClickListener(new Button.OnClickListener() {
+ ((TextView) view.findViewById(R.id.temperature_action)).setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
tempController.readTemperature();
@@ -169,6 +175,12 @@ public void onClick(View v) {
debugController.resetDevice();
}
});
+ ((TextView) view.findViewById(R.id.textView1)).setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mwController.readBatteryLevel();
+ }
+ });
}
@Override
diff --git a/src/com/mbientlab/metawear/app/popup/AccelerometerSettings.java b/src/com/mbientlab/metawear/app/popup/AccelerometerSettings.java
new file mode 100644
index 0000000..6558817
--- /dev/null
+++ b/src/com/mbientlab/metawear/app/popup/AccelerometerSettings.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2014 MbientLab Inc. All rights reserved.
+ *
+ * IMPORTANT: Your use of this Software is limited to those specific rights
+ * granted under the terms of a software license agreement between the user who
+ * downloaded the software, his/her employer (which must be your employer) and
+ * MbientLab Inc, (the "License"). You may not use this Software unless you
+ * agree to abide by the terms of the License which can be found at
+ * www.mbientlab.com/terms . The License limits your use, and you acknowledge,
+ * that the Software may not be modified, copied or distributed and can be used
+ * solely and exclusively in conjunction with a MbientLab Inc, product. Other
+ * than for the foregoing purpose, you may not use, reproduce, copy, prepare
+ * derivative works of, modify, distribute, perform, display or sell this
+ * Software and/or its documentation for any purpose.
+ *
+ * YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
+ * PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
+ * NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
+ * MBIENTLAB OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE,
+ * STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE
+ * THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED
+ * TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST
+ * PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY,
+ * SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY
+ * DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
+ *
+ * Should you have any questions regarding your right to use this Software,
+ * contact MbientLab Inc, at www.mbientlab.com.
+ */
+package com.mbientlab.metawear.app.popup;
+
+import com.mbientlab.metawear.api.controller.Accelerometer.Axis;
+import com.mbientlab.metawear.api.controller.Accelerometer.SamplingConfig.FullScaleRange;
+import com.mbientlab.metawear.api.controller.Accelerometer.SamplingConfig.OutputDataRate;
+import com.mbientlab.metawear.api.controller.Accelerometer.TapType;
+import com.mbientlab.metawear.app.AccelerometerFragment;
+import com.mbientlab.metawear.app.R;
+
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+
+/**
+ * @author etsai
+ *
+ */
+public class AccelerometerSettings extends DialogFragment {
+
+ @Override
+ public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_accelerometer_settings, container);
+ }
+
+ @Override
+ public void onViewCreated (View view, Bundle savedInstanceState) {
+ getDialog().setTitle("Accelerometer Settings");
+
+ Spinner spinnerObj;
+
+ spinnerObj= (Spinner) view.findViewById(R.id.spinner1);
+ spinnerObj.setAdapter(new ArrayAdapter(getActivity(),
+ R.layout.command_row, R.id.command_name, TapType.values()));
+ spinnerObj.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view,
+ int position, long id) {
+ editor.modifyTapType(position);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { }
+ });
+ spinnerObj.setSelection(config.tapTypePos());
+
+ spinnerObj= (Spinner) view.findViewById(R.id.spinner2);
+ spinnerObj.setAdapter(new ArrayAdapter(getActivity(),
+ R.layout.command_row, R.id.command_name, Axis.values()));
+ spinnerObj.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view,
+ int position, long id) {
+ editor.modifyTapAxis(position);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { }
+ });
+ spinnerObj.setSelection(config.tapAxisPos());
+
+ spinnerObj= (Spinner) view.findViewById(R.id.spinner3);
+ spinnerObj.setAdapter(new ArrayAdapter(getActivity(),
+ R.layout.command_row, R.id.command_name, Axis.values()));
+ spinnerObj.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view,
+ int position, long id) {
+ editor.modifyShakeAxis(position);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { }
+ });
+ spinnerObj.setSelection(config.shakeAxisPos());
+
+ spinnerObj= (Spinner) view.findViewById(R.id.spinner4);
+ spinnerObj.setAdapter(new ArrayAdapter(getActivity(),
+ R.layout.command_row, R.id.command_name, FullScaleRange.values()));
+ spinnerObj.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view,
+ int position, long id) {
+ editor.modifyDataRange(position);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { }
+ });
+ spinnerObj.setSelection(config.fsrPos());
+
+ spinnerObj= (Spinner) view.findViewById(R.id.spinner5);
+ spinnerObj.setAdapter(new ArrayAdapter(getActivity(),
+ R.layout.command_row, R.id.command_name, OutputDataRate.values()));
+ spinnerObj.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view,
+ int position, long id) {
+ editor.modifySamplingRate(position);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { }
+ });
+ spinnerObj.setSelection(config.odrPos());
+
+ spinnerObj= (Spinner) view.findViewById(R.id.spinner6);
+ spinnerObj.setAdapter(new ArrayAdapter(getActivity(),
+ R.layout.command_row, R.id.command_name, new String[] {"Free Fall", "Motion"}));
+ spinnerObj.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view,
+ int position, long id) {
+ editor.modifyMovementType(position);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { }
+ });
+ spinnerObj.setSelection(config.movementPos());
+ }
+
+ private AccelerometerFragment.ConfigEditor editor;
+ private AccelerometerFragment.Configuration config;
+ public void setConfigEditor(AccelerometerFragment.Configuration config,
+ AccelerometerFragment.ConfigEditor editor) {
+ this.editor= editor;
+ this.config= config;
+ }
+}
diff --git a/src/com/mbientlab/metawear/app/popup/DataPlotFragment.java b/src/com/mbientlab/metawear/app/popup/DataPlotFragment.java
new file mode 100644
index 0000000..44a8d3b
--- /dev/null
+++ b/src/com/mbientlab/metawear/app/popup/DataPlotFragment.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014 MbientLab Inc. All rights reserved.
+ *
+ * IMPORTANT: Your use of this Software is limited to those specific rights
+ * granted under the terms of a software license agreement between the user who
+ * downloaded the software, his/her employer (which must be your employer) and
+ * MbientLab Inc, (the "License"). You may not use this Software unless you
+ * agree to abide by the terms of the License which can be found at
+ * www.mbientlab.com/terms . The License limits your use, and you acknowledge,
+ * that the Software may not be modified, copied or distributed and can be used
+ * solely and exclusively in conjunction with a MbientLab Inc, product. Other
+ * than for the foregoing purpose, you may not use, reproduce, copy, prepare
+ * derivative works of, modify, distribute, perform, display or sell this
+ * Software and/or its documentation for any purpose.
+ *
+ * YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
+ * PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
+ * NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
+ * MBIENTLAB OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE,
+ * STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE
+ * THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED
+ * TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST
+ * PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY,
+ * SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY
+ * DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
+ *
+ * Should you have any questions regarding your right to use this Software,
+ * contact MbientLab Inc, at www.mbientlab.com.
+ */
+package com.mbientlab.metawear.app.popup;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+import com.jjoe64.graphview.GraphView;
+import com.jjoe64.graphview.GraphViewDataInterface;
+import com.jjoe64.graphview.GraphViewSeries;
+import com.jjoe64.graphview.LineGraphView;
+import com.jjoe64.graphview.GraphViewSeries.GraphViewSeriesStyle;
+import com.mbientlab.metawear.app.R;
+
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+/**
+ * @author etsai
+ *
+ */
+public class DataPlotFragment extends DialogFragment {
+ private final int[] chartColors= new int[] { Color.rgb(255, 0, 0),
+ Color.rgb(0, 255, 0), Color.rgb(0, 0, 255)};
+ private final HashMap dataSeries= new HashMap<>();
+
+ @Override
+ public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_data_plot, container);
+ }
+
+ //
+
+ @Override
+ public void onViewCreated (View view, Bundle savedInstanceState) {
+
+ GraphView graph= new LineGraphView(getActivity(), "");
+ graph.setShowHorizontalLabels(false);
+ graph.setScrollable(true);
+ graph.setScalable(true);
+ graph.setShowLegend(true);
+
+ int colorIndex= 0;
+ for(Entry data: dataSeries.entrySet()) {
+ graph.addSeries(new GraphViewSeries(data.getKey(),
+ new GraphViewSeriesStyle(chartColors[colorIndex], 5),
+ data.getValue()));
+ colorIndex++;
+ }
+ ((LinearLayout) view.findViewById(R.id.data_plot)).addView(graph);
+ }
+
+ public void addDataSeries(String legendTitle, final Collection graphData) {
+ GraphViewDataInterface[] graphDataAsArray= new GraphViewDataInterface[graphData.size()];
+ graphData.toArray(graphDataAsArray);
+
+ dataSeries.put(legendTitle, graphDataAsArray);
+ }
+}