unetjs 1.0.0 → 2.0.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 v1.0.0 2021-07-07T04:11:04.914Z */
1
+ /* unet.js v2.0.0 2022-05-18T02:36:38.084Z */
2
2
 
3
- /* fjage.js v1.9.1-rc5 2021-07-07T04:07:53.061Z */
3
+ /* fjage.js v1.9.1-rc6 */
4
4
 
5
5
  /* global window self */
6
6
 
@@ -1271,6 +1271,8 @@ let UnetServices = {
1271
1271
  'TRANSPORT': 'org.arl.unet.Services.TRANSPORT',
1272
1272
  'REMOTE': 'org.arl.unet.Services.REMOTE',
1273
1273
  'STATE_MANAGER': 'org.arl.unet.Services.STATE_MANAGER',
1274
+ 'DEVICE_INFO': 'org.arl.unet.Services.DEVICE_INFO',
1275
+ 'DOA': 'org.arl.unet.Services.DOA'
1274
1276
  };
1275
1277
 
1276
1278
  Object.assign(Services, UnetServices);
@@ -1299,100 +1301,361 @@ let Protocol = {
1299
1301
  */
1300
1302
  let UnetMessages = {
1301
1303
  // unet
1302
- 'TestReportNtf' : MessageClass('org.arl.unet.TestReportNtf'),
1303
- 'AbnormalTerminationNtf' : MessageClass('org.arl.unet.AbnormalTerminationNtf'),
1304
- 'CapabilityListRsp' : MessageClass('org.arl.unet.CapabilityListRsp'),
1305
- 'CapabilityReq' : MessageClass('org.arl.unet.CapabilityReq'),
1306
- 'ClearReq' : MessageClass('org.arl.unet.ClearReq'),
1307
- 'DatagramCancelReq' : MessageClass('org.arl.unet.DatagramCancelReq'),
1308
- 'DatagramDeliveryNtf' : MessageClass('org.arl.unet.DatagramDeliveryNtf'),
1309
- 'DatagramFailureNtf' : MessageClass('org.arl.unet.DatagramFailureNtf'),
1310
- 'DatagramNtf' : MessageClass('org.arl.unet.DatagramNtf'),
1311
- 'DatagramProgressNtf' : MessageClass('org.arl.unet.DatagramProgressNtf'),
1312
- 'DatagramReq' : MessageClass('org.arl.unet.DatagramReq'),
1313
- 'ParamChangeNtf' : MessageClass('org.arl.unet.ParamChangeNtf'),
1314
- 'RefuseRsp' : MessageClass('org.arl.unet.RefuseRsp'),
1315
- 'FailureNtf' : MessageClass('org.arl.unet.FailureNtf'),
1304
+ 'TestReportNtf' : MessageClass('org.arl.unet.TestReportNtf'),
1305
+ 'AbnormalTerminationNtf' : MessageClass('org.arl.unet.AbnormalTerminationNtf'),
1306
+ 'CapabilityListRsp' : MessageClass('org.arl.unet.CapabilityListRsp'),
1307
+ 'CapabilityReq' : MessageClass('org.arl.unet.CapabilityReq'),
1308
+ 'ClearReq' : MessageClass('org.arl.unet.ClearReq'),
1309
+ 'DatagramCancelReq' : MessageClass('org.arl.unet.DatagramCancelReq'),
1310
+ 'DatagramDeliveryNtf' : MessageClass('org.arl.unet.DatagramDeliveryNtf'),
1311
+ 'DatagramFailureNtf' : MessageClass('org.arl.unet.DatagramFailureNtf'),
1312
+ 'DatagramNtf' : MessageClass('org.arl.unet.DatagramNtf'),
1313
+ 'DatagramProgressNtf' : MessageClass('org.arl.unet.DatagramProgressNtf'),
1314
+ 'DatagramReq' : MessageClass('org.arl.unet.DatagramReq'),
1315
+ 'ParamChangeNtf' : MessageClass('org.arl.unet.ParamChangeNtf'),
1316
+ 'RefuseRsp' : MessageClass('org.arl.unet.RefuseRsp'),
1317
+ 'FailureNtf' : MessageClass('org.arl.unet.FailureNtf'),
1316
1318
 
1317
1319
  // net
1318
- 'DatagramTraceReq' : MessageClass('org.arl.unet.net.DatagramTraceReq'),
1319
- 'RouteDiscoveryReq' : MessageClass('org.arl.unet.net.RouteDiscoveryReq'),
1320
- 'RouteTraceReq' : MessageClass('org.arl.unet.net.RouteTraceReq'),
1321
- 'RouteDiscoveryNtf' : MessageClass('org.arl.unet.net.RouteDiscoveryNtf'),
1322
- 'RouteTraceNtf' : MessageClass('org.arl.unet.net.RouteTraceNtf'),
1320
+ 'DatagramTraceReq' : MessageClass('org.arl.unet.net.DatagramTraceReq'),
1321
+ 'RouteDiscoveryReq' : MessageClass('org.arl.unet.net.RouteDiscoveryReq'),
1322
+ 'RouteTraceReq' : MessageClass('org.arl.unet.net.RouteTraceReq'),
1323
+ 'RouteDiscoveryNtf' : MessageClass('org.arl.unet.net.RouteDiscoveryNtf'),
1324
+ 'RouteTraceNtf' : MessageClass('org.arl.unet.net.RouteTraceNtf'),
1323
1325
 
1324
1326
  // phy
1325
- 'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
1326
- 'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf'),
1327
- 'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq'),
1328
- 'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
1327
+ 'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
1328
+ 'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf'),
1329
+ 'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq'),
1330
+ 'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
1329
1331
  'BadRangeNtf' : MessageClass('org.arl.unet.phy.BadRangeNtf'),
1330
- 'ClearSyncReq' : MessageClass('org.arl.unet.phy.ClearSyncReq'),
1331
- 'CollisionNtf' : MessageClass('org.arl.unet.phy.CollisionNtf'),
1332
- 'RxFrameNtf' : MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1),
1333
- 'RxFrameStartNtf' : MessageClass('org.arl.unet.phy.RxFrameStartNtf'),
1334
- 'SyncInfoReq' : MessageClass('org.arl.unet.phy.SyncInfoReq'),
1335
- 'SyncInfoRsp' : MessageClass('org.arl.unet.phy.SyncInfoRsp'),
1336
- 'TxFrameNtf' : MessageClass('org.arl.unet.phy.TxFrameNtf'),
1337
- 'TxFrameReq' : MessageClass('org.arl.unet.phy.TxFrameReq', DatagramReq$1),
1338
- 'TxFrameStartNtf' : MessageClass('org.arl.unet.phy.TxFrameStartNtf'),
1339
- 'TxRawFrameReq' : MessageClass('org.arl.unet.phy.TxRawFrameReq'),
1332
+ 'ClearSyncReq' : MessageClass('org.arl.unet.phy.ClearSyncReq'),
1333
+ 'CollisionNtf' : MessageClass('org.arl.unet.phy.CollisionNtf'),
1334
+ 'RxFrameNtf' : MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1),
1335
+ 'RxFrameStartNtf' : MessageClass('org.arl.unet.phy.RxFrameStartNtf'),
1336
+ 'SyncInfoReq' : MessageClass('org.arl.unet.phy.SyncInfoReq'),
1337
+ 'SyncInfoRsp' : MessageClass('org.arl.unet.phy.SyncInfoRsp'),
1338
+ 'TxFrameNtf' : MessageClass('org.arl.unet.phy.TxFrameNtf'),
1339
+ 'TxFrameReq' : MessageClass('org.arl.unet.phy.TxFrameReq', DatagramReq$1),
1340
+ 'TxFrameStartNtf' : MessageClass('org.arl.unet.phy.TxFrameStartNtf'),
1341
+ 'TxRawFrameReq' : MessageClass('org.arl.unet.phy.TxRawFrameReq'),
1340
1342
 
1341
1343
  // addr
1342
- 'AddressAllocReq' : MessageClass('org.arl.unet.addr.AddressAllocReq'),
1343
- 'AddressAllocRsp' : MessageClass('org.arl.unet.addr.AddressAllocRsp'),
1344
- 'AddressResolutionReq' : MessageClass('org.arl.unet.addr.AddressResolutionReq'),
1345
- 'AddressResolutionRsp' : MessageClass('org.arl.unet.addr.AddressResolutionRsp'),
1344
+ 'AddressAllocReq' : MessageClass('org.arl.unet.addr.AddressAllocReq'),
1345
+ 'AddressAllocRsp' : MessageClass('org.arl.unet.addr.AddressAllocRsp'),
1346
+ 'AddressResolutionReq' : MessageClass('org.arl.unet.addr.AddressResolutionReq'),
1347
+ 'AddressResolutionRsp' : MessageClass('org.arl.unet.addr.AddressResolutionRsp'),
1346
1348
 
1347
1349
  // bb
1348
- 'BasebandSignal' : MessageClass('org.arl.unet.bb.BasebandSignal'),
1349
- 'RecordBasebandSignalReq' : MessageClass('org.arl.unet.bb.RecordBasebandSignalReq'),
1350
- 'RxBasebandSignalNtf' : MessageClass('org.arl.unet.bb.RxBasebandSignalNtf', BasebandSignal),
1351
- 'TxBasebandSignalReq' : MessageClass('org.arl.unet.bb.TxBasebandSignalReq', BasebandSignal),
1350
+ 'BasebandSignal' : MessageClass('org.arl.unet.bb.BasebandSignal'),
1351
+ 'RecordBasebandSignalReq' : MessageClass('org.arl.unet.bb.RecordBasebandSignalReq'),
1352
+ 'RxBasebandSignalNtf' : MessageClass('org.arl.unet.bb.RxBasebandSignalNtf', BasebandSignal),
1353
+ 'TxBasebandSignalReq' : MessageClass('org.arl.unet.bb.TxBasebandSignalReq', BasebandSignal),
1352
1354
 
1353
1355
  // link
1354
- 'LinkStatusNtf' : MessageClass('org.arl.unet.link.LinkStatusNtf'),
1356
+ 'LinkStatusNtf' : MessageClass('org.arl.unet.link.LinkStatusNtf'),
1355
1357
 
1356
1358
  // localization
1357
- 'RangeNtf' : MessageClass('org.arl.unet.localization.RangeNtf'),
1358
- 'RangeReq' : MessageClass('org.arl.unet.localization.RangeReq'),
1359
- 'BeaconReq' : MessageClass('org.arl.unet.localization.BeaconReq'),
1360
- 'RespondReq' : MessageClass('org.arl.unet.localization.RespondReq'),
1361
- 'InterrogationNtf' : MessageClass('org.arl.unet.localization.InterrogationNtf'),
1359
+ 'RangeNtf' : MessageClass('org.arl.unet.localization.RangeNtf'),
1360
+ 'RangeReq' : MessageClass('org.arl.unet.localization.RangeReq'),
1361
+ 'BeaconReq' : MessageClass('org.arl.unet.localization.BeaconReq'),
1362
+ 'RespondReq' : MessageClass('org.arl.unet.localization.RespondReq'),
1363
+ 'InterrogationNtf' : MessageClass('org.arl.unet.localization.InterrogationNtf'),
1362
1364
 
1363
1365
 
1364
1366
  // mac
1365
- 'ReservationAcceptReq' : MessageClass('org.arl.unet.mac.ReservationAcceptReq'),
1366
- 'ReservationCancelReq' : MessageClass('org.arl.unet.mac.ReservationCancelReq'),
1367
- 'ReservationReq' : MessageClass('org.arl.unet.mac.ReservationReq'),
1368
- 'ReservationRsp' : MessageClass('org.arl.unet.mac.ReservationRsp'),
1369
- 'ReservationStatusNtf' : MessageClass('org.arl.unet.mac.ReservationStatusNtf'),
1370
- 'RxAckNtf' : MessageClass('org.arl.unet.mac.RxAckNtf'),
1371
- 'TxAckReq' : MessageClass('org.arl.unet.mac.TxAckReq'),
1367
+ 'ReservationAcceptReq' : MessageClass('org.arl.unet.mac.ReservationAcceptReq'),
1368
+ 'ReservationCancelReq' : MessageClass('org.arl.unet.mac.ReservationCancelReq'),
1369
+ 'ReservationReq' : MessageClass('org.arl.unet.mac.ReservationReq'),
1370
+ 'ReservationRsp' : MessageClass('org.arl.unet.mac.ReservationRsp'),
1371
+ 'ReservationStatusNtf' : MessageClass('org.arl.unet.mac.ReservationStatusNtf'),
1372
+ 'RxAckNtf' : MessageClass('org.arl.unet.mac.RxAckNtf'),
1373
+ 'TxAckReq' : MessageClass('org.arl.unet.mac.TxAckReq'),
1372
1374
 
1373
1375
 
1374
1376
  // remote
1375
- 'RemoteExecReq' : MessageClass('org.arl.unet.remote.RemoteExecReq'),
1376
- 'RemoteFailureNtf' : MessageClass('org.arl.unet.remote.RemoteFailureNtf'),
1377
- 'RemoteFileGetReq' : MessageClass('org.arl.unet.remote.RemoteFileGetReq'),
1378
- 'RemoteFileNtf' : MessageClass('org.arl.unet.remote.RemoteFileNtf'),
1379
- 'RemoteFilePutReq' : MessageClass('org.arl.unet.remote.RemoteFilePutReq'),
1380
- 'RemoteSuccessNtf' : MessageClass('org.arl.unet.remote.RemoteSuccessNtf'),
1381
- 'RemoteTextNtf' : MessageClass('org.arl.unet.remote.RemoteTextNtf'),
1382
- 'RemoteTextReq' : MessageClass('org.arl.unet.remote.RemoteTextReq'),
1377
+ 'RemoteExecReq' : MessageClass('org.arl.unet.remote.RemoteExecReq'),
1378
+ 'RemoteFailureNtf' : MessageClass('org.arl.unet.remote.RemoteFailureNtf'),
1379
+ 'RemoteFileGetReq' : MessageClass('org.arl.unet.remote.RemoteFileGetReq'),
1380
+ 'RemoteFileNtf' : MessageClass('org.arl.unet.remote.RemoteFileNtf'),
1381
+ 'RemoteFilePutReq' : MessageClass('org.arl.unet.remote.RemoteFilePutReq'),
1382
+ 'RemoteSuccessNtf' : MessageClass('org.arl.unet.remote.RemoteSuccessNtf'),
1383
+ 'RemoteTextNtf' : MessageClass('org.arl.unet.remote.RemoteTextNtf'),
1384
+ 'RemoteTextReq' : MessageClass('org.arl.unet.remote.RemoteTextReq'),
1383
1385
 
1384
1386
  // scheduler
1385
- 'AddScheduledSleepReq' : MessageClass('org.arl.unet.scheduler.AddScheduledSleepReq'),
1386
- 'GetSleepScheduleReq' : MessageClass('org.arl.unet.scheduler.GetSleepScheduleReq'),
1387
- 'RemoveScheduledSleepReq' : MessageClass('org.arl.unet.scheduler.RemoveScheduledSleepReq'),
1388
- 'SleepScheduleRsp' : MessageClass('org.arl.unet.scheduler.SleepScheduleRsp'),
1389
- 'WakeFromSleepNtf' : MessageClass('org.arl.unet.scheduler.WakeFromSleepNtf'),
1387
+ 'AddScheduledSleepReq' : MessageClass('org.arl.unet.scheduler.AddScheduledSleepReq'),
1388
+ 'GetSleepScheduleReq' : MessageClass('org.arl.unet.scheduler.GetSleepScheduleReq'),
1389
+ 'RemoveScheduledSleepReq' : MessageClass('org.arl.unet.scheduler.RemoveScheduledSleepReq'),
1390
+ 'SleepScheduleRsp' : MessageClass('org.arl.unet.scheduler.SleepScheduleRsp'),
1391
+ 'WakeFromSleepNtf' : MessageClass('org.arl.unet.scheduler.WakeFromSleepNtf'),
1390
1392
 
1391
1393
  // state
1392
- 'ClearStateReq' : MessageClass('org.arl.unet.state.ClearStateReq'),
1394
+ 'ClearStateReq' : MessageClass('org.arl.unet.state.ClearStateReq'),
1393
1395
  'SaveStateReq' : MessageClass('org.arl.unet.state.SaveStateReq')
1394
1396
  };
1395
1397
 
1398
+ /**
1399
+ * Convert coordinates from a local coordinates to GPS coordinate
1400
+ * @param {Array} origin - Local coordinate system's origin as `[latitude, longitude]`
1401
+ * @param {Number} x - X coordinate of the local coordinate to be converted
1402
+ * @param {Number} y - Y coordinate of the local coordinate to be converted
1403
+ * @returns {Array} - GPS coordinates (in decimal degrees) as `[latitude, longitude]`
1404
+ */
1405
+
1406
+ function toGps(origin, x, y) {
1407
+ let coords = [] ;
1408
+ let [xScale,yScale] = _initConv(origin[0]);
1409
+ coords[1] = x/xScale + origin[1];
1410
+ coords[0] = y/yScale + origin[0];
1411
+ return coords;
1412
+ }
1413
+
1414
+ /**
1415
+ * Convert coordinates from a GPS coordinates to local coordinate
1416
+ * @param {Array} origin - Local coordinate system's origin as `[latitude, longitude]`
1417
+ * @param {Number} lat - Latitude of the GPS coordinate to be converted
1418
+ * @param {Number} lon - Longitude of the GPS coordinate to be converted
1419
+ * @returns {Array} - GPS coordinates (in decimal degrees) as `[latitude, longitude]`
1420
+ */
1421
+ function toLocal(origin, lat, lon) {
1422
+ let pos = [];
1423
+ let [xScale,yScale] = _initConv(origin[0]);
1424
+ pos[0] = (lon-origin[1]) * xScale;
1425
+ pos[1] = (lat-origin[0]) * yScale;
1426
+ return pos;
1427
+ }
1428
+
1429
+ function _initConv(lat){
1430
+ let rlat = lat * Math.PI/180;
1431
+ let yScale = 111132.92 - 559.82*Math.cos(2*rlat) + 1.175*Math.cos(4*rlat) - 0.0023*Math.cos(6*rlat);
1432
+ let xScale = 111412.84*Math.cos(rlat) - 93.5*Math.cos(3*rlat) + 0.118*Math.cos(5*rlat);
1433
+ return [xScale, yScale];
1434
+ }
1435
+
1436
+ /**
1437
+ * A message which requests the transmission of the datagram from the Unet
1438
+ *
1439
+ * @typedef {Message} DatagramReq
1440
+ * @property {number[]} data - data as an Array of bytes
1441
+ * @property {number} from - from/source node address
1442
+ * @property {number} to - to/destination node address
1443
+ * @property {number} protocol - protocol number to be used to send this Datagram
1444
+ * @property {boolean} reliability - true if Datagram should be reliable, false if unreliable
1445
+ * @property {number} ttl - time-to-live for the datagram. Time-to-live is advisory, and an agent may choose it ignore it
1446
+ */
1447
+
1448
+ /**
1449
+ * Notification of received datagram message received by the Unet node.
1450
+ *
1451
+ * @typedef {Message} DatagramNtf
1452
+ * @property {number[]} data - data as an Array of bytes
1453
+ * @property {number} from - from/source node address
1454
+ * @property {number} to - to/destination node address
1455
+ * @property {number} protocol - protocol number to be used to send this Datagram
1456
+ * @property {number} ttl - time-to-live for the datagram. Time-to-live is advisory, and an agent may choose it ignore it
1457
+ */
1458
+
1459
+ /**
1460
+ * An identifier for an agent or a topic.
1461
+ * @external AgentID
1462
+ * @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
1463
+ */
1464
+
1465
+ /**
1466
+ * Services supported by fjage agents.
1467
+ * @external Services
1468
+ * @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
1469
+ */
1470
+
1471
+ /**
1472
+ * An action represented by a message.
1473
+ * @external Performative
1474
+ * @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
1475
+ */
1476
+
1477
+ /**
1478
+ * Function to creates a unqualified message class based on a fully qualified name.
1479
+ * @external MessageClass
1480
+ * @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
1481
+ */
1482
+
1483
+ /**
1484
+ * A caching CachingAgentID which caches Agent parameters locally.
1485
+ *
1486
+ * @class
1487
+ * @extends AgentID
1488
+ * @param {string | AgentID} name - name of the agent or an AgentID to copy
1489
+ * @param {boolean} topic - name of topic
1490
+ * @param {Gateway} owner - Gateway owner for this AgentID
1491
+ * @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
1492
+ *
1493
+ */
1494
+ class CachingAgentID extends AgentID {
1495
+
1496
+ constructor(name, topic, owner, greedy=true) {
1497
+ if (name instanceof AgentID) {
1498
+ super(name.getName(), name.topic, name.owner);
1499
+ } else {
1500
+ super(name, topic, owner);
1501
+ }
1502
+ this.greedy = greedy;
1503
+ this.cache = {};
1504
+ }
1505
+
1506
+ /**
1507
+ * Sets parameter(s) on the Agent referred to by this AgentID, and caches the parameter(s).
1508
+ *
1509
+ * @param {(string|string[])} params - parameters name(s) to be set
1510
+ * @param {(Object|Object[])} values - parameters value(s) to be set
1511
+ * @param {number} [index=-1] - index of parameter(s) to be set
1512
+ * @param {number} [timeout=5000] - timeout for the response
1513
+ * @returns {Promise<(Object|Object[])>} - a promise which returns the new value(s) of the parameters
1514
+ */
1515
+ async set(params, values, index=-1, timeout=5000) {
1516
+ let s = await super.set(params, values, index, timeout);
1517
+ this._updateCache(params, s, index);
1518
+ }
1519
+
1520
+ /**
1521
+ * Gets parameter(s) on the Agent referred to by this AgentID, getting them from the cache if possible.
1522
+ *
1523
+ * @param {(string|string[])} params - parameters name(s) to be fetched
1524
+ * @param {number} [index=-1] - index of parameter(s) to be fetched
1525
+ * @param {number} [timeout=5000] - timeout for the response
1526
+ * @param {number} [maxage=5000] - maximum age of the cached result to retreive
1527
+ * @returns {Promise<(Object|Object[])>} - a promise which returns the value(s) of the parameters
1528
+ */
1529
+ async get(params, index=-1, timeout=5000, maxage=5000) {
1530
+ if (this._isCached(params, index, maxage)) return this._getCache(params, index);
1531
+ if (this.greedy && !(Array.isArray(params) && params.includes('name')) && params != 'name') {
1532
+ let rsp = await super.get(null, index, timeout);
1533
+ this._updateCache(null, rsp, index);
1534
+ if (Array.isArray(params)) {
1535
+ return params.map(p => {
1536
+ let f = Object.keys(rsp).find(rv => this._toNamed(rv) === p);
1537
+ return f ? rsp[f] : null;
1538
+ });
1539
+ } else {
1540
+ let f = Object.keys(rsp).find(rv => this._toNamed(rv) === params);
1541
+ return f ? rsp[f] : null;
1542
+ }
1543
+ } else {
1544
+ let r = await super.get(params, index, timeout);
1545
+ this._updateCache(params, r, index);
1546
+ return r;
1547
+ }
1548
+ }
1549
+
1550
+ _updateCache(params, vals, index) {
1551
+ if (vals == null || Array.isArray(vals) && vals.every(v => v == null)) return;
1552
+ if (params == null) {
1553
+ params = Object.keys(vals);
1554
+ vals = Object.values(vals);
1555
+ } else if (!Array.isArray(params)) params = [params];
1556
+ if (!Array.isArray(vals)) vals = [vals];
1557
+ params = params.map(this._toNamed);
1558
+ if (this.cache[index.toString()] === undefined) this.cache[index.toString()] = {};
1559
+ let c = this.cache[index.toString()];
1560
+ for (let i = 0; i < params.length; i++) {
1561
+ if (c[params[i]] === undefined) c[params[i]] = {};
1562
+ c[params[i]].value = vals[i];
1563
+ c[params[i]].ctime = Date.now();
1564
+ }
1565
+ }
1566
+
1567
+ _isCached(params, index, maxage) {
1568
+ if (maxage <= 0) return false;
1569
+ if (params == null) return false;
1570
+ let c = this.cache[index.toString()];
1571
+ if (!c) {
1572
+ return false;
1573
+ }
1574
+ if (!Array.isArray(params)) params = [params];
1575
+ const rv = params.every(p => {
1576
+ p = this._toNamed(p);
1577
+ return (p in c) && (Date.now() - c[p].ctime <= maxage);
1578
+ });
1579
+ return rv;
1580
+ }
1581
+
1582
+ _getCache(params, index) {
1583
+ let c = this.cache[index.toString()];
1584
+ if (!c) return null;
1585
+ if (!Array.isArray(params)){
1586
+ if (params in c) return c[params].value;
1587
+ return null;
1588
+ }else {
1589
+ return params.map(p => p in c ? c[p].value : null);
1590
+ }
1591
+ }
1592
+
1593
+ _toNamed(param) {
1594
+ const idx = param.lastIndexOf('.');
1595
+ if (idx < 0) return param;
1596
+ else return param.slice(idx+1);
1597
+ }
1598
+
1599
+ }
1600
+
1601
+
1602
+ class CachingGateway extends Gateway{
1603
+
1604
+ /**
1605
+ * Get an AgentID for a given agent name.
1606
+ *
1607
+ * @param {string} name - name of agent
1608
+ * @param {Boolean} [caching=true] - if the AgentID should cache parameters
1609
+ * @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
1610
+ * @returns {AgentID|CachingAgentID} - AgentID for the given name
1611
+ */
1612
+ agent(name, caching=true, greedy=true) {
1613
+ const aid = super.agent(name);
1614
+ return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
1615
+ }
1616
+
1617
+ /**
1618
+ * Returns an object representing the named topic.
1619
+ *
1620
+ * @param {string|AgentID} topic - name of the topic or AgentID
1621
+ * @param {string} topic2 - name of the topic if the topic param is an AgentID
1622
+ * @param {Boolean} [caching=true] - if the AgentID should cache parameters
1623
+ * @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
1624
+ * @returns {AgentID|CachingAgentID} - object representing the topic
1625
+ */
1626
+ topic(topic, topic2, caching=true, greedy=true) {
1627
+ const aid = super.topic(topic, topic2);
1628
+ return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
1629
+ }
1630
+
1631
+ /**
1632
+ * Finds an agent that provides a named service. If multiple agents are registered
1633
+ * to provide a given service, any of the agents' id may be returned.
1634
+ *
1635
+ * @param {string} service - the named service of interest
1636
+ * @param {Boolean} [caching=true] - if the AgentID should cache parameters
1637
+ * @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
1638
+ * @returns {Promise<?AgentID|CachingAgentID>} - a promise which returns an agent id for an agent that provides the service when resolved
1639
+ */
1640
+ async agentForService(service, caching=true, greedy=true) {
1641
+ const aid = await super.agentForService(service);
1642
+ return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
1643
+ }
1644
+
1645
+ /**
1646
+ * Finds all agents that provides a named service.
1647
+ *
1648
+ * @param {string} service - the named service of interest
1649
+ * @param {Boolean} [caching=true] - if the AgentID should cache parameters
1650
+ * @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
1651
+ * @returns {Promise<?AgentID|CachingAgentID[]>} - a promise which returns an array of all agent ids that provides the service when resolved
1652
+ */
1653
+ async agentsForService(service, caching=true, greedy=true) {
1654
+ const aids = await super.agentsForService(service);
1655
+ return caching ? aids.map(a => new CachingAgentID(a, null, null, greedy)) : aids;
1656
+ }
1657
+ }
1658
+
1396
1659
  const REQUEST_TIMEOUT = 1000;
1397
1660
 
1398
1661
  const AddressResolutionReq = UnetMessages.AddressResolutionReq;
@@ -1401,26 +1664,26 @@ const DatagramNtf = UnetMessages.DatagramNtf;
1401
1664
  const RxFrameNtf = UnetMessages.RxFrameNtf;
1402
1665
 
1403
1666
  /**
1404
- * Creates a new UnetSocket to connect to a running Unet instance. This constructor returns a
1405
- * {@link Promise} instead of the constructed UnetSocket object. Use `await` or `.then()` to get
1406
- * a reference to the UnetSocket object. Based on if this is run in a Browser or Node.js,
1667
+ * Creates a new UnetSocket to connect to a running Unet instance. This constructor returns a
1668
+ * {@link Promise} instead of the constructed UnetSocket object. Use `await` or `.then()` to get
1669
+ * a reference to the UnetSocket object. Based on if this is run in a Browser or Node.js,
1407
1670
  * it will internally connect over WebSockets or TCP respectively.
1408
1671
  *
1409
- *
1672
+ *
1410
1673
  * @class UnetSocket
1411
1674
  * @param {string} [hostname] - hostname/ip address of the master container to connect to
1412
1675
  * @param {number} [port] - port number of the master container to connect to
1413
1676
  * @param {string} [path=''] - path of the master container to connect to (for WebSockets)
1414
1677
  * @returns {Promise<UnetSocket>} - Promise which resolves to the UnetSocket object being constructed
1415
- *
1678
+ *
1416
1679
  * @example
1417
1680
  * let socket = await new UnetSocket('localhost', 8081, '/ws/');
1418
1681
  */
1419
1682
  class UnetSocket {
1420
1683
 
1421
- constructor(hostname, port, path='') {
1684
+ constructor(hostname, port, path='') {
1422
1685
  return (async () => {
1423
- this.gw = new Gateway({
1686
+ this.gw = new CachingGateway({
1424
1687
  hostname : hostname,
1425
1688
  port : port,
1426
1689
  path : path
@@ -1449,13 +1712,13 @@ class UnetSocket {
1449
1712
  * Checks if a socket is closed.
1450
1713
  * @returns {boolean} - true if closed, false if open
1451
1714
  */
1452
- isClosed() {
1715
+ isClosed() {
1453
1716
  return this.gw == null;
1454
1717
  }
1455
1718
 
1456
1719
  /**
1457
1720
  * Binds a socket to listen to a specific protocol datagrams.
1458
- * Protocol numbers between Protocol.DATA+1 to Protocol.USER-1 are reserved protocols
1721
+ * Protocol numbers between Protocol.DATA+1 to Protocol.USER-1 are reserved protocols
1459
1722
  * and cannot be bound. Unbound sockets listen to all unreserved
1460
1723
  * @param {Protocol} protocol - protocol number to listen for
1461
1724
  * @returns {boolean} - true on success, false on failure
@@ -1467,9 +1730,9 @@ class UnetSocket {
1467
1730
  }
1468
1731
  return false;
1469
1732
  }
1470
-
1733
+
1471
1734
  /**
1472
- * Unbinds a socket so that it listens to all unreserved protocols.
1735
+ * Unbinds a socket so that it listens to all unreserved protocols.
1473
1736
  * Protocol numbers between Protocol.DATA+1 to Protocol.USER-1 are considered reserved.
1474
1737
  * @returns {void}
1475
1738
  */
@@ -1482,13 +1745,13 @@ class UnetSocket {
1482
1745
  isBound() { return this.localProtocol >= 0;}
1483
1746
 
1484
1747
  /**
1485
- * Sets the default destination address and destination protocol number for datagrams sent
1486
- * using this socket. The defaults can be overridden for specific send() calls.
1487
- * The default protcol number when a socket is opened is Protcol.DATA.
1488
- * The default node address is undefined.
1489
- * Protocol numbers between Protocol.DATA+1 to Protocol.USER-1 are considered reserved,
1748
+ * Sets the default destination address and destination protocol number for datagrams sent
1749
+ * using this socket. The defaults can be overridden for specific send() calls.
1750
+ * The default protcol number when a socket is opened is Protcol.DATA.
1751
+ * The default node address is undefined.
1752
+ * Protocol numbers between Protocol.DATA+1 to Protocol.USER-1 are considered reserved,
1490
1753
  * and cannot be used for sending datagrams using the socket.
1491
- *
1754
+ *
1492
1755
  * @param {number} to - default destination node address
1493
1756
  * @param {Protocol} protocol - default protocol number
1494
1757
  * @returns {boolean} - true on success, false on failure
@@ -1503,11 +1766,11 @@ class UnetSocket {
1503
1766
  }
1504
1767
 
1505
1768
  /**
1506
- * Resets the default destination address to undefined, and the default protocol number
1769
+ * Resets the default destination address to undefined, and the default protocol number
1507
1770
  * to Protocol.DATA.
1508
1771
  * @returns {void}
1509
1772
  */
1510
- disconnect() {
1773
+ disconnect() {
1511
1774
  this.remoteAddress = -1;
1512
1775
  this.remoteProtocol = 0;
1513
1776
  }
@@ -1522,7 +1785,7 @@ class UnetSocket {
1522
1785
  * Gets the local node address of the Unet node connected to.
1523
1786
  * @returns {Promise<int>} - local node address, or -1 on error
1524
1787
  */
1525
- async getLocalAddress() {
1788
+ async getLocalAddress() {
1526
1789
  if (this.gw == null) return -1;
1527
1790
  const nodeinfo = await this.gw.agentForService(Services.NODE_INFO);
1528
1791
  if (nodeinfo == null) return -1;
@@ -1549,14 +1812,14 @@ class UnetSocket {
1549
1812
  getRemoteProtocol() { return this.remoteProtocol; }
1550
1813
 
1551
1814
  /**
1552
- * Sets the timeout for datagram reception. A timeout of 0 means the
1553
- * {@link UnetSocket#receive|receive method} will check any appropriate
1815
+ * Sets the timeout for datagram reception. A timeout of 0 means the
1816
+ * {@link UnetSocket#receive|receive method} will check any appropriate
1554
1817
  * Datagram has already been received (and is cached) else return immediately.
1555
- *
1818
+ *
1556
1819
  * @param {number} ms - timeout in milliseconds
1557
1820
  * @returns {void}
1558
1821
  */
1559
- setTimeout(ms) {
1822
+ setTimeout(ms) {
1560
1823
  if (ms < 0) ms = 0;
1561
1824
  this.timeout = ms;
1562
1825
  }
@@ -1605,12 +1868,12 @@ class UnetSocket {
1605
1868
  }
1606
1869
 
1607
1870
  /**
1608
- * Receives a datagram sent to the local node and the bound protocol number. If the socket is unbound,
1871
+ * Receives a datagram sent to the local node and the bound protocol number. If the socket is unbound,
1609
1872
  * then datagrams with all unreserved protocols are received. Any broadcast datagrams are also received.
1610
- *
1873
+ *
1611
1874
  * @returns {Promise<?DatagramNtf>} - datagram received by the socket
1612
1875
  */
1613
- async receive() {
1876
+ async receive() {
1614
1877
  if (this.gw == null) return null;
1615
1878
  return await this.gw.receive(msg => {
1616
1879
  if (msg.__clazz__ != DatagramNtf.__clazz__ && msg.__clazz__ != RxFrameNtf.__clazz__ ) return false;
@@ -1631,31 +1894,34 @@ class UnetSocket {
1631
1894
  /**
1632
1895
  * Gets an AgentID providing a specified service for low-level access to UnetStack
1633
1896
  * @param {string} svc - the named service of interest
1897
+ * @param {Boolean} caching - if the AgentID should cache parameters
1634
1898
  * @returns {Promise<?AgentID>} - a promise which returns an {@link AgentID} that provides the service when resolved
1635
1899
  */
1636
- async agentForService(svc) {
1900
+ async agentForService(svc, caching=true) {
1637
1901
  if (this.gw == null) return null;
1638
- return await this.gw.agentForService(svc);
1902
+ return await this.gw.agentForService(svc, caching);
1639
1903
  }
1640
1904
 
1641
1905
  /**
1642
- *
1906
+ *
1643
1907
  * @param {string} svc - the named service of interest
1908
+ * @param {Boolean} caching - if the AgentID should cache parameters
1644
1909
  * @returns {Promise<AgentID[]>} - a promise which returns an array of {@link AgentID|AgentIDs} that provides the service when resolved
1645
1910
  */
1646
- async agentsForService(svc) {
1911
+ async agentsForService(svc, caching=true) {
1647
1912
  if (this.gw == null) return null;
1648
- return await this.gw.agentsForService(svc);
1913
+ return await this.gw.agentsForService(svc, caching``);
1649
1914
  }
1650
1915
 
1651
1916
  /**
1652
1917
  * Gets a named AgentID for low-level access to UnetStack.
1653
1918
  * @param {string} name - name of agent
1919
+ * @param {Boolean} caching - if the AgentID should cache parameters
1654
1920
  * @returns {AgentID} - AgentID for the given name
1655
1921
  */
1656
- agent(name) {
1922
+ agent(name, caching=true) {
1657
1923
  if (this.gw == null) return null;
1658
- return this.gw.agent(name);
1924
+ return this.gw.agent(name, caching);
1659
1925
  }
1660
1926
 
1661
1927
  /**
@@ -1663,7 +1929,7 @@ class UnetSocket {
1663
1929
  * @param {string} nodeName - name of the node to resolve
1664
1930
  * @returns {Promise<?number>} - address of the node, or null if unable to resolve
1665
1931
  */
1666
- async host(nodeName) {
1932
+ async host(nodeName) {
1667
1933
  const arp = await this.agentForService(Services.ADDRESS_RESOLUTION);
1668
1934
  if (arp == null) return null;
1669
1935
  const req = new AddressResolutionReq(nodeName);
@@ -1675,4 +1941,4 @@ class UnetSocket {
1675
1941
  }
1676
1942
  }
1677
1943
 
1678
- export { AgentID, Gateway, Message, MessageClass, Performative, Protocol, Services, UnetMessages, UnetSocket };
1944
+ export { AgentID, CachingAgentID, CachingGateway as Gateway, Message, MessageClass, Performative, Protocol, Services, UnetMessages, UnetSocket, toGps, toLocal };