Cleanup of server side state
This commit is contained in:
parent
a5979b2774
commit
fd7ccd596e
@ -104,7 +104,7 @@ const rules = (env) => {
|
|||||||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
||||||
loader: require.resolve("url-loader"),
|
loader: require.resolve("url-loader"),
|
||||||
options: {
|
options: {
|
||||||
limit: 10000,
|
limit: (env === "prod") ? 10000 : 0,
|
||||||
name: "static/media/[name].[hash:8].[ext]",
|
name: "static/media/[name].[hash:8].[ext]",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
import * as express from "express";
|
import * as express from "express";
|
||||||
|
|
||||||
|
import * as schema from "@common/sprinklers/schema";
|
||||||
|
import {serialize} from "serializr";
|
||||||
|
import {state} from "../state";
|
||||||
import logger from "./logger";
|
import logger from "./logger";
|
||||||
import serveApp from "./serveApp";
|
import serveApp from "./serveApp";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
app.use(logger);
|
app.use(logger);
|
||||||
|
|
||||||
|
app.get("/api/grinklers", (req, res) => {
|
||||||
|
const j = serialize(schema.sprinklersDevice, state.device);
|
||||||
|
res.send(j);
|
||||||
|
});
|
||||||
|
|
||||||
serveApp(app);
|
serveApp(app);
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
@ -4,89 +4,22 @@ import "env";
|
|||||||
import "./configureLogger";
|
import "./configureLogger";
|
||||||
|
|
||||||
import log from "@common/logger";
|
import log from "@common/logger";
|
||||||
import * as mqtt from "@common/sprinklers/mqtt";
|
import {Server} from "http";
|
||||||
import { Server } from "http";
|
|
||||||
import * as WebSocket from "ws";
|
import * as WebSocket from "ws";
|
||||||
|
|
||||||
import app from "./app";
|
import app from "./app";
|
||||||
|
import {state} from "./state";
|
||||||
const mqttClient = new mqtt.MqttApiClient("mqtt://localhost:1883");
|
import {handler as webSocketHandler} from "./websocket";
|
||||||
mqttClient.start();
|
|
||||||
|
|
||||||
import * as schema from "@common/sprinklers/schema";
|
|
||||||
import * as requests from "@common/sprinklers/requests";
|
|
||||||
import * as ws from "@common/sprinklers/websocketData";
|
|
||||||
import { autorun } from "mobx";
|
|
||||||
import { serialize } from "serializr";
|
|
||||||
const device = mqttClient.getDevice("grinklers");
|
|
||||||
|
|
||||||
app.get("/api/grinklers", (req, res) => {
|
|
||||||
const j = serialize(schema.sprinklersDevice, device);
|
|
||||||
res.send(j);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function doDeviceCallRequest(requestData: ws.IDeviceCallRequest) {
|
|
||||||
const { deviceName, data } = requestData;
|
|
||||||
if (deviceName !== "grinklers") {
|
|
||||||
// error handling? or just get the right device
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const request = schema.requests.deserializeRequest(data);
|
|
||||||
return device.makeRequest(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deviceCallRequest(socket: WebSocket, data: ws.IDeviceCallRequest): Promise<void> {
|
|
||||||
let response: requests.Response | false;
|
|
||||||
try {
|
|
||||||
response = await doDeviceCallRequest(data);
|
|
||||||
} catch (err) {
|
|
||||||
response = err;
|
|
||||||
}
|
|
||||||
if (response) {
|
|
||||||
const resData: ws.IDeviceCallResponse = {
|
|
||||||
type: "deviceCallResponse",
|
|
||||||
id: data.id,
|
|
||||||
data: response,
|
|
||||||
};
|
|
||||||
socket.send(JSON.stringify(resData));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function webSocketHandler(socket: WebSocket) {
|
|
||||||
const stop = autorun(() => {
|
|
||||||
const json = serialize(schema.sprinklersDevice, device);
|
|
||||||
log.trace({ device: json });
|
|
||||||
const data = { type: "deviceUpdate", name: "grinklers", data: json };
|
|
||||||
socket.send(JSON.stringify(data));
|
|
||||||
}, { delay: 100 });
|
|
||||||
socket.on("message", (socketData: WebSocket.Data) => {
|
|
||||||
if (typeof socketData !== "string") {
|
|
||||||
return log.error({ type: typeof socketData }, "received invalid socket data type from client");
|
|
||||||
}
|
|
||||||
let data: ws.IClientMessage;
|
|
||||||
try {
|
|
||||||
data = JSON.parse(socketData);
|
|
||||||
} catch (err) {
|
|
||||||
return log.error({ event, err }, "received invalid websocket message from client");
|
|
||||||
}
|
|
||||||
switch (data.type) {
|
|
||||||
case "deviceCallRequest":
|
|
||||||
deviceCallRequest(socket, data);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return log.warn({ data }, "received invalid client message type");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
socket.on("close", () => stop());
|
|
||||||
}
|
|
||||||
|
|
||||||
const port = +(process.env.PORT || 8080);
|
const port = +(process.env.PORT || 8080);
|
||||||
const host = process.env.HOST || "0.0.0.0";
|
const host = process.env.HOST || "0.0.0.0";
|
||||||
|
|
||||||
const server = new Server(app);
|
const server = new Server(app);
|
||||||
const webSocketServer = new WebSocket.Server({ server });
|
const webSocketServer = new WebSocket.Server({server});
|
||||||
|
|
||||||
webSocketServer.on("connection", webSocketHandler);
|
webSocketServer.on("connection", webSocketHandler);
|
||||||
|
|
||||||
|
state.start();
|
||||||
server.listen(port, host, () => {
|
server.listen(port, host, () => {
|
||||||
log.info(`listening at ${host}:${port}`);
|
log.info(`listening at ${host}:${port}`);
|
||||||
});
|
});
|
||||||
|
16
server/state.ts
Normal file
16
server/state.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {SprinklersDevice} from "@common/sprinklers";
|
||||||
|
import * as mqtt from "@common/sprinklers/mqtt";
|
||||||
|
|
||||||
|
export class State {
|
||||||
|
mqttClient!: mqtt.MqttApiClient;
|
||||||
|
device!: SprinklersDevice;
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.mqttClient = new mqtt.MqttApiClient("mqtt://localhost:1883");
|
||||||
|
this.device = this.mqttClient.getDevice("grinklers");
|
||||||
|
|
||||||
|
this.mqttClient.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const state: State = new State();
|
65
server/websocket/index.ts
Normal file
65
server/websocket/index.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { autorun } from "mobx";
|
||||||
|
import { serialize } from "serializr";
|
||||||
|
import * as WebSocket from "ws";
|
||||||
|
|
||||||
|
import log from "@common/logger";
|
||||||
|
import * as requests from "@common/sprinklers/requests";
|
||||||
|
import * as schema from "@common/sprinklers/schema";
|
||||||
|
import * as ws from "@common/sprinklers/websocketData";
|
||||||
|
|
||||||
|
import {state} from "../state";
|
||||||
|
|
||||||
|
async function doDeviceCallRequest(requestData: ws.IDeviceCallRequest) {
|
||||||
|
const { deviceName, data } = requestData;
|
||||||
|
if (deviceName !== "grinklers") {
|
||||||
|
// error handling? or just get the right device
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const request = schema.requests.deserializeRequest(data);
|
||||||
|
return state.device.makeRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deviceCallRequest(socket: WebSocket, data: ws.IDeviceCallRequest): Promise<void> {
|
||||||
|
let response: requests.Response | false;
|
||||||
|
try {
|
||||||
|
response = await doDeviceCallRequest(data);
|
||||||
|
} catch (err) {
|
||||||
|
response = err;
|
||||||
|
}
|
||||||
|
if (response) {
|
||||||
|
const resData: ws.IDeviceCallResponse = {
|
||||||
|
type: "deviceCallResponse",
|
||||||
|
id: data.id,
|
||||||
|
data: response,
|
||||||
|
};
|
||||||
|
socket.send(JSON.stringify(resData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handler(socket: WebSocket) {
|
||||||
|
const stop = autorun(() => {
|
||||||
|
const json = serialize(schema.sprinklersDevice, state.device);
|
||||||
|
log.trace({ device: json });
|
||||||
|
const data = { type: "deviceUpdate", name: "grinklers", data: json };
|
||||||
|
socket.send(JSON.stringify(data));
|
||||||
|
}, { delay: 100 });
|
||||||
|
socket.on("message", (socketData: WebSocket.Data) => {
|
||||||
|
if (typeof socketData !== "string") {
|
||||||
|
return log.error({ type: typeof socketData }, "received invalid socket data type from client");
|
||||||
|
}
|
||||||
|
let data: ws.IClientMessage;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(socketData);
|
||||||
|
} catch (err) {
|
||||||
|
return log.error({ event, err }, "received invalid websocket message from client");
|
||||||
|
}
|
||||||
|
switch (data.type) {
|
||||||
|
case "deviceCallRequest":
|
||||||
|
deviceCallRequest(socket, data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return log.warn({ data }, "received invalid client message type");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.on("close", () => stop());
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user