From acb4deff27f1d7a17dcfe4b0a1f9fe1e59112259 Mon Sep 17 00:00:00 2001 From: Markus Bullmann Date: Tue, 11 Jun 2019 16:11:17 +0200 Subject: [PATCH] Added Wifi FTM Sensor --- app/build.gradle | 4 +- .../java/android/net/wifi/ScanResultHack.java | 43 +++++ .../indoor/sensorreadout/MainActivity.java | 19 ++- .../indoor/sensorreadout/sensors/WiFiRTT.java | 160 ++++++++++++++++++ 4 files changed, 219 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/android/net/wifi/ScanResultHack.java create mode 100644 app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java diff --git a/app/build.gradle b/app/build.gradle index 983ed45..df965fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,7 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion '26.0.2' + compileSdkVersion 28 defaultConfig { applicationId "de.fhws.indoor.sensorreadout" @@ -10,6 +9,7 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + multiDexEnabled true } buildTypes { release { diff --git a/app/src/main/java/android/net/wifi/ScanResultHack.java b/app/src/main/java/android/net/wifi/ScanResultHack.java new file mode 100644 index 0000000..9a37df2 --- /dev/null +++ b/app/src/main/java/android/net/wifi/ScanResultHack.java @@ -0,0 +1,43 @@ +package android.net.wifi; + +import android.net.MacAddress; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; + +public class ScanResultHack { + + public static ScanResult createScanResultFromMacAddress(MacAddress mac) { + + // only works with targetSDK < 28 + ScanResult result = new ScanResult(); + result.BSSID = mac.toString(); + result.SSID = "tof_test"; + result.frequency = 2447; + result.capabilities = "[ESS]"; + + try { + + Class clazz = Class.forName("android.net.wifi.ScanResult$InformationElement"); + Object[] ies = (Object[]) Array.newInstance(clazz, 1); + + Object ie = clazz.getDeclaredConstructor().newInstance(); + ies[0] = ie; + + Field f1 = result.getClass().getDeclaredField("flags"); + f1.setAccessible(true); + f1.set(result, 2); + + Field f2 = result.getClass().getDeclaredField("informationElements"); + f2.setAccessible(true); + f2.set(result, ies); + + } catch (final Exception e) { + e.printStackTrace(); + } + + return result; + } +} 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 f4f22db..85d8e34 100644 --- a/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/MainActivity.java @@ -35,6 +35,7 @@ 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.WiFi; +import de.fhws.indoor.sensorreadout.sensors.WiFiRTT; import de.fhws.indoor.sensorreadout.sensors.iBeacon; import de.fhws.indoor.sensorreadout.sensors.iBeaconOld; import de.fhws.indoor.sensorreadout.sensors.mySensor; @@ -277,11 +278,19 @@ public class MainActivity extends Activity { }); // logo wifi using sensor number 8 - final WiFi wifi = new WiFi(this); - sensors.add(wifi); - wifi.setListener(new mySensor.SensorListener() { - @Override public void onData(final String csv) { add(SensorType.WIFI, csv); } - @Override public void onData(final SensorType id, final String csv) {return; } +// final WiFi wifi = new WiFi(this); +// sensors.add(wifi); +// wifi.setListener(new mySensor.SensorListener() { +// @Override public void onData(final String csv) { add(SensorType.WIFI, csv); } +// @Override public void onData(final SensorType id, final String csv) {return; } +// }); + + // log wifi RTT using sensor number 17 + final WiFiRTT wifirtt = new WiFiRTT(this); + sensors.add(wifirtt); + wifirtt.setListener(new mySensor.SensorListener() { + @Override public void onData(final String csv) { add(SensorType.WIFIRTT, csv); } + @Override public void onData(final SensorType id, final String csv) {add(id, csv); } }); //log gps using sensor number 16 diff --git a/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java new file mode 100644 index 0000000..ea57e86 --- /dev/null +++ b/app/src/main/java/de/fhws/indoor/sensorreadout/sensors/WiFiRTT.java @@ -0,0 +1,160 @@ +package de.fhws.indoor.sensorreadout.sensors; +//package android.net.wifi; + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.net.MacAddress; +import android.net.wifi.ScanResult; +import android.net.wifi.ScanResultHack; +import android.net.wifi.rtt.RangingRequest; +import android.net.wifi.rtt.RangingResult; +import android.net.wifi.rtt.RangingResultCallback; +import android.net.wifi.rtt.WifiRttManager; +import android.support.v4.app.ActivityCompat; +import android.util.Log; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +public class WiFiRTT extends mySensor { + + private final Activity act; + private final WifiRttManager rttManager; + private Executor mainExecutor; + + private Thread ftmThread; + private boolean ftmRunning; + + + public WiFiRTT(final Activity act) { + this.act = act; + this.rttManager = (WifiRttManager) act.getSystemService(Context.WIFI_RTT_RANGING_SERVICE); + this.mainExecutor = act.getMainExecutor(); + } + + @Override + public void onResume(Activity act) { + startScan(); + } + + @Override + public void onPause(Activity act) { + stopScan(); + } + + private void startScan() { + if (ftmRunning) + return; + + ftmRunning = true; + + final ArrayList macs = new ArrayList<>(); + macs.add(MacAddress.fromString("38:de:ad:6d:77:25")); // NUC 1 + macs.add(MacAddress.fromString("38:de:ad:6d:60:ff")); // NUC 2 + macs.add(MacAddress.fromString("1c:1b:b5:ef:a2:9a")); // NUC 3 + macs.add(MacAddress.fromString("1c:1b:b5:ec:d1:82")); // NUC 4 + + ftmThread = new Thread() { + public void run() { + while (ftmRunning) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + startRangingOnMacs(macs); + } + } + }; + + ftmThread.start(); + } + + private void stopScan() { + ftmRunning = false; + } + + private void startRangingOnMacs(final ArrayList macs) { + RangingRequest.Builder builder = new RangingRequest.Builder(); + + for (final MacAddress mac : macs) { + //builder.addWifiAwarePeer(mac); + + ScanResult sr = ScanResultHack.createScanResultFromMacAddress(mac); + builder.addAccessPoint(sr); + } + + // fire# + if (ActivityCompat.checkSelfPermission(act, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + ftmRunning = false; + } else { + final RangingRequest request = builder.build(); + rttManager.startRanging(request, mainExecutor, rangeCallback); + } + } + + + + // result callback + private final RangingResultCallback rangeCallback = new RangingResultCallback() { + @Override + public void onRangingFailure(final int i) { + //emitter.onError(new RuntimeException("The WiFi-Ranging failed with error code: " + i)); + Log.d("RTT", "onRangingFailure: " + i); + } + + @Override + public void onRangingResults(final List list) { + //emitter.onSuccess(list); + Log.d("RTT", "onRangingResults: " + list.size()); + + for (final RangingResult res : list) { + + int success = 0; + MacAddress mac = res.getMacAddress(); + int dist = 0; + int stdDevDist = 0; + int rssi = 0; + int numAttemptedMeas = 0; + int numSuccessfulMeas = 0; + + if (res.getStatus() == RangingResult.STATUS_SUCCESS) { + success = 1; + dist = res.getDistanceMm(); + stdDevDist = res.getDistanceStdDevMm(); + rssi = res.getRssi(); + numAttemptedMeas = res.getNumAttemptedMeasurements(); + numSuccessfulMeas = res.getNumSuccessfulMeasurements(); + + Log.d("RTT", mac.toString() + " " + dist + " " + stdDevDist + " " + rssi); + } else { + Log.d("RTT", mac.toString() + " FAILED"); + } + + if (listener != null) { + // success; mac; dist; stdDevDist; RSSI; numAttemptedMeas; numSuccessfulMeas + StringBuilder sb = new StringBuilder(); + + sb.append(success).append(';'); + sb.append(Helper.stripMAC(mac.toString())).append(';'); + sb.append(dist).append(';'); + sb.append(stdDevDist).append(';'); + sb.append(rssi).append(';'); + sb.append(numAttemptedMeas).append(';'); + sb.append(numSuccessfulMeas); + + + listener.onData(SensorType.WIFIRTT, sb.toString()); + } + } + } + }; +}