Browse Source

Refactored out websocket api and state stuff

update-deps
Alex Mikhalev 7 years ago
parent
commit
d5b65d7a99
  1. 2
      common/sprinklers/schema/list.ts
  2. 16
      server/app/index.ts
  3. 13
      server/index.ts
  4. 4
      server/state.ts
  5. 82
      server/websocket/index.ts

2
common/sprinklers/schema/list.ts

@ -2,7 +2,7 @@ import { primitive, PropSchema } from "serializr"; @@ -2,7 +2,7 @@ import { primitive, PropSchema } from "serializr";
function invariant(cond: boolean, message?: string) {
if (!cond) {
throw new Error("[serializr] " + (message || "Illegal State"));
throw new Error("[serializr] " + (message || "Illegal ServerState"));
}
}

16
server/app/index.ts

@ -2,19 +2,21 @@ import * as express from "express"; @@ -2,19 +2,21 @@ import * as express from "express";
import * as schema from "@common/sprinklers/schema";
import {serialize} from "serializr";
import {state} from "../state";
import { ServerState } from "../state";
import logger from "./logger";
import serveApp from "./serveApp";
const app = express();
export function createApp(state: ServerState) {
const app = express();
app.use(logger);
app.use(logger);
app.get("/api/grinklers", (req, res) => {
app.get("/api/grinklers", (req, res) => {
const j = serialize(schema.sprinklersDevice, state.device);
res.send(j);
});
});
serveApp(app);
serveApp(app);
export default app;
return app;
}

13
server/index.ts

@ -7,17 +7,20 @@ import log from "@common/logger"; @@ -7,17 +7,20 @@ import log from "@common/logger";
import {Server} from "http";
import * as WebSocket from "ws";
import app from "./app";
import {state} from "./state";
import {handler as webSocketHandler} from "./websocket";
import { ServerState } from "./state";
import { createApp } from "./app";
import { WebSocketApi } from "./websocket";
const state = new ServerState();
const app = createApp(state);
const webSocketApi = new WebSocketApi(state);
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});
webSocketServer.on("connection", webSocketHandler);
webSocketServer.on("connection", webSocketApi.handleConnection);
state.start();
server.listen(port, host, () => {

4
server/state.ts

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import {SprinklersDevice} from "@common/sprinklers";
import * as mqtt from "@common/sprinklers/mqtt";
export class State {
export class ServerState {
mqttClient!: mqtt.MqttApiClient;
device!: SprinklersDevice;
@ -16,5 +16,3 @@ export class State { @@ -16,5 +16,3 @@ export class State {
this.mqttClient.start();
}
}
export const state: State = new State();

82
server/websocket/index.ts

@ -1,45 +1,23 @@ @@ -1,45 +1,23 @@
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 { autorun } from "mobx";
import { serialize } from "serializr";
import * as WebSocket from "ws";
import { ServerState } from "../state";
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);
}
export class WebSocketApi {
state: ServerState;
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));
constructor(state: ServerState) {
this.state = state;
}
}
export function handler(socket: WebSocket) {
handleConnection = (socket: WebSocket) => {
const disposers = [
autorun(() => {
const json = serialize(schema.sprinklersDevice, state.device);
const json = serialize(schema.sprinklersDevice, this.state.device);
log.trace({ device: json });
const data: ws.IDeviceUpdate = { type: "deviceUpdate", name: "grinklers", data: json };
socket.send(JSON.stringify(data));
@ -47,7 +25,7 @@ export function handler(socket: WebSocket) { @@ -47,7 +25,7 @@ export function handler(socket: WebSocket) {
autorun(() => {
const data: ws.IBrokerConnectionUpdate = {
type: "brokerConnectionUpdate",
brokerConnected: state.mqttClient.connected,
brokerConnected: this.state.mqttClient.connected,
};
socket.send(JSON.stringify(data));
}),
@ -55,7 +33,11 @@ export function handler(socket: WebSocket) { @@ -55,7 +33,11 @@ export function handler(socket: WebSocket) {
const stop = () => {
disposers.forEach((disposer) => disposer());
};
socket.on("message", (socketData: WebSocket.Data) => {
socket.on("message", this.handleSocketMessage);
socket.on("close", () => stop());
}
private handleSocketMessage = (socket: WebSocket, socketData: WebSocket.Data) => {
if (typeof socketData !== "string") {
return log.error({ type: typeof socketData }, "received invalid socket data type from client");
}
@ -67,11 +49,37 @@ export function handler(socket: WebSocket) { @@ -67,11 +49,37 @@ export function handler(socket: WebSocket) {
}
switch (data.type) {
case "deviceCallRequest":
deviceCallRequest(socket, data);
this.deviceCallRequest(socket, data);
break;
default:
return log.warn({ data }, "received invalid client message type");
}
});
socket.on("close", () => stop());
}
private async deviceCallRequest(socket: WebSocket, data: ws.IDeviceCallRequest): Promise<void> {
let response: requests.Response | false;
try {
response = await this.doDeviceCallRequest(data);
} catch (err) {
response = err;
}
if (response) {
const resData: ws.IDeviceCallResponse = {
type: "deviceCallResponse",
id: data.id,
data: response,
};
socket.send(JSON.stringify(resData));
}
}
private async doDeviceCallRequest(requestData: ws.IDeviceCallRequest): Promise<requests.Response | false> {
const { deviceName, data } = requestData;
if (deviceName !== "grinklers") {
// error handling? or just get the right device
return false;
}
const request = schema.requests.deserializeRequest(data);
return this.state.device.makeRequest(request);
}
}

Loading…
Cancel
Save