From fbff0ce9624a714c9fe2085eb022aa5352ad46b7 Mon Sep 17 00:00:00 2001 From: kazu Date: Tue, 7 Jun 2016 18:00:20 +0200 Subject: [PATCH] added missing semicolons switched to relative timestamps reduced file footprint fixed layout issues removed layout margins more robust data-folder detection fixed some potential timing issues reduced rotation matrix calculation (only with MAG_SENSOR) added data-rate calculation reduced UI-updates --- .../indoor/sensorreadout/MainActivity.java | 44 +++++------- .../sensorreadout/sensors/DataFolder.java | 37 ++++++---- .../indoor/sensorreadout/sensors/Logger.java | 23 +++++-- .../sensorreadout/sensors/PhoneSensors.java | 69 +++++++++++++------ .../indoor/sensorreadout/sensors/WiFi.java | 10 +-- app/src/main/res/layout/activity_main.xml | 68 ++++++++++-------- 6 files changed, 149 insertions(+), 102 deletions(-) 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 e1f987f..a5219a0 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java @@ -34,13 +34,13 @@ import de.fhws.indoor.sensorreadout.sensors.SensorType; public class MainActivity extends Activity { private final ArrayList sensors = new ArrayList(); - private final ArrayList txtFields = new ArrayList(); private final Logger logger = new Logger(this); private Button btnStart; private Button btnStop; private Button btnGround; private int groundTruthCounter = 0; private boolean isInitialized = false; + final private int MY_PERMISSIONS_REQUEST_READ_BT = 123; final private int MY_PERMISSIONS_REQUEST_READ_HEART = 321; @@ -195,24 +195,6 @@ public class MainActivity extends Activity { @Override public void onData(final SensorType id, final String csv) {return; } }); - final LinearLayout lay = (LinearLayout) findViewById(R.id.layoutMain); - lay.setOrientation(LinearLayout.HORIZONTAL); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); - params.setMargins(10,10,10,10); - - // fixed number of textfields - for (int i = 0; i < 16; ++i) { - final TextView tv = new TextView(this); - - //Set margin and color - tv.setTextColor(Color.parseColor("#2fbf78")); - tv.setLayoutParams(params); - - lay.addView(tv); - txtFields.add(tv); - } - - // bluetooth permission if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { @@ -236,17 +218,18 @@ public class MainActivity extends Activity { private void start() { + loadCounterAny = 0; logger.start(); - txtFields.get(2).setText(logger.getFile().getAbsolutePath()); + final TextView txt = (TextView) findViewById(R.id.txtFile); + txt.setText(logger.getFile().getAbsolutePath()); for (final mySensor s : sensors) {s.onResume(this);} } private void stop() { - logger.stop(); - for(int i = 0; i < txtFields.size(); i++) { - txtFields.get(i).setText(""); - } for (final mySensor s : sensors) {s.onPause(this);} + logger.stop(); + ((TextView) findViewById(R.id.txtWifi)).setText(""); + ((TextView) findViewById(R.id.txtBeacon)).setText(""); } /** new sensor data */ @@ -261,13 +244,18 @@ public class MainActivity extends Activity { @Override public void run() { if (id == SensorType.WIFI) { - txtFields.get(0).setText( ((++loadCounterWifi % 2) == 0) ? "wi" : "WI"); + final TextView txt = (TextView) findViewById(R.id.txtWifi); + txt.setText( ((++loadCounterWifi % 2) == 0) ? "wi" : "WI"); } else if (id == SensorType.IBEACON){ - txtFields.get(1).setText( ((++loadCounterBeacon % 2) == 0) ? "ib" : "IB"); + final TextView txt = (TextView) findViewById(R.id.txtBeacon); + txt.setText( ((++loadCounterBeacon % 2) == 0) ? "ib" : "IB"); } - if (++loadCounterAny % 10 == 0) { - txtFields.get(2).setText( (logger.getSize() / 1024) + " kb - " + logger.getNumEntries()); + // dump buffer stats every x entries + if (++loadCounterAny % 100 == 0) { + final TextView txt = (TextView) findViewById(R.id.txtBuffer); + final int kbPerMin = (int) (logger.getSize() / 1024 * 1000 * 60 / (System.currentTimeMillis() - logger.getStartTS())); + txt.setText( (logger.getSize() / 1024) + "kb, " + logger.getNumEntries() + ", " + kbPerMin + "kb/min"); } } diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java index 90047d6..16e7929 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/DataFolder.java @@ -24,24 +24,33 @@ public class DataFolder { public DataFolder(Context context, String folderName){ this.context = context; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - folder = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), folderName); - } else if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - folder = new File(Environment.getExternalStorageDirectory() + "/" + folderName); - } else { - folder = new File(context.getApplicationInfo().dataDir); - } + // 1) try external data folder + folder = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), folderName); + if (isOK(folder)) {return;} - // build folders + // 2) try sd-card folder + folder = new File(Environment.getExternalStorageDirectory() + "/" + folderName); + if (isOK(folder)) {return;} + + // 3) try internal data folder + folder = new File(context.getApplicationInfo().dataDir); + if (isOK(folder)) {return;} + + // all failed + throw new MyException("failed to create/access storage folder"); + + } + + /** ensure the given folder is OK */ + private static final boolean isOK(final File folder) { folder.mkdirs(); - - // sanity check: - if (!folder.exists() || !folder.isDirectory()) { - throw new MyException("failed to create/access storage folder: " + folder.getAbsolutePath()); - } else { + final boolean ok = folder.exists() && folder.isDirectory(); + if (ok) { Log.d("dataFolder", "using: " + folder); + } else { + Log.d("dataFolder", "not OK: " + folder); } - + return ok; } public File getFolder(){ 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 3fb957c..3f4b133 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 @@ -21,6 +21,9 @@ public final class Logger { private Context context; private int entries = 0; + /** timestamp of logging start. all entries are relative to this one */ + private long startTS = 0; + public Logger(Context context) { this.context = context; } @@ -32,14 +35,17 @@ public final class Logger { sb.setLength(0); entries = 0; + // starting timestamp + startTS = System.currentTimeMillis(); + // open the output-file immeditaly (to get permission errors) // but do NOT yet write anything to the file - DataFolder folder = new DataFolder(context, "sensorOutFiles"); - file = new File(folder.getFolder(), System.currentTimeMillis() + ".csv"); - Log.d("logger", "will write to: " + file.toString()); + 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); } @@ -69,20 +75,25 @@ public final class Logger { /** 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) { - sb.append(System.currentTimeMillis()); + 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"); + sb.append('\n'); ++entries; } debug(); } + public final long getStartTS() { + return startTS; + } + int cnt = 0; private final void debug() { - if (++cnt % 10 == 0) { + if (++cnt % 500 == 0) { Log.d("buffer", "size: " + sb.length()); } } 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 266efbc..3505708 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 @@ -85,8 +85,10 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ final StringBuilder sb = new StringBuilder(); // constructor smartphone details - sb.append("Device: " + android.os.Build.MODEL).append(NL); - sb.append("Android: " + Build.VERSION.RELEASE).append(NL); + sb.append("[Device]").append(NL); + sb.append("\tModel: " + android.os.Build.MODEL).append(NL); + sb.append("\tAndroid: " + Build.VERSION.RELEASE).append(NL); + sb.append(NL); // construct sensor details dumpSensor(sb, SensorType.ACCELEROMETER, acc); @@ -113,11 +115,13 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ /** dump all details of the given sensor into the provided stringbuilder */ private void dumpSensor(final StringBuilder sb, final SensorType type, final Sensor sensor) { - sb.append("Sensor").append(NL); - sb.append("id: ").append(type.ordinal()).append(NL); - sb.append("type: ").append(type).append(NL); + sb.append("[Sensor]").append(NL); + sb.append("\tour_id: ").append(type.id()).append(NL); + sb.append("\ttype: ").append(type).append(NL); + if (sensor != null) { sb.append("\tVendor: ").append(sensor.getVendor()).append(NL); + sb.append("\tName: ").append(sensor.getName()).append(NL); sb.append("\tVersion: ").append(sensor.getVersion()).append(NL); sb.append("\tMinDelay: ").append(sensor.getMinDelay()).append(NL); //sb.append("\tMaxDelay: ").append(sensor.getMaxDelay()).append(NL); @@ -280,7 +284,10 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ // keep a local copy (needed for orientation matrix) System.arraycopy(event.values, 0, mGravity, 0, 3); - updateOrientation(); + + // NOTE: + // @see TYPE_MAGNETIC_FIELD + //updateOrientation(); } @@ -297,6 +304,10 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ // keep a local copy (needed for orientation matrix) System.arraycopy(event.values, 0, mGeomagnetic, 0, 3); + + // NOTE + // @see TYPE_ACCELEROMETER + // only MAG updates the current orientation as MAG is usually slower than ACC and this reduces the file-footprint updateOrientation(); } @@ -319,29 +330,43 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ if (!success) {return;} // derive orientation-vector using the rotation matrix - float orientation[] = new float[3]; - SensorManager.getOrientation(R, orientation); + float orientationNew[] = new float[3]; + SensorManager.getOrientation(R, orientationNew); // inform listeners if (listener != null) { + // orientation vector listener.onData(SensorType.ORIENTATION_NEW, - Float.toString(orientation[0]) + ";" + - Float.toString(orientation[1]) + ";" + - Float.toString(orientation[2]) + Float.toString(orientationNew[0]) + ";" + + Float.toString(orientationNew[1]) + ";" + + Float.toString(orientationNew[2]) ); + // rotation matrix + final StringBuilder sb = new StringBuilder(1024); + sb.append(R[0]).append(';'); + sb.append(R[1]).append(';'); + sb.append(R[2]).append(';'); + sb.append(R[3]).append(';'); + sb.append(R[4]).append(';'); + sb.append(R[5]).append(';'); + sb.append(R[6]).append(';'); + sb.append(R[7]).append(';'); + sb.append(R[8]); + //Write the whole rotationMatrix R into the Listener. - listener.onData(SensorType.ROTATION_MATRIX, - Float.toString(R[0]) + ";" + - Float.toString(R[1]) + ";" + - Float.toString(R[2]) + ";" + - Float.toString(R[3]) + ";" + - Float.toString(R[4]) + ";" + - Float.toString(R[5]) + ";" + - Float.toString(R[6]) + ";" + - Float.toString(R[7]) + ";" + - Float.toString(R[8]) + listener.onData(SensorType.ROTATION_MATRIX, sb.toString()); + +// Float.toString(R[0]) + ";" + +// Float.toString(R[1]) + ";" + +// Float.toString(R[2]) + ";" + +// Float.toString(R[3]) + ";" + +// Float.toString(R[4]) + ";" + +// Float.toString(R[5]) + ";" + +// Float.toString(R[6]) + ";" + +// Float.toString(R[7]) + ";" + +// Float.toString(R[8]) // Float.toString(R[9]) + ";" + // Float.toString(R[10]) + ";" + // Float.toString(R[11]) + ";" + @@ -349,7 +374,7 @@ public class PhoneSensors extends mySensor implements SensorEventListener{ // Float.toString(R[13]) + ";" + // Float.toString(R[14]) + ";" + // Float.toString(R[15]) - ); +// ); } 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 2269dd0..fd4f0f5 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 @@ -30,15 +30,15 @@ public class WiFi extends mySensor { this.receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - final StringBuilder sb = new StringBuilder(); + 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); + sb.append(Helper.stripMAC(sr.BSSID)).append(';'); + sb.append(sr.frequency).append(';'); + sb.append(sr.level).append(';'); } - startScan(); if (listener != null && isReceiverRegistered) {listener.onData(sb.toString());} + startScan(); //Log.d("wifi", sb.toString()); } }; diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ee33be3..6625edf 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,28 +1,12 @@ + - - - - - - + android:layout_width="match_parent" + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools" + android:keepScreenOn="true" + tools:context="de.fhws.indoor.sensorreadout.MainActivity" + android:background="#333">