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