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 (11)
Showing
with 319 additions and 72 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.
......
package org.mekelburger.moritz.scanble;
import android.bluetooth.BluetoothDevice;
import android.util.Log;
/**
* Created by moritz on 08.11.2014.
......@@ -10,34 +11,41 @@ public class Beacon extends SimpleBeacon{
private AdvertisementHistory advertisements = new AdvertisementHistory();
private long last_advertisement_ts = 0;
private static final String TAG = "Beacon";
private int tx;
private final static float C = -(float) Math.log(10) / 20;
public Beacon(BluetoothDevice device, byte[] scanRecord, float[] position) {
super(position, 0, 0);
super(position, 0, 0, 0);
this.mac = device.getAddress();
this.tx = scanRecord[29];
}
public SimpleBeacon flatCopy() {
SimpleBeacon result = new SimpleBeacon(this.getPosition().clone(), this.getDistance(),
this.getDistanceError());
this.getDistanceError(), this.advertisements.getCurrentValue(this.getMac()));
return result;
}
public void add_rssi(int rssi) {
public void addRssi(int rssi) {
this.last_advertisement_ts = System.currentTimeMillis();
this.advertisements.addAdvertisement(rssi);
}
public float getDistance() {
float ratio_power = this.tx - this.advertisements.getAverageValue();
return (float) Math.pow(Math.pow(10., ratio_power / 10.), 0.5);
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()));
return distance;
}
public float getDistanceError() {
return Beacon.C * this.getDistance() * this.advertisements.getError();
float distanceError = Beacon.C * this.getDistance() * this.advertisements.getError();
Log.d(TAG, String.format("Distance error %s: %.2f", this.getMac(), distanceError));
Log.v(TAG, String.format("Distance error %s from %s", this.getMac(), this.advertisements.toString()));
return distanceError;
}
public String getMac() {
......
......@@ -5,12 +5,24 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.util.Log;
import org.apache.commons.math3.exception.TooManyEvaluationsException;
import org.apache.commons.math3.optimization.GoalType;
import org.apache.commons.math3.optimization.PointValuePair;
import org.apache.commons.math3.optimization.direct.NelderMeadSimplex;
import org.apache.commons.math3.optimization.direct.SimplexOptimizer;
// */
/*
import org.apache.commons.math3.optim.InitialGuess;
import org.apache.commons.math3.optim.PointValuePair;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer;
// */
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
......@@ -38,6 +50,12 @@ public class BeaconHandler implements Runnable {
private static HashMap<String, float[]> KNOWN_BEACONS = new HashMap<String, float[]>();
private boolean scanning;
public List<SimpleBeacon> getTmpBeacons() {
return tmpBeacons;
}
List<SimpleBeacon> tmpBeacons = new ArrayList<SimpleBeacon>();
private Runnable stopLe = new Runnable() {
@Override
public void run() {
......@@ -53,16 +71,6 @@ public class BeaconHandler implements Runnable {
scanning = true;
}
synchronized (this.pos) {
if (this.stopLeScanFuture != null && !this.stopLeScanFuture.isDone() &&
!this.stopLeScanFuture.isCancelled()) {
this.stopLeScanFuture.cancel(false);
}
this.stopLeScanFuture = this.stopLeScanWorker.schedule(stopLe,
BeaconHandler.INACTIVITY_TIMEOUT, TimeUnit.MILLISECONDS);
for (Beacon b: this.beacons.values()) {
Log.i(TAG, String.format("%s: %.2f +- %.2f", b.getMac(), b.getDistance(),
b.getDistanceError()));
}
return this.pos;
}
}
......@@ -82,11 +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[]{0f,0f,0f});
KNOWN_BEACONS.put("00:07:80:68:28:64", new float[]{0f,0f,0f});
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[]{0f,0f,0f});
KNOWN_BEACONS.put("00:07:80:72:CD:E3", new float[]{0f,0f,0f});
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[]{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});
}
/**
......@@ -113,25 +125,53 @@ public class BeaconHandler implements Runnable {
while (true) {
try {
Thread.sleep(1000);
synchronized (this.pos) {
List<SimpleBeacon> tmpBeacons = new ArrayList<SimpleBeacon>();
for (String mac: this.beacons.keySet()) {
synchronized (this.beacons) {
this.tmpBeacons = new ArrayList<SimpleBeacon>();
for (String mac : this.beacons.keySet()) {
if (this.beacons.get(mac).getDistance() != Float.NaN) {
tmpBeacons.add(beacons.get(mac).flatCopy());
}
}
if (tmpBeacons.size() >= 4) {
// ToDo: Move away from the functions marked as deprecated.
// ToDo: Check what all these constants are for and replace them.
}
double[] tmpPos = new double[]{0.,0.,0.};
synchronized (this.pos) {
for (int i = 0; i < 3; i++) {
tmpPos[i] = this.pos[i];
}
}
if (tmpBeacons.size() >= 4) {
// ToDo: Move away from the functions marked as deprecated.
// ToDo: Check what all these constants are for and replace them.
/* SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
NelderMeadSimplex nms = new NelderMeadSimplex(tmpBeacons.size());
nms.iterate(new NelderMead(tmpBeacons), new Comparator<PointValuePair>() {
@Override
public int compare(PointValuePair lhs, PointValuePair rhs) {
return lhs.getValue().compareTo(rhs.getValue());
}
});
PointValuePair optimum = optimizer.optimize(nms, GoalType.MINIMIZE,
new InitialGuess(tmpPos));
// */
try {
SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
optimizer.setSimplex(new NelderMeadSimplex(new double[]{0.15, 0.15, 0.15}));
PointValuePair optimum = optimizer.optimize(5000, new NelderMead(tmpBeacons),
GoalType.MINIMIZE, new double[]{3., 0.3, 0.});
Log.d(TAG, String.format("Position: %s", optimum.toString()));
} else {
Log.d(TAG, String.format("Not enough beacons for position recognition: %d",
tmpBeacons.size()));
}
GoalType.MINIMIZE, tmpPos);
Log.d(TAG, String.format("Position: (%s, %s)", optimum.getPoint()[0],
optimum.getPoint()[1]));
synchronized (this.pos) {
for (int i = 0; i < 3; i++) {
this.pos[i] = (float) optimum.getPoint()[i];
}
}
} catch (TooManyEvaluationsException e) {
}// */
} else {
Log.d(TAG, String.format("Not enough beacons for position recognition: %d",
tmpBeacons.size()));
}
Log.v(TAG, "BeaconService beaconHandler Thread");
} catch (InterruptedException e) {
......@@ -170,7 +210,7 @@ public class BeaconHandler implements Runnable {
} else {
b = this.beacons.get(device.getAddress());
}
b.add_rssi(rssi);
b.addRssi(rssi);
}
Log.v(TAG, String.format("Advertisement from %s", device.getAddress()));
} else {
......
......@@ -8,12 +8,18 @@ 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;
import java.util.concurrent.ScheduledExecutorService;
......@@ -30,7 +36,10 @@ public class MainActivity extends Activity {
private static final ScheduledExecutorService requestPosition =
Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture requestPositionFuture;
private ScheduledFuture<?> requestPositionFuture;
private Handler runhandler = new Handler();
private Boolean doAutoUpdate = false;
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
......@@ -67,21 +76,56 @@ public class MainActivity extends Activity {
do_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Button pressed - START");
updateText("Button");
Log.d(TAG, "Button pressed - END");
}
});
if (bounded) {
beaconService.getBeaconHandler().getPos();
Switch do_switch = (Switch) findViewById(R.id.myswitch);
do_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
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;
}
});
bindService(intent, this.serviceConnection, BIND_ABOVE_CLIENT);
this.requestPositionFuture = this.requestPosition.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
beaconService.getBeaconHandler().getPos();
}
}, 1, 2, TimeUnit.SECONDS);
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) {
......@@ -105,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;
......
......@@ -15,7 +15,6 @@ public class NelderMead implements MultivariateFunction {
this.beacons = beacons;
}
public double value(double[] doubles) {
double result = 0.;
float[] tmpPos;
......@@ -23,9 +22,9 @@ public class NelderMead implements MultivariateFunction {
for (SimpleBeacon b: this.beacons) {
tmpPos = b.getPosition();
expectedDistance = Math.pow(Math.pow(tmpPos[0] - doubles[0], 2) +
Math.pow(tmpPos[1] - doubles[1], 2) +
Math.pow(tmpPos[2] - doubles[2], 2), 0.5);
result = Math.pow(expectedDistance - b.getDistance(), 2);
Math.pow(tmpPos[1] - doubles[1], 2) +
Math.pow(tmpPos[2] - doubles[2], 2), 0.5);
result += Math.pow(expectedDistance - b.getDistance(), 2);
}
return result;
......
......@@ -9,11 +9,13 @@ public class SimpleBeacon {
private float[] position;
private float distance;
private float distanceError;
private float rssi;
public SimpleBeacon(float[] position, float distance, float distanceError) {
public SimpleBeacon(float[] position, float distance, float distanceError, float rssi) {
this.position = position;
this.distance = distance;
this.distanceError = distanceError;
this.rssi = rssi;
}
public float[] getPosition() {
......@@ -30,10 +32,7 @@ public class SimpleBeacon {
@Override
public String toString() {
return "SimpleBeacon{" +
"position=" + Arrays.toString(getPosition()) +
", distance=" + getDistance() +
", distanceError=" + getDistanceError() +
'}';
return String.format("SimpleBeacon: %s | %.2f | %.2f | %.2f", Arrays.toString(position),
this.getDistance(), this.getDistanceError(), this.rssi);
}
}
......@@ -14,5 +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\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: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>