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