aes70 1.3.6 → 1.3.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/Changelog +17 -0
- package/dist/AES70.es5.js +1 -1
- package/package.json +1 -1
- package/src/OCP1/message_generator.js +1 -1
- package/src/controller/ControlClasses/OcaFilterFIR.d.ts +5 -0
- package/src/controller/ControlClasses/OcaFilterFIR.js +9 -1
- package/src/controller/ControlClasses/OcaPowerManager.d.ts +5 -0
- package/src/controller/ControlClasses/OcaPowerManager.js +9 -1
- package/src/controller/ControlClasses/OcaPowerSupply.d.ts +10 -0
- package/src/controller/ControlClasses/OcaPowerSupply.js +20 -2
- package/src/controller/ControlClasses/OcaSensor.d.ts +5 -0
- package/src/controller/ControlClasses/OcaSensor.js +9 -1
- package/src/controller/ControlClasses.d.ts +0 -1
- package/src/controller/abstract_udp_connection.js +211 -0
- package/src/controller/client_connection.d.ts +1 -1
- package/src/controller/client_connection.js +17 -5
- package/src/controller/make_control_class.js +24 -4
- package/src/controller/node_udp.js +141 -0
- package/src/controller/remote_device.js +2 -3
- package/src/controller/udp_connection.js +5 -266
- package/src/index.browser.js +2 -0
- package/src/index.js +2 -0
- package/tests/device/locking.js +2 -1
- package/tests/device/method_callback.js +24 -0
- package/tests/device/test.js +11 -5
- package/tests/device.js +3 -1
- package/bin/connectMany.js +0 -64
|
@@ -33,6 +33,16 @@ export declare class OcaPowerSupply extends OcaAgent {
|
|
|
33
33
|
*/
|
|
34
34
|
OnChargingChanged: PropertyEvent<boolean>;
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* This event is emitted whenever LoadFractionAvailable changes.
|
|
38
|
+
*/
|
|
39
|
+
OnLoadFractionAvailableChanged: PropertyEvent<number>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* This event is emitted whenever StorageFractionAvailable changes.
|
|
43
|
+
*/
|
|
44
|
+
OnStorageFractionAvailableChanged: PropertyEvent<number>;
|
|
45
|
+
|
|
36
46
|
constructor(objectNumber: number, device: RemoteDevice);
|
|
37
47
|
|
|
38
48
|
/**
|
|
@@ -33,8 +33,8 @@ export const OcaPowerSupply = make_control_class(
|
|
|
33
33
|
['ModelInfo', [OcaString], 3, 2, false, false, null],
|
|
34
34
|
['State', [OcaPowerSupplyState], 3, 3, false, false, null],
|
|
35
35
|
['Charging', [OcaBoolean], 3, 4, false, false, null],
|
|
36
|
-
['LoadFractionAvailable', [OcaFloat32], 3, 5,
|
|
37
|
-
['StorageFractionAvailable', [OcaFloat32], 3, 6,
|
|
36
|
+
['LoadFractionAvailable', [OcaFloat32], 3, 5, false, false, null],
|
|
37
|
+
['StorageFractionAvailable', [OcaFloat32], 3, 6, false, false, null],
|
|
38
38
|
['Location', [OcaPowerSupplyLocation], 3, 7, true, false, null],
|
|
39
39
|
],
|
|
40
40
|
[]
|
|
@@ -126,3 +126,21 @@ export const OcaPowerSupply = make_control_class(
|
|
|
126
126
|
*
|
|
127
127
|
* @member {PropertyEvent<boolean>} OcaPowerSupply#OnChargingChanged
|
|
128
128
|
*/
|
|
129
|
+
/**
|
|
130
|
+
* This event is emitted when the property LoadFractionAvailable changes in the remote object.
|
|
131
|
+
* The property ``LoadFractionAvailable`` is described in the AES70 standard as follows.
|
|
132
|
+
* Fraction of power supply's load capacity that is currently not being
|
|
133
|
+
* used. Readonly. Normal value range 0...1. A negative value indicates
|
|
134
|
+
* this data is not available.
|
|
135
|
+
*
|
|
136
|
+
* @member {PropertyEvent<number>} OcaPowerSupply#OnLoadFractionAvailableChanged
|
|
137
|
+
*/
|
|
138
|
+
/**
|
|
139
|
+
* This event is emitted when the property StorageFractionAvailable changes in the remote object.
|
|
140
|
+
* The property ``StorageFractionAvailable`` is described in the AES70 standard as follows.
|
|
141
|
+
* Fraction of power supply's energy storage that remains available. For
|
|
142
|
+
* battery supplies. Readonly. Normal value range 0...1. A negative value
|
|
143
|
+
* indicates this data is not available.
|
|
144
|
+
*
|
|
145
|
+
* @member {PropertyEvent<number>} OcaPowerSupply#OnStorageFractionAvailableChanged
|
|
146
|
+
*/
|
|
@@ -10,6 +10,11 @@ import { OcaSensorReadingState } from '../../types/OcaSensorReadingState';
|
|
|
10
10
|
* @class OcaSensor
|
|
11
11
|
*/
|
|
12
12
|
export declare class OcaSensor extends OcaWorker {
|
|
13
|
+
/**
|
|
14
|
+
* This event is emitted whenever ReadingState changes.
|
|
15
|
+
*/
|
|
16
|
+
OnReadingStateChanged: PropertyEvent<OcaSensorReadingState>;
|
|
17
|
+
|
|
13
18
|
constructor(objectNumber: number, device: RemoteDevice);
|
|
14
19
|
|
|
15
20
|
/**
|
|
@@ -14,7 +14,7 @@ export const OcaSensor = make_control_class(
|
|
|
14
14
|
2,
|
|
15
15
|
OcaWorker,
|
|
16
16
|
[['GetReadingState', 3, 1, [], [OcaSensorReadingState]]],
|
|
17
|
-
[['ReadingState', [OcaSensorReadingState], 3, 1, false,
|
|
17
|
+
[['ReadingState', [OcaSensorReadingState], 3, 1, false, false, null]],
|
|
18
18
|
[]
|
|
19
19
|
);
|
|
20
20
|
|
|
@@ -25,3 +25,11 @@ export const OcaSensor = make_control_class(
|
|
|
25
25
|
* @returns {Promise<OcaSensorReadingState>}
|
|
26
26
|
* A promise which resolves to a single value of type :class:`OcaSensorReadingState`.
|
|
27
27
|
*/
|
|
28
|
+
/**
|
|
29
|
+
* This event is emitted when the property ReadingState changes in the remote object.
|
|
30
|
+
* The property ``ReadingState`` is described in the AES70 standard as follows.
|
|
31
|
+
* Enum that describes whether current reading value is valid and if not,
|
|
32
|
+
* why not. Readonly.
|
|
33
|
+
*
|
|
34
|
+
* @member {PropertyEvent<OcaSensorReadingState>} OcaSensor#OnReadingStateChanged
|
|
35
|
+
*/
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
import { encodeMessage } from '../OCP1/encode_message.js';
|
|
4
|
+
import { decodeMessage } from '../OCP1/decode_message.js';
|
|
5
|
+
import { KeepAlive } from '../OCP1/keepalive.js';
|
|
6
|
+
import { ClientConnection } from './client_connection.js';
|
|
7
|
+
|
|
8
|
+
function delay(n) {
|
|
9
|
+
return new Promise((resolve) => setTimeout(resolve, n));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function waitForKeepalive(socket, options) {
|
|
13
|
+
const waiter = socket.receiveMessage().then((buffer) => {
|
|
14
|
+
const pdus = [];
|
|
15
|
+
let pos = 0;
|
|
16
|
+
|
|
17
|
+
pos = decodeMessage(new DataView(buffer), 0, pdus);
|
|
18
|
+
|
|
19
|
+
if (pdus.length !== 1) throw new Error('Expected keepalive response.');
|
|
20
|
+
|
|
21
|
+
return true;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const msg = encodeMessage(new KeepAlive(1000));
|
|
25
|
+
const t = 5 * (options.retry_interval || 250);
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < 3; i++) {
|
|
28
|
+
socket.send(msg);
|
|
29
|
+
|
|
30
|
+
if (await Promise.race([waiter, delay(t)])) return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
throw new Error('Failed to connect.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* :class:`ClientConnection` subclass which implements OCP.1 with UDP
|
|
38
|
+
* transport.
|
|
39
|
+
*/
|
|
40
|
+
export class AbstractUDPConnection extends ClientConnection {
|
|
41
|
+
constructor(socket, options) {
|
|
42
|
+
// allow us to batch 128 bytes max
|
|
43
|
+
// Set this to a higher value, e.g. close to MTU
|
|
44
|
+
// if you are sure that the device can handle it.
|
|
45
|
+
if (!(options.batch >= 0)) options.batch = 128;
|
|
46
|
+
super(options);
|
|
47
|
+
this.socket = socket;
|
|
48
|
+
this.delay = options.delay >= 0 ? options.delay : 5;
|
|
49
|
+
this.retry_interval =
|
|
50
|
+
options.retry_interval >= 0 ? options.retry_interval : 250;
|
|
51
|
+
this.retry_count = options.retry_count >= 0 ? options.retry_count : 3;
|
|
52
|
+
this._write_out_id = -1;
|
|
53
|
+
this._write_out_callback = () => {
|
|
54
|
+
this._write_out_id = -1;
|
|
55
|
+
this._write_out();
|
|
56
|
+
};
|
|
57
|
+
this._retry_id =
|
|
58
|
+
this.retry_interval > 0
|
|
59
|
+
? setInterval(() => this._retryCommands(), this.retry_interval)
|
|
60
|
+
: -1;
|
|
61
|
+
this.q = [];
|
|
62
|
+
socket.onmessage = (buffer) => {
|
|
63
|
+
try {
|
|
64
|
+
this.read(buffer);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.warn('Failed to parse incoming AES70 packet: %o', err);
|
|
67
|
+
}
|
|
68
|
+
if (this.inbuf !== null) this.close();
|
|
69
|
+
};
|
|
70
|
+
socket.onerror = (err) => this.error(err);
|
|
71
|
+
this.set_keepalive_interval(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get is_reliable() {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Connect to the given endpoint.
|
|
80
|
+
*
|
|
81
|
+
* @param {String} options.host - hostname or ip
|
|
82
|
+
* @param {number} options.port - port number
|
|
83
|
+
* @param {number} [options.delay=10] - Delay in ms between individual packets.
|
|
84
|
+
* This can be a useful strategy when communicating with devices which
|
|
85
|
+
* cannot handle high packet rates.
|
|
86
|
+
* @param {number} [options.retry_interval=250] - Delay in ms after which a
|
|
87
|
+
* command should be automatically re-sent if no response has been
|
|
88
|
+
* received, yet.
|
|
89
|
+
* @param {number} [options.retry_count=3] - Number of times to retry sending
|
|
90
|
+
* commands. If no response has been received after all retries, the
|
|
91
|
+
* command will fail with an error.
|
|
92
|
+
* @param {number} [options.batch=128] - Maximum number of bytes to send
|
|
93
|
+
* in an individual UDP packet. Note that AES70 messages which are larger
|
|
94
|
+
* than this limit are sent anyway. This only limits how many seperate
|
|
95
|
+
* messages are batched into a single packet.
|
|
96
|
+
* @returns {Promise<UDPConnection>}
|
|
97
|
+
* The connection.
|
|
98
|
+
*/
|
|
99
|
+
static async connect(udpApi, options) {
|
|
100
|
+
const socket = await udpApi.connect(options.host, options.port, options.type);
|
|
101
|
+
|
|
102
|
+
await waitForKeepalive(socket, options);
|
|
103
|
+
|
|
104
|
+
return new this(socket, options);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
write(buf) {
|
|
108
|
+
this.q.push(buf);
|
|
109
|
+
|
|
110
|
+
if (this.tx_idle_time() >= this.delay) this._write_out();
|
|
111
|
+
else this._schedule_write_out();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
flush() {
|
|
115
|
+
super.flush();
|
|
116
|
+
if (this.tx_idle_time() > this.delay) this._write_out();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
cleanup() {
|
|
120
|
+
super.cleanup();
|
|
121
|
+
if (this.socket) {
|
|
122
|
+
this.socket.close();
|
|
123
|
+
this.socket = null;
|
|
124
|
+
}
|
|
125
|
+
if (this._write_out_id !== -1) {
|
|
126
|
+
clearTimeout(this._write_out_id);
|
|
127
|
+
this._write_out_id = -1;
|
|
128
|
+
}
|
|
129
|
+
if (this._retry_id !== -1) {
|
|
130
|
+
clearInterval(this._retry_id);
|
|
131
|
+
this._retry_id = -1;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_estimate_next_tx_time() {
|
|
136
|
+
return this._now() + (this.delay + 2) * this.q.length;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
_write_out() {
|
|
140
|
+
if (!this.socket) return;
|
|
141
|
+
const q = this.q;
|
|
142
|
+
|
|
143
|
+
if (!q.length) return;
|
|
144
|
+
|
|
145
|
+
const buf = q.shift();
|
|
146
|
+
|
|
147
|
+
this.socket.send(buf);
|
|
148
|
+
super.write(buf);
|
|
149
|
+
|
|
150
|
+
if (q.length) this._schedule_write_out();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
_schedule_write_out() {
|
|
154
|
+
const tx_idle_time = this.tx_idle_time();
|
|
155
|
+
const delay = this.delay;
|
|
156
|
+
|
|
157
|
+
if (tx_idle_time >= delay) {
|
|
158
|
+
this._write_out();
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Already scheduled.
|
|
163
|
+
if (this._write_out_id !== -1) return;
|
|
164
|
+
|
|
165
|
+
this._write_out_id = setTimeout(
|
|
166
|
+
this._write_out_callback,
|
|
167
|
+
delay - tx_idle_time
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
_retryCommands() {
|
|
172
|
+
const now = this._now();
|
|
173
|
+
const retryTime = now - this.retry_interval;
|
|
174
|
+
// This is an estimate for how many commands we would manage to send
|
|
175
|
+
// off.
|
|
176
|
+
const max = 5 * (this.retry_interval / this.delay) - this.q.length;
|
|
177
|
+
const pendingCommands = this._pendingCommands;
|
|
178
|
+
|
|
179
|
+
const retries = [];
|
|
180
|
+
const failed = [];
|
|
181
|
+
|
|
182
|
+
for (const entry of pendingCommands) {
|
|
183
|
+
const [, pendingCommand] = entry;
|
|
184
|
+
|
|
185
|
+
// All later commands are newer than the cutoff.
|
|
186
|
+
if (pendingCommand.lastSent > retryTime) break;
|
|
187
|
+
if (pendingCommand.retries >= this.retry_count) {
|
|
188
|
+
failed.push(entry);
|
|
189
|
+
} else if (retries.length < max) {
|
|
190
|
+
retries.push(entry);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (failed.length) {
|
|
195
|
+
const timeoutError = new Error('Timeout.');
|
|
196
|
+
|
|
197
|
+
failed.forEach(([handle, pendingCommand]) => {
|
|
198
|
+
pendingCommands.delete(handle);
|
|
199
|
+
pendingCommand.reject(timeoutError);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
retries.forEach(([handle, pendingCommand]) => {
|
|
204
|
+
pendingCommands.delete(handle);
|
|
205
|
+
pendingCommands.set(handle, pendingCommand);
|
|
206
|
+
this.send(pendingCommand.command);
|
|
207
|
+
pendingCommand.lastSent = now;
|
|
208
|
+
pendingCommand.retries++;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { RemoteError } from './remote_error.js';
|
|
2
2
|
import { Connection } from '../connection.js';
|
|
3
3
|
import { Response } from '../OCP1/response.js';
|
|
4
|
-
import { encodeMessage } from '../OCP1/encode_message.js';
|
|
5
4
|
import { KeepAlive } from '../OCP1/keepalive.js';
|
|
6
5
|
import { Notification } from '../OCP1/notification.js';
|
|
7
6
|
import { Arguments } from './arguments.js';
|
|
@@ -119,8 +118,12 @@ export class ClientConnection extends Connection {
|
|
|
119
118
|
return handle;
|
|
120
119
|
}
|
|
121
120
|
|
|
122
|
-
|
|
123
|
-
return
|
|
121
|
+
_estimate_next_tx_time() {
|
|
122
|
+
return this._now();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
send_command(command, returnTypes, callback) {
|
|
126
|
+
const executor = (resolve, reject) => {
|
|
124
127
|
const handle = this._getNextCommandHandle();
|
|
125
128
|
|
|
126
129
|
command.handle = handle;
|
|
@@ -134,9 +137,18 @@ export class ClientConnection extends Connection {
|
|
|
134
137
|
|
|
135
138
|
this._pendingCommands.set(handle, pendingCommand);
|
|
136
139
|
|
|
137
|
-
pendingCommand.lastSent = this.
|
|
140
|
+
pendingCommand.lastSent = this._estimate_next_tx_time();
|
|
138
141
|
this.send(command);
|
|
139
|
-
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
if (callback) {
|
|
145
|
+
executor(
|
|
146
|
+
(result) => callback(true, result),
|
|
147
|
+
(error) => callback(false, error)
|
|
148
|
+
);
|
|
149
|
+
} else {
|
|
150
|
+
return new Promise(executor);
|
|
151
|
+
}
|
|
140
152
|
}
|
|
141
153
|
|
|
142
154
|
_removePendingCommand(handle) {
|
|
@@ -58,15 +58,35 @@ function implement_method(cls, method) {
|
|
|
58
58
|
|
|
59
59
|
const [name, level, index, argumentTypes, returnTypes] = method;
|
|
60
60
|
|
|
61
|
-
cls.prototype[name] = function () {
|
|
61
|
+
cls.prototype[name] = function (...args) {
|
|
62
|
+
const argumentCount = argumentTypes.length;
|
|
63
|
+
let callback = null;
|
|
64
|
+
|
|
65
|
+
// If there are too few arguments, this might mean
|
|
66
|
+
//
|
|
67
|
+
// - that some of them use the default encoding (e.g. 0)
|
|
68
|
+
// - that the method signature has change in the AES70 version
|
|
69
|
+
// used
|
|
70
|
+
//
|
|
71
|
+
// this is why we do not error here, yet.
|
|
72
|
+
if (argumentCount < args.length) {
|
|
73
|
+
if (
|
|
74
|
+
argumentCount + 1 === args.length &&
|
|
75
|
+
typeof args[argumentCount] === 'function'
|
|
76
|
+
) {
|
|
77
|
+
callback = args[argumentCount];
|
|
78
|
+
args.length = argumentCount;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
62
82
|
const cmd = new CommandRrq(
|
|
63
83
|
this.ono,
|
|
64
84
|
level,
|
|
65
85
|
index,
|
|
66
|
-
|
|
67
|
-
new EncodedArguments(argumentTypes,
|
|
86
|
+
argumentCount,
|
|
87
|
+
new EncodedArguments(argumentTypes, args)
|
|
68
88
|
);
|
|
69
|
-
return this.device.send_command(cmd, returnTypes);
|
|
89
|
+
return this.device.send_command(cmd, returnTypes, callback);
|
|
70
90
|
};
|
|
71
91
|
}
|
|
72
92
|
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
import { createSocket } from 'dgram';
|
|
4
|
+
import { isIPv4, isIPv6 } from 'net';
|
|
5
|
+
import { lookup } from 'dns';
|
|
6
|
+
|
|
7
|
+
function lookup_address(host) {
|
|
8
|
+
if (isIPv4(host))
|
|
9
|
+
return Promise.resolve(host);
|
|
10
|
+
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
lookup(host, { family: 4 }, (err, address) => {
|
|
13
|
+
if (err) reject(err);
|
|
14
|
+
else resolve(address);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class NodeUDP {
|
|
20
|
+
get onmessage() {
|
|
21
|
+
return this._onmessage;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
set onmessage(cb) {
|
|
25
|
+
if (this._onmessage && cb)
|
|
26
|
+
throw new Error('Cannot install more than one message callback.');
|
|
27
|
+
|
|
28
|
+
this._onmessage = cb;
|
|
29
|
+
this._notifyMessage();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get onerror() {
|
|
33
|
+
return this._onerror;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set onerror(cb) {
|
|
37
|
+
if (this._onerror && cb)
|
|
38
|
+
throw new Error('Cannot install more than one error callback.');
|
|
39
|
+
|
|
40
|
+
this._onerror = cb;
|
|
41
|
+
this._notifyError();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
_notifyMessage() {
|
|
45
|
+
const onmessage = this.onmessage;
|
|
46
|
+
|
|
47
|
+
if (!onmessage) return;
|
|
48
|
+
|
|
49
|
+
const inbuf = this._inbuf;
|
|
50
|
+
|
|
51
|
+
if (!inbuf.length) return;
|
|
52
|
+
|
|
53
|
+
this._inbuf = [];
|
|
54
|
+
|
|
55
|
+
for (let i = 0; i < inbuf.length; i++) {
|
|
56
|
+
onmessage(inbuf[i].buffer);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_notifyError() {
|
|
61
|
+
const onerror = this.onerror;
|
|
62
|
+
|
|
63
|
+
if (!onerror) return;
|
|
64
|
+
|
|
65
|
+
const error = this._error;
|
|
66
|
+
|
|
67
|
+
if (!error) return;
|
|
68
|
+
this._error = null;
|
|
69
|
+
|
|
70
|
+
onerror(error);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
send(buf) {
|
|
74
|
+
this.socket.send(Buffer.from(buf));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
receiveMessage(timeout) {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
if (this._error) {
|
|
80
|
+
reject(this._error);
|
|
81
|
+
} else if (this._inbuf.length) {
|
|
82
|
+
resolve(this._inbuf.shift());
|
|
83
|
+
} else {
|
|
84
|
+
this.onmessage = (msg) => {
|
|
85
|
+
this.onmessage = null;
|
|
86
|
+
this.onerror = null;
|
|
87
|
+
resolve(msg);
|
|
88
|
+
};
|
|
89
|
+
this.onerror = (err) => {
|
|
90
|
+
this.onmessage = null;
|
|
91
|
+
this.onerror = null;
|
|
92
|
+
reject(err);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
close() {
|
|
99
|
+
this.socket.close();
|
|
100
|
+
this.socket = null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
constructor(socket) {
|
|
104
|
+
this._inbuf = [];
|
|
105
|
+
this._onmessage = null;
|
|
106
|
+
this._onerror = null;
|
|
107
|
+
this.socket = socket;
|
|
108
|
+
socket.on('message', (msg, rinfo) => {
|
|
109
|
+
this._inbuf.push(msg);
|
|
110
|
+
this._notifyMessage();
|
|
111
|
+
});
|
|
112
|
+
socket.on('error', (err) => {
|
|
113
|
+
this._error = err;
|
|
114
|
+
this._notifyError(err);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static connect(host, port, type) {
|
|
119
|
+
return lookup_address(host).then((ip) => {
|
|
120
|
+
return new Promise((resolve, reject) => {
|
|
121
|
+
const socket = createSocket(type || 'udp4');
|
|
122
|
+
const onerror = function (ev) {
|
|
123
|
+
reject(ev);
|
|
124
|
+
};
|
|
125
|
+
socket.on('error', onerror);
|
|
126
|
+
socket.bind(
|
|
127
|
+
{
|
|
128
|
+
exclusive: true,
|
|
129
|
+
},
|
|
130
|
+
() => {
|
|
131
|
+
socket.on('connect', () => {
|
|
132
|
+
resolve(new this(socket));
|
|
133
|
+
socket.removeListener('error', onerror);
|
|
134
|
+
});
|
|
135
|
+
socket.connect(port, host);
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -21,7 +21,6 @@ import * as RemoteControlClasses from './ControlClasses.js';
|
|
|
21
21
|
|
|
22
22
|
import { OcaManagerDefaultObjectNumbers } from '../types/OcaManagerDefaultObjectNumbers.js';
|
|
23
23
|
import { OcaNotificationDeliveryMode } from '../types/OcaNotificationDeliveryMode.js';
|
|
24
|
-
import { RemoteError } from './remote_error.js';
|
|
25
24
|
|
|
26
25
|
function eventToKey(event) {
|
|
27
26
|
const ono = event.EmitterONo;
|
|
@@ -248,8 +247,8 @@ export class RemoteDevice extends Events {
|
|
|
248
247
|
this.connection.close();
|
|
249
248
|
}
|
|
250
249
|
|
|
251
|
-
send_command(cmd, returnType) {
|
|
252
|
-
return this.connection.send_command(cmd, returnType);
|
|
250
|
+
send_command(cmd, returnType, callback) {
|
|
251
|
+
return this.connection.send_command(cmd, returnType, callback);
|
|
253
252
|
}
|
|
254
253
|
|
|
255
254
|
_doSubscribe(event) {
|