Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ccc-ffm/scanble
  • dachdecker2/scanble
  • mrm2m/scanble
3 results
Show changes
Commits on Source (9)
Showing with 227 additions and 51 deletions
......@@ -3,8 +3,9 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.2" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
......
......@@ -3,7 +3,7 @@
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
</project>
......
......@@ -12,7 +12,6 @@
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
......
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="ScanBle" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="scanble" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
......@@ -10,7 +10,7 @@
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugJava" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugTestSources" />
......@@ -31,11 +31,13 @@
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/test/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
......@@ -77,11 +79,13 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 20 Platform" jdkType="Android SDK" />
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="commons-math-2.0" level="project" />
<orderEntry type="library" exported="" name="commons-math3-3.3" level="project" />
<orderEntry type="library" exported="" name="commons-math3-3.3-javadoc" level="project" />
<orderEntry type="library" exported="" name="sgfilter_v1_2" level="project" />
</component>
</module>
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
compileSdkVersion 18
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "org.mekelburger.moritz.scanble"
minSdkVersion 19
minSdkVersion 18
targetSdkVersion 20
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
// runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/notice.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/dependencies.txt'
exclude 'META-INF/LGPL2.1'
}
productFlavors {
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/commons-math3-3.3.jar')
compile files('libs/sgfilter_v1_2.jar')
}
File added
File added
......@@ -2,15 +2,26 @@ package org.mekelburger.moritz.scanble;
import android.util.Log;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.Set;
import java.util.List;
import java.util.TreeMap;
import mr.go.sgfilter.ContinuousPadder;
import mr.go.sgfilter.SGFilter;
/**
* This class stores a history of RSSI values of received advertisements with time stamps
*/
public class AdvertisementHistory extends HashMap<Long, Integer> {
private final static int OLD = 3000;
public class AdvertisementHistory extends TreeMap<Long, Integer> {
private final static int OLD = 2000;
private final static int TIMEOUT = 500;
private final static String TAG = "AdvertisementHistory";
public AdvertisementHistory() {
super();
......@@ -25,6 +36,95 @@ public class AdvertisementHistory extends HashMap<Long, Integer> {
this.put(new Long(System.currentTimeMillis()), new Integer(rssi));
}
/**
* Generate a data set where missing data is padded (left padding).
*
* As advertisements are sent with a nearly constant rate there should be one data point every
* n milliseconds. So we get that n as minimum of our data points and pad missing values from
* the right.
* All values older then AdvertisementHistory.OLD will be deleted before evaluation, If we got
* no new results within the last AdvertisementHistory.TIMEOUT milliseconds all data is flushed
* and an empty data set is returned. If there are not at least two values in the history the
* result is empty as well.
*
* @return padded data set
*/
private double[] getPaddedData(String beaconID) {
List<Integer> tmpResult = new ArrayList<Integer>();
Object[] timestamps;
long lastTimestamp = 0;
Long currentTs;
Log.d(TAG, "getPaddedData started");
this.getAverageValue();
if (this.keySet().size() < 2) {
return new double[]{};
}
timestamps = this.keySet().toArray();
if (System.currentTimeMillis() - ((Long) timestamps[timestamps.length - 1]).longValue() >
AdvertisementHistory.OLD) {
Log.d(TAG, String.format("Last time stamp too old: %d - %d = %d > %d",
System.currentTimeMillis(),
((Long) timestamps[timestamps.length - 1]).longValue(),
System.currentTimeMillis() -
((Long) timestamps[timestamps.length - 1]).longValue(),
AdvertisementHistory.OLD));
return new double[]{};
}
Log.v(TAG, String.format("KeySet sorted..: %s", Arrays.toString(timestamps)));
// get the medium time delta.
long[] timeDeltas = new long[this.keySet().size() - 1];
for (int i=0; i < timeDeltas.length; i++) {
timeDeltas[i] =
((Long) timestamps[i + 1]).longValue() - ((Long) timestamps[i]).longValue();
}
long mediumDelta = timeDeltas[timeDeltas.length / 2];
lastTimestamp = 0;
for (Object ts: timestamps) {
currentTs = (Long) ts;
if (lastTimestamp != 0) {
while (lastTimestamp == 0 || currentTs.longValue() - lastTimestamp > 1.5 * mediumDelta) {
tmpResult.add(new Integer(0));
lastTimestamp += mediumDelta;
}
}
lastTimestamp = currentTs.longValue();
tmpResult.add(this.get(currentTs));
}
double[] result = new double[tmpResult.size()];
for (int i=tmpResult.size() - 1; i >= 0; i--) {
if (tmpResult.get(i).intValue() == 0) {
result[i] = result[i+1];
} else {
result[i] = (double) tmpResult.get(i);
}
}
Log.v(TAG, String.format("Padded data: %s - %s", beaconID, Arrays.toString(result)));
return result;
}
public float getCurrentValue(String beaconID) {
double[] dataSet = this.getPaddedData(beaconID);
if (dataSet.length <= 3) {
return Float.NaN;
}
double[] coeffs = SGFilter.computeSGCoefficients(dataSet.length - 1, 0, 3);
float result = 0.f;
for (int i=0; i < dataSet.length; i++) {
// Log.v(TAG, String.format("Savitzky/Golay %.2f += %.2f * %.2f = %.2f", result, coeffs[i], dataSet[i], coeffs[i] * dataSet[i]));
result += coeffs[i] * (float) dataSet[i];
}
Log.v(TAG, String.format("Savitzky/Golay coefficients: %s", Arrays.toString(coeffs)));
// Log.d(TAG, String.format("Savitzky/Golay value: %.2f", result));
return result;
}
/**
* Calculate the mean value of the latest values. Old entries (more then
* AdvertisementHistory.OLD ms old) are deleted.
......
......@@ -24,7 +24,7 @@ public class Beacon extends SimpleBeacon{
public SimpleBeacon flatCopy() {
SimpleBeacon result = new SimpleBeacon(this.getPosition().clone(), this.getDistance(),
this.getDistanceError(), this.advertisements.getAverageValue());
this.getDistanceError(), this.advertisements.getCurrentValue(this.getMac()));
return result;
}
......@@ -34,7 +34,7 @@ public class Beacon extends SimpleBeacon{
}
public float getDistance() {
float ratio_power = this.tx - this.advertisements.getAverageValue();
float ratio_power = this.tx - this.advertisements.getCurrentValue(this.getMac());
float distance = (float) Math.pow(Math.pow(10., ratio_power / 10.), 0.5);
Log.d(TAG, String.format("Distance %s: %.2f (from %d measurements)", this.getMac(),
distance, this.advertisements.size()));
......
......@@ -90,12 +90,15 @@ public class BeaconHandler implements Runnable {
this.bluetoothAdapter.startLeScan(leScanCallback);
scanning = true;
this.stopLeScanFuture = this.stopLeScanWorker.schedule(stopLe, BeaconHandler.INACTIVITY_TIMEOUT, TimeUnit.MILLISECONDS);
KNOWN_BEACONS.put("00:07:80:68:28:29", new float[]{0.f,-1.5f,1.f});
KNOWN_BEACONS.put("00:07:80:68:28:64", new float[]{2.f,1.5f,2.f});
KNOWN_BEACONS.put("00:07:80:68:28:29", new float[]{6.f,-3f,1.f});
KNOWN_BEACONS.put("00:07:80:C0:FF:EE", new float[]{0.f,-3f,1.f});
KNOWN_BEACONS.put("00:07:80:68:28:64", new float[]{0.f,3f,2.25f});
// KNOWN_BEACONS.put("00:07:80:11:11:11", new float[]{0f,0f,0f});
KNOWN_BEACONS.put("00:07:80:79:00:BA", new float[]{0.f,1.5f,0.8f});
KNOWN_BEACONS.put("00:07:80:72:CD:E3", new float[]{2.f,0.f,1.f});
KNOWN_BEACONS.put("00:07:80:79:00:BA", new float[]{9.f,1.f,0.8f}); // DKBLE BLE113
KNOWN_BEACONS.put("00:07:80:72:CD:E3", new float[]{6.f,0.f,1.f}); // BLE113 eval-board
KNOWN_BEACONS.put("00:07:80:7F:41:30", new float[]{-2.f,0.f,2.f});
KNOWN_BEACONS.put("0E:F3:EE:5A:04:CD", new float[]{0.f,0.f,1.2f});
KNOWN_BEACONS.put("60:03:08:AE:CB:F2", new float[]{0.f,0.f,0.2f});
}
/**
......
......@@ -8,12 +8,17 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.TextView;
import java.util.concurrent.Executors;
......@@ -32,6 +37,9 @@ public class MainActivity extends Activity {
private static final ScheduledExecutorService requestPosition =
Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> requestPositionFuture;
private Handler runhandler = new Handler();
private Boolean doAutoUpdate = false;
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
......@@ -69,37 +77,55 @@ public class MainActivity extends Activity {
@Override
public void onClick(View v) {
Log.d(TAG, "Button pressed - START");
String beaconString = "";
for (SimpleBeacon b: beaconService.getBeaconHandler().getTmpBeacons()) {
beaconString += b.toString();
beaconString += "\n";
}
((TextView) findViewById(R.id.textView)).setText(
String.format("Position: %.2f, %.2f\n%s",
beaconService.getBeaconHandler().getPos()[0],
beaconService.getBeaconHandler().getPos()[1],
beaconString));
// ((TextView) findViewById(R.id.textView)).setText("Foo!");
/* if (bounded) {
beaconService.getBeaconHandler().getPos();
} // */
updateText("Button");
Log.d(TAG, "Button pressed - END");
}
});
bindService(intent, this.serviceConnection, BIND_ABOVE_CLIENT);
/* this.requestPositionFuture = this.requestPosition.scheduleAtFixedRate(new Runnable() {
Switch do_switch = (Switch) findViewById(R.id.myswitch);
do_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void run() {
Log.d(TAG, "Timer - START");
// ((TextView) findViewById(R.id.textView)).setText(beaconService.getBeaconHandler().getPos().toString());
runOnUiThread();
((TextView) findViewById(R.id.textView)).setText("Foo!");
Log.d(TAG, "Timer - END");
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
{
doAutoUpdate = true;
runhandler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "Timer2 - START");
updateText("Scheduler");
Log.d(TAG, "Timer2 - END");
if (doAutoUpdate)
runhandler.postDelayed(this, 1000);
}
}
, 1000);
}
else
doAutoUpdate = false;
}
}, 1, 2, TimeUnit.SECONDS); // */
});
bindService(intent, this.serviceConnection, BIND_ABOVE_CLIENT);
getWindow().getDecorView().findViewById(android.R.id.content).invalidate();
((TextView) findViewById(R.id.textView)).invalidate();
}
private void updateText (String defaultString) {
String beaconString = "";
for (SimpleBeacon b: beaconService.getBeaconHandler().getTmpBeacons()) {
beaconString += b.toString();
beaconString += "\n";
}
((TextView) findViewById(R.id.textView)).setText(
String.format("caller: %s\nPosition: %.2f, %.2f\n%s",
defaultString,
beaconService.getBeaconHandler().getPos()[0],
beaconService.getBeaconHandler().getPos()[1],
beaconString));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
......@@ -123,7 +149,7 @@ public class MainActivity extends Activity {
@Override
protected void onStop() {
super.onStop();
this.requestPositionFuture.cancel(false);
// this.requestPositionFuture.cancel(false);
if (this.bounded) {
unbindService(this.serviceConnection);
bounded = false;
......
......@@ -14,15 +14,24 @@
android:text="Tu was!"
android:id="@+id/button"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:text="New Text\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
android:id="@+id/textView"
android:layout_alignParentEnd="true"
android:layout_below="@+id/button"
android:layout_alignParentStart="true" />
android:layout_alignParentStart="true"
android:inputType="textMultiLine" />
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="autouptdate"
android:id="@+id/myswitch"
android:layout_alignParentTop="true"
android:layout_alignEnd="@+id/textView" />
</RelativeLayout>
......@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.2'
classpath 'com.android.tools.build:gradle:0.14.4'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......
#Wed Apr 10 15:27:10 PDT 2013
#Sun Nov 23 15:26:37 CET 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/main" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>