diff --git a/src/main/java/org/altbeacon/beacon/Beacon.java b/src/main/java/org/altbeacon/beacon/Beacon.java index 8a2777347..e76e1362b 100644 --- a/src/main/java/org/altbeacon/beacon/Beacon.java +++ b/src/main/java/org/altbeacon/beacon/Beacon.java @@ -126,6 +126,11 @@ public class Beacon implements Parcelable { */ protected int mBeaconTypeCode; + /** + * A count of the number of advertisements detected + */ + protected long mAdvertisementCount; + /** * A two byte code indicating the beacon manufacturer. A list of registered manufacturer codes * may be found here: @@ -223,6 +228,10 @@ protected Beacon(Parcel in) { } mManufacturer = in.readInt(); mBluetoothName = in.readString(); + // This nonsense is needed because we can't do readDouble on null values. + // See: http://stackoverflow.com/a/10769887/1461050 + mRunningAverageRssi = (Double) in.readValue(Double.class.getClassLoader()); + mAdvertisementCount = in.readLong(); } /** @@ -262,6 +271,18 @@ public void setRunningAverageRssi(double rssi) { mDistance = null; // force calculation of accuracy and proximity next time they are requested } + /** + * Gets the running average rssi, if available, otherwise get the latest rssi + */ + public double getRunningAverageRssi() { + if (mRunningAverageRssi != null) { + return mRunningAverageRssi; + } + else { + return getRssi(); + } + } + /** * Sets the most recently measured rssi for use in distance calculations if a running average is * not available @@ -367,6 +388,20 @@ public List getIdentifiers() { } } + /** + * @see #mAdvertisementCount + */ + public long getAdvertisementCount() { + return mAdvertisementCount; + } + + /** + * @see #mAdvertisementCount + */ + public void setAdvertisementCount(long advertisementCount) { + mAdvertisementCount = advertisementCount; + } + /** * Provides a calculated estimate of the distance to the beacon based on a running average of @@ -526,6 +561,8 @@ public void writeToParcel(Parcel out, int flags) { } out.writeInt(mManufacturer); out.writeString(mBluetoothName); + out.writeValue(mRunningAverageRssi); + out.writeLong(mAdvertisementCount); } diff --git a/src/main/java/org/altbeacon/beacon/BeaconManager.java b/src/main/java/org/altbeacon/beacon/BeaconManager.java index 6585fdbe7..4f57a353a 100644 --- a/src/main/java/org/altbeacon/beacon/BeaconManager.java +++ b/src/main/java/org/altbeacon/beacon/BeaconManager.java @@ -689,7 +689,7 @@ public static void logDebug(String tag, String message, Throwable t) { protected static BeaconSimulator beaconSimulator; - protected static String distanceModelUpdateUrl = "http://data.altbeacon.org/android-distance.json"; + protected static String distanceModelUpdateUrl = "http://data.altbeacon.org/android-distance-r2.json"; public static String getDistanceModelUpdateUrl() { return distanceModelUpdateUrl; diff --git a/src/main/java/org/altbeacon/beacon/distance/AndroidModel.java b/src/main/java/org/altbeacon/beacon/distance/AndroidModel.java index d934a428d..835d96502 100644 --- a/src/main/java/org/altbeacon/beacon/distance/AndroidModel.java +++ b/src/main/java/org/altbeacon/beacon/distance/AndroidModel.java @@ -91,6 +91,56 @@ public int matchScore(AndroidModel otherModel) { return score; } + /** + * Calculates a qualitative match score between two different Android device models for the + * purposes of how likely they are to have similar Bluetooth signal level responses + * This algorithm takes into account partial matches of model strings, as Samsung devices + * commonly have different model name suffixes + * @param otherModel + * @return match quality, higher numbers are a better match + */ + public double matchScoreWithPartialModel(AndroidModel otherModel) { + double score = 0; + if (this.mManufacturer.equalsIgnoreCase(otherModel.mManufacturer)) { + score = 1; + } + if (score == 1 ) { + score = 1+ratioOfMatchingPrefixCharacters(this.getModel(), otherModel.getModel()); + } + LogManager.d(TAG, "Score is %s for %s compared to %s", score, toString(), otherModel); + return score; + } + + /** + * Returns 1.0 if the string is a complete match, 0.0 if the first characters are different + * and 0.5 if the first halves of each string match. Not case sensitive. + * @param string1 + * @param string2 + * @return + */ + private double ratioOfMatchingPrefixCharacters(String string1, String string2) { + int maxLength = 0; + int minLength = 0; + int matchingChars = 0; + String lower1 = string1.toLowerCase(); + String lower2 = string2.toLowerCase(); + if (string2.length() >= string1.length()) { + maxLength = string2.length(); + minLength = string1.length(); + } + else { + maxLength = string1.length(); + minLength = string2.length(); + } + + for (int i = 0; i < minLength; i++) { + if (lower1.charAt(i) == lower2.charAt(i)) { + matchingChars++; + } + } + return 1.0*matchingChars/maxLength; + } + @Override public String toString() { return ""+mManufacturer+";"+mModel+";"+mBuildNumber+";"+mVersion; diff --git a/src/main/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculator.java b/src/main/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculator.java index 42f7db771..675fcba2b 100644 --- a/src/main/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculator.java +++ b/src/main/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculator.java @@ -46,7 +46,7 @@ */ public class ModelSpecificDistanceCalculator implements DistanceCalculator { Map mModelMap; - private static final String CONFIG_FILE = "model-distance-calculations.json"; + private static final String CONFIG_FILE = "model-distance-calculations-r2.json"; private static final String TAG = "ModelSpecificDistanceCalculator"; private AndroidModel mDefaultModel; private DistanceCalculator mDistanceCalculator; @@ -54,6 +54,7 @@ public class ModelSpecificDistanceCalculator implements DistanceCalculator { private AndroidModel mRequestedModel; private String mRemoteUpdateUrlString = null; private Context mContext; + private static Class sCalculatorClass = CurveFittedDistanceCalculator.class; private final ReentrantLock mLock = new ReentrantLock(); /** @@ -64,11 +65,20 @@ public ModelSpecificDistanceCalculator(Context context, String remoteUpdateUrlSt this(context, remoteUpdateUrlString, AndroidModel.forThisDevice()); } + /** + * Configures the distance calculator to be used + * @param klass + */ + public static void setDistanceCalculatorClass(Class klass) { + sCalculatorClass = klass; + } + /** * Obtains the best possible DistanceCalculator for the Android device passed * as an argument */ public ModelSpecificDistanceCalculator(Context context, String remoteUpdateUrlString, AndroidModel model) { + LogManager.i(TAG, "Constructing model distance database"); mRequestedModel = model; mRemoteUpdateUrlString = remoteUpdateUrlString; mContext = context; @@ -109,26 +119,26 @@ DistanceCalculator findCalculatorForModelWithLock(AndroidModel model) { } private DistanceCalculator findCalculatorForModel(AndroidModel model) { - LogManager.d(TAG, "Finding best distance calculator for %s, %s, %s, %s", + LogManager.i(TAG, "Finding best distance calculator for %s, %s, %s, %s", model.getVersion(), model.getBuildNumber(), model.getModel(), model.getManufacturer()); if (mModelMap == null) { - LogManager.d(TAG, "Cannot get distance calculator because modelMap was never initialized"); + LogManager.e(TAG, "Cannot get distance calculator because modelMap was never initialized"); return null; } - int highestScore = 0; + double highestScore = 0; AndroidModel bestMatchingModel = null; for (AndroidModel candidateModel : mModelMap.keySet()) { - if (candidateModel.matchScore(model) > highestScore) { - highestScore = candidateModel.matchScore(model); + if (candidateModel.matchScoreWithPartialModel(model) > highestScore) { + highestScore = candidateModel.matchScoreWithPartialModel(model); bestMatchingModel = candidateModel; } } if (bestMatchingModel != null) { LogManager.d(TAG, "found a match with score %s", highestScore); - LogManager.d(TAG, "Finding best distance calculator for %s, %s, %s, %s", + LogManager.i(TAG, "Using best match distance calculator for %s, %s, %s, %s", bestMatchingModel.getVersion(), bestMatchingModel.getBuildNumber(), bestMatchingModel.getModel(), bestMatchingModel.getManufacturer()); mModel = bestMatchingModel; @@ -274,21 +284,42 @@ private void buildModelMap(String jsonString) throws JSONException { if (modelObject.has("default")) { defaultFlag = modelObject.getBoolean("default"); } - Double coefficient1 = modelObject.getDouble("coefficient1"); - Double coefficient2 = modelObject.getDouble("coefficient2"); - Double coefficient3 = modelObject.getDouble("coefficient3"); + String version = modelObject.getString("version"); String buildNumber = modelObject.getString("build_number"); String model = modelObject.getString("model"); String manufacturer = modelObject.getString("manufacturer"); + AndroidModel androidModel = new AndroidModel(version, buildNumber, model, manufacturer); - CurveFittedDistanceCalculator distanceCalculator = - new CurveFittedDistanceCalculator(coefficient1,coefficient2,coefficient3); + DistanceCalculator distanceCalculator = null; + if (sCalculatorClass.equals(CurveFittedDistanceCalculator.class)) { + Double coefficient1 = modelObject.optDouble("coefficient1"); + Double coefficient2 = modelObject.optDouble("coefficient2"); + Double coefficient3 = modelObject.optDouble("coefficient3"); - AndroidModel androidModel = new AndroidModel(version, buildNumber, model, manufacturer); - mModelMap.put(androidModel, distanceCalculator); - if (defaultFlag) { - mDefaultModel = androidModel; + if (!coefficient1.isNaN() && !coefficient2.isNaN() && !coefficient3.isNaN()) { + distanceCalculator = + new CurveFittedDistanceCalculator(coefficient1,coefficient2,coefficient3); + } + } + else if (sCalculatorClass.equals(PathLossDistanceCalculator.class)) { + Double receiverRssiOffset = modelObject.optDouble("receiver_rssi_offset"); + Double receiverRssiSlope = modelObject.optDouble("receiver_rssi_slope"); + if (!receiverRssiOffset.isNaN() && !receiverRssiSlope.isNaN()) { + distanceCalculator = + new PathLossDistanceCalculator(receiverRssiSlope, receiverRssiOffset); + } + } + + if (distanceCalculator != null) { + mModelMap.put(androidModel, distanceCalculator); + if (defaultFlag) { + mDefaultModel = androidModel; + } + } + else { + LogManager.w(TAG, "No distance calculator may be constructed for model "+androidModel+ + " because data are missing for configured calculator "+sCalculatorClass.getName()); } } } diff --git a/src/main/java/org/altbeacon/beacon/distance/PathLossDistanceCalculator.java b/src/main/java/org/altbeacon/beacon/distance/PathLossDistanceCalculator.java new file mode 100644 index 000000000..d0ceba05c --- /dev/null +++ b/src/main/java/org/altbeacon/beacon/distance/PathLossDistanceCalculator.java @@ -0,0 +1,63 @@ +package org.altbeacon.beacon.distance; + +import org.altbeacon.beacon.logging.LogManager; + +/** + * This class estimates the distance between the mobile device and a BLE beacon based on the measured + * RSSI and a txPower calibration value that represents the expected RSSI for an iPhone 5 receiving + * the signal when it is 1 meter away. + *

+ * This class uses a path loss equation with receiverRssiSlope and receiverRssiOffset parameter. + * The offset must be supplied by the caller and is specific to the Android device being used. + * See the ModelSpecificDistanceCalculator for more information on the offset. + *

+ * Created by dyoung on 7/26/15. + */ +public class PathLossDistanceCalculator implements DistanceCalculator { + + public static final String TAG = "PathLossDistanceCalculator"; + private double mReceiverRssiSlope; + private double mReceiverRssiOffset; + + /** + * Construct a calculator with an offset specific for the device's antenna gain + * + * @param receiverRssiOffset + */ + public PathLossDistanceCalculator(double receiverRssiSlope, double receiverRssiOffset) { + mReceiverRssiSlope = receiverRssiSlope; + mReceiverRssiOffset = receiverRssiOffset; + } + + /** + * Calculated the estimated distance in meters to the beacon based on a reference rssi at 1m + * and the known actual rssi at the current location + * + * @param txPower + * @param rssi + * @return estimated distance + */ + @Override + public double calculateDistance(int txPower, double rssi) { + if (rssi == 0) { + return -1.0; // if we cannot determine accuracy, return -1. + } + + LogManager.d(TAG, "calculating distance based on mRssi of %s and txPower of %s", rssi, txPower); + + + double ratio = rssi * 1.0 / txPower; + double distance; + if (ratio < 1.0) { + distance = Math.pow(ratio, 10); + } else { + double adjustment = +mReceiverRssiSlope*rssi+mReceiverRssiOffset; + double adjustedRssi = rssi-adjustment; + System.out.println("Adjusting rssi by "+adjustment+" when rssi is "+rssi); + System.out.println("Adjusted rssi is now "+adjustedRssi); + distance = Math.pow(10.0, ((-adjustedRssi+txPower)/10*0.35)); + } + LogManager.d(TAG, "avg mRssi: %s distance: %s", rssi, distance); + return distance; + } +} diff --git a/src/main/java/org/altbeacon/beacon/service/BeaconService.java b/src/main/java/org/altbeacon/beacon/service/BeaconService.java index 1ec4932bc..81e14e71b 100644 --- a/src/main/java/org/altbeacon/beacon/service/BeaconService.java +++ b/src/main/java/org/altbeacon/beacon/service/BeaconService.java @@ -451,6 +451,7 @@ protected Void doInBackground(ScanData... params) { } } if (beacon != null) { + android.util.Log.d(TAG, "brssi, "+(new java.util.Date().getTime())+", "+scanData.rssi); mDetectionTracker.recordDetection(); processBeaconFromScan(beacon); } diff --git a/src/main/java/org/altbeacon/beacon/service/RangedBeacon.java b/src/main/java/org/altbeacon/beacon/service/RangedBeacon.java index 34722c4a0..c4b77d826 100644 --- a/src/main/java/org/altbeacon/beacon/service/RangedBeacon.java +++ b/src/main/java/org/altbeacon/beacon/service/RangedBeacon.java @@ -14,6 +14,7 @@ public class RangedBeacon { //kept here for backward compatibility public static final long DEFAULT_SAMPLE_EXPIRATION_MILLISECONDS = 20000; /* 20 seconds */ private static long sampleExpirationMilliseconds = DEFAULT_SAMPLE_EXPIRATION_MILLISECONDS; + private static long mAdvertisementCount = 0; private boolean mTracked = true; protected long lastTrackedTimeMillis = 0; Beacon mBeacon; @@ -62,6 +63,10 @@ public void commitMeasurements() { } public void addMeasurement(Integer rssi) { + if (mAdvertisementCount < Long.MAX_VALUE) { + mAdvertisementCount++; + } + mBeacon.setAdvertisementCount(mAdvertisementCount); // Filter out unreasonable values per // http://stackoverflow.com/questions/30118991/rssi-returned-by-altbeacon-library-127-messes-up-distance if (rssi != 127) { diff --git a/src/main/resources/model-distance-calculations-r2.json b/src/main/resources/model-distance-calculations-r2.json new file mode 100644 index 000000000..667bdd24a --- /dev/null +++ b/src/main/resources/model-distance-calculations-r2.json @@ -0,0 +1,61 @@ +{ + "models": + [ + { + "coefficient1": 0.42093, + "coefficient2": 6.9476, + "coefficient3": 0.54992, + "receiver_rssi_offset": -4, + "receiver_rssi_slope": 0, + "version":"4.4.2", + "build_number":"KOT49H", + "model":"Nexus 4", + "manufacturer":"LGE" + }, + { + "coefficient1": 0.42093, + "coefficient2": 6.9476, + "coefficient3": 0.54992, + "receiver_rssi_offset": -4, + "receiver_rssi_slope": 0, + "version":"4.4.2", + "build_number":"LPV79", + "model":"Nexus 5", + "manufacturer":"LGE", + "default": true + }, + { + "receiver_rssi_offset": -10, + "receiver_rssi_slope": 0, + "version":"5.1.1", + "build_number":"LVY48C", + "model":"Moto G", + "manufacturer":"motorola" + }, + { + "receiver_rssi_offset": -21.25, + "receiver_rssi_slope": 0, + "version":"5.0", + "build_number":"LRX21T", + "model":"SM-G900V", + "manufacturer":"samsung" + }, + { + "receiver_rssi_offset": -4, + "receiver_rssi_slope": 0, + "version":"4.4.2", + "build_number":"KOT49H", + "model":"SCH-I535", + "manufacturer":"samsung" + }, + { + "receiver_rssi_offset": 11.38316832, + "receiver_rssi_slope": 0.2772277228, + "version":"5.1.1", + "build_number":"LMY47X.G928TUVU2COI5", + "model":"SM-G928T", + "manufacturer":"samsung" + } + + ] +} diff --git a/src/test/java/org/altbeacon/beacon/BeaconTest.java b/src/test/java/org/altbeacon/beacon/BeaconTest.java index e31e6f545..434e0a611 100644 --- a/src/test/java/org/altbeacon/beacon/BeaconTest.java +++ b/src/test/java/org/altbeacon/beacon/BeaconTest.java @@ -166,6 +166,7 @@ public void testCanSerializeParcelable() { Beacon beacon = new AltBeacon.Builder().setId1("1").setId2("2").setId3("3").setRssi(4) .setBeaconTypeCode(5).setTxPower(6).setBluetoothName("xx") .setBluetoothAddress("1:2:3:4:5:6").setDataFields(Arrays.asList(100l)).build(); + beacon.setRunningAverageRssi(-15.0); beacon.writeToParcel(parcel, 0); parcel.setDataPosition(0); Beacon beacon2 = new Beacon(parcel); @@ -182,6 +183,7 @@ public void testCanSerializeParcelable() { assertEquals("manufacturer is same after deserialization", beacon.getManufacturer(), beacon2.getManufacturer()); assertEquals("data field 0 is the same after deserialization", beacon.getDataFields().get(0), beacon2.getDataFields().get(0)); assertEquals("data field 0 is the right value", beacon.getDataFields().get(0), (Long) 100l); + assertEquals("running average rssi is the right value", beacon2.getRunningAverageRssi(), -15.0, 0.001); } @Test diff --git a/src/test/java/org/altbeacon/beacon/RegionTest.java b/src/test/java/org/altbeacon/beacon/RegionTest.java index e6dca7ae8..34d64feca 100644 --- a/src/test/java/org/altbeacon/beacon/RegionTest.java +++ b/src/test/java/org/altbeacon/beacon/RegionTest.java @@ -175,5 +175,22 @@ public void testConvenienceIdentifierAccessors() { assertEquals("3", region.getId3().toString()); } + @Test + public void testSingleIdentifierMatchesWildcardRegion() { + ArrayList idlist = new ArrayList(1); + idlist.add(Identifier.fromInt(123)); + + Beacon beacon = new Beacon.Builder() + .setIdentifiers(idlist) + .setManufacturer(0x4c) + .setTxPower(-59) + .build(); + + Region region = new Region("com.example.myapp.boostrapRegion", null, null, null); + + assertTrue("Beacon should match region", region.matchesBeacon(beacon)); + } + + } diff --git a/src/test/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculatorTest.java b/src/test/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculatorTest.java index 0a97f1ad2..103b2d229 100644 --- a/src/test/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculatorTest.java +++ b/src/test/java/org/altbeacon/beacon/distance/ModelSpecificDistanceCalculatorTest.java @@ -3,6 +3,7 @@ import android.content.Context; import org.junit.Test; +import org.junit.Before; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @@ -26,6 +27,12 @@ * Created by dyoung on 8/28/14. */ public class ModelSpecificDistanceCalculatorTest { + + @Before + public void setup() { + ModelSpecificDistanceCalculator.setDistanceCalculatorClass(CurveFittedDistanceCalculator.class); + } + @Test public void testCalculatesDistance() { org.robolectric.shadows.ShadowLog.stream = System.err; @@ -35,6 +42,51 @@ public void testCalculatesDistance() { assertEquals("Distance should be 1.0 for same power and rssi", 1.0, distance, 0.1); } + @Test + public void testCalculatesDistanceAt10MetersOnANexus5() { + org.robolectric.shadows.ShadowLog.stream = System.err; + AndroidModel model = new AndroidModel("5.0.0", "LPV79","Nexus 5","LGE"); + + ModelSpecificDistanceCalculator distanceCalculator = new ModelSpecificDistanceCalculator(null, null, model); + Double distance = distanceCalculator.calculateDistance(-45,-71); + assertEquals("Distance should be 10.0 ", 10.0, distance, 1.0); + } + + /* + @Test + public void testCalculatesDistanceAt5MetersOnANexus5WithPathLossFormula() { + org.robolectric.shadows.ShadowLog.stream = System.err; + AndroidModel model = new AndroidModel("5.0.0", "LPV79","Nexus 5","LGE"); + ModelSpecificDistanceCalculator.setDistanceCalculatorClass(PathLossDistanceCalculator.class); + + ModelSpecificDistanceCalculator distanceCalculator = new ModelSpecificDistanceCalculator(null, null, model); + Double distance = distanceCalculator.calculateDistance(-53,-64); + assertEquals("Distance should be 5.0 ", 5.0, distance, 1.0); + } + */ + + @Test + public void testCalculatesDistanceAt10MetersOnAGalaxyS6EdgePlusWithPathLossFormula() { + org.robolectric.shadows.ShadowLog.stream = System.err; + AndroidModel model = new AndroidModel("5.1.1", "LMY47X.G928TUVU2COI5","SM-G928T","samsung"); + ModelSpecificDistanceCalculator.setDistanceCalculatorClass(PathLossDistanceCalculator.class); + + ModelSpecificDistanceCalculator distanceCalculator = new ModelSpecificDistanceCalculator(null, null, model); + Double distance = distanceCalculator.calculateDistance(-48,-81); + assertEquals("Distance should be 10.0 ", 5.0, distance, 1.0); + } + + @Test + public void testCalculatesDistanceAt10MetersOnAGalaxyS6EdgePlusWithPathLossFormulaAndLowPowerDot() { + org.robolectric.shadows.ShadowLog.stream = System.err; + AndroidModel model = new AndroidModel("5.1.1", "LMY47X.G928TUVU2COI5","SM-G928T","samsung"); + ModelSpecificDistanceCalculator.setDistanceCalculatorClass(PathLossDistanceCalculator.class); + + ModelSpecificDistanceCalculator distanceCalculator = new ModelSpecificDistanceCalculator(null, null, model); + Double distance = distanceCalculator.calculateDistance(-56,-74); + assertEquals("Distance should be 2.0 ", 2.0, distance, 1.0); + } + @Test public void testSelectsDefaultModel() { org.robolectric.shadows.ShadowLog.stream = System.err; @@ -52,6 +104,17 @@ public void testSelectsNexus4OnExactMatch() { assertEquals("should be Nexus 4", "Nexus 4", distanceCalculator.getModel().getModel()); } + @Test + public void testSelectsSamsungS3OnEPartialMatch() { + org.robolectric.shadows.ShadowLog.stream = System.err; + ModelSpecificDistanceCalculator.setDistanceCalculatorClass(PathLossDistanceCalculator.class); + AndroidModel model = new AndroidModel("4.4.4.4.4", "nonsense","SCH-I536","samsung"); + ModelSpecificDistanceCalculator distanceCalculator = new ModelSpecificDistanceCalculator(null, null, model); + assertEquals("should be S3 SCH-I535", "SCH-I535", distanceCalculator.getModel().getModel()); + } + + + @Test public void testConcurrentModificationException() { org.robolectric.shadows.ShadowLog.stream = System.err; @@ -60,7 +123,7 @@ public void testConcurrentModificationException() { final AndroidModel model = new AndroidModel("4.4.2", "KOT49H", "Nexus 4", "LGE"); final String modelMapJson = - "{\"models\":[ \"coefficient1\": 0.89976,\"coefficient2\": 7.7095,\"coefficient3\": 0.111," + + "{\"models\":[ {\"coefficient1\": 0.89976,\"coefficient2\": 7.7095,\"coefficient3\": 0.111," + "\"version\":\"4.4.2\",\"build_number\":\"KOT49H\",\"model\":\"Nexus 4\"," + "\"manufacturer\":\"LGE\"},{\"coefficient1\": 0.42093,\"coefficient2\": 6.9476," + "\"coefficient3\": 0.54992,\"version\":\"4.4.2\",\"build_number\":\"LPV79\"," + diff --git a/src/test/resources/model-distance-calculations-r2.json b/src/test/resources/model-distance-calculations-r2.json new file mode 100644 index 000000000..667bdd24a --- /dev/null +++ b/src/test/resources/model-distance-calculations-r2.json @@ -0,0 +1,61 @@ +{ + "models": + [ + { + "coefficient1": 0.42093, + "coefficient2": 6.9476, + "coefficient3": 0.54992, + "receiver_rssi_offset": -4, + "receiver_rssi_slope": 0, + "version":"4.4.2", + "build_number":"KOT49H", + "model":"Nexus 4", + "manufacturer":"LGE" + }, + { + "coefficient1": 0.42093, + "coefficient2": 6.9476, + "coefficient3": 0.54992, + "receiver_rssi_offset": -4, + "receiver_rssi_slope": 0, + "version":"4.4.2", + "build_number":"LPV79", + "model":"Nexus 5", + "manufacturer":"LGE", + "default": true + }, + { + "receiver_rssi_offset": -10, + "receiver_rssi_slope": 0, + "version":"5.1.1", + "build_number":"LVY48C", + "model":"Moto G", + "manufacturer":"motorola" + }, + { + "receiver_rssi_offset": -21.25, + "receiver_rssi_slope": 0, + "version":"5.0", + "build_number":"LRX21T", + "model":"SM-G900V", + "manufacturer":"samsung" + }, + { + "receiver_rssi_offset": -4, + "receiver_rssi_slope": 0, + "version":"4.4.2", + "build_number":"KOT49H", + "model":"SCH-I535", + "manufacturer":"samsung" + }, + { + "receiver_rssi_offset": 11.38316832, + "receiver_rssi_slope": 0.2772277228, + "version":"5.1.1", + "build_number":"LMY47X.G928TUVU2COI5", + "model":"SM-G928T", + "manufacturer":"samsung" + } + + ] +} diff --git a/src/test/resources/model-distance-calculations.json b/src/test/resources/model-distance-calculations.json index 64b445460..015f30ec8 100644 --- a/src/test/resources/model-distance-calculations.json +++ b/src/test/resources/model-distance-calculations.json @@ -2,9 +2,9 @@ "models": [ { - "coefficient1": 0.89976, - "coefficient2": 7.7095, - "coefficient3": 0.111, + "coefficient1": 0.42093, + "coefficient2": 6.9476, + "coefficient3": 0.54992, "version":"4.4.2", "build_number":"KOT49H", "model":"Nexus 4",