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/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.12.2 */
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 TCPconnector {
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 {string} opts.port - port number of the master container to connect to
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 {TCPConnector~ReadCallback} cb - callback that is called when the connector gets a string
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 {string} opts.port - port number of the master container to connect to
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 = opts.hostname;
244
- this.url.port = opts.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
- * Set a callback for receiving incoming strings from the connector
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
- * @callback WSConnector~ReadCallback
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
- * @typedef {Object} Performative
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 {string} msg - message to send
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 {Message} inReplyTo - message to which this response corresponds to
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
- /** @private */
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
- /** @private */
638
- static _deserialize(obj) {
639
- if (typeof obj == 'string' || obj instanceof String) {
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(obj);
669
+ obj = JSON.parse(json);
642
670
  }catch(e){
643
671
  return null;
644
672
  }
645
- }
646
- try {
647
- let qclazz = obj.clazz;
648
- let clazz = qclazz.replace(/^.*\./, '');
649
- let rv = MessageClass[clazz] ? new MessageClass[clazz] : new Message();
650
- rv.__clazz__ = qclazz;
651
- rv._inflate(obj.data);
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} [opts.hostname="localhost"] - hostname/ip address of the master container to connect to
668
- * @param {string} [opts.port='1100'] - port number of the master container to connect to
669
- * @param {string} [opts.pathname=""] - path of the master container to connect to (for WebSockets)
670
- * @param {boolean} [opts.keepAlive=true] - try to reconnect if the connection is lost
671
- * @param {number} [opts.queueSize=128] - size of the queue of received messages that haven't been consumed yet
672
- * @param {number} [opts.timeout=1000] - timeout for fjage level messages in ms
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 = {}, port, pathname='/ws/', timeout=1000) {
682
- // Support for deprecated constructor
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((isBrowser ? 'WebGW-' : 'NodeGW-')+_guid(4)); // gateway agent name
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
- /** @private */
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
- /** @private */
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
- /** @private */
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
- /** @private */
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
- /** @private */
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 TCPconnector({
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
- /** @private */
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
- /** @private */
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
- /** @private */
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
- /** @private */
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
- /** @private */
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
- /** @private */
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 {string} - agent ID
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 {string} msg - message to send
1225
+ * @param {Message} msg - message to send
1162
1226
  * @param {number} [timeout=1000] - timeout in milliseconds
1163
- * @returns {Promise<?Message>} - a promise which resolves with the received response message, null on timeout
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} [filter=] - original message to which a response is expected, or a MessageClass of the type
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<?Message>} - received response message, null on timeout
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 {class} [parent=Message] - class of the parent MessageClass to inherit from
1233
- * @returns {function} - constructor for the unqualified message class
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.getInt64(i, littleEndian));
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
- 'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf'),
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'),