unetjs 3.1.5 → 3.2.1
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 +202 -113
- package/dist/esm/unet.js +202 -113
- package/dist/unetjs.js +201 -112
- 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 +2 -2
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.7 */
|
|
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,33 +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
|
|
700
|
+
constructor(opts = {}) {
|
|
701
|
+
// Similar to Object.assign but also overwrites `undefined` and empty strings with defaults
|
|
694
702
|
for (var key in GATEWAY_DEFAULTS){
|
|
695
703
|
if (opts[key] == undefined || opts[key] === '') opts[key] = GATEWAY_DEFAULTS[key];
|
|
696
704
|
}
|
|
@@ -709,13 +717,19 @@
|
|
|
709
717
|
this.listener = {}; // set of callbacks that want to listen to incoming messages
|
|
710
718
|
this.eventListeners = {}; // external listeners wanting to listen internal events
|
|
711
719
|
this.queue = []; // incoming message queue
|
|
720
|
+
this.connected = false; // connection status
|
|
712
721
|
this.debug = false; // debug info to be logged to console?
|
|
713
|
-
this.aid = new AgentID(
|
|
722
|
+
this.aid = new AgentID('gateway-'+_guid(4)); // gateway agent name
|
|
714
723
|
this.connector = this._createConnector(url);
|
|
715
724
|
this._addGWCache(this);
|
|
716
725
|
}
|
|
717
726
|
|
|
718
|
-
/**
|
|
727
|
+
/**
|
|
728
|
+
* Sends an event to all registered listeners of the given type.
|
|
729
|
+
* @private
|
|
730
|
+
* @param {string} type - type of event
|
|
731
|
+
* @param {Object|Message|string} val - value to be sent to the listeners
|
|
732
|
+
*/
|
|
719
733
|
_sendEvent(type, val) {
|
|
720
734
|
if (Array.isArray(this.eventListeners[type])) {
|
|
721
735
|
this.eventListeners[type].forEach(l => {
|
|
@@ -730,7 +744,11 @@
|
|
|
730
744
|
}
|
|
731
745
|
}
|
|
732
746
|
|
|
733
|
-
/**
|
|
747
|
+
/**
|
|
748
|
+
* @private
|
|
749
|
+
* @param {string} data - stringfied JSON data received from the master container to be processed
|
|
750
|
+
* @returns {void}
|
|
751
|
+
*/
|
|
734
752
|
_onMsgRx(data) {
|
|
735
753
|
var obj;
|
|
736
754
|
if (this.debug) console.log('< '+data);
|
|
@@ -747,6 +765,7 @@
|
|
|
747
765
|
delete this.pending[obj.id];
|
|
748
766
|
} else if (obj.action == 'send') {
|
|
749
767
|
// incoming message from master
|
|
768
|
+
// @ts-ignore
|
|
750
769
|
let msg = Message._deserialize(obj.message);
|
|
751
770
|
if (!msg) return;
|
|
752
771
|
this._sendEvent('rxmsg', msg);
|
|
@@ -807,7 +826,12 @@
|
|
|
807
826
|
}
|
|
808
827
|
}
|
|
809
828
|
|
|
810
|
-
/**
|
|
829
|
+
/**
|
|
830
|
+
* Sends a message out to the master container.
|
|
831
|
+
* @private
|
|
832
|
+
* @param {string|Object} s - JSON object (either stringified or not) to be sent to the master container
|
|
833
|
+
* @returns {boolean} - true if the message was sent successfully
|
|
834
|
+
*/
|
|
811
835
|
_msgTx(s) {
|
|
812
836
|
if (typeof s != 'string' && !(s instanceof String)) s = JSON.stringify(s);
|
|
813
837
|
if(this.debug) console.log('> '+s);
|
|
@@ -815,7 +839,11 @@
|
|
|
815
839
|
return this.connector.write(s);
|
|
816
840
|
}
|
|
817
841
|
|
|
818
|
-
/**
|
|
842
|
+
/**
|
|
843
|
+
* @private
|
|
844
|
+
* @param {Object} rq - request to be sent to the master container as a JSON object
|
|
845
|
+
* @returns {Promise<Object>} - a promise which returns the response from the master container
|
|
846
|
+
*/
|
|
819
847
|
_msgTxRx(rq) {
|
|
820
848
|
rq.id = _guid(8);
|
|
821
849
|
return new Promise(resolve => {
|
|
@@ -837,25 +865,32 @@
|
|
|
837
865
|
});
|
|
838
866
|
}
|
|
839
867
|
|
|
840
|
-
/**
|
|
868
|
+
/**
|
|
869
|
+
* @private
|
|
870
|
+
* @param {URL} url - URL object of the master container to connect to
|
|
871
|
+
* @returns {TCPConnector|WSConnector} - connector object to connect to the master container
|
|
872
|
+
*/
|
|
841
873
|
_createConnector(url){
|
|
842
874
|
let conn;
|
|
843
875
|
if (url.protocol.startsWith('ws')){
|
|
844
876
|
conn = new WSConnector({
|
|
845
877
|
'hostname':url.hostname,
|
|
846
|
-
'port':url.port,
|
|
878
|
+
'port':parseInt(url.port),
|
|
847
879
|
'pathname':url.pathname,
|
|
848
|
-
'keepAlive': this._keepAlive
|
|
880
|
+
'keepAlive': this._keepAlive,
|
|
881
|
+
'debug': this.debug
|
|
849
882
|
});
|
|
850
883
|
}else if (url.protocol.startsWith('tcp')){
|
|
851
|
-
conn = new
|
|
884
|
+
conn = new TCPConnector({
|
|
852
885
|
'hostname':url.hostname,
|
|
853
|
-
'port':url.port,
|
|
854
|
-
'keepAlive': this._keepAlive
|
|
886
|
+
'port':parseInt(url.port),
|
|
887
|
+
'keepAlive': this._keepAlive,
|
|
888
|
+
'debug': this.debug
|
|
855
889
|
});
|
|
856
890
|
} else return null;
|
|
857
891
|
conn.setReadCallback(this._onMsgRx.bind(this));
|
|
858
892
|
conn.addConnectionListener(state => {
|
|
893
|
+
this.connected = !!state;
|
|
859
894
|
if (state == true){
|
|
860
895
|
this.flush();
|
|
861
896
|
this.connector.write('{"alive": true}');
|
|
@@ -866,7 +901,13 @@
|
|
|
866
901
|
return conn;
|
|
867
902
|
}
|
|
868
903
|
|
|
869
|
-
/**
|
|
904
|
+
/**
|
|
905
|
+
* Checks if the object is a constructor.
|
|
906
|
+
*
|
|
907
|
+
* @private
|
|
908
|
+
* @param {Object} value - an object to be checked if it is a constructor
|
|
909
|
+
* @returns {boolean} - if the object is a constructor
|
|
910
|
+
*/
|
|
870
911
|
_isConstructor(value) {
|
|
871
912
|
try {
|
|
872
913
|
new new Proxy(value, {construct() { return {}; }});
|
|
@@ -876,7 +917,13 @@
|
|
|
876
917
|
}
|
|
877
918
|
}
|
|
878
919
|
|
|
879
|
-
/**
|
|
920
|
+
/**
|
|
921
|
+
* Matches a message with a filter.
|
|
922
|
+
* @private
|
|
923
|
+
* @param {string|Object|function} filter - filter to be matched
|
|
924
|
+
* @param {Message} msg - message to be matched to the filter
|
|
925
|
+
* @returns {boolean} - true if the message matches the filter
|
|
926
|
+
*/
|
|
880
927
|
_matchMessage(filter, msg){
|
|
881
928
|
if (typeof filter == 'string' || filter instanceof String) {
|
|
882
929
|
return 'inReplyTo' in msg && msg.inReplyTo == filter;
|
|
@@ -896,18 +943,25 @@
|
|
|
896
943
|
}
|
|
897
944
|
}
|
|
898
945
|
|
|
899
|
-
/**
|
|
946
|
+
/**
|
|
947
|
+
* Gets the next message from the queue that matches the filter.
|
|
948
|
+
* @private
|
|
949
|
+
* @param {string|Object|function} filter - filter to be matched
|
|
950
|
+
*/
|
|
900
951
|
_getMessageFromQueue(filter) {
|
|
901
952
|
if (!this.queue.length) return;
|
|
902
953
|
if (!filter) return this.queue.shift();
|
|
903
|
-
|
|
904
954
|
let matchedMsg = this.queue.find( msg => this._matchMessage(filter, msg));
|
|
905
955
|
if (matchedMsg) this.queue.splice(this.queue.indexOf(matchedMsg), 1);
|
|
906
|
-
|
|
907
956
|
return matchedMsg;
|
|
908
957
|
}
|
|
909
958
|
|
|
910
|
-
/**
|
|
959
|
+
/**
|
|
960
|
+
* Gets a cached gateway object for the given URL (if it exists).
|
|
961
|
+
* @private
|
|
962
|
+
* @param {URL} url - URL object of the master container to connect to
|
|
963
|
+
* @returns {Gateway|void} - gateway object for the given URL
|
|
964
|
+
*/
|
|
911
965
|
_getGWCache(url){
|
|
912
966
|
if (!gObj.fjage || !gObj.fjage.gateways) return null;
|
|
913
967
|
var f = gObj.fjage.gateways.filter(g => g.connector.url.toString() == url.toString());
|
|
@@ -915,13 +969,21 @@
|
|
|
915
969
|
return null;
|
|
916
970
|
}
|
|
917
971
|
|
|
918
|
-
/**
|
|
972
|
+
/**
|
|
973
|
+
* Adds a gateway object to the cache if it doesn't already exist.
|
|
974
|
+
* @private
|
|
975
|
+
* @param {Gateway} gw - gateway object to be added to the cache
|
|
976
|
+
*/
|
|
919
977
|
_addGWCache(gw){
|
|
920
978
|
if (!gObj.fjage || !gObj.fjage.gateways) return;
|
|
921
979
|
gObj.fjage.gateways.push(gw);
|
|
922
980
|
}
|
|
923
981
|
|
|
924
|
-
/**
|
|
982
|
+
/**
|
|
983
|
+
* Removes a gateway object from the cache if it exists.
|
|
984
|
+
* @private
|
|
985
|
+
* @param {Gateway} gw - gateway object to be removed from the cache
|
|
986
|
+
*/
|
|
925
987
|
_removeGWCache(gw){
|
|
926
988
|
if (!gObj.fjage || !gObj.fjage.gateways) return;
|
|
927
989
|
var index = gObj.fjage.gateways.indexOf(gw);
|
|
@@ -1009,7 +1071,7 @@
|
|
|
1009
1071
|
/**
|
|
1010
1072
|
* Gets the agent ID associated with the gateway.
|
|
1011
1073
|
*
|
|
1012
|
-
* @returns {
|
|
1074
|
+
* @returns {AgentID} - agent ID
|
|
1013
1075
|
*/
|
|
1014
1076
|
getAgentID() {
|
|
1015
1077
|
return this.aid;
|
|
@@ -1029,7 +1091,7 @@
|
|
|
1029
1091
|
* Returns an object representing the named topic.
|
|
1030
1092
|
*
|
|
1031
1093
|
* @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
|
|
1094
|
+
* @param {string} [topic2] - name of the topic if the topic param is an AgentID
|
|
1033
1095
|
* @returns {AgentID} - object representing the topic
|
|
1034
1096
|
*/
|
|
1035
1097
|
topic(topic, topic2) {
|
|
@@ -1050,6 +1112,7 @@
|
|
|
1050
1112
|
if (!topic.isTopic()) topic = new AgentID(topic.getName() + '__ntf', true, this);
|
|
1051
1113
|
this.subscriptions[topic.toJSON()] = true;
|
|
1052
1114
|
this._update_watch();
|
|
1115
|
+
return true;
|
|
1053
1116
|
}
|
|
1054
1117
|
|
|
1055
1118
|
/**
|
|
@@ -1141,6 +1204,7 @@
|
|
|
1141
1204
|
}
|
|
1142
1205
|
this._sendEvent('txmsg', msg);
|
|
1143
1206
|
let rq = JSON.stringify({ action: 'send', relay: true, message: '###MSG###' });
|
|
1207
|
+
// @ts-ignore
|
|
1144
1208
|
rq = rq.replace('"###MSG###"', msg._serialize());
|
|
1145
1209
|
return !!this._msgTx(rq);
|
|
1146
1210
|
}
|
|
@@ -1158,9 +1222,9 @@
|
|
|
1158
1222
|
* Sends a request and waits for a response. This method returns a {Promise} which resolves when a response
|
|
1159
1223
|
* is received or if no response is received after the timeout.
|
|
1160
1224
|
*
|
|
1161
|
-
* @param {
|
|
1225
|
+
* @param {Message} msg - message to send
|
|
1162
1226
|
* @param {number} [timeout=1000] - timeout in milliseconds
|
|
1163
|
-
* @returns {Promise
|
|
1227
|
+
* @returns {Promise<Message|void>} - a promise which resolves with the received response message, null on timeout
|
|
1164
1228
|
*/
|
|
1165
1229
|
async request(msg, timeout=1000) {
|
|
1166
1230
|
this.send(msg);
|
|
@@ -1171,10 +1235,10 @@
|
|
|
1171
1235
|
* Returns a response message received by the gateway. This method returns a {Promise} which resolves when
|
|
1172
1236
|
* a response is received or if no response is received after the timeout.
|
|
1173
1237
|
*
|
|
1174
|
-
* @param {function}
|
|
1238
|
+
* @param {function|Message|typeof Message} filter - original message to which a response is expected, or a MessageClass of the type
|
|
1175
1239
|
* of message to match, or a closure to use to match against the message
|
|
1176
1240
|
* @param {number} [timeout=0] - timeout in milliseconds
|
|
1177
|
-
* @returns {Promise
|
|
1241
|
+
* @returns {Promise<Message|void>} - received response message, null on timeout
|
|
1178
1242
|
*/
|
|
1179
1243
|
async receive(filter, timeout=0) {
|
|
1180
1244
|
return new Promise(resolve => {
|
|
@@ -1229,8 +1293,8 @@
|
|
|
1229
1293
|
/**
|
|
1230
1294
|
* Creates a unqualified message class based on a fully qualified name.
|
|
1231
1295
|
* @param {string} name - fully qualified name of the message class to be created
|
|
1232
|
-
* @param {
|
|
1233
|
-
* @
|
|
1296
|
+
* @param {typeof Message} [parent] - class of the parent MessageClass to inherit from
|
|
1297
|
+
* @constructs Message
|
|
1234
1298
|
* @example
|
|
1235
1299
|
* const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
|
|
1236
1300
|
* let pReq = new ParameterReq()
|
|
@@ -1239,6 +1303,9 @@
|
|
|
1239
1303
|
let sname = name.replace(/^.*\./, '');
|
|
1240
1304
|
if (MessageClass[sname]) return MessageClass[sname];
|
|
1241
1305
|
let cls = class extends parent {
|
|
1306
|
+
/**
|
|
1307
|
+
* @param {{ [x: string]: any; }} params
|
|
1308
|
+
*/
|
|
1242
1309
|
constructor(params) {
|
|
1243
1310
|
super();
|
|
1244
1311
|
this.__clazz__ = name;
|
|
@@ -1248,6 +1315,7 @@
|
|
|
1248
1315
|
this[k] = params[k];
|
|
1249
1316
|
}
|
|
1250
1317
|
}
|
|
1318
|
+
if (name.endsWith('Req')) this.perf = Performative.REQUEST;
|
|
1251
1319
|
}
|
|
1252
1320
|
};
|
|
1253
1321
|
cls.__clazz__ = name;
|
|
@@ -1294,7 +1362,7 @@
|
|
|
1294
1362
|
break;
|
|
1295
1363
|
case '[J': // long array
|
|
1296
1364
|
for (i = 0; i < len; i+=8)
|
|
1297
|
-
rv.push(view.
|
|
1365
|
+
rv.push(view.getBigInt64(i, littleEndian));
|
|
1298
1366
|
break;
|
|
1299
1367
|
case '[F': // float array
|
|
1300
1368
|
for (i = 0; i < len; i+=4)
|
|
@@ -1329,6 +1397,8 @@
|
|
|
1329
1397
|
////// global
|
|
1330
1398
|
|
|
1331
1399
|
const GATEWAY_DEFAULTS = {};
|
|
1400
|
+
|
|
1401
|
+
/** @type {Window & globalThis & Object} */
|
|
1332
1402
|
let gObj = {};
|
|
1333
1403
|
let DEFAULT_URL;
|
|
1334
1404
|
if (isBrowser || isWebWorker){
|
|
@@ -1345,7 +1415,7 @@
|
|
|
1345
1415
|
DEFAULT_URL = new URL('ws://localhost');
|
|
1346
1416
|
// Enable caching of Gateways
|
|
1347
1417
|
if (typeof gObj.fjage === 'undefined') gObj.fjage = {};
|
|
1348
|
-
if (typeof gObj.fjage.gateways == 'undefined')gObj.fjage.gateways = [];
|
|
1418
|
+
if (typeof gObj.fjage.gateways == 'undefined') gObj.fjage.gateways = [];
|
|
1349
1419
|
} else if (isJsDom || isNode){
|
|
1350
1420
|
gObj = global;
|
|
1351
1421
|
Object.assign(GATEWAY_DEFAULTS, {
|
|
@@ -1361,10 +1431,28 @@
|
|
|
1361
1431
|
gObj.atob = a => Buffer.from(a, 'base64').toString('binary');
|
|
1362
1432
|
}
|
|
1363
1433
|
|
|
1434
|
+
/**
|
|
1435
|
+
* @typedef {Object} ParameterReq.Entry
|
|
1436
|
+
* @property {string} param - parameter name
|
|
1437
|
+
* @property {Object} value - parameter value
|
|
1438
|
+
* @exports ParameterReq.Entry
|
|
1439
|
+
*/
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* A message that requests one or more parameters of an agent.
|
|
1444
|
+
* @typedef {Message} ParameterReq
|
|
1445
|
+
* @property {string} param - parameters name to be get/set if only a single parameter is to be get/set
|
|
1446
|
+
* @property {Object} value - parameters value to be set if only a single parameter is to be set
|
|
1447
|
+
* @property {Array<ParameterReq.Entry>} requests - a list of multiple parameters to be get/set
|
|
1448
|
+
* @property {number} [index=-1] - index of parameter(s) to be set
|
|
1449
|
+
* @exports ParameterReq
|
|
1450
|
+
*/
|
|
1364
1451
|
const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
|
|
1365
1452
|
|
|
1366
1453
|
const DatagramReq$1 = MessageClass('org.arl.unet.DatagramReq');
|
|
1367
1454
|
const DatagramNtf$1 = MessageClass('org.arl.unet.DatagramNtf');
|
|
1455
|
+
const RxFrameNtf$1 = MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1);
|
|
1368
1456
|
const BasebandSignal = MessageClass('org.arl.unet.bb.BasebandSignal');
|
|
1369
1457
|
|
|
1370
1458
|
let UnetServices = {
|
|
@@ -1436,7 +1524,8 @@
|
|
|
1436
1524
|
|
|
1437
1525
|
// phy
|
|
1438
1526
|
'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
|
|
1439
|
-
'
|
|
1527
|
+
'RxSWiG1FrameNtf' : MessageClass('org.arl.unet.phy.RxSWiG1FrameNtf', RxFrameNtf$1),
|
|
1528
|
+
'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf', RxFrameNtf$1),
|
|
1440
1529
|
'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq'),
|
|
1441
1530
|
'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
|
|
1442
1531
|
'BadRangeNtf' : MessageClass('org.arl.unet.phy.BadRangeNtf'),
|