initial sample pulse ox app
diff --git a/res/layout/activity_ara_plox.xml b/res/layout/activity_ara_plox.xml
index 138579e..66778d3 100644
--- a/res/layout/activity_ara_plox.xml
+++ b/res/layout/activity_ara_plox.xml
@@ -1,7 +1,24 @@
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="com.google.araplox.AraPloxActivity"
- tools:ignore="MergeRootFrame" />
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout android:id="@+id/chart"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="2"/>
+
+ <TextView
+ android:id="@+id/textView"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:layout_weight="1"
+ android:background="#FFFFFF"
+ android:fontFamily="sans-serif"
+ android:textSize="64sp"
+ android:text="@string/hello_world" />
+
+</LinearLayout>
diff --git a/res/menu/ara_plox.xml b/res/menu/ara_plox.xml
index cc99be6..44d8766 100644
--- a/res/menu/ara_plox.xml
+++ b/res/menu/ara_plox.xml
@@ -2,11 +2,4 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.google.araplox.AraPloxActivity" >
-
- <item
- android:id="@+id/action_settings"
- android:orderInCategory="100"
- android:title="@string/action_settings"
- app:showAsAction="never"/>
-
</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6bc5510..d4f6f28 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
-
<string name="app_name">AraPloxIO</string>
<string name="hello_world">Hello world!</string>
- <string name="action_settings">Settings</string>
-
</resources>
diff --git a/src/com/google/araplox/AFE4400Thread.java b/src/com/google/araplox/AFE4400Thread.java
new file mode 100644
index 0000000..7bffe32
--- /dev/null
+++ b/src/com/google/araplox/AFE4400Thread.java
@@ -0,0 +1,63 @@
+package com.google.araplox;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public class AFE4400Thread extends Thread {
+ private static final String TAG = "AFE4400Thread";
+
+ private boolean stopped = false;
+ private DataInputStream dataInputStream;
+
+ Context mContext;
+ Handler mHandler;
+
+ public AFE4400Thread(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+
+ try {
+ dataInputStream = new DataInputStream(mContext.getAssets().open("plox.dat"));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+ Log.d(TAG, "AFE4400 thread started");
+ int x = 0;
+ while (!stopped) {
+ Message msg;
+ try {
+ msg = mHandler.obtainMessage(0, x++, dataInputStream.readInt());
+ dataInputStream.readInt();
+ msg.sendToTarget();
+ } catch (IOException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ break;
+ }
+
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void requestStop() {
+ stopped = true;
+ }
+
+ public boolean isStopped() {
+ return this.stopped;
+ }
+}
diff --git a/src/com/google/araplox/AraPloxActivity.java b/src/com/google/araplox/AraPloxActivity.java
index 4a35693..e323b4b 100644
--- a/src/com/google/araplox/AraPloxActivity.java
+++ b/src/com/google/araplox/AraPloxActivity.java
@@ -1,64 +1,166 @@
package com.google.araplox;
-import android.support.v7.app.ActionBarActivity;
-import android.support.v7.app.ActionBar;
-import android.support.v4.app.Fragment;
+import org.achartengine.ChartFactory;
+import org.achartengine.GraphicalView;
+import org.achartengine.chart.PointStyle;
+import org.achartengine.model.XYMultipleSeriesDataset;
+import org.achartengine.model.XYSeries;
+import org.achartengine.renderer.XYMultipleSeriesRenderer;
+import org.achartengine.renderer.XYSeriesRenderer;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.Paint.Align;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.os.Build;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.Window;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.LinearLayout;
+import android.widget.TextView;
-public class AraPloxActivity extends ActionBarActivity {
+import com.google.araplox.AFE4400Thread;
- @Override
+public class AraPloxActivity extends Activity {
+ private static final String TAG = "AraPlox/Activity";
+
+ private static TextView bpmTextView;
+ private static Handler mHandler = null;
+ private static AFE4400Thread afe4400Thread = null;
+ private GraphicalView chart_view = null;
+
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Log.d(TAG, "onCreate()");
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_ara_plox);
+ bpmTextView = (TextView)findViewById(R.id.textView);
- if (savedInstanceState == null) {
- getSupportFragmentManager().beginTransaction()
- .add(R.id.container, new PlaceholderFragment()).commit();
+ mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ handleAFE4400Message(msg);
+ }
+ };
+ }
+
+ private String[] fakeBPMs = new String[] {
+ "72", "72", "74", "75", "73", "73", "70", "70", "71", "73", "76", "78"
+ };
+ private int fakeBPMCount = 0;
+ private void handleAFE4400Message(Message msg) {
+ // Log.d(TAG, "Message received: arg1: " + msg.arg1 + " arg2: " + msg.arg2);
+ double x = msg.arg1;
+ double y = msg.arg2;
+
+ xySeries.add(x, y);
+ // Scroll continuously after ~150 points
+ if (x > 150) {
+ xySeries.remove(0);
+ }
+
+ // Autoscale
+ double maxX = xySeries.getMaxX();
+ double minX = xySeries.getMinX();
+ double maxY = xySeries.getMaxY();
+ double minY = xySeries.getMinY();
+ renderer.setXAxisMax(maxX);
+ renderer.setXAxisMin(minX);
+ renderer.setYAxisMax(maxY);
+ renderer.setYAxisMin(minY);
+
+ chart_view.repaint();
+
+ // fake pulse rate...
+ if (x % 10 == 0) {
+ bpmTextView.setText(fakeBPMs[fakeBPMCount++] + " bpm");
+ if (fakeBPMCount == fakeBPMs.length) {
+ fakeBPMCount = 0;
+ }
}
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ private XYMultipleSeriesRenderer renderer;
+ private XYMultipleSeriesDataset dataSet;
+ private XYSeries xySeries;
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.ara_plox, menu);
- return true;
- }
+ private void makeChart() {
+ dataSet = new XYMultipleSeriesDataset();
+ xySeries = new XYSeries("");
+ dataSet.addSeries(xySeries);
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- if (id == R.id.action_settings) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
+ int[] colors = new int[] {Color.RED};
+ PointStyle[] styles = new PointStyle[] {PointStyle.CIRCLE};
- /**
- * A placeholder fragment containing a simple view.
- */
- public static class PlaceholderFragment extends Fragment {
-
- public PlaceholderFragment() {
+ renderer = new XYMultipleSeriesRenderer();
+
+ int length = colors.length;
+ for (int i = 0; i < length; i++) {
+ XYSeriesRenderer r = new XYSeriesRenderer();
+ r.setFillPoints(true);
+ r.setLineWidth(10.0f);
+ r.setPointStrokeWidth(1);
+ r.setColor(colors[i]);
+ r.setPointStyle(styles[i]);
+ renderer.addSeriesRenderer(r);
}
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View rootView = inflater.inflate(R.layout.fragment_ara_plox,
- container, false);
- return rootView;
+ renderer.setChartTitleTextSize(20);
+ renderer.setLabelsTextSize(15);
+ renderer.setLegendTextSize(15);
+ renderer.setPointSize(5f);
+ renderer.setMargins(new int[] { 100, 100, 100, 100 });
+ renderer.setXAxisMin(0);
+ renderer.setXAxisMax(10);
+ renderer.setYAxisMin(0);
+ renderer.setYAxisMax(100);
+ renderer.setAxesColor(Color.BLACK);
+ renderer.setLabelsColor(Color.BLACK);
+ renderer.setShowLegend(false);
+ renderer.setXLabels(10);
+ renderer.setYLabels(0);
+ renderer.setShowGrid(false);
+ renderer.setXLabelsAlign(Align.CENTER);
+ renderer.setApplyBackgroundColor(true);
+ renderer.setBackgroundColor(Color.WHITE);
+ renderer.setMarginsColor(Color.WHITE);
+ if (chart_view == null) {
+ LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
+ chart_view = ChartFactory.getCubeLineChartView(this, dataSet, renderer, 1.0f);
+ layout.addView(chart_view, new LayoutParams(LayoutParams.FILL_PARENT,
+ LayoutParams.FILL_PARENT));
+ chart_view.repaint();
}
}
+
+ protected void onResume() {
+ super.onResume();
+ Log.d(TAG, "onResume()");
+ if (afe4400Thread == null) {
+ afe4400Thread = new AFE4400Thread(getApplicationContext(), mHandler);
+ afe4400Thread.start();
+ }
+ makeChart();
+ }
+
+ protected void onPause() {
+ super.onPause();
+ Log.d(TAG, "onPause()");
+ if (afe4400Thread != null) {
+ afe4400Thread.requestStop();
+ afe4400Thread = null;
+ }
+
+ }
+
+ protected void onStop() {
+ super.onStop();
+ Log.d(TAG, "onStop()");
+ if (chart_view != null) {
+ LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
+ layout.removeView(chart_view);
+ chart_view = null;
+ }
+ }
}