websocket solution

This commit is contained in:
Break27 2023-10-09 19:45:22 +08:00
parent c536a1ac49
commit 1da10b3996
3 changed files with 43 additions and 40 deletions

View File

@ -20,10 +20,10 @@ class RemoteApi:
# ===== # =====
@exposed_http("POST", "/remote") @exposed_http("POST", "/remote/update")
async def __state_handler(self, _: Request) -> Response: async def __remote_update_handler(self, _: Request) -> Response:
return make_json_response({ return make_json_response({
"hosts": await self.__remote.get_state(), "update": await self.__remote.update(),
}) })
@exposed_http("POST", "/remote/control") @exposed_http("POST", "/remote/control")

View File

@ -5,22 +5,45 @@ import { $, $$$, tools } from "../tools.js";
import { fromNow } from "./relativeTime.js"; import { fromNow } from "./relativeTime.js";
let prev_state = {};
let loading = false; let loading = false;
let firstRun = true;
/********************************************************/ /********************************************************/
export function main() { export function main() {
loadRemoteApi(x => makeView(x));
setInterval(update, 10000);
$("rf").addEventListener("click", refresh); $("rf").addEventListener("click", refresh);
createWebSocket();
setInterval(updateOfflineTime, 5000);
} }
function update() { function createWebSocket() {
loadRemoteApi(x => x.forEach(y => updateState(y))); let address = `wss://${window.location.host}/api/ws`;
updateOfflineTime(); let socket = new WebSocket(address);
socket.onopen = () => {
console.log("WebSocket connection established.");
};
socket.onmessage = (e) => {
let { event_type, event } = JSON.parse(e.data);
if (event_type != "remote_state") {
return;
}
if (firstRun) { makeView(event); firstRun = false; }
else event.forEach(x => updateState(x));
};
socket.onerror = () => {
socket.close();
};
socket.onclose = () => {
console.log("Websocket connection lost. Retrying in 5 seconds.");
setTimeout(createWebSocket, 5000);
};
} }
function refresh(event) { function refresh(event) {
@ -30,8 +53,7 @@ function refresh(event) {
let icon = $$$("#rf div.icon")[0]; let icon = $$$("#rf div.icon")[0];
icon.classList.toggle("spin"); icon.classList.toggle("spin");
prev_state = {}; getApiUpdate(x => {
loadRemoteApi(x => {
x.forEach(y => updateState(y)); x.forEach(y => updateState(y));
setTimeout(() => { setTimeout(() => {
icon.classList.toggle("spin") icon.classList.toggle("spin")
@ -59,17 +81,15 @@ function guards(http) {
return true; return true;
} }
function loadRemoteApi(callback) { function getApiUpdate(callback) {
let http = tools.makeRequest("POST", "/api/remote", () => { let http = tools.makeRequest("POST", "/api/remote/update", () => {
let response = http.responseText; let response = http.responseText;
if (! guards(http)) return; if (! guards(http)) return;
if (! response) return; if (! response) return;
let hosts = JSON.parse(response).result.hosts; let update = JSON.parse(response).result.update;
let diff = stateDiff(hosts); callback(update);
callback(diff);
}); });
} }
@ -84,9 +104,7 @@ function actionPerform(target, action) {
let result = JSON.parse(response).result; let result = JSON.parse(response).result;
if (result.code != 0) { if (result.code != 0) {
delete prev_state[target];
let state = $$$(`.host[name='${target}'] span.state`)[0]; let state = $$$(`.host[name='${target}'] span.state`)[0];
state.innerHTML = '  ⦻  Failed'; state.innerHTML = '  ⦻  Failed';
setTimeout(update, 3000); setTimeout(update, 3000);
} }
@ -175,18 +193,3 @@ function updateOfflineTime(name) {
state.innerHTML = '  –  ' + fromNow(timestamp); state.innerHTML = '  –  ' + fromNow(timestamp);
} }
} }
function stateDiff(hosts) {
let diff = [];
for (const host of hosts) {
if (! (host.name in prev_state)
|| prev_state[host.name].online != host.online)
{
diff.push(host);
}
prev_state[host.name] = host;
}
return diff;
}