started with functionality in wifi selection

This commit is contained in:
Martin Bauer 2021-06-06 21:31:41 +02:00
parent fee67e04aa
commit a6db96ef29
6 changed files with 187 additions and 47 deletions

19
App.js
View File

@ -63,25 +63,31 @@ export default class App extends React.Component {
const screenOptions = {
headerShown: false,
};
/*
return (
<Provider store={store}>
<PersistGate loading={<AppLoading />} persistor={persistor}>
<NavigationContainer>
<Stack.Navigator initialRouteName="WifiPasswordView">
<Stack.Navigator initialRouteName="WifiSelectionView">
<Stack.Screen
name="WifiSelectionView"
options={screenOptions} >
{props => <WifiSelectionView {...props} device={this.device} />}
</Stack.Screen>
<Stack.Screen
name="WifiPasswordView"
component={WifiPasswordView}
options={screenOptions}
/>
component={WifiPasswordView}
>
</Stack.Screen>
</Stack.Navigator>
</NavigationContainer>
</PersistGate>
</Provider>
);
*/
/*
return (
<Provider store={store}>
<PersistGate loading={<AppLoading />} persistor={persistor}>
@ -112,6 +118,7 @@ export default class App extends React.Component {
</PersistGate>
</Provider>
);
*/
}
}

View File

@ -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);
}
}
}

View File

@ -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
}
};

View File

@ -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,

View File

@ -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) {

View File

@ -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 (
<TouchableOpacity>
<TouchableOpacity onPress={props.onPress}>
<View style={wifiListElementStyles.container}>
<MaterialIcon style={wifiListElementStyles.icon} name={iconName}></MaterialIcon>
<Text style={wifiListElementStyles.text} >{props.text}</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 (
<SetupView
headerText="WiFi Connection"
lowerLeftButtonText="My WiFi wasn't found"
lowerRightButtonText="Need help?"
>
<View style={styles.listContainer}>
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 = (
<ScrollView>
<WifiListElement text="WLAN" strength="4" lock={true}></WifiListElement>
<WifiListElement text="GastWLAN" strength="2" lock={false}></WifiListElement>
{this.state.wifiInfo.map(e => (
<WifiListElement
text={e.ssid}
strength={e.strength}
lock={e.locked}
key={e.ssid}
onPress={() => { 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",
}); }}>
</WifiListElement>)
)}
</ScrollView>)
}
else {
inner = (<ActivityIndicator size="large" color="#ffffff" />
<WifiListElement text="WLAN" strength="4"></WifiListElement>
<WifiListElement text="GastWLAN" strength="2"></WifiListElement>
)
}
<WifiListElement text="WLAN" strength="4"></WifiListElement>
<WifiListElement text="GastWLAN" strength="2"></WifiListElement>
</ScrollView>
</View>
</SetupView>
)
return (
<SetupView
headerText="WiFi Connection"
lowerLeftButtonText="My WiFi wasn't found"
lowerRightButtonText="Need help?"
>
<View style={styles.listContainer}>
{inner}
</View>
</SetupView>
)
}
}
const styles = StyleSheet.create({
listContainer: {
height: "75%",