diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 3b62741..bb92e91 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index fc32ebe..dbb041f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "de.fhws.indoor.sensorreadout" - minSdkVersion 23 + minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" 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 f1b605a..e730976 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java @@ -39,6 +39,7 @@ 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.UnorderedLogger; import de.fhws.indoor.sensorreadout.sensors.WiFi; import de.fhws.indoor.sensorreadout.sensors.iBeacon; import de.fhws.indoor.sensorreadout.sensors.mySensor; @@ -54,7 +55,8 @@ public class MainActivity extends Activity { private final ArrayList sensors = new ArrayList(); //private final Logger logger = new Logger(this); - private final LoggerRAM logger = new LoggerRAM(this); + //private final LoggerRAM logger = new LoggerRAM(this); + private final UnorderedLogger logger = new UnorderedLogger(this); private Button btnStart; private Button btnStop; private Button btnGround; diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/UnorderedLogger.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/UnorderedLogger.java new file mode 100644 index 0000000..ee81367 --- /dev/null +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/UnorderedLogger.java @@ -0,0 +1,190 @@ +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.ArrayBlockingQueue; +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 UnorderedLogger { + + public static final long BEGINNING_TS = -1; + + private StringBuilder stringBuilder = new StringBuilder(); + private File file; + private FileOutputStream fos; + private Context context; + + private int entries = 0; + private int sizeTotal = 0; + private int currentSize = 0; + + private volatile boolean addingStopped = false; // Just to be sure + private ArrayBlockingQueue lineBuffer = new ArrayBlockingQueue<>(5000); + private WriteBackWorker writeBackWorker; + + /** timestamp of logging start. all entries are relative to this one */ + private long startTS = 0; + + public UnorderedLogger(Context context) { + this.context = context; + } + + /** start logging (caching a couple of entries in RAM) */ + public final void start() { + + // start empty + stringBuilder.setLength(0); + entries = 0; + sizeTotal = 0; + addingStopped = false; + writeBackWorker = new WriteBackWorker(); + + // starting timestamp + startTS = SystemClock.elapsedRealtimeNanos(); + + // open the output-file immediately (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); + } + writeBackWorker.start(); + } + + /** stop logging and flush RAM-data to the flash-chip */ + public final void stop() { + debug(true); + addingStopped = true; + // wait for flushing to succeed + try { + writeBackWorker.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + debug(true); + 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) { + final long relTS = (timestamp == BEGINNING_TS) ? 0 : (timestamp - startTS); + if(relTS >= 0) { // drop pre startTS logs (at the beginning, sensors sometimes deliver old values) + 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 line/flush buffer + lineBuffer.add(logEntry); + } + debug(false); + } + + 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: " + lineBuffer.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 { + while (true) { + LogEntry entry = lineBuffer.poll(); + if (entry == null) { + if (addingStopped) { // Queue empty, recording stopped. exit + return; + } else { // Currently no line in queue, wait 10 ms + Thread.sleep(10); + } + } else { // print log line + fos.write(entry.csv.getBytes()); + } + } + } catch(InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + +} 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 3597aba..3f3b2a7 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 @@ -64,7 +64,7 @@ public class iBeacon extends mySensor { settings = new ScanSettings.Builder() .setReportDelay(0) .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) - .setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT) + //.setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT) //comment this out for apk < 23 .build(); }