From fd7ccd596e5a1a5b640e3673e28f3b664d73cade Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Thu, 24 May 2018 10:36:16 -0600 Subject: [PATCH] Cleanup of server side state --- app/webpack.config.js | 2 +- server/app/index.ts | 9 +++++ server/index.ts | 79 +++------------------------------------ server/state.ts | 16 ++++++++ server/websocket/index.ts | 65 ++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 74 deletions(-) create mode 100644 server/state.ts create mode 100644 server/websocket/index.ts diff --git a/app/webpack.config.js b/app/webpack.config.js index e187bc1..c9dbfd4 100644 --- a/app/webpack.config.js +++ b/app/webpack.config.js @@ -104,7 +104,7 @@ const rules = (env) => { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: require.resolve("url-loader"), options: { - limit: 10000, + limit: (env === "prod") ? 10000 : 0, name: "static/media/[name].[hash:8].[ext]", }, }, diff --git a/server/app/index.ts b/server/app/index.ts index eb9f994..fdaff43 100644 --- a/server/app/index.ts +++ b/server/app/index.ts @@ -1,11 +1,20 @@ 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 serveApp from "./serveApp"; const app = express(); app.use(logger); + +app.get("/api/grinklers", (req, res) => { + const j = serialize(schema.sprinklersDevice, state.device); + res.send(j); +}); + serveApp(app); export default app; diff --git a/server/index.ts b/server/index.ts index 07e56e9..322a1a7 100644 --- a/server/index.ts +++ b/server/index.ts @@ -4,89 +4,22 @@ import "env"; import "./configureLogger"; 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 app from "./app"; - -const mqttClient = new mqtt.MqttApiClient("mqtt://localhost:1883"); -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 { - 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()); -} +import app from "./app"; +import {state} from "./state"; +import {handler as webSocketHandler} from "./websocket"; const port = +(process.env.PORT || 8080); const host = process.env.HOST || "0.0.0.0"; const server = new Server(app); -const webSocketServer = new WebSocket.Server({ server }); +const webSocketServer = new WebSocket.Server({server}); webSocketServer.on("connection", webSocketHandler); +state.start(); server.listen(port, host, () => { log.info(`listening at ${host}:${port}`); }); diff --git a/server/state.ts b/server/state.ts new file mode 100644 index 0000000..191e930 --- /dev/null +++ b/server/state.ts @@ -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(); diff --git a/server/websocket/index.ts b/server/websocket/index.ts new file mode 100644 index 0000000..3edf4e9 --- /dev/null +++ b/server/websocket/index.ts @@ -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 { + 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()); +}