generated from homebridge/homebridge-plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SocketClient.ts
123 lines (99 loc) · 3.58 KB
/
SocketClient.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import {client as WssClient, connection as WssConnection} from 'websocket';
import {Logger} from 'homebridge';
export default class SocketClient {
private client: WssClient | null = null;
private connection: WssConnection | null = null;
private listeners: Array<{id: string; callback: (msg: string) => unknown}> = [];
constructor(
private readonly sockeHost: string,
private readonly socketPort: number,
private readonly irCodeType: string,
private readonly logger: Logger,
) {
this.logger.debug('Inside SocketClient Class');
this.connect();
}
private connect(callback?: (err?: Error) => void) {
this.client = new WssClient();
this.client.on('connect', (connection: WssConnection) => {
this.logger.debug('Socket Connection established!');
this.connection = connection;
this.logger.debug('Adding connection listeners...');
this.connection.on('error', (error) => {
this.logger.error('WSS Connection Error');
this.logger.error(error.message);
this.connection!.close();
setTimeout(() => {
this.connect();
}, 1000);
});
this.connection.on('close', () => {
this.logger.debug('Socket Connection closed by Server');
this.connect();
});
this.connection.on('message', (message) => {
if (message.type !== 'utf8') {
throw new Error('Cannot handle binary WebSocket messages...');
}
this.handleMessage(message.utf8Data as string);
});
if (callback) {
callback();
}
});
this.client.on('connectFailed', (err) => {
if (callback) {
callback(err);
}
this.logger.error('WSS Connection failed!');
this.logger.error(err.message);
setTimeout(() => {
this.connect();
}, 1000);
});
this.logger.debug('Connecting to Socket Server...');
const wssServerAddress = `ws://${this.sockeHost}:${this.socketPort}`;
this.logger.debug(`Server: ${wssServerAddress}`);
this.client.connect(wssServerAddress);
}
public addMessageListener(listenerId: string, callback: (msg: string) => unknown) {
this.listeners.push({id: listenerId, callback});
}
public removeMessageListener(listenerId: string) {
this.listeners = this.listeners.filter(
(listener) => listener.id !== listenerId,
);
}
private handleMessage(msg: string) {
const [command, payload] = msg.split(';');
this.logger.debug('received message: ' + JSON.stringify({command, payload}));
this.listeners.forEach((listener) => listener.callback(msg));
}
public sendCommand(command: string, payload = '') {
if (command === 'IR-SEND') {
command = 'IR-SEND:' + this.irCodeType;
}
this.logger.debug(`SENDING SOCKET MESSAGE: ${JSON.stringify({command, payload})}`);
return new Promise((resolve, reject) => {
if (!this.connection) {
this.connect((err) => {
if (err) {
throw new Error('No connection available');
}
return this.sendCommand(command, payload);
});
return;
}
this.connection.send(`${command};${payload}`, (err) => {
if (err) {
this.logger.debug('Sending failed!');
this.logger.error(err!.message);
reject(err);
} else {
this.logger.debug('Sending succeeded!');
resolve();
}
});
});
}
}