Detect broken connection via app layer ping

This commit is contained in:
Martin Bauer 2021-07-23 16:25:26 +02:00
parent db3589c86d
commit 03812fe514
2 changed files with 38 additions and 12 deletions

View File

@ -14,6 +14,7 @@ const OpCodes = {
ANSWER_SESSION_LIST: 7, ANSWER_SESSION_LIST: 7,
WIFI_STATE_RESPONSE: 8, WIFI_STATE_RESPONSE: 8,
WIFI_SCAN_RESPONSE: 9, WIFI_SCAN_RESPONSE: 9,
APP_LAYER_PING: 10,
// from frontend to device // from frontend to device
START_SESSION: 128, START_SESSION: 128,
@ -26,11 +27,12 @@ const OpCodes = {
WIFI_TRIGGER_SCAN: 135, WIFI_TRIGGER_SCAN: 135,
}; };
const HEARTBEAT_TIMEOUT = 3000;
export default class SwimTrackerWebsocketConnection { export default class SwimTrackerWebsocketConnection {
constructor(swimTrackerHost, onData, onStarted, onStopped, onWifiStateInfo, onConnect, onDisconnect) { constructor(swimTrackerHost, onData, onStarted, onStopped, onWifiStateInfo, onConnect, onDisconnect) {
this.swimTrackerHost = swimTrackerHost; this.swimTrackerHost = swimTrackerHost;
this.onData = onData; this.onData = onData;
this.onStarted = onStarted; this.onStarted = onStarted;
this.onStopped = onStopped; this.onStopped = onStopped;
@ -57,15 +59,27 @@ export default class SwimTrackerWebsocketConnection {
}); });
this._wifiScanPromises = []; this._wifiScanPromises = [];
this.pingTimeout = null;
}
heartbeat() {
clearTimeout(this.pingTimeout);
let connection = this;
this.pingTimeout = setTimeout(() => {
connection.ws.reconnect();
}, HEARTBEAT_TIMEOUT);
} }
close() { close() {
this.ws.onmessage = null; if (this.ws !== null) {
this.ws.onopen = null; this.ws.onmessage = null;
this.ws.onclose = null; this.ws.onopen = null;
this.ws.onerror = null; this.ws.onclose = null;
this.ws.close(); this.ws.onerror = null;
this.ws = null; this.ws.close();
this.ws = null;
}
} }
sendStartCommand() { sendStartCommand() {
@ -128,6 +142,8 @@ export default class SwimTrackerWebsocketConnection {
const dv = new DataView(e.data); const dv = new DataView(e.data);
const opCode = dv.getInt8(0); const opCode = dv.getInt8(0);
const payload = new Uint8Array(e.data).slice(1); const payload = new Uint8Array(e.data).slice(1);
this.heartbeat();
if (opCode === OpCodes.INITIAL_INFO) { if (opCode === OpCodes.INITIAL_INFO) {
const headerSize = 6; const headerSize = 6;
@ -157,6 +173,8 @@ export default class SwimTrackerWebsocketConnection {
} else if (opCode === OpCodes.WIFI_STATE_RESPONSE) { } else if (opCode === OpCodes.WIFI_STATE_RESPONSE) {
const wifiInfo = msgpack.decode(payload, { codec: this.msgpackCodec }); const wifiInfo = msgpack.decode(payload, { codec: this.msgpackCodec });
this.onWifiStateInfo(wifiInfo); this.onWifiStateInfo(wifiInfo);
} else if (opCode === OpCodes.APP_LAYER_PING) {
//console.log("got heartbeat");
} }
} }

View File

@ -11,6 +11,7 @@ import themeColors from '../components/themeColors';
import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons"; import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
import EntypoIcon from "react-native-vector-icons/Entypo"; import EntypoIcon from "react-native-vector-icons/Entypo";
import ImageHeader from "../components/ImageHeader"; import ImageHeader from "../components/ImageHeader";
import { connect } from 'react-redux';
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
@ -24,6 +25,7 @@ function SettingsTextInput(props) {
placeholder={props.placeholder} placeholder={props.placeholder}
placeholderTextColor="rgba(167,167,167,1)" placeholderTextColor="rgba(167,167,167,1)"
selectionColor='rgb(120,120,120)' selectionColor='rgb(120,120,120)'
value={props.value}
></TextInput> ></TextInput>
</React.Fragment> </React.Fragment>
); );
@ -124,6 +126,7 @@ const settingsGroupStyles = StyleSheet.create({
textInput: { textInput: {
color: "rgba(255,255,255,1)", color: "rgba(255,255,255,1)",
marginTop: 8, marginTop: 8,
textAlign: "right",
}, },
slider: { slider: {
minWidth: 100, minWidth: 100,
@ -140,6 +143,7 @@ const settingsGroupStyles = StyleSheet.create({
function SettingsView(props) { function SettingsView(props) {
console.log("settings props", props);
return ( return (
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<StatusBar hidden={true} /> <StatusBar hidden={true} />
@ -154,11 +158,11 @@ function SettingsView(props) {
<SettingsGroup title="swimtracker Device"> <SettingsGroup title="swimtracker Device">
<SettingsTextInput <SettingsTextInput
label="URL/IP" label="URL/IP"
placeholder="192.168.178.??" placeholder="swimtracker-????"
/> value={props.settings.swimTrackerHost}
<SettingsSwitch
label="SomeSwitch"
/> />
<SettingsSwitch label="Start automatically" />
<SettingsSwitch label="Stop automatically" />
</SettingsGroup> </SettingsGroup>
</View> </View>
</View> </View>
@ -166,4 +170,8 @@ function SettingsView(props) {
) )
} }
export default SettingsView; const mapStateToProps = (state) => {
return { settings: state.settings };
};
export default connect(mapStateToProps)(SettingsView);