diff --git a/data_processing/SwimTrackerWebsocketConnection.js b/data_processing/SwimTrackerWebsocketConnection.js index ac7c190..cde7f8a 100644 --- a/data_processing/SwimTrackerWebsocketConnection.js +++ b/data_processing/SwimTrackerWebsocketConnection.js @@ -14,6 +14,7 @@ const OpCodes = { ANSWER_SESSION_LIST: 7, WIFI_STATE_RESPONSE: 8, WIFI_SCAN_RESPONSE: 9, + APP_LAYER_PING: 10, // from frontend to device START_SESSION: 128, @@ -26,11 +27,12 @@ const OpCodes = { WIFI_TRIGGER_SCAN: 135, }; +const HEARTBEAT_TIMEOUT = 3000; export default class SwimTrackerWebsocketConnection { constructor(swimTrackerHost, onData, onStarted, onStopped, onWifiStateInfo, onConnect, onDisconnect) { this.swimTrackerHost = swimTrackerHost; - + this.onData = onData; this.onStarted = onStarted; this.onStopped = onStopped; @@ -57,15 +59,27 @@ export default class SwimTrackerWebsocketConnection { }); this._wifiScanPromises = []; + this.pingTimeout = null; + } + + heartbeat() { + clearTimeout(this.pingTimeout); + + let connection = this; + this.pingTimeout = setTimeout(() => { + connection.ws.reconnect(); + }, HEARTBEAT_TIMEOUT); } close() { - this.ws.onmessage = null; - this.ws.onopen = null; - this.ws.onclose = null; - this.ws.onerror = null; - this.ws.close(); - this.ws = null; + if (this.ws !== null) { + this.ws.onmessage = null; + this.ws.onopen = null; + this.ws.onclose = null; + this.ws.onerror = null; + this.ws.close(); + this.ws = null; + } } sendStartCommand() { @@ -128,6 +142,8 @@ export default class SwimTrackerWebsocketConnection { const dv = new DataView(e.data); const opCode = dv.getInt8(0); const payload = new Uint8Array(e.data).slice(1); + + this.heartbeat(); if (opCode === OpCodes.INITIAL_INFO) { const headerSize = 6; @@ -157,6 +173,8 @@ export default class SwimTrackerWebsocketConnection { } else if (opCode === OpCodes.WIFI_STATE_RESPONSE) { const wifiInfo = msgpack.decode(payload, { codec: this.msgpackCodec }); this.onWifiStateInfo(wifiInfo); + } else if (opCode === OpCodes.APP_LAYER_PING) { + //console.log("got heartbeat"); } } diff --git a/views/SettingsView.js b/views/SettingsView.js index ac36687..10f981c 100644 --- a/views/SettingsView.js +++ b/views/SettingsView.js @@ -11,6 +11,7 @@ import themeColors from '../components/themeColors'; import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons"; import EntypoIcon from "react-native-vector-icons/Entypo"; import ImageHeader from "../components/ImageHeader"; +import { connect } from 'react-redux'; // --------------------------------------------------------------------------------------------- @@ -24,6 +25,7 @@ function SettingsTextInput(props) { placeholder={props.placeholder} placeholderTextColor="rgba(167,167,167,1)" selectionColor='rgb(120,120,120)' + value={props.value} > ); @@ -124,6 +126,7 @@ const settingsGroupStyles = StyleSheet.create({ textInput: { color: "rgba(255,255,255,1)", marginTop: 8, + textAlign: "right", }, slider: { minWidth: 100, @@ -140,6 +143,7 @@ const settingsGroupStyles = StyleSheet.create({ function SettingsView(props) { + console.log("settings props", props); return ( @@ -166,4 +170,8 @@ function SettingsView(props) { ) } -export default SettingsView; \ No newline at end of file +const mapStateToProps = (state) => { + return { settings: state.settings }; +}; + +export default connect(mapStateToProps)(SettingsView);