Major progress on #20. Promised-based websocket command structure is completed. All functionality needs to be placed into individual classes and any new functions get added to the server.

Will create entire thin client using this method.
This commit is contained in:
Matt McWilliams 2023-02-25 11:59:56 -05:00
parent e64277e438
commit 1290a8f324
15 changed files with 465 additions and 85 deletions

View File

@ -1,5 +1,5 @@
{
"version": "1.7.7",
"version": "1.7.9",
"ext_port": 1111,
"profiles": {
"mcopy": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/**
* Delay in an async/await function
*
* @param {integer} ms Milliseconds to delay for
*
* @returns {Promise} Promise to resolve after timeout
**/
declare function delay(ms: number): Promise<unknown>;

View File

@ -7,6 +7,7 @@ const ws_1 = require("ws");
const express_1 = __importDefault(require("express"));
const promises_1 = require("fs/promises");
const mime_1 = __importDefault(require("mime"));
const uuid_1 = require("uuid");
const Log = require("log");
class Server {
constructor() {
@ -25,6 +26,8 @@ class Server {
this.port = 9900;
this.wsPort = 9901;
this.proxy = {};
this.queue = {};
this.intervalPeriod = 10000; //10 sec
this.init();
}
async init() {
@ -57,18 +60,28 @@ class Server {
this.log.error(err);
return;
}
this.wss.on('connection', (ws) => {
this.log.info(`Client connected to WebSocketServer`);
console.dir(ws);
ws.send('mcopy');
});
this.wss.on('connection', async function (ws) {
ws.on("message", function (data) {
let obj = JSON.parse(data);
this.log.info(data);
if (obj.id && this.queue[obj.id]) {
this.queue[obj.id](obj);
delete this.queue[obj.id];
}
}.bind(this));
ws.on('close', function () {
this.log.info('Client disconnected');
}.bind(this));
await this.cmd(ws, 'mcopy');
this.log.info('Client connected');
}.bind(this));
this.log.info(`Websocket server started!`);
this.log.info(`WSS [ ws://localhost:${this.wsPort} ]`);
}
async startHttp() {
return new Promise(function (resolve, reject) {
this.httpd = this.http.listen(this.port, function () {
this.isActive = true;
this.log.info(`Server started!`);
this.log.info(`HTTP server started!`);
this.log.info(`URL [ http://localhost:${this.port} ]`);
return resolve(true);
}.bind(this));
@ -77,16 +90,24 @@ class Server {
async start() {
await this.startHttp();
await this.startWss();
this.interval = setInterval(async function () {
await this.cmdAll('ping');
}.bind(this), this.intervalPeriod);
this.isActive = true;
}
async stop() {
async stopHttp() {
return new Promise(function (resolve, reject) {
return this.httpd.close(function () {
this.isActive = false;
this.log.info(`Server stopped :(`);
this.log.info(`HTTP server stopped :(`);
return resolve(false);
}.bind(this));
}.bind(this));
}
async stop() {
await this.stopHttp();
clearInterval(this.interval);
this.isActive = false;
}
index(req, res, next) {
const html = this.template('index', { PORT: `${this.port}` });
this.log.info('GET /');
@ -122,12 +143,43 @@ class Server {
}.bind(this));
}
addProxy(key, filePath) {
//wipe every time
this.proxy = {};
this.proxy[key] = {
path: filePath,
mime: mime_1.default.getType(filePath)
};
this.log.info(`Added proxy image [${key}]`);
}
async cmdAll(action, options = {}) {
const cmds = [];
if (this.isActive && this.wss.clients.size > 0) {
this.wss.clients.forEach(function (ws) {
cmds.push(this.cmd(ws, action, options));
}.bind(this));
return await Promise.all(cmds);
}
return false;
}
/**
* WSS
**/
async cmd(ws, action, options = {}) {
const id = uuid_1.v4();
let obj = {
id, action
};
let str;
obj = Object.assign(obj, options);
str = JSON.stringify(obj);
ws.send(str);
return new Promise(function (resolve, reject) {
this.queue[id] = function (obj) {
return resolve(obj);
};
//setTimeout() ?
}.bind(this));
}
}
module.exports = function () {
return new Server();

File diff suppressed because one or more lines are too long

2
app/package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "mcopy-app",
"version": "1.7.9",
"version": "1.7.10",
"lockfileVersion": 2,
"requires": true,
"packages": {

View File

@ -1,6 +1,6 @@
{
"name": "mcopy-app",
"version": "1.7.9",
"version": "1.7.10",
"description": "GUI for the mcopy small gauge film optical printer platform",
"main": "main.js",
"scripts": {

View File

@ -3,6 +3,9 @@
<style>
html, body{ background: #000; padding: 0; margin: 0; width: 100vw; height: 100vh; overflow: hidden; }
body.meter { background: rgb(117, 117, 117); }
body.blank { background: #000; }
body.blank #img { display: none; }
body.blank #can { display: none; }
#nosleep { color: #fff; margin: 50px auto }
#img {
position: absolute;

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{
"version": "1.7.9",
"version": "1.7.10",
"ext_port": 1111,
"profiles": {
"mcopy": {

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "mcopy",
"version": "1.7.9",
"version": "1.7.10",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "mcopy",
"version": "1.7.9",
"version": "1.7.10",
"license": "MIT",
"dependencies": {
"arduino": "file:app/lib/arduino",

View File

@ -1,6 +1,6 @@
{
"name": "mcopy",
"version": "1.7.9",
"version": "1.7.10",
"description": "Small gauge film optical printer platform",
"main": "build.js",
"directories": {

View File

@ -1,5 +1,5 @@
{
"version": "1.7.9",
"version": "1.7.10",
"ext_port": 1111,
"profiles": {
"mcopy": {

View File

@ -2,7 +2,9 @@ import WebSocket, { WebSocketServer } from 'ws'
import express, { Express, Request, Response, Application } from 'express'
import { readFile } from 'fs/promises'
import mime from 'mime'
import { v4 as uuidv4 } from 'uuid'
import Log = require('log')
import { delay } from 'delay';
interface ServerData {
[key: string]: string;
@ -24,6 +26,10 @@ interface ServerProxyList {
[key: string]: ServerProxy;
}
interface ServerQueue {
[key: string]: Function;
}
class Server {
private id : string = 'server'
public isActive : boolean = false
@ -44,10 +50,12 @@ class Server {
private port : number = 9900
private wsPort : number = 9901
private proxy : ServerProxyList = {}
private queue : ServerQueue = {}
private interval : ReturnType<typeof setInterval>
private intervalPeriod : number = 10000 //10 sec
constructor () {
this.init()
}
async init () {
@ -84,17 +92,32 @@ class Server {
this.log.error(err)
return
}
this.wss.on('connection', (ws) => {
this.log.info(`Client connected to WebSocketServer`)
ws.send(JSON.stringify({ action : 'mcopy' });
})
this.wss.on('connection', async function (ws : WebSocket) {
ws.on("message", function (data : string ) {
let obj : any = JSON.parse(data)
this.log.info(data)
if (obj.id && this.queue[obj.id]) {
this.queue[obj.id](obj)
delete this.queue[obj.id]
}
}.bind(this))
ws.on('close', function () {
this.log.info('Client disconnected')
}.bind(this))
await this.cmd(ws, 'mcopy')
this.log.info('Client connected')
}.bind(this))
this.log.info(`Websocket server started!`)
this.log.info(`WSS [ ws://localhost:${this.wsPort} ]`)
}
async startHttp () {
return new Promise(function (resolve : Function, reject : Function) {
this.httpd = this.http.listen(this.port, function () {
this.log.info(`Server started!`)
this.log.info(`HTTP server started!`)
this.log.info(`URL [ http://localhost:${this.port} ]`)
return resolve(true)
}.bind(this))
@ -104,19 +127,27 @@ class Server {
async start () {
await this.startHttp()
await this.startWss()
this.interval = setInterval(async function () {
await this.cmdAll('ping');
}.bind(this), this.intervalPeriod)
this.isActive = true
}
async stop() {
async stopHttp() {
return new Promise(function (resolve : Function, reject : Function) {
return this.httpd.close(function () {
this.isActive = false
this.log.info(`Server stopped :(`)
this.log.info(`HTTP server stopped :(`)
return resolve(false)
}.bind(this))
}.bind(this))
}
async stop () {
await this.stopHttp()
clearInterval(this.interval)
this.isActive = false
}
index (req : Request, res : Response, next : Function) {
const html : string = this.template('index', { PORT : `${this.port}` })
this.log.info('GET /')
@ -152,12 +183,48 @@ class Server {
}
public addProxy (key : string, filePath : string) {
//wipe every time
this.proxy = {}
this.proxy[key] = {
path : filePath,
mime : mime.getType(filePath)
}
this.log.info(`Added proxy image [${key}]`)
}
public async cmdAll (action : string, options : any = {}) {
const cmds : any[] = []
if (this.isActive && this.wss.clients.size > 0) {
this.wss.clients.forEach(function (ws : WebSocket) {
cmds.push(this.cmd(ws, action, options))
}.bind(this))
return await Promise.all(cmds)
}
return false
}
/**
* WSS
**/
public async cmd (ws : WebSocket, action : string, options : any = {}) {
const id : string = uuidv4()
let obj = {
id, action
}
let str : string
obj = Object.assign(obj, options)
str = JSON.stringify(obj)
ws.send(str)
return new Promise(function (resolve : Function, reject: Function) {
this.queue[id] = function (obj : any) {
return resolve(obj)
}
//setTimeout() ?
}.bind(this))
}
}
module.exports = function () {