diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml
new file mode 100644
index 0000000..80f880e
--- /dev/null
+++ b/.idea/assetWizardSettings.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
new file mode 100644
index 0000000..c0a1d75
Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..15a15b2
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index cfe4315..ee635a3 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -3,9 +3,11 @@
diff --git a/.idea/misc.xml b/.idea/misc.xml
index ba7052b..37a7509 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,30 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 9a8c334..cd6d7b7 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index df965fe..cab69e3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,7 +1,8 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 28
+ compileSdkVersion 29
+ buildToolsVersion '29.0.2'
defaultConfig {
applicationId "de.fhws.indoor.sensorreadout"
@@ -20,10 +21,13 @@ android {
}
dependencies {
+ implementation 'com.android.support:design:23.4.0'
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
- compile 'com.android.support:appcompat-v7:23.4.0'
- compile 'com.google.android.gms:play-services:10.2.0'
+ implementation 'com.android.support:appcompat-v7:23.4.0'
+ implementation 'com.google.android.gms:play-services:10.2.0'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ implementation 'org.apmem.tools:layouts:1.10@aar'
//compile 'com.google.android.support:wearable:1.3.0'
//compile 'com.google.android.gms:play-services-wearable:8.4.0'
//provided 'com.google.android.wearable:wearable:1.0.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6c5724c..de7f3dc 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,10 +1,7 @@
- >
-
-
@@ -13,8 +10,7 @@
-
-
+
@@ -24,6 +20,8 @@
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme">
+
+
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java b/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java
index 85d8e34..e8e6cb5 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java
@@ -4,59 +4,64 @@ import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Configuration;
-import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
+import android.os.SystemClock;
+import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.pm.ActivityInfoCompat;
//import android.support.wearable.activity.WearableActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
-import android.widget.LinearLayout;
import android.widget.Spinner;
+import android.widget.TableLayout;
+import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import android.view.ViewGroup.LayoutParams;
-import com.google.android.gms.vision.text.Line;
-
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
-import de.fhws.indoor.sensorreadout.sensors.Gps;
import de.fhws.indoor.sensorreadout.sensors.GpsNew;
import de.fhws.indoor.sensorreadout.sensors.GroundTruth;
import de.fhws.indoor.sensorreadout.sensors.Logger;
+import de.fhws.indoor.sensorreadout.sensors.LoggerRAM;
import de.fhws.indoor.sensorreadout.sensors.PedestrianActivity;
import de.fhws.indoor.sensorreadout.sensors.PedestrianActivityButton;
import de.fhws.indoor.sensorreadout.sensors.PhoneSensors;
import de.fhws.indoor.sensorreadout.sensors.WiFi;
-import de.fhws.indoor.sensorreadout.sensors.WiFiRTT;
import de.fhws.indoor.sensorreadout.sensors.iBeacon;
-import de.fhws.indoor.sensorreadout.sensors.iBeaconOld;
import de.fhws.indoor.sensorreadout.sensors.mySensor;
import de.fhws.indoor.sensorreadout.sensors.SensorType;
public class MainActivity extends Activity {
+ MediaPlayer mpStart;
+ MediaPlayer mpStop;
+ MediaPlayer mpGround;
+ MediaPlayer mpFailure;
+
private final ArrayList sensors = new ArrayList();
- private final Logger logger = new Logger(this);
+ //private final Logger logger = new Logger(this);
+ private final LoggerRAM logger = new LoggerRAM(this);
private Button btnStart;
private Button btnStop;
private Button btnGround;
- private PedestrianActivityButton btnWalk;
- private PedestrianActivityButton btnStand;
- private PedestrianActivityButton btnStairsUp;
- private PedestrianActivityButton btnStairsDown;
- private PedestrianActivityButton btnElevatorUp;
- private PedestrianActivityButton btnElevatorDown;
- private PedestrianActivity currentPedestrianActivity;
- private PedestrianActivity pastPedestrianActivity;
+ private Button btnSettings;
+ private TableLayout activityButtonContainer;
+ private HashMap activityButtons = new HashMap<>();
+ private PedestrianActivity currentPedestrianActivity = PedestrianActivity.STANDING;
private int groundTruthCounter = 0;
private boolean isInitialized = false;
@@ -71,10 +76,18 @@ public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+ // This static call will reset default values for preferences only on the first ever read
+ PreferenceManager.setDefaultValues(getBaseContext(), R.xml.preferences, false);
// context access
MainActivity.context = getApplicationContext();
+ // setup sound-effects
+ mpStart = MediaPlayer.create(this, R.raw.go);
+ mpStop = MediaPlayer.create(this, R.raw.go);
+ mpGround = MediaPlayer.create(this, R.raw.go);
+ mpFailure = MediaPlayer.create(this, R.raw.error);
+
//init Path spinner
final Spinner pathSpinner = (Spinner) findViewById(R.id.pathspinner);
List pathList = new ArrayList();
@@ -101,31 +114,15 @@ public class MainActivity extends Activity {
btnStart = (Button) findViewById(R.id.btnStart);
btnStop = (Button) findViewById(R.id.btnStop);
btnGround = (Button) findViewById(R.id.btnGround);
-
- //get activity Buttons
- btnWalk = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnWalk), PedestrianActivity.WALK);
- btnStand = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnStanding), PedestrianActivity.STANDING);
- btnStairsUp = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnStairsUp), PedestrianActivity.STAIRS_UP);
- btnStairsDown = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnStairsDown), PedestrianActivity.STAIRS_DOWN);
- btnElevatorUp = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnElevatorUp), PedestrianActivity.ELEVATOR_UP);
- btnElevatorDown = new PedestrianActivityButton((LinearLayout) findViewById(R.id.btnElevatorDown), PedestrianActivity.ELEVATOR_DOWN);
-
- //set current activity
- btnStand.toggleActivity(); //first activity is standing!
- currentPedestrianActivity = PedestrianActivity.STANDING;
-
- //Click Sound
- final MediaPlayer mpStart = MediaPlayer.create(this, R.raw.go);
- final MediaPlayer mpStop = MediaPlayer.create(this, R.raw.go);
- final MediaPlayer mpGround = MediaPlayer.create(this, R.raw.go);
- final MediaPlayer mpFailure = MediaPlayer.create(this, R.raw.error);
+ btnSettings = (Button) findViewById(R.id.btnSettings);
+ activityButtonContainer = (TableLayout) findViewById(R.id.pedestrianActivityButtonContainer);
// log GroundTruth ButtonClicks using sensor number 99
final GroundTruth grndTruth = new GroundTruth(this);
sensors.add(grndTruth);
grndTruth.setListener(new mySensor.SensorListener() {
- @Override public void onData(final String csv) { return; }
- @Override public void onData(SensorType id, final String csv) {add(id, csv); }
+ @Override public void onData(final long timestamp, final String csv) { return; }
+ @Override public void onData(SensorType id, final long timestamp, final String csv) {add(id, csv, timestamp); }
});
@@ -145,7 +142,7 @@ public class MainActivity extends Activity {
grndTruth.writeGroundTruth(groundTruthCounter);
//Write first activity
- add(SensorType.PEDESTRIAN_ACTIVITY, PedestrianActivity.STANDING.toString() + ";" + PedestrianActivity.STANDING.ordinal());
+ add(SensorType.PEDESTRIAN_ACTIVITY, PedestrianActivity.STANDING.toString() + ";" + PedestrianActivity.STANDING.ordinal(), Logger.BEGINNING_TS);
//Disable the spinners
groundSpinner.setEnabled(false);
@@ -154,7 +151,6 @@ public class MainActivity extends Activity {
else{
mpFailure.start();
}
-
}
});
@@ -175,7 +171,7 @@ public class MainActivity extends Activity {
pathSpinner.setEnabled(true);
//reset activity buttons
- setActivityBtn(PedestrianActivity.STANDING);
+ setActivityBtn(PedestrianActivity.STANDING, false);
}
else{
mpFailure.start();
@@ -202,174 +198,28 @@ public class MainActivity extends Activity {
}
});
-
- btnWalk.getLayout().setOnClickListener(new View.OnClickListener() {
- @Override public void onClick(View v) {
- if(isInitialized) {
- setActivityBtn(PedestrianActivity.WALK);
- }
- else{
+ btnSettings.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if(!isInitialized) { // Only allow when not currently running
+ startActivity(new Intent(context, SettingsActivity.class));
+ } else {
mpFailure.start();
}
}
});
-
- btnStand.getLayout().setOnClickListener(new View.OnClickListener() {
- @Override public void onClick(View v) {
- if(isInitialized) {
- setActivityBtn(PedestrianActivity.STANDING);
- }
- else{
- mpFailure.start();
- }
- }
- });
-
- btnStairsUp.getLayout().setOnClickListener(new View.OnClickListener() {
- @Override public void onClick(View v) {
- if(isInitialized) {
- setActivityBtn(PedestrianActivity.STAIRS_UP);
- }
- else{
- mpFailure.start();
- }
- }
- });
-
- btnStairsDown.getLayout().setOnClickListener(new View.OnClickListener() {
- @Override public void onClick(View v) {
- if(isInitialized) {
- setActivityBtn(PedestrianActivity.STAIRS_DOWN);
- }
- else{
- mpFailure.start();
- }
- }
- });
-
- btnElevatorUp.getLayout().setOnClickListener(new View.OnClickListener() {
- @Override public void onClick(View v) {
- if(isInitialized) {
- setActivityBtn(PedestrianActivity.ELEVATOR_UP);
- }
- else{
- mpFailure.start();
- }
- }
- });
-
- btnElevatorDown.getLayout().setOnClickListener(new View.OnClickListener() {
- @Override public void onClick(View v) {
- if(isInitialized) {
- setActivityBtn(PedestrianActivity.ELEVATOR_DOWN);
- }
- else{
- mpFailure.start();
- }
- }
- });
-
- //all Sensors
- final PhoneSensors phoneSensors = new PhoneSensors(this);
- sensors.add(phoneSensors);
- phoneSensors.setListener(new mySensor.SensorListener(){
- @Override public void onData(final String csv) { return; }
- @Override public void onData(final SensorType id, final String csv) {add(id, csv); }
- });
-
- // logo wifi using sensor number 8
-// final WiFi wifi = new WiFi(this);
-// sensors.add(wifi);
-// wifi.setListener(new mySensor.SensorListener() {
-// @Override public void onData(final String csv) { add(SensorType.WIFI, csv); }
-// @Override public void onData(final SensorType id, final String csv) {return; }
-// });
-
- // log wifi RTT using sensor number 17
- final WiFiRTT wifirtt = new WiFiRTT(this);
- sensors.add(wifirtt);
- wifirtt.setListener(new mySensor.SensorListener() {
- @Override public void onData(final String csv) { add(SensorType.WIFIRTT, csv); }
- @Override public void onData(final SensorType id, final String csv) {add(id, csv); }
- });
-
- //log gps using sensor number 16
- final GpsNew gps = new GpsNew(this);
- sensors.add(gps);
- gps.setListener(new mySensor.SensorListener(){
- @Override public void onData(final String csv) { add(SensorType.GPS, csv); }
- @Override public void onData(final SensorType id, final String csv) {return; }
- });
-
- // log iBeacons using sensor number 9
- final mySensor beacon;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- beacon = new iBeacon(this);
- } else{
- beacon = new iBeaconOld(this);
- }
-
- sensors.add(beacon);
- beacon.setListener(new mySensor.SensorListener() {
- @Override public void onData(final String csv) { add(SensorType.IBEACON, csv); }
- @Override public void onData(final SensorType id, final String csv) {return; }
- });
-
-
- // bluetooth permission
- if(ActivityCompat.shouldShowRequestPermissionRationale(this,
- Manifest.permission.ACCESS_FINE_LOCATION)) {
- } else {
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
- MY_PERMISSIONS_REQUEST_READ_BT);
- }
-
- // heartbeat permission
-/* if(ActivityCompat.shouldShowRequestPermissionRationale(this,
- Manifest.permission.BODY_SENSORS)) {
- } else {
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.BODY_SENSORS},
- MY_PERMISSIONS_REQUEST_READ_HEART);
- }*/
-
}
- private void setActivityBtn(PedestrianActivity act){
-
- // set and write new activity
- if(currentPedestrianActivity != act){
-
- // toggle past and current activity
- PedestrianActivity[] tmpActArray = new PedestrianActivity[] {currentPedestrianActivity, act};
-
- for(PedestrianActivity a : tmpActArray){
- switch (a) {
- case WALK: btnWalk.toggleActivity();
- break;
- case STANDING: btnStand.toggleActivity();
- break;
- case STAIRS_UP: btnStairsUp.toggleActivity();
- break;
- case STAIRS_DOWN: btnStairsDown.toggleActivity();
- break;
- case ELEVATOR_UP: btnElevatorUp.toggleActivity();
- break;
- case ELEVATOR_DOWN: btnElevatorDown.toggleActivity();
- break;
- default:
- break;
- }
- }
-
- currentPedestrianActivity = act;
- add(SensorType.PEDESTRIAN_ACTIVITY, act.toString() + ";" + act.ordinal());
- } else {
- //do nothin
+ private void setActivityBtn(PedestrianActivity newActivity, boolean logChange){
+ if(activityButtons.containsKey(currentPedestrianActivity)) {
+ activityButtons.get(currentPedestrianActivity).setActivity(false);
+ }
+ currentPedestrianActivity = newActivity;
+ activityButtons.get(newActivity).setActivity(true);
+ if(logChange) {
+ add(SensorType.PEDESTRIAN_ACTIVITY, newActivity.toString() + ";" + newActivity.ordinal());
}
-
}
private void start() {
@@ -395,31 +245,45 @@ public class MainActivity extends Activity {
private int loadCounterGPS = 0;
private int loadCounterAny = 0;
private void add(final SensorType id, final String csv) {
+ add(id, csv, SystemClock.elapsedRealtimeNanos());
+ }
+ private void add(final SensorType id, final String csv, final long timestamp) {
- logger.addCSV(id, csv);
+ logger.addCSV(id, timestamp, csv);
- runOnUiThread(new Runnable() {
- @Override public void run() {
- if (id == SensorType.WIFI) {
- final TextView txt = (TextView) findViewById(R.id.txtWifi);
- txt.setText( ((++loadCounterWifi % 2) == 0) ? "wi" : "WI");
- } else if (id == SensorType.IBEACON){
- final TextView txt = (TextView) findViewById(R.id.txtBeacon);
- txt.setText( ((++loadCounterBeacon % 2) == 0) ? "ib" : "IB");
- } else if (id == SensorType.GPS){
- final TextView txt = (TextView) findViewById(R.id.txtGPS);
- txt.setText( ((++loadCounterGPS % 2) == 0) ? "gps" : "GPS");}
+ // update UI for WIFI/BEACON/GPS
+ if (id == SensorType.WIFI || id == SensorType.IBEACON || id == SensorType.GPS) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
- // dump buffer stats every x entries
- if (++loadCounterAny % 250 == 0) {
- final TextView txt = (TextView) findViewById(R.id.txtBuffer);
- final int kbPerMin = (int) (logger.getTotalSize() / 1024 * 1000 * 60 / (System.currentTimeMillis() - logger.getStartTS()));
- txt.setText( (logger.getCurrentSize() / 1024) + "k, " + logger.getNumEntries() + ", " + kbPerMin + "k/m");
+ if (id == SensorType.WIFI) {
+ final TextView txt = (TextView) findViewById(R.id.txtWifi);
+ txt.setText(((++loadCounterWifi % 2) == 0) ? "wi" : "WI");
+ } else if (id == SensorType.IBEACON) {
+ final TextView txt = (TextView) findViewById(R.id.txtBeacon);
+ txt.setText(((++loadCounterBeacon % 2) == 0) ? "ib" : "IB");
+ } else if (id == SensorType.GPS) {
+ final TextView txt = (TextView) findViewById(R.id.txtGPS);
+ txt.setText(((++loadCounterGPS % 2) == 0) ? "gps" : "GPS");
+ }
}
+ });
+ }
- }
- });
+ // dump buffer stats every x entries
+ if (++loadCounterAny % 250 == 0) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final TextView txt = (TextView) findViewById(R.id.txtBuffer);
+ final float elapsedMinutes = (timestamp - logger.getStartTS()) / 1000.0f / 1000.0f / 1000.0f / 60.0f;
+ final int kBPerMin = (int) (logger.getTotalSize() / 1024.0f / elapsedMinutes);
+ txt.setText((logger.getCurrentBufferSize() / 1024) + "k, " + logger.getNumEntries() + ", " + kBPerMin + "kB/m");
+ }
+ });
+ }
}
@@ -429,11 +293,20 @@ public class MainActivity extends Activity {
super.onPause();
}
+ protected void onStart() {
+ super.onStart();
+ if(!isInitialized) {
+ // Do not apply new settings when recording is currently running, since we can't have come
+ // from the SettingsActivity, then.
+ setupActivityButtons();
+ setupSensors();
+ }
+ }
+
/** resume activity */
protected void onResume() {
super.onResume();
-
//print memory info
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
@@ -468,4 +341,151 @@ public class MainActivity extends Activity {
return MainActivity.context;
}
+
+
+
+
+
+ protected void setupActivityButtons() {
+ // cleanup before recreation
+ for(int i = 0; i < activityButtonContainer.getChildCount(); ++i) {
+ TableRow buttonRow = (TableRow)activityButtonContainer.getChildAt(i);
+ buttonRow.removeAllViews();
+ }
+ activityButtonContainer.removeAllViews();
+ activityButtons.clear();
+
+ // setup activity buttons
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ Set activeActivities = preferences.getStringSet("prefActiveActions", new HashSet());
+
+ activityButtons.put(PedestrianActivity.STANDING, new PedestrianActivityButton(this, PedestrianActivity.STANDING, R.drawable.ic_standing));
+ if(activeActivities.contains("WALK")) {
+ activityButtons.put(PedestrianActivity.WALK, new PedestrianActivityButton(this, PedestrianActivity.WALK, R.drawable.ic_walk));
+ }
+ if(activeActivities.contains("ELEVATOR")) {
+ activityButtons.put(PedestrianActivity.ELEVATOR_UP, new PedestrianActivityButton(this, PedestrianActivity.ELEVATOR_UP, R.drawable.ic_elevator_up));
+ activityButtons.put(PedestrianActivity.ELEVATOR_DOWN, new PedestrianActivityButton(this, PedestrianActivity.ELEVATOR_DOWN, R.drawable.ic_elevator_down));
+ }
+ if(activeActivities.contains("STAIRS")) {
+ activityButtons.put(PedestrianActivity.STAIRS_UP, new PedestrianActivityButton(this, PedestrianActivity.STAIRS_UP, R.drawable.ic_stairs_up));
+ activityButtons.put(PedestrianActivity.STAIRS_DOWN, new PedestrianActivityButton(this, PedestrianActivity.STAIRS_DOWN, R.drawable.ic_stairs_down));
+ }
+ if(activeActivities.contains("MESS_AROUND")) {
+ activityButtons.put(PedestrianActivity.MESS_AROUND, new PedestrianActivityButton(this, PedestrianActivity.MESS_AROUND, R.drawable.ic_mess_around));
+ }
+ int activityButtonColumns = 1;
+ if(activityButtons.size() > 6) { activityButtonColumns = 4; }
+ else if(activityButtons.size() > 4) { activityButtonColumns = 3; }
+ else if(activityButtons.size() > 2) { activityButtonColumns = 2; }
+
+ TableLayout.LayoutParams rowLayout = new TableLayout.LayoutParams();
+ rowLayout.width = LayoutParams.MATCH_PARENT;
+ rowLayout.height = LayoutParams.WRAP_CONTENT;
+ rowLayout.weight = 1.0f;
+ TableRow.LayoutParams columnLayout = new TableRow.LayoutParams();
+ columnLayout.height = LayoutParams.MATCH_PARENT;
+ columnLayout.width = 1; // set minWidth to 1, because this will be stretched, and the images adjust in size
+ columnLayout.weight = 1.0f;
+ PedestrianActivity[] activeActiviesArray = activityButtons.keySet().toArray(new PedestrianActivity[activityButtons.size()]);
+ Arrays.sort(activeActiviesArray);
+ TableRow currentButtonRow = null;
+ for(int i = 0; i < activeActiviesArray.length; ++i) {
+ final PedestrianActivityButton button = activityButtons.get(activeActiviesArray[i]);
+ if(i % activityButtonColumns == 0) {
+ currentButtonRow = new TableRow(this);
+ currentButtonRow.setWeightSum(1.0f * activityButtonColumns);
+ activityButtonContainer.addView(currentButtonRow, rowLayout);
+ }
+ currentButtonRow.addView(button, columnLayout);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if(isInitialized) {
+ setActivityBtn(button.getPedestrianActivity(), true);
+ }
+ else{
+ mpFailure.start();
+ }
+ }
+ });
+ }
+
+ //set current activity
+ setActivityBtn(PedestrianActivity.STANDING, false);
+ }
+
+ protected void setupSensors() {
+ //cleanup first
+ sensors.clear();
+
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ Set activeSensors = preferences.getStringSet("prefActiveSensors", new HashSet());
+
+ if(activeSensors.contains("PHONE")) {
+ // heartbeat permission
+ if(ActivityCompat.shouldShowRequestPermissionRationale(this,
+ Manifest.permission.BODY_SENSORS)) {
+ } else {
+ ActivityCompat.requestPermissions(this,
+ new String[]{Manifest.permission.BODY_SENSORS},
+ MY_PERMISSIONS_REQUEST_READ_HEART);
+ }
+
+ //all Phone-Sensors (Accel, Gyro, Magnet, ...)
+ final PhoneSensors phoneSensors = new PhoneSensors(this);
+ sensors.add(phoneSensors);
+ phoneSensors.setListener(new mySensor.SensorListener(){
+ @Override public void onData(final long timestamp, final String csv) { return; }
+ @Override public void onData(final SensorType id, final long timestamp, final String csv) {add(id, csv, timestamp); }
+ });
+ }
+ if(activeSensors.contains("GPS")) {
+ //log gps using sensor number 16
+ final GpsNew gps = new GpsNew(this);
+ sensors.add(gps);
+ gps.setListener(new mySensor.SensorListener(){
+ @Override public void onData(final long timestamp, final String csv) { add(SensorType.GPS, csv, timestamp); }
+ @Override public void onData(final SensorType id, final long timestamp, final String csv) {return; }
+ });
+ }
+ if(activeSensors.contains("WIFI")) {
+ // log wifi using sensor number 8
+ final WiFi wifi = new WiFi(this);
+ sensors.add(wifi);
+ wifi.setListener(new mySensor.SensorListener() {
+ @Override public void onData(final long timestamp, final String csv) { add(SensorType.WIFI, csv, timestamp); }
+ @Override public void onData(final SensorType id, final long timestamp, final String csv) {return; }
+ });
+ }
+ if(activeSensors.contains("BLUETOOTH")) {
+ // bluetooth permission
+ if(ActivityCompat.shouldShowRequestPermissionRationale(this,
+ Manifest.permission.ACCESS_FINE_LOCATION)) {
+ } else {
+ ActivityCompat.requestPermissions(this,
+ new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
+ MY_PERMISSIONS_REQUEST_READ_BT);
+ }
+
+ // log iBeacons using sensor number 9
+ final mySensor beacon;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ beacon = new iBeacon(this);
+ } else {
+ beacon = null;
+ //beacon = new iBeaconOld(this);
+ }
+
+ if (beacon != null) {
+ sensors.add(beacon);
+ beacon.setListener(new mySensor.SensorListener() {
+ @Override public void onData(final long timestamp, final String csv) { add(SensorType.IBEACON, csv, timestamp); }
+ @Override public void onData(final SensorType id, final long timestamp, final String csv) {return; }
+ });
+ }
+ }
+ }
+
+
}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/SettingsActivity.java b/app/src/main/java/de/fhws/indoor/sensorreadout/SettingsActivity.java
new file mode 100644
index 0000000..4bcc46f
--- /dev/null
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/SettingsActivity.java
@@ -0,0 +1,14 @@
+package de.fhws.indoor.sensorreadout;
+
+import android.preference.PreferenceManager;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+
+public class SettingsActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
+ }
+}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/SettingsFragment.java b/app/src/main/java/de/fhws/indoor/sensorreadout/SettingsFragment.java
new file mode 100644
index 0000000..18f185c
--- /dev/null
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/SettingsFragment.java
@@ -0,0 +1,16 @@
+package de.fhws.indoor.sensorreadout;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+import android.support.annotation.Nullable;
+
+public class SettingsFragment extends PreferenceFragment {
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.preferences);
+ }
+
+}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Gps.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Gps.java
index eec513f..63b71d7 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Gps.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Gps.java
@@ -85,7 +85,7 @@ public class Gps extends mySensor implements LocationListener {
// inform listeners
if (listener != null){
- listener.onData(SensorType.GRAVITY,
+ listener.onData(SensorType.GRAVITY, location.getElapsedRealtimeNanos(), //TODO: Is this correct? SystemClock.elapsedRealtimeNanos() otherwise..
Double.toString(location.getLatitude()) + ";" +
Double.toString(location.getLongitude()) + ";" +
Double.toString(location.getAltitude()) + ";" +
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GpsNew.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GpsNew.java
index f969c03..bf085de 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GpsNew.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GpsNew.java
@@ -169,7 +169,7 @@ public class GpsNew extends mySensor implements ConnectionCallbacks, OnConnectio
// inform listeners
if (listener != null){
- listener.onData(SensorType.GRAVITY,
+ listener.onData(SensorType.GRAVITY, location.getElapsedRealtimeNanos(), //TODO: Is this correct? SystemClock.elapsedRealtimeNanos() otherwise..
Double.toString(location.getLatitude()) + ";" +
Double.toString(location.getLongitude()) + ";" +
Double.toString(location.getAltitude()) + ";" +
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java
index e1e7143..97c1ef8 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/GroundTruth.java
@@ -1,6 +1,7 @@
package de.fhws.indoor.sensorreadout.sensors;
import android.app.Activity;
+import android.os.SystemClock;
/**
* Created by Toni on 02.06.2015.
@@ -12,14 +13,14 @@ public class GroundTruth extends mySensor {
}
public void writeGroundTruth(final int groundTruthCounter){
- if (listener != null){listener.onData(SensorType.GROUND_TRUTH,
+ if (listener != null){listener.onData(SensorType.GROUND_TRUTH, SystemClock.elapsedRealtimeNanos(),
Integer.toString(groundTruthCounter)
);}
}
public void writeInitData(int pathID, int numGroundTruthPoints){
- if (listener != null){listener.onData(SensorType.GROUND_TRUTH_PATH,
+ if (listener != null){listener.onData(SensorType.GROUND_TRUTH_PATH, SystemClock.elapsedRealtimeNanos(),
Integer.toString(pathID) + ";" +
Integer.toString(numGroundTruthPoints)
);}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java
index 4b363ae..264f1a8 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/Logger.java
@@ -2,27 +2,41 @@ package de.fhws.indoor.sensorreadout.sensors;
import android.content.Context;
import android.os.AsyncTask;
+import android.os.SystemClock;
+import android.support.annotation.NonNull;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.PriorityQueue;
+import java.util.concurrent.Semaphore;
/**
* log sensor data to file
* Created by Frank on 25.03.2015.
+ * Re-Written by Markus on 20.06.2019.
*/
public final class Logger {
- private static final int FLUSH_LIMIT = 2*1024*1024;
+ public static final long BEGINNING_TS = -1;
- private StringBuilder sb = new StringBuilder();
+ private static final int CACHED_ENTRIES = 1000;
+ private static final int FLUSH_BATCH_SIZE = 100;
+
+ private StringBuilder stringBuilder = new StringBuilder();
private File file;
private FileOutputStream fos;
private Context context;
private int entries = 0;
- private int sizeCurrent = 0;
private int sizeTotal = 0;
+ private int currentSize = 0;
+
+ private volatile boolean addingStopped = false; // Just to be sure
+ private PriorityQueue reorderBuffer = new PriorityQueue<>(2 * CACHED_ENTRIES + FLUSH_BATCH_SIZE);
+ private Semaphore flushSemaphore = new Semaphore(0);
+ private WriteBackWorker writeBackWorker;
/** timestamp of logging start. all entries are relative to this one */
private long startTS = 0;
@@ -35,13 +49,15 @@ public final class Logger {
public final void start() {
// start empty
- sb.setLength(0);
+ stringBuilder.setLength(0);
entries = 0;
sizeTotal = 0;
- sizeCurrent = 0;
+ addingStopped = false;
+ flushSemaphore.drainPermits();
+ writeBackWorker = new WriteBackWorker();
// starting timestamp
- startTS = System.currentTimeMillis();
+ startTS = SystemClock.elapsedRealtimeNanos();
// open the output-file immeditaly (to get permission errors)
// but do NOT yet write anything to the file
@@ -54,88 +70,68 @@ public final class Logger {
} catch (final Exception e) {
throw new MyException("error while opening log-file", e);
}
-
+ writeBackWorker.start();
}
/** stop logging and flush RAM-data to the flash-chip */
public final void stop() {
- synchronized (this) {
- flush(true);
- close();
+ debug(true);
+ synchronized (reorderBuffer) {
+ addingStopped = true;
+ // Unblock WriteBackThread for all remaining log-lines (+1)
+ // some elements in reorderBuffer could already have been released for flushing -> this might release more than necessary.
+ flushSemaphore.release(reorderBuffer.size() + 1);
}
+ // wait for flushing to succeed
+ try {
+ writeBackWorker.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ debug(true);
+ close();
}
public File getFile() {
return file;
}
- public int getCurrentSize() {return sizeCurrent;}
+ public int getCurrentBufferSize() {return currentSize;}
public int getTotalSize() {return sizeTotal;}
public int getNumEntries() {return entries;}
/** add a new CSV entry for the given sensor number to the internal buffer */
- public final void addCSV(final SensorType sensorNr, final String csv) {
- synchronized (this) {
- final long relTS = System.currentTimeMillis() - startTS;
- sb.append(relTS); // relative timestamp (uses less space)
- sb.append(';');
- sb.append(sensorNr.id());
- sb.append(';');
- sb.append(csv);
- sb.append('\n');
- ++entries;
- sizeTotal += csv.length() + 10; // approx!
- sizeCurrent = sb.length();
- if (sb.length() > FLUSH_LIMIT) {flush(false);}
+ public final void addCSV(final SensorType sensorNr, final long timestamp, final String csv) {
+ final long relTS = (timestamp == BEGINNING_TS) ? 0 : (timestamp - startTS);
+ if(relTS >= 0) { // drop pre startTS logs (at the beginning, sensors sometimes deliver old values)
+ synchronized (reorderBuffer) {
+ if(addingStopped) {
+ // addCSV was called after calling stop();
+ return;
+ }
+
+ stringBuilder.append(relTS); // relative timestamp (uses less space)
+ stringBuilder.append(';');
+ stringBuilder.append(sensorNr.id());
+ stringBuilder.append(';');
+ stringBuilder.append(csv);
+ stringBuilder.append('\n');
+ ++entries;
+ LogEntry logEntry = new LogEntry(relTS, stringBuilder.toString());
+ sizeTotal += logEntry.csv.length();
+ currentSize += logEntry.csv.length();
+ stringBuilder.setLength(0);
+
+ // commit to reorder-buffer and start flush (if necessary)
+ reorderBuffer.add(logEntry);
+ if(flushSemaphore.availablePermits() == 0 && reorderBuffer.size() > (CACHED_ENTRIES + FLUSH_BATCH_SIZE)) {
+ // Unblock WriteBackThread and allow it to flush FLUSH_BATCH_SIZE csv-lines.
+ flushSemaphore.release(reorderBuffer.size() - CACHED_ENTRIES);
+ }
+ }
}
-
- debug();
- }
-
-
-
- /** helper method for exception-less writing. DO NOT CALL DIRECTLY! */
- private final void _write(final byte[] data) {
- try {
- fos.write(data);
- Log.d("logger", "flushed " + data.length + " bytes to disk");
- } catch (final Exception e) {
- throw new RuntimeException("error while writing log-file", e);
- }
- }
-
- /** helper-class for background writing */
- class FlushAsync extends AsyncTask {
- @Override
- protected final Integer doInBackground(byte[][] data) {
- _write(data[0]);
- return null;
- }
- };
-
- /** flush current buffer-contents to disk */
- private final void flush(boolean sync) {
-
- // fetch current buffer contents to write and hereafter empty the buffer
- // this action MUST be atomic, just like the add-method
- byte[] data = null;
- synchronized (this) {
- data = sb.toString().getBytes(); // fetch data to write
- sb.setLength(0); // reset the buffer
- sizeCurrent = 0;
- }
-
- // write
- if (sync) {
- // write to disk using the current thread
- _write(data);
- } else {
- // write to disk using a background-thread
- new FlushAsync().execute(new byte[][] {data});
- }
-
-
+ debug(false);
}
private final void close() {
@@ -151,10 +147,67 @@ public final class Logger {
}
int cnt = 0;
- private final void debug() {
- if (++cnt % 1000 == 0) {
- Log.d("buffer", "size: " + sizeCurrent);
+ private final void debug(boolean force) {
+ if (++cnt % 1000 == 0 || force) {
+ Log.d("buffer", "size: " + reorderBuffer.size() + " lines");
}
}
+
+
+ private static class LogEntry implements Comparable {
+ public long timestamp;
+ public String csv;
+
+ public LogEntry(long timestamp, String csv) {
+ this.timestamp = timestamp;
+ this.csv = csv;
+ }
+
+ @Override
+ public int compareTo(@NonNull LogEntry another) {
+ return (timestamp < another.timestamp) ? (-1) : (+1);
+ }
+ }
+
+ private class WriteBackWorker extends Thread {
+
+ public WriteBackWorker() {
+ setName("WriteBackWorker");
+ setPriority(Thread.MIN_PRIORITY);
+ }
+
+ @Override
+ public void run() {
+ try {
+ boolean stop = false;
+ while(!stop) {
+ flushSemaphore.acquireUninterruptibly();
+
+ LogEntry[] entriesToFlush = null;
+ synchronized (reorderBuffer) {
+ int flushBatchSize = 1 + flushSemaphore.drainPermits(); // might contain extra-permit for stop-unblocking
+ if(flushBatchSize > reorderBuffer.size()) { // We were unblocked more than there are available lines to fush -> request to flush all & stop
+ stop = true;
+ flushBatchSize = reorderBuffer.size();
+ }
+ entriesToFlush = new LogEntry[flushBatchSize];
+
+ for(int i = 0; i < flushBatchSize; ++i) {
+ entriesToFlush[i] = reorderBuffer.poll();
+ currentSize -= entriesToFlush[i].csv.length();
+ }
+ }
+
+ for(int i = 0; i < entriesToFlush.length; ++i) {
+ fos.write(entriesToFlush[i].csv.getBytes());
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+
}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/LoggerRAM.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/LoggerRAM.java
new file mode 100644
index 0000000..417b298
--- /dev/null
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/LoggerRAM.java
@@ -0,0 +1,171 @@
+package de.fhws.indoor.sensorreadout.sensors;
+
+import android.content.Context;
+import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * log sensor data to RAM
+ * only flush to file when finished
+ */
+public final class LoggerRAM {
+
+ public static final long BEGINNING_TS = -1;
+
+
+ private StringBuilder stringBuilder = new StringBuilder();
+ private File file;
+ private FileOutputStream fos;
+ private Context context;
+
+ private boolean addingStopped = false;
+ private int entries = 0;
+ private int sizeTotal = 0;
+ private int currentSize = 0;
+
+ private ArrayList buffer = new ArrayList<>();
+
+ /** timestamp of logging start. all entries are relative to this one */
+ private long startTS = 0;
+
+ public LoggerRAM(Context context) {
+ this.context = context;
+ }
+
+ /** start logging (into RAM) */
+ public final void start() {
+
+ // start empty
+ stringBuilder.setLength(0);
+ entries = 0;
+ sizeTotal = 0;
+ currentSize = 0;
+ buffer.clear();
+ addingStopped = false;
+
+ // starting timestamp
+ startTS = SystemClock.elapsedRealtimeNanos();
+
+ // open the output-file immeditaly (to get permission errors)
+ // but do NOT yet write anything to the file
+ final DataFolder folder = new DataFolder(context, "sensorOutFiles");
+ file = new File(folder.getFolder(), startTS + ".csv");
+
+ try {
+ fos = new FileOutputStream(file);
+ Log.d("logger", "will write to: " + file.toString());
+ } catch (final Exception e) {
+ throw new MyException("error while opening log-file", e);
+ }
+
+ }
+
+ /** stop logging and flush RAM-data to the flash-chip */
+ public final void stop() {
+
+ addingStopped = true;
+
+ synchronized (buffer) {
+
+ // sort by TS (ensure strict ordering)
+ Collections.sort(buffer);
+
+ // export each entry
+ for (LogEntry e : buffer) {
+ try {
+ fos.write(e.csv.getBytes());
+ } catch (final Exception ex) {
+ ex.printStackTrace();;
+ }
+ }
+
+ // done
+ buffer.clear();
+
+ }
+
+ // done
+ close();
+
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public int getCurrentBufferSize() {return currentSize;}
+ public int getTotalSize() {return sizeTotal;}
+
+ public int getNumEntries() {return entries;}
+
+ /** add a new CSV entry for the given sensor number to the internal buffer */
+ public final void addCSV(final SensorType sensorNr, final long timestamp, final String csv) {
+
+ if (addingStopped) {return;}
+
+ final long relTS = (timestamp == BEGINNING_TS) ? 0 : (timestamp - startTS);
+ if(relTS >= 0) { // drop pre startTS logs (at the beginning, sensors sometimes deliver old values)
+
+ stringBuilder.setLength(0);
+ stringBuilder.append(relTS); // relative timestamp (uses less space)
+ stringBuilder.append(';');
+ stringBuilder.append(sensorNr.id());
+ stringBuilder.append(';');
+ stringBuilder.append(csv);
+ stringBuilder.append('\n');
+ ++entries;
+ LogEntry logEntry = new LogEntry(relTS, stringBuilder.toString());
+ sizeTotal += logEntry.csv.length();
+ currentSize += logEntry.csv.length();
+
+ synchronized (buffer) {
+ buffer.add(logEntry);
+ }
+
+ }
+
+ }
+
+ private final void close() {
+ try {
+ fos.close();
+ } catch (final Exception e) {
+ throw new MyException("error while writing log-file", e);
+ }
+ }
+
+ public final long getStartTS() {
+ return startTS;
+ }
+
+ int cnt = 0;
+ private final void debug(boolean force) {
+ if (++cnt % 1000 == 0 || force) {
+ Log.d("buffer", "size: " + buffer.size() + " lines");
+ }
+ }
+
+
+
+ private static class LogEntry implements Comparable {
+ public long timestamp;
+ public String csv;
+
+ public LogEntry(long timestamp, String csv) {
+ this.timestamp = timestamp;
+ this.csv = csv;
+ }
+
+ @Override
+ public int compareTo(@NonNull LogEntry another) {
+ return (timestamp < another.timestamp) ? (-1) : (+1);
+ }
+ }
+
+}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivity.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivity.java
index 1e7042b..0fc4291 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivity.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivity.java
@@ -12,6 +12,7 @@ public enum PedestrianActivity {
STAIRS_DOWN(3),
ELEVATOR_UP(4),
ELEVATOR_DOWN(5),
+ MESS_AROUND(6),
;
private int id;
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivityButton.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivityButton.java
index 288732f..7d13aab 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivityButton.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PedestrianActivityButton.java
@@ -1,35 +1,45 @@
package de.fhws.indoor.sensorreadout.sensors;
+import android.content.Context;
import android.graphics.Color;
+import android.support.annotation.DrawableRes;
import android.view.View;
+import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import de.fhws.indoor.sensorreadout.R;
/**
* Created by toni on 10/01/18.
+ * Extended by Markus on 19/06/19
*/
-public class PedestrianActivityButton {
+public class PedestrianActivityButton extends LinearLayout {
- private LinearLayout btn;
- private boolean isActivated = false;
- private PedestrianActivity whatActivity;
+ private LinearLayout innerBtn;
+ private boolean isActive = false;
+ private PedestrianActivity activity;
- public PedestrianActivityButton(LinearLayout btn, PedestrianActivity act){
- this.btn = btn;
- this.whatActivity = act;
+ public PedestrianActivityButton(Context context, PedestrianActivity activity, @DrawableRes int imageId) {
+ super(context);
+ inflate(getContext(), R.layout.pedestrian_activity_button, this);
+ this.activity = activity;
+ // setup ui
+ ImageView imageView = (ImageView)this.findViewById(R.id.activityButtonImage);
+ imageView.setImageResource(imageId);
+ TextView textView = (TextView)this.findViewById(R.id.activityButtonText);
+ textView.setText(activity.toString());
+ innerBtn = (LinearLayout)getChildAt(0);
+ setActivity(false);
}
- public void toggleActivity(){
- isActivated = !isActivated;
-
- if(isActivated){
- btn.setBackgroundColor(Color.parseColor("#F9D737"));
- } else {
- btn.setBackgroundColor(Color.parseColor("#B2B2B2"));
- }
+ public void setActivity(boolean active) {
+ this.isActive = active;
+ innerBtn.setBackgroundColor(Color.parseColor(
+ (isActive) ? "#F9D737" : "#B2B2B2"
+ ));
}
- public LinearLayout getLayout(){
- return btn;
- }
+ public PedestrianActivity getPedestrianActivity() { return this.activity; }
}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java
index 0103455..ebd04e9 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/PhoneSensors.java
@@ -39,6 +39,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
private Sensor rotationVector;
private Sensor light;
private Sensor temperature;
+ private Sensor gameRotationVector;
/** local gravity copy (needed for orientation matrix) */
private float[] mGravity = new float[3];
@@ -65,6 +66,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
rotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
light = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
temperature = sensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
+ gameRotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
// dump sensor-vendor info to file
dumpVendors(act);
@@ -102,6 +104,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
dumpSensor(sb, SensorType.LIGHT, light);
dumpSensor(sb, SensorType.AMBIENT_TEMPERATURE, temperature);
dumpSensor(sb, SensorType.HEART_RATE, heart);
+ dumpSensor(sb, SensorType.GAME_ROTATION_VECTOR, gameRotationVector);
// write
fos.write(sb.toString().getBytes());
@@ -139,13 +142,12 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
@Override
public void onSensorChanged(SensorEvent event) {
- /*
// to compare with the other orientation
if(event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
// inform listeners
if (listener != null){
- listener.onData(SensorType.ORIENTATION_OLD,
+ listener.onData(SensorType.ORIENTATION_OLD, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
Float.toString(event.values[2])
@@ -153,13 +155,12 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
}
}
- */
if(event.sensor.getType() == Sensor.TYPE_HEART_RATE) {
// inform listeners
if (listener != null){
- listener.onData(SensorType.HEART_RATE,
+ listener.onData(SensorType.HEART_RATE, event.timestamp,
Float.toString(event.values[0])
);
}
@@ -170,7 +171,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.LIGHT,
+ listener.onData(SensorType.LIGHT, event.timestamp,
Float.toString(event.values[0])
);
}
@@ -181,7 +182,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.AMBIENT_TEMPERATURE,
+ listener.onData(SensorType.AMBIENT_TEMPERATURE, event.timestamp,
Float.toString(event.values[0])
);
}
@@ -192,7 +193,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.RELATIVE_HUMIDITY,
+ listener.onData(SensorType.RELATIVE_HUMIDITY, event.timestamp,
Float.toString(event.values[0])
);
}
@@ -205,14 +206,14 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
if (listener != null){
if(event.values.length > 3){
- listener.onData(SensorType.ROTATION_VECTOR,
+ listener.onData(SensorType.ROTATION_VECTOR, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
Float.toString(event.values[2]) + ";" +
Float.toString(event.values[3])
);
} else {
- listener.onData(SensorType.ROTATION_VECTOR,
+ listener.onData(SensorType.ROTATION_VECTOR, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
Float.toString(event.values[2])
@@ -227,7 +228,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.GYROSCOPE,
+ listener.onData(SensorType.GYROSCOPE, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
Float.toString(event.values[2])
@@ -240,7 +241,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.PRESSURE,
+ listener.onData(SensorType.PRESSURE, event.timestamp,
Float.toString(event.values[0])
);
}
@@ -251,10 +252,10 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.LINEAR_ACCELERATION,
+ listener.onData(SensorType.LINEAR_ACCELERATION, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
- Float.toString(event.values[2]) + ";"
+ Float.toString(event.values[2])
);
}
@@ -264,7 +265,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.GRAVITY,
+ listener.onData(SensorType.GRAVITY, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
Float.toString(event.values[2])
@@ -277,7 +278,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.ACCELEROMETER,
+ listener.onData(SensorType.ACCELEROMETER, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
Float.toString(event.values[2])
@@ -297,7 +298,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// inform listeners
if (listener != null){
- listener.onData(SensorType.MAGNETIC_FIELD,
+ listener.onData(SensorType.MAGNETIC_FIELD, event.timestamp,
Float.toString(event.values[0]) + ";" +
Float.toString(event.values[1]) + ";" +
Float.toString(event.values[2])
@@ -310,14 +311,25 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
// NOTE
// @see TYPE_ACCELEROMETER
// only MAG updates the current orientation as MAG is usually slower than ACC and this reduces the file-footprint
- updateOrientation();
+ updateOrientation(event.timestamp);
}
+ else if(event.sensor.getType() == Sensor.TYPE_GAME_ROTATION_VECTOR) {
+ // inform listeners
+ if (listener != null) {
+ listener.onData(SensorType.GAME_ROTATION_VECTOR, event.timestamp,
+ Float.toString(event.values[0]) + ";" +
+ Float.toString(event.values[1]) + ";" +
+ Float.toString(event.values[2])
+ );
+ }
+ }
+
}
/** calculate orientation from acc and mag */
- private void updateOrientation() {
+ private void updateOrientation(long timestamp) {
// skip orientation update if either grav or geo is missing
if (mGravity == null) {return;}
@@ -339,7 +351,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
if (listener != null) {
// orientation vector
- listener.onData(SensorType.ORIENTATION_NEW,
+ listener.onData(SensorType.ORIENTATION_NEW, timestamp,
Float.toString(orientationNew[0]) + ";" +
Float.toString(orientationNew[1]) + ";" +
Float.toString(orientationNew[2])
@@ -358,7 +370,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
sb.append(R[8]);
//Write the whole rotationMatrix R into the Listener.
- listener.onData(SensorType.ROTATION_MATRIX, sb.toString());
+ listener.onData(SensorType.ROTATION_MATRIX, timestamp, sb.toString());
// Float.toString(R[0]) + ";" +
// Float.toString(R[1]) + ";" +
@@ -403,6 +415,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{
registerIfPresent(rotationVector, SensorManager.SENSOR_DELAY_FASTEST);
registerIfPresent(light, SensorManager.SENSOR_DELAY_FASTEST);
registerIfPresent(temperature, SensorManager.SENSOR_DELAY_FASTEST);
+ registerIfPresent(gameRotationVector, SensorManager.SENSOR_DELAY_FASTEST);
}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java
index d458d90..4a7830b 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/SensorType.java
@@ -23,6 +23,7 @@ public enum SensorType {
HEART_RATE(15),
GPS(16),
WIFIRTT(17),
+ GAME_ROTATION_VECTOR(18),
PEDESTRIAN_ACTIVITY(50),
GROUND_TRUTH(99),
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java
index cce8c67..e0d57d1 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFi.java
@@ -23,6 +23,7 @@ public class WiFi extends mySensor {
private final WifiManager wifi;
private BroadcastReceiver receiver;
private boolean isReceiverRegistered;
+ private boolean isFirstMeasurement = true;
public WiFi(final Activity act) {
@@ -40,15 +41,29 @@ public class WiFi extends mySensor {
this.receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- final StringBuilder sb = new StringBuilder(1024);
- final List res = wifi.getScanResults();
- for (final ScanResult sr : res) {
- sb.append(Helper.stripMAC(sr.BSSID)).append(';');
- sb.append(sr.frequency).append(';');
- sb.append(sr.level).append(';');
- }
- if (listener != null && isReceiverRegistered) {
- listener.onData(sb.toString());
+
+ // ignore the first measurement
+ if (isFirstMeasurement) {
+ isFirstMeasurement = false;
+ } else {
+ final StringBuilder sb = new StringBuilder(1024);
+ final List res = wifi.getScanResults();
+ long timestamp = 0;
+ for (final ScanResult sr : res) {
+ sb.append(Helper.stripMAC(sr.BSSID)).append(';');
+ sb.append(sr.frequency).append(';');
+ sb.append(sr.level).append(';');
+
+ // export with oldest timestamp among all contained measurements
+ final long nanos = sr.timestamp * 1000;
+ if (nanos > timestamp) {
+ timestamp = nanos;
+ }
+
+ }
+ if (listener != null && isReceiverRegistered) {
+ listener.onData(timestamp, sb.toString());
+ }
}
startScan();
//Log.d("wifi", sb.toString());
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java
index ea57e86..c6b2a1c 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java
@@ -152,7 +152,7 @@ public class WiFiRTT extends mySensor {
sb.append(numSuccessfulMeas);
- listener.onData(SensorType.WIFIRTT, sb.toString());
+ listener.onData(SensorType.WIFIRTT,res.getRangingTimestampMillis()*1000, sb.toString());
}
}
}
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java
index 3cc2017..9b78cdf 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeacon.java
@@ -20,7 +20,7 @@ public class iBeacon extends mySensor {
private static final int REQUEST_ENABLE_BT = 1;
private ScanCallback mLeScanCallback;
- /** ctor */
+ // ctor
public iBeacon(final Activity act) {
// sanity check
@@ -48,7 +48,7 @@ public class iBeacon extends mySensor {
@Override public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) {
//Log.d("BT", device + " " + rssi);
if (listener != null) {
- listener.onData(Helper.stripMAC(result.getDevice().getAddress()) + ";" + result.getRssi() + ";" + result.getScanRecord().getTxPowerLevel());
+ listener.onData(result.getTimestampNanos(), Helper.stripMAC(result.getDevice().getAddress()) + ";" + result.getRssi() + ";" + result.getScanRecord().getTxPowerLevel());
}
}
};
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java
index 725c9fd..b190e7a 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/iBeaconOld.java
@@ -8,19 +8,20 @@ import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.os.SystemClock;
import android.widget.Toast;
/**
* Created by toni on 02/06/16.
*/
-
+/*
public class iBeaconOld extends mySensor {
private BluetoothAdapter bt = null;
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter.LeScanCallback mLeScanCallback;
- /** ctor */
+ // ctor
public iBeaconOld(final Activity act) {
// sanity check
@@ -45,7 +46,7 @@ public class iBeaconOld extends mySensor {
@Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
//Log.d("BT", device + " " + rssi);
if (listener != null) {
- listener.onData(Helper.stripMAC(device.getAddress()) + ";" + rssi);
+ listener.onData(SystemClock.elapsedRealtimeNanos(), Helper.stripMAC(device.getAddress()) + ";" + rssi);
}
}
};
@@ -69,3 +70,4 @@ public class iBeaconOld extends mySensor {
}
}
+*/
diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java
index f3c8381..015eb39 100644
--- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java
+++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/mySensor.java
@@ -12,10 +12,10 @@ public abstract class mySensor {
/** listen for sensor events */
public interface SensorListener {
- public void onData(final String csv);
+ public void onData(final long timestamp, final String csv);
/** received data from the given sensor */
- public void onData(final SensorType id, final String csv);
+ public void onData(final SensorType id, final long timestamp, final String csv);
}
diff --git a/app/src/main/res/drawable/ic_mess_around.xml b/app/src/main/res/drawable/ic_mess_around.xml
new file mode 100644
index 0000000..8e0a806
--- /dev/null
+++ b/app/src/main/res/drawable/ic_mess_around.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 83f3a3f..d1a9090 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,6 +1,7 @@
-
-
+
-
- android:layout_marginTop="10dip"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:weightSum="3">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
new file mode 100644
index 0000000..20873b7
--- /dev/null
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/pedestrian_activity_button.xml b/app/src/main/res/layout/pedestrian_activity_button.xml
new file mode 100644
index 0000000..2179a4a
--- /dev/null
+++ b/app/src/main/res/layout/pedestrian_activity_button.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 47c8224..812cb7b 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -2,4 +2,5 @@
16dp
16dp
+ 16dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d4b74c2..b278592 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -5,4 +5,46 @@
Hello world!
Settings
+ Active Sensors
+ Choose the sensors included in the recording
+
+ - GPS
+ - WiFi
+ - Bluetooth
+ - Phone (Accel, Gyro, Magnet)
+
+
+ - GPS
+ - WIFI
+ - BLUETOOTH
+ - PHONE
+
+
+ - GPS
+ - WIFI
+ - BLUETOOTH
+ - PHONE
+
+
+ Active Pedestrian-Actions
+ Choose which Pedestrian-Actions should be available to choose from during recording.
+
+ - Walk
+ - Elevator Up/Down
+ - Stairs Up/Down
+ - Messing Around
+
+
+ - WALK
+ - ELEVATOR
+ - STAIRS
+ - MESS_AROUND
+
+
+ - WALK
+ - ELEVATOR
+ - STAIRS
+ - MESS_AROUND
+
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 319eb0c..3e92110 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -5,4 +5,13 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
new file mode 100644
index 0000000..5d6ad7b
--- /dev/null
+++ b/app/src/main/res/xml/preferences.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 399e18e..5d652f1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,9 +8,10 @@ buildscript {
url 'https://maven.google.com/'
name 'Google'
}
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.0'
+ classpath 'com.android.tools.build:gradle:3.4.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 76010aa..de55c05 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Nov 13 09:30:52 CET 2017
+#Sun Aug 18 15:19:02 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip