fix reconnect and add banner message when trying to reconnect5r
This commit is contained in:
parent
6bbd925dbc
commit
0f881b668c
5 changed files with 73 additions and 29 deletions
12
capybara.py
12
capybara.py
|
@ -2,7 +2,7 @@ import sys
|
||||||
from asyncio import wait_for, TimeoutError
|
from asyncio import wait_for, TimeoutError
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.response import file, redirect
|
from sanic.response import file, redirect, empty
|
||||||
|
|
||||||
from InputController import InputController
|
from InputController import InputController
|
||||||
from MessageParser import MessageParser
|
from MessageParser import MessageParser
|
||||||
|
@ -10,7 +10,7 @@ from MessageParser import MessageParser
|
||||||
|
|
||||||
app = Sanic(
|
app = Sanic(
|
||||||
"capybara",
|
"capybara",
|
||||||
load_env="CAPYBARA_"
|
env_prefix="CAPYBARA_"
|
||||||
)
|
)
|
||||||
input_controller = InputController()
|
input_controller = InputController()
|
||||||
control_message_parser = MessageParser()
|
control_message_parser = MessageParser()
|
||||||
|
@ -40,13 +40,15 @@ async def gateway(req, ws):
|
||||||
return
|
return
|
||||||
|
|
||||||
code, args = control_message_parser.parse(auth_payload)
|
code, args = control_message_parser.parse(auth_payload)
|
||||||
if (not code or
|
if (
|
||||||
|
not code or
|
||||||
code != "0" or
|
code != "0" or
|
||||||
args["auth_string"] != app.ctx.EXPECTED_AUTH_STRING): # 0 is the code for the initial auth packet
|
args["auth_string"] != app.ctx.EXPECTED_AUTH_STRING
|
||||||
|
): # 0 is the code for the initial auth packet
|
||||||
await ws.close(code=4001, reason="Invalid auth packet")
|
await ws.close(code=4001, reason="Invalid auth packet")
|
||||||
return
|
return
|
||||||
|
|
||||||
await ws.send("1") # send a single `1` to let the client know the server is input packets
|
await ws.send("1") # send a single `1` to let the client know the server is accepting input packets
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
input_controller.process_message(await ws.recv())
|
input_controller.process_message(await ws.recv())
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Banner from "./Banner";
|
||||||
import Connection from "./Connection";
|
import Connection from "./Connection";
|
||||||
import KeyboardController from "./Keyboard";
|
import KeyboardController from "./Keyboard";
|
||||||
import { getAuth, setAuth } from "./LocalConfiguration";
|
import { getAuth, setAuth } from "./LocalConfiguration";
|
||||||
|
@ -18,6 +19,8 @@ class App {
|
||||||
this.unmountApp();
|
this.unmountApp();
|
||||||
if (code === 4001) { // 4001 - code for bad auth
|
if (code === 4001) { // 4001 - code for bad auth
|
||||||
this.transitionTo("login");
|
this.transitionTo("login");
|
||||||
|
} else {
|
||||||
|
this.transitionTo("reconnectingBanner");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.connection.onHandshakeCompleted = () => {
|
this.connection.onHandshakeCompleted = () => {
|
||||||
|
@ -28,24 +31,45 @@ class App {
|
||||||
transitionTo(type) {
|
transitionTo(type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "login":
|
case "login":
|
||||||
|
this.unmountBannerComponent();
|
||||||
this.unmountApp();
|
this.unmountApp();
|
||||||
this.mountLoginComponent();
|
this.mountLoginComponent();
|
||||||
break;
|
break;
|
||||||
case "app":
|
case "app":
|
||||||
|
this.unmountBannerComponent();
|
||||||
this.unmountLoginComponent();
|
this.unmountLoginComponent();
|
||||||
this.mountApp();
|
this.mountApp();
|
||||||
break;
|
break;
|
||||||
|
case "reconnectingBanner":
|
||||||
|
this.unmountApp();
|
||||||
|
this.unmountLoginComponent();
|
||||||
|
this.mountBannerComponent("Connecting...", "Looks like you've lost connection. We're trying to reconnect you.");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`transitionTo type ${type} is invalid`);
|
throw new Error(`transitionTo type ${type} is invalid`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mountBannerComponent(title, text) {
|
||||||
|
if (!this.bannerComponent)
|
||||||
|
this.bannerComponent = new Banner();
|
||||||
|
|
||||||
|
this.bannerComponent.mountOn(this.mountElement);
|
||||||
|
this.bannerComponent.updateTitle(title);
|
||||||
|
this.bannerComponent.updateText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
unmountBannerComponent() {
|
||||||
|
if (this.bannerComponent)
|
||||||
|
this.bannerComponent.unmount();
|
||||||
|
}
|
||||||
|
|
||||||
mountLoginComponent() {
|
mountLoginComponent() {
|
||||||
if (!this.loginPromptComponent)
|
if (!this.loginPromptComponent)
|
||||||
this.loginPromptComponent = new LoginPrompt(this.connection);
|
this.loginPromptComponent = new LoginPrompt(this.connection);
|
||||||
|
|
||||||
this.loginPromptComponent.mountOn(this.mountElement);
|
this.loginPromptComponent.mountOn(this.mountElement);
|
||||||
this.loginPromptComponent.onPasswordSubmitted = p => {
|
this.loginPromptComponent.onPasswordSubmitted = (p) => {
|
||||||
setAuth(p);
|
setAuth(p);
|
||||||
this.connection.connect(p);
|
this.connection.connect(p);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
class Banner {
|
class Banner {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.text = null;
|
this.element = null;
|
||||||
|
|
||||||
|
this.title = "";
|
||||||
|
this.text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
updateText(text) {
|
updateText(newText) {
|
||||||
this.text = text;
|
this.text = newText;
|
||||||
|
this.element.querySelector("#banner-text").innerText = this.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTitle(newTitle) {
|
||||||
|
this.title = newTitle;
|
||||||
|
this.element.querySelector("#banner-title").innerText = this.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
mountOn(target) {
|
mountOn(target) {
|
||||||
|
@ -13,22 +22,21 @@ class Banner {
|
||||||
|
|
||||||
this.element = document.createRange().createContextualFragment(`
|
this.element = document.createRange().createContextualFragment(`
|
||||||
<div class="card small-card center-text">
|
<div class="card small-card center-text">
|
||||||
<h2>Login</h2>
|
<h2 id="banner-title"></h2>
|
||||||
<p>You need to enter the login code before you can start controlling your device.</p>
|
<p id="banner-text"></p>
|
||||||
<br>
|
|
||||||
<div class="full-width">
|
|
||||||
<input id="code-input" class="input full-width" placeholder="Code">
|
|
||||||
<br>
|
|
||||||
<button id="continue-button" class="button-default full-width">Continue</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`).children[0];
|
`).children[0];
|
||||||
|
|
||||||
this.element.querySelector("#continue-button").addEventListener("click", () => {
|
|
||||||
if (this.onPasswordSubmitted)
|
|
||||||
this.onPasswordSubmitted(this.element.querySelector("#code-input").value);
|
|
||||||
});
|
|
||||||
|
|
||||||
target.appendChild(this.element);
|
target.appendChild(this.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unmount() {
|
||||||
|
if (!this.element)
|
||||||
|
return; // Already unmounted
|
||||||
|
|
||||||
|
this.element.parentElement.removeChild(this.element);
|
||||||
|
this.element = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Banner;
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Connection {
|
||||||
this.messageLog = Logger(["Connection", "Message"], ["log"]).log;
|
this.messageLog = Logger(["Connection", "Message"], ["log"]).log;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.isReady = false;
|
this.isReady = false;
|
||||||
|
this.reconnectTimeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatAuthString(password) {
|
formatAuthString(password) {
|
||||||
|
@ -18,6 +19,7 @@ class Connection {
|
||||||
this.ws.onerror = (e) => this.log("Error", e);
|
this.ws.onerror = (e) => this.log("Error", e);
|
||||||
this.ws.onopen = () => {
|
this.ws.onopen = () => {
|
||||||
this.log("Open");
|
this.log("Open");
|
||||||
|
this.reconnectTimeout = 0;
|
||||||
this.log("Sending authentication packet");
|
this.log("Sending authentication packet");
|
||||||
this.ws.send(`0${this.formatAuthString(password)}`); // send auth packet
|
this.ws.send(`0${this.formatAuthString(password)}`); // send auth packet
|
||||||
};
|
};
|
||||||
|
@ -35,9 +37,12 @@ class Connection {
|
||||||
this.log("Closed due to bad auth - skipping reconnect");
|
this.log("Closed due to bad auth - skipping reconnect");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.log("Closed - attempting to reconnect in 4000ms");
|
|
||||||
this.isReady = false;
|
this.isReady = false;
|
||||||
setTimeout(() => this.connect(), 4000);
|
this.reconnectTimeout += 400;
|
||||||
|
if (this.reconnectTimeout >= 30000)
|
||||||
|
this.reconnectTimeout = 30000;
|
||||||
|
this.log(`Closed - will reconnect in ${this.reconnectTimeout}ms`);
|
||||||
|
setTimeout(() => this.connect(password), this.reconnectTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ body {
|
||||||
color: var(--accent-bg-color);
|
color: var(--accent-bg-color);
|
||||||
overflow-x: none;
|
overflow-x: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 8px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
|
@ -105,7 +105,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.touchpad {
|
.touchpad {
|
||||||
height: clamp(5rem, 30rem, 55vh);
|
height: clamp(5rem, 30rem, 50vh);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--accent-bg-color);
|
background-color: var(--accent-bg-color);
|
||||||
border-radius: var(--card-border-radius);
|
border-radius: var(--card-border-radius);
|
||||||
|
@ -113,9 +113,15 @@ body {
|
||||||
|
|
||||||
/* for virtual keyboard */
|
/* for virtual keyboard */
|
||||||
|
|
||||||
|
.hg-theme-default {
|
||||||
|
font-weight: var(--main-font-weight);
|
||||||
|
font-family: var(--fonts-regular);
|
||||||
|
}
|
||||||
|
|
||||||
.keyboard {
|
.keyboard {
|
||||||
|
padding: 8px;
|
||||||
color: var(--body-bg-color);
|
color: var(--body-bg-color);
|
||||||
margin-top: 28px;
|
margin-top: 24px;
|
||||||
border-radius: var(--card-border-radius);
|
border-radius: var(--card-border-radius);
|
||||||
background-color: var(--accent-bg-color);
|
background-color: var(--accent-bg-color);
|
||||||
}
|
}
|
||||||
|
@ -126,7 +132,6 @@ body {
|
||||||
|
|
||||||
.hg-button {
|
.hg-button {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
padding: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hg-activeButton {
|
.hg-activeButton {
|
||||||
|
|
Loading…
Reference in a new issue