robotank/client-hodejs/robobase.ts

121 lines
3 KiB
TypeScript
Raw Normal View History

2025-03-03 02:17:50 +01:00
// SPDX-License-Identifier: GPL-3.0-or-later
// Author: Sascha Nitsch https://contentnation.net/@grumpydevelop
import WebSocket from 'ws';
import { RobotCmd } from './robotcmd';
import { RobotStatus } from './robotstatus';
abstract class RoboBase {
private pingTimeout: NodeJS.Timeout;
private socket: WebSocket;
private name: string;
private model: string;
protected cmd: RobotCmd;
protected width: number;
protected height: number;
private lastUpdate: number;
protected deltaTime: number;
constructor(name: string, model:string) {
this.name = name;
this.model = model;
this.cmd = new RobotCmd();
this.width = 0;
this.height = 0;
this.lastUpdate = 0;
this.deltaTime = 0;
}
connect() {
this.socket = new WebSocket('ws://127.0.0.1:3000/robot', undefined, {
perMessageDeflate: false,
autoPong: true
});
this.socket.addEventListener('error', this.error);
this.socket.addEventListener('open', () => {
this.open();
this.heartbeat();
});
this.socket.addEventListener('ping', this.heartbeat);
this.socket.addEventListener('message', this.message);
this.socket.addEventListener('close', () => {
clearTimeout(this.pingTimeout);
});
}
disconnect() {
this.socket.close();
}
error(...param) {
console.error(param);
}
private heartbeat = () => {
clearTimeout(this.pingTimeout);
this.pingTimeout = setTimeout(() => {
this.socket.terminate();
}, 30000 + 1000);
}
message = (event: MessageEvent) => {
this.heartbeat();
const msgtext = event.data.toString();
const tokens = msgtext.split(' ');
if (tokens.length == 1) {
switch (tokens[0]) {
case 'lost':
this.lost();
break;
case 'ready':
this.ready();
break;
case 'start':
this.start();
break;
case 'won':
this.won();
break;
default:
console.log('msg', tokens[0])
}
} else if (tokens.length == 2) {
switch (tokens[0]) {
case 'specs':
const specs = JSON.parse(tokens[1]);
this.width = specs['width'];
this.height = specs['height'];
break;
case 'status':
const status:RobotStatus = JSON.parse(tokens[1]);
this.deltaTime = status.simulationTime - this.lastUpdate;
this.lastUpdate = status.simulationTime;
this.statusReady(status);
break;
default:
console.log('unknown command tk2 ', msgtext);
}
} else {
console.log('unknown command tk3', msgtext);
}
}
open() {
this.socket.send('name ' + this.name);
this.socket.send('model ' + this.model);
}
sendCmd() {
this.socket.send('cmd ' + JSON.stringify(this.cmd.toObject()));
this.cmd.fire = false;
}
abstract lost(): void;
abstract ready(): void;
abstract start(): void;
abstract statusReady(status: RobotStatus): void;
abstract won(): void;
}
export { RoboBase }