Detect broken connection via app layer ping
This commit is contained in:
parent
db3589c86d
commit
03812fe514
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue