Initial commit
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -37,4 +37,4 @@ Makefile*
|
|||||||
# QtCtreator CMake
|
# QtCtreator CMake
|
||||||
CMakeLists.txt.user*
|
CMakeLists.txt.user*
|
||||||
|
|
||||||
|
PaxHeader/
|
||||||
|
|||||||
105
Manager.cpp
Normal file
105
Manager.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#include "Manager.h"
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
#include <QtAndroidExtras/QAndroidJniObject>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
const std::string NUC1 = "38:de:ad:6d:77:25";
|
||||||
|
const std::string NUC2 = "38:de:ad:6d:60:ff";
|
||||||
|
const std::string NUC3 = "1c:1b:b5:ef:a2:9a";
|
||||||
|
const std::string NUC4 = "1c:1b:b5:ec:d1:82";
|
||||||
|
|
||||||
|
Manager::Manager() {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::trigger() {
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
|
||||||
|
QAndroidJniObject::callStaticMethod<int>("android/net/wifi/RTT", "start", "()I");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
//onData("38:de:ad:6d:77:25;FAILED");
|
||||||
|
onData(NUC1+";6230;1231");
|
||||||
|
onData(NUC2+";3430;3423");
|
||||||
|
onData(NUC3+";5630;2341");
|
||||||
|
onData(NUC4+";8830;2241");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::onData(std::string str) {
|
||||||
|
|
||||||
|
qDebug() << QString(str.c_str());
|
||||||
|
|
||||||
|
std::stringstream lineStream(str);
|
||||||
|
std::string cell;
|
||||||
|
|
||||||
|
std::string mac;
|
||||||
|
|
||||||
|
int distIndex = 0;
|
||||||
|
int i = 0;
|
||||||
|
const float alpha = 0.7f;
|
||||||
|
|
||||||
|
while (std::getline(lineStream, cell, ';')) {
|
||||||
|
|
||||||
|
switch(i) {
|
||||||
|
|
||||||
|
case 0: {
|
||||||
|
if(NUC1 == cell) {distIndex = 0;}
|
||||||
|
if(NUC2 == cell) {distIndex = 1;}
|
||||||
|
if(NUC3 == cell) {distIndex = 2;}
|
||||||
|
if(NUC4 == cell) {distIndex = 3;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: {
|
||||||
|
if ("FAILED" == cell) {
|
||||||
|
_dist[distIndex] = 0;
|
||||||
|
} else {
|
||||||
|
//_dist[distIndex] = std::stoi(cell);
|
||||||
|
_dist[distIndex] = _dist[distIndex] * alpha + atoi(cell.c_str()) * (1-alpha);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
_stdDev[distIndex] = atoi(cell.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit distChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Manager mgmt;
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_android_net_wifi_RTT_onRTTComplete(JNIEnv* env, jobject jobj, jbyteArray arrayID) {
|
||||||
|
(void) env; (void) jobj;
|
||||||
|
jsize length = env->GetArrayLength(arrayID);
|
||||||
|
jbyte* data = env->GetByteArrayElements(arrayID, 0);
|
||||||
|
std::string str((char*)data, length);
|
||||||
|
env->ReleaseByteArrayElements(arrayID, data, JNI_ABORT);
|
||||||
|
mgmt.onData(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
54
Manager.h
Normal file
54
Manager.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef MANAGER_H
|
||||||
|
#define MANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class Manager : public QObject {
|
||||||
|
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
float _dist[4];
|
||||||
|
float _stdDev[4];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Q_PROPERTY(float dist1 READ getDist1() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float dist2 READ getDist2() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float dist3 READ getDist3() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float dist4 READ getDist4() NOTIFY distChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(float stdDev1 READ getStdDev1() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float stdDev2 READ getStdDev2() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float stdDev3 READ getStdDev3() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float stdDev4 READ getStdDev4() NOTIFY distChanged)
|
||||||
|
|
||||||
|
|
||||||
|
Q_INVOKABLE void trigger();
|
||||||
|
|
||||||
|
void onData(std::string str);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
float getDist1() {return _dist[0];}
|
||||||
|
float getDist2() {return _dist[1];}
|
||||||
|
float getDist3() {return _dist[2];}
|
||||||
|
float getDist4() {return _dist[3];}
|
||||||
|
|
||||||
|
float getStdDev1() {return _stdDev[0];}
|
||||||
|
float getStdDev2() {return _stdDev[1];}
|
||||||
|
float getStdDev3() {return _stdDev[2];}
|
||||||
|
float getStdDev4() {return _stdDev[3];}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void distChanged();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Manager();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MANAGER_H
|
||||||
45
RTT.pro
Normal file
45
RTT.pro
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
QT += quick
|
||||||
|
QT += androidextras
|
||||||
|
CONFIG += c++11
|
||||||
|
|
||||||
|
# The following define makes your compiler emit warnings if you use
|
||||||
|
# any feature of Qt which as been marked deprecated (the exact warnings
|
||||||
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
# deprecated API in order to know how to port your code away from it.
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
|
||||||
|
# You can also make your code fail to compile if you use deprecated APIs.
|
||||||
|
# In order to do so, uncomment the following line.
|
||||||
|
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
main.cpp \
|
||||||
|
Manager.cpp
|
||||||
|
|
||||||
|
RESOURCES += qml.qrc
|
||||||
|
|
||||||
|
OTHER_FILES += \
|
||||||
|
_android/src/MyActivity.java\
|
||||||
|
_android/src/WiFi.java\
|
||||||
|
_android/src/RTT.java\
|
||||||
|
_android/src/LocationPermissionController.java\
|
||||||
|
_android/AndroidManifest.xml
|
||||||
|
|
||||||
|
# use files in ./_android for the project as well
|
||||||
|
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/_android
|
||||||
|
|
||||||
|
|
||||||
|
# Additional import path used to resolve QML modules in Qt Creator's code model
|
||||||
|
QML_IMPORT_PATH =
|
||||||
|
|
||||||
|
# Additional import path used to resolve QML modules just for Qt Quick Designer
|
||||||
|
QML_DESIGNER_IMPORT_PATH =
|
||||||
|
|
||||||
|
# Default rules for deployment.
|
||||||
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
|
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
Manager.h
|
||||||
49
_android/AndroidManifest.xml
Normal file
49
_android/AndroidManifest.xml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<manifest package="indoor.java" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
|
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="26"/>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
|
<uses-permission android:name="android.permission.BODY_SENSORS"/>
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
||||||
|
|
||||||
|
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||||
|
|
||||||
|
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/app_name">
|
||||||
|
|
||||||
|
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="indoor.java.MyActivity" android:label="TEST" android:screenOrientation="unspecified">
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
|
||||||
|
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
||||||
|
<meta-data android:name="android.app.repository" android:value="default"/>
|
||||||
|
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||||
|
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
||||||
|
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||||
|
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||||
|
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
||||||
|
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
||||||
|
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
||||||
|
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
||||||
|
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
||||||
|
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
8
_android/build.gradle.2
Normal file
8
_android/build.gradle.2
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
buildscript {
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
compile "com.android.support:support-v4:23.0.+"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
70
_android/src/LocationPermissionController.java
Normal file
70
_android/src/LocationPermissionController.java
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package de.plinzen.android.rttmanager.permission;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
//import android.support.design.widget.Snackbar;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
//import de.plinzen.android.rttmanager.R;
|
||||||
|
|
||||||
|
/*
|
||||||
|
public class LocationPermissionController {
|
||||||
|
|
||||||
|
private static final int REQUEST_LOCATION_PERMISSION = 8545;
|
||||||
|
|
||||||
|
public boolean checkLocationPermissions(final Context context) {
|
||||||
|
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) ==
|
||||||
|
PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(context, Manifest.permission
|
||||||
|
.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions,
|
||||||
|
@NonNull final int[] grantResults) {
|
||||||
|
if (requestCode == REQUEST_LOCATION_PERMISSION) {
|
||||||
|
return verifyPermissions(grantResults);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestLocationPermission(final Activity activity, final View snackbarContainer) {
|
||||||
|
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_COARSE_LOCATION) ||
|
||||||
|
ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission
|
||||||
|
.ACCESS_FINE_LOCATION)) {
|
||||||
|
// Snackbar.make(snackbarContainer, R.string.permission_location_description, Snackbar.LENGTH_INDEFINITE)
|
||||||
|
// .setAction(android.R.string.ok, view -> requestPermissions(activity)).show();
|
||||||
|
Snackbar.make(snackbarContainer, R.string.permission_location_description, Snackbar.LENGTH_INDEFINITE)
|
||||||
|
.setAction(android.R.string.ok, new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
requestPermissions(activity);
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
} else {
|
||||||
|
requestPermissions(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestPermissions(final Activity activity) {
|
||||||
|
// ActivityCompat.requestPermissions(activity,
|
||||||
|
// new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
|
||||||
|
// REQUEST_LOCATION_PERMISSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean verifyPermissions(int[] grantResults) {
|
||||||
|
if (grantResults.length < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int result : grantResults) {
|
||||||
|
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
37
_android/src/MyActivity.java
Normal file
37
_android/src/MyActivity.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package indoor.java;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
public class MyActivity extends QtActivity {
|
||||||
|
|
||||||
|
public static MyActivity act;
|
||||||
|
|
||||||
|
// IPIN2016
|
||||||
|
//private StepLoggerClient stepLogger;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedState) {
|
||||||
|
|
||||||
|
MyActivity.act = this;
|
||||||
|
super.onCreate(savedState);
|
||||||
|
|
||||||
|
// prevent power-safe?
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
|
// IPIN2016
|
||||||
|
//stepLogger = new StepLoggerClient(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
MyActivity.act = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
195
_android/src/RTT.java
Normal file
195
_android/src/RTT.java
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
//package indoor.java;
|
||||||
|
package android.net.wifi;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import android.net.wifi.ScanResult;
|
||||||
|
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 java.util.concurrent.Executor;
|
||||||
|
import android.net.MacAddress;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
|
import indoor.java.MyActivity;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
|
||||||
|
public class RTT {
|
||||||
|
|
||||||
|
private static Activity act;
|
||||||
|
private static WifiRttManager rttManager;
|
||||||
|
private static Executor mainExecutor;
|
||||||
|
|
||||||
|
// called when a RTT is completed successfully
|
||||||
|
public static native void onRTTComplete(final byte[] result);
|
||||||
|
|
||||||
|
// result callback
|
||||||
|
private static final RangingResultCallback callback = 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<RangingResult> list) {
|
||||||
|
//emitter.onSuccess(list);
|
||||||
|
Log.d("RTT", "onRangingResults: " + list.size());
|
||||||
|
|
||||||
|
for (final RangingResult res : list) {
|
||||||
|
|
||||||
|
final MacAddress mac = res.getMacAddress();
|
||||||
|
if (res.getStatus() == RangingResult.STATUS_SUCCESS) {
|
||||||
|
final int dist = res.getDistanceMm();
|
||||||
|
final int stdDevDist = res.getDistanceStdDevMm();
|
||||||
|
Log.d("RTT", mac.toString() + " " + dist + " " + stdDevDist);
|
||||||
|
} else {
|
||||||
|
Log.d("RTT", mac.toString() + " FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
RTT.onRTTComplete(serialize(res));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static byte[] serialize(final RangingResult res) {
|
||||||
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
|
||||||
|
char delim = ';';
|
||||||
|
|
||||||
|
baos.write(res.getMacAddress().toString().getBytes());
|
||||||
|
baos.write(delim);
|
||||||
|
|
||||||
|
if (res.getStatus() == RangingResult.STATUS_SUCCESS) {
|
||||||
|
baos.write( ("" + res.getDistanceMm()).getBytes() );
|
||||||
|
baos.write(delim);
|
||||||
|
baos.write( ("" + res.getDistanceStdDevMm()).getBytes() );
|
||||||
|
} else {
|
||||||
|
baos.write( "FAILED".getBytes() );
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (final Exception e) {;}
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int start() {
|
||||||
|
|
||||||
|
Log.d("RTT", "start()");
|
||||||
|
|
||||||
|
MyActivity act = MyActivity.act;
|
||||||
|
rttManager = (WifiRttManager) act.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
|
||||||
|
|
||||||
|
mainExecutor = act.getMainExecutor();
|
||||||
|
|
||||||
|
final ArrayList<MacAddress> 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
|
||||||
|
|
||||||
|
new Thread() {
|
||||||
|
public void run() {
|
||||||
|
while(true) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(200);
|
||||||
|
} catch (Exception e) {;}
|
||||||
|
startRangingOnMacs(macs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
|
||||||
|
|
||||||
|
return 1337;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startRangingOnMacs(final ArrayList<MacAddress> macs) {
|
||||||
|
|
||||||
|
Log.d("RTT", "startRangingOnMac()");
|
||||||
|
|
||||||
|
RangingRequest.Builder builder = new RangingRequest.Builder();
|
||||||
|
|
||||||
|
for (final MacAddress mac : macs) {
|
||||||
|
|
||||||
|
ScanResult sr = new ScanResult();
|
||||||
|
sr.BSSID = mac.toString();
|
||||||
|
sr.SSID = "tof_test";
|
||||||
|
sr.frequency = 2447;
|
||||||
|
sr.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 = sr.getClass().getDeclaredField("flags");
|
||||||
|
f1.setAccessible(true);
|
||||||
|
f1.set(sr, 2);
|
||||||
|
|
||||||
|
Field f2 = sr.getClass().getDeclaredField("informationElements");
|
||||||
|
f2.setAccessible(true);
|
||||||
|
f2.set(sr, ies);
|
||||||
|
|
||||||
|
builder.addAccessPoint(sr);
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("RTT", "startRanging() on " + macs.size());
|
||||||
|
if (macs.size() == 0) {return;}
|
||||||
|
|
||||||
|
// fire#
|
||||||
|
final RangingRequest request = builder.build();
|
||||||
|
rttManager.startRanging(request, mainExecutor, callback);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void startRangingOnScanResult(final List<ScanResult> scanResults) {
|
||||||
|
|
||||||
|
Log.d("RTT", "startRangingOnScanResult()");
|
||||||
|
|
||||||
|
// build the request
|
||||||
|
int cnt = 0;
|
||||||
|
RangingRequest.Builder builder = new RangingRequest.Builder();
|
||||||
|
for (final ScanResult r : scanResults) {
|
||||||
|
if (r.is80211mcResponder()) {
|
||||||
|
Log.d("RTT", "- " + r.BSSID + " [supported]");
|
||||||
|
builder.addAccessPoint(r);
|
||||||
|
++cnt;
|
||||||
|
} else {
|
||||||
|
Log.d("RTT", "- " + r.BSSID + " [NO!]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("RTT", "startRanging on " + cnt + " devices");
|
||||||
|
if (cnt == 0) {return;}
|
||||||
|
|
||||||
|
// fire
|
||||||
|
final RangingRequest request = builder.build();
|
||||||
|
rttManager.startRanging(request, mainExecutor, callback);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
181
_android/src/WiFi.java
Normal file
181
_android/src/WiFi.java
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
package indoor.java;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.net.wifi.ScanResult;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
|
import android.os.Debug;
|
||||||
|
import android.util.Log;
|
||||||
|
import java.util.List;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import android.os.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.lang.StringBuffer;
|
||||||
|
|
||||||
|
public class WiFi {
|
||||||
|
|
||||||
|
private static Activity act;
|
||||||
|
private static WifiManager manager;
|
||||||
|
private static BroadcastReceiver receiver;
|
||||||
|
|
||||||
|
private static Thread tHeartbeat = null;
|
||||||
|
private static long lastScanStartTS = 0;
|
||||||
|
|
||||||
|
// called when a scan is completed successfully
|
||||||
|
public static native void onScanComplete(final byte[] result);
|
||||||
|
|
||||||
|
private static String makeString(final byte[] arr) {
|
||||||
|
StringBuffer output=new StringBuffer();
|
||||||
|
for (byte a : arr) {
|
||||||
|
int val1 = a & 0xff;
|
||||||
|
output.append(Integer.toHexString(val1));
|
||||||
|
output.append(" ");
|
||||||
|
}
|
||||||
|
return output.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int start() {
|
||||||
|
|
||||||
|
Log.d("wifi", "start()");
|
||||||
|
|
||||||
|
MyActivity act = MyActivity.act;
|
||||||
|
manager = (WifiManager) act.getSystemService(Context.WIFI_SERVICE);
|
||||||
|
|
||||||
|
// reset();
|
||||||
|
|
||||||
|
WiFi.receiver = new BroadcastReceiver() {
|
||||||
|
public final void onReceive(final Context context, final Intent intent) {
|
||||||
|
|
||||||
|
Log.d("wifi", "onReceive()");
|
||||||
|
|
||||||
|
// trigger RTT scan
|
||||||
|
//RTT.startRangingOnScanResult(manager.getScanResults());
|
||||||
|
|
||||||
|
// serialze
|
||||||
|
final byte[] result = serialize(manager.getScanResults());
|
||||||
|
|
||||||
|
for (final ScanResult sr : manager.getScanResults()) {
|
||||||
|
|
||||||
|
Log.d("wifi", sr.BSSID + " - " + sr.SSID + " " + sr.capabilities + " " + sr.centerFreq0 + " " + sr.centerFreq1 + " " + sr.channelWidth + " " + sr.frequency + " " + sr.level);
|
||||||
|
|
||||||
|
// final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
// final ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||||
|
// oos.write(p1);
|
||||||
|
|
||||||
|
// Parcel p = Parcel.obtain();
|
||||||
|
// p.writeValue(sr);
|
||||||
|
// p.setDataPosition(0);
|
||||||
|
// byte [] b = p.marshall();
|
||||||
|
// Log.d("wifi", "" + makeString(b));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger next scan
|
||||||
|
//triggerOneScan();
|
||||||
|
|
||||||
|
// send serialized data to Qt
|
||||||
|
WiFi.onScanComplete(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// register scan callback
|
||||||
|
act.registerReceiver(WiFi.receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
|
||||||
|
|
||||||
|
// start the first scan
|
||||||
|
triggerOneScan();
|
||||||
|
|
||||||
|
// //this is a very nice hack. do not try this at home.
|
||||||
|
// Method m = null;
|
||||||
|
// try {
|
||||||
|
// m = manager.getClass().getDeclaredMethod("setFrequencyBand", int.class, boolean.class);
|
||||||
|
// m.setAccessible(true);
|
||||||
|
// m.invoke(manager, 2, true);
|
||||||
|
// m.invoke(manager, 2, true);
|
||||||
|
// m.invoke(manager, 2, true);
|
||||||
|
// Log.d("wifi", "HACK IS RUNNING, BIAAAATCH");
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// Log.d("wifi", "HACK HAS FAILED >.<");
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // if the scan result takes longer than X milliseconds,
|
||||||
|
// // trigger another-scan to ensure nothing is stuck
|
||||||
|
// final Runnable r = new Runnable() {
|
||||||
|
// public void run() {
|
||||||
|
// while(true) {
|
||||||
|
// final long ts = System.currentTimeMillis();
|
||||||
|
// final long diff = ts - lastScanStartTS;
|
||||||
|
// if (diff > 1000) { triggerOneScan(); }
|
||||||
|
// try {Thread.sleep(200);} catch (final Exception e) {;}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // start the heartbeat once
|
||||||
|
// if (tHeartbeat == null) {
|
||||||
|
// tHeartbeat = new Thread(r);
|
||||||
|
// tHeartbeat.start();
|
||||||
|
// }
|
||||||
|
|
||||||
|
return 1337;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] serialize(final List<ScanResult> lst) {
|
||||||
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
for (final ScanResult res : lst) {
|
||||||
|
baos.write(res.BSSID.getBytes());
|
||||||
|
baos.write((byte)res.level);
|
||||||
|
baos.write((byte)0);
|
||||||
|
baos.write((byte)0);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {;}
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void reset() {
|
||||||
|
WiFi.manager.disconnect();
|
||||||
|
WiFi.manager.createWifiLock(manager.WIFI_MODE_SCAN_ONLY, "Indoor");
|
||||||
|
//WiFi.manager.setWifiEnabled(false);
|
||||||
|
//WiFi.manager.setWifiEnabled(true);
|
||||||
|
WiFi.manager.disconnect();
|
||||||
|
WiFi.manager.disconnect();
|
||||||
|
WiFi.manager.disconnect();
|
||||||
|
WiFi.manager.disconnect();
|
||||||
|
WiFi.manager.disconnect();
|
||||||
|
WiFi.manager.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to trigger one scan process
|
||||||
|
private static void triggerOneScan() {
|
||||||
|
|
||||||
|
Log.d("wifi", "triggerOneScan()");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!manager.startScan()) {throw new RuntimeException("WiFi: can not startScan()");}
|
||||||
|
lastScanStartTS = System.currentTimeMillis();
|
||||||
|
}catch (final Exception e) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (Exception ex) {;}
|
||||||
|
Log.e("wifi", "triggerOneScan() failed!!!!!");
|
||||||
|
//throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
32
main.cpp
Normal file
32
main.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
|
||||||
|
#include <QQmlContext>
|
||||||
|
|
||||||
|
#include "Manager.h"
|
||||||
|
extern Manager mgmt;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
QQmlApplicationEngine engine;
|
||||||
|
|
||||||
|
engine.rootContext()->setContextProperty("mgmt", &mgmt);
|
||||||
|
|
||||||
|
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
|
||||||
|
|
||||||
|
if (engine.rootObjects().isEmpty())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//QAndroidJniObject::callStaticMethod<int>("android/net/wifi/RTT", "start", "()I");
|
||||||
|
//QAndroidJniObject::callStaticMethod<int>("indoor/java/WiFi", "start", "()I");
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
157
main.qml
Normal file
157
main.qml
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Window 2.2
|
||||||
|
import QtQuick.Controls 2.4
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: window
|
||||||
|
|
||||||
|
visible: true
|
||||||
|
width: 640
|
||||||
|
height: 680
|
||||||
|
title: qsTr("Hello World")
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "dist1: " + ((mgmt.dist1 ? mgmt.dist1+sld1.value : 0)/1000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "dist2: " + ((mgmt.dist2 ? mgmt.dist2+sld1.value : 0)/1000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "dist3: " + ((mgmt.dist3 ? mgmt.dist3+sld1.value : 0)/1000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "dist4: " + ((mgmt.dist4 ? mgmt.dist4+sld1.value : 0)/1000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
width: 400;
|
||||||
|
id: sld1;
|
||||||
|
from: -3000;
|
||||||
|
to: 5000;
|
||||||
|
onValueChanged: leCanvas.requestPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "offset: " + sld1.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: mgmt
|
||||||
|
onDistChanged: leCanvas.requestPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "party hard";
|
||||||
|
onClicked: mgmt.trigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas {
|
||||||
|
|
||||||
|
id: leCanvas;
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 0
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 0
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 0
|
||||||
|
anchors.top: column.bottom
|
||||||
|
anchors.topMargin: 20
|
||||||
|
|
||||||
|
readonly property double s: 0.02;
|
||||||
|
|
||||||
|
|
||||||
|
function leArc(ctx, cx, cy, dist, stdDev) {
|
||||||
|
|
||||||
|
// center circle
|
||||||
|
ctx.fillStyle = "#000000";
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(cx*s, cy*s, 2, 0, 360);
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// error circle
|
||||||
|
// ctx.beginPath();
|
||||||
|
// ctx.arc(cx*s, cy*s, (dist+sld1.value)*s, 0, 360);
|
||||||
|
// ctx.closePath();
|
||||||
|
// ctx.lineWidth = stdDev*s*0.5;
|
||||||
|
// ctx.strokeStyle = "#66000000";
|
||||||
|
// ctx.stroke();
|
||||||
|
|
||||||
|
// circle
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.strokeStyle = "#aa000000";
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(cx*s, cy*s, (dist+sld1.value)*s, 0, 360);
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onPaint: {
|
||||||
|
var ctx = getContext("2d")
|
||||||
|
|
||||||
|
ctx.reset();
|
||||||
|
|
||||||
|
ctx.fillStyle = "#dddddd";
|
||||||
|
ctx.clearRect(0, 0, leCanvas.width, leCanvas.height);
|
||||||
|
|
||||||
|
//ctx.strokeStyle = Qt.rgba(0, 0, 0, 1)
|
||||||
|
//ctx.lineWidth = 1
|
||||||
|
|
||||||
|
var ox = 4000;
|
||||||
|
var oy = 4000;
|
||||||
|
|
||||||
|
var cx1 = ox+0;
|
||||||
|
var cy1 = oy+0;
|
||||||
|
|
||||||
|
var cx2 = ox+0;
|
||||||
|
var cy2 = oy+7250;
|
||||||
|
|
||||||
|
var cx3 = ox+9000;
|
||||||
|
var cy3 = oy+7250;
|
||||||
|
|
||||||
|
var cx4 = ox+9000;
|
||||||
|
var cy4 = oy+0;
|
||||||
|
|
||||||
|
leArc(ctx, cx1, cy1, mgmt.dist1, mgmt.stdDev1);
|
||||||
|
leArc(ctx, cx2, cy2, mgmt.dist2, mgmt.stdDev2);
|
||||||
|
leArc(ctx, cx3, cy3, mgmt.dist3, mgmt.stdDev3);
|
||||||
|
leArc(ctx, cx4, cy4, mgmt.dist4, mgmt.stdDev4);
|
||||||
|
|
||||||
|
var sigma = 2000;
|
||||||
|
var stepSize = 333;
|
||||||
|
|
||||||
|
var maxP = Math.pow( 1.0 / Math.sqrt(2*Math.PI*sigma), 4.1);
|
||||||
|
|
||||||
|
for (var y = 0; y < leCanvas.height/s; y += stepSize) {
|
||||||
|
for (var x = 0; x < leCanvas.width/s; x += stepSize) {
|
||||||
|
|
||||||
|
var d1 = Math.sqrt( Math.pow(x-cx1, 2) + Math.pow(y-cy1, 2) ) - (mgmt.dist1-sld1.value);
|
||||||
|
var d2 = Math.sqrt( Math.pow(x-cx2, 2) + Math.pow(y-cy2, 2) ) - (mgmt.dist2-sld1.value);
|
||||||
|
var d3 = Math.sqrt( Math.pow(x-cx3, 2) + Math.pow(y-cy3, 2) ) - (mgmt.dist3-sld1.value);
|
||||||
|
var d4 = Math.sqrt( Math.pow(x-cx4, 2) + Math.pow(y-cy4, 2) ) - (mgmt.dist4-sld1.value);
|
||||||
|
|
||||||
|
var p = 1;
|
||||||
|
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d1*d1/(2*sigma*sigma) );
|
||||||
|
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d2*d2/(2*sigma*sigma) );
|
||||||
|
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d3*d3/(2*sigma*sigma) );
|
||||||
|
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d4*d4/(2*sigma*sigma) );
|
||||||
|
|
||||||
|
//p = Math.pow(p, 1);
|
||||||
|
|
||||||
|
if (p > maxP / 50) {
|
||||||
|
ctx.fillStyle = Qt.rgba(1,0,0, p/maxP);
|
||||||
|
ctx.fillRect(x*s, y*s, stepSize*s, stepSize*s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user