Browse Source

Cleanup of server side state

update-deps
Alex Mikhalev 7 years ago
parent
commit
fd7ccd596e
  1. 2
      app/webpack.config.js
  2. 9
      server/app/index.ts
  3. 79
      server/index.ts
  4. 16
      server/state.ts
  5. 65
      server/websocket/index.ts

2
app/webpack.config.js

@ -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]",
}, },
}, },

9
server/app/index.ts

@ -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;

79
server/index.ts

@ -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";
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<void> { import app from "./app";
let response: requests.Response | false; import {state} from "./state";
try { import {handler as webSocketHandler} from "./websocket";
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

@ -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

@ -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…
Cancel
Save