From 43148f4d544c8e2bb121bf2b05b10f843633de5a Mon Sep 17 00:00:00 2001 From: kazu Date: Fri, 15 Jul 2016 15:00:49 +0200 Subject: [PATCH] initial version --- _android/AndroidManifest.xml | 49 +++++++++ _android/src/MyActivity.java | 23 +++++ _android/src/WiFi.java | 101 +++++++++++++++++++ deployment.pri | 13 +++ main.cpp | 51 ++++++++++ misc/Debug.h | 16 +++ misc/fixc11.h | 13 +++ qml.qrc | 6 ++ sensors/AccelerometerSensor.h | 22 ++++ sensors/Sensor.h | 50 +++++++++ sensors/SensorFactory.h | 47 +++++++++ sensors/StepSensor.h | 66 ++++++++++++ sensors/WiFiSensor.h | 43 ++++++++ sensors/android/AccelerometerSensorAndroid.h | 55 ++++++++++ sensors/android/WiFiSensorAndroid.h | 76 ++++++++++++++ sensors/dummy/AccelerometerSensorDummy.h | 27 +++++ sensors/dummy/WiFiSensorDummy.h | 92 +++++++++++++++++ sensors/linux/WiFiSensorLinux.h | 33 ++++++ yasmin.pro | 54 ++++++++++ 19 files changed, 837 insertions(+) create mode 100644 _android/AndroidManifest.xml create mode 100644 _android/src/MyActivity.java create mode 100644 _android/src/WiFi.java create mode 100644 deployment.pri create mode 100644 main.cpp create mode 100644 misc/Debug.h create mode 100644 misc/fixc11.h create mode 100644 qml.qrc create mode 100644 sensors/AccelerometerSensor.h create mode 100644 sensors/Sensor.h create mode 100644 sensors/SensorFactory.h create mode 100644 sensors/StepSensor.h create mode 100644 sensors/WiFiSensor.h create mode 100644 sensors/android/AccelerometerSensorAndroid.h create mode 100644 sensors/android/WiFiSensorAndroid.h create mode 100644 sensors/dummy/AccelerometerSensorDummy.h create mode 100644 sensors/dummy/WiFiSensorDummy.h create mode 100644 sensors/linux/WiFiSensorLinux.h create mode 100644 yasmin.pro diff --git a/_android/AndroidManifest.xml b/_android/AndroidManifest.xml new file mode 100644 index 0000000..5978c42 --- /dev/null +++ b/_android/AndroidManifest.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_android/src/MyActivity.java b/_android/src/MyActivity.java new file mode 100644 index 0000000..871850e --- /dev/null +++ b/_android/src/MyActivity.java @@ -0,0 +1,23 @@ +package our.java.stuff; + +import android.os.Bundle; +import org.qtproject.qt5.android.bindings.QtActivity; + +public class MyActivity extends QtActivity { + + public static MyActivity act; + + @Override + public void onCreate(Bundle savedState) { + MyActivity.act = this; + super.onCreate(savedState); + } + + @Override + public void onDestroy() { + super.onDestroy(); + MyActivity.act = null; + } + + +} diff --git a/_android/src/WiFi.java b/_android/src/WiFi.java new file mode 100644 index 0000000..e883432 --- /dev/null +++ b/_android/src/WiFi.java @@ -0,0 +1,101 @@ +package java.indoor; + +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; + +public class WiFi { + + private static Activity act; + private static WifiManager manager; + private static BroadcastReceiver receiver; + + + + /** called when a scan is completed successfully */ + public static native void onScanComplete(final byte[] result); + + /** + * start WiFi scanning in the background. + * will call onScanComplete() once a scan is available + */ + 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) { + final byte[] result = serialize(manager.getScanResults()); + WiFi.onScanComplete(result); + triggerOneScan(); + } + }; + + // register scan callback + act.registerReceiver(WiFi.receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); + + // start the first scan + triggerOneScan(); + + return 0; + + } + + /** convert the given scan-result to a binary byte[] representation */ + private static byte[] serialize(final List 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(); + } + + + + /** reset the WiFi subsystem (better scanning) */ + 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("Cant start WiFi!");} + }catch (final Exception e) { + throw new RuntimeException(e); + } + + } + + +} diff --git a/deployment.pri b/deployment.pri new file mode 100644 index 0000000..265ce71 --- /dev/null +++ b/deployment.pri @@ -0,0 +1,13 @@ +unix:!android { + isEmpty(target.path) { + qnx { + target.path = /tmp/$${TARGET}/bin + } else { + target.path = /opt/$${TARGET}/bin + } + export(target.path) + } + INSTALLS += target +} + +export(INSTALLS) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..9ba96e7 --- /dev/null +++ b/main.cpp @@ -0,0 +1,51 @@ +#include +#include + + +#include "sensors/SensorFactory.h" + + +#include + +class LeListener : public SensorListener, public SensorListener, public SensorListener { + +public: + void onSensorData(const WiFiSensorData& data) override { + const std::string str = "\n" + data.asString(); + qDebug(str.c_str()); + } + void onSensorData(const AccelerometerData& data) override { + const std::string str = data.asString(); + qDebug(str.c_str()); + } + void onSensorData(const StepData& data) override { + qDebug("STEP!"); + } + +}; + +int main(int argc, char *argv[]) { +// test(); + LeListener listener; + WiFiSensor& wifi = SensorFactory::getWiFi(); + wifi.addListener(&listener); + wifi.start(); + +// AccelerometerSensor& acc = SensorFactory::getAccelerometer(); +// acc.addListener(&listener); +// acc.start(); + + StepSensor& steps = SensorFactory::getSteps(); + steps.addListener(&listener); + steps.start();; + + std::this_thread::sleep_for(std::chrono::seconds(10000)); + +// QGuiApplication app(argc, argv); + +// QQmlApplicationEngine engine; +// engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + +// return app.exec(); + +} diff --git a/misc/Debug.h b/misc/Debug.h new file mode 100644 index 0000000..4ff5dac --- /dev/null +++ b/misc/Debug.h @@ -0,0 +1,16 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include + +class Debug { + +public: + + static void error(const std::string& err) { + qDebug(err.c_str()); + throw err; + } +}; + +#endif // DEBUG_H diff --git a/misc/fixc11.h b/misc/fixc11.h new file mode 100644 index 0000000..a8507fb --- /dev/null +++ b/misc/fixc11.h @@ -0,0 +1,13 @@ +#ifndef FIXC11_H +#define FIXC11_H + +#include + +//namespace std { + +// template T sqrt(const T val) {return ::sqrt(val);} + +//} + + +#endif // FIXC11_H diff --git a/qml.qrc b/qml.qrc new file mode 100644 index 0000000..7684346 --- /dev/null +++ b/qml.qrc @@ -0,0 +1,6 @@ + + + main.qml + MainForm.ui.qml + + diff --git a/sensors/AccelerometerSensor.h b/sensors/AccelerometerSensor.h new file mode 100644 index 0000000..b4ed6c0 --- /dev/null +++ b/sensors/AccelerometerSensor.h @@ -0,0 +1,22 @@ +#ifndef ACCELEROMETERSENSOR_H +#define ACCELEROMETERSENSOR_H + +#include "Sensor.h" + +struct AccelerometerData { + float x; + float y; + float z; + AccelerometerData(const float x, const float y, const float z) : x(x), y(y), z(z) {;} + std::string asString() const { + std::stringstream ss; + ss << "(" << x << "," << y << "," << z << ")"; + return ss.str(); + } +}; + +class AccelerometerSensor : public Sensor { + +}; + +#endif // ACCELEROMETERSENSOR_H diff --git a/sensors/Sensor.h b/sensors/Sensor.h new file mode 100644 index 0000000..8c37d9d --- /dev/null +++ b/sensors/Sensor.h @@ -0,0 +1,50 @@ +#ifndef SENSOR_H +#define SENSOR_H + +#include +#include + +/** listen for sensor events */ +template class SensorListener { + +public: + + /** incoming sensor data */ + virtual void onSensorData(const T& data) = 0; + +}; + + +/** base-class for all sensors */ +template class Sensor { + +private: + + std::vector*> listeners; + +public: + + /** start this sensor */ + virtual void start() = 0; + + /** stop this sensor */ + virtual void stop() = 0; + + /** add the given listener to the sensor */ + void addListener(SensorListener* l) { + listeners.push_back(l); + } + +protected: + + /** inform all attached listeners */ + void informListeners(const T& sensorData) const { + for (SensorListener* l : listeners) { + l->onSensorData(sensorData); + } + } + + +}; + +#endif // SENSOR_H diff --git a/sensors/SensorFactory.h b/sensors/SensorFactory.h new file mode 100644 index 0000000..cac9a92 --- /dev/null +++ b/sensors/SensorFactory.h @@ -0,0 +1,47 @@ +#ifndef SENSORFACTORY_H +#define SENSORFACTORY_H + +#include "Sensor.h" + +#include "WiFiSensor.h" +#include "dummy/WiFiSensorDummy.h" +#include "linux/WiFiSensorLinux.h" +#include "android/WiFiSensorAndroid.h" + +#include "AccelerometerSensor.h" +#include "dummy/AccelerometerSensorDummy.h" +#include "android/AccelerometerSensorAndroid.h" + +#include "StepSensor.h" + +class SensorFactory { + +public: + + /** get the WiFi sensor */ + static WiFiSensor& getWiFi() { +#ifdef ANDROID + return WiFiSensorAndroid::get(); +#else + return WiFiSensorDummy::get(); +#endif + } + + /** get the Accelerometer sensor */ + static AccelerometerSensor& getAccelerometer() { + #ifdef ANDROID + return AccelerometerSensor::get(); +#else + return AccelerometerSensorDummy::get(); +#endif + } + + /** get the Step sensor */ + static StepSensor& getSteps() { + static StepSensor steps(getAccelerometer()); + return steps; + } + +}; + +#endif // SENSORFACTORY_H diff --git a/sensors/StepSensor.h b/sensors/StepSensor.h new file mode 100644 index 0000000..ecdc42b --- /dev/null +++ b/sensors/StepSensor.h @@ -0,0 +1,66 @@ +#ifndef STEPSENSOR_H +#define STEPSENSOR_H + + +#include "../misc/fixc11.h" +#include "AccelerometerSensor.h" +#include "Sensor.h" + +struct StepData { + ; +}; + +class StepSensor : public Sensor, public SensorListener { + +private: + + AccelerometerSensor& acc; + +public: + + /** hidden ctor. use singleton */ + StepSensor(AccelerometerSensor& acc) : acc(acc) { + ; + } + + void start() override { + acc.addListener(this); + acc.start(); + } + + void stop() override { + throw "todo"; + } + + virtual void onSensorData(const AccelerometerData& data) override { + parse(data); + } + + +protected: + + const float threshold = 11.0; + const int blockTime = 25; + int block = 0; + + void parse(const AccelerometerData& data) { + + const float x = data.x; + const float y = data.y; + const float z = data.z; + + const float mag = std::sqrt( (x*x) + (y*y) + (z*z) ); + + if (block > 0) { + --block; + } else if (mag > threshold) { + informListeners(StepData()); + block = blockTime; + } + + } + +}; + + +#endif // STEPSENSOR_H diff --git a/sensors/WiFiSensor.h b/sensors/WiFiSensor.h new file mode 100644 index 0000000..8da04b4 --- /dev/null +++ b/sensors/WiFiSensor.h @@ -0,0 +1,43 @@ +#ifndef WIFISENSOR_H +#define WIFISENSOR_H + +#include +#include +#include "Sensor.h" + + +struct WiFiSensorDataEntry { + std::string bssid; + float rssi; + WiFiSensorDataEntry(const std::string& bssid, const float rssi) : bssid(bssid), rssi(rssi) {;} + std::string asString() const { + std::stringstream ss; + ss << bssid << '\t' << (int)rssi; + return ss.str(); + } +}; + + +struct WiFiSensorData { + std::vector entries; + std::string asString() const { + std::stringstream ss; + for(const WiFiSensorDataEntry& e : entries) {ss << e.asString() << '\n';} + return ss.str(); + } +}; + + +/** interface for all wifi sensors */ +class WiFiSensor : public Sensor { + +protected: + + /** hidden ctor. use SensorFactory */ + WiFiSensor() { + + } + +}; + +#endif // WIFISENSOR_H diff --git a/sensors/android/AccelerometerSensorAndroid.h b/sensors/android/AccelerometerSensorAndroid.h new file mode 100644 index 0000000..bcc6639 --- /dev/null +++ b/sensors/android/AccelerometerSensorAndroid.h @@ -0,0 +1,55 @@ +#ifndef ACCELEROMETERSENSOR_H +#define ACCELEROMETERSENSOR_H + + +#ifdef ANDROID + +#include + +#include "../AccelerometerSensor.h" + +#include + + + +class AccelerometerSensorAndroid : public AccelerometerSensor { + +private: + + QAccelerometer acc; + + /** hidden ctor. use singleton */ + AccelerometerSensorAndroid() { + ; + } + +public: + + /** singleton access */ + static AccelerometerSensor& get() { + static AccelerometerSensor acc; + return acc; + } + + void start() override { + + auto onSensorData = [&] () { + AccelerometerData data(acc.reading()->x(), acc.reading()->y(), acc.reading()->z()); + informListeners(data); + }; + + acc.connect(&acc, &QAccelerometer::readingChanged, onSensorData); + acc.start(); + + } + + void stop() override { + throw "todo"; + } + + +}; + +#endif ANDROID + +#endif // ACCELEROMETERSENSOR_H diff --git a/sensors/android/WiFiSensorAndroid.h b/sensors/android/WiFiSensorAndroid.h new file mode 100644 index 0000000..07ea415 --- /dev/null +++ b/sensors/android/WiFiSensorAndroid.h @@ -0,0 +1,76 @@ +#ifndef WIFISENSORANDROID_H +#define WIFISENSORANDROID_H + + +#ifdef ANDROID + +#include + +#include "Debug.h" +#include "WiFiSensor.h" + +class WiFiSensorAndroid : public WiFiSensor { + +private: + + /** hidden ctor. use singleton! */ + WiFiSensorAndroid() {;} + +public: + + /** singleton access */ + static WiFiSensorAndroid& get() { + static WiFiSensorAndroid wifi; + return wifi; + } + + void start() override { + + // start scanning + int res = QAndroidJniObject::callStaticMethod("java/indoor/WiFi", "start", "()I"); + (void) res; + + } + + /** called from java. handle the given incoming scan result */ + void handle(const std::string& data) { + + // to-be-constructed sensor data + WiFiSensorData sensorData; + + // parse each mac->rssi entry + for (int i = 0; i < (int)data.length(); i += 17+1+2) { + const std::string bssid = data.substr(i, 17); + const int8_t rssi = data[i+17]; + const int8_t pad1 = data[i+18]; + const int8_t pad2 = data[i+19]; + if (pad1 != 0 || pad2 != 0) {Debug::error("padding error within WiFi scan result");} + sensorData.entries.push_back(WiFiSensorDataEntry(bssid, rssi)); + } + + // call listeners + informListeners(sensorData); + + } + +}; + + +extern "C" { + + /** called after each successful WiFi scan */ + JNIEXPORT void JNICALL Java_java_indoor_WiFi_onScanComplete(JNIEnv* env, jobject jobj, jbyteArray arrayID) { + (void) env; (void) jobj; + jsize length = env->GetArrayLength(arrayID); + jboolean isCopy; + jbyte* data = env->GetByteArrayElements(arrayID, &isCopy); + std::string str((char*)data, length); + env->ReleaseByteArrayElements(arrayID, data, JNI_ABORT); + WiFiSensorAndroid::get().handle(str); + } + +} + +#endif + +#endif // WIFISENSORANDROID_H diff --git a/sensors/dummy/AccelerometerSensorDummy.h b/sensors/dummy/AccelerometerSensorDummy.h new file mode 100644 index 0000000..4af499c --- /dev/null +++ b/sensors/dummy/AccelerometerSensorDummy.h @@ -0,0 +1,27 @@ +#ifndef ACCELEROMETERSENSORDUMMY_H +#define ACCELEROMETERSENSORDUMMY_H + +#include "../AccelerometerSensor.h" + +class AccelerometerSensorDummy : public AccelerometerSensor { + + +public: + + /** singleton access */ + static AccelerometerSensorDummy& get() { + static AccelerometerSensorDummy acc; + return acc; + } + + void start() override { + //throw "todo"; + } + + void stop() override { + throw "todo"; + } + +}; + +#endif // ACCELEROMETERSENSORDUMMY_H diff --git a/sensors/dummy/WiFiSensorDummy.h b/sensors/dummy/WiFiSensorDummy.h new file mode 100644 index 0000000..5f94310 --- /dev/null +++ b/sensors/dummy/WiFiSensorDummy.h @@ -0,0 +1,92 @@ +#ifndef WIFISENSORDUMMY_H +#define WIFISENSORDUMMY_H + +#include "../WiFiSensor.h" +#include + +#include +#include + +#include +#include + + +class WiFiSensorDummy : public WiFiSensor { + +private: + + bool enabled; + +public: + + + /** singleton access */ + static WiFiSensorDummy& get() { + static WiFiSensorDummy wifi; + return wifi; + } + + + void start() override { + + enabled = true; + std::thread t(&WiFiSensorDummy::simulate, this); + t.detach(); + + } + + void stop() override { + enabled = false; + } + +private: + + + struct DummyAP { + std::string mac; + Point2 pos; + DummyAP(const std::string mac, const Point2 pos) : mac(mac), pos(pos) {;} + }; + + void simulate() { + + std::vector aps; + aps.push_back(DummyAP("00:00:00:00:00:01", Point2(0, 0))); + aps.push_back(DummyAP("00:00:00:00:00:02", Point2(20, 0))); + aps.push_back(DummyAP("00:00:00:00:00:03", Point2(10, 20))); + + float deg = 0; + + while(enabled) { + + // wait + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + // circle-run around center + deg += M_PI * 0.4; + + const float cx = 10; + const float cy = 10; + const float rad = 5; + + const float x = cx + std::sin(deg) * rad; + const float y = cy + std::cos(deg) * rad; + + // construct scan data + WiFiSensorData scan; + for (DummyAP& ap : aps) { + const float dist = ap.pos.getDistance(Point2(x, y)); + const float rssi = LogDistanceModel::distanceToRssi(-40, 1.5, dist); + scan.entries.push_back(WiFiSensorDataEntry(ap.mac, rssi)); + } + + // call + informListeners(scan); + + } + + } + +}; + +#endif // WIFISENSORDUMMY_H diff --git a/sensors/linux/WiFiSensorLinux.h b/sensors/linux/WiFiSensorLinux.h new file mode 100644 index 0000000..17f4b56 --- /dev/null +++ b/sensors/linux/WiFiSensorLinux.h @@ -0,0 +1,33 @@ +#ifndef WIFISENSORLINUX_H +#define WIFISENSORLINUX_H + +#include "../WiFiSensor.h" + +class WiFiSensorLinux : public WiFiSensor { + + +private: + + WiFiSensorLinux() { + + } + +public: + + /** singleton access */ + static WiFiSensorLinux& get() { + static WiFiSensorLinux wifi; + return wifi; + } + + void start() override { + + } + + void stop() override { + + } + +}; + +#endif // WIFISENSORLINUX_H diff --git a/yasmin.pro b/yasmin.pro new file mode 100644 index 0000000..8d0f007 --- /dev/null +++ b/yasmin.pro @@ -0,0 +1,54 @@ +TEMPLATE = app + +QT += qml + +# android? +#QT += androidextras sensors +#DEFINES += ANDROID + +CONFIG += c++11 + +# use files in ./_android for the project as well +ANDROID_PACKAGE_SOURCE_DIR = $$PWD/_android + +INCLUDEPATH += \ + ../ + +OTHER_FILES += \ + _android/src/WiFi.java \ + _android/AndroidManifest.xml + +SOURCES += \ + main.cpp \ + +RESOURCES += qml.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Default rules for deployment. +include(deployment.pri) + +target.path = $$[QT_INSTALL_EXAMPLES]/androidextras/notification +INSTALLS += target + +#DISTFILES += \ +# android-sources/AndroidManifest.xml \ +# android-sources/src/WiFi.java + +HEADERS += \ + sensors/linux/WiFiSensorLinux.h \ + sensors/android/WiFiSensorAndroid.h \ + sensors/StepSensor.h \ + sensors/AccelerometerSensor.h \ + sensors/android/AccelerometerSensorAndroid.h \ + sensors/dummy/AccelerometerSensorDummy.h \ + sensors/Sensor.h \ + sensors/SensorFactory.h \ + sensors/WiFiSensor.h \ + misc/Debug.h \ + misc/fixc11.h \ + sensors/dummy/WiFiSensorDummy.h + +DISTFILES += \ + android-sources/src/MyActivity.java