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/esm/unet.js CHANGED
@@ -1,6 +1,6 @@
1
- /* unet.js v3.1.5 2024-09-13T08:21:33.661Z */
1
+ /* unet.js v3.2.1 2025-01-31T16:55:08.538Z */
2
2
 
3
- /* fjage.js v1.12.2 */
3
+ /* fjage.js v1.13.7 */
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,33 +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
696
+ constructor(opts = {}) {
697
+ // Similar to Object.assign but also overwrites `undefined` and empty strings with defaults
690
698
  for (var key in GATEWAY_DEFAULTS){
691
699
  if (opts[key] == undefined || opts[key] === '') opts[key] = GATEWAY_DEFAULTS[key];
692
700
  }
@@ -705,13 +713,19 @@ class Gateway {
705
713
  this.listener = {}; // set of callbacks that want to listen to incoming messages
706
714
  this.eventListeners = {}; // external listeners wanting to listen internal events
707
715
  this.queue = []; // incoming message queue
716
+ this.connected = false; // connection status
708
717
  this.debug = false; // debug info to be logged to console?
709
- this.aid = new AgentID((isBrowser ? 'WebGW-' : 'NodeGW-')+_guid(4)); // gateway agent name
718
+ this.aid = new AgentID('gateway-'+_guid(4)); // gateway agent name
710
719
  this.connector = this._createConnector(url);
711
720
  this._addGWCache(this);
712
721
  }
713
722
 
714
- /** @private */
723
+ /**
724
+ * Sends an event to all registered listeners of the given type.
725
+ * @private
726
+ * @param {string} type - type of event
727
+ * @param {Object|Message|string} val - value to be sent to the listeners
728
+ */
715
729
  _sendEvent(type, val) {
716
730
  if (Array.isArray(this.eventListeners[type])) {
717
731
  this.eventListeners[type].forEach(l => {
@@ -726,7 +740,11 @@ class Gateway {
726
740
  }
727
741
  }
728
742
 
729
- /** @private */
743
+ /**
744
+ * @private
745
+ * @param {string} data - stringfied JSON data received from the master container to be processed
746
+ * @returns {void}
747
+ */
730
748
  _onMsgRx(data) {
731
749
  var obj;
732
750
  if (this.debug) console.log('< '+data);
@@ -743,6 +761,7 @@ class Gateway {
743
761
  delete this.pending[obj.id];
744
762
  } else if (obj.action == 'send') {
745
763
  // incoming message from master
764
+ // @ts-ignore
746
765
  let msg = Message._deserialize(obj.message);
747
766
  if (!msg) return;
748
767
  this._sendEvent('rxmsg', msg);
@@ -803,7 +822,12 @@ class Gateway {
803
822
  }
804
823
  }
805
824
 
806
- /** @private */
825
+ /**
826
+ * Sends a message out to the master container.
827
+ * @private
828
+ * @param {string|Object} s - JSON object (either stringified or not) to be sent to the master container
829
+ * @returns {boolean} - true if the message was sent successfully
830
+ */
807
831
  _msgTx(s) {
808
832
  if (typeof s != 'string' && !(s instanceof String)) s = JSON.stringify(s);
809
833
  if(this.debug) console.log('> '+s);
@@ -811,7 +835,11 @@ class Gateway {
811
835
  return this.connector.write(s);
812
836
  }
813
837
 
814
- /** @private */
838
+ /**
839
+ * @private
840
+ * @param {Object} rq - request to be sent to the master container as a JSON object
841
+ * @returns {Promise<Object>} - a promise which returns the response from the master container
842
+ */
815
843
  _msgTxRx(rq) {
816
844
  rq.id = _guid(8);
817
845
  return new Promise(resolve => {
@@ -833,25 +861,32 @@ class Gateway {
833
861
  });
834
862
  }
835
863
 
836
- /** @private */
864
+ /**
865
+ * @private
866
+ * @param {URL} url - URL object of the master container to connect to
867
+ * @returns {TCPConnector|WSConnector} - connector object to connect to the master container
868
+ */
837
869
  _createConnector(url){
838
870
  let conn;
839
871
  if (url.protocol.startsWith('ws')){
840
872
  conn = new WSConnector({
841
873
  'hostname':url.hostname,
842
- 'port':url.port,
874
+ 'port':parseInt(url.port),
843
875
  'pathname':url.pathname,
844
- 'keepAlive': this._keepAlive
876
+ 'keepAlive': this._keepAlive,
877
+ 'debug': this.debug
845
878
  });
846
879
  }else if (url.protocol.startsWith('tcp')){
847
- conn = new TCPconnector({
880
+ conn = new TCPConnector({
848
881
  'hostname':url.hostname,
849
- 'port':url.port,
850
- 'keepAlive': this._keepAlive
882
+ 'port':parseInt(url.port),
883
+ 'keepAlive': this._keepAlive,
884
+ 'debug': this.debug
851
885
  });
852
886
  } else return null;
853
887
  conn.setReadCallback(this._onMsgRx.bind(this));
854
888
  conn.addConnectionListener(state => {
889
+ this.connected = !!state;
855
890
  if (state == true){
856
891
  this.flush();
857
892
  this.connector.write('{"alive": true}');
@@ -862,7 +897,13 @@ class Gateway {
862
897
  return conn;
863
898
  }
864
899
 
865
- /** @private */
900
+ /**
901
+ * Checks if the object is a constructor.
902
+ *
903
+ * @private
904
+ * @param {Object} value - an object to be checked if it is a constructor
905
+ * @returns {boolean} - if the object is a constructor
906
+ */
866
907
  _isConstructor(value) {
867
908
  try {
868
909
  new new Proxy(value, {construct() { return {}; }});
@@ -872,7 +913,13 @@ class Gateway {
872
913
  }
873
914
  }
874
915
 
875
- /** @private */
916
+ /**
917
+ * Matches a message with a filter.
918
+ * @private
919
+ * @param {string|Object|function} filter - filter to be matched
920
+ * @param {Message} msg - message to be matched to the filter
921
+ * @returns {boolean} - true if the message matches the filter
922
+ */
876
923
  _matchMessage(filter, msg){
877
924
  if (typeof filter == 'string' || filter instanceof String) {
878
925
  return 'inReplyTo' in msg && msg.inReplyTo == filter;
@@ -892,18 +939,25 @@ class Gateway {
892
939
  }
893
940
  }
894
941
 
895
- /** @private */
942
+ /**
943
+ * Gets the next message from the queue that matches the filter.
944
+ * @private
945
+ * @param {string|Object|function} filter - filter to be matched
946
+ */
896
947
  _getMessageFromQueue(filter) {
897
948
  if (!this.queue.length) return;
898
949
  if (!filter) return this.queue.shift();
899
-
900
950
  let matchedMsg = this.queue.find( msg => this._matchMessage(filter, msg));
901
951
  if (matchedMsg) this.queue.splice(this.queue.indexOf(matchedMsg), 1);
902
-
903
952
  return matchedMsg;
904
953
  }
905
954
 
906
- /** @private */
955
+ /**
956
+ * Gets a cached gateway object for the given URL (if it exists).
957
+ * @private
958
+ * @param {URL} url - URL object of the master container to connect to
959
+ * @returns {Gateway|void} - gateway object for the given URL
960
+ */
907
961
  _getGWCache(url){
908
962
  if (!gObj.fjage || !gObj.fjage.gateways) return null;
909
963
  var f = gObj.fjage.gateways.filter(g => g.connector.url.toString() == url.toString());
@@ -911,13 +965,21 @@ class Gateway {
911
965
  return null;
912
966
  }
913
967
 
914
- /** @private */
968
+ /**
969
+ * Adds a gateway object to the cache if it doesn't already exist.
970
+ * @private
971
+ * @param {Gateway} gw - gateway object to be added to the cache
972
+ */
915
973
  _addGWCache(gw){
916
974
  if (!gObj.fjage || !gObj.fjage.gateways) return;
917
975
  gObj.fjage.gateways.push(gw);
918
976
  }
919
977
 
920
- /** @private */
978
+ /**
979
+ * Removes a gateway object from the cache if it exists.
980
+ * @private
981
+ * @param {Gateway} gw - gateway object to be removed from the cache
982
+ */
921
983
  _removeGWCache(gw){
922
984
  if (!gObj.fjage || !gObj.fjage.gateways) return;
923
985
  var index = gObj.fjage.gateways.indexOf(gw);
@@ -1005,7 +1067,7 @@ class Gateway {
1005
1067
  /**
1006
1068
  * Gets the agent ID associated with the gateway.
1007
1069
  *
1008
- * @returns {string} - agent ID
1070
+ * @returns {AgentID} - agent ID
1009
1071
  */
1010
1072
  getAgentID() {
1011
1073
  return this.aid;
@@ -1025,7 +1087,7 @@ class Gateway {
1025
1087
  * Returns an object representing the named topic.
1026
1088
  *
1027
1089
  * @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
1090
+ * @param {string} [topic2] - name of the topic if the topic param is an AgentID
1029
1091
  * @returns {AgentID} - object representing the topic
1030
1092
  */
1031
1093
  topic(topic, topic2) {
@@ -1046,6 +1108,7 @@ class Gateway {
1046
1108
  if (!topic.isTopic()) topic = new AgentID(topic.getName() + '__ntf', true, this);
1047
1109
  this.subscriptions[topic.toJSON()] = true;
1048
1110
  this._update_watch();
1111
+ return true;
1049
1112
  }
1050
1113
 
1051
1114
  /**
@@ -1137,6 +1200,7 @@ class Gateway {
1137
1200
  }
1138
1201
  this._sendEvent('txmsg', msg);
1139
1202
  let rq = JSON.stringify({ action: 'send', relay: true, message: '###MSG###' });
1203
+ // @ts-ignore
1140
1204
  rq = rq.replace('"###MSG###"', msg._serialize());
1141
1205
  return !!this._msgTx(rq);
1142
1206
  }
@@ -1154,9 +1218,9 @@ class Gateway {
1154
1218
  * Sends a request and waits for a response. This method returns a {Promise} which resolves when a response
1155
1219
  * is received or if no response is received after the timeout.
1156
1220
  *
1157
- * @param {string} msg - message to send
1221
+ * @param {Message} msg - message to send
1158
1222
  * @param {number} [timeout=1000] - timeout in milliseconds
1159
- * @returns {Promise<?Message>} - a promise which resolves with the received response message, null on timeout
1223
+ * @returns {Promise<Message|void>} - a promise which resolves with the received response message, null on timeout
1160
1224
  */
1161
1225
  async request(msg, timeout=1000) {
1162
1226
  this.send(msg);
@@ -1167,10 +1231,10 @@ class Gateway {
1167
1231
  * Returns a response message received by the gateway. This method returns a {Promise} which resolves when
1168
1232
  * a response is received or if no response is received after the timeout.
1169
1233
  *
1170
- * @param {function} [filter=] - original message to which a response is expected, or a MessageClass of the type
1234
+ * @param {function|Message|typeof Message} filter - original message to which a response is expected, or a MessageClass of the type
1171
1235
  * of message to match, or a closure to use to match against the message
1172
1236
  * @param {number} [timeout=0] - timeout in milliseconds
1173
- * @returns {Promise<?Message>} - received response message, null on timeout
1237
+ * @returns {Promise<Message|void>} - received response message, null on timeout
1174
1238
  */
1175
1239
  async receive(filter, timeout=0) {
1176
1240
  return new Promise(resolve => {
@@ -1225,8 +1289,8 @@ const Services = {
1225
1289
  /**
1226
1290
  * Creates a unqualified message class based on a fully qualified name.
1227
1291
  * @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
1292
+ * @param {typeof Message} [parent] - class of the parent MessageClass to inherit from
1293
+ * @constructs Message
1230
1294
  * @example
1231
1295
  * const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
1232
1296
  * let pReq = new ParameterReq()
@@ -1235,6 +1299,9 @@ function MessageClass(name, parent=Message) {
1235
1299
  let sname = name.replace(/^.*\./, '');
1236
1300
  if (MessageClass[sname]) return MessageClass[sname];
1237
1301
  let cls = class extends parent {
1302
+ /**
1303
+ * @param {{ [x: string]: any; }} params
1304
+ */
1238
1305
  constructor(params) {
1239
1306
  super();
1240
1307
  this.__clazz__ = name;
@@ -1244,6 +1311,7 @@ function MessageClass(name, parent=Message) {
1244
1311
  this[k] = params[k];
1245
1312
  }
1246
1313
  }
1314
+ if (name.endsWith('Req')) this.perf = Performative.REQUEST;
1247
1315
  }
1248
1316
  };
1249
1317
  cls.__clazz__ = name;
@@ -1290,7 +1358,7 @@ function _b64toArray(base64, dtype, littleEndian=true) {
1290
1358
  break;
1291
1359
  case '[J': // long array
1292
1360
  for (i = 0; i < len; i+=8)
1293
- rv.push(view.getInt64(i, littleEndian));
1361
+ rv.push(view.getBigInt64(i, littleEndian));
1294
1362
  break;
1295
1363
  case '[F': // float array
1296
1364
  for (i = 0; i < len; i+=4)
@@ -1325,6 +1393,8 @@ function _decodeBase64(k, d) {
1325
1393
  ////// global
1326
1394
 
1327
1395
  const GATEWAY_DEFAULTS = {};
1396
+
1397
+ /** @type {Window & globalThis & Object} */
1328
1398
  let gObj = {};
1329
1399
  let DEFAULT_URL;
1330
1400
  if (isBrowser || isWebWorker){
@@ -1341,7 +1411,7 @@ if (isBrowser || isWebWorker){
1341
1411
  DEFAULT_URL = new URL('ws://localhost');
1342
1412
  // Enable caching of Gateways
1343
1413
  if (typeof gObj.fjage === 'undefined') gObj.fjage = {};
1344
- if (typeof gObj.fjage.gateways == 'undefined')gObj.fjage.gateways = [];
1414
+ if (typeof gObj.fjage.gateways == 'undefined') gObj.fjage.gateways = [];
1345
1415
  } else if (isJsDom || isNode){
1346
1416
  gObj = global;
1347
1417
  Object.assign(GATEWAY_DEFAULTS, {
@@ -1357,10 +1427,28 @@ if (isBrowser || isWebWorker){
1357
1427
  gObj.atob = a => Buffer.from(a, 'base64').toString('binary');
1358
1428
  }
1359
1429
 
1430
+ /**
1431
+ * @typedef {Object} ParameterReq.Entry
1432
+ * @property {string} param - parameter name
1433
+ * @property {Object} value - parameter value
1434
+ * @exports ParameterReq.Entry
1435
+ */
1436
+
1437
+
1438
+ /**
1439
+ * A message that requests one or more parameters of an agent.
1440
+ * @typedef {Message} ParameterReq
1441
+ * @property {string} param - parameters name to be get/set if only a single parameter is to be get/set
1442
+ * @property {Object} value - parameters value to be set if only a single parameter is to be set
1443
+ * @property {Array<ParameterReq.Entry>} requests - a list of multiple parameters to be get/set
1444
+ * @property {number} [index=-1] - index of parameter(s) to be set
1445
+ * @exports ParameterReq
1446
+ */
1360
1447
  const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
1361
1448
 
1362
1449
  const DatagramReq$1 = MessageClass('org.arl.unet.DatagramReq');
1363
1450
  const DatagramNtf$1 = MessageClass('org.arl.unet.DatagramNtf');
1451
+ const RxFrameNtf$1 = MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1);
1364
1452
  const BasebandSignal = MessageClass('org.arl.unet.bb.BasebandSignal');
1365
1453
 
1366
1454
  let UnetServices = {
@@ -1432,7 +1520,8 @@ let UnetMessages = {
1432
1520
 
1433
1521
  // phy
1434
1522
  'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
1435
- 'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf'),
1523
+ 'RxSWiG1FrameNtf' : MessageClass('org.arl.unet.phy.RxSWiG1FrameNtf', RxFrameNtf$1),
1524
+ 'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf', RxFrameNtf$1),
1436
1525
  'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq'),
1437
1526
  'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
1438
1527
  'BadRangeNtf' : MessageClass('org.arl.unet.phy.BadRangeNtf'),