mirror of
https://github.com/parnic/node-intellicenter.git
synced 2025-06-16 18:20:14 -05:00
Getting a feel for how the development experience is with this setup. With the previous idea of abstracting the request into a getSystemInfo() function on the Unit itself, the documentation for what to expect from GetSystemInfo either had to live in two places or be presented as a link to the canonical location. Neither felt great, so I think the caller can just call send(GetRequest()) themselves. Also added the first "set" message which is capable of toggling a body or circuit.
72 lines
1.8 KiB
TypeScript
72 lines
1.8 KiB
TypeScript
import { EventEmitter } from "events";
|
|
import { WebSocket } from "ws";
|
|
import { ICRequest } from "./messages/request.js";
|
|
import { ICResponse } from "./messages/response.js";
|
|
|
|
export class Unit extends EventEmitter {
|
|
private client?: WebSocket;
|
|
private pingTimeout?: ReturnType<typeof setTimeout>;
|
|
|
|
constructor(
|
|
public endpoint: string,
|
|
public port = 6680,
|
|
) {
|
|
super();
|
|
|
|
this.endpoint = endpoint;
|
|
this.port = port;
|
|
}
|
|
|
|
public async connect() {
|
|
if (this.client) {
|
|
throw new Error("can't open a client that is already open");
|
|
}
|
|
|
|
this.client = new WebSocket(
|
|
`ws://${this.endpoint}:${this.port.toString()}`,
|
|
);
|
|
|
|
const { heartbeat, onClientMessage } = this;
|
|
this.client.on("error", console.error);
|
|
this.client.on("open", heartbeat);
|
|
this.client.on("ping", heartbeat);
|
|
this.client.on("close", () => {
|
|
clearTimeout(this.pingTimeout);
|
|
this.client?.removeAllListeners();
|
|
this.client = undefined;
|
|
});
|
|
this.client.on("message", onClientMessage);
|
|
|
|
await new Promise((resolve, reject) => {
|
|
this.client?.once("error", reject);
|
|
this.client?.once("open", resolve);
|
|
});
|
|
}
|
|
|
|
public close() {
|
|
this.client?.close();
|
|
}
|
|
|
|
private heartbeat = () => {
|
|
clearTimeout(this.pingTimeout);
|
|
|
|
this.pingTimeout = setTimeout(() => {
|
|
this.close();
|
|
}, 30000 + 1000);
|
|
};
|
|
|
|
private onClientMessage = (msg: Buffer) => {
|
|
const respObj = JSON.parse(msg.toString()) as ICResponse;
|
|
this.emit(`response-${respObj.messageID}`, respObj);
|
|
};
|
|
|
|
public async send(request: ICRequest): Promise<ICResponse> {
|
|
this.client?.send(JSON.stringify(request));
|
|
return await new Promise((resolve) => {
|
|
this.once(`response-${request.messageID}`, (resp: ICResponse) => {
|
|
resolve(resp);
|
|
});
|
|
});
|
|
}
|
|
}
|