diff --git a/android/ConductorsSensor/app/build.gradle b/android/ConductorsSensor/app/build.gradle index 8b1a7ce..f34dab1 100644 --- a/android/ConductorsSensor/app/build.gradle +++ b/android/ConductorsSensor/app/build.gradle @@ -4,7 +4,7 @@ android { compileSdkVersion 26 defaultConfig { applicationId "de.tonifetzer.conductorssensor" - minSdkVersion 21 + minSdkVersion 24 targetSdkVersion 26 versionCode 1 versionName "1.0" @@ -34,5 +34,5 @@ dependencies { api 'com.mbientlab:metawear:3.4.0' implementation 'com.android.support:preference-v7:26.1.0' implementation 'com.android.support:preference-v14:26.1.0' - compile 'com.github.wendykierp:JTransforms:3.1' + implementation 'com.github.wendykierp:JTransforms:3.1' } diff --git a/android/ConductorsSensor/app/src/main/AndroidManifest.xml b/android/ConductorsSensor/app/src/main/AndroidManifest.xml index 08c7f1b..03f66a3 100644 --- a/android/ConductorsSensor/app/src/main/AndroidManifest.xml +++ b/android/ConductorsSensor/app/src/main/AndroidManifest.xml @@ -4,6 +4,8 @@ + + mFragmentStack; ToggleButton mStartStopToggle; + TextView mBpmTextView; Estimator mEstimator; @@ -35,9 +48,19 @@ public class MainActivity extends FragmentActivity implements PopupMenu.OnMenuIt mStartStopToggle= (ToggleButton) findViewById(R.id.startBtn); mStartStopToggle.setOnCheckedChangeListener(this); + //textview to show the bpm estimation + mBpmTextView = (TextView) findViewById(R.id.bpmText); + + mEstimator = new Estimator(); + mEstimator.addListener(this); + // ensures the connection to the bt sensor board mConnectFragment = new ConnectFragment(); mFragmentStack = new Stack<>(); + + //check for ble permissions + checkForBlePermissions(); + } @Override @@ -135,21 +158,78 @@ public class MainActivity extends FragmentActivity implements PopupMenu.OnMenuIt if (isChecked) { if(mConnectFragment.getSensorBoard() != null && mConnectFragment.getSensorBoard().isConnected()){ - mConnectFragment.getSensorBoard().startAccelerometer(); - //todo: estimator classe mit start und stop funktion. board bei start durchreichen. + mBpmTextView.setTextColor(Color.parseColor("#EE693F")); + Toast.makeText(this, "Start estimation", Toast.LENGTH_SHORT).show(); + mEstimator.start(mConnectFragment.getSensorBoard()); + + //todo: metronom } else { + Toast.makeText(this, "Please connect a sensor!", Toast.LENGTH_SHORT).show(); mStartStopToggle.setChecked(false); } } else { if(mConnectFragment.getSensorBoard() != null){ - mConnectFragment.getSensorBoard().stopAccelerometer(); + + mBpmTextView.setTextColor(Color.parseColor("#158b69")); + Toast.makeText(this, "Stop estimation", Toast.LENGTH_SHORT).show(); + mEstimator.stop(); } } } -} + + @Override + public void onNewEstimationAvailable(double bpm) { + + runOnUiThread(new Runnable() { + @Override + public void run() { + mBpmTextView.setText(String.valueOf(Math.round(bpm))); + } + }); + } + + + private void checkForBlePermissions(){ + if(this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("This app needs location access"); + builder.setMessage("Please grant location access so this app can detect the Sensor over Bluetooth."); + builder.setPositiveButton(android.R.string.ok, null); + builder.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION); + } + }); + builder.show(); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, String permission[], int[] grantResults){ + switch(requestCode){ + case PERMISSION_REQUEST_COARSE_LOCATION: { + if(grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Log.d("MainActivity", "coarse location permissin granted"); + } else { + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("Functionality limited"); + builder.setMessage("Without permission, this app is not able to connect to a sensor."); + builder.setPositiveButton(android.R.string.ok, null); + builder.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + } + }); + builder.show(); + } + } + } + } +} \ No newline at end of file diff --git a/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/BpmEstimator.java b/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/BpmEstimator.java index 55cb641..8ac4a2f 100644 --- a/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/BpmEstimator.java +++ b/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/BpmEstimator.java @@ -27,7 +27,7 @@ public class BpmEstimator { //private SimpleKalman mKalman; - public BpmEstimator(AccelerometerWindowBuffer windowBuffer, double sampleRate_ms, int resetAfter_ms){ + BpmEstimator(AccelerometerWindowBuffer windowBuffer, double sampleRate_ms, int resetAfter_ms){ mBuffer = windowBuffer; mSampleRate_ms = sampleRate_ms; @@ -46,6 +46,14 @@ public class BpmEstimator { //mKalman = new SimpleKalman(); } + public void reset(){ + mResetCounter = 0; + mBpmHistory_X.clear(); + mBpmHistory_Y.clear(); + mBpmHistory_Z.clear(); + mBpmHistory.clear(); + } + //TODO: we use the buffer from outside.. this buffer is continuously updated.. not good! public double estimate(AccelerometerWindowBuffer fixedWindow){ diff --git a/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/Estimator.java b/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/Estimator.java index c4d80f1..16eec0b 100644 --- a/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/Estimator.java +++ b/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/estimation/Estimator.java @@ -1,6 +1,5 @@ package de.tonifetzer.conductorssensor.estimation; -import android.hardware.Sensor; import android.util.Log; import java.util.LinkedList; @@ -20,14 +19,14 @@ public class Estimator implements SensorBoard.OnSensorBoardDataListener { private Timer mTimer = new Timer(); - Estimator(){ + public Estimator(){ mAccelerometerWindowBuffer = new AccelerometerWindowBuffer(6000, 750); mBpmEstimator = new BpmEstimator(mAccelerometerWindowBuffer, 0, 5000); } public void start(SensorBoard sensorBoard){ - if(mSensorBoard != null){ + if(sensorBoard != null){ mSensorBoard = sensorBoard; mSensorBoard.addListener(this); mSensorBoard.startAccelerometer(); @@ -45,6 +44,7 @@ public class Estimator implements SensorBoard.OnSensorBoardDataListener { mSensorBoard.stopAccelerometer(); mAccelerometerWindowBuffer.clear(); + mBpmEstimator.reset(); } else { Log.i("Estimator","Cant stop estimator. SensorBoard is null."); @@ -97,7 +97,7 @@ public class Estimator implements SensorBoard.OnSensorBoardDataListener { Utils.removeOutliersZScore(bpmList, 3.4); //Utils.removeOutliersHeuristic(); - //Log.d("BPM: ", bpmList.toString()); + Log.d("BPM: ", bpmList.toString()); double bpm = -1; if(!bpmList.isEmpty()) { @@ -160,7 +160,7 @@ public class Estimator implements SensorBoard.OnSensorBoardDataListener { } private List mEstimationListeners = new CopyOnWriteArrayList<>(); - public void add(OnEstimationListener listener){mEstimationListeners.add(listener);} - public void remove(OnEstimationListener listener){mEstimationListeners.remove(listener);} + public void addListener(OnEstimationListener listener){mEstimationListeners.add(listener);} + public void removeListener(OnEstimationListener listener){mEstimationListeners.remove(listener);} } diff --git a/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/sensor/SensorBoard.java b/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/sensor/SensorBoard.java index c11d45b..9e6ab2f 100644 --- a/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/sensor/SensorBoard.java +++ b/android/ConductorsSensor/app/src/main/java/de/tonifetzer/conductorssensor/sensor/SensorBoard.java @@ -211,7 +211,6 @@ public class SensorBoard implements ServiceConnection { source.stream(new Subscriber() { @Override public void apply(Data data, Object... env) { - Log.i("MainActivity", data.value(Acceleration.class).toString()); for(OnSensorBoardDataListener listener : mDataListeners){ listener.onAccelerometerChanged(new AccelerometerData(