diff --git a/App.js b/App.js
index 72b7ad0..2980ba1 100644
--- a/App.js
+++ b/App.js
@@ -63,25 +63,31 @@ export default class App extends React.Component {
const screenOptions = {
headerShown: false,
};
-
- /*
+
+
return (
} persistor={persistor}>
-
+
+
+ {props => }
+
+ component={WifiPasswordView}
+ >
+
);
- */
+ /*
return (
} persistor={persistor}>
@@ -112,6 +118,7 @@ export default class App extends React.Component {
);
+ */
}
}
diff --git a/data_processing/SwimTrackerWebsocketConnection.js b/data_processing/SwimTrackerWebsocketConnection.js
index 37e8185..9a71a10 100644
--- a/data_processing/SwimTrackerWebsocketConnection.js
+++ b/data_processing/SwimTrackerWebsocketConnection.js
@@ -1,22 +1,32 @@
import ReconnectingWebSocket from 'reconnecting-websocket';
+import * as msgpack from 'msgpack-lite';
+
const OpCodes = {
- // from device to frontend
- INITIAL_INFO: 1,
- SESSION_STARTED: 2,
- SESSION_STOPPED: 3,
- SESSION_NEW_DATA: 4,
- ANSWER_USER_LIST : 5,
- ANSWER_SESSION_LIST : 6,
-
+ // from swim tracker device to frontend
+ ERROR: 1,
+
+ INITIAL_INFO: 2,
+ SESSION_STARTED: 3,
+ SESSION_STOPPED: 4,
+ SESSION_NEW_DATA: 5,
+ ANSWER_USER_LIST: 6,
+ ANSWER_SESSION_LIST: 7,
+ WIFI_STATE_RESPONSE: 8,
+ WIFI_SCAN_RESPONSE: 9,
+
// from frontend to device
- START_SESSION: 7,
- STOP_SESSION: 8,
- TARE: 9,
- QUERY_USER_LIST: 10,
- QUERY_SESSION_LIST: 11
+ START_SESSION: 128,
+ STOP_SESSION: 129,
+ TARE: 130,
+ QUERY_USER_LIST: 131,
+ QUERY_SESSION_LIST: 132,
+ WIFI_STATE_SET: 133,
+ WIFI_STATE_GET: 134,
+ WIFI_TRIGGER_SCAN: 135,
};
+
export default class SwimTrackerWebsocketConnection {
constructor(swimTrackerHost, onData, onStarted, onStopped, onConnect, onDisconnect) {
this.swimTrackerHost = swimTrackerHost;
@@ -36,6 +46,15 @@ export default class SwimTrackerWebsocketConnection {
this.ws.onclose = this.onDisconnect;
this.ws.onerror = this._onError;
this.ws.binaryType = 'arraybuffer';
+
+ this.msgpackCodec = msgpack.createCodec();
+ this.msgpackCodec.addExtUnpacker(205, function (byteArr) {
+ const buffer = byteArr.buffer.slice(byteArr.byteOffset, byteArr.byteLength + byteArr.byteOffset);
+ const result = new Int16Array(buffer);
+ return result;
+ });
+
+ this._wifiScanPromise = null;
}
sendStartCommand() {
@@ -56,6 +75,24 @@ export default class SwimTrackerWebsocketConnection {
this.ws.send(data);
}
+ scanWifiNetworks() {
+ // trigger scan
+ const data = new Uint8Array(1);
+ data[0] = OpCodes.WIFI_TRIGGER_SCAN;
+ this.ws.send(data);
+
+ if (this._wifiScanPromise !== null) {
+ return Promise.reject("Scan in progress");
+ }
+ else {
+
+ let conn = this;
+ return new Promise((resolve, reject) => {
+ conn._wifiScanPromise = { resolve: resolve, reject: reject };
+ });
+ }
+ }
+
_onMessage = (e) => {
const dv = new DataView(e.data);
const opCode = dv.getInt8(0);
@@ -78,6 +115,15 @@ export default class SwimTrackerWebsocketConnection {
} else if (opCode === OpCodes.SESSION_NEW_DATA) {
const data = new Uint16Array(e.data.slice(1));
this.onData(data);
+ } else if (opCode === OpCodes.WIFI_SCAN_RESPONSE) {
+ console.log("got data", e.data);
+ const scanResult = msgpack.decode(new Uint8Array(e.data).slice(1), { codec: this.msgpackCodec });
+ if (this._wifiScanPromise !== null) {
+ this._wifiScanPromise.resolve(scanResult);
+ this._wifiScanPromise = null;
+ } else {
+ console.log("Got unexpected WiFi scan result", scanResult);
+ }
}
}
diff --git a/state/DeviceReduxCoupling.js b/state/DeviceReduxCoupling.js
index 027da32..c52cb8e 100644
--- a/state/DeviceReduxCoupling.js
+++ b/state/DeviceReduxCoupling.js
@@ -7,7 +7,14 @@ export const ConnState = {
CONNECTED_STOPPED: 'connected_stopped',
CONNECTED_RUNNING: 'connected_running',
CONNECTED_STARTING: 'connected_starting', // start message sent, but device hasn't ack'ed it yet
- CONNECTED_STOPPING: 'connected_stopping' // stop message sent..
+ CONNECTED_STOPPING: 'connected_stopping' // stop message sent..
+}
+
+export const WifiState = {
+ UNKNOWN: 'unknown',
+ STA: 'sta', // connected to regular wifi
+ AP_PROVISIONING: 'ap_provisioning', // acting as access point for provisioning
+ AP_SECURE: 'ap_secure', // acting as access point, password has been set
}
// -------------------------------------------- Actions ---------------------------------------------
@@ -21,6 +28,12 @@ export const SESSION_NEW_DATA = "SESSION_NEW_DATA";
export const START_SESSION = "START_SESSION";
export const STOP_SESSION = "STOP_SESSION";
+export const WIFI_SET_STATE = "WIFI_SET_STATE";
+
+export const reportNewWifiState = (newStateStr) => ({
+ type: WIFI_SET_STATE,
+ newStateStr: newStateStr
+});
export const reportSessionStarted = (sessionId) => ({
type: SESSION_STARTED,
@@ -107,6 +120,7 @@ const INITIAL_ANALYSIS = {
const INITIAL_DEVICE_STATE = {
connState: ConnState.DISCONNECTED,
+ wifiState: WifiState.UNKNOWN,
sessionId: 0,
measurements: List(),
analysis: INITIAL_ANALYSIS,
@@ -130,18 +144,25 @@ export const deviceStateReducer = (state = INITIAL_DEVICE_STATE, action) => {
case SESSION_STOPPED:
return { ...INITIAL_DEVICE_STATE, connState: ConnState.CONNECTED_STOPPED };
case START_SESSION:
- if(state.connState === ConnState.SESSION_STARTED)
+ if (state.connState === ConnState.SESSION_STARTED)
return state;
return { ...INITIAL_DEVICE_STATE, connState: ConnState.CONNECTED_STARTING };
case STOP_SESSION:
- if(state.connState === ConnState.SESSION_STOPPED)
+ if (state.connState === ConnState.SESSION_STOPPED)
return state;
return { ...INITIAL_DEVICE_STATE, connState: ConnState.CONNECTED_STOPPING };
+ case WIFI_SET_STATE:
+ console.log("here");
+ let wifState = WifiState.UNKNOWN;
+ if (action.data === "STATION_MODE") { wifState = WifiState.STA; }
+ else if (action.data === "AP_PROVISIONING") { wifState = WifiState.AP_PROVISIONING; }
+ else if (action.data === "AP_SECURE") { wifState = WifiState.AP_SECURE; }
+ return { ...state, wifiState: wifState };
default:
- console.log("Unhandled state in deviceStateReducer", action.type);
+ console.log("Unhandled state in deviceStateReducer", action, action.type);
return state
}
};
-
+
diff --git a/state/Reducer.js b/state/Reducer.js
index 633abef..bf3035b 100644
--- a/state/Reducer.js
+++ b/state/Reducer.js
@@ -22,7 +22,7 @@ const INITIAL_SETTINGS = {
theme: "hot",
username: "",
//swimTrackerHost: "192.168.178.107", // am pool
- swimTrackerHost: "192.168.178.110", // testgeraet
+ swimTrackerHost: "192.168.42.1", // testgeraet
analysis: {
peaksPerLap: 30,
diff --git a/views/WifiPasswordView.js b/views/WifiPasswordView.js
index 30bbdaf..66e34b2 100644
--- a/views/WifiPasswordView.js
+++ b/views/WifiPasswordView.js
@@ -13,6 +13,7 @@ import themeColors from '../components/themeColors';
function WifiPasswordView(props) {
+ props = {...props, ...props.route.params};
let iconName = "wifi-strength-" + props.strength;
if (props.lock) {
diff --git a/views/WifiSelectionView.js b/views/WifiSelectionView.js
index dd85469..31f0ed3 100644
--- a/views/WifiSelectionView.js
+++ b/views/WifiSelectionView.js
@@ -1,10 +1,11 @@
-import React from "react";
+import React from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
ScrollView,
+ ActivityIndicator,
} from "react-native";
import SetupView from '../components/SetupView';
import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
@@ -12,12 +13,12 @@ import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
function WifiListElement(props) {
let iconName = "wifi-strength-" + props.strength;
- if(props.lock) {
+ if (props.lock) {
iconName += "-lock";
}
return (
-
+
{props.text}
@@ -51,32 +52,96 @@ const wifiListElementStyles = {
// ---------------------------------------------------------------------------------------------
+class WifiSelectionView extends React.Component {
+ constructor() {
+ super();
+ this.state = { wifiInfo: [] };
+ }
-function WifiSelectionView(props) {
+ processDeviceResponse(response) {
+ // sort from strong to weak
+ response.sort((e1, e2) => {
+ if (e1.rssi > e2.rssi)
+ return -1;
+ if (e1.rssi < e2.rssi)
+ return 1;
+ else
+ return 0;
+ });
- return (
-
-
+ let ssidsAlreadyAdded = {};
+ let result = [];
+ for (let i = 0; i < response.length; i++) {
+ if (response[i].ssid in ssidsAlreadyAdded)
+ continue;
+
+ const locked = (response[i].sec != "open");
+ let strength = 1;
+ if (response[i].rssi > -30)
+ strength = 4;
+ else if (response[i].rssi > -67)
+ strength = 3;
+ else if (response[i].rssi > -70)
+ strength = 2;
+
+ result.push({ ssid: response[i].ssid, locked: locked, strength: strength });
+ ssidsAlreadyAdded[response[i].ssid] = true;
+ }
+ return result;
+ }
+
+ componentDidMount() {
+ this.props.device.conn.scanWifiNetworks().then(
+ (result) => {
+ this.setState({ wifiInfo: this.processDeviceResponse(result) })
+ }
+ );
+ }
+
+ render() {
+ let inner;
+
+ if (this.state.wifiInfo.length > 0) {
+ inner = (
-
-
+ {this.state.wifiInfo.map(e => (
+ { this.props.navigation.navigate("WifiPasswordView", {
+ ssid: e.ssid,
+ lock: e.locked,
+ strength: e.strength,
+ buttonText: "Set Password",
+ subText: "Please enter password for your home WiFi",
+ }); }}>
+ )
+ )}
+ )
+ }
+ else {
+ inner = (
-
-
+ )
+ }
-
-
-
-
-
-
- )
+ return (
+
+
+ {inner}
+
+
+ )
+ }
}
+
const styles = StyleSheet.create({
listContainer: {
height: "75%",