From ad77fe7740dbc80c9a4236d7e2c1877efba2ee79 Mon Sep 17 00:00:00 2001 From: Graham Jones Date: Sun, 15 Oct 2017 21:25:38 +0100 Subject: [PATCH] Progressing with raw analysis in networkPassiveDataSource - not working yet. --- app/build.gradle | 1 + .../SdDataSourceNetworkPassive.java | 585 ++++-------------- 2 files changed, 119 insertions(+), 467 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c697549..898a1b4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,6 +39,7 @@ dependencies { // google play services used for location finding for SMS alerts. compile 'com.google.android.gms:play-services-location:10.0.0' compile 'com.google.android.gms:play-services:10.0.1' + compile 'com.github.wendykierp:JTransforms:3.0' } diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetworkPassive.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetworkPassive.java index 421c4a5..44e2046 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetworkPassive.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetworkPassive.java @@ -25,9 +25,9 @@ package uk.org.openseizuredetector; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.net.Uri; +import android.os.BatteryManager; import android.os.Handler; import android.preference.PreferenceManager; import android.text.format.Time; @@ -37,11 +37,10 @@ import android.widget.Toast; import com.getpebble.android.kit.PebbleKit; import com.getpebble.android.kit.util.PebbleDictionary; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import org.json.JSONArray; +import org.json.JSONObject; +import org.jtransforms.fft.DoubleFFT_1D; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; @@ -56,73 +55,23 @@ import java.util.UUID; */ public class SdDataSourceNetworkPassive extends SdDataSource { private Handler mHandler = new Handler(); - private Timer mSettingsTimer; private Timer mStatusTimer; - private Time mPebbleStatusTime; - private boolean mPebbleAppRunningCheck = false; + private Time mDataStatusTime; + private boolean mWatchAppRunningCheck = false; private int mAppRestartTimeout = 10; // Timeout before re-starting watch app (sec) if we have not received - // data after mDataUpdatePeriod - //private Looper mServiceLooper; + // data after mDataUpdatePeriod private int mFaultTimerPeriod = 30; // Fault Timer Period in sec - private int mSettingsPeriod = 60; // period between requesting settings in seconds. - private PebbleKit.PebbleDataReceiver msgDataHandler = null; - private String TAG = "SdDataSourceNetPassive"; - 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; - private int KEY_DATA_UPDATE_PERIOD = 25; - private int KEY_MUTE_PERIOD = 26; - 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; - private int KEY_DEBUG = 32; - private int KEY_DISPLAY_SPECTRUM = 33; - private int KEY_SAMPLE_PERIOD = 34; - private int KEY_VERSION_MAJOR = 35; - private int KEY_VERSION_MINOR = 36; - private int KEY_FREQ_CUTOFF = 37; - - // 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) - 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 int SIMPLE_SPEC_FMAX = 10; private short mDebug; + private short mFreqCutoff = 12; private short mDisplaySpectrum; private short mDataUpdatePeriod; private short mMutePeriod; @@ -143,8 +92,9 @@ public class SdDataSourceNetworkPassive extends SdDataSource { // 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 double[] mAccData = new double[MAX_RAW_DATA]; + int mNSamp = 0; + public SdDataSourceNetworkPassive(Context context, Handler handler, SdDataReceiver sdDataReceiver) { @@ -164,9 +114,8 @@ public class SdDataSourceNetworkPassive extends SdDataSource { Log.v(TAG, "start()"); mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.start()"); updatePrefs(); - startServer(); - // Start timer to check status of pebble regularly. - mPebbleStatusTime = new Time(Time.getCurrentTimezone()); + // Start timer to check status of watch regularly. + mDataStatusTime = new Time(Time.getCurrentTimezone()); // use a timer to check the status of the pebble app on the same frequency // as we get app data. if (mStatusTimer == null) { @@ -183,24 +132,6 @@ public class SdDataSourceNetworkPassive extends SdDataSource { Log.v(TAG, "start(): status timer already running."); mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.start() - status timer already running??"); } - // make sure we get some data when we first start. - //getData(); - // Start timer to retrieve pebble settings regularly. - //getWatchSdSettings(); - if (mSettingsTimer == null) { - Log.v(TAG, "start(): starting settings timer"); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.start() - starting settings timer"); - mSettingsTimer = new Timer(); - mSettingsTimer.schedule(new TimerTask() { - @Override - public void run() { - //mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.mSettingsTimer timed out.");getWatchSdSettings(); - } - }, 0, 1000 * mSettingsPeriod); // ask for settings less frequently than we get data - } else { - Log.v(TAG, "start(): settings timer already running."); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.start() - settings timer already running??"); - } } /** @@ -218,19 +149,6 @@ public class SdDataSourceNetworkPassive extends SdDataSource { mStatusTimer.purge(); mStatusTimer = null; } - // Stop the settings timer - if (mSettingsTimer != null) { - Log.v(TAG, "stop(): cancelling settings timer"); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.stop() - cancelling settings timer"); - mSettingsTimer.cancel(); - mSettingsTimer.purge(); - mSettingsTimer = null; - } - // Stop pebble message handler. - Log.v(TAG, "stop(): stopping NetworkPassive server"); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.stop() - stopping pebble server"); - stopServer(); - } catch (Exception e) { Log.v(TAG, "Error in stop() - " + e.toString()); mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.stop() - error - "+e.toString()); @@ -353,346 +271,129 @@ public class SdDataSourceNetworkPassive extends SdDataSource { } - /** - * Set this server to receive pebble data by registering it as - * A PebbleDataReceiver - */ - private void startServer() { - Log.v(TAG, "StartPebbleServer()"); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.startServer()"); - 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 have a message, the app must be running - Log.v(TAG, "Setting mPebbleAppRunningCheck to true"); - 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); + // Force the data stored in this datasource to update in line with the JSON string encoded data provided. + // Used by webServer to update the NetworkPassiveDatasource + public void updateFromJSON(String jsonStr) { + Log.v(TAG,"updateFromJSON - "+jsonStr); - 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"; - mSdData.haveData = true; - 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"); - try { - mSdData.analysisPeriod = data.getUnsignedIntegerAsLong(KEY_SAMPLE_PERIOD); - 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; - } catch (Exception ex) { - mUtil.showToast("*** Error interpreting settings sent from watch - Please check you have " - + "the latest version of the watch app installed by using the OpenSeizureDetector " - + "menu to install the Watch App"); - mUtil.writeToSysLogFile("Error interpreting settings received from watch - wrong version " - + "of watch app installed?"); - } - } - 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 (int i = 0; i < rawDataBytes.length - 4; i += 4) { // 4 bytes per sample - int x = (rawDataBytes[i]); - //int y = (rawDataBytes[i+2] & 0xff) | (rawDataBytes[i+3] << 8); - //int z = (rawDataBytes[i+4] & 0xff) | (rawDataBytes[i+5] << 8); - //Log.v(TAG,"x="+x+", y="+y+", z="+z); - Log.v(TAG,"x="+x); - if (nRawData < MAX_RAW_DATA) { - rawData[nRawData] = (int)Math.sqrt(x); - } else { - Log.i(TAG, "WARNING - rawData Buffer Full"); - } - - } - - - //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); - // We struggle to connect to pebble time if app is already running, - // so stop app so we can re-connect to it. - //stopWatchApp(); - startWatchApp(); - } - - /** - * De-register this server from receiving pebble data - */ - public void stopServer() { - Log.v(TAG, "stopServer(): Stopping Pebble Server"); - Log.v(TAG, "stopServer(): msgDataHandler = " + msgDataHandler.toString()); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.stopServer()"); try { - mContext.unregisterReceiver(msgDataHandler); - stopWatchApp(); - } catch (Exception e) { - Log.v(TAG, "stopServer() - error " + e.toString()); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.stopServer() - error " + e.toString()); - } - } + JSONObject mainObject = new JSONObject(jsonStr); + JSONObject dataObject = mainObject.getJSONObject("dataObj"); + String dataTypeStr = dataObject.getString("dataType"); + Log.v(TAG,"updateFromJSON - dataType="+dataTypeStr); + JSONArray accelVals = dataObject.getJSONArray("data"); - /** - * Attempt to start the pebble_sd watch app on the pebble watch. - */ - public void startWatchApp() { - Log.v(TAG, "startWatchApp() - closing app first"); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.startWatchApp() - closing app first"); - // first close the watch app if it is running. - PebbleKit.closeAppOnPebble(mContext, SD_UUID); - Log.v(TAG, "startWatchApp() - starting watch app after 5 seconds delay..."); - // Wait 5 seconds then start the app. - Timer appStartTimer = new Timer(); - appStartTimer.schedule(new TimerTask() { - @Override - public void run() { - Log.v(TAG, "startWatchApp() - starting watch app..."); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.startWatchApp() - starting watch app"); - PebbleKit.startAppOnPebble(mContext, SD_UUID); + Log.v(TAG,"Received " + accelVals.length() + " acceleration values"); + + int i; + for (i=0;i (mDataUpdatePeriod + mFaultTimerPeriod) * 1000) { - Log.v(TAG, "getStatus() - Pebble App Not Running - Attempting to Re-Start"); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.getStatus() - Pebble App not Running - Attempting to Re-Start"); - startWatchApp(); - mPebbleStatusTime.setToNow(); + Log.v(TAG, "getStatus() - Watch App Not Running"); + mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.getStatus() - Watch App not Running"); + //mDataStatusTime.setToNow(); mSdDataReceiver.onSdDataFault(mSdData); } else { Log.v(TAG, "getStatus() - Waiting for mFaultTimerPeriod before issuing audible warning..."); @@ -703,66 +404,16 @@ public class SdDataSourceNetworkPassive extends SdDataSource { // 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 (mWatchAppRunningCheck) { + mWatchAppRunningCheck = false; + mDataStatusTime.setToNow(); } if (!mSdData.haveSettings) { - Log.v(TAG, "getStatus() - no settings received yet - requesting"); - getPebbleSdSettings(); - getData(); - } - - if (mPebbleSdMode == SD_MODE_RAW) { - analyseRawData(); + Log.v(TAG, "getStatus() - no settings received yet"); } } - /** - * analyseRawData() - called when raw data is received. - * FIXME - this does not do anything at the moment so raw data is - * ignored! - */ - 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; - } - - /** - * Install the wach app that is bundled in the 'assets' folder of this - * phone app. - * from https://github.com/pebble-examples/pebblekit-android-example/blob/master/android/Eclipse/src/com/getpebble/pebblekitexample/MainActivity.java#L148 - */ - @Override - public void installWatchApp() { - Log.v(TAG, "SdDataSourceNetworkPassive.installWatchApp()"); - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.installWatchApp()"); - } - - /** - * Install the OpenSeizureDetector watch app onto the watch from Pebble AppStore - * based on https://forums.getpebble.com/discussion/13128/install-watch-app-pebble-store-from-android-companion-app - */ - public void installWatchAppFromPebbleAppStore() { - } - - - - - /** - * Open Pebble or Pebble Time app. If it is not installed, open Play store so the user can install it. - */ - @Override - public void startPebbleApp() { - mUtil.writeToSysLogFile("SdDataSourceNetworkPassive.startPebbleApp()"); - - } - - }