aes70 2.0.14 → 2.0.16
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/AES70.es5.js +398 -145
- package/package.json +1 -1
- package/src/OCP1/message_generator.js +9 -1
- package/src/connection.d.ts +17 -0
- package/src/connection.js +36 -16
- package/src/controller/abstract_udp_connection.js +83 -86
- package/src/controller/client_connection.js +63 -19
- package/src/controller/fetch_device_content.js +4 -0
- package/src/controller/node_udp.js +71 -36
- package/src/controller/property.js +13 -21
- package/src/events.js +10 -5
- package/src/utils/subscribeEvent.js +32 -0
- package/src/utils/subscriptions.js +27 -0
- package/src/utils/timer.js +123 -0
package/dist/AES70.es5.js
CHANGED
|
@@ -31,12 +31,13 @@
|
|
|
31
31
|
class Events {
|
|
32
32
|
constructor() {
|
|
33
33
|
this.event_handlers = new Map();
|
|
34
|
+
this.event_handlers_cleared = false;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Emit an event.
|
|
38
39
|
*
|
|
39
|
-
* @param {
|
|
40
|
+
* @param {string} name - Name of the event.
|
|
40
41
|
* @param {...*} args - Extra arguments.
|
|
41
42
|
*/
|
|
42
43
|
emit(name) {
|
|
@@ -57,7 +58,7 @@
|
|
|
57
58
|
/**
|
|
58
59
|
* Subscribe to an event.
|
|
59
60
|
*
|
|
60
|
-
* @param {
|
|
61
|
+
* @param {string} name - Name of the event.
|
|
61
62
|
* @param {Function} cb - Callback function.
|
|
62
63
|
*/
|
|
63
64
|
on(name, cb) {
|
|
@@ -81,14 +82,17 @@
|
|
|
81
82
|
/**
|
|
82
83
|
* Removes an event handler.
|
|
83
84
|
*
|
|
84
|
-
* @param {
|
|
85
|
+
* @param {string} name - Name of the event.
|
|
85
86
|
* @param {Function} cb - Callback function.
|
|
86
87
|
*/
|
|
87
88
|
removeEventListener(name, cb) {
|
|
88
89
|
const handlers = this.event_handlers.get(name);
|
|
89
90
|
|
|
90
91
|
if (!handlers || !handlers.has(cb)) {
|
|
91
|
-
|
|
92
|
+
if (!this.event_handlers_cleared) {
|
|
93
|
+
console.warn('removeEventListeners(): not installed:', name, cb);
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
handlers.delete(cb);
|
|
@@ -97,7 +101,7 @@
|
|
|
97
101
|
/**
|
|
98
102
|
* Removes an event handler.
|
|
99
103
|
*
|
|
100
|
-
* @param {
|
|
104
|
+
* @param {string} name
|
|
101
105
|
* @param {Function} cb
|
|
102
106
|
*/
|
|
103
107
|
off(name, cb) {
|
|
@@ -109,6 +113,7 @@
|
|
|
109
113
|
*/
|
|
110
114
|
removeAllEventListeners() {
|
|
111
115
|
this.event_handlers.clear();
|
|
116
|
+
this.event_handlers_cleared = true;
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
/**
|
|
@@ -934,6 +939,14 @@
|
|
|
934
939
|
};
|
|
935
940
|
}
|
|
936
941
|
|
|
942
|
+
get bufferedAmount() {
|
|
943
|
+
return this._currentSize;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
get batchSize() {
|
|
947
|
+
return this._batchSize;
|
|
948
|
+
}
|
|
949
|
+
|
|
937
950
|
add(pdu) {
|
|
938
951
|
const currentSize = this._currentSize;
|
|
939
952
|
const encodedLength = pdu.encoded_length();
|
|
@@ -966,7 +979,7 @@
|
|
|
966
979
|
/* Keepalive packets are never combined into one message. */
|
|
967
980
|
this._lastMessageType = messageType;
|
|
968
981
|
|
|
969
|
-
if (this._currentSize > this._batchSize) {
|
|
982
|
+
if (this._currentSize + additionalSize > this._batchSize) {
|
|
970
983
|
this.flush();
|
|
971
984
|
} else if (this._pdus.length === 1) {
|
|
972
985
|
this.scheduleFlush();
|
|
@@ -1031,6 +1044,130 @@
|
|
|
1031
1044
|
}
|
|
1032
1045
|
}
|
|
1033
1046
|
|
|
1047
|
+
function isItTime(target, now) {
|
|
1048
|
+
// We are ok with 1ms accuracy.
|
|
1049
|
+
return target - now < 1;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
class Timer {
|
|
1053
|
+
constructor(callback, getNow) {
|
|
1054
|
+
this._callback = callback;
|
|
1055
|
+
this._getNow = getNow;
|
|
1056
|
+
this._targetTime = undefined;
|
|
1057
|
+
this._timerId = undefined;
|
|
1058
|
+
this._timerAt = undefined;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
poll() {
|
|
1062
|
+
const now = this._getNow();
|
|
1063
|
+
|
|
1064
|
+
if (this._targetTime === undefined) return;
|
|
1065
|
+
|
|
1066
|
+
if (isItTime(this._targetTime, now)) {
|
|
1067
|
+
this._targetTime = undefined;
|
|
1068
|
+
try {
|
|
1069
|
+
this._callback();
|
|
1070
|
+
} catch (err) {
|
|
1071
|
+
console.error('Timer callback threw an exception', err);
|
|
1072
|
+
}
|
|
1073
|
+
} else {
|
|
1074
|
+
this._reschedule();
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
_reschedule() {
|
|
1079
|
+
const target = this._targetTime;
|
|
1080
|
+
const interval = target - this._getNow();
|
|
1081
|
+
|
|
1082
|
+
if (this._timerId !== undefined) {
|
|
1083
|
+
if (target >= this._timerAt) {
|
|
1084
|
+
// The timer will fire before target. We will then reschedule it.
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
clearTimeout(this._timerId);
|
|
1089
|
+
this._timerId = undefined;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
this._timerAt = target;
|
|
1093
|
+
this._timerId = setTimeout(() => {
|
|
1094
|
+
this._timerId = undefined;
|
|
1095
|
+
this._timerAt = undefined;
|
|
1096
|
+
this.poll();
|
|
1097
|
+
}, Math.max(0, interval));
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
*
|
|
1102
|
+
* @param {number} interval
|
|
1103
|
+
* Interval in milliseconds.
|
|
1104
|
+
*/
|
|
1105
|
+
scheduleIn(interval) {
|
|
1106
|
+
if (!(interval >= 0)) {
|
|
1107
|
+
throw new TypeError(`Expected positive interval.`);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
this._targetTime = this._getNow() + interval;
|
|
1111
|
+
this._reschedule();
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Schedule the timer in a given number of milliseconds. If the timer
|
|
1116
|
+
* is already running and scheduled to run before, do not modify it.
|
|
1117
|
+
*
|
|
1118
|
+
* @param {number} interval
|
|
1119
|
+
*/
|
|
1120
|
+
scheduleDeadlineIn(interval) {
|
|
1121
|
+
if (!(interval >= 0)) {
|
|
1122
|
+
throw new TypeError(`Expected positive interval.`);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
const target = this._getNow() + interval;
|
|
1126
|
+
|
|
1127
|
+
if (this._targetTime !== undefined && this._targetTime <= target) {
|
|
1128
|
+
this.poll();
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
this.scheduleAt(target);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
*
|
|
1137
|
+
* @param {number} target
|
|
1138
|
+
* Target time in milliseconds.
|
|
1139
|
+
*/
|
|
1140
|
+
scheduleAt(target) {
|
|
1141
|
+
if (!(target >= 0)) {
|
|
1142
|
+
throw new TypeError();
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
this._targetTime = target;
|
|
1146
|
+
this._reschedule();
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
stop() {
|
|
1150
|
+
this._targetTime = undefined;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
cancel() {
|
|
1154
|
+
this.stop();
|
|
1155
|
+
this._clearTimeout();
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
_clearTimeout() {
|
|
1159
|
+
if (this._timerId) {
|
|
1160
|
+
clearTimeout(this._timerId);
|
|
1161
|
+
this._timerId = undefined;
|
|
1162
|
+
this._timerAt = undefined;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
dispose() {
|
|
1167
|
+
this.cancel();
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1034
1171
|
/**
|
|
1035
1172
|
* Connection base class. It extends :class:`Events` and defines two events:
|
|
1036
1173
|
*
|
|
@@ -1067,8 +1204,11 @@
|
|
|
1067
1204
|
this.last_tx_time = now;
|
|
1068
1205
|
this.rx_bytes = 0;
|
|
1069
1206
|
this.tx_bytes = 0;
|
|
1207
|
+
this._keepalive_timer = new Timer(
|
|
1208
|
+
() => this._check_keepalive(),
|
|
1209
|
+
() => this._now()
|
|
1210
|
+
);
|
|
1070
1211
|
this.keepalive_interval = -1;
|
|
1071
|
-
this._keepalive_interval_id = null;
|
|
1072
1212
|
this._closed = false;
|
|
1073
1213
|
this.on('close', () => {
|
|
1074
1214
|
if (this._closed) return;
|
|
@@ -1087,6 +1227,18 @@
|
|
|
1087
1227
|
return true;
|
|
1088
1228
|
}
|
|
1089
1229
|
|
|
1230
|
+
get bufferedAmount() {
|
|
1231
|
+
return this._message_generator.bufferedAmount;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
get batchSize() {
|
|
1235
|
+
return this._message_generator.batchSize;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
get pendingWrites() {
|
|
1239
|
+
return this._message_generator.bufferedAmount > 0 ? 1 : 0;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1090
1242
|
send(pdu) {
|
|
1091
1243
|
if (this.is_closed()) throw new Error('Connection is closed.');
|
|
1092
1244
|
this.emit('send', pdu);
|
|
@@ -1144,7 +1296,7 @@
|
|
|
1144
1296
|
}
|
|
1145
1297
|
}
|
|
1146
1298
|
|
|
1147
|
-
this.
|
|
1299
|
+
this.poll();
|
|
1148
1300
|
}
|
|
1149
1301
|
|
|
1150
1302
|
incoming(a) {}
|
|
@@ -1175,16 +1327,18 @@
|
|
|
1175
1327
|
if (this.is_closed()) throw new Error('cleanup() called twice.');
|
|
1176
1328
|
|
|
1177
1329
|
// disable keepalive
|
|
1178
|
-
this.
|
|
1330
|
+
this._keepalive_timer.dispose();
|
|
1179
1331
|
this._message_generator.dispose();
|
|
1180
1332
|
this._message_generator = null;
|
|
1181
1333
|
this.removeAllEventListeners();
|
|
1182
1334
|
}
|
|
1183
1335
|
|
|
1184
1336
|
_check_keepalive() {
|
|
1185
|
-
if (
|
|
1186
|
-
|
|
1337
|
+
if (this.is_closed()) return;
|
|
1187
1338
|
const t = this.keepalive_interval;
|
|
1339
|
+
if (!(t > 0)) return;
|
|
1340
|
+
|
|
1341
|
+
this._keepalive_timer.scheduleIn(t / 2 + 10);
|
|
1188
1342
|
|
|
1189
1343
|
if (this.rx_idle_time() > t * 3) {
|
|
1190
1344
|
this.emit('timeout');
|
|
@@ -1196,6 +1350,13 @@
|
|
|
1196
1350
|
}
|
|
1197
1351
|
}
|
|
1198
1352
|
|
|
1353
|
+
/**
|
|
1354
|
+
* Check if some regular internal timers must run.
|
|
1355
|
+
*/
|
|
1356
|
+
poll() {
|
|
1357
|
+
this._keepalive_timer.poll();
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1199
1360
|
/**
|
|
1200
1361
|
* Flush write buffers. This are usually PDUs or may also be unwritten
|
|
1201
1362
|
* buffers.
|
|
@@ -1221,11 +1382,6 @@
|
|
|
1221
1382
|
|
|
1222
1383
|
const t = seconds * 1000;
|
|
1223
1384
|
|
|
1224
|
-
if (this._keepalive_interval_id !== null) {
|
|
1225
|
-
clearInterval(this._keepalive_interval_id);
|
|
1226
|
-
this._keepalive_interval_id = null;
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
1385
|
this.keepalive_interval = t;
|
|
1230
1386
|
|
|
1231
1387
|
// Notify the other side about our new keepalive
|
|
@@ -1233,12 +1389,12 @@
|
|
|
1233
1389
|
|
|
1234
1390
|
this.send(new KeepAlive(t));
|
|
1235
1391
|
|
|
1236
|
-
if (
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
this.
|
|
1241
|
-
}
|
|
1392
|
+
if (t > 0) {
|
|
1393
|
+
// we check twice as often to make sure we stay within the timers
|
|
1394
|
+
this._keepalive_timer.scheduleIn(t / 2 + 10);
|
|
1395
|
+
} else {
|
|
1396
|
+
this._keepalive_timer.stop();
|
|
1397
|
+
}
|
|
1242
1398
|
}
|
|
1243
1399
|
}
|
|
1244
1400
|
|
|
@@ -1585,6 +1741,67 @@
|
|
|
1585
1741
|
}
|
|
1586
1742
|
}
|
|
1587
1743
|
|
|
1744
|
+
class Subscriptions {
|
|
1745
|
+
constructor() {
|
|
1746
|
+
this._callbacks = [];
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* Add a subscription.
|
|
1751
|
+
*
|
|
1752
|
+
* @param {Function[]} cbs
|
|
1753
|
+
*/
|
|
1754
|
+
add(...cbs) {
|
|
1755
|
+
cbs.forEach((cb) => {
|
|
1756
|
+
this._callbacks.push(cb);
|
|
1757
|
+
});
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
unsubscribe() {
|
|
1761
|
+
this._callbacks.forEach((cb) => {
|
|
1762
|
+
try {
|
|
1763
|
+
cb();
|
|
1764
|
+
} catch (err) {
|
|
1765
|
+
console.error(err);
|
|
1766
|
+
}
|
|
1767
|
+
});
|
|
1768
|
+
this._callbacks.length = 0;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
function addEvent(target, name, callback) {
|
|
1773
|
+
if (target.addEventListener) {
|
|
1774
|
+
target.addEventListener(name, callback);
|
|
1775
|
+
} else if (target.on) {
|
|
1776
|
+
target.on(name, callback);
|
|
1777
|
+
} else {
|
|
1778
|
+
throw new TypeError('Unsupported event target ', target);
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
function removeEvent(target, name, callback) {
|
|
1783
|
+
if (target.removeEventListener) {
|
|
1784
|
+
target.removeEventListener(name, callback);
|
|
1785
|
+
} else if (target.off) {
|
|
1786
|
+
target.off(name, callback);
|
|
1787
|
+
} else {
|
|
1788
|
+
throw new TypeError('Unsupported event target ', target);
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
/**
|
|
1793
|
+
*
|
|
1794
|
+
* @param {EventTarget|Events} target
|
|
1795
|
+
* @param {string} name
|
|
1796
|
+
* @param {callback} callback
|
|
1797
|
+
*/
|
|
1798
|
+
function subscribeEvent(target, name, callback) {
|
|
1799
|
+
addEvent(target, name, callback);
|
|
1800
|
+
return () => {
|
|
1801
|
+
removeEvent(target, name, callback);
|
|
1802
|
+
};
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1588
1805
|
class PendingCommand {
|
|
1589
1806
|
get handle() {
|
|
1590
1807
|
return this.command.handle;
|
|
@@ -1663,17 +1880,57 @@
|
|
|
1663
1880
|
class ClientConnection extends Connection {
|
|
1664
1881
|
constructor(options) {
|
|
1665
1882
|
super(options);
|
|
1883
|
+
// All pending commands by id/handle
|
|
1666
1884
|
this._pendingCommands = new Map();
|
|
1885
|
+
// All pending commands scheduled to be sent.
|
|
1886
|
+
this._scheduledPendingCommands = new Set();
|
|
1887
|
+
// All pending commands wich have been sent.
|
|
1888
|
+
this._sentPendingCommands = new Set();
|
|
1667
1889
|
this._nextCommandHandle = 0;
|
|
1668
1890
|
this._subscribers = new Map();
|
|
1891
|
+
this._sendCommandsTimer = new Timer(
|
|
1892
|
+
() => {
|
|
1893
|
+
this.sendCommands();
|
|
1894
|
+
},
|
|
1895
|
+
() => this._now()
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
shouldSendMoreCommands() {
|
|
1900
|
+
return this.is_reliable;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
sendCommands() {
|
|
1904
|
+
const { _scheduledPendingCommands, _sentPendingCommands } = this;
|
|
1905
|
+
|
|
1906
|
+
for (const pendingCommand of _scheduledPendingCommands) {
|
|
1907
|
+
if (!this.shouldSendMoreCommands()) break;
|
|
1908
|
+
_scheduledPendingCommands.delete(pendingCommand);
|
|
1909
|
+
_sentPendingCommands.add(pendingCommand);
|
|
1910
|
+
this.send(pendingCommand.command);
|
|
1911
|
+
pendingCommand.lastSent = this._now();
|
|
1912
|
+
pendingCommand.retries++;
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
scheduleSendCommands() {
|
|
1917
|
+
this._sendCommandsTimer.scheduleDeadlineIn(5);
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
poll() {
|
|
1921
|
+
super.poll();
|
|
1922
|
+
this._sendCommandsTimer.poll();
|
|
1669
1923
|
}
|
|
1670
1924
|
|
|
1671
1925
|
cleanup(error) {
|
|
1672
1926
|
super.cleanup(error);
|
|
1927
|
+
this._sendCommandsTimer.dispose();
|
|
1673
1928
|
const subscribers = this._subscribers;
|
|
1674
1929
|
this._subscribers = null;
|
|
1675
1930
|
const pendingCommands = this._pendingCommands;
|
|
1676
1931
|
this._pendingCommands = null;
|
|
1932
|
+
this._scheduledPendingCommands.clear();
|
|
1933
|
+
this._sentPendingCommands.clear();
|
|
1677
1934
|
|
|
1678
1935
|
const e = new CloseError(error);
|
|
1679
1936
|
pendingCommands.forEach((pendingCommand, id) => {
|
|
@@ -1752,9 +2009,8 @@
|
|
|
1752
2009
|
);
|
|
1753
2010
|
|
|
1754
2011
|
this._pendingCommands.set(handle, pendingCommand);
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
this.send(command);
|
|
2012
|
+
this._scheduledPendingCommands.add(pendingCommand);
|
|
2013
|
+
this.scheduleSendCommands();
|
|
1758
2014
|
};
|
|
1759
2015
|
|
|
1760
2016
|
if (callback) {
|
|
@@ -1775,6 +2031,9 @@
|
|
|
1775
2031
|
|
|
1776
2032
|
pendingCommands.delete(handle);
|
|
1777
2033
|
|
|
2034
|
+
if (!this._sentPendingCommands.delete(pendingCommand))
|
|
2035
|
+
this._scheduledPendingCommands.delete(pendingCommand);
|
|
2036
|
+
|
|
1778
2037
|
return pendingCommand;
|
|
1779
2038
|
}
|
|
1780
2039
|
|
|
@@ -1829,35 +2088,34 @@
|
|
|
1829
2088
|
* the connection will be closed and the returned promise will reject.
|
|
1830
2089
|
* @param {number} interval
|
|
1831
2090
|
* Keepalive interval in seconds.
|
|
2091
|
+
* @param {AbortSignal} [signal]
|
|
2092
|
+
* Optional abort signal which can be used to abort
|
|
2093
|
+
* the process.
|
|
1832
2094
|
*/
|
|
1833
|
-
wait_for_keepalive(interval) {
|
|
1834
|
-
|
|
1835
|
-
const subscriptions = [];
|
|
2095
|
+
wait_for_keepalive(interval, signal) {
|
|
2096
|
+
const subscriptions = new Subscriptions();
|
|
1836
2097
|
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
}
|
|
1845
|
-
subscriptions.
|
|
2098
|
+
return new Promise((resolve, reject) => {
|
|
2099
|
+
if (signal) {
|
|
2100
|
+
subscriptions.add(
|
|
2101
|
+
subscribeEvent(signal, 'abort', () => {
|
|
2102
|
+
reject(signal.reason);
|
|
2103
|
+
})
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
subscriptions.add(
|
|
1846
2107
|
this.subscribe('error', (error) => {
|
|
1847
2108
|
reject(error);
|
|
1848
|
-
cleanup();
|
|
1849
2109
|
}),
|
|
1850
2110
|
this.subscribe('close', () => {
|
|
1851
2111
|
reject(new CloseError());
|
|
1852
|
-
cleanup();
|
|
1853
2112
|
}),
|
|
1854
2113
|
this.subscribe('keepalive', () => {
|
|
1855
2114
|
resolve();
|
|
1856
|
-
cleanup();
|
|
1857
2115
|
})
|
|
1858
2116
|
);
|
|
1859
2117
|
this.set_keepalive_interval(interval);
|
|
1860
|
-
});
|
|
2118
|
+
}).finally(() => subscriptions.unsubscribe());
|
|
1861
2119
|
}
|
|
1862
2120
|
}
|
|
1863
2121
|
|
|
@@ -3486,8 +3744,7 @@
|
|
|
3486
3744
|
* @returns {Function} The getter. If none could be found, null is returned.
|
|
3487
3745
|
*/
|
|
3488
3746
|
getter(o, no_bind) {
|
|
3489
|
-
|
|
3490
|
-
let i = 0;
|
|
3747
|
+
const name = this.name;
|
|
3491
3748
|
const aliases = this.aliases;
|
|
3492
3749
|
const accessors = this.accessors;
|
|
3493
3750
|
|
|
@@ -3529,10 +3786,13 @@
|
|
|
3529
3786
|
return no_bind ? fun : fun.bind(o);
|
|
3530
3787
|
}
|
|
3531
3788
|
|
|
3532
|
-
|
|
3789
|
+
// iterate all possible names
|
|
3790
|
+
const possibleNames = aliases ? [name, ...aliases] : [name];
|
|
3791
|
+
|
|
3792
|
+
for (const possibleName of possibleNames) {
|
|
3533
3793
|
if (this.static) {
|
|
3534
3794
|
const c = o.constructor;
|
|
3535
|
-
const v = c[
|
|
3795
|
+
const v = c[possibleName];
|
|
3536
3796
|
|
|
3537
3797
|
if (v !== void 0) {
|
|
3538
3798
|
return function () {
|
|
@@ -3540,16 +3800,11 @@
|
|
|
3540
3800
|
};
|
|
3541
3801
|
}
|
|
3542
3802
|
} else {
|
|
3543
|
-
const fun = o['Get' +
|
|
3803
|
+
const fun = o['Get' + possibleName];
|
|
3544
3804
|
|
|
3545
3805
|
if (fun) return no_bind ? fun : fun.bind(o);
|
|
3546
3806
|
}
|
|
3547
|
-
|
|
3548
|
-
if (aliases && i < aliases.length) {
|
|
3549
|
-
name = aliases[i++];
|
|
3550
|
-
continue;
|
|
3551
|
-
}
|
|
3552
|
-
} while (false);
|
|
3807
|
+
}
|
|
3553
3808
|
|
|
3554
3809
|
return null;
|
|
3555
3810
|
}
|
|
@@ -3565,20 +3820,15 @@
|
|
|
3565
3820
|
setter(o, no_bind) {
|
|
3566
3821
|
if (this.readonly || this.static) return null;
|
|
3567
3822
|
|
|
3568
|
-
|
|
3569
|
-
i = 0;
|
|
3823
|
+
const name = this.name;
|
|
3570
3824
|
const aliases = this.aliases;
|
|
3825
|
+
const possibleNames = aliases ? [name, ...aliases] : [name];
|
|
3571
3826
|
|
|
3572
|
-
|
|
3573
|
-
const fun = o['Set' +
|
|
3827
|
+
for (const possibleName of possibleNames) {
|
|
3828
|
+
const fun = o['Set' + possibleName];
|
|
3574
3829
|
|
|
3575
3830
|
if (fun) return no_bind ? fun : fun.bind(o);
|
|
3576
|
-
|
|
3577
|
-
if (aliases && i < aliases.length) {
|
|
3578
|
-
name = aliases[i++];
|
|
3579
|
-
continue;
|
|
3580
|
-
}
|
|
3581
|
-
} while (false);
|
|
3831
|
+
}
|
|
3582
3832
|
|
|
3583
3833
|
return null;
|
|
3584
3834
|
}
|
|
@@ -28733,35 +28983,6 @@
|
|
|
28733
28983
|
|
|
28734
28984
|
/* eslint-env node */
|
|
28735
28985
|
|
|
28736
|
-
|
|
28737
|
-
function delay(n) {
|
|
28738
|
-
return new Promise((resolve) => setTimeout(resolve, n));
|
|
28739
|
-
}
|
|
28740
|
-
|
|
28741
|
-
async function waitForKeepalive(socket, options) {
|
|
28742
|
-
const waiter = socket.receiveMessage().then((buffer) => {
|
|
28743
|
-
const pdus = [];
|
|
28744
|
-
const pos = decodeMessage(new DataView(buffer), 0, pdus);
|
|
28745
|
-
|
|
28746
|
-
if (pdus.length !== 1) throw new Error('Expected keepalive response.');
|
|
28747
|
-
if (pos !== buffer.byteLength)
|
|
28748
|
-
throw new Error('Trailing data in initial keepalive pdu.');
|
|
28749
|
-
|
|
28750
|
-
return true;
|
|
28751
|
-
});
|
|
28752
|
-
|
|
28753
|
-
const msg = encodeMessage(new KeepAlive(1000));
|
|
28754
|
-
const t = 5 * (options.retry_interval || 250);
|
|
28755
|
-
|
|
28756
|
-
for (let i = 0; i < 3; i++) {
|
|
28757
|
-
socket.send(msg);
|
|
28758
|
-
|
|
28759
|
-
if (await Promise.race([waiter, delay(t)])) return;
|
|
28760
|
-
}
|
|
28761
|
-
|
|
28762
|
-
throw new Error('Failed to connect.');
|
|
28763
|
-
}
|
|
28764
|
-
|
|
28765
28986
|
/**
|
|
28766
28987
|
* :class:`ClientConnection` subclass which implements OCP.1 with UDP
|
|
28767
28988
|
* transport.
|
|
@@ -28778,15 +28999,20 @@
|
|
|
28778
28999
|
this.retry_interval =
|
|
28779
29000
|
options.retry_interval >= 0 ? options.retry_interval : 250;
|
|
28780
29001
|
this.retry_count = options.retry_count >= 0 ? options.retry_count : 3;
|
|
28781
|
-
this.
|
|
28782
|
-
|
|
28783
|
-
|
|
28784
|
-
|
|
28785
|
-
|
|
28786
|
-
|
|
28787
|
-
|
|
28788
|
-
|
|
28789
|
-
|
|
29002
|
+
this._write_out_timer = new Timer(
|
|
29003
|
+
() => {
|
|
29004
|
+
this._write_out();
|
|
29005
|
+
},
|
|
29006
|
+
() => this._now()
|
|
29007
|
+
);
|
|
29008
|
+
this._retry_timer = new Timer(
|
|
29009
|
+
() => {
|
|
29010
|
+
this._retryCommands();
|
|
29011
|
+
this._retry_timer.scheduleIn(this.retry_interval);
|
|
29012
|
+
},
|
|
29013
|
+
() => this._now()
|
|
29014
|
+
);
|
|
29015
|
+
this._retry_timer.scheduleIn(this.retry_interval);
|
|
28790
29016
|
this.q = [];
|
|
28791
29017
|
socket.onmessage = (buffer) => {
|
|
28792
29018
|
try {
|
|
@@ -28804,11 +29030,33 @@
|
|
|
28804
29030
|
return false;
|
|
28805
29031
|
}
|
|
28806
29032
|
|
|
29033
|
+
get bufferedAmount() {
|
|
29034
|
+
let amount = super.bufferedAmount;
|
|
29035
|
+
|
|
29036
|
+
for (const buf of this.q) {
|
|
29037
|
+
amount += buf.byteLength;
|
|
29038
|
+
}
|
|
29039
|
+
|
|
29040
|
+
return amount;
|
|
29041
|
+
}
|
|
29042
|
+
|
|
29043
|
+
get pendingWrites() {
|
|
29044
|
+
return super.pendingWrites + this.q.length;
|
|
29045
|
+
}
|
|
29046
|
+
|
|
29047
|
+
shouldSendMoreCommands() {
|
|
29048
|
+
return this.q.length < 3;
|
|
29049
|
+
}
|
|
29050
|
+
|
|
28807
29051
|
/**
|
|
28808
29052
|
* Connect to the given endpoint.
|
|
28809
29053
|
*
|
|
28810
|
-
* @param {String} options.host
|
|
28811
|
-
*
|
|
29054
|
+
* @param {String} options.host
|
|
29055
|
+
* Hostname or ip address.
|
|
29056
|
+
* @param {number} options.port
|
|
29057
|
+
* Port number.
|
|
29058
|
+
* @param {'udp4' | 'udp6'} [options.type]
|
|
29059
|
+
* Optional ip protocol type.
|
|
28812
29060
|
* @param {number} [options.delay=10] - Delay in ms between individual packets.
|
|
28813
29061
|
* This can be a useful strategy when communicating with devices which
|
|
28814
29062
|
* cannot handle high packet rates.
|
|
@@ -28822,23 +29070,33 @@
|
|
|
28822
29070
|
* in an individual UDP packet. Note that AES70 messages which are larger
|
|
28823
29071
|
* than this limit are sent anyway. This only limits how many seperate
|
|
28824
29072
|
* messages are batched into a single packet.
|
|
28825
|
-
* @
|
|
29073
|
+
* @param {AbortSignal} [options.connectSignal]
|
|
29074
|
+
* An optional AbortSignal which can be used to abort the connect attempt.
|
|
29075
|
+
* Note that this is different from the `signal` option which will destroy
|
|
29076
|
+
* the socket also after the connect attempt has been successful.
|
|
29077
|
+
* @returns {Promise<AbstractUDPConnection>}
|
|
28826
29078
|
* The connection.
|
|
28827
29079
|
*/
|
|
28828
29080
|
static async connect(udpApi, options) {
|
|
28829
|
-
const
|
|
28830
|
-
|
|
28831
|
-
|
|
28832
|
-
|
|
28833
|
-
|
|
29081
|
+
const { host, port, type, connectSignal } = options;
|
|
29082
|
+
const socket = await udpApi.connect({
|
|
29083
|
+
host,
|
|
29084
|
+
port,
|
|
29085
|
+
type,
|
|
29086
|
+
signal: connectSignal,
|
|
29087
|
+
});
|
|
29088
|
+
|
|
29089
|
+
const connection = new this(socket, options);
|
|
28834
29090
|
|
|
28835
29091
|
try {
|
|
28836
|
-
await
|
|
28837
|
-
|
|
29092
|
+
await connection.wait_for_keepalive(1, connectSignal);
|
|
29093
|
+
connectSignal?.throwIfAborted();
|
|
28838
29094
|
} catch (err) {
|
|
28839
|
-
|
|
29095
|
+
connection.close();
|
|
28840
29096
|
throw err;
|
|
28841
29097
|
}
|
|
29098
|
+
|
|
29099
|
+
return connection;
|
|
28842
29100
|
}
|
|
28843
29101
|
|
|
28844
29102
|
write(buf) {
|
|
@@ -28859,14 +29117,8 @@
|
|
|
28859
29117
|
this.socket.close();
|
|
28860
29118
|
this.socket = null;
|
|
28861
29119
|
}
|
|
28862
|
-
|
|
28863
|
-
|
|
28864
|
-
this._write_out_id = -1;
|
|
28865
|
-
}
|
|
28866
|
-
if (this._retry_id !== -1) {
|
|
28867
|
-
clearInterval(this._retry_id);
|
|
28868
|
-
this._retry_id = -1;
|
|
28869
|
-
}
|
|
29120
|
+
this._write_out_timer.dispose();
|
|
29121
|
+
this._retry_timer.dispose();
|
|
28870
29122
|
}
|
|
28871
29123
|
|
|
28872
29124
|
_estimate_next_tx_time() {
|
|
@@ -28885,6 +29137,13 @@
|
|
|
28885
29137
|
super.write(buf);
|
|
28886
29138
|
|
|
28887
29139
|
if (q.length) this._schedule_write_out();
|
|
29140
|
+
this.scheduleSendCommands();
|
|
29141
|
+
}
|
|
29142
|
+
|
|
29143
|
+
poll() {
|
|
29144
|
+
super.poll();
|
|
29145
|
+
this._write_out_timer.poll();
|
|
29146
|
+
this._retry_timer.poll();
|
|
28888
29147
|
}
|
|
28889
29148
|
|
|
28890
29149
|
_schedule_write_out() {
|
|
@@ -28896,38 +29155,36 @@
|
|
|
28896
29155
|
return;
|
|
28897
29156
|
}
|
|
28898
29157
|
|
|
28899
|
-
|
|
28900
|
-
if (this._write_out_id !== -1) return;
|
|
28901
|
-
|
|
28902
|
-
this._write_out_id = setTimeout(
|
|
28903
|
-
this._write_out_callback,
|
|
28904
|
-
delay - tx_idle_time
|
|
28905
|
-
);
|
|
29158
|
+
this._write_out_timer.scheduleIn(delay - tx_idle_time);
|
|
28906
29159
|
}
|
|
28907
29160
|
|
|
28908
29161
|
_retryCommands() {
|
|
28909
29162
|
const now = this._now();
|
|
28910
29163
|
const retryTime = now - this.retry_interval;
|
|
28911
|
-
// This is an estimate for how many commands we would manage to send
|
|
28912
|
-
// off.
|
|
28913
|
-
const max = 5 * (this.retry_interval / this.delay) - this.q.length;
|
|
28914
29164
|
const pendingCommands = this._pendingCommands;
|
|
29165
|
+
const _sentPendingCommands = this._sentPendingCommands;
|
|
29166
|
+
const _scheduledPendingCommands = this._scheduledPendingCommands;
|
|
28915
29167
|
|
|
28916
|
-
|
|
29168
|
+
let scheduledCount = 0;
|
|
28917
29169
|
const failed = [];
|
|
28918
29170
|
|
|
28919
|
-
for (const
|
|
28920
|
-
const [, pendingCommand] = entry;
|
|
28921
|
-
|
|
28922
|
-
// All later commands are newer than the cutoff.
|
|
29171
|
+
for (const pendingCommand of _sentPendingCommands) {
|
|
28923
29172
|
if (pendingCommand.lastSent > retryTime) break;
|
|
29173
|
+
|
|
29174
|
+
_sentPendingCommands.delete(pendingCommand);
|
|
29175
|
+
|
|
28924
29176
|
if (pendingCommand.retries >= this.retry_count) {
|
|
28925
|
-
failed.push(
|
|
28926
|
-
} else
|
|
28927
|
-
|
|
29177
|
+
failed.push(pendingCommand);
|
|
29178
|
+
} else {
|
|
29179
|
+
_scheduledPendingCommands.add(pendingCommand);
|
|
29180
|
+
scheduledCount++;
|
|
28928
29181
|
}
|
|
28929
29182
|
}
|
|
28930
29183
|
|
|
29184
|
+
if (scheduledCount) {
|
|
29185
|
+
this.scheduleSendCommands();
|
|
29186
|
+
}
|
|
29187
|
+
|
|
28931
29188
|
if (failed.length) {
|
|
28932
29189
|
const timeoutError = new Error('Timeout.');
|
|
28933
29190
|
|
|
@@ -28936,14 +29193,6 @@
|
|
|
28936
29193
|
pendingCommand.reject(timeoutError);
|
|
28937
29194
|
});
|
|
28938
29195
|
}
|
|
28939
|
-
|
|
28940
|
-
retries.forEach(([handle, pendingCommand]) => {
|
|
28941
|
-
pendingCommands.delete(handle);
|
|
28942
|
-
pendingCommands.set(handle, pendingCommand);
|
|
28943
|
-
this.send(pendingCommand.command);
|
|
28944
|
-
pendingCommand.lastSent = now;
|
|
28945
|
-
pendingCommand.retries++;
|
|
28946
|
-
});
|
|
28947
29196
|
}
|
|
28948
29197
|
}
|
|
28949
29198
|
|
|
@@ -29072,6 +29321,10 @@
|
|
|
29072
29321
|
}
|
|
29073
29322
|
return value;
|
|
29074
29323
|
}
|
|
29324
|
+
} else if (typeof value === 'bigint') {
|
|
29325
|
+
return value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER
|
|
29326
|
+
? Number(value)
|
|
29327
|
+
: value.toString();
|
|
29075
29328
|
} else {
|
|
29076
29329
|
return value;
|
|
29077
29330
|
}
|