@evops/lightwaverf 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LightwaveAccount.d.ts +13 -0
- package/dist/LightwaveAccount.js +81 -0
- package/dist/LightwaveDevice.d.ts +26 -0
- package/dist/LightwaveDevice.js +64 -0
- package/dist/LightwaveJsonMessageProcessor.d.ts +10 -0
- package/dist/LightwaveJsonMessageProcessor.js +24 -0
- package/dist/LightwaveMessage.d.ts +9 -0
- package/dist/LightwaveMessage.js +2 -0
- package/dist/LightwaveMessageProcessor.d.ts +7 -0
- package/dist/LightwaveMessageProcessor.js +3 -0
- package/dist/LightwaveRFClient.d.ts +32 -0
- package/dist/LightwaveRFClient.js +202 -0
- package/dist/LightwaveTextMessageProcessor.d.ts +10 -0
- package/dist/LightwaveTextMessageProcessor.js +25 -0
- package/dist/LightwaveTransaction.d.ts +8 -0
- package/dist/LightwaveTransaction.js +2 -0
- package/dist/Queue.d.ts +7 -0
- package/dist/Queue.js +19 -0
- package/dist/index.d.ts +13 -74
- package/dist/index.js +116 -343
- package/package.json +2 -2
- package/src/LightwaveAccount.ts +107 -0
- package/src/LightwaveDevice.ts +66 -0
- package/src/LightwaveJsonMessageProcessor.ts +29 -0
- package/src/LightwaveMessageProcessor.ts +8 -0
- package/src/LightwaveRFClient.ts +236 -0
- package/src/LightwaveTextMessageProcessor.ts +30 -0
- package/src/LightwaveTransaction.ts +9 -0
- package/src/Queue.ts +17 -0
- package/src/index.ts +332 -0
- package/index.ts +0 -586
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import Debug, { Debugger } from "debug";
|
|
2
|
+
import { RequestAPI, RequiredUriUrl } from "request";
|
|
3
|
+
import rp from "request-promise";
|
|
4
|
+
import { LightwaveDevice, LightwaveDeviceType } from "./LightwaveDevice";
|
|
5
|
+
import { LightwaveRFClient } from "./LightwaveRFClient";
|
|
6
|
+
|
|
7
|
+
export class LightwaveAccount {
|
|
8
|
+
debug: Debug.Debugger;
|
|
9
|
+
client: LightwaveRFClient;
|
|
10
|
+
email: string;
|
|
11
|
+
pin: string;
|
|
12
|
+
mainDebug: Debug.Debugger;
|
|
13
|
+
|
|
14
|
+
constructor(debug: Debugger, client: LightwaveRFClient, email: string, pin: string) {
|
|
15
|
+
if (!email || !pin) {
|
|
16
|
+
throw "No email or pin specified. The server configuration (rooms, devices, etc.) cannot be obtained";
|
|
17
|
+
}
|
|
18
|
+
this.mainDebug = debug;
|
|
19
|
+
this.debug = debug.extend('account');
|
|
20
|
+
this.client = client;
|
|
21
|
+
this.email = email;
|
|
22
|
+
this.pin = pin;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getConfiguration(callback: any) {
|
|
26
|
+
this.debug('Getting rooms from LightWave');
|
|
27
|
+
var self = this;
|
|
28
|
+
var host = 'https://control-api.lightwaverf.com';
|
|
29
|
+
var json = rp.defaults({
|
|
30
|
+
json: true
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
var auth: RequestAPI<rp.RequestPromise<any>, rp.RequestPromiseOptions, RequiredUriUrl>, token;
|
|
34
|
+
json.get(host + '/v1/user?password=' + this.pin + '&username=' + this.email)
|
|
35
|
+
.then(function (res) {
|
|
36
|
+
return json.get(host + '/v1/auth?application_key=' + res.application_key)
|
|
37
|
+
})
|
|
38
|
+
.then(function (res) {
|
|
39
|
+
token = res.token;
|
|
40
|
+
auth = json.defaults({
|
|
41
|
+
headers: {
|
|
42
|
+
'X-LWRF-token': token,
|
|
43
|
+
'X-LWRF-platform': 'ios',
|
|
44
|
+
'X-LWRF-skin': 'lightwaverf'
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return auth.get(host + '/v1/device_type?nested=1');
|
|
49
|
+
})
|
|
50
|
+
.then(function (res) {
|
|
51
|
+
return auth.get(host + '/v1/user_profile?nested=1')
|
|
52
|
+
})
|
|
53
|
+
.then(function (res) {
|
|
54
|
+
self.parseRooms(res, callback);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
parseRooms(lightwaveResponse: any, callback: (devices: LightwaveDevice[], error: Error | null) => void) {
|
|
60
|
+
this.debug('Parsing lightwaveResponse: ',
|
|
61
|
+
lightwaveResponse.content.estates[0].locations[0].zones[0].rooms[0].devices);
|
|
62
|
+
|
|
63
|
+
const home = lightwaveResponse.content.estates[0].locations[0].zones[0];
|
|
64
|
+
const devices = [];
|
|
65
|
+
|
|
66
|
+
for (var i = 0; i < home.rooms.length; i++) {
|
|
67
|
+
var r = home.rooms[i];
|
|
68
|
+
|
|
69
|
+
this.debug("Room " + r.name + " with " + r.devices.length + " devices");
|
|
70
|
+
|
|
71
|
+
// Get device types
|
|
72
|
+
// O: On/Off Switch
|
|
73
|
+
// D: Dimmer
|
|
74
|
+
// R: Radiator(s)
|
|
75
|
+
// P: Open/Close
|
|
76
|
+
// I: Inactive (i.e. not configured)
|
|
77
|
+
// m: Mood (inactive)
|
|
78
|
+
// M: Mood (active)
|
|
79
|
+
// o: All Off
|
|
80
|
+
var deviceTypeMapping: Map<number, LightwaveDeviceType> = new Map<number, LightwaveDeviceType>();
|
|
81
|
+
deviceTypeMapping.set(1, LightwaveDeviceType.OnOff);
|
|
82
|
+
deviceTypeMapping.set(2, LightwaveDeviceType.Dimmer);
|
|
83
|
+
deviceTypeMapping.set(3, LightwaveDeviceType.OnOff);
|
|
84
|
+
|
|
85
|
+
for (var j = 0; j < r.devices.length; j++) {
|
|
86
|
+
var d = r.devices[j];
|
|
87
|
+
|
|
88
|
+
const device = new LightwaveDevice(
|
|
89
|
+
this.client,
|
|
90
|
+
this.mainDebug,
|
|
91
|
+
r.room_number,
|
|
92
|
+
d.device_number,
|
|
93
|
+
r.name,
|
|
94
|
+
d.name,
|
|
95
|
+
deviceTypeMapping.get(d.device_type_id)!
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
devices.push(device);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.debug('Devices: %O', devices)
|
|
103
|
+
|
|
104
|
+
callback(devices, null);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import Debug from 'debug';
|
|
2
|
+
import { LightwaveRFClient } from './LightwaveRFClient';
|
|
3
|
+
|
|
4
|
+
export interface LightwaveRFDeviceInterface {
|
|
5
|
+
roomId: number
|
|
6
|
+
deviceId: number
|
|
7
|
+
roomName: string
|
|
8
|
+
deviceName: string
|
|
9
|
+
deviceType: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export enum LightwaveDeviceType {
|
|
13
|
+
Dimmer = "D",
|
|
14
|
+
OnOff = "O",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class LightwaveDevice implements LightwaveRFDeviceInterface {
|
|
18
|
+
roomId: number;
|
|
19
|
+
deviceId: number;
|
|
20
|
+
roomName: string;
|
|
21
|
+
deviceName: string;
|
|
22
|
+
deviceType: LightwaveDeviceType;
|
|
23
|
+
client: LightwaveRFClient;
|
|
24
|
+
debug: Debug.Debugger;
|
|
25
|
+
|
|
26
|
+
constructor(client: LightwaveRFClient, debug: debug.Debugger, roomId: number, deviceId: number, roomName: string, deviceName: string, deviceType: LightwaveDeviceType) {
|
|
27
|
+
this.client = client;
|
|
28
|
+
this.debug = debug.extend(deviceName);
|
|
29
|
+
this.roomId = roomId;
|
|
30
|
+
this.deviceId = deviceId;
|
|
31
|
+
this.roomName = roomName;
|
|
32
|
+
this.deviceName = deviceName;
|
|
33
|
+
this.deviceType = deviceType;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async turnOn(): Promise<void> {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
this.debug("Device turning on");
|
|
39
|
+
this.client.send(`R${this.roomId}D${this.deviceId}F1`, (message, error) => {
|
|
40
|
+
resolve();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async turnOff(): Promise<void> {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
this.debug("Device turning off");
|
|
48
|
+
this.client.send(`R${this.roomId}D${this.deviceId}F0`, (message, error) => {
|
|
49
|
+
if (error) return reject(error);
|
|
50
|
+
resolve();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async dim(percentage: number): Promise<void> {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
this.debug("Device dimming to %d", percentage);
|
|
58
|
+
|
|
59
|
+
const lwDim = Math.round(percentage * 0.32);
|
|
60
|
+
this.client.send(`R${this.roomId}D${this.deviceId}FdP${lwDim}`, (message, error) => {
|
|
61
|
+
if (error) return reject(error);
|
|
62
|
+
resolve();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Debugger } from "debug";
|
|
2
|
+
import "./LightwaveTransaction";
|
|
3
|
+
import { LightwaveTransaction } from "./LightwaveTransaction";
|
|
4
|
+
import LightwaveMessageProcessor from "./LightwaveMessageProcessor";
|
|
5
|
+
|
|
6
|
+
export class LightwaveJsonMessageProcessor implements LightwaveMessageProcessor {
|
|
7
|
+
debug: Debugger;
|
|
8
|
+
constructor(debug: Debugger) {
|
|
9
|
+
this.debug = debug.extend('jsonMessageProcessor');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
process(message: Buffer): any {
|
|
13
|
+
this.debug('Processing message')
|
|
14
|
+
const textMessage = message.toString('utf-8').replace('*!', '');
|
|
15
|
+
const json = JSON.parse(textMessage);
|
|
16
|
+
|
|
17
|
+
const response = json;
|
|
18
|
+
response.id = json.trans;
|
|
19
|
+
response.error = json.error ?? null;
|
|
20
|
+
|
|
21
|
+
return response;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
canProcess(message: Buffer): boolean {
|
|
25
|
+
this.debug("Checking if can process message");
|
|
26
|
+
return message.toString('utf-8').startsWith('*!');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import dgram from 'dgram';
|
|
2
|
+
import events from 'events';
|
|
3
|
+
import Debug, { Debugger } from 'debug';
|
|
4
|
+
import LightwaveMessageProcessor from './LightwaveMessageProcessor';
|
|
5
|
+
import LightwaveTextMessageProcessor from './LightwaveTextMessageProcessor';
|
|
6
|
+
import { LightwaveJsonMessageProcessor } from './LightwaveJsonMessageProcessor';
|
|
7
|
+
import { LightwaveTransaction } from './LightwaveTransaction';
|
|
8
|
+
import { Queue } from './Queue';
|
|
9
|
+
|
|
10
|
+
declare interface LightwaveRFClientInterface {
|
|
11
|
+
on(event: 'ready', listener: (client: LightwaveRFClient) => void): this;
|
|
12
|
+
on(event: 'deviceTurnedOn', listener: (room: number, device: number) => void): this;
|
|
13
|
+
on(event: 'deviceTurnedOff', listener: (room: number, device: number) => void): this;
|
|
14
|
+
on(event: 'deviceDimmed', listener: (room: number, device: number, dimPercentage: number) => void): this;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class LightwaveRFClient extends events.EventEmitter implements LightwaveRFClientInterface {
|
|
18
|
+
private senderSocket: dgram.Socket;
|
|
19
|
+
private receiverSocket: dgram.Socket;
|
|
20
|
+
|
|
21
|
+
private senderSocketReady: boolean = false;
|
|
22
|
+
private receiverSocketReady: boolean = false;
|
|
23
|
+
|
|
24
|
+
private commandQueue: Queue<LightwaveTransaction> = new Queue<LightwaveTransaction>();
|
|
25
|
+
|
|
26
|
+
private messageProcessors: LightwaveMessageProcessor[] = [];
|
|
27
|
+
|
|
28
|
+
private debug: Debug.Debugger;
|
|
29
|
+
private ip: string;
|
|
30
|
+
private transactionListeners: Map<number, any> = new Map();
|
|
31
|
+
delay: number = 125;
|
|
32
|
+
|
|
33
|
+
constructor(debug: Debugger, ip: string = "255.255.255.255", port: number = 9761) {
|
|
34
|
+
super();
|
|
35
|
+
|
|
36
|
+
this.ip = ip;
|
|
37
|
+
this.debug = debug.extend('client');
|
|
38
|
+
this.senderSocket = dgram.createSocket('udp4');
|
|
39
|
+
this.receiverSocket = dgram.createSocket('udp4');
|
|
40
|
+
|
|
41
|
+
this.messageProcessors.push(new LightwaveJsonMessageProcessor(this.debug));
|
|
42
|
+
this.messageProcessors.push(new LightwaveTextMessageProcessor(this.debug));
|
|
43
|
+
|
|
44
|
+
this.receiverSocket.on('message', (buffer: Buffer) => {
|
|
45
|
+
this.debug("RAW: %o", buffer.toString('utf-8'));
|
|
46
|
+
});
|
|
47
|
+
this.receiverSocket.on('message', this.processRawMessage.bind(this));
|
|
48
|
+
|
|
49
|
+
this.receiverSocket.once('listening', () => {
|
|
50
|
+
this.debug("Receiver socket bound", this.receiverSocket.address());
|
|
51
|
+
this.receiverSocketReady = true
|
|
52
|
+
});
|
|
53
|
+
this.receiverSocket.once('listening', this.socketReady.bind(this));
|
|
54
|
+
|
|
55
|
+
this.senderSocket.once('listening', () => {
|
|
56
|
+
this.debug("Sender socket bound", this.senderSocket.address());
|
|
57
|
+
this.senderSocketReady = true
|
|
58
|
+
});
|
|
59
|
+
this.senderSocket.once('listening', this.socketReady.bind(this));
|
|
60
|
+
|
|
61
|
+
this.senderSocket.unref();
|
|
62
|
+
|
|
63
|
+
this.senderSocket.bind();
|
|
64
|
+
|
|
65
|
+
this.debug("Binding receiver socket on address %s and port %d", ip, port);
|
|
66
|
+
this.receiverSocket.bind(port);
|
|
67
|
+
|
|
68
|
+
this.receiverSocket.on('error', () => {
|
|
69
|
+
throw new Error("Error binding receiver socket");
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
process.on('SIGINT', () => {
|
|
73
|
+
this.debug("\nClosing sockets");
|
|
74
|
+
this.stop();
|
|
75
|
+
process.exit();
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public stop() {
|
|
80
|
+
try {
|
|
81
|
+
this.receiverSocket.close();
|
|
82
|
+
} catch { }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private socketReady() {
|
|
86
|
+
if (!this.senderSocketReady) return;
|
|
87
|
+
if (!this.receiverSocketReady) return;
|
|
88
|
+
|
|
89
|
+
this.checkRegistration();
|
|
90
|
+
this.processQueue();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private checkRegistration() {
|
|
94
|
+
this.debug("Checking registration");
|
|
95
|
+
this.send("@H", (transaction: LightwaveTransaction | null, error: Error) => {
|
|
96
|
+
if (error) {
|
|
97
|
+
this.debug('Error: %o', error);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.debug(transaction);
|
|
101
|
+
this.emit('ready');
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public send(message: (string | Buffer), callback: (transaction: LightwaveTransaction | null, error: Error) => void) {
|
|
106
|
+
const transaction = Math.round(Math.random() * Math.pow(10, 8));
|
|
107
|
+
const messageWithTransaction = `${transaction},!${message}`;
|
|
108
|
+
const transactionDebug = this.debug.extend("transaction:" + transaction);
|
|
109
|
+
|
|
110
|
+
this.transactionListeners.set(transaction, {
|
|
111
|
+
message: message,
|
|
112
|
+
debug: transactionDebug,
|
|
113
|
+
delay: this.delay,
|
|
114
|
+
callback: callback
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
this.debug("Queueing message: %s", messageWithTransaction);
|
|
118
|
+
|
|
119
|
+
this.commandQueue.add(<LightwaveTransaction>{
|
|
120
|
+
id: transaction,
|
|
121
|
+
message: messageWithTransaction,
|
|
122
|
+
debug: transactionDebug,
|
|
123
|
+
callback
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
this.processQueue();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private async processQueue() {
|
|
130
|
+
if (this.commandQueue.busy) {
|
|
131
|
+
setTimeout(this.processQueue.bind(this), this.delay);
|
|
132
|
+
return
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const command = this.commandQueue.receive();
|
|
136
|
+
if (!command) return;
|
|
137
|
+
|
|
138
|
+
this.commandQueue.busy = true;
|
|
139
|
+
const transactionListener = this.transactionListeners.get(command.id);
|
|
140
|
+
const originalCallback = transactionListener.callback;
|
|
141
|
+
|
|
142
|
+
transactionListener.callback = (transaction: LightwaveTransaction, error: Error) => {
|
|
143
|
+
this.commandQueue.busy = false;
|
|
144
|
+
setTimeout(this.processQueue.bind(this), this.delay);
|
|
145
|
+
originalCallback(transaction, error);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
setTimeout(() => {
|
|
149
|
+
const listener = this.transactionListeners.get(command.id);
|
|
150
|
+
if (!listener) return;
|
|
151
|
+
|
|
152
|
+
originalCallback(null, new Error("Execution expired"));
|
|
153
|
+
this.transactionListeners.delete(command.id);
|
|
154
|
+
this.processQueue();
|
|
155
|
+
}, 5000)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
const transactionDebug = this.debug.extend(`transaction:${command?.id}`);
|
|
159
|
+
transactionDebug("Starting new transaction");
|
|
160
|
+
this.exec(command!.message, (message: LightwaveTransaction | null, error: Error) => { });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private exec(message: (Buffer | string | undefined), callback: (message: LightwaveTransaction | null, error: Error) => void) {
|
|
164
|
+
if (message === undefined) return;
|
|
165
|
+
|
|
166
|
+
this.debug("Sending message: %s to %s on port %d", message, this.ip, 9760);
|
|
167
|
+
this.senderSocket.setBroadcast(this.ip === "255.255.255.255");
|
|
168
|
+
this.senderSocket.send(message, 9760, this.ip, (error: Error | null, bytes: number) => {
|
|
169
|
+
if (error) {
|
|
170
|
+
this.debug("Message send errror: %o", error);
|
|
171
|
+
}
|
|
172
|
+
this.debug("Message sent: %s, length: %d", message, bytes);
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private processRawMessage(message: Buffer, remoteInfo: dgram.RemoteInfo) {
|
|
177
|
+
this.debug("Message has come through from %o", remoteInfo);
|
|
178
|
+
this.debug("Message received: %o", message.toString('ascii'));
|
|
179
|
+
|
|
180
|
+
for (const messageProcessor of this.messageProcessors) {
|
|
181
|
+
if (messageProcessor.canProcess(message)) {
|
|
182
|
+
this.debug("Message can be processed by %s", messageProcessor.constructor.name);
|
|
183
|
+
const lightwaveMessage = messageProcessor.process(message);
|
|
184
|
+
this.processLightwaveMessage(lightwaveMessage);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
throw "Message cannot be processed";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
processLightwaveMessage(lightwaveMessage: any) {
|
|
193
|
+
this.debug("Processing lightwave message: %o", lightwaveMessage);
|
|
194
|
+
this.debug("Current listeners: %o", this.transactionListeners);
|
|
195
|
+
|
|
196
|
+
this.debug("Link response fn", lightwaveMessage.fn)
|
|
197
|
+
if (lightwaveMessage.fn === "on") {
|
|
198
|
+
this.emit("deviceTurnedOn", lightwaveMessage.room, lightwaveMessage.dev);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (lightwaveMessage.fn === "off") {
|
|
202
|
+
this.emit("deviceTurnedOff", lightwaveMessage.room, lightwaveMessage.dev);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (lightwaveMessage.fn === "dim") {
|
|
206
|
+
this.emit("deviceDimmed", lightwaveMessage.room, lightwaveMessage.dev, Math.round(lightwaveMessage.param / 32 * 100));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const listener = this.transactionListeners.get(lightwaveMessage.id);
|
|
210
|
+
if (!listener) return;
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
if (lightwaveMessage.error?.match(/^ERR,6,/)) {
|
|
214
|
+
listener.delay = listener.delay * 2;
|
|
215
|
+
const msg = `${lightwaveMessage.id},!${listener.message}`
|
|
216
|
+
this.debug("message errorred, retrying: %o, %o with delay: %o", msg, listener, listener.delay);
|
|
217
|
+
setTimeout(() => {
|
|
218
|
+
this.exec(msg, (message: LightwaveTransaction | null, error: Error) => {
|
|
219
|
+
this.debug("message: %o, error: %o", message, error)
|
|
220
|
+
});
|
|
221
|
+
}, Math.round(listener.delay));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (listener) {
|
|
226
|
+
listener.debug("Found transaction listener");
|
|
227
|
+
listener.callback(lightwaveMessage, null);
|
|
228
|
+
listener.debug("Transaction completed, removing listener");
|
|
229
|
+
this.transactionListeners.delete(lightwaveMessage.id);
|
|
230
|
+
this.commandQueue.busy = false;
|
|
231
|
+
} else {
|
|
232
|
+
this.debug("Listener not found for message: %o", lightwaveMessage)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Debugger } from "debug";
|
|
2
|
+
import "./LightwaveTransaction";
|
|
3
|
+
import LightwaveMessageProcessor from "./LightwaveMessageProcessor";
|
|
4
|
+
|
|
5
|
+
export default class LightwaveTextMessageProcessor implements LightwaveMessageProcessor {
|
|
6
|
+
debug: Debugger;
|
|
7
|
+
constructor(debug: Debugger) {
|
|
8
|
+
this.debug = debug.extend('textMessageProcessor');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
process(message: Buffer): any {
|
|
12
|
+
this.debug('Processing message')
|
|
13
|
+
const textMessage = message.toString('utf-8');
|
|
14
|
+
var parts = textMessage.split(",");
|
|
15
|
+
var trans = parts.splice(0, 1);
|
|
16
|
+
var content = parts.join(",").replace(/(\r\n|\n|\r)/gm, "");
|
|
17
|
+
|
|
18
|
+
const response: any = {};
|
|
19
|
+
response.id = parseInt(trans[0]);
|
|
20
|
+
response.message = content;
|
|
21
|
+
response.error = content.match("^ERR") ? content : null;
|
|
22
|
+
return response;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
canProcess(message: Buffer): boolean {
|
|
26
|
+
this.debug("Checking if can process message");
|
|
27
|
+
return message.toString('utf-8').endsWith("\n");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
package/src/Queue.ts
ADDED