diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fb0b4c0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+build
+.gradle
+.idea
+app/build
+
diff --git a/Android_Pebble_SD.iml b/Android_Pebble_SD.iml
index 2e54f2b..f983017 100644
--- a/Android_Pebble_SD.iml
+++ b/Android_Pebble_SD.iml
@@ -13,7 +13,7 @@
-
+
\ No newline at end of file
diff --git a/app/app.iml b/app/app.iml
index 09b3522..da9f13b 100644
--- a/app/app.iml
+++ b/app/app.iml
@@ -1,5 +1,5 @@
-
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 05ee419..425d13c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
+ android:versionCode="17"
+ android:versionName="2.0a">
diff --git a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
index 68d9d4e..05b9d49 100644
--- a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
@@ -25,9 +25,7 @@
package uk.org.openseizuredetector;
-import android.app.ActionBar;
import android.app.Activity;
-import android.app.IntentService;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
@@ -35,22 +33,15 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageInfo;
-import android.preference.Preference;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
-import android.content.Context;
import android.graphics.Color;
-import android.media.AudioManager;
-import android.media.ToneGenerator;
import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
-import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
@@ -58,7 +49,6 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
-import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Button;
import java.lang.reflect.Field;
@@ -69,28 +59,12 @@ import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.conn.util.InetAddressUtils;
-import java.lang.CharSequence;
-import android.util.AttributeSet;
//MPAndroidChart
import com.github.mikephil.charting.charts.LineChart;
-import com.github.mikephil.charting.components.Legend;
-import com.github.mikephil.charting.components.Legend.LegendForm;
-import com.github.mikephil.charting.components.LimitLine;
-import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition;
-import com.github.mikephil.charting.components.XAxis;
-import com.github.mikephil.charting.components.YAxis;
-import com.github.mikephil.charting.data.DataSet;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
-import com.github.mikephil.charting.data.filter.Approximator;
-import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType;
-import com.github.mikephil.charting.listener.OnChartGestureListener;
-import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
-import com.github.mikephil.charting.utils.Highlight;
-
-import uk.org.openseizuredetector.SdServer;
public class MainActivity extends Activity
{
@@ -466,31 +440,31 @@ public class MainActivity extends Activity
try {
if (mBound) {
tv = (TextView) findViewById(R.id.alarmTv);
- if ((mSdServer.sdData.alarmState==0)
- && !mSdServer.sdData.alarmStanding
- && !mSdServer.sdData.fallAlarmStanding) {
+ if ((mSdServer.mSdData.alarmState==0)
+ && !mSdServer.mSdData.alarmStanding
+ && !mSdServer.mSdData.fallAlarmStanding) {
tv.setText("OK");
tv.setBackgroundColor(okColour);
}
- if ((mSdServer.sdData.alarmState==1)
- && !mSdServer.sdData.alarmStanding
- && !mSdServer.sdData.fallAlarmStanding) {
+ if ((mSdServer.mSdData.alarmState==1)
+ && !mSdServer.mSdData.alarmStanding
+ && !mSdServer.mSdData.fallAlarmStanding) {
tv.setText("WARNING");
tv.setBackgroundColor(warnColour);
}
- if (mSdServer.sdData.alarmStanding) {
+ if (mSdServer.mSdData.alarmStanding) {
tv.setText("**ALARM**");
tv.setBackgroundColor(alarmColour);
}
- if (mSdServer.sdData.fallAlarmStanding) {
+ if (mSdServer.mSdData.fallAlarmStanding) {
tv.setText("**FALL**");
tv.setBackgroundColor(alarmColour);
}
tv = (TextView) findViewById(R.id.pebTimeTv);
- tv.setText(mSdServer.mPebbleStatusTime.format("%H:%M:%S"));
+ tv.setText(mSdServer.mSdData.dataTime.format("%H:%M:%S"));
// Pebble Connected Phrase
tv = (TextView) findViewById(R.id.pebbleTv);
- if (mSdServer.sdData.pebbleConnected) {
+ if (mSdServer.mSdData.pebbleConnected) {
tv.setText("Pebble Watch Connected OK");
tv.setBackgroundColor(okColour);
} else {
@@ -498,7 +472,7 @@ public class MainActivity extends Activity
tv.setBackgroundColor(alarmColour);
}
tv = (TextView) findViewById(R.id.appTv);
- if (mSdServer.sdData.pebbleAppRunning) {
+ if (mSdServer.mSdData.pebbleAppRunning) {
tv.setText("Pebble App OK");
tv.setBackgroundColor(okColour);
} else {
@@ -506,19 +480,19 @@ public class MainActivity extends Activity
tv.setBackgroundColor(alarmColour);
}
tv = (TextView) findViewById(R.id.battTv);
- tv.setText("Pebble Battery = "+String.valueOf(mSdServer.sdData.batteryPc)+"%");
- if (mSdServer.sdData.batteryPc<=20)
+ tv.setText("Pebble Battery = "+String.valueOf(mSdServer.mSdData.batteryPc)+"%");
+ if (mSdServer.mSdData.batteryPc<=20)
tv.setBackgroundColor(alarmColour);
- if (mSdServer.sdData.batteryPc>20)
+ if (mSdServer.mSdData.batteryPc>20)
tv.setBackgroundColor(warnColour);
- if (mSdServer.sdData.batteryPc>=40)
+ if (mSdServer.mSdData.batteryPc>=40)
tv.setBackgroundColor(okColour);
tv = (TextView) findViewById(R.id.debugTv);
String specStr = "";
for (int i=0;i<10;i++)
specStr = specStr
- + mSdServer.sdData.simpleSpec[i]
+ + mSdServer.mSdData.simpleSpec[i]
+ ", ";
tv.setText("Spec = "+specStr);
}
@@ -544,7 +518,7 @@ public class MainActivity extends Activity
ArrayList yVals = new ArrayList();
for (int i = 0; i < 10; i++) {
if (mSdServer!=null)
- yVals.add(new Entry(mSdServer.sdData.simpleSpec[i], i));
+ yVals.add(new Entry(mSdServer.mSdData.simpleSpec[i], i));
else
yVals.add(new Entry(i, i));
}
diff --git a/app/src/main/java/uk/org/openseizuredetector/SdData.java b/app/src/main/java/uk/org/openseizuredetector/SdData.java
index da00bf8..bc7e5a8 100644
--- a/app/src/main/java/uk/org/openseizuredetector/SdData.java
+++ b/app/src/main/java/uk/org/openseizuredetector/SdData.java
@@ -125,7 +125,7 @@ public class SdData implements Parcelable {
jsonObj.put("dataTimeStr","00000000T000000");
jsonObj.put("dataTime","00-00-00 00:00:00");
}
- Log.v(TAG,"sdData.dataTime = "+dataTime);
+ Log.v(TAG,"mSdData.dataTime = "+dataTime);
jsonObj.put("maxVal",maxVal);
jsonObj.put("maxFreq",maxFreq);
jsonObj.put("specPower",specPower);
diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java
new file mode 100644
index 0000000..86adaf6
--- /dev/null
+++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java
@@ -0,0 +1,74 @@
+/*
+ Android_Pebble_sd - Android alarm client for openseizuredetector..
+
+ See http://openseizuredetector.org for more information.
+
+ Copyright Graham Jones, 2015.
+
+ This file is part of pebble_sd.
+
+ Android_Pebble_sd is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Android_Pebble_sd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Android_pebble_sd. If not, see .
+
+*/
+package uk.org.openseizuredetector;
+
+import android.content.Context;
+import android.util.Log;
+
+interface SdDataReceiver {
+ public void onSdDataReceived(SdData sdData);
+ public void onSdDataFault(SdData sdData);
+}
+
+/**
+ * Abstract class for a seizure detector data source. Subclasses include a pebble smart watch data source and a
+ * network data source.
+ */
+public abstract class SdDataSource {
+ public SdData mSdData;
+ protected Context mContext;
+ protected SdDataReceiver mSdDataReceiver;
+ private String TAG = "SdDataSource";
+
+ public SdDataSource(Context context, SdDataReceiver sdDataReceiver) {
+ Log.v(TAG, "SdDataSource() Constructor");
+ mContext = context;
+ mSdDataReceiver = sdDataReceiver;
+ mSdData = new SdData();
+ }
+
+ /**
+ * Returns the SdData object stored by this class.
+ * @return
+ */
+ public SdData getSdData() {
+ return mSdData;
+ }
+
+ /**
+ * Start the datasource updating - initialises from sharedpreferences first to
+ * make sure any changes to preferences are taken into account.
+ */
+ public void start() {
+ Log.v(TAG, "start()");
+ }
+
+ /**
+ * Stop the datasource from updating
+ */
+ public void stop() {
+ Log.v(TAG, "stop()");
+ }
+
+}
diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSourcePebble.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSourcePebble.java
new file mode 100644
index 0000000..6c90f8e
--- /dev/null
+++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSourcePebble.java
@@ -0,0 +1,441 @@
+/*
+ Android_Pebble_sd - Android alarm client for openseizuredetector..
+
+ See http://openseizuredetector.org for more information.
+
+ Copyright Graham Jones, 2015.
+
+ This file is part of pebble_sd.
+
+ Android_Pebble_sd is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Android_Pebble_sd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Android_pebble_sd. If not, see .
+
+*/
+package uk.org.openseizuredetector;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Handler;
+import android.os.Looper;
+import android.preference.PreferenceManager;
+import android.text.format.Time;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.getpebble.android.kit.Constants;
+import com.getpebble.android.kit.PebbleKit;
+import com.getpebble.android.kit.util.PebbleDictionary;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.UUID;
+
+
+
+/**
+ * Abstract class for a seizure detector data source. Subclasses include a pebble smart watch data source and a
+ * network data source.
+ */
+public class SdDataSourcePebble extends SdDataSource {
+ private Timer mSettingsTimer;
+ private Timer mStatusTimer;
+ private Time mPebbleStatusTime;
+ private boolean mPebbleAppRunningCheck = false;
+ private int mAppRestartTimeout = 10; // Timeout before re-starting watch app (sec).
+ //private Looper mServiceLooper;
+ private int mFaultTimerPeriod = 30; // Fault Timer Period in sec
+ private PebbleKit.PebbleDataReceiver msgDataHandler = null;
+
+
+ private String TAG = "SdDataSourcePebble";
+
+ private UUID SD_UUID = UUID.fromString("03930f26-377a-4a3d-aa3e-f3b19e421c9d");
+ private int NSAMP = 512; // Number of samples in fft input dataset.
+
+ private int KEY_DATA_TYPE = 1;
+ private int KEY_ALARMSTATE = 2;
+ private int KEY_MAXVAL = 3;
+ private int KEY_MAXFREQ = 4;
+ private int KEY_SPECPOWER = 5;
+ private int KEY_SETTINGS = 6;
+ private int KEY_ALARM_FREQ_MIN = 7;
+ private int KEY_ALARM_FREQ_MAX = 8;
+ private int KEY_WARN_TIME = 9;
+ private int KEY_ALARM_TIME = 10;
+ private int KEY_ALARM_THRESH = 11;
+ private int KEY_POS_MIN = 12; // position of first data point in array
+ private int KEY_POS_MAX = 13; // position of last data point in array.
+ private int KEY_SPEC_DATA = 14; // Spectrum data
+ private int KEY_ROIPOWER = 15;
+ private int KEY_NMIN = 16;
+ private int KEY_NMAX = 17;
+ private int KEY_ALARM_RATIO_THRESH = 18;
+ private int KEY_BATTERY_PC = 19;
+ //private int KEY_SET_SETTINGS =20; // Phone is asking us to update watch app settings.
+ private int KEY_FALL_THRESH_MIN = 21;
+ private int KEY_FALL_THRESH_MAX = 22;
+ private int KEY_FALL_WINDOW = 23;
+ private int KEY_FALL_ACTIVE = 24;
+
+ // Values of the KEY_DATA_TYPE entry in a message
+ private int DATA_TYPE_RESULTS = 1; // Analysis Results
+ private int DATA_TYPE_SETTINGS = 2; // Settings
+ private int DATA_TYPE_SPEC = 3; // FFT Spectrum (or part of a spectrum)
+
+ public SdDataSourcePebble(Context context, SdDataReceiver sdDataReceiver) {
+ super(context,sdDataReceiver);
+ }
+
+
+ /**
+ * Start the datasource updating - initialises from sharedpreferences first to
+ * make sure any changes to preferences are taken into account.
+ */
+ public void start() {
+ Log.v(TAG, "start()");
+ updatePrefs();
+ startPebbleServer();
+ // Start timer to check status of pebble regularly.
+ mPebbleStatusTime = new Time(Time.getCurrentTimezone());
+ //getPebbleStatus();
+ if (mStatusTimer == null) {
+ Log.v(TAG, "onCreate(): starting status timer");
+ mStatusTimer = new Timer();
+ mStatusTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ getPebbleStatus();
+ }
+ }, 0, 1000);
+ } else {
+ Log.v(TAG, "onCreate(): status timer already running.");
+ }
+
+ // Start timer to retrieve pebble settings regularly.
+ getPebbleSdSettings();
+ if (mSettingsTimer == null) {
+ Log.v(TAG, "onCreate(): starting settings timer");
+ mSettingsTimer = new Timer();
+ mSettingsTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ getPebbleSdSettings();
+ }
+ }, 0, 1000 * 60);
+ } else {
+ Log.v(TAG, "onCreate(): settings timer already running.");
+ }
+
+
+ }
+
+ /**
+ * Stop the datasource from updating
+ */
+ public void stop() {
+ Log.v(TAG, "stop()");
+ try {
+ // Stop the status timer
+ if (mStatusTimer != null) {
+ Log.v(TAG, "onDestroy(): cancelling status timer");
+ mStatusTimer.cancel();
+ mStatusTimer.purge();
+ mStatusTimer = null;
+ }
+ // Stop the settings timer
+ if (mSettingsTimer != null) {
+ Log.v(TAG, "onDestroy(): cancelling settings timer");
+ mSettingsTimer.cancel();
+ mSettingsTimer.purge();
+ mSettingsTimer = null;
+ }
+ // Stop pebble message handler.
+ Log.v(TAG, "onDestroy(): stopping pebble server");
+ stopPebbleServer();
+
+ } catch (Exception e) {
+ Log.v(TAG, "Error in stop() - " + e.toString());
+ }
+
+
+ }
+
+ /**
+ * updatePrefs() - update basic settings from the SharedPreferences
+ * - defined in res/xml/SdDataSourcePebblePrefs.xml
+ */
+ public void updatePrefs() {
+ Log.v(TAG, "updatePrefs()");
+ SharedPreferences SP = PreferenceManager
+ .getDefaultSharedPreferences(mContext);
+ try {
+ // Parse the AppRestartTimeout period setting.
+ try {
+ String appRestartTimeoutStr = SP.getString("AppRestartTimeout", "10");
+ mAppRestartTimeout = Integer.parseInt(appRestartTimeoutStr);
+ Log.v(TAG, "updatePrefs() - mAppRestartTimeout = " + mAppRestartTimeout);
+ } catch (Exception ex) {
+ Log.v(TAG, "updatePrefs() - Problem with AppRestartTimeout preference!");
+ Toast toast = Toast.makeText(mContext, "Problem Parsing AppRestartTimeout Preference", Toast.LENGTH_SHORT);
+ toast.show();
+ }
+
+
+ // Parse the FaultTimer period setting.
+ try {
+ String faultTimerPeriodStr = SP.getString("FaultTimerPeriod", "30");
+ mFaultTimerPeriod = Integer.parseInt(faultTimerPeriodStr);
+ Log.v(TAG, "updatePrefs() - mFaultTimerPeriod = " + mFaultTimerPeriod);
+ } catch (Exception ex) {
+ Log.v(TAG, "updatePrefs() - Problem with FaultTimerPeriod preference!");
+ Toast toast = Toast.makeText(mContext, "Problem Parsing FaultTimerPeriod Preference", Toast.LENGTH_SHORT);
+ toast.show();
+ }
+
+
+ // Watch Settings
+ PebbleDictionary setDict = new PebbleDictionary();
+ short intVal;
+ String prefStr;
+ prefStr = SP.getString("AlarmFreqMin", "5");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() AlarmFreqMin = " + intVal);
+ setDict.addInt16(KEY_ALARM_FREQ_MIN, intVal);
+
+ prefStr = SP.getString("AlarmFreqMax", "10");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() AlarmFreqMax = " + intVal);
+ setDict.addUint16(KEY_ALARM_FREQ_MAX, (short) intVal);
+
+ prefStr = SP.getString("WarnTime", "5");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() WarnTime = " + intVal);
+ setDict.addUint16(KEY_WARN_TIME, (short) intVal);
+
+ prefStr = SP.getString("AlarmTime", "10");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() AlarmTime = " + intVal);
+ setDict.addUint16(KEY_ALARM_TIME, (short) intVal);
+
+ prefStr = SP.getString("AlarmThresh", "100");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() AlarmThresh = " + intVal);
+ setDict.addUint16(KEY_ALARM_THRESH, (short) intVal);
+
+ prefStr = SP.getString("AlarmRatioThresh", "30");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() AlarmRatioThresh = " + intVal);
+ setDict.addUint16(KEY_ALARM_RATIO_THRESH, (short) intVal);
+
+ boolean fallActiveBool = SP.getBoolean("FallActive", false);
+ Log.v(TAG, "updatePrefs() FallActive = " + fallActiveBool);
+ if (fallActiveBool)
+ setDict.addUint16(KEY_FALL_ACTIVE, (short) 1);
+ else
+ setDict.addUint16(KEY_FALL_ACTIVE, (short) 0);
+
+ prefStr = SP.getString("FallThreshMin", "200");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() FallThreshMin = " + intVal);
+ setDict.addUint16(KEY_FALL_THRESH_MIN, (short) intVal);
+
+ prefStr = SP.getString("FallThreshMax", "1200");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() FallThreshMax = " + intVal);
+ setDict.addUint16(KEY_FALL_THRESH_MAX, (short) intVal);
+
+ prefStr = SP.getString("FallWindow", "1500");
+ intVal = (short) Integer.parseInt(prefStr);
+ Log.v(TAG, "updatePrefs() FallWindow = " + intVal);
+ setDict.addUint16(KEY_FALL_WINDOW, (short) intVal);
+
+
+ // Send Watch Settings to Pebble
+ Log.v(TAG, "updatePrefs() - setDict = " + setDict.toJsonString());
+ PebbleKit.sendDataToPebble(mContext, SD_UUID, setDict);
+ } catch (Exception ex) {
+ Log.v(TAG, "updatePrefs() - Problem parsing preferences!");
+ Toast toast = Toast.makeText(mContext, "Problem Parsing Preferences - Something won't work - Please go back to Settings and correct it!", Toast.LENGTH_SHORT);
+ toast.show();
+ }
+ }
+
+
+ /**
+ * Set this server to receive pebble data by registering it as
+ * A PebbleDataReceiver
+ */
+ private void startPebbleServer() {
+ Log.v(TAG, "StartPebbleServer()");
+ final Handler handler = new Handler();
+ msgDataHandler = new PebbleKit.PebbleDataReceiver(SD_UUID) {
+ @Override
+ public void receiveData(final Context context,
+ final int transactionId,
+ final PebbleDictionary data) {
+ Log.v(TAG, "Received message from Pebble - data type="
+ + data.getUnsignedIntegerAsLong(KEY_DATA_TYPE));
+ // If we ha ve a message, the app must be running
+ mPebbleAppRunningCheck = true;
+ PebbleKit.sendAckToPebble(context, transactionId);
+ //Log.v(TAG,"Message is: "+data.toJsonString());
+ if (data.getUnsignedIntegerAsLong(KEY_DATA_TYPE)
+ == DATA_TYPE_RESULTS) {
+ Log.v(TAG, "DATA_TYPE = Results");
+ mSdData.dataTime.setToNow();
+ Log.v(TAG, "mSdData.dataTime=" + mSdData.dataTime);
+
+ mSdData.alarmState = data.getUnsignedIntegerAsLong(
+ KEY_ALARMSTATE);
+ mSdData.maxVal = data.getUnsignedIntegerAsLong(KEY_MAXVAL);
+ mSdData.maxFreq = data.getUnsignedIntegerAsLong(KEY_MAXFREQ);
+ mSdData.specPower = data.getUnsignedIntegerAsLong(KEY_SPECPOWER);
+ mSdData.roiPower = data.getUnsignedIntegerAsLong(KEY_ROIPOWER);
+ mSdData.alarmPhrase = "Unknown";
+ mSdDataReceiver.onSdDataReceived(mSdData);
+ }
+
+
+ // Read the data that has been sent, and convert it into
+ // an integer array.
+ byte[] byteArr = data.getBytes(KEY_SPEC_DATA);
+ if ((byteArr!=null) && (byteArr.length!=0)) {
+ IntBuffer intBuf = ByteBuffer.wrap(byteArr)
+ .order(ByteOrder.LITTLE_ENDIAN)
+ .asIntBuffer();
+ int[] intArray = new int[intBuf.remaining()];
+ intBuf.get(intArray);
+ for (int i = 0; i < intArray.length; i++) {
+ mSdData.simpleSpec[i] = intArray[i];
+ }
+ } else {
+ Log.v(TAG,"***** zero length spectrum received - error!!!!");
+ }
+
+
+ if (data.getUnsignedIntegerAsLong(KEY_DATA_TYPE)
+ == DATA_TYPE_SETTINGS) {
+ Log.v(TAG, "DATA_TYPE = Settings");
+ mSdData.alarmFreqMin = data.getUnsignedIntegerAsLong(KEY_ALARM_FREQ_MIN);
+ mSdData.alarmFreqMax = data.getUnsignedIntegerAsLong(KEY_ALARM_FREQ_MAX);
+ mSdData.nMin = data.getUnsignedIntegerAsLong(KEY_NMIN);
+ mSdData.nMax = data.getUnsignedIntegerAsLong(KEY_NMAX);
+ mSdData.warnTime = data.getUnsignedIntegerAsLong(KEY_WARN_TIME);
+ mSdData.alarmTime = data.getUnsignedIntegerAsLong(KEY_ALARM_TIME);
+ mSdData.alarmThresh = data.getUnsignedIntegerAsLong(KEY_ALARM_THRESH);
+ mSdData.alarmRatioThresh = data.getUnsignedIntegerAsLong(KEY_ALARM_RATIO_THRESH);
+ mSdData.batteryPc = data.getUnsignedIntegerAsLong(KEY_BATTERY_PC);
+ mSdData.haveSettings = true;
+ }
+ }
+ };
+ PebbleKit.registerReceivedDataHandler(mContext, msgDataHandler);
+ }
+
+ /**
+ * De-register this server from receiving pebble data
+ */
+ public void stopPebbleServer() {
+ Log.v(TAG, "stopPebbleServer(): Stopping Pebble Server");
+ Log.v(TAG, "stopPebbleServer(): msgDataHandler = " + msgDataHandler.toString());
+ try {
+ mContext.unregisterReceiver(msgDataHandler);
+ } catch (Exception e) {
+ Log.v(TAG, "stopPebbleServer() - error " + e.toString());
+ }
+ }
+
+ /**
+ * Attempt to start the pebble_sd watch app on the pebble watch.
+ */
+ public void startWatchApp() {
+ PebbleKit.startAppOnPebble(mContext, SD_UUID);
+
+ }
+
+ /**
+ * stop the pebble_sd watch app on the pebble watch.
+ */
+ public void stopWatchApp() {
+ PebbleKit.closeAppOnPebble(mContext, SD_UUID);
+ }
+
+
+ /**
+ * Request Pebble App to send us its latest settings.
+ * Will be received as a message by the receiveData handler
+ */
+ public void getPebbleSdSettings() {
+ Log.v(TAG, "getPebbleSdSettings() - requesting settings from pebble");
+ PebbleDictionary data = new PebbleDictionary();
+ data.addUint8(KEY_SETTINGS, (byte) 1);
+ PebbleKit.sendDataToPebble(
+ mContext,
+ SD_UUID,
+ data);
+ }
+
+ /**
+ * Checks the status of the connection to the pebble watch,
+ * and sets class variables for use by other functions.
+ * If the watch app is not running, it attempts to re-start it.
+ */
+ public void getPebbleStatus() {
+ Time tnow = new Time(Time.getCurrentTimezone());
+ long tdiff;
+ tnow.setToNow();
+ tdiff = (tnow.toMillis(false) - mPebbleStatusTime.toMillis(false));
+ // Check we are actually connected to the pebble.
+ mSdData.pebbleConnected = PebbleKit.isWatchConnected(mContext);
+ // And is the pebble_sd app running?
+ // set mPebbleAppRunningCheck has been false for more than 10 seconds
+ // the app is not talking to us
+ // mPebbleAppRunningCheck is set to true in the receiveData handler.
+ if (!mPebbleAppRunningCheck &&
+ (tdiff > mAppRestartTimeout * 1000)) {
+ Log.v(TAG, "getPebbleStatus() - tdiff = " + tdiff);
+ mSdData.pebbleAppRunning = false;
+ Log.v(TAG, "getPebbleStatus() - Pebble App Not Running - Attempting to Re-Start");
+ startWatchApp();
+ getPebbleSdSettings();
+ // Only make audible warning beep if we have not received data for more than mFaultTimerPeriod seconds.
+ if (tdiff > mFaultTimerPeriod * 1000) {
+ mSdDataReceiver.onSdDataFault(mSdData);
+ } else {
+ Log.v(TAG, "getPebbleStatus() - Waiting for mFaultTimerPeriod before issuing audible warning...");
+ }
+ } else {
+ mSdData.pebbleAppRunning = true;
+ }
+
+ // if we have confirmation that the app is running, reset the
+ // status time to now and initiate another check.
+ if (mPebbleAppRunningCheck) {
+ mPebbleAppRunningCheck = false;
+ mPebbleStatusTime.setToNow();
+ }
+
+ if (!mSdData.haveSettings) {
+ Log.v(TAG, "getPebbleStatus() - no settings received yet - requesting");
+ getPebbleSdSettings();
+ }
+ }
+
+
+
+
+}
+
diff --git a/app/src/main/java/uk/org/openseizuredetector/SdServer.java b/app/src/main/java/uk/org/openseizuredetector/SdServer.java
index bf3da71..60b5c76 100644
--- a/app/src/main/java/uk/org/openseizuredetector/SdServer.java
+++ b/app/src/main/java/uk/org/openseizuredetector/SdServer.java
@@ -27,11 +27,9 @@
package uk.org.openseizuredetector;
import java.util.Map;
+
import fi.iki.elonen.NanoHTTPD;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningServiceInfo;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -39,89 +37,40 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
-import android.content.res.AssetFileDescriptor;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.ToneGenerator;
-import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
import android.os.HandlerThread;
import android.os.Binder;
-import android.os.CountDownTimer;
import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
-import android.os.Process;
import android.preference.PreferenceManager;
import android.telephony.SmsManager;
-import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
+
import java.util.Timer;
import java.util.TimerTask;
import java.io.*;
import java.util.*;
-import java.util.UUID;
import java.util.StringTokenizer;
-import java.net.URL;
-import android.net.Uri;
-import java.nio.ByteBuffer;
-import java.nio.ShortBuffer;
-import java.nio.IntBuffer;
-import java.nio.ByteOrder;
+
import android.text.format.Time;
+
import org.json.JSONObject;
import org.json.JSONArray;
-import com.getpebble.android.kit.Constants;
-import com.getpebble.android.kit.PebbleKit;
-import com.getpebble.android.kit.util.PebbleDictionary;
/**
* Based on example at:
* http://stackoverflow.com/questions/14309256/using-nanohttpd-in-android
- * and
+ * and
* http://developer.android.com/guide/components/services.html#ExtendingService
*/
-public class SdServer extends Service
-{
- private UUID SD_UUID = UUID.fromString("03930f26-377a-4a3d-aa3e-f3b19e421c9d");
- private int NSAMP = 512; // Number of samples in fft input dataset.
-
- private int KEY_DATA_TYPE = 1;
- private int KEY_ALARMSTATE = 2;
- private int KEY_MAXVAL = 3;
- private int KEY_MAXFREQ = 4;
- private int KEY_SPECPOWER = 5;
- private int KEY_SETTINGS = 6;
- private int KEY_ALARM_FREQ_MIN =7;
- private int KEY_ALARM_FREQ_MAX =8;
- private int KEY_WARN_TIME = 9;
- private int KEY_ALARM_TIME = 10;
- private int KEY_ALARM_THRESH = 11;
- private int KEY_POS_MIN = 12; // position of first data point in array
- private int KEY_POS_MAX = 13; // position of last data point in array.
- private int KEY_SPEC_DATA = 14; // Spectrum data
- private int KEY_ROIPOWER = 15;
- private int KEY_NMIN = 16;
- private int KEY_NMAX = 17;
- private int KEY_ALARM_RATIO_THRESH = 18;
- private int KEY_BATTERY_PC = 19;
- //private int KEY_SET_SETTINGS =20; // Phone is asking us to update watch app settings.
- private int KEY_FALL_THRESH_MIN = 21;
- private int KEY_FALL_THRESH_MAX = 22;
- private int KEY_FALL_WINDOW = 23;
- private int KEY_FALL_ACTIVE =24;
-
- // Values of the KEY_DATA_TYPE entry in a message
- private int DATA_TYPE_RESULTS = 1; // Analysis Results
- private int DATA_TYPE_SETTINGS = 2; // Settings
- private int DATA_TYPE_SPEC = 3; // FFT Spectrum (or part of a spectrum)
-
+public class SdServer extends Service implements SdDataReceiver {
// Notification ID
private int NOTIFICATION_ID = 1;
@@ -129,18 +78,11 @@ public class SdServer extends Service
private WebServer webServer = null;
private final static String TAG = "SdServer";
- private Looper mServiceLooper;
- public Time mPebbleStatusTime;
- private boolean mPebbleAppRunningCheck = false;
- private Timer statusTimer = null;
- private int mFaultTimerPeriod = 30; // Fault Timer Period in sec
- private int mAppRestartTimeout = 10; // Timeout before re-starting watch app (sec).
- private Timer settingsTimer = null;
private Timer dataLogTimer = null;
private HandlerThread thread;
private WakeLock mWakeLock = null;
- public SdData sdData;
- private PebbleKit.PebbleDataReceiver msgDataHandler = null;
+ public SdDataSource mSdDataSource;
+ public SdData mSdData;
private boolean mLatchAlarms = false;
private boolean mCancelAudible = false;
private boolean mAudibleAlarm = false;
@@ -158,44 +100,44 @@ public class SdServer extends Service
/**
* class to handle binding the MainApp activity to this service
- * so it can access sdData.
+ * so it can access mSdData.
*/
public class SdBinder extends Binder {
- SdServer getService() {
- return SdServer.this;
- }
+ SdServer getService() {
+ return SdServer.this;
+ }
}
/**
* Constructor for SdServer class - does not do much!
*/
public SdServer() {
- super();
- sdData = new SdData();
- Log.v(TAG,"SdServer Created");
+ super();
+ mSdData = new SdData();
+ Log.v(TAG, "SdServer Created");
}
@Override
public IBinder onBind(Intent intent) {
- Log.v(TAG,"sdServer.onBind()");
- return mBinder;
+ Log.v(TAG, "sdServer.onBind()");
+ return mBinder;
}
-
/**
* onCreate() - called when services is created. Starts message
* handler process to listen for messages from other processes.
*/
@Override
public void onCreate() {
- Log.v(TAG,"onCreate()");
+ Log.v(TAG, "onCreate()");
- // Create a wake lock, but don't use it until the service is started.
- PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- "MyWakelockTag");
+
+ // Create a wake lock, but don't use it until the service is started.
+ PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "MyWakelockTag");
}
/**
@@ -204,204 +146,256 @@ public class SdServer extends Service
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- Log.v(TAG,"onStartCommand() - SdServer service starting");
-
- // Update preferences.
- Log.v(TAG,"onStartCommand() - calling updatePrefs()");
- updatePrefs();
-
- // Display a notification icon in the status bar of the phone to
- // show the service is running.
- Log.v(TAG,"showing Notification");
- showNotification();
+ Log.v(TAG, "onStartCommand() - SdServer service starting");
- // Record last time we sent an SMS so we can limit rate of SMS
- // sending to one per minute.
- mSMSTime = new Time(Time.getCurrentTimezone());
+ // Update preferences.
+ Log.v(TAG, "onStartCommand() - calling updatePrefs()");
+ updatePrefs();
+ mSdDataSource = new SdDataSourcePebble(this.getApplicationContext(), this);
+ mSdDataSource.start();
- // Start receiving data from the pebble watch
- startPebbleServer();
+ // Display a notification icon in the status bar of the phone to
+ // show the service is running.
+ Log.v(TAG, "showing Notification");
+ showNotification();
- // Start timer to check status of pebble regularly.
- mPebbleStatusTime = new Time(Time.getCurrentTimezone());
- //getPebbleStatus();
- if (statusTimer==null) {
- Log.v(TAG,"onCreate(): starting status timer");
- statusTimer = new Timer();
- statusTimer.schedule(new TimerTask() {
- @Override
- public void run() {getPebbleStatus();}
- }, 0, 1000);
- } else {
- Log.v(TAG,"onCreate(): status timer already running.");
- }
-
- // Start timer to retrieve pebble settings regularly.
- getPebbleSdSettings();
- if (settingsTimer == null) {
- Log.v(TAG,"onCreate(): starting settings timer");
- settingsTimer = new Timer();
- settingsTimer.schedule(new TimerTask() {
- @Override
- public void run() {getPebbleSdSettings();}
- }, 0, 1000*60);
- } else {
- Log.v(TAG,"onCreate(): settings timer already running.");
- }
-
- // Start timer to log data regularly..
- if (dataLogTimer == null) {
- Log.v(TAG,"onCreate(): starting dataLog timer");
- dataLogTimer = new Timer();
- dataLogTimer.schedule(new TimerTask() {
- @Override
- public void run() {logData();}
- }, 0, 1000*60);
- } else {
- Log.v(TAG,"onCreate(): dataLog timer already running.");
- }
+ // Record last time we sent an SMS so we can limit rate of SMS
+ // sending to one per minute.
+ mSMSTime = new Time(Time.getCurrentTimezone());
- // Start the web server
- startWebServer();
- // Apply the wake-lock to prevent CPU sleeping (very battery intensive!)
- if (mWakeLock!=null) {
- mWakeLock.acquire();
- Log.v(TAG,"Applied Wake Lock to prevent device sleeping");
- } else {
- Log.d(TAG,"mmm...mWakeLock is null, so not aquiring lock. This shouldn't happen!");
- }
+ // Start timer to log data regularly..
+ if (dataLogTimer == null) {
+ Log.v(TAG, "onCreate(): starting dataLog timer");
+ dataLogTimer = new Timer();
+ dataLogTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ logData();
+ }
+ }, 0, 1000 * 60);
+ } else {
+ Log.v(TAG, "onCreate(): dataLog timer already running.");
+ }
- return START_STICKY;
+
+ // Start the web server
+ startWebServer();
+
+ // Apply the wake-lock to prevent CPU sleeping (very battery intensive!)
+ if (mWakeLock != null) {
+ mWakeLock.acquire();
+ Log.v(TAG, "Applied Wake Lock to prevent device sleeping");
+ } else {
+ Log.d(TAG, "mmm...mWakeLock is null, so not aquiring lock. This shouldn't happen!");
+ }
+
+ return START_STICKY;
}
@Override
public void onDestroy() {
- Log.v(TAG,"onDestroy(): SdServer Service stopping");
- // release the wake lock to allow CPU to sleep and reduce
- // battery drain.
- if (mWakeLock!=null) {
- mWakeLock.release();
- Log.v(TAG,"Released Wake Lock to allow device to sleep.");
- } else {
- Log.d(TAG, "mmm...mWakeLock is null, so not releasing lock. This shouldn't happen!");
- }
+ Log.v(TAG, "onDestroy(): SdServer Service stopping");
+ // release the wake lock to allow CPU to sleep and reduce
+ // battery drain.
+ if (mWakeLock != null) {
+ mWakeLock.release();
+ Log.v(TAG, "Released Wake Lock to allow device to sleep.");
+ } else {
+ Log.d(TAG, "mmm...mWakeLock is null, so not releasing lock. This shouldn't happen!");
+ }
- try {
- // Stop the status timer
- if (statusTimer!=null) {
- Log.v(TAG,"onDestroy(): cancelling status timer");
- statusTimer.cancel();
- statusTimer.purge();
- statusTimer = null;
- }
- // Stop the settings timer
- if (settingsTimer!=null) {
- Log.v(TAG,"onDestroy(): cancelling settings timer");
- settingsTimer.cancel();
- settingsTimer.purge();
- settingsTimer = null;
- }
- // Cancel the notification.
- Log.v(TAG,"onDestroy(): cancelling notification");
- mNM.cancel(NOTIFICATION_ID);
- // Stop web server
- Log.v(TAG,"onDestroy(): stopping web server");
- stopWebServer();
- // Stop pebble message handler.
- Log.v(TAG,"onDestroy(): stopping pebble server");
- stopPebbleServer();
- // stop this service.
- Log.v(TAG,"onDestroy(): calling stopSelf()");
- stopSelf();
+ mSdDataSource.stop();
- } catch(Exception e) {
- Log.v(TAG,"Error in onDestroy() - "+e.toString());
- }
+ try {
+ // Cancel the notification.
+ Log.v(TAG, "onDestroy(): cancelling notification");
+ mNM.cancel(NOTIFICATION_ID);
+ // Stop web server
+ Log.v(TAG, "onDestroy(): stopping web server");
+ stopWebServer();
+ // stop this service.
+ Log.v(TAG, "onDestroy(): calling stopSelf()");
+ stopSelf();
+
+ } catch (Exception e) {
+ Log.v(TAG, "Error in onDestroy() - " + e.toString());
+ }
}
-
/**
* Show a notification while this service is running.
*/
private void showNotification() {
- Log.v(TAG,"showNotification()");
+ Log.v(TAG, "showNotification()");
CharSequence text = "OpenSeizureDetector Server Running";
- Notification notification =
- new Notification(R.drawable.star_of_life_24x24, text,
- System.currentTimeMillis());
- PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ Notification notification =
+ new Notification(R.drawable.star_of_life_24x24, text,
+ System.currentTimeMillis());
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
notification.setLatestEventInfo(this, "OpenSeizureDetector Server",
- text, contentIntent);
- notification.flags |= Notification.FLAG_NO_CLEAR;
- mNM = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
+ text, contentIntent);
+ notification.flags |= Notification.FLAG_NO_CLEAR;
+ mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNM.notify(NOTIFICATION_ID, notification);
}
+ /**
+ * Process the data received from the SdData source.
+ * @param sdData
+ */
+ public void onSdDataReceived(SdData sdData) {
+ Log.v(TAG, "onSdDataReceived()");
+ if (sdData.alarmState == 0) {
+ if ((!mLatchAlarms) ||
+ (mLatchAlarms &&
+ (!sdData.alarmStanding && !sdData.fallAlarmStanding))) {
+ sdData.alarmPhrase = "OK";
+ sdData.alarmStanding = false;
+ sdData.fallAlarmStanding = false;
+ }
+ }
+ if (sdData.alarmState == 1) {
+ if ((!mLatchAlarms) ||
+ (mLatchAlarms &&
+ (!sdData.alarmStanding && !sdData.fallAlarmStanding))) {
+ sdData.alarmPhrase = "WARNING";
+ sdData.alarmStanding = false;
+ sdData.fallAlarmStanding = false;
+ }
+ if (mLogAlarms) {
+ Log.v(TAG, "WARNING - Logging to SD Card");
+ writeAlarmToSD();
+ logData();
+ } else {
+ Log.v(TAG, "WARNING");
+ }
+ warningBeep();
+ }
+ if ((sdData.alarmState == 2) || (sdData.alarmStanding)) {
+ sdData.alarmPhrase = "ALARM";
+ sdData.alarmStanding = true;
+ if (mLogAlarms) {
+ Log.v(TAG, "***ALARM*** - Logging to SD Card");
+ writeAlarmToSD();
+ logData();
+ } else {
+ Log.v(TAG, "***ALARM***");
+ }
+ // Make alarm beep tone
+ alarmBeep();
+ // Send SMS Alarm.
+ if (mSMSAlarm) {
+ Time tnow = new Time(Time.getCurrentTimezone());
+ tnow.setToNow();
+ // limit SMS alarms to one per minute
+ if ((tnow.toMillis(false)
+ - mSMSTime.toMillis(false))
+ > 60000) {
+ sendSMSAlarm();
+ mSMSTime = tnow;
+ }
+ }
+ }
+ if ((sdData.alarmState == 3) || (sdData.fallAlarmStanding)) {
+ sdData.alarmPhrase = "FALL";
+ sdData.fallAlarmStanding = true;
+ if (mLogAlarms) {
+ Log.v(TAG, "***FALL*** - Logging to SD Card");
+ writeAlarmToSD();
+ logData();
+ } else {
+ Log.v(TAG, "***FALL***");
+ }
+ // Make alarm beep tone
+ alarmBeep();
+ // Send SMS Alarm.
+ if (mSMSAlarm) {
+ Time tnow = new Time(Time.getCurrentTimezone());
+ tnow.setToNow();
+ // limit SMS alarms to one per minute
+ if ((tnow.toMillis(false)
+ - mSMSTime.toMillis(false))
+ > 60000) {
+ sendSMSAlarm();
+ mSMSTime = tnow;
+ }
+ }
+
+ }
+ mSdData = sdData;
+ }
+
+ public void onSdDataFault(SdData sdData) {
+ Log.v(TAG,"onSdDataFault()");
+ if (mAudibleFaultWarning) {
+ faultWarningBeep();
+ }
+ }
/* from http://stackoverflow.com/questions/12154940/how-to-make-a-beep-in-android */
+
/**
* beep for duration miliseconds, but only if mAudibleAlarm is set.
*/
private void beep(int duration) {
- ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 100);
- toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, duration);
- Log.v(TAG,"beep()");
+ ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 100);
+ toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, duration);
+ Log.v(TAG, "beep()");
}
/*
* beep, provided mAudibleAlarm is set
*/
- public void faultWarningBeep() {
- if (mCancelAudible) {
- Log.v(TAG, "faultWarningBeep() - CancelAudible Active - silent beep...");
- } else {
- if (mAudibleFaultWarning) {
- beep(10);
- Log.v(TAG, "faultWarningBeep()");
- } else {
- Log.v(TAG, "faultWarningBeep() - silent...");
- }
- }
- }
-
+ public void faultWarningBeep() {
+ if (mCancelAudible) {
+ Log.v(TAG, "faultWarningBeep() - CancelAudible Active - silent beep...");
+ } else {
+ if (mAudibleFaultWarning) {
+ beep(10);
+ Log.v(TAG, "faultWarningBeep()");
+ } else {
+ Log.v(TAG, "faultWarningBeep() - silent...");
+ }
+ }
+ }
/*
* beep, provided mAudibleAlarm is set
*/
public void alarmBeep() {
- if (mCancelAudible) {
- Log.v(TAG,"alarmBeep() - CancelAudible Active - silent beep...");
- } else {
- if (mAudibleAlarm) {
- beep(1000);
- Log.v(TAG,"alarmBeep()");
- } else {
- Log.v(TAG,"alarmBeep() - silent...");
- }
- }
+ if (mCancelAudible) {
+ Log.v(TAG, "alarmBeep() - CancelAudible Active - silent beep...");
+ } else {
+ if (mAudibleAlarm) {
+ beep(1000);
+ Log.v(TAG, "alarmBeep()");
+ } else {
+ Log.v(TAG, "alarmBeep() - silent...");
+ }
+ }
}
/*
* beep, provided mAudibleWarning is set
*/
public void warningBeep() {
- if (mCancelAudible) {
- Log.v(TAG,"warningBeep() - CancelAudible Active - silent beep...");
- } else {
- if (mAudibleWarning) {
- beep(100);
- Log.v(TAG,"warningBeep()");
- } else {
- Log.v(TAG,"warningBeep() - silent...");
- }
- }
+ if (mCancelAudible) {
+ Log.v(TAG, "warningBeep() - CancelAudible Active - silent beep...");
+ } else {
+ if (mAudibleWarning) {
+ beep(100);
+ Log.v(TAG, "warningBeep()");
+ } else {
+ Log.v(TAG, "warningBeep() - silent...");
+ }
+ }
}
@@ -409,203 +403,33 @@ public class SdServer extends Service
* Sends SMS Alarms to the telephone numbers specified in mSMSNumbers[]
*/
public void sendSMSAlarm() {
- if (mSMSAlarm) {
- Log.v(TAG,"sendSMSAlarm() - Sending to "+mSMSNumbers.length+" Numbers");
- Time tnow = new Time(Time.getCurrentTimezone());
- tnow.setToNow();
- String dateStr = tnow.format("%Y-%m-%d %H-%M-%S");
- SmsManager sm = SmsManager.getDefault();
- for (int i=0;i 60000) {
- sendSMSAlarm();
- mSMSTime = tnow;
- }
- }
- }
- if ((sdData.alarmState == 3) || (sdData.fallAlarmStanding)) {
- sdData.alarmPhrase = "FALL";
- sdData.fallAlarmStanding = true;
- if (mLogAlarms) {
- Log.v(TAG, "***FALL*** - Logging to SD Card");
- writeAlarmToSD();
- logData();
- } else {
- Log.v(TAG, "***FALL***");
- }
- // Make alarm beep tone
- alarmBeep();
- // Send SMS Alarm.
- if (mSMSAlarm) {
- Time tnow = new Time(Time.getCurrentTimezone());
- tnow.setToNow();
- // limit SMS alarms to one per minute
- if ((tnow.toMillis(false)
- - mSMSTime.toMillis(false))
- > 60000) {
- sendSMSAlarm();
- mSMSTime = tnow;
- }
- }
- }
-
-
- // Read the data that has been sent, and convert it into
- // an integer array.
- byte[] byteArr = data.getBytes(KEY_SPEC_DATA);
- IntBuffer intBuf = ByteBuffer.wrap(byteArr)
- .order(ByteOrder.LITTLE_ENDIAN)
- .asIntBuffer();
- int[] intArray = new int[intBuf.remaining()];
- intBuf.get(intArray);
- for (int i=0;i mAppRestartTimeout * 1000)) {
- Log.v(TAG, "getPebbleStatus() - tdiff = " + tdiff);
- sdData.pebbleAppRunning = false;
- Log.v(TAG, "getPebbleStatus() - Pebble App Not Running - Attempting to Re-Start");
- startWatchApp();
- getPebbleSdSettings();
- // Only make audible warning beep if we have not received data for more than mFaultTimerPeriod seconds.
- if ((tdiff > mFaultTimerPeriod * 1000)
- && (mAudibleFaultWarning)
- ) {
- faultWarningBeep();
- } else {
- Log.v(TAG, "getPebbleStatus() - Waiting for mFaultTimerPeriod before issuing audible warning...");
- }
- } else {
- sdData.pebbleAppRunning = true;
- }
-
- // if we have confirmation that the app is running, reset the
- // status time to now and initiate another check.
- if (mPebbleAppRunningCheck) {
- mPebbleAppRunningCheck = false;
- mPebbleStatusTime.setToNow();
- }
-
- if (!sdData.haveSettings) {
- Log.v(TAG, "getPebbleStatus() - no settings received yet - requesting");
- getPebbleSdSettings();
- }
- }
-
- /**
- * Request Pebble App to send us its latest settings.
- * Will be received as a message by the receiveData handler
- */
- public void getPebbleSdSettings() {
- Log.v(TAG,"getPebbleSdSettings() - requesting settings from pebble");
- PebbleDictionary data = new PebbleDictionary();
- data.addUint8(KEY_SETTINGS, (byte)1);
- PebbleKit.sendDataToPebble(
- getApplicationContext(),
- SD_UUID,
- data);
+ if (mLogData) {
+ Log.v(TAG, "logData() - writing data to SD Card");
+ writeToSD();
+ }
}
@@ -721,190 +483,106 @@ public class SdServer extends Service
* - defined in res/xml/prefs.xml
*/
public void updatePrefs() {
- Log.v(TAG,"updatePrefs()");
- SharedPreferences SP = PreferenceManager
- .getDefaultSharedPreferences(getBaseContext());
- try {
- mLatchAlarms = SP.getBoolean("LatchAlarms",false);
- Log.v(TAG,"updatePrefs() - mLatchAlarms = "+mLatchAlarms);
- mAudibleFaultWarning = SP.getBoolean("AudibleFaultWarning",true);
- Log.v(TAG,"updatePrefs() - mAuidbleFaultWarning = "+mAudibleFaultWarning);
- mAudibleAlarm = SP.getBoolean("AudibleAlarm",true);
- Log.v(TAG,"updatePrefs() - mAuidbleAlarm = "+mAudibleAlarm);
- mAudibleWarning = SP.getBoolean("AudibleWarning",true);
- Log.v(TAG,"updatePrefs() - mAuidbleWarning = "+mAudibleWarning);
- mSMSAlarm = SP.getBoolean("SMSAlarm",false);
- Log.v(TAG,"updatePrefs() - mSMSAlarm = "+mSMSAlarm);
- String SMSNumberStr = SP.getString("SMSNumbers","");
- mSMSNumbers = SMSNumberStr.split(",");
- mSMSMsgStr = SP.getString("SMSMsg","Seizure Detected!!!");
- Log.v(TAG,"updatePrefs() - SMSNumberStr = "+SMSNumberStr);
- Log.v(TAG,"updatePrefs() - mSMSNumbers = "+mSMSNumbers);
- mLogAlarms = SP.getBoolean("LogAlarms",true);
- Log.v(TAG,"updatePrefs() - mLogAlarms = "+mLogAlarms);
- mLogData = SP.getBoolean("LogData",false);
- Log.v(TAG,"updatePrefs() - mLogData = "+mLogData);
+ Log.v(TAG, "updatePrefs()");
+ SharedPreferences SP = PreferenceManager
+ .getDefaultSharedPreferences(getBaseContext());
+ try {
+ mLatchAlarms = SP.getBoolean("LatchAlarms", false);
+ Log.v(TAG, "updatePrefs() - mLatchAlarms = " + mLatchAlarms);
+ mAudibleFaultWarning = SP.getBoolean("AudibleFaultWarning", true);
+ Log.v(TAG, "updatePrefs() - mAuidbleFaultWarning = " + mAudibleFaultWarning);
+ mAudibleAlarm = SP.getBoolean("AudibleAlarm", true);
+ Log.v(TAG, "updatePrefs() - mAuidbleAlarm = " + mAudibleAlarm);
+ mAudibleWarning = SP.getBoolean("AudibleWarning", true);
+ Log.v(TAG, "updatePrefs() - mAuidbleWarning = " + mAudibleWarning);
+ mSMSAlarm = SP.getBoolean("SMSAlarm", false);
+ Log.v(TAG, "updatePrefs() - mSMSAlarm = " + mSMSAlarm);
+ String SMSNumberStr = SP.getString("SMSNumbers", "");
+ mSMSNumbers = SMSNumberStr.split(",");
+ mSMSMsgStr = SP.getString("SMSMsg", "Seizure Detected!!!");
+ Log.v(TAG, "updatePrefs() - SMSNumberStr = " + SMSNumberStr);
+ Log.v(TAG, "updatePrefs() - mSMSNumbers = " + mSMSNumbers);
+ mLogAlarms = SP.getBoolean("LogAlarms", true);
+ Log.v(TAG, "updatePrefs() - mLogAlarms = " + mLogAlarms);
+ mLogData = SP.getBoolean("LogData", false);
+ Log.v(TAG, "updatePrefs() - mLogData = " + mLogData);
- // Parse the AppRestartTimeout period setting.
- try {
- String appRestartTimeoutStr = SP.getString("AppRestartTimeout", "10");
- mAppRestartTimeout = Integer.parseInt(appRestartTimeoutStr);
- Log.v(TAG, "onStart() - mAppRestartTimeout = " + mAppRestartTimeout);
- } catch (Exception ex) {
- Log.v(TAG, "onStart() - Problem with AppRestartTimeout preference!");
- Toast toast = Toast.makeText(getApplicationContext(), "Problem Parsing AppRestartTimeout Preference", Toast.LENGTH_SHORT);
- toast.show();
- }
-
-
- // Parse the FaultTimer period setting.
- try {
- String faultTimerPeriodStr = SP.getString("FaultTimerPeriod", "30");
- mFaultTimerPeriod = Integer.parseInt(faultTimerPeriodStr);
- Log.v(TAG, "onStart() - mFaultTimerPeriod = " + mFaultTimerPeriod);
- } catch (Exception ex) {
- Log.v(TAG, "onStart() - Problem with FaultTimerPeriod preference!");
- Toast toast = Toast.makeText(getApplicationContext(), "Problem Parsing FaultTimerPeriod Preference", Toast.LENGTH_SHORT);
- toast.show();
- }
-
-
- // Watch Settings
- PebbleDictionary setDict = new PebbleDictionary();
- short intVal;
- String prefStr;
- prefStr = SP.getString("AlarmFreqMin","5");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG, "updatePrefs() AlarmFreqMin = " + intVal);
- setDict.addInt16(KEY_ALARM_FREQ_MIN,intVal);
-
- prefStr = SP.getString("AlarmFreqMax","10");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG, "updatePrefs() AlarmFreqMax = " + intVal);
- setDict.addUint16(KEY_ALARM_FREQ_MAX, (short) intVal);
-
- prefStr = SP.getString("WarnTime","5");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG, "updatePrefs() WarnTime = " + intVal);
- setDict.addUint16(KEY_WARN_TIME,(short)intVal);
-
- prefStr = SP.getString("AlarmTime","10");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG, "updatePrefs() AlarmTime = " + intVal);
- setDict.addUint16(KEY_ALARM_TIME,(short)intVal);
-
- prefStr = SP.getString("AlarmThresh","100");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG, "updatePrefs() AlarmThresh = " + intVal);
- setDict.addUint16(KEY_ALARM_THRESH,(short)intVal);
-
- prefStr = SP.getString("AlarmRatioThresh","30");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG, "updatePrefs() AlarmRatioThresh = " + intVal);
- setDict.addUint16(KEY_ALARM_RATIO_THRESH, (short) intVal);
-
- boolean fallActiveBool = SP.getBoolean("FallActive",false);
- Log.v(TAG, "updatePrefs() FallActive = " + fallActiveBool);
- if (fallActiveBool)
- setDict.addUint16(KEY_FALL_ACTIVE,(short)1);
- else
- setDict.addUint16(KEY_FALL_ACTIVE,(short)0);
-
- prefStr = SP.getString("FallThreshMin","200");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG,"updatePrefs() FallThreshMin = "+intVal);
- setDict.addUint16(KEY_FALL_THRESH_MIN,(short)intVal);
-
- prefStr = SP.getString("FallThreshMax","1200");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG,"updatePrefs() FallThreshMax = "+intVal);
- setDict.addUint16(KEY_FALL_THRESH_MAX,(short)intVal);
-
- prefStr = SP.getString("FallWindow","1500");
- intVal = (short)Integer.parseInt(prefStr);
- Log.v(TAG,"updatePrefs() FallWindow = "+intVal);
- setDict.addUint16(KEY_FALL_WINDOW,(short)intVal);
-
-
- // Send Watch Settings to Pebble
- Log.v(TAG,"updatePrefs() - setDict = "+setDict.toJsonString());
- PebbleKit.sendDataToPebble(getApplicationContext(), SD_UUID, setDict);
- } catch (Exception ex) {
- Log.v(TAG,"updatePrefs() - Problem parsing preferences!");
- Toast toast = Toast.makeText(getApplicationContext(),"Problem Parsing Preferences - Something won't work - Please go back to Settings and correct it!",Toast.LENGTH_SHORT);
- toast.show();
- }
+ } catch (Exception ex) {
+ Log.v(TAG, "updatePrefs() - Problem parsing preferences!");
+ Toast toast = Toast.makeText(getApplicationContext(), "Problem Parsing Preferences - Something won't work - Please go back to Settings and correct it!", Toast.LENGTH_SHORT);
+ toast.show();
+ }
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
- String state = Environment.getExternalStorageState();
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- return true;
- }
- return false;
+ String state = Environment.getExternalStorageState();
+ if (Environment.MEDIA_MOUNTED.equals(state)) {
+ return true;
+ }
+ return false;
}
public File getDataStorageDir() {
- // Get the directory for the user's public pictures directory.
- File file =
- new File(Environment.getExternalStorageDirectory()
- ,"OpenSeizureDetector");
- if (!file.mkdirs()) {
- Log.e(TAG, "Directory not created");
- }
- return file;
+ // Get the directory for the user's public pictures directory.
+ File file =
+ new File(Environment.getExternalStorageDirectory()
+ , "OpenSeizureDetector");
+ if (!file.mkdirs()) {
+ Log.e(TAG, "Directory not created");
+ }
+ return file;
}
/**
* Write data to SD card alarm log
*/
public void writeAlarmToSD() {
- writeToSD(true);
+ writeToSD(true);
}
/**
* Write to data log file on SD Card
*/
public void writeToSD() {
- writeToSD(false);
+ writeToSD(false);
}
-
+
/**
* Write data to SD card - writes to data log file unless alarm=true,
* in which case writes to alarm log file.
*/
public void writeToSD(boolean alarm) {
- Log.v(TAG,"writeToSD("+alarm+")");
- Time tnow = new Time(Time.getCurrentTimezone());
- tnow.setToNow();
- String dateStr = tnow.format("%Y-%m-%d");
+ Log.v(TAG, "writeToSD(" + alarm + ")");
+ Time tnow = new Time(Time.getCurrentTimezone());
+ tnow.setToNow();
+ String dateStr = tnow.format("%Y-%m-%d");
- // Select filename depending on 'alarm' parameter.
- String fname;
- if (alarm)
- fname = "AlarmLog";
- else
- fname = "DataLog";
+ // Select filename depending on 'alarm' parameter.
+ String fname;
+ if (alarm)
+ fname = "AlarmLog";
+ else
+ fname = "DataLog";
- fname = fname+"_"+dateStr+".txt";
- // Open output directory on SD Card.
- if (isExternalStorageWritable()) {
- try {
- FileWriter of = new FileWriter(getDataStorageDir().toString()
- + "/" + fname, true);
- if (sdData!=null) {
- Log.v(TAG,"writing sdData.toString()");
- of.append(sdData.toString()+"\n");
- }
- of.close();
- } catch(Exception ex) {
- Log.e(TAG,"writeAlarmToSD - error "+ex.toString());
- }
- } else {
- Log.e(TAG,"ERROR - Can not Write to External Folder");
- }
+ fname = fname + "_" + dateStr + ".txt";
+ // Open output directory on SD Card.
+ if (isExternalStorageWritable()) {
+ try {
+ FileWriter of = new FileWriter(getDataStorageDir().toString()
+ + "/" + fname, true);
+ if (mSdData != null) {
+ Log.v(TAG, "writing mSdData.toString()");
+ of.append(mSdData.toString() + "\n");
+ }
+ of.close();
+ } catch (Exception ex) {
+ Log.e(TAG, "writeAlarmToSD - error " + ex.toString());
+ }
+ } else {
+ Log.e(TAG, "ERROR - Can not Write to External Folder");
+ }
}
/**
@@ -912,203 +590,190 @@ public class SdServer extends Service
* 8080.
*/
private class WebServer extends NanoHTTPD {
- private String TAG = "WebServer";
- public WebServer()
- {
- // Set the port to listen on (8080)
+ private String TAG = "WebServer";
+
+ public WebServer() {
+ // Set the port to listen on (8080)
super(8080);
}
@Override
- public Response serve(String uri, Method method,
+ public Response serve(String uri, Method method,
Map header,
Map parameters,
Map files) {
- Log.v(TAG,"WebServer.serve() - uri="+uri+" Method="+method.toString());
- String answer = "Error - you should not see this message! - Something wrong in WebServer.serve()";
+ Log.v(TAG, "WebServer.serve() - uri=" + uri + " Method=" + method.toString());
+ String answer = "Error - you should not see this message! - Something wrong in WebServer.serve()";
- Iterator it = parameters.keySet().iterator();
- while (it.hasNext()) {
- Object key = it.next();
- Object value = parameters.get(key);
- //Log.v(TAG,"Request parameters - key="+key+" value="+value);
- }
+ Iterator it = parameters.keySet().iterator();
+ while (it.hasNext()) {
+ Object key = it.next();
+ Object value = parameters.get(key);
+ //Log.v(TAG,"Request parameters - key="+key+" value="+value);
+ }
- if (uri.equals("/")) uri = "/index.html";
- switch(uri) {
- case "/data":
- //Log.v(TAG,"WebServer.serve() - Returning data");
- try {
- //JSONObject jsonObj = new JSONObject();
- //jsonObj.put("Time",mPebbleStatusTime.format("%H:%M:%S"));
- //jsonObj.put("alarmState",sdData.alarmState);
- //jsonObj.put("alarmPhrase",sdData.alarmPhrase);
- //jsonObj.put("maxVal",sdData.maxVal);
- //jsonObj.put("maxFreq",sdData.maxFreq);
- //jsonObj.put("specPower",sdData.specPower);
- //jsonObj.put("roiPower",sdData.roiPower);
- //jsonObj.put("pebCon",mPebbleConnected);
- //jsonObj.put("pebAppRun",mPebbleAppRunning);
- answer = sdData.toString();
- } catch (Exception ex) {
- Log.v(TAG,"Error Creating Data Object - "+ex.toString());
- answer = "Error Creating Data Object";
- }
- break;
+ if (uri.equals("/")) uri = "/index.html";
+ switch (uri) {
+ case "/data":
+ //Log.v(TAG,"WebServer.serve() - Returning data");
+ try {
+ answer = mSdData.toString();
+ } catch (Exception ex) {
+ Log.v(TAG, "Error Creating Data Object - " + ex.toString());
+ answer = "Error Creating Data Object";
+ }
+ break;
- case "/settings":
- //Log.v(TAG,"WebServer.serve() - Returning settings");
- try {
- JSONObject jsonObj = new JSONObject();
- jsonObj.put("alarmFreqMin",sdData.alarmFreqMin);
- jsonObj.put("alarmFreqMax",sdData.alarmFreqMax);
- jsonObj.put("nMin",sdData.nMin);
- jsonObj.put("nMax",sdData.nMax);
- jsonObj.put("warnTime",sdData.warnTime);
- jsonObj.put("alarmTime",sdData.alarmTime);
- jsonObj.put("alarmThresh",sdData.alarmThresh);
- jsonObj.put("alarmRatioThresh",sdData.alarmRatioThresh);
- jsonObj.put("batteryPc",sdData.batteryPc);
- answer = jsonObj.toString();
- } catch (Exception ex) {
- Log.v(TAG,"Error Creating Data Object - "+ex.toString());
- answer = "Error Creating Data Object";
- }
- break;
+ case "/settings":
+ //Log.v(TAG,"WebServer.serve() - Returning settings");
+ try {
+ JSONObject jsonObj = new JSONObject();
+ jsonObj.put("alarmFreqMin", mSdData.alarmFreqMin);
+ jsonObj.put("alarmFreqMax", mSdData.alarmFreqMax);
+ jsonObj.put("nMin", mSdData.nMin);
+ jsonObj.put("nMax", mSdData.nMax);
+ jsonObj.put("warnTime", mSdData.warnTime);
+ jsonObj.put("alarmTime", mSdData.alarmTime);
+ jsonObj.put("alarmThresh", mSdData.alarmThresh);
+ jsonObj.put("alarmRatioThresh", mSdData.alarmRatioThresh);
+ jsonObj.put("batteryPc", mSdData.batteryPc);
+ answer = jsonObj.toString();
+ } catch (Exception ex) {
+ Log.v(TAG, "Error Creating Data Object - " + ex.toString());
+ answer = "Error Creating Data Object";
+ }
+ break;
- case "/spectrum":
- Log.v(TAG,"WebServer.serve() - Returning spectrum - 1");
- try {
- JSONObject jsonObj = new JSONObject();
- Log.v(TAG,"WebServer.serve() - Returning spectrum - 2");
- // Initialised it this way because one phone was ok with JSONArray(sdData.simpleSpec), and the other crashed...
- JSONArray arr = new JSONArray();
- for (int i=0;i