unetjs 3.1.4 → 3.2.0
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/cjs/unet.cjs +200 -115
- package/dist/esm/unet.js +200 -115
- package/dist/unetjs.js +199 -114
- package/dist/unetjs.js.map +1 -1
- package/dist/unetjs.min.js +1 -1
- package/dist/unetjs.min.js.map +1 -1
- package/package.json +3 -3
package/dist/unetjs.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.unet = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
/* fjage.js v1.
|
|
7
|
+
/* fjage.js v1.13.5 */
|
|
8
8
|
|
|
9
9
|
const isBrowser =
|
|
10
10
|
typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
@@ -29,9 +29,7 @@
|
|
|
29
29
|
(navigator.userAgent.includes("Node.js") ||
|
|
30
30
|
navigator.userAgent.includes("jsdom")));
|
|
31
31
|
|
|
32
|
-
typeof Deno !== "undefined" &&
|
|
33
|
-
typeof Deno.version !== "undefined" &&
|
|
34
|
-
typeof Deno.version.deno !== "undefined";
|
|
32
|
+
typeof Deno !== "undefined" && typeof Deno.core !== "undefined";
|
|
35
33
|
|
|
36
34
|
const SOCKET_OPEN = 'open';
|
|
37
35
|
const SOCKET_OPENING = 'opening';
|
|
@@ -43,29 +41,31 @@
|
|
|
43
41
|
* @class
|
|
44
42
|
* @ignore
|
|
45
43
|
*/
|
|
46
|
-
class
|
|
44
|
+
class TCPConnector {
|
|
47
45
|
|
|
48
46
|
/**
|
|
49
47
|
* Create an TCPConnector to connect to a fjage master over TCP
|
|
50
48
|
* @param {Object} opts
|
|
51
|
-
* @param {string} opts.hostname - hostname/ip address of the master container to connect to
|
|
52
|
-
* @param {
|
|
53
|
-
* @param {boolean} opts.keepAlive - try to reconnect if the connection is lost
|
|
49
|
+
* @param {string} [opts.hostname='localhost'] - hostname/ip address of the master container to connect to
|
|
50
|
+
* @param {number} [opts.port=1100] - port number of the master container to connect to
|
|
51
|
+
* @param {boolean} [opts.keepAlive=true] - try to reconnect if the connection is lost
|
|
52
|
+
* @param {boolean} [opts.debug=false] - debug info to be logged to console?
|
|
54
53
|
* @param {number} [opts.reconnectTime=5000] - time before reconnection is attempted after an error
|
|
55
54
|
*/
|
|
56
55
|
constructor(opts = {}) {
|
|
57
|
-
let host = opts.hostname;
|
|
58
|
-
let port = opts.port;
|
|
56
|
+
let host = opts.hostname || 'localhost';
|
|
57
|
+
let port = opts.port || 1100;
|
|
59
58
|
this._keepAlive = opts.keepAlive;
|
|
60
59
|
this._reconnectTime = opts.reconnectTime || DEFAULT_RECONNECT_TIME$1;
|
|
61
60
|
this.url = new URL('tcp://localhost');
|
|
62
61
|
this.url.hostname = host;
|
|
63
|
-
this.url.port = port;
|
|
62
|
+
this.url.port = port.toString();
|
|
64
63
|
this._buf = '';
|
|
65
64
|
this._firstConn = true; // if the Gateway has managed to connect to a server before
|
|
66
65
|
this._firstReConn = true; // if the Gateway has attempted to reconnect to a server before
|
|
67
66
|
this.pendingOnOpen = []; // list of callbacks make as soon as gateway is open
|
|
68
67
|
this.connListeners = []; // external listeners wanting to listen connection events
|
|
68
|
+
this.debug = false;
|
|
69
69
|
this._sockInit(host, port);
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
_sockInit(host, port){
|
|
80
80
|
if (!createConnection){
|
|
81
81
|
try {
|
|
82
|
+
// @ts-ignore
|
|
82
83
|
import('net').then(module => {
|
|
83
84
|
createConnection = module.createConnection;
|
|
84
85
|
this._sockSetup(host, port);
|
|
@@ -162,20 +163,20 @@
|
|
|
162
163
|
return false;
|
|
163
164
|
}
|
|
164
165
|
|
|
166
|
+
/**
|
|
167
|
+
* @callback TCPConnectorReadCallback
|
|
168
|
+
* @ignore
|
|
169
|
+
* @param {string} s - incoming message string
|
|
170
|
+
*/
|
|
171
|
+
|
|
165
172
|
/**
|
|
166
173
|
* Set a callback for receiving incoming strings from the connector
|
|
167
|
-
* @param {
|
|
174
|
+
* @param {TCPConnectorReadCallback} cb - callback that is called when the connector gets a string
|
|
168
175
|
*/
|
|
169
176
|
setReadCallback(cb){
|
|
170
177
|
if (cb && {}.toString.call(cb) === '[object Function]') this._onSockRx = cb;
|
|
171
178
|
}
|
|
172
179
|
|
|
173
|
-
/**
|
|
174
|
-
* @callback TCPConnector~ReadCallback
|
|
175
|
-
* @ignore
|
|
176
|
-
* @param {string} s - incoming message string
|
|
177
|
-
*/
|
|
178
|
-
|
|
179
180
|
/**
|
|
180
181
|
* Add listener for connection events
|
|
181
182
|
* @param {function} listener - a listener callback that is called when the connection is opened/closed
|
|
@@ -232,17 +233,20 @@
|
|
|
232
233
|
/**
|
|
233
234
|
* Create an WSConnector to connect to a fjage master over WebSockets
|
|
234
235
|
* @param {Object} opts
|
|
235
|
-
* @param {string} opts.hostname - hostname/ip address of the master container to connect to
|
|
236
|
-
* @param {
|
|
237
|
-
* @param {string} opts.pathname - path of the master container to connect to
|
|
238
|
-
* @param {boolean} opts.keepAlive - try to reconnect if the connection is lost
|
|
236
|
+
* @param {string} [opts.hostname='localhost'] - hostname/ip address of the master container to connect to
|
|
237
|
+
* @param {number} [opts.port=80] - port number of the master container to connect to
|
|
238
|
+
* @param {string} [opts.pathname="/"] - path of the master container to connect to
|
|
239
|
+
* @param {boolean} [opts.keepAlive=true] - try to reconnect if the connection is lost
|
|
240
|
+
* @param {boolean} [opts.debug=false] - debug info to be logged to console?
|
|
239
241
|
* @param {number} [opts.reconnectTime=5000] - time before reconnection is attempted after an error
|
|
240
242
|
*/
|
|
241
243
|
constructor(opts = {}) {
|
|
244
|
+
let host = opts.hostname || 'localhost';
|
|
245
|
+
let port = opts.port || 80;
|
|
242
246
|
this.url = new URL('ws://localhost');
|
|
243
|
-
this.url.hostname =
|
|
244
|
-
this.url.port =
|
|
245
|
-
this.url.pathname = opts.pathname;
|
|
247
|
+
this.url.hostname = host;
|
|
248
|
+
this.url.port = port.toString();
|
|
249
|
+
this.url.pathname = opts.pathname || '/';
|
|
246
250
|
this._keepAlive = opts.keepAlive;
|
|
247
251
|
this._reconnectTime = opts.reconnectTime || DEFAULT_RECONNECT_TIME;
|
|
248
252
|
this.debug = opts.debug || false; // debug info to be logged to console?
|
|
@@ -317,19 +321,19 @@
|
|
|
317
321
|
}
|
|
318
322
|
|
|
319
323
|
/**
|
|
320
|
-
*
|
|
321
|
-
* @param {WSConnector~ReadCallback} cb - callback that is called when the connector gets a string
|
|
324
|
+
* @callback WSConnectorReadCallback
|
|
322
325
|
* @ignore
|
|
326
|
+
* @param {string} s - incoming message string
|
|
323
327
|
*/
|
|
324
|
-
setReadCallback(cb){
|
|
325
|
-
if (cb && {}.toString.call(cb) === '[object Function]') this._onWebsockRx = cb;
|
|
326
|
-
}
|
|
327
328
|
|
|
328
329
|
/**
|
|
329
|
-
*
|
|
330
|
+
* Set a callback for receiving incoming strings from the connector
|
|
331
|
+
* @param {WSConnectorReadCallback} cb - callback that is called when the connector gets a string
|
|
330
332
|
* @ignore
|
|
331
|
-
* @param {string} s - incoming message string
|
|
332
333
|
*/
|
|
334
|
+
setReadCallback(cb){
|
|
335
|
+
if (cb && {}.toString.call(cb) === '[object Function]') this._onWebsockRx = cb;
|
|
336
|
+
}
|
|
333
337
|
|
|
334
338
|
/**
|
|
335
339
|
* Add listener for connection events
|
|
@@ -380,7 +384,7 @@
|
|
|
380
384
|
/**
|
|
381
385
|
* An action represented by a message. The performative actions are a subset of the
|
|
382
386
|
* FIPA ACL recommendations for interagent communication.
|
|
383
|
-
* @
|
|
387
|
+
* @enum {string}
|
|
384
388
|
*/
|
|
385
389
|
const Performative = {
|
|
386
390
|
REQUEST: 'REQUEST', // Request an action to be performed
|
|
@@ -401,13 +405,13 @@
|
|
|
401
405
|
* An identifier for an agent or a topic.
|
|
402
406
|
* @class
|
|
403
407
|
* @param {string} name - name of the agent
|
|
404
|
-
* @param {boolean} topic - name of topic
|
|
405
|
-
* @param {Gateway} owner - Gateway owner for this AgentID
|
|
408
|
+
* @param {boolean} [topic=false] - name of topic
|
|
409
|
+
* @param {Gateway} [owner] - Gateway owner for this AgentID
|
|
406
410
|
*/
|
|
407
411
|
class AgentID {
|
|
408
412
|
|
|
409
413
|
|
|
410
|
-
constructor(name, topic, owner) {
|
|
414
|
+
constructor(name, topic=false, owner) {
|
|
411
415
|
this.name = name;
|
|
412
416
|
this.topic = topic;
|
|
413
417
|
this.owner = owner;
|
|
@@ -434,12 +438,13 @@
|
|
|
434
438
|
/**
|
|
435
439
|
* Sends a message to the agent represented by this id.
|
|
436
440
|
*
|
|
437
|
-
* @param {
|
|
441
|
+
* @param {Message} msg - message to send
|
|
438
442
|
* @returns {void}
|
|
439
443
|
*/
|
|
440
444
|
send(msg) {
|
|
441
445
|
msg.recipient = this.toJSON();
|
|
442
|
-
this.owner.send(msg);
|
|
446
|
+
if (this.owner) this.owner.send(msg);
|
|
447
|
+
else throw new Error('Unowned AgentID cannot send messages');
|
|
443
448
|
}
|
|
444
449
|
|
|
445
450
|
/**
|
|
@@ -451,7 +456,8 @@
|
|
|
451
456
|
*/
|
|
452
457
|
async request(msg, timeout=1000) {
|
|
453
458
|
msg.recipient = this.toJSON();
|
|
454
|
-
return this.owner.request(msg, timeout);
|
|
459
|
+
if (this.owner) return this.owner.request(msg, timeout);
|
|
460
|
+
else throw new Error('Unowned AgentID cannot send messages');
|
|
455
461
|
}
|
|
456
462
|
|
|
457
463
|
/**
|
|
@@ -567,15 +573,27 @@
|
|
|
567
573
|
}
|
|
568
574
|
}
|
|
569
575
|
|
|
576
|
+
// protected String msgID = UUID.randomUUID().toString();
|
|
577
|
+
// protected Performative perf;
|
|
578
|
+
// protected AgentID recipient;
|
|
579
|
+
// protected AgentID sender = null;
|
|
580
|
+
// protected String inReplyTo = null;
|
|
581
|
+
// protected Long sentAt = null;
|
|
582
|
+
|
|
570
583
|
/**
|
|
571
584
|
* Base class for messages transmitted by one agent to another. Creates an empty message.
|
|
572
585
|
* @class
|
|
573
|
-
* @param {
|
|
574
|
-
* @param {Performative} - performative
|
|
586
|
+
* @param {string} [msgID] - unique identifier for the message
|
|
587
|
+
* @param {Performative} [perf=Performative.INFORM] - performative
|
|
588
|
+
* @param {AgentID} [recipient] - recipient of the message
|
|
589
|
+
* @param {AgentID} [sender] - sender of the message
|
|
590
|
+
* @param {string} [inReplyTo] - message to which this response corresponds to
|
|
591
|
+
* @param {Message} [inReplyTo] - message to which this response corresponds to
|
|
592
|
+
* @param {number} [sentAt] - time at which the message was sent
|
|
575
593
|
*/
|
|
576
594
|
class Message {
|
|
577
595
|
|
|
578
|
-
constructor(inReplyTo={msgID:null, sender:null}, perf=
|
|
596
|
+
constructor(inReplyTo={msgID:null, sender:null}, perf=Performative.INFORM) {
|
|
579
597
|
this.__clazz__ = 'org.arl.fjage.Message';
|
|
580
598
|
this.msgID = _guid(8);
|
|
581
599
|
this.sender = null;
|
|
@@ -616,7 +634,11 @@
|
|
|
616
634
|
// convert a message into a JSON string
|
|
617
635
|
// NOTE: we don't do any base64 encoding for TX as
|
|
618
636
|
// we don't know what data type is intended
|
|
619
|
-
/**
|
|
637
|
+
/**
|
|
638
|
+
* @private
|
|
639
|
+
*
|
|
640
|
+
* @return {string} - JSON string representation of the message
|
|
641
|
+
*/
|
|
620
642
|
_serialize() {
|
|
621
643
|
let clazz = this.__clazz__ || 'org.arl.fjage.Message';
|
|
622
644
|
let data = JSON.stringify(this, (k,v) => {
|
|
@@ -634,26 +656,27 @@
|
|
|
634
656
|
}
|
|
635
657
|
|
|
636
658
|
// convert a dictionary (usually from decoding JSON) into a message
|
|
637
|
-
/**
|
|
638
|
-
|
|
639
|
-
|
|
659
|
+
/**
|
|
660
|
+
* @private
|
|
661
|
+
*
|
|
662
|
+
* @param {(string|Object)} json - JSON string or object to be converted to a message
|
|
663
|
+
* @returns {Message} - message created from the JSON string or object
|
|
664
|
+
* */
|
|
665
|
+
static _deserialize(json) {
|
|
666
|
+
let obj = null;
|
|
667
|
+
if (typeof json == 'string') {
|
|
640
668
|
try {
|
|
641
|
-
obj = JSON.parse(
|
|
669
|
+
obj = JSON.parse(json);
|
|
642
670
|
}catch(e){
|
|
643
671
|
return null;
|
|
644
672
|
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
return rv;
|
|
653
|
-
} catch (err) {
|
|
654
|
-
console.warn('Error trying to deserialize JSON object : ', obj, err);
|
|
655
|
-
return null;
|
|
656
|
-
}
|
|
673
|
+
} else obj = json;
|
|
674
|
+
let qclazz = obj.clazz;
|
|
675
|
+
let clazz = qclazz.replace(/^.*\./, '');
|
|
676
|
+
let rv = MessageClass[clazz] ? new MessageClass[clazz] : new Message();
|
|
677
|
+
rv.__clazz__ = qclazz;
|
|
678
|
+
rv._inflate(obj.data);
|
|
679
|
+
return rv;
|
|
657
680
|
}
|
|
658
681
|
}
|
|
659
682
|
|
|
@@ -664,36 +687,18 @@
|
|
|
664
687
|
*
|
|
665
688
|
* @class
|
|
666
689
|
* @param {Object} opts
|
|
667
|
-
* @param {string}
|
|
668
|
-
* @param {
|
|
669
|
-
* @param {string}
|
|
670
|
-
* @param {
|
|
671
|
-
* @param {number}
|
|
672
|
-
* @param {number}
|
|
690
|
+
* @param {string} [opts.hostname="localhost"] - hostname/ip address of the master container to connect to
|
|
691
|
+
* @param {number} [opts.port=1100] - port number of the master container to connect to
|
|
692
|
+
* @param {string} [opts.pathname=""] - path of the master container to connect to (for WebSockets)
|
|
693
|
+
* @param {string} [opts.keepAlive=true] - try to reconnect if the connection is lost
|
|
694
|
+
* @param {number} [opts.queueSize=128] - size of the queue of received messages that haven't been consumed yet
|
|
695
|
+
* @param {number} [opts.timeout=1000] - timeout for fjage level messages in ms
|
|
673
696
|
* @param {boolean} [opts.returnNullOnFailedResponse=true] - return null instead of throwing an error when a parameter is not found
|
|
674
|
-
* @param {string} [hostname="localhost"] - <strike>Deprecated : hostname/ip address of the master container to connect to</strike>
|
|
675
|
-
* @param {number} [port=] - <strike>Deprecated : port number of the master container to connect to</strike>
|
|
676
|
-
* @param {string} [pathname=="/ws/"] - <strike>Deprecated : path of the master container to connect to (for WebSockets)</strike>
|
|
677
|
-
* @param {number} [timeout=1000] - <strike>Deprecated : timeout for fjage level messages in ms</strike>
|
|
678
697
|
*/
|
|
679
698
|
class Gateway {
|
|
680
699
|
|
|
681
|
-
constructor(opts = {}
|
|
682
|
-
|
|
683
|
-
if (typeof opts === 'string' || opts instanceof String){
|
|
684
|
-
opts = {
|
|
685
|
-
'hostname': opts,
|
|
686
|
-
'port' : port,
|
|
687
|
-
'pathname' : pathname,
|
|
688
|
-
'timeout' : timeout
|
|
689
|
-
};
|
|
690
|
-
console.warn('Deprecated use of Gateway constructor');
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
// Set defaults
|
|
694
|
-
for (var key in GATEWAY_DEFAULTS){
|
|
695
|
-
if (opts[key] == undefined || opts[key] === '') opts[key] = GATEWAY_DEFAULTS[key];
|
|
696
|
-
}
|
|
700
|
+
constructor(opts = {}) {
|
|
701
|
+
opts = Object.assign({}, GATEWAY_DEFAULTS, opts);
|
|
697
702
|
var url = DEFAULT_URL;
|
|
698
703
|
url.hostname = opts.hostname;
|
|
699
704
|
url.port = opts.port;
|
|
@@ -709,13 +714,19 @@
|
|
|
709
714
|
this.listener = {}; // set of callbacks that want to listen to incoming messages
|
|
710
715
|
this.eventListeners = {}; // external listeners wanting to listen internal events
|
|
711
716
|
this.queue = []; // incoming message queue
|
|
717
|
+
this.connected = false; // connection status
|
|
712
718
|
this.debug = false; // debug info to be logged to console?
|
|
713
719
|
this.aid = new AgentID((isBrowser ? 'WebGW-' : 'NodeGW-')+_guid(4)); // gateway agent name
|
|
714
720
|
this.connector = this._createConnector(url);
|
|
715
721
|
this._addGWCache(this);
|
|
716
722
|
}
|
|
717
723
|
|
|
718
|
-
/**
|
|
724
|
+
/**
|
|
725
|
+
* Sends an event to all registered listeners of the given type.
|
|
726
|
+
* @private
|
|
727
|
+
* @param {string} type - type of event
|
|
728
|
+
* @param {Object|Message|string} val - value to be sent to the listeners
|
|
729
|
+
*/
|
|
719
730
|
_sendEvent(type, val) {
|
|
720
731
|
if (Array.isArray(this.eventListeners[type])) {
|
|
721
732
|
this.eventListeners[type].forEach(l => {
|
|
@@ -730,7 +741,11 @@
|
|
|
730
741
|
}
|
|
731
742
|
}
|
|
732
743
|
|
|
733
|
-
/**
|
|
744
|
+
/**
|
|
745
|
+
* @private
|
|
746
|
+
* @param {string} data - stringfied JSON data received from the master container to be processed
|
|
747
|
+
* @returns {void}
|
|
748
|
+
*/
|
|
734
749
|
_onMsgRx(data) {
|
|
735
750
|
var obj;
|
|
736
751
|
if (this.debug) console.log('< '+data);
|
|
@@ -747,6 +762,7 @@
|
|
|
747
762
|
delete this.pending[obj.id];
|
|
748
763
|
} else if (obj.action == 'send') {
|
|
749
764
|
// incoming message from master
|
|
765
|
+
// @ts-ignore
|
|
750
766
|
let msg = Message._deserialize(obj.message);
|
|
751
767
|
if (!msg) return;
|
|
752
768
|
this._sendEvent('rxmsg', msg);
|
|
@@ -807,7 +823,12 @@
|
|
|
807
823
|
}
|
|
808
824
|
}
|
|
809
825
|
|
|
810
|
-
/**
|
|
826
|
+
/**
|
|
827
|
+
* Sends a message out to the master container.
|
|
828
|
+
* @private
|
|
829
|
+
* @param {string|Object} s - JSON object (either stringified or not) to be sent to the master container
|
|
830
|
+
* @returns {boolean} - true if the message was sent successfully
|
|
831
|
+
*/
|
|
811
832
|
_msgTx(s) {
|
|
812
833
|
if (typeof s != 'string' && !(s instanceof String)) s = JSON.stringify(s);
|
|
813
834
|
if(this.debug) console.log('> '+s);
|
|
@@ -815,7 +836,11 @@
|
|
|
815
836
|
return this.connector.write(s);
|
|
816
837
|
}
|
|
817
838
|
|
|
818
|
-
/**
|
|
839
|
+
/**
|
|
840
|
+
* @private
|
|
841
|
+
* @param {Object} rq - request to be sent to the master container as a JSON object
|
|
842
|
+
* @returns {Promise<Object>} - a promise which returns the response from the master container
|
|
843
|
+
*/
|
|
819
844
|
_msgTxRx(rq) {
|
|
820
845
|
rq.id = _guid(8);
|
|
821
846
|
return new Promise(resolve => {
|
|
@@ -837,25 +862,32 @@
|
|
|
837
862
|
});
|
|
838
863
|
}
|
|
839
864
|
|
|
840
|
-
/**
|
|
865
|
+
/**
|
|
866
|
+
* @private
|
|
867
|
+
* @param {URL} url - URL object of the master container to connect to
|
|
868
|
+
* @returns {TCPConnector|WSConnector} - connector object to connect to the master container
|
|
869
|
+
*/
|
|
841
870
|
_createConnector(url){
|
|
842
871
|
let conn;
|
|
843
872
|
if (url.protocol.startsWith('ws')){
|
|
844
873
|
conn = new WSConnector({
|
|
845
874
|
'hostname':url.hostname,
|
|
846
|
-
'port':url.port,
|
|
875
|
+
'port':parseInt(url.port),
|
|
847
876
|
'pathname':url.pathname,
|
|
848
|
-
'keepAlive': this._keepAlive
|
|
877
|
+
'keepAlive': this._keepAlive,
|
|
878
|
+
'debug': this.debug
|
|
849
879
|
});
|
|
850
880
|
}else if (url.protocol.startsWith('tcp')){
|
|
851
|
-
conn = new
|
|
881
|
+
conn = new TCPConnector({
|
|
852
882
|
'hostname':url.hostname,
|
|
853
|
-
'port':url.port,
|
|
854
|
-
'keepAlive': this._keepAlive
|
|
883
|
+
'port':parseInt(url.port),
|
|
884
|
+
'keepAlive': this._keepAlive,
|
|
885
|
+
'debug': this.debug
|
|
855
886
|
});
|
|
856
887
|
} else return null;
|
|
857
888
|
conn.setReadCallback(this._onMsgRx.bind(this));
|
|
858
889
|
conn.addConnectionListener(state => {
|
|
890
|
+
this.connected = !!state;
|
|
859
891
|
if (state == true){
|
|
860
892
|
this.flush();
|
|
861
893
|
this.connector.write('{"alive": true}');
|
|
@@ -866,7 +898,13 @@
|
|
|
866
898
|
return conn;
|
|
867
899
|
}
|
|
868
900
|
|
|
869
|
-
/**
|
|
901
|
+
/**
|
|
902
|
+
* Checks if the object is a constructor.
|
|
903
|
+
*
|
|
904
|
+
* @private
|
|
905
|
+
* @param {Object} value - an object to be checked if it is a constructor
|
|
906
|
+
* @returns {boolean} - if the object is a constructor
|
|
907
|
+
*/
|
|
870
908
|
_isConstructor(value) {
|
|
871
909
|
try {
|
|
872
910
|
new new Proxy(value, {construct() { return {}; }});
|
|
@@ -876,7 +914,13 @@
|
|
|
876
914
|
}
|
|
877
915
|
}
|
|
878
916
|
|
|
879
|
-
/**
|
|
917
|
+
/**
|
|
918
|
+
* Matches a message with a filter.
|
|
919
|
+
* @private
|
|
920
|
+
* @param {string|Object|function} filter - filter to be matched
|
|
921
|
+
* @param {Message} msg - message to be matched to the filter
|
|
922
|
+
* @returns {boolean} - true if the message matches the filter
|
|
923
|
+
*/
|
|
880
924
|
_matchMessage(filter, msg){
|
|
881
925
|
if (typeof filter == 'string' || filter instanceof String) {
|
|
882
926
|
return 'inReplyTo' in msg && msg.inReplyTo == filter;
|
|
@@ -896,18 +940,25 @@
|
|
|
896
940
|
}
|
|
897
941
|
}
|
|
898
942
|
|
|
899
|
-
/**
|
|
943
|
+
/**
|
|
944
|
+
* Gets the next message from the queue that matches the filter.
|
|
945
|
+
* @private
|
|
946
|
+
* @param {string|Object|function} filter - filter to be matched
|
|
947
|
+
*/
|
|
900
948
|
_getMessageFromQueue(filter) {
|
|
901
949
|
if (!this.queue.length) return;
|
|
902
950
|
if (!filter) return this.queue.shift();
|
|
903
|
-
|
|
904
951
|
let matchedMsg = this.queue.find( msg => this._matchMessage(filter, msg));
|
|
905
952
|
if (matchedMsg) this.queue.splice(this.queue.indexOf(matchedMsg), 1);
|
|
906
|
-
|
|
907
953
|
return matchedMsg;
|
|
908
954
|
}
|
|
909
955
|
|
|
910
|
-
/**
|
|
956
|
+
/**
|
|
957
|
+
* Gets a cached gateway object for the given URL (if it exists).
|
|
958
|
+
* @private
|
|
959
|
+
* @param {URL} url - URL object of the master container to connect to
|
|
960
|
+
* @returns {Gateway|void} - gateway object for the given URL
|
|
961
|
+
*/
|
|
911
962
|
_getGWCache(url){
|
|
912
963
|
if (!gObj.fjage || !gObj.fjage.gateways) return null;
|
|
913
964
|
var f = gObj.fjage.gateways.filter(g => g.connector.url.toString() == url.toString());
|
|
@@ -915,13 +966,21 @@
|
|
|
915
966
|
return null;
|
|
916
967
|
}
|
|
917
968
|
|
|
918
|
-
/**
|
|
969
|
+
/**
|
|
970
|
+
* Adds a gateway object to the cache if it doesn't already exist.
|
|
971
|
+
* @private
|
|
972
|
+
* @param {Gateway} gw - gateway object to be added to the cache
|
|
973
|
+
*/
|
|
919
974
|
_addGWCache(gw){
|
|
920
975
|
if (!gObj.fjage || !gObj.fjage.gateways) return;
|
|
921
976
|
gObj.fjage.gateways.push(gw);
|
|
922
977
|
}
|
|
923
978
|
|
|
924
|
-
/**
|
|
979
|
+
/**
|
|
980
|
+
* Removes a gateway object from the cache if it exists.
|
|
981
|
+
* @private
|
|
982
|
+
* @param {Gateway} gw - gateway object to be removed from the cache
|
|
983
|
+
*/
|
|
925
984
|
_removeGWCache(gw){
|
|
926
985
|
if (!gObj.fjage || !gObj.fjage.gateways) return;
|
|
927
986
|
var index = gObj.fjage.gateways.indexOf(gw);
|
|
@@ -1009,7 +1068,7 @@
|
|
|
1009
1068
|
/**
|
|
1010
1069
|
* Gets the agent ID associated with the gateway.
|
|
1011
1070
|
*
|
|
1012
|
-
* @returns {
|
|
1071
|
+
* @returns {AgentID} - agent ID
|
|
1013
1072
|
*/
|
|
1014
1073
|
getAgentID() {
|
|
1015
1074
|
return this.aid;
|
|
@@ -1029,7 +1088,7 @@
|
|
|
1029
1088
|
* Returns an object representing the named topic.
|
|
1030
1089
|
*
|
|
1031
1090
|
* @param {string|AgentID} topic - name of the topic or AgentID
|
|
1032
|
-
* @param {string} topic2 - name of the topic if the topic param is an AgentID
|
|
1091
|
+
* @param {string} [topic2] - name of the topic if the topic param is an AgentID
|
|
1033
1092
|
* @returns {AgentID} - object representing the topic
|
|
1034
1093
|
*/
|
|
1035
1094
|
topic(topic, topic2) {
|
|
@@ -1050,6 +1109,7 @@
|
|
|
1050
1109
|
if (!topic.isTopic()) topic = new AgentID(topic.getName() + '__ntf', true, this);
|
|
1051
1110
|
this.subscriptions[topic.toJSON()] = true;
|
|
1052
1111
|
this._update_watch();
|
|
1112
|
+
return true;
|
|
1053
1113
|
}
|
|
1054
1114
|
|
|
1055
1115
|
/**
|
|
@@ -1141,6 +1201,7 @@
|
|
|
1141
1201
|
}
|
|
1142
1202
|
this._sendEvent('txmsg', msg);
|
|
1143
1203
|
let rq = JSON.stringify({ action: 'send', relay: true, message: '###MSG###' });
|
|
1204
|
+
// @ts-ignore
|
|
1144
1205
|
rq = rq.replace('"###MSG###"', msg._serialize());
|
|
1145
1206
|
return !!this._msgTx(rq);
|
|
1146
1207
|
}
|
|
@@ -1158,9 +1219,9 @@
|
|
|
1158
1219
|
* Sends a request and waits for a response. This method returns a {Promise} which resolves when a response
|
|
1159
1220
|
* is received or if no response is received after the timeout.
|
|
1160
1221
|
*
|
|
1161
|
-
* @param {
|
|
1222
|
+
* @param {Message} msg - message to send
|
|
1162
1223
|
* @param {number} [timeout=1000] - timeout in milliseconds
|
|
1163
|
-
* @returns {Promise
|
|
1224
|
+
* @returns {Promise<Message|void>} - a promise which resolves with the received response message, null on timeout
|
|
1164
1225
|
*/
|
|
1165
1226
|
async request(msg, timeout=1000) {
|
|
1166
1227
|
this.send(msg);
|
|
@@ -1171,10 +1232,10 @@
|
|
|
1171
1232
|
* Returns a response message received by the gateway. This method returns a {Promise} which resolves when
|
|
1172
1233
|
* a response is received or if no response is received after the timeout.
|
|
1173
1234
|
*
|
|
1174
|
-
* @param {function}
|
|
1235
|
+
* @param {function|Message|typeof Message} filter - original message to which a response is expected, or a MessageClass of the type
|
|
1175
1236
|
* of message to match, or a closure to use to match against the message
|
|
1176
1237
|
* @param {number} [timeout=0] - timeout in milliseconds
|
|
1177
|
-
* @returns {Promise
|
|
1238
|
+
* @returns {Promise<Message|void>} - received response message, null on timeout
|
|
1178
1239
|
*/
|
|
1179
1240
|
async receive(filter, timeout=0) {
|
|
1180
1241
|
return new Promise(resolve => {
|
|
@@ -1229,8 +1290,8 @@
|
|
|
1229
1290
|
/**
|
|
1230
1291
|
* Creates a unqualified message class based on a fully qualified name.
|
|
1231
1292
|
* @param {string} name - fully qualified name of the message class to be created
|
|
1232
|
-
* @param {
|
|
1233
|
-
* @
|
|
1293
|
+
* @param {typeof Message} [parent] - class of the parent MessageClass to inherit from
|
|
1294
|
+
* @constructs Message
|
|
1234
1295
|
* @example
|
|
1235
1296
|
* const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
|
|
1236
1297
|
* let pReq = new ParameterReq()
|
|
@@ -1239,6 +1300,9 @@
|
|
|
1239
1300
|
let sname = name.replace(/^.*\./, '');
|
|
1240
1301
|
if (MessageClass[sname]) return MessageClass[sname];
|
|
1241
1302
|
let cls = class extends parent {
|
|
1303
|
+
/**
|
|
1304
|
+
* @param {{ [x: string]: any; }} params
|
|
1305
|
+
*/
|
|
1242
1306
|
constructor(params) {
|
|
1243
1307
|
super();
|
|
1244
1308
|
this.__clazz__ = name;
|
|
@@ -1294,7 +1358,7 @@
|
|
|
1294
1358
|
break;
|
|
1295
1359
|
case '[J': // long array
|
|
1296
1360
|
for (i = 0; i < len; i+=8)
|
|
1297
|
-
rv.push(view.
|
|
1361
|
+
rv.push(view.getBigInt64(i, littleEndian));
|
|
1298
1362
|
break;
|
|
1299
1363
|
case '[F': // float array
|
|
1300
1364
|
for (i = 0; i < len; i+=4)
|
|
@@ -1329,6 +1393,8 @@
|
|
|
1329
1393
|
////// global
|
|
1330
1394
|
|
|
1331
1395
|
const GATEWAY_DEFAULTS = {};
|
|
1396
|
+
|
|
1397
|
+
/** @type {Window & globalThis & Object} */
|
|
1332
1398
|
let gObj = {};
|
|
1333
1399
|
let DEFAULT_URL;
|
|
1334
1400
|
if (isBrowser || isWebWorker){
|
|
@@ -1345,7 +1411,7 @@
|
|
|
1345
1411
|
DEFAULT_URL = new URL('ws://localhost');
|
|
1346
1412
|
// Enable caching of Gateways
|
|
1347
1413
|
if (typeof gObj.fjage === 'undefined') gObj.fjage = {};
|
|
1348
|
-
if (typeof gObj.fjage.gateways == 'undefined')gObj.fjage.gateways = [];
|
|
1414
|
+
if (typeof gObj.fjage.gateways == 'undefined') gObj.fjage.gateways = [];
|
|
1349
1415
|
} else if (isJsDom || isNode){
|
|
1350
1416
|
gObj = global;
|
|
1351
1417
|
Object.assign(GATEWAY_DEFAULTS, {
|
|
@@ -1361,10 +1427,28 @@
|
|
|
1361
1427
|
gObj.atob = a => Buffer.from(a, 'base64').toString('binary');
|
|
1362
1428
|
}
|
|
1363
1429
|
|
|
1430
|
+
/**
|
|
1431
|
+
* @typedef {Object} ParameterReq.Entry
|
|
1432
|
+
* @property {string} param - parameter name
|
|
1433
|
+
* @property {Object} value - parameter value
|
|
1434
|
+
* @exports ParameterReq.Entry
|
|
1435
|
+
*/
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* A message that requests one or more parameters of an agent.
|
|
1440
|
+
* @typedef {Message} ParameterReq
|
|
1441
|
+
* @property {string} param - parameters name to be get/set if only a single parameter is to be get/set
|
|
1442
|
+
* @property {Object} value - parameters value to be set if only a single parameter is to be set
|
|
1443
|
+
* @property {Array<ParameterReq.Entry>} requests - a list of multiple parameters to be get/set
|
|
1444
|
+
* @property {number} [index=-1] - index of parameter(s) to be set
|
|
1445
|
+
* @exports ParameterReq
|
|
1446
|
+
*/
|
|
1364
1447
|
const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
|
|
1365
1448
|
|
|
1366
1449
|
const DatagramReq$1 = MessageClass('org.arl.unet.DatagramReq');
|
|
1367
1450
|
const DatagramNtf$1 = MessageClass('org.arl.unet.DatagramNtf');
|
|
1451
|
+
const RxFrameNtf$1 = MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1);
|
|
1368
1452
|
const BasebandSignal = MessageClass('org.arl.unet.bb.BasebandSignal');
|
|
1369
1453
|
|
|
1370
1454
|
let UnetServices = {
|
|
@@ -1436,7 +1520,8 @@
|
|
|
1436
1520
|
|
|
1437
1521
|
// phy
|
|
1438
1522
|
'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
|
|
1439
|
-
'
|
|
1523
|
+
'RxSWiG1FrameNtf' : MessageClass('org.arl.unet.phy.RxSWiG1FrameNtf', RxFrameNtf$1),
|
|
1524
|
+
'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf', RxFrameNtf$1),
|
|
1440
1525
|
'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq'),
|
|
1441
1526
|
'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
|
|
1442
1527
|
'BadRangeNtf' : MessageClass('org.arl.unet.phy.BadRangeNtf'),
|