Merge branch 'v2.0.x' of https://github.com/OpenSeizureDetector/Android_Pebble_SD into v2.0.x
This commit is contained in:
@@ -24,17 +24,16 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile files('libs/mpandroidchartlibrary-2-0-7.jar')
|
compile files('libs/mpandroidchartlibrary-2-0-7.jar')
|
||||||
compile 'com.getpebble:pebblekit:3.0.0@aar'
|
compile 'com.getpebble:pebblekit:3.1.0@aar'
|
||||||
|
|
||||||
// Unit testing dependencies
|
// Unit testing dependencies
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
// Set this dependency if you want to use Mockito
|
// Set this dependency if you want to use Mockito
|
||||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||||
// Set this dependency if you want to use Hamcrest matching
|
// Set this dependency if you want to use Hamcrest matching
|
||||||
testCompile 'org.hamcrest:hamcrest-library:1.1'
|
testCompile 'org.hamcrest:hamcrest-library:1.1'
|
||||||
|
|
||||||
compile 'com.android.support:appcompat-v7:22.2.1'
|
compile 'com.android.support:appcompat-v7:22.2.1'
|
||||||
compile 'com.android.support:support-v4:22.2.1'
|
compile 'com.android.support:support-v4:22.2.1'
|
||||||
|
compile files('libs/JTransforms-3.1-with-dependencies.jar')
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||
BIN
app/libs/JTransforms-3.1-with-dependencies.jar
Normal file
BIN
app/libs/JTransforms-3.1-with-dependencies.jar
Normal file
Binary file not shown.
Binary file not shown.
85
app/src/main/java/uk/org/openseizuredetector/AccelData.java
Normal file
85
app/src/main/java/uk/org/openseizuredetector/AccelData.java
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by graham on 27/06/16.
|
||||||
|
*/
|
||||||
|
/* From https://github.com/kramimus/pebble-accel-analyzer */
|
||||||
|
public class AccelData {
|
||||||
|
private final String TAG = AccelData.class.getSimpleName();
|
||||||
|
|
||||||
|
final private int x;
|
||||||
|
final private int y;
|
||||||
|
final private int z;
|
||||||
|
|
||||||
|
private long timestamp = 0;
|
||||||
|
final private boolean didVibrate;
|
||||||
|
|
||||||
|
public AccelData(byte[] data) {
|
||||||
|
x = (data[0] & 0xff) | (data[1] << 8);
|
||||||
|
y = (data[2] & 0xff) | (data[3] << 8);
|
||||||
|
z = (data[4] & 0xff) | (data[5] << 8);
|
||||||
|
didVibrate = data[6] != 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
timestamp |= ((long)(data[i+7] & 0xff)) << (i * 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
try {
|
||||||
|
json.put("x", x);
|
||||||
|
json.put("y", y);
|
||||||
|
json.put("z", z);
|
||||||
|
json.put("ts", timestamp);
|
||||||
|
json.put("v", didVibrate);
|
||||||
|
return json;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.w(TAG, "problem constructing accel data, skipping " + e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<AccelData> fromDataArray(byte[] data) {
|
||||||
|
List<AccelData> accels = new ArrayList<AccelData>();
|
||||||
|
for (int i = 0; i < data.length; i += 15) {
|
||||||
|
accels.add(new AccelData(Arrays.copyOfRange(data, i, i + 15)));
|
||||||
|
}
|
||||||
|
return accels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMagnitude() {
|
||||||
|
return (int)Math.sqrt(x*x + y*y + z*z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyTimezone(TimeZone tz) {
|
||||||
|
timestamp -= tz.getOffset(timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import java.util.AbstractList;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by graham on 28/06/16.
|
||||||
|
*/
|
||||||
|
public class CircularArrayList<E>
|
||||||
|
extends AbstractList<E> implements RandomAccess {
|
||||||
|
/**
|
||||||
|
* If you use this code, please consider notifying isak at du-preez dot com
|
||||||
|
* with a brief description of your application.
|
||||||
|
*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
* distribute this software, either in source code form or as a compiled
|
||||||
|
* binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
* means.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private final int n; // buffer length
|
||||||
|
private final List<E> buf; // a List implementing RandomAccess
|
||||||
|
private int head = 0;
|
||||||
|
private int tail = 0;
|
||||||
|
|
||||||
|
public CircularArrayList(int capacity) {
|
||||||
|
n = capacity + 1;
|
||||||
|
buf = new ArrayList<E>(Collections.nCopies(n, (E) null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int capacity() {
|
||||||
|
return n - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int wrapIndex(int i) {
|
||||||
|
int m = i % n;
|
||||||
|
if (m < 0) { // java modulus can be negative
|
||||||
|
m += n;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method is O(n) but will never be called if the
|
||||||
|
// CircularArrayList is used in its typical/intended role.
|
||||||
|
private void shiftBlock(int startIndex, int endIndex) {
|
||||||
|
assert (endIndex > startIndex);
|
||||||
|
for (int i = endIndex - 1; i >= startIndex; i--) {
|
||||||
|
set(i + 1, get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return tail - head + (tail < head ? n : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E get(int i) {
|
||||||
|
if (i < 0 || i >= size()) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
return buf.get(wrapIndex(head + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E set(int i, E e) {
|
||||||
|
if (i < 0 || i >= size()) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
return buf.set(wrapIndex(head + i), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(int i, E e) {
|
||||||
|
int s = size();
|
||||||
|
if (s == n - 1) {
|
||||||
|
throw new IllegalStateException("Cannot add element."
|
||||||
|
+ " CircularArrayList is filled to capacity.");
|
||||||
|
}
|
||||||
|
if (i < 0 || i > s) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
tail = wrapIndex(tail + 1);
|
||||||
|
if (i < s) {
|
||||||
|
shiftBlock(i, s);
|
||||||
|
}
|
||||||
|
set(i, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E remove(int i) {
|
||||||
|
int s = size();
|
||||||
|
if (i < 0 || i >= s) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
E e = get(i);
|
||||||
|
if (i > 0) {
|
||||||
|
shiftBlock(0, i);
|
||||||
|
}
|
||||||
|
head = wrapIndex(head + 1);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,12 @@ import org.apache.http.conn.util.InetAddressUtils;
|
|||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
|
import java.util.AbstractList;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OsdUtil - OpenSeizureDetector Utilities
|
* OsdUtil - OpenSeizureDetector Utilities
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ public class SdData implements Parcelable {
|
|||||||
public short mFallThreshMin;
|
public short mFallThreshMin;
|
||||||
public short mFallThreshMax;
|
public short mFallThreshMax;
|
||||||
public short mFallWindow;
|
public short mFallWindow;
|
||||||
|
public long mSdMode;
|
||||||
|
public long mSampleFreq;
|
||||||
public long alarmFreqMin;
|
public long alarmFreqMin;
|
||||||
public long alarmFreqMax;
|
public long alarmFreqMax;
|
||||||
public long nMin;
|
public long nMin;
|
||||||
@@ -148,6 +150,8 @@ public class SdData implements Parcelable {
|
|||||||
jsonObj.put("haveSettings", haveSettings);
|
jsonObj.put("haveSettings", haveSettings);
|
||||||
jsonObj.put("alarmState", alarmState);
|
jsonObj.put("alarmState", alarmState);
|
||||||
jsonObj.put("alarmPhrase", alarmPhrase);
|
jsonObj.put("alarmPhrase", alarmPhrase);
|
||||||
|
jsonObj.put("sdMode",mSdMode);
|
||||||
|
jsonObj.put("sampleFreq",mSampleFreq);
|
||||||
jsonObj.put("alarmFreqMin",alarmFreqMin);
|
jsonObj.put("alarmFreqMin",alarmFreqMin);
|
||||||
jsonObj.put("alarmFreqMax",alarmFreqMax);
|
jsonObj.put("alarmFreqMax",alarmFreqMax);
|
||||||
jsonObj.put("alarmThresh", alarmThresh);
|
jsonObj.put("alarmThresh", alarmThresh);
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ import com.getpebble.android.kit.Constants;
|
|||||||
import com.getpebble.android.kit.PebbleKit;
|
import com.getpebble.android.kit.PebbleKit;
|
||||||
import com.getpebble.android.kit.util.PebbleDictionary;
|
import com.getpebble.android.kit.util.PebbleDictionary;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.jtransforms.fft.DoubleFFT_1D;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -46,6 +50,10 @@ import java.io.OutputStream;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -63,7 +71,7 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
private Time mPebbleStatusTime;
|
private Time mPebbleStatusTime;
|
||||||
private boolean mPebbleAppRunningCheck = false;
|
private boolean mPebbleAppRunningCheck = false;
|
||||||
private int mAppRestartTimeout = 10; // Timeout before re-starting watch app (sec) if we have not received
|
private int mAppRestartTimeout = 10; // Timeout before re-starting watch app (sec) if we have not received
|
||||||
// data after mDataUpdatePeriod
|
// data after mDataUpdatePeriod
|
||||||
//private Looper mServiceLooper;
|
//private Looper mServiceLooper;
|
||||||
private int mFaultTimerPeriod = 30; // Fault Timer Period in sec
|
private int mFaultTimerPeriod = 30; // Fault Timer Period in sec
|
||||||
private PebbleKit.PebbleDataReceiver msgDataHandler = null;
|
private PebbleKit.PebbleDataReceiver msgDataHandler = null;
|
||||||
@@ -101,14 +109,27 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
private int KEY_DATA_UPDATE_PERIOD = 25;
|
private int KEY_DATA_UPDATE_PERIOD = 25;
|
||||||
private int KEY_MUTE_PERIOD = 26;
|
private int KEY_MUTE_PERIOD = 26;
|
||||||
private int KEY_MAN_ALARM_PERIOD = 27;
|
private int KEY_MAN_ALARM_PERIOD = 27;
|
||||||
|
private int KEY_SD_MODE = 28;
|
||||||
|
private int KEY_SAMPLE_FREQ = 29;
|
||||||
|
private int KEY_RAW_DATA = 30;
|
||||||
|
private int KEY_NUM_RAW_DATA = 31;
|
||||||
|
|
||||||
// Values of the KEY_DATA_TYPE entry in a message
|
// Values of the KEY_DATA_TYPE entry in a message
|
||||||
private int DATA_TYPE_RESULTS = 1; // Analysis Results
|
private int DATA_TYPE_RESULTS = 1; // Analysis Results
|
||||||
private int DATA_TYPE_SETTINGS = 2; // Settings
|
private int DATA_TYPE_SETTINGS = 2; // Settings
|
||||||
private int DATA_TYPE_SPEC = 3; // FFT Spectrum (or part of a spectrum)
|
private int DATA_TYPE_SPEC = 3; // FFT Spectrum (or part of a spectrum)
|
||||||
|
private int DATA_TYPE_RAW = 4; // raw accelerometer data.
|
||||||
|
|
||||||
|
// Values for SD_MODE
|
||||||
|
private int SD_MODE_FFT = 0; // The original OpenSeizureDetector mode (FFT based)
|
||||||
|
private int SD_MODE_RAW = 1; // Send raw, unprocessed data to the phone.
|
||||||
|
private int SD_MODE_FILTER = 2; // Use digital filter rather than FFT.
|
||||||
|
|
||||||
private short mDataUpdatePeriod;
|
private short mDataUpdatePeriod;
|
||||||
private short mMutePeriod;
|
private short mMutePeriod;
|
||||||
private short mManAlarmPeriod;
|
private short mManAlarmPeriod;
|
||||||
|
private short mPebbleSdMode;
|
||||||
|
private short mSampleFreq;
|
||||||
private short mAlarmFreqMin;
|
private short mAlarmFreqMin;
|
||||||
private short mAlarmFreqMax;
|
private short mAlarmFreqMax;
|
||||||
private short mWarnTime;
|
private short mWarnTime;
|
||||||
@@ -120,8 +141,13 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
private short mFallThreshMax;
|
private short mFallThreshMax;
|
||||||
private short mFallWindow;
|
private short mFallWindow;
|
||||||
|
|
||||||
|
// raw data storage for SD_MODE_RAW
|
||||||
|
private int MAX_RAW_DATA = 500;
|
||||||
|
private double[] rawData = new double[MAX_RAW_DATA];
|
||||||
|
private int nRawData = 0;
|
||||||
|
|
||||||
public SdDataSourcePebble(Context context, SdDataReceiver sdDataReceiver) {
|
public SdDataSourcePebble(Context context, SdDataReceiver sdDataReceiver) {
|
||||||
super(context,sdDataReceiver);
|
super(context, sdDataReceiver);
|
||||||
mName = "Pebble";
|
mName = "Pebble";
|
||||||
// Set default settings from XML files (mContext is set by super().
|
// Set default settings from XML files (mContext is set by super().
|
||||||
PreferenceManager.setDefaultValues(mContext,
|
PreferenceManager.setDefaultValues(mContext,
|
||||||
@@ -251,7 +277,15 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
mManAlarmPeriod = (short) Integer.parseInt(prefStr);
|
mManAlarmPeriod = (short) Integer.parseInt(prefStr);
|
||||||
Log.v(TAG, "updatePrefs() ManAlarmPeriod = " + mManAlarmPeriod);
|
Log.v(TAG, "updatePrefs() ManAlarmPeriod = " + mManAlarmPeriod);
|
||||||
|
|
||||||
prefStr = SP.getString("AlarmFreqMin","SET_FROM_XML");
|
prefStr = SP.getString("PebbleSdMode", "SET_FROM_XML");
|
||||||
|
mPebbleSdMode = (short) Integer.parseInt(prefStr);
|
||||||
|
Log.v(TAG, "updatePrefs() PebbleSdMode = " + mPebbleSdMode);
|
||||||
|
|
||||||
|
prefStr = SP.getString("SampleFreq", "SET_FROM_XML");
|
||||||
|
mSampleFreq = (short) Integer.parseInt(prefStr);
|
||||||
|
Log.v(TAG, "updatePrefs() SampleFreq = " + mSampleFreq);
|
||||||
|
|
||||||
|
prefStr = SP.getString("AlarmFreqMin", "SET_FROM_XML");
|
||||||
mAlarmFreqMin = (short) Integer.parseInt(prefStr);
|
mAlarmFreqMin = (short) Integer.parseInt(prefStr);
|
||||||
Log.v(TAG, "updatePrefs() AlarmFreqMin = " + mAlarmFreqMin);
|
Log.v(TAG, "updatePrefs() AlarmFreqMin = " + mAlarmFreqMin);
|
||||||
|
|
||||||
@@ -313,7 +347,7 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
Log.v(TAG, "Received message from Pebble - data type="
|
Log.v(TAG, "Received message from Pebble - data type="
|
||||||
+ data.getUnsignedIntegerAsLong(KEY_DATA_TYPE));
|
+ data.getUnsignedIntegerAsLong(KEY_DATA_TYPE));
|
||||||
// If we have a message, the app must be running
|
// If we have a message, the app must be running
|
||||||
Log.v(TAG,"Setting mPebbleAppRunningCheck to true");
|
Log.v(TAG, "Setting mPebbleAppRunningCheck to true");
|
||||||
mPebbleAppRunningCheck = true;
|
mPebbleAppRunningCheck = true;
|
||||||
PebbleKit.sendAckToPebble(context, transactionId);
|
PebbleKit.sendAckToPebble(context, transactionId);
|
||||||
//Log.v(TAG,"Message is: "+data.toJsonString());
|
//Log.v(TAG,"Message is: "+data.toJsonString());
|
||||||
@@ -365,6 +399,23 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
mSdData.batteryPc = data.getUnsignedIntegerAsLong(KEY_BATTERY_PC);
|
mSdData.batteryPc = data.getUnsignedIntegerAsLong(KEY_BATTERY_PC);
|
||||||
mSdData.haveSettings = true;
|
mSdData.haveSettings = true;
|
||||||
}
|
}
|
||||||
|
if (data.getUnsignedIntegerAsLong(KEY_DATA_TYPE)
|
||||||
|
== DATA_TYPE_RAW) {
|
||||||
|
Log.v(TAG, "DATA_TYPE = Raw");
|
||||||
|
long numSamples;
|
||||||
|
numSamples = data.getUnsignedIntegerAsLong(KEY_NUM_RAW_DATA);
|
||||||
|
Log.v(TAG, "numSamples = " + numSamples);
|
||||||
|
byte[] rawDataBytes = data.getBytes(KEY_RAW_DATA);
|
||||||
|
for (AccelData reading : AccelData.fromDataArray(rawDataBytes)) {
|
||||||
|
if (nRawData < MAX_RAW_DATA) {
|
||||||
|
rawData[nRawData] = reading.getMagnitude();
|
||||||
|
nRawData++;
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "WARNING - rawData Buffer Full");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PebbleKit.registerReceivedDataHandler(mContext, msgDataHandler);
|
PebbleKit.registerReceivedDataHandler(mContext, msgDataHandler);
|
||||||
@@ -427,12 +478,14 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
* variables to the watch.
|
* variables to the watch.
|
||||||
*/
|
*/
|
||||||
public void sendPebbleSdSettings() {
|
public void sendPebbleSdSettings() {
|
||||||
Log.v(TAG, "sendPebblSdSettings() - preparing settings dictionary..");
|
Log.v(TAG, "sendPebblSdSettings() - preparing settings dictionary.. mSampleFreq=" + mSampleFreq);
|
||||||
// Watch Settings
|
// Watch Settings
|
||||||
final PebbleDictionary setDict = new PebbleDictionary();
|
final PebbleDictionary setDict = new PebbleDictionary();
|
||||||
setDict.addInt16(KEY_DATA_UPDATE_PERIOD, mDataUpdatePeriod);
|
setDict.addInt16(KEY_DATA_UPDATE_PERIOD, mDataUpdatePeriod);
|
||||||
setDict.addInt16(KEY_MUTE_PERIOD, mMutePeriod);
|
setDict.addInt16(KEY_MUTE_PERIOD, mMutePeriod);
|
||||||
setDict.addInt16(KEY_MAN_ALARM_PERIOD, mManAlarmPeriod);
|
setDict.addInt16(KEY_MAN_ALARM_PERIOD, mManAlarmPeriod);
|
||||||
|
setDict.addInt16(KEY_SD_MODE, mPebbleSdMode);
|
||||||
|
setDict.addInt16(KEY_SAMPLE_FREQ, mSampleFreq);
|
||||||
setDict.addInt16(KEY_ALARM_FREQ_MIN, mAlarmFreqMin);
|
setDict.addInt16(KEY_ALARM_FREQ_MIN, mAlarmFreqMin);
|
||||||
setDict.addInt16(KEY_ALARM_FREQ_MAX, mAlarmFreqMax);
|
setDict.addInt16(KEY_ALARM_FREQ_MAX, mAlarmFreqMax);
|
||||||
setDict.addUint16(KEY_WARN_TIME, mWarnTime);
|
setDict.addUint16(KEY_WARN_TIME, mWarnTime);
|
||||||
@@ -460,57 +513,57 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
* @return true if they are all the same, or false if there are discrepancies.
|
* @return true if they are all the same, or false if there are discrepancies.
|
||||||
*/
|
*/
|
||||||
public boolean checkWatchSettings() {
|
public boolean checkWatchSettings() {
|
||||||
boolean settingsOk = true;
|
boolean settingsOk = true;
|
||||||
if (mDataUpdatePeriod != mSdData.mDataUpdatePeriod) {
|
if (mDataUpdatePeriod != mSdData.mDataUpdatePeriod) {
|
||||||
Log.v(TAG,"checkWatchSettings - mDataUpdatePeriod Wrong");
|
Log.v(TAG, "checkWatchSettings - mDataUpdatePeriod Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mMutePeriod != mSdData.mMutePeriod) {
|
if (mMutePeriod != mSdData.mMutePeriod) {
|
||||||
Log.v(TAG,"checkWatchSettings - mMutePeriod Wrong");
|
Log.v(TAG, "checkWatchSettings - mMutePeriod Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mManAlarmPeriod != mSdData.mManAlarmPeriod) {
|
if (mManAlarmPeriod != mSdData.mManAlarmPeriod) {
|
||||||
Log.v(TAG,"checkWatchSettings - mManAlarmPeriod Wrong");
|
Log.v(TAG, "checkWatchSettings - mManAlarmPeriod Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mAlarmFreqMin != mSdData.alarmFreqMin) {
|
if (mAlarmFreqMin != mSdData.alarmFreqMin) {
|
||||||
Log.v(TAG,"checkWatchSettings - mAlarmFreqMin Wrong");
|
Log.v(TAG, "checkWatchSettings - mAlarmFreqMin Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mAlarmFreqMax != mSdData.alarmFreqMax) {
|
if (mAlarmFreqMax != mSdData.alarmFreqMax) {
|
||||||
Log.v(TAG,"checkWatchSettings - mAlarmFreqMax Wrong");
|
Log.v(TAG, "checkWatchSettings - mAlarmFreqMax Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mWarnTime != mSdData.warnTime) {
|
if (mWarnTime != mSdData.warnTime) {
|
||||||
Log.v(TAG,"checkWatchSettings - mWarnTime Wrong");
|
Log.v(TAG, "checkWatchSettings - mWarnTime Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mAlarmTime != mSdData.alarmTime) {
|
if (mAlarmTime != mSdData.alarmTime) {
|
||||||
Log.v(TAG,"checkWatchSettings - mAlarmTime Wrong");
|
Log.v(TAG, "checkWatchSettings - mAlarmTime Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mAlarmThresh != mSdData.alarmThresh) {
|
if (mAlarmThresh != mSdData.alarmThresh) {
|
||||||
Log.v(TAG,"checkWatchSettings - mAlarmThresh Wrong");
|
Log.v(TAG, "checkWatchSettings - mAlarmThresh Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mAlarmRatioThresh != mSdData.alarmRatioThresh) {
|
if (mAlarmRatioThresh != mSdData.alarmRatioThresh) {
|
||||||
Log.v(TAG,"checkWatchSettings - mAlarmRatioThresh Wrong");
|
Log.v(TAG, "checkWatchSettings - mAlarmRatioThresh Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mFallActive != mSdData.mFallActive) {
|
if (mFallActive != mSdData.mFallActive) {
|
||||||
Log.v(TAG,"checkWatchSettings - mAlarmFreqMin Wrong");
|
Log.v(TAG, "checkWatchSettings - mAlarmFreqMin Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mFallThreshMin != mSdData.mFallThreshMin) {
|
if (mFallThreshMin != mSdData.mFallThreshMin) {
|
||||||
Log.v(TAG,"checkWatchSettings - mFallThreshMin Wrong");
|
Log.v(TAG, "checkWatchSettings - mFallThreshMin Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mFallThreshMax != mSdData.mFallThreshMax) {
|
if (mFallThreshMax != mSdData.mFallThreshMax) {
|
||||||
Log.v(TAG,"checkWatchSettings - mFallThreshMax Wrong");
|
Log.v(TAG, "checkWatchSettings - mFallThreshMax Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
if (mFallWindow != mSdData.mFallWindow) {
|
if (mFallWindow != mSdData.mFallWindow) {
|
||||||
Log.v(TAG,"checkWatchSettings - mFallWindow Wrong");
|
Log.v(TAG, "checkWatchSettings - mFallWindow Wrong");
|
||||||
settingsOk = false;
|
settingsOk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,7 +596,7 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
tnow.setToNow();
|
tnow.setToNow();
|
||||||
// get time since the last data was received from the Pebble watch.
|
// get time since the last data was received from the Pebble watch.
|
||||||
tdiff = (tnow.toMillis(false) - mPebbleStatusTime.toMillis(false));
|
tdiff = (tnow.toMillis(false) - mPebbleStatusTime.toMillis(false));
|
||||||
Log.v(TAG, "getPebbleStatus() - mPebbleAppRunningCheck="+mPebbleAppRunningCheck+" tdiff="+tdiff);
|
Log.v(TAG, "getPebbleStatus() - mPebbleAppRunningCheck=" + mPebbleAppRunningCheck + " tdiff=" + tdiff);
|
||||||
// Check we are actually connected to the pebble.
|
// Check we are actually connected to the pebble.
|
||||||
mSdData.pebbleConnected = PebbleKit.isWatchConnected(mContext);
|
mSdData.pebbleConnected = PebbleKit.isWatchConnected(mContext);
|
||||||
if (!mSdData.pebbleConnected) mPebbleAppRunningCheck = false;
|
if (!mSdData.pebbleConnected) mPebbleAppRunningCheck = false;
|
||||||
@@ -552,7 +605,7 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
// the app is not talking to us
|
// the app is not talking to us
|
||||||
// mPebbleAppRunningCheck is set to true in the receiveData handler.
|
// mPebbleAppRunningCheck is set to true in the receiveData handler.
|
||||||
if (!mPebbleAppRunningCheck &&
|
if (!mPebbleAppRunningCheck &&
|
||||||
(tdiff > (mDataUpdatePeriod+mAppRestartTimeout) * 1000)) {
|
(tdiff > (mDataUpdatePeriod + mAppRestartTimeout) * 1000)) {
|
||||||
Log.v(TAG, "getPebbleStatus() - tdiff = " + tdiff);
|
Log.v(TAG, "getPebbleStatus() - tdiff = " + tdiff);
|
||||||
mSdData.pebbleAppRunning = false;
|
mSdData.pebbleAppRunning = false;
|
||||||
Log.v(TAG, "getPebbleStatus() - Pebble App Not Running - Attempting to Re-Start");
|
Log.v(TAG, "getPebbleStatus() - Pebble App Not Running - Attempting to Re-Start");
|
||||||
@@ -560,7 +613,7 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
//mPebbleStatusTime = tnow; // set status time to now so we do not re-start app repeatedly.
|
//mPebbleStatusTime = tnow; // set status time to now so we do not re-start app repeatedly.
|
||||||
getPebbleSdSettings();
|
getPebbleSdSettings();
|
||||||
// Only make audible warning beep if we have not received data for more than mFaultTimerPeriod seconds.
|
// Only make audible warning beep if we have not received data for more than mFaultTimerPeriod seconds.
|
||||||
if (tdiff > (mDataUpdatePeriod+mFaultTimerPeriod) * 1000) {
|
if (tdiff > (mDataUpdatePeriod + mFaultTimerPeriod) * 1000) {
|
||||||
mSdDataReceiver.onSdDataFault(mSdData);
|
mSdDataReceiver.onSdDataFault(mSdData);
|
||||||
} else {
|
} else {
|
||||||
Log.v(TAG, "getPebbleStatus() - Waiting for mFaultTimerPeriod before issuing audible warning...");
|
Log.v(TAG, "getPebbleStatus() - Waiting for mFaultTimerPeriod before issuing audible warning...");
|
||||||
@@ -581,6 +634,19 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
getPebbleSdSettings();
|
getPebbleSdSettings();
|
||||||
getPebbleData();
|
getPebbleData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mPebbleSdMode == SD_MODE_RAW) {
|
||||||
|
analyseRawData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void analyseRawData() {
|
||||||
|
Log.v(TAG,"analyserawData()");
|
||||||
|
DoubleFFT_1D fft = new DoubleFFT_1D(MAX_RAW_DATA);
|
||||||
|
fft.realForward(rawData);
|
||||||
|
// FIXME - rawData should really be a circular buffer.
|
||||||
|
nRawData = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -614,10 +680,9 @@ public class SdDataSourcePebble extends SdDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
16
app/src/main/res/values/pebble_sample_freq_list.xml
Normal file
16
app/src/main/res/values/pebble_sample_freq_list.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string-array name="pebble_sample_freq_list">
|
||||||
|
<item>"100 Hz"</item>
|
||||||
|
<item>"50 Hz"</item>
|
||||||
|
<item>"25 Hz"</item>
|
||||||
|
<item>"10 Hz"</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="pebble_sample_freq_list_values">
|
||||||
|
<item>"100"</item>
|
||||||
|
<item>"50"</item>
|
||||||
|
<item>"25"</item>
|
||||||
|
<item>"10"</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
14
app/src/main/res/values/pebble_sd_mode_list.xml
Normal file
14
app/src/main/res/values/pebble_sd_mode_list.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string-array name="pebble_sd_mode_list">
|
||||||
|
<item>"Normal - OpenSeizureDetector FFT"</item>
|
||||||
|
<item>"Raw"</item>
|
||||||
|
<item>"Digital Filter"</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="pebble_sd_mode_list_values">
|
||||||
|
<item>"0"</item>
|
||||||
|
<item>"1"</item>
|
||||||
|
<item>"2"</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
android:summary="Select whether to use a Pebble Watch or network connection as the seizure detector data source."
|
android:summary="Select whether to use a Pebble Watch or network connection as the seizure detector data source."
|
||||||
android:entries="@array/datasource_list"
|
android:entries="@array/datasource_list"
|
||||||
android:entryValues="@array/datasource_list_values"
|
android:entryValues="@array/datasource_list_values"
|
||||||
|
android:defaultValue="Pebble"
|
||||||
android:dialogTitle="Select Data Source" />
|
android:dialogTitle="Select Data Source" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
|||||||
@@ -19,6 +19,23 @@
|
|||||||
android:title="Manual Alarm Period (sec)" />
|
android:title="Manual Alarm Period (sec)" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="Seizure Detector Settings">
|
<PreferenceCategory android:title="Seizure Detector Settings">
|
||||||
|
<ListPreference
|
||||||
|
android:key="PebbleSdMode"
|
||||||
|
android:title="Seizure Detector Mode"
|
||||||
|
android:summary="Select one of the three available modes of operation."
|
||||||
|
android:entries="@array/pebble_sd_mode_list"
|
||||||
|
android:entryValues="@array/pebble_sd_mode_list_values"
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:dialogTitle="Select Seizure Detector Mode" />
|
||||||
|
<ListPreference
|
||||||
|
android:key="SampleFreq"
|
||||||
|
android:title="Select Sample Frequency"
|
||||||
|
android:summary="Higher Frequency is more Accurate, but uses more battery power."
|
||||||
|
android:entries="@array/pebble_sample_freq_list"
|
||||||
|
android:entryValues="@array/pebble_sample_freq_list_values"
|
||||||
|
android:defaultValue="100"
|
||||||
|
android:dialogTitle="Select Sample Frequency" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue="3"
|
android:defaultValue="3"
|
||||||
android:key="AlarmFreqMin"
|
android:key="AlarmFreqMin"
|
||||||
|
|||||||
Reference in New Issue
Block a user