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/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.5 */
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,36 +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
694
- for (var key in GATEWAY_DEFAULTS){
695
- if (opts[key] == undefined || opts[key] === '') opts[key] = GATEWAY_DEFAULTS[key];
696
- }
700
+ constructor(opts = {}) {
701
+ opts = Object.assign({}, GATEWAY_DEFAULTS, opts);
697
702
  var url = DEFAULT_URL;
698
703
  url.hostname = opts.hostname;
699
704
  url.port = opts.port;
@@ -709,13 +714,19 @@
709
714
  this.listener = {}; // set of callbacks that want to listen to incoming messages
710
715
  this.eventListeners = {}; // external listeners wanting to listen internal events
711
716
  this.queue = []; // incoming message queue
717
+ this.connected = false; // connection status
712
718
  this.debug = false; // debug info to be logged to console?
713
719
  this.aid = new AgentID((isBrowser ? 'WebGW-' : 'NodeGW-')+_guid(4)); // gateway agent name
714
720
  this.connector = this._createConnector(url);
715
721
  this._addGWCache(this);
716
722
  }
717
723
 
718
- /** @private */
724
+ /**
725
+ * Sends an event to all registered listeners of the given type.
726
+ * @private
727
+ * @param {string} type - type of event
728
+ * @param {Object|Message|string} val - value to be sent to the listeners
729
+ */
719
730
  _sendEvent(type, val) {
720
731
  if (Array.isArray(this.eventListeners[type])) {
721
732
  this.eventListeners[type].forEach(l => {
@@ -730,7 +741,11 @@
730
741
  }
731
742
  }
732
743
 
733
- /** @private */
744
+ /**
745
+ * @private
746
+ * @param {string} data - stringfied JSON data received from the master container to be processed
747
+ * @returns {void}
748
+ */
734
749
  _onMsgRx(data) {
735
750
  var obj;
736
751
  if (this.debug) console.log('< '+data);
@@ -747,6 +762,7 @@
747
762
  delete this.pending[obj.id];
748
763
  } else if (obj.action == 'send') {
749
764
  // incoming message from master
765
+ // @ts-ignore
750
766
  let msg = Message._deserialize(obj.message);
751
767
  if (!msg) return;
752
768
  this._sendEvent('rxmsg', msg);
@@ -807,7 +823,12 @@
807
823
  }
808
824
  }
809
825
 
810
- /** @private */
826
+ /**
827
+ * Sends a message out to the master container.
828
+ * @private
829
+ * @param {string|Object} s - JSON object (either stringified or not) to be sent to the master container
830
+ * @returns {boolean} - true if the message was sent successfully
831
+ */
811
832
  _msgTx(s) {
812
833
  if (typeof s != 'string' && !(s instanceof String)) s = JSON.stringify(s);
813
834
  if(this.debug) console.log('> '+s);
@@ -815,7 +836,11 @@
815
836
  return this.connector.write(s);
816
837
  }
817
838
 
818
- /** @private */
839
+ /**
840
+ * @private
841
+ * @param {Object} rq - request to be sent to the master container as a JSON object
842
+ * @returns {Promise<Object>} - a promise which returns the response from the master container
843
+ */
819
844
  _msgTxRx(rq) {
820
845
  rq.id = _guid(8);
821
846
  return new Promise(resolve => {
@@ -837,25 +862,32 @@
837
862
  });
838
863
  }
839
864
 
840
- /** @private */
865
+ /**
866
+ * @private
867
+ * @param {URL} url - URL object of the master container to connect to
868
+ * @returns {TCPConnector|WSConnector} - connector object to connect to the master container
869
+ */
841
870
  _createConnector(url){
842
871
  let conn;
843
872
  if (url.protocol.startsWith('ws')){
844
873
  conn = new WSConnector({
845
874
  'hostname':url.hostname,
846
- 'port':url.port,
875
+ 'port':parseInt(url.port),
847
876
  'pathname':url.pathname,
848
- 'keepAlive': this._keepAlive
877
+ 'keepAlive': this._keepAlive,
878
+ 'debug': this.debug
849
879
  });
850
880
  }else if (url.protocol.startsWith('tcp')){
851
- conn = new TCPconnector({
881
+ conn = new TCPConnector({
852
882
  'hostname':url.hostname,
853
- 'port':url.port,
854
- 'keepAlive': this._keepAlive
883
+ 'port':parseInt(url.port),
884
+ 'keepAlive': this._keepAlive,
885
+ 'debug': this.debug
855
886
  });
856
887
  } else return null;
857
888
  conn.setReadCallback(this._onMsgRx.bind(this));
858
889
  conn.addConnectionListener(state => {
890
+ this.connected = !!state;
859
891
  if (state == true){
860
892
  this.flush();
861
893
  this.connector.write('{"alive": true}');
@@ -866,7 +898,13 @@
866
898
  return conn;
867
899
  }
868
900
 
869
- /** @private */
901
+ /**
902
+ * Checks if the object is a constructor.
903
+ *
904
+ * @private
905
+ * @param {Object} value - an object to be checked if it is a constructor
906
+ * @returns {boolean} - if the object is a constructor
907
+ */
870
908
  _isConstructor(value) {
871
909
  try {
872
910
  new new Proxy(value, {construct() { return {}; }});
@@ -876,7 +914,13 @@
876
914
  }
877
915
  }
878
916
 
879
- /** @private */
917
+ /**
918
+ * Matches a message with a filter.
919
+ * @private
920
+ * @param {string|Object|function} filter - filter to be matched
921
+ * @param {Message} msg - message to be matched to the filter
922
+ * @returns {boolean} - true if the message matches the filter
923
+ */
880
924
  _matchMessage(filter, msg){
881
925
  if (typeof filter == 'string' || filter instanceof String) {
882
926
  return 'inReplyTo' in msg && msg.inReplyTo == filter;
@@ -896,18 +940,25 @@
896
940
  }
897
941
  }
898
942
 
899
- /** @private */
943
+ /**
944
+ * Gets the next message from the queue that matches the filter.
945
+ * @private
946
+ * @param {string|Object|function} filter - filter to be matched
947
+ */
900
948
  _getMessageFromQueue(filter) {
901
949
  if (!this.queue.length) return;
902
950
  if (!filter) return this.queue.shift();
903
-
904
951
  let matchedMsg = this.queue.find( msg => this._matchMessage(filter, msg));
905
952
  if (matchedMsg) this.queue.splice(this.queue.indexOf(matchedMsg), 1);
906
-
907
953
  return matchedMsg;
908
954
  }
909
955
 
910
- /** @private */
956
+ /**
957
+ * Gets a cached gateway object for the given URL (if it exists).
958
+ * @private
959
+ * @param {URL} url - URL object of the master container to connect to
960
+ * @returns {Gateway|void} - gateway object for the given URL
961
+ */
911
962
  _getGWCache(url){
912
963
  if (!gObj.fjage || !gObj.fjage.gateways) return null;
913
964
  var f = gObj.fjage.gateways.filter(g => g.connector.url.toString() == url.toString());
@@ -915,13 +966,21 @@
915
966
  return null;
916
967
  }
917
968
 
918
- /** @private */
969
+ /**
970
+ * Adds a gateway object to the cache if it doesn't already exist.
971
+ * @private
972
+ * @param {Gateway} gw - gateway object to be added to the cache
973
+ */
919
974
  _addGWCache(gw){
920
975
  if (!gObj.fjage || !gObj.fjage.gateways) return;
921
976
  gObj.fjage.gateways.push(gw);
922
977
  }
923
978
 
924
- /** @private */
979
+ /**
980
+ * Removes a gateway object from the cache if it exists.
981
+ * @private
982
+ * @param {Gateway} gw - gateway object to be removed from the cache
983
+ */
925
984
  _removeGWCache(gw){
926
985
  if (!gObj.fjage || !gObj.fjage.gateways) return;
927
986
  var index = gObj.fjage.gateways.indexOf(gw);
@@ -1009,7 +1068,7 @@
1009
1068
  /**
1010
1069
  * Gets the agent ID associated with the gateway.
1011
1070
  *
1012
- * @returns {string} - agent ID
1071
+ * @returns {AgentID} - agent ID
1013
1072
  */
1014
1073
  getAgentID() {
1015
1074
  return this.aid;
@@ -1029,7 +1088,7 @@
1029
1088
  * Returns an object representing the named topic.
1030
1089
  *
1031
1090
  * @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
1091
+ * @param {string} [topic2] - name of the topic if the topic param is an AgentID
1033
1092
  * @returns {AgentID} - object representing the topic
1034
1093
  */
1035
1094
  topic(topic, topic2) {
@@ -1050,6 +1109,7 @@
1050
1109
  if (!topic.isTopic()) topic = new AgentID(topic.getName() + '__ntf', true, this);
1051
1110
  this.subscriptions[topic.toJSON()] = true;
1052
1111
  this._update_watch();
1112
+ return true;
1053
1113
  }
1054
1114
 
1055
1115
  /**
@@ -1141,6 +1201,7 @@
1141
1201
  }
1142
1202
  this._sendEvent('txmsg', msg);
1143
1203
  let rq = JSON.stringify({ action: 'send', relay: true, message: '###MSG###' });
1204
+ // @ts-ignore
1144
1205
  rq = rq.replace('"###MSG###"', msg._serialize());
1145
1206
  return !!this._msgTx(rq);
1146
1207
  }
@@ -1158,9 +1219,9 @@
1158
1219
  * Sends a request and waits for a response. This method returns a {Promise} which resolves when a response
1159
1220
  * is received or if no response is received after the timeout.
1160
1221
  *
1161
- * @param {string} msg - message to send
1222
+ * @param {Message} msg - message to send
1162
1223
  * @param {number} [timeout=1000] - timeout in milliseconds
1163
- * @returns {Promise<?Message>} - a promise which resolves with the received response message, null on timeout
1224
+ * @returns {Promise<Message|void>} - a promise which resolves with the received response message, null on timeout
1164
1225
  */
1165
1226
  async request(msg, timeout=1000) {
1166
1227
  this.send(msg);
@@ -1171,10 +1232,10 @@
1171
1232
  * Returns a response message received by the gateway. This method returns a {Promise} which resolves when
1172
1233
  * a response is received or if no response is received after the timeout.
1173
1234
  *
1174
- * @param {function} [filter=] - original message to which a response is expected, or a MessageClass of the type
1235
+ * @param {function|Message|typeof Message} filter - original message to which a response is expected, or a MessageClass of the type
1175
1236
  * of message to match, or a closure to use to match against the message
1176
1237
  * @param {number} [timeout=0] - timeout in milliseconds
1177
- * @returns {Promise<?Message>} - received response message, null on timeout
1238
+ * @returns {Promise<Message|void>} - received response message, null on timeout
1178
1239
  */
1179
1240
  async receive(filter, timeout=0) {
1180
1241
  return new Promise(resolve => {
@@ -1229,8 +1290,8 @@
1229
1290
  /**
1230
1291
  * Creates a unqualified message class based on a fully qualified name.
1231
1292
  * @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
1293
+ * @param {typeof Message} [parent] - class of the parent MessageClass to inherit from
1294
+ * @constructs Message
1234
1295
  * @example
1235
1296
  * const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
1236
1297
  * let pReq = new ParameterReq()
@@ -1239,6 +1300,9 @@
1239
1300
  let sname = name.replace(/^.*\./, '');
1240
1301
  if (MessageClass[sname]) return MessageClass[sname];
1241
1302
  let cls = class extends parent {
1303
+ /**
1304
+ * @param {{ [x: string]: any; }} params
1305
+ */
1242
1306
  constructor(params) {
1243
1307
  super();
1244
1308
  this.__clazz__ = name;
@@ -1294,7 +1358,7 @@
1294
1358
  break;
1295
1359
  case '[J': // long array
1296
1360
  for (i = 0; i < len; i+=8)
1297
- rv.push(view.getInt64(i, littleEndian));
1361
+ rv.push(view.getBigInt64(i, littleEndian));
1298
1362
  break;
1299
1363
  case '[F': // float array
1300
1364
  for (i = 0; i < len; i+=4)
@@ -1329,6 +1393,8 @@
1329
1393
  ////// global
1330
1394
 
1331
1395
  const GATEWAY_DEFAULTS = {};
1396
+
1397
+ /** @type {Window & globalThis & Object} */
1332
1398
  let gObj = {};
1333
1399
  let DEFAULT_URL;
1334
1400
  if (isBrowser || isWebWorker){
@@ -1345,7 +1411,7 @@
1345
1411
  DEFAULT_URL = new URL('ws://localhost');
1346
1412
  // Enable caching of Gateways
1347
1413
  if (typeof gObj.fjage === 'undefined') gObj.fjage = {};
1348
- if (typeof gObj.fjage.gateways == 'undefined')gObj.fjage.gateways = [];
1414
+ if (typeof gObj.fjage.gateways == 'undefined') gObj.fjage.gateways = [];
1349
1415
  } else if (isJsDom || isNode){
1350
1416
  gObj = global;
1351
1417
  Object.assign(GATEWAY_DEFAULTS, {
@@ -1361,10 +1427,28 @@
1361
1427
  gObj.atob = a => Buffer.from(a, 'base64').toString('binary');
1362
1428
  }
1363
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
+ */
1364
1447
  const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
1365
1448
 
1366
1449
  const DatagramReq$1 = MessageClass('org.arl.unet.DatagramReq');
1367
1450
  const DatagramNtf$1 = MessageClass('org.arl.unet.DatagramNtf');
1451
+ const RxFrameNtf$1 = MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1);
1368
1452
  const BasebandSignal = MessageClass('org.arl.unet.bb.BasebandSignal');
1369
1453
 
1370
1454
  let UnetServices = {
@@ -1436,7 +1520,8 @@
1436
1520
 
1437
1521
  // phy
1438
1522
  'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
1439
- '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),
1440
1525
  'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq'),
1441
1526
  'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
1442
1527
  'BadRangeNtf' : MessageClass('org.arl.unet.phy.BadRangeNtf'),