unetjs 5.1.0 → 6.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/README.md +8 -40
- package/dist/cjs/unet.cjs +439 -295
- package/dist/esm/unet.js +439 -294
- package/dist/unetjs.js +438 -294
- package/dist/unetjs.js.map +1 -1
- package/dist/unetjs.min.js +1 -1
- package/dist/unetjs.min.js.map +1 -1
- package/package.json +7 -7
package/dist/cjs/unet.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* unet.js
|
|
1
|
+
/* unet.js v6.0.0 2026-04-01T02:42:00.135Z */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -1912,9 +1912,15 @@ init();
|
|
|
1912
1912
|
const DatagramReq$1 = MessageClass('org.arl.unet.DatagramReq');
|
|
1913
1913
|
const DatagramNtf$1 = MessageClass('org.arl.unet.DatagramNtf');
|
|
1914
1914
|
const TxFrameReq = MessageClass('org.arl.unet.phy.TxFrameReq', DatagramReq$1);
|
|
1915
|
-
const RxFrameNtf
|
|
1915
|
+
const RxFrameNtf = MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1);
|
|
1916
1916
|
const BasebandSignal = MessageClass('org.arl.unet.bb.BasebandSignal');
|
|
1917
1917
|
|
|
1918
|
+
const UnetTopics = {
|
|
1919
|
+
'PARAMCHANGE' : 'org.arl.unet.Topics.PARAMCHANGE', // Topic for parameter change notification.
|
|
1920
|
+
'LIFECYCLE' : 'org.arl.unet.Topics.LIFECYCLE', // Topic for agent lifecycle notification.
|
|
1921
|
+
'DATAGRAM' : 'org.arl.unet.Topics.DATAGRAM', // Topic for incoming datagram notification.
|
|
1922
|
+
};
|
|
1923
|
+
|
|
1918
1924
|
let UnetServices = {
|
|
1919
1925
|
'NODE_INFO': 'org.arl.unet.Services.NODE_INFO',
|
|
1920
1926
|
'ADDRESS_RESOLUTION': 'org.arl.unet.Services.ADDRESS_RESOLUTION',
|
|
@@ -1978,6 +1984,7 @@ let UnetMessages = {
|
|
|
1978
1984
|
'DatagramNtf' : MessageClass('org.arl.unet.DatagramNtf'),
|
|
1979
1985
|
'DatagramProgressNtf' : MessageClass('org.arl.unet.DatagramProgressNtf'),
|
|
1980
1986
|
'DatagramReq' : MessageClass('org.arl.unet.DatagramReq'),
|
|
1987
|
+
'DatagramTransmissionNtf': MessageClass('org.arl.unet.DatagramTransmissionNtf'),
|
|
1981
1988
|
'ParamChangeNtf' : MessageClass('org.arl.unet.ParamChangeNtf'),
|
|
1982
1989
|
'RefuseRsp' : MessageClass('org.arl.unet.RefuseRsp'),
|
|
1983
1990
|
'FailureNtf' : MessageClass('org.arl.unet.FailureNtf'),
|
|
@@ -1991,9 +1998,9 @@ let UnetMessages = {
|
|
|
1991
1998
|
|
|
1992
1999
|
// phy
|
|
1993
2000
|
'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
|
|
1994
|
-
'RxSWiG1FrameNtf' : MessageClass('org.arl.unet.phy.RxSWiG1FrameNtf', RxFrameNtf
|
|
2001
|
+
'RxSWiG1FrameNtf' : MessageClass('org.arl.unet.phy.RxSWiG1FrameNtf', RxFrameNtf),
|
|
1995
2002
|
'TxSWiG1FrameReq' : MessageClass('org.arl.unet.phy.TxSWiG1FrameReq', TxFrameReq),
|
|
1996
|
-
'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf', RxFrameNtf
|
|
2003
|
+
'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf', RxFrameNtf),
|
|
1997
2004
|
'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq', TxFrameReq),
|
|
1998
2005
|
'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
|
|
1999
2006
|
'BadRangeNtf' : MessageClass('org.arl.unet.phy.BadRangeNtf'),
|
|
@@ -2047,6 +2054,7 @@ let UnetMessages = {
|
|
|
2047
2054
|
'RemoteFileGetReq' : MessageClass('org.arl.unet.remote.RemoteFileGetReq'),
|
|
2048
2055
|
'RemoteFileNtf' : MessageClass('org.arl.unet.remote.RemoteFileNtf'),
|
|
2049
2056
|
'RemoteFilePutReq' : MessageClass('org.arl.unet.remote.RemoteFilePutReq'),
|
|
2057
|
+
'RemoteDeliveryNtf' : MessageClass('org.arl.unet.remote.RemoteDeliveryNtf'),
|
|
2050
2058
|
'RemoteSuccessNtf' : MessageClass('org.arl.unet.remote.RemoteSuccessNtf'),
|
|
2051
2059
|
'RemoteTextNtf' : MessageClass('org.arl.unet.remote.RemoteTextNtf'),
|
|
2052
2060
|
'RemoteTextReq' : MessageClass('org.arl.unet.remote.RemoteTextReq'),
|
|
@@ -2101,243 +2109,33 @@ function _initConv(lat){
|
|
|
2101
2109
|
return [xScale, yScale];
|
|
2102
2110
|
}
|
|
2103
2111
|
|
|
2104
|
-
|
|
2105
|
-
* A message which requests the transmission of the datagram from the Unet
|
|
2106
|
-
*
|
|
2107
|
-
* @typedef {Message} DatagramReq
|
|
2108
|
-
* @property {number[]} data - data as an Array of bytes
|
|
2109
|
-
* @property {number} from - from/source node address
|
|
2110
|
-
* @property {number} to - to/destination node address
|
|
2111
|
-
* @property {number} protocol - protocol number to be used to send this Datagram
|
|
2112
|
-
* @property {boolean} reliability - true if Datagram should be reliable, false if unreliable
|
|
2113
|
-
* @property {number} ttl - time-to-live for the datagram. Time-to-live is advisory, and an agent may choose it ignore it
|
|
2114
|
-
*/
|
|
2115
|
-
|
|
2116
|
-
/**
|
|
2117
|
-
* Notification of received datagram message received by the Unet node.
|
|
2118
|
-
*
|
|
2119
|
-
* @typedef {Message} DatagramNtf
|
|
2120
|
-
* @property {number[]} data - data as an Array of bytes
|
|
2121
|
-
* @property {number} from - from/source node address
|
|
2122
|
-
* @property {number} to - to/destination node address
|
|
2123
|
-
* @property {number} protocol - protocol number to be used to send this Datagram
|
|
2124
|
-
* @property {number} ttl - time-to-live for the datagram. Time-to-live is advisory, and an agent may choose it ignore it
|
|
2125
|
-
*/
|
|
2126
|
-
|
|
2127
|
-
/**
|
|
2128
|
-
* An identifier for an agent or a topic.
|
|
2129
|
-
* @external AgentID
|
|
2130
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2131
|
-
*/
|
|
2132
|
-
|
|
2133
|
-
/**
|
|
2134
|
-
* Services supported by fjage agents.
|
|
2135
|
-
* @external Services
|
|
2136
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2137
|
-
*/
|
|
2138
|
-
|
|
2139
|
-
/**
|
|
2140
|
-
* An action represented by a message.
|
|
2141
|
-
* @external Performative
|
|
2142
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2143
|
-
*/
|
|
2144
|
-
|
|
2145
|
-
/**
|
|
2146
|
-
* Function to creates a unqualified message class based on a fully qualified name.
|
|
2147
|
-
* @external MessageClass
|
|
2148
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2149
|
-
*/
|
|
2150
|
-
|
|
2151
|
-
/**
|
|
2152
|
-
* A caching CachingAgentID which caches Agent parameters locally.
|
|
2153
|
-
*
|
|
2154
|
-
* @class
|
|
2155
|
-
* @extends AgentID
|
|
2156
|
-
* @param {string | AgentID} name - name of the agent or an AgentID to copy
|
|
2157
|
-
* @param {boolean} topic - name of topic
|
|
2158
|
-
* @param {Gateway} owner - Gateway owner for this AgentID
|
|
2159
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2160
|
-
*
|
|
2161
|
-
*/
|
|
2162
|
-
class CachingAgentID extends AgentID {
|
|
2163
|
-
|
|
2164
|
-
constructor(name, topic, owner, greedy=true) {
|
|
2165
|
-
if (name instanceof AgentID) {
|
|
2166
|
-
super(name.getName(), name.topic, name.owner);
|
|
2167
|
-
} else {
|
|
2168
|
-
super(name, topic, owner);
|
|
2169
|
-
}
|
|
2170
|
-
this.greedy = greedy;
|
|
2171
|
-
this.cache = {};
|
|
2172
|
-
this.specialParams = ['name', 'version'];
|
|
2173
|
-
}
|
|
2174
|
-
|
|
2175
|
-
/**
|
|
2176
|
-
* Sets parameter(s) on the Agent referred to by this AgentID, and caches the parameter(s).
|
|
2177
|
-
*
|
|
2178
|
-
* @param {(string|string[])} params - parameters name(s) to be set
|
|
2179
|
-
* @param {(Object|Object[])} values - parameters value(s) to be set
|
|
2180
|
-
* @param {number} [index=-1] - index of parameter(s) to be set
|
|
2181
|
-
* @param {number} [timeout=5000] - timeout for the response
|
|
2182
|
-
* @returns {Promise<(Object|Object[])>} - a promise which returns the new value(s) of the parameters
|
|
2183
|
-
*/
|
|
2184
|
-
async set(params, values, index=-1, timeout=5000) {
|
|
2185
|
-
let s = await super.set(params, values, index, timeout);
|
|
2186
|
-
this._updateCache(params, s, index);
|
|
2187
|
-
return s;
|
|
2188
|
-
}
|
|
2189
|
-
|
|
2190
|
-
/**
|
|
2191
|
-
* Gets parameter(s) on the Agent referred to by this AgentID, getting them from the cache if possible.
|
|
2192
|
-
*
|
|
2193
|
-
* @param {(string|string[])} params - parameters name(s) to be fetched
|
|
2194
|
-
* @param {number} [index=-1] - index of parameter(s) to be fetched
|
|
2195
|
-
* @param {number} [timeout=5000] - timeout for the response
|
|
2196
|
-
* @param {number} [maxage=5000] - maximum age of the cached result to retreive
|
|
2197
|
-
* @returns {Promise<(Object|Object[])>} - a promise which returns the value(s) of the parameters
|
|
2198
|
-
*/
|
|
2199
|
-
async get(params, index=-1, timeout=5000, maxage=5000) {
|
|
2200
|
-
if (this._isCached(params, index, maxage)) return this._getCache(params, index);
|
|
2201
|
-
if (this.greedy &&
|
|
2202
|
-
!(Array.isArray(params) && [...new Set([...params, ...this.specialParams])].length!=0) &&
|
|
2203
|
-
!this.specialParams.includes(params)) {
|
|
2204
|
-
let rsp = await super.get(null, index, timeout);
|
|
2205
|
-
this._updateCache(null, rsp, index);
|
|
2206
|
-
if (!rsp) return Array.isArray(params) ? new Array(params.length).fill(null) : null;
|
|
2207
|
-
if (!params) return rsp;
|
|
2208
|
-
else if (Array.isArray(params)) {
|
|
2209
|
-
return params.map(p => {
|
|
2210
|
-
let f = Object.keys(rsp).find(rv => this._toNamed(rv) === p);
|
|
2211
|
-
return f ? rsp[f] : null;
|
|
2212
|
-
});
|
|
2213
|
-
} else {
|
|
2214
|
-
let f = Object.keys(rsp).find(rv => this._toNamed(rv) === params);
|
|
2215
|
-
return f ? rsp[f] : null;
|
|
2216
|
-
}
|
|
2217
|
-
} else {
|
|
2218
|
-
let r = await super.get(params, index, timeout);
|
|
2219
|
-
this._updateCache(params, r, index);
|
|
2220
|
-
return r;
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
|
-
|
|
2224
|
-
_updateCache(params, vals, index) {
|
|
2225
|
-
if (vals == null || Array.isArray(vals) && vals.every(v => v == null)) return;
|
|
2226
|
-
if (params == null) {
|
|
2227
|
-
params = Object.keys(vals);
|
|
2228
|
-
vals = Object.values(vals);
|
|
2229
|
-
} else if (!Array.isArray(params)) params = [params];
|
|
2230
|
-
if (!Array.isArray(vals)) vals = [vals];
|
|
2231
|
-
params = params.map(this._toNamed);
|
|
2232
|
-
if (this.cache[index.toString()] === undefined) this.cache[index.toString()] = {};
|
|
2233
|
-
let c = this.cache[index.toString()];
|
|
2234
|
-
for (let i = 0; i < params.length; i++) {
|
|
2235
|
-
if (c[params[i]] === undefined) c[params[i]] = {};
|
|
2236
|
-
c[params[i]].value = vals[i];
|
|
2237
|
-
c[params[i]].ctime = Date.now();
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
|
|
2241
|
-
_isCached(params, index, maxage) {
|
|
2242
|
-
if (maxage <= 0) return false;
|
|
2243
|
-
if (params == null) return false;
|
|
2244
|
-
let c = this.cache[index.toString()];
|
|
2245
|
-
if (!c) {
|
|
2246
|
-
return false;
|
|
2247
|
-
}
|
|
2248
|
-
if (!Array.isArray(params)) params = [params];
|
|
2249
|
-
const rv = params.every(p => {
|
|
2250
|
-
p = this._toNamed(p);
|
|
2251
|
-
return (p in c) && (Date.now() - c[p].ctime <= maxage);
|
|
2252
|
-
});
|
|
2253
|
-
return rv;
|
|
2254
|
-
}
|
|
2255
|
-
|
|
2256
|
-
_getCache(params, index) {
|
|
2257
|
-
let c = this.cache[index.toString()];
|
|
2258
|
-
if (!c) return null;
|
|
2259
|
-
if (!Array.isArray(params)){
|
|
2260
|
-
if (params in c) return c[params].value;
|
|
2261
|
-
return null;
|
|
2262
|
-
}else {
|
|
2263
|
-
return params.map(p => p in c ? c[p].value : null);
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
|
|
2267
|
-
_toNamed(param) {
|
|
2268
|
-
const idx = param.lastIndexOf('.');
|
|
2269
|
-
if (idx < 0) return param;
|
|
2270
|
-
else return param.slice(idx+1);
|
|
2271
|
-
}
|
|
2272
|
-
|
|
2273
|
-
}
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
class CachingGateway extends Gateway{
|
|
2277
|
-
|
|
2278
|
-
/**
|
|
2279
|
-
* Get an AgentID for a given agent name.
|
|
2280
|
-
*
|
|
2281
|
-
* @param {string} name - name of agent
|
|
2282
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2283
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2284
|
-
* @returns {AgentID|CachingAgentID} - AgentID for the given name
|
|
2285
|
-
*/
|
|
2286
|
-
agent(name, caching=true, greedy=true) {
|
|
2287
|
-
const aid = super.agent(name);
|
|
2288
|
-
return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
|
|
2289
|
-
}
|
|
2290
|
-
|
|
2291
|
-
/**
|
|
2292
|
-
* Returns an object representing the named topic.
|
|
2293
|
-
*
|
|
2294
|
-
* @param {string|AgentID} topic - name of the topic or AgentID
|
|
2295
|
-
* @param {string} topic2 - name of the topic if the topic param is an AgentID
|
|
2296
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2297
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2298
|
-
* @returns {AgentID|CachingAgentID} - object representing the topic
|
|
2299
|
-
*/
|
|
2300
|
-
topic(topic, topic2, caching=true, greedy=true) {
|
|
2301
|
-
const aid = super.topic(topic, topic2);
|
|
2302
|
-
return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
|
|
2303
|
-
}
|
|
2304
|
-
|
|
2305
|
-
/**
|
|
2306
|
-
* Finds an agent that provides a named service. If multiple agents are registered
|
|
2307
|
-
* to provide a given service, any of the agents' id may be returned.
|
|
2308
|
-
*
|
|
2309
|
-
* @param {string} service - the named service of interest
|
|
2310
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2311
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2312
|
-
* @returns {Promise<?AgentID|CachingAgentID>} - a promise which returns an agent id for an agent that provides the service when resolved
|
|
2313
|
-
*/
|
|
2314
|
-
async agentForService(service, caching=true, greedy=true) {
|
|
2315
|
-
const aid = await super.agentForService(service);
|
|
2316
|
-
if (!aid) return aid;
|
|
2317
|
-
return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
|
|
2318
|
-
}
|
|
2319
|
-
|
|
2320
|
-
/**
|
|
2321
|
-
* Finds all agents that provides a named service.
|
|
2322
|
-
*
|
|
2323
|
-
* @param {string} service - the named service of interest
|
|
2324
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2325
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2326
|
-
* @returns {Promise<?AgentID|CachingAgentID[]>} - a promise which returns an array of all agent ids that provides the service when resolved
|
|
2327
|
-
*/
|
|
2328
|
-
async agentsForService(service, caching=true, greedy=true) {
|
|
2329
|
-
const aids = await super.agentsForService(service);
|
|
2330
|
-
return caching ? aids.map(a => new CachingAgentID(a, null, null, greedy)) : aids;
|
|
2331
|
-
}
|
|
2332
|
-
}
|
|
2333
|
-
|
|
2112
|
+
const BROADCAST_ADDR = 0;
|
|
2334
2113
|
const REQUEST_TIMEOUT = 1000;
|
|
2114
|
+
const NON_BLOCKING = 0;
|
|
2115
|
+
const SEMI_BLOCKING = 1;
|
|
2116
|
+
const BLOCKING = 2;
|
|
2335
2117
|
|
|
2336
2118
|
const AddressResolutionReq = UnetMessages.AddressResolutionReq;
|
|
2119
|
+
const DatagramDeliveryNtf = UnetMessages.DatagramDeliveryNtf;
|
|
2120
|
+
const DatagramFailureNtf = UnetMessages.DatagramFailureNtf;
|
|
2337
2121
|
const DatagramReq = UnetMessages.DatagramReq;
|
|
2338
2122
|
const DatagramNtf = UnetMessages.DatagramNtf;
|
|
2339
|
-
const
|
|
2123
|
+
const DatagramTransmissionNtf = UnetMessages.DatagramTransmissionNtf;
|
|
2124
|
+
const RemoteDeliveryNtf = UnetMessages.RemoteDeliveryNtf;
|
|
2125
|
+
const RemoteFailureNtf = UnetMessages.RemoteFailureNtf;
|
|
2126
|
+
const RemoteSuccessNtf = UnetMessages.RemoteSuccessNtf;
|
|
2127
|
+
|
|
2128
|
+
function isReservedProtocol(protocol) {
|
|
2129
|
+
return protocol != Protocol.DATA && (protocol < Protocol.USER || protocol > Protocol.MAX);
|
|
2130
|
+
}
|
|
2340
2131
|
|
|
2132
|
+
function hasValue(value) {
|
|
2133
|
+
return value !== undefined && value !== null;
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
function hasFiniteNumber(value) {
|
|
2137
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
2138
|
+
}
|
|
2341
2139
|
/**
|
|
2342
2140
|
* Creates a new UnetSocket to connect to a running Unet instance. This constructor returns a
|
|
2343
2141
|
* {@link Promise} instead of the constructed UnetSocket object. Use `await` or `.then()` to get
|
|
@@ -2358,18 +2156,63 @@ class UnetSocket {
|
|
|
2358
2156
|
|
|
2359
2157
|
constructor(hostname, port, path='') {
|
|
2360
2158
|
return (async () => {
|
|
2361
|
-
this.
|
|
2159
|
+
this._gw = new Gateway({
|
|
2362
2160
|
hostname : hostname,
|
|
2363
2161
|
port : port,
|
|
2364
2162
|
path : path
|
|
2365
2163
|
});
|
|
2366
|
-
this.
|
|
2367
|
-
this.
|
|
2368
|
-
this.
|
|
2369
|
-
this.
|
|
2370
|
-
this.
|
|
2371
|
-
|
|
2372
|
-
|
|
2164
|
+
this._localProtocol = -1;
|
|
2165
|
+
this._remoteAddress = -1;
|
|
2166
|
+
this._localAddress = -1;
|
|
2167
|
+
this._remoteProtocol = Protocol.DATA;
|
|
2168
|
+
this._timeout = 0;
|
|
2169
|
+
this._serviceProvider = null;
|
|
2170
|
+
this._ttl = NaN;
|
|
2171
|
+
this._priority = null;
|
|
2172
|
+
this._reliability = null;
|
|
2173
|
+
this._route = null;
|
|
2174
|
+
this._mimeType = null;
|
|
2175
|
+
this._remoteRecipient = null;
|
|
2176
|
+
this._mailbox = null;
|
|
2177
|
+
this._messageClass = null;
|
|
2178
|
+
this._sendMode = SEMI_BLOCKING;
|
|
2179
|
+
this._warnedDeprecatedSend = false;
|
|
2180
|
+
this._paramChangeCallbacks = {};
|
|
2181
|
+
|
|
2182
|
+
//for new UnetStack versions (5.2.0 and later)
|
|
2183
|
+
this._gw.subscribe(this._gw.topic(UnetTopics.DATAGRAM));
|
|
2184
|
+
|
|
2185
|
+
//for compatibility with older UnetStack versions (before 5.2.0)
|
|
2186
|
+
const alist = await this._gw.agentsForService(Services.DATAGRAM);
|
|
2187
|
+
alist.forEach(a => {this._gw.subscribe(this._gw.topic(a));});
|
|
2188
|
+
|
|
2189
|
+
// get local nodeinfo agent
|
|
2190
|
+
const nodeinfo = await this._gw.agentForService(Services.NODE_INFO);
|
|
2191
|
+
|
|
2192
|
+
// subscribe to paramchange notifications for onParamChange callbacks
|
|
2193
|
+
this._gw.subscribe(this._gw.topic(UnetTopics.PARAMCHANGE));
|
|
2194
|
+
if (nodeinfo != null) this._gw.subscribe(this._gw.topic(nodeinfo)); // nodeinfo publishes param changes for local node parameters
|
|
2195
|
+
this._gw.addMessageListener(msg => {
|
|
2196
|
+
if (msg instanceof UnetMessages.ParamChangeNtf) {
|
|
2197
|
+
const sender = (msg.sender instanceof AgentID) ? msg.sender.name : msg.sender;
|
|
2198
|
+
if (msg.paramValues != null){
|
|
2199
|
+
for (const p in msg.paramValues) {
|
|
2200
|
+
// if p has dots inside then take the substring after the last dot as the parameter name,
|
|
2201
|
+
// since many times fully qualified parameter names are used in the notifications
|
|
2202
|
+
const paramName = p.includes('.') ? p.substring(p.lastIndexOf('.') + 1) : p;
|
|
2203
|
+
const callback = this._paramChangeCallbacks[sender + '.' + paramName];
|
|
2204
|
+
if (callback != null) callback(msg.paramValues[p]);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
2209
|
+
|
|
2210
|
+
// get local node address and subscribe to changes in the local node address
|
|
2211
|
+
if (nodeinfo != null) {
|
|
2212
|
+
this.onParamChange(nodeinfo.name, 'address', (addr) => { this._localAddress = addr; });
|
|
2213
|
+
this._localAddress = await nodeinfo.get('address');
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2373
2216
|
return this;
|
|
2374
2217
|
})();
|
|
2375
2218
|
}
|
|
@@ -2379,8 +2222,8 @@ class UnetSocket {
|
|
|
2379
2222
|
* @returns {void}
|
|
2380
2223
|
*/
|
|
2381
2224
|
close() {
|
|
2382
|
-
this.
|
|
2383
|
-
this.
|
|
2225
|
+
this._gw.close();
|
|
2226
|
+
this._gw = null;
|
|
2384
2227
|
}
|
|
2385
2228
|
|
|
2386
2229
|
/**
|
|
@@ -2388,7 +2231,7 @@ class UnetSocket {
|
|
|
2388
2231
|
* @returns {boolean} - true if closed, false if open
|
|
2389
2232
|
*/
|
|
2390
2233
|
isClosed() {
|
|
2391
|
-
return this.
|
|
2234
|
+
return this._gw == null;
|
|
2392
2235
|
}
|
|
2393
2236
|
|
|
2394
2237
|
/**
|
|
@@ -2400,7 +2243,7 @@ class UnetSocket {
|
|
|
2400
2243
|
*/
|
|
2401
2244
|
bind(protocol) {
|
|
2402
2245
|
if (protocol == Protocol.DATA || (protocol >= Protocol.USER && protocol <= Protocol.MAX)) {
|
|
2403
|
-
this.
|
|
2246
|
+
this._localProtocol = protocol;
|
|
2404
2247
|
return true;
|
|
2405
2248
|
}
|
|
2406
2249
|
return false;
|
|
@@ -2411,13 +2254,13 @@ class UnetSocket {
|
|
|
2411
2254
|
* Protocol numbers between Protocol.DATA+1 to Protocol.USER-1 are considered reserved.
|
|
2412
2255
|
* @returns {void}
|
|
2413
2256
|
*/
|
|
2414
|
-
unbind() { this.
|
|
2257
|
+
unbind() { this._localProtocol = -1;}
|
|
2415
2258
|
|
|
2416
2259
|
/**
|
|
2417
2260
|
* Checks if a socket is bound.
|
|
2418
2261
|
* @returns {boolean} - true if bound to a protocol, false if unbound
|
|
2419
2262
|
*/
|
|
2420
|
-
isBound() { return this.
|
|
2263
|
+
isBound() { return this._localProtocol >= 0;}
|
|
2421
2264
|
|
|
2422
2265
|
/**
|
|
2423
2266
|
* Sets the default destination address and destination protocol number for datagrams sent
|
|
@@ -2433,8 +2276,8 @@ class UnetSocket {
|
|
|
2433
2276
|
*/
|
|
2434
2277
|
connect(to, protocol) {
|
|
2435
2278
|
if (to >= 0 && (protocol == Protocol.DATA || (protocol >= Protocol.USER && protocol <= Protocol.MAX))) {
|
|
2436
|
-
this.
|
|
2437
|
-
this.
|
|
2279
|
+
this._remoteAddress = to;
|
|
2280
|
+
this._remoteProtocol = protocol;
|
|
2438
2281
|
return true;
|
|
2439
2282
|
}
|
|
2440
2283
|
return false;
|
|
@@ -2446,23 +2289,23 @@ class UnetSocket {
|
|
|
2446
2289
|
* @returns {void}
|
|
2447
2290
|
*/
|
|
2448
2291
|
disconnect() {
|
|
2449
|
-
this.
|
|
2450
|
-
this.
|
|
2292
|
+
this._remoteAddress = -1;
|
|
2293
|
+
this._remoteProtocol = 0;
|
|
2451
2294
|
}
|
|
2452
2295
|
|
|
2453
2296
|
/**
|
|
2454
2297
|
* Checks if a socket is connected, i.e., has a default destination address and protocol number.
|
|
2455
2298
|
* @returns {boolean} - true if connected, false otherwise
|
|
2456
2299
|
*/
|
|
2457
|
-
isConnected() { return this.
|
|
2300
|
+
isConnected() { return this._remoteAddress >= 0; }
|
|
2458
2301
|
|
|
2459
2302
|
/**
|
|
2460
2303
|
* Gets the local node address of the Unet node connected to.
|
|
2461
2304
|
* @returns {Promise<int>} - local node address, or -1 on error
|
|
2462
2305
|
*/
|
|
2463
2306
|
async getLocalAddress() {
|
|
2464
|
-
if (this.
|
|
2465
|
-
const nodeinfo = await this.
|
|
2307
|
+
if (this._gw == null) return -1;
|
|
2308
|
+
const nodeinfo = await this._gw.agentForService(Services.NODE_INFO);
|
|
2466
2309
|
if (nodeinfo == null) return -1;
|
|
2467
2310
|
const addr = await nodeinfo.get('address');
|
|
2468
2311
|
return addr != null ? addr : -1;
|
|
@@ -2470,21 +2313,21 @@ class UnetSocket {
|
|
|
2470
2313
|
|
|
2471
2314
|
/**
|
|
2472
2315
|
* Gets the protocol number that the socket is bound to.
|
|
2473
|
-
* @returns {number}
|
|
2316
|
+
* @returns {number} - protocol number if socket is bound, -1 otherwise
|
|
2474
2317
|
*/
|
|
2475
|
-
getLocalProtocol() { return this.
|
|
2318
|
+
getLocalProtocol() { return this._localProtocol; }
|
|
2476
2319
|
|
|
2477
2320
|
/**
|
|
2478
2321
|
* Gets the default destination node address for a connected socket.
|
|
2479
|
-
* @returns {number}
|
|
2322
|
+
* @returns {number} - default destination node address if connected, -1 otherwise
|
|
2480
2323
|
*/
|
|
2481
|
-
getRemoteAddress() { return this.
|
|
2324
|
+
getRemoteAddress() { return this._remoteAddress; }
|
|
2482
2325
|
|
|
2483
2326
|
/**
|
|
2484
2327
|
* Gets the default transmission protocol number.
|
|
2485
|
-
* @returns {number}
|
|
2328
|
+
* @returns {number} - default protocol number used to transmit a datagram
|
|
2486
2329
|
*/
|
|
2487
|
-
getRemoteProtocol() { return this.
|
|
2330
|
+
getRemoteProtocol() { return this._remoteProtocol; }
|
|
2488
2331
|
|
|
2489
2332
|
/**
|
|
2490
2333
|
* Sets the timeout for datagram reception. A timeout of 0 means the
|
|
@@ -2496,14 +2339,275 @@ class UnetSocket {
|
|
|
2496
2339
|
*/
|
|
2497
2340
|
setTimeout(ms) {
|
|
2498
2341
|
if (ms < 0) ms = 0;
|
|
2499
|
-
this.
|
|
2342
|
+
this._timeout = ms;
|
|
2500
2343
|
}
|
|
2501
2344
|
|
|
2502
2345
|
/**
|
|
2503
2346
|
* Gets the timeout for datagram reception.
|
|
2504
2347
|
* @returns {number} - timeout in milliseconds
|
|
2505
2348
|
*/
|
|
2506
|
-
getTimeout() { return this.
|
|
2349
|
+
getTimeout() { return this._timeout; }
|
|
2350
|
+
|
|
2351
|
+
/**
|
|
2352
|
+
* Sets the default time-to-live for datagrams sent using this socket.
|
|
2353
|
+
* TTL is advisory; an agent may choose to ignore it.
|
|
2354
|
+
* @param {number} ttl - time-to-live in seconds
|
|
2355
|
+
* @returns {void}
|
|
2356
|
+
*/
|
|
2357
|
+
setTTL(ttl) {
|
|
2358
|
+
this._ttl = ttl;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
/**
|
|
2362
|
+
* Gets the default time-to-live for datagrams sent using this socket.
|
|
2363
|
+
* @returns {number} - time-to-live in seconds, or NaN if not set
|
|
2364
|
+
*/
|
|
2365
|
+
getTTL() {
|
|
2366
|
+
return this._ttl;
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
/**
|
|
2370
|
+
* Sets the default priority for datagrams sent using this socket.
|
|
2371
|
+
* @param {*} priority - priority value; interpretation is provider-dependent
|
|
2372
|
+
* @returns {void}
|
|
2373
|
+
*/
|
|
2374
|
+
setPriority(priority) {
|
|
2375
|
+
this._priority = priority;
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
/**
|
|
2379
|
+
* Gets the default priority for datagrams sent using this socket.
|
|
2380
|
+
* @returns {*} - priority value, or null if not set
|
|
2381
|
+
*/
|
|
2382
|
+
getPriority() {
|
|
2383
|
+
return this._priority;
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
/**
|
|
2387
|
+
* Sets the default reliability for datagrams sent using this socket.
|
|
2388
|
+
* When set to true, the socket will request reliable delivery and, in
|
|
2389
|
+
* SEMI_BLOCKING mode, will wait for a delivery confirmation before returning.
|
|
2390
|
+
* @param {boolean} reliability - true for reliable delivery, false for unreliable
|
|
2391
|
+
* @returns {void}
|
|
2392
|
+
*/
|
|
2393
|
+
setReliability(reliability) {
|
|
2394
|
+
this._reliability = reliability;
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2397
|
+
/**
|
|
2398
|
+
* Gets the default reliability setting for datagrams sent using this socket.
|
|
2399
|
+
* @returns {boolean|null} - true if reliable, false if unreliable, null if not set
|
|
2400
|
+
*/
|
|
2401
|
+
getReliability() {
|
|
2402
|
+
return this._reliability;
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
/**
|
|
2406
|
+
* Sets the default route identifier for datagrams sent using this socket.
|
|
2407
|
+
* Route selection is provider-dependent; not all providers support explicit routing.
|
|
2408
|
+
* @param {*} route - route identifier
|
|
2409
|
+
* @returns {void}
|
|
2410
|
+
*/
|
|
2411
|
+
setRoute(route) {
|
|
2412
|
+
this._route = route;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
* Gets the default route identifier for datagrams sent using this socket.
|
|
2417
|
+
* @returns {*} - route identifier, or null if not set
|
|
2418
|
+
*/
|
|
2419
|
+
getRoute() {
|
|
2420
|
+
return this._route;
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
/**
|
|
2424
|
+
* Sets the default MIME type describing the datagram payload.
|
|
2425
|
+
* This can be used by REMOTE service providers to apply content-aware compression.
|
|
2426
|
+
* @param {string} mimeType - MIME type string (e.g. 'application/json')
|
|
2427
|
+
* @returns {void}
|
|
2428
|
+
*/
|
|
2429
|
+
setMimeType(mimeType) {
|
|
2430
|
+
this._mimeType = mimeType;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
/**
|
|
2434
|
+
* Gets the default MIME type for datagrams sent using this socket.
|
|
2435
|
+
* @returns {string|null} - MIME type string, or null if not set
|
|
2436
|
+
*/
|
|
2437
|
+
getMimeType() {
|
|
2438
|
+
return this._mimeType;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
/**
|
|
2442
|
+
* Sets the default remote recipient for datagrams sent using this socket.
|
|
2443
|
+
* Used by REMOTE service providers to address a specific entity on the remote node.
|
|
2444
|
+
* @param {*} remoteRecipient - remote recipient identifier (e.g. an AgentID or name string)
|
|
2445
|
+
* @returns {void}
|
|
2446
|
+
*/
|
|
2447
|
+
setRemoteRecipient(remoteRecipient) {
|
|
2448
|
+
this._remoteRecipient = remoteRecipient;
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
/**
|
|
2452
|
+
* Gets the default remote recipient for datagrams sent using this socket.
|
|
2453
|
+
* @returns {*} - remote recipient identifier, or null if not set
|
|
2454
|
+
*/
|
|
2455
|
+
getRemoteRecipient() {
|
|
2456
|
+
return this._remoteRecipient;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
/**
|
|
2460
|
+
* Sets the default mailbox name for datagrams sent using this socket.
|
|
2461
|
+
* Mailboxes are used by REMOTE service providers to deliver messages
|
|
2462
|
+
* to a named queue on the remote node.
|
|
2463
|
+
* @param {string} mailbox - mailbox name
|
|
2464
|
+
* @returns {void}
|
|
2465
|
+
*/
|
|
2466
|
+
setMailbox(mailbox) {
|
|
2467
|
+
this._mailbox = mailbox;
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
/**
|
|
2471
|
+
* Gets the default mailbox name for datagrams sent using this socket.
|
|
2472
|
+
* @returns {string|null} - mailbox name, or null if not set
|
|
2473
|
+
*/
|
|
2474
|
+
getMailbox() {
|
|
2475
|
+
return this._mailbox;
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
/**
|
|
2479
|
+
* Sets the default application message class for datagrams sent using this socket.
|
|
2480
|
+
* Used by REMOTE service providers to associate a fully-qualified class name with the payload.
|
|
2481
|
+
* @param {string} messageClass - fully-qualified message class name (e.g. 'org.example.Status')
|
|
2482
|
+
* @returns {void}
|
|
2483
|
+
*/
|
|
2484
|
+
setMessageClass(messageClass) {
|
|
2485
|
+
this._messageClass = messageClass;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
/**
|
|
2489
|
+
* Gets the default application message class for datagrams sent using this socket.
|
|
2490
|
+
* @returns {string|null} - message class name, or null if not set
|
|
2491
|
+
*/
|
|
2492
|
+
getMessageClass() {
|
|
2493
|
+
return this._messageClass;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
/**
|
|
2497
|
+
* Overrides the service provider used to transmit datagrams. When set, provider
|
|
2498
|
+
* auto-selection is bypassed and all sends go through the specified agent.
|
|
2499
|
+
* Pass null to re-enable auto-selection.
|
|
2500
|
+
* @param {AgentID|string|null} provider - agent id, agent name string, or null to clear the override
|
|
2501
|
+
* @returns {void}
|
|
2502
|
+
*/
|
|
2503
|
+
setServiceProvider(provider) {
|
|
2504
|
+
if (typeof provider === 'string') provider = this.agent(provider);
|
|
2505
|
+
this._serviceProvider = provider instanceof AgentID || provider == null ? provider : null;
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
/**
|
|
2509
|
+
* Gets the currently configured service provider override.
|
|
2510
|
+
* @returns {AgentID|null} - the override agent id, or null if auto-selection is active
|
|
2511
|
+
*/
|
|
2512
|
+
getServiceProvider() {
|
|
2513
|
+
return this._serviceProvider;
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
/**
|
|
2517
|
+
* Sets the send mode that controls how send() behaves after the provider accepts a request:
|
|
2518
|
+
* - `UnetSocket.NON_BLOCKING` (0): returns immediately after the provider agrees.
|
|
2519
|
+
* - `UnetSocket.SEMI_BLOCKING` (1): if reliability is not true, returns after AGREE; otherwise
|
|
2520
|
+
* waits for a delivery confirmation (RemoteDeliveryNtf / DatagramDeliveryNtf) or failure.
|
|
2521
|
+
* - `UnetSocket.BLOCKING` (2): waits for a transmission or delivery notification
|
|
2522
|
+
* (DatagramTransmissionNtf, DatagramDeliveryNtf) before returning.
|
|
2523
|
+
* The default is SEMI_BLOCKING.
|
|
2524
|
+
* @param {number} sendMode - one of UnetSocket.NON_BLOCKING, SEMI_BLOCKING, or BLOCKING
|
|
2525
|
+
* @returns {void}
|
|
2526
|
+
*/
|
|
2527
|
+
setSendMode(sendMode) {
|
|
2528
|
+
if ([NON_BLOCKING, SEMI_BLOCKING, BLOCKING].includes(sendMode)) this._sendMode = sendMode;
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
/**
|
|
2532
|
+
* Gets the current send mode.
|
|
2533
|
+
* @returns {number} - current send mode (NON_BLOCKING=0, SEMI_BLOCKING=1, BLOCKING=2)
|
|
2534
|
+
*/
|
|
2535
|
+
getSendMode() {
|
|
2536
|
+
return this._sendMode;
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
async _chooseAgentForService(service) {
|
|
2540
|
+
const agents = await this._gw.agentsForService(service);
|
|
2541
|
+
if (agents == null || agents.length === 0) return null;
|
|
2542
|
+
return agents[Math.floor(Math.random() * agents.length)];
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
async _resolveProvider() {
|
|
2546
|
+
if (this._serviceProvider != null) return this._serviceProvider;
|
|
2547
|
+
const serviceOrder = [
|
|
2548
|
+
Services.REMOTE,
|
|
2549
|
+
Services.TRANSPORT,
|
|
2550
|
+
Services.ROUTING,
|
|
2551
|
+
Services.LINK,
|
|
2552
|
+
Services.PHYSICAL,
|
|
2553
|
+
Services.DATAGRAM,
|
|
2554
|
+
];
|
|
2555
|
+
for (const service of serviceOrder) {
|
|
2556
|
+
const provider = await this._chooseAgentForService(service);
|
|
2557
|
+
if (provider != null) return provider;
|
|
2558
|
+
}
|
|
2559
|
+
return null;
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
_applySocketSettings(req) {
|
|
2563
|
+
if (!hasValue(req.priority) && hasValue(this._priority)) req.priority = this._priority;
|
|
2564
|
+
if (!hasValue(req.reliability) && hasValue(this._reliability)) req.reliability = this._reliability;
|
|
2565
|
+
if ((!hasValue(req.ttl) || Number.isNaN(req.ttl)) && hasFiniteNumber(this._ttl)) req.ttl = this._ttl;
|
|
2566
|
+
if (!hasValue(req.route) && hasValue(this._route)) req.route = this._route;
|
|
2567
|
+
if (!hasValue(req.mimeType) && hasValue(this._mimeType)) req.mimeType = this._mimeType;
|
|
2568
|
+
if (!hasValue(req.remoteRecipient) && hasValue(this._remoteRecipient)) req.remoteRecipient = this._remoteRecipient;
|
|
2569
|
+
if (!hasValue(req.mailbox) && hasValue(this._mailbox)) req.mailbox = this._mailbox;
|
|
2570
|
+
if (!hasValue(req.messageClass) && hasValue(this._messageClass)) req.messageClass = this._messageClass;
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
_effectiveReliability(req) {
|
|
2574
|
+
return hasValue(req.reliability) ? req.reliability : this._reliability;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
async _waitForNotification(req, types, timeout = REQUEST_TIMEOUT) {
|
|
2578
|
+
return await this._gw.receive(msg => {
|
|
2579
|
+
if (!types.some(type => msg instanceof type)) return false;
|
|
2580
|
+
if (hasValue(msg.inReplyTo) && msg.inReplyTo === req.msgID) return true;
|
|
2581
|
+
return false;
|
|
2582
|
+
}, timeout);
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
async _waitForSemiBlockingOutcome(req) {
|
|
2586
|
+
const notification = await this._waitForNotification(req, [
|
|
2587
|
+
DatagramDeliveryNtf,
|
|
2588
|
+
DatagramFailureNtf,
|
|
2589
|
+
RemoteDeliveryNtf,
|
|
2590
|
+
RemoteSuccessNtf,
|
|
2591
|
+
RemoteFailureNtf,
|
|
2592
|
+
]);
|
|
2593
|
+
if (notification == null) return false;
|
|
2594
|
+
if (notification instanceof DatagramFailureNtf || notification instanceof RemoteFailureNtf) return false;
|
|
2595
|
+
return true;
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
async _waitForBlockingOutcome(req) {
|
|
2599
|
+
const notification = await this._waitForNotification(req, [
|
|
2600
|
+
DatagramTransmissionNtf,
|
|
2601
|
+
DatagramDeliveryNtf,
|
|
2602
|
+
DatagramFailureNtf,
|
|
2603
|
+
RemoteDeliveryNtf,
|
|
2604
|
+
RemoteSuccessNtf,
|
|
2605
|
+
RemoteFailureNtf,
|
|
2606
|
+
]);
|
|
2607
|
+
if (notification == null) return false;
|
|
2608
|
+
if (notification instanceof DatagramFailureNtf || notification instanceof RemoteFailureNtf) return false;
|
|
2609
|
+
return true;
|
|
2610
|
+
}
|
|
2507
2611
|
|
|
2508
2612
|
/**
|
|
2509
2613
|
* Transmits a datagram to the specified node address using the specified protocol.
|
|
@@ -2514,32 +2618,43 @@ class UnetSocket {
|
|
|
2514
2618
|
* @param {number} protocol - protocol number
|
|
2515
2619
|
* @returns {Promise<boolean>} - true if the Unet node agreed to send out the Datagram, false otherwise
|
|
2516
2620
|
*/
|
|
2517
|
-
async send(data, to=this.
|
|
2518
|
-
if (
|
|
2519
|
-
|
|
2520
|
-
if (Array.isArray(data)){
|
|
2621
|
+
async send(data, to=this._remoteAddress, protocol=this._remoteProtocol) {
|
|
2622
|
+
if (this._gw == null) return false;
|
|
2623
|
+
let req;
|
|
2624
|
+
if (Array.isArray(data)) {
|
|
2521
2625
|
req = new DatagramReq();
|
|
2522
2626
|
req.data = data;
|
|
2523
2627
|
req.to = to;
|
|
2524
2628
|
req.protocol = protocol;
|
|
2525
|
-
} else if (data instanceof DatagramReq){
|
|
2629
|
+
} else if (data instanceof DatagramReq) {
|
|
2526
2630
|
req = data;
|
|
2631
|
+
if (!this._warnedDeprecatedSend && typeof console !== 'undefined' && typeof console.warn === 'function') {
|
|
2632
|
+
console.warn('UnetSocket.send(DatagramReq) is deprecated; prefer socket metadata setters with send(data, to, protocol).');
|
|
2633
|
+
this._warnedDeprecatedSend = true;
|
|
2634
|
+
}
|
|
2527
2635
|
} else {
|
|
2528
2636
|
return false;
|
|
2529
2637
|
}
|
|
2530
|
-
|
|
2531
|
-
if (
|
|
2638
|
+
if ((!hasValue(req.to) || req.to < 0) && to >= 0) req.to = to;
|
|
2639
|
+
if (!hasValue(req.protocol)) req.protocol = protocol;
|
|
2640
|
+
this._applySocketSettings(req);
|
|
2641
|
+
|
|
2642
|
+
if (!Array.isArray(req.data) || req.to < 0 || isReservedProtocol(req.protocol)) return false;
|
|
2532
2643
|
if (req.recipient == null) {
|
|
2533
|
-
|
|
2534
|
-
if (
|
|
2535
|
-
if (this.provider == null) this.provider = await this.gw.agentForService(Services.LINK);
|
|
2536
|
-
if (this.provider == null) this.provider = await this.gw.agentForService(Services.PHYSICAL);
|
|
2537
|
-
if (this.provider == null) this.provider = await this.gw.agentForService(Services.DATAGRAM);
|
|
2538
|
-
if (this.provider == null) return false;
|
|
2539
|
-
req.recipient = this.provider;
|
|
2644
|
+
req.recipient = await this._resolveProvider();
|
|
2645
|
+
if (req.recipient == null) return false;
|
|
2540
2646
|
}
|
|
2541
|
-
const rsp = await this.
|
|
2542
|
-
|
|
2647
|
+
const rsp = await this._gw.request(req, REQUEST_TIMEOUT);
|
|
2648
|
+
if (rsp == null || rsp.perf != Performative.AGREE) return false;
|
|
2649
|
+
|
|
2650
|
+
if (this._sendMode === NON_BLOCKING) return true;
|
|
2651
|
+
|
|
2652
|
+
if (this._sendMode === SEMI_BLOCKING) {
|
|
2653
|
+
if (this._effectiveReliability(req) !== true) return true;
|
|
2654
|
+
return await this._waitForSemiBlockingOutcome(req);
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
return await this._waitForBlockingOutcome(req);
|
|
2543
2658
|
}
|
|
2544
2659
|
|
|
2545
2660
|
/**
|
|
@@ -2549,22 +2664,23 @@ class UnetSocket {
|
|
|
2549
2664
|
* @returns {Promise<?DatagramNtf>} - datagram received by the socket
|
|
2550
2665
|
*/
|
|
2551
2666
|
async receive() {
|
|
2552
|
-
if (this.
|
|
2553
|
-
return await this.
|
|
2554
|
-
if (msg
|
|
2667
|
+
if (this._gw == null) return null;
|
|
2668
|
+
return await this._gw.receive(msg => {
|
|
2669
|
+
if (!(msg instanceof DatagramNtf)) return false;
|
|
2555
2670
|
let p = msg.protocol;
|
|
2671
|
+
if (msg.to != BROADCAST_ADDR && msg.to != this._localAddress) return false; // Datagram not addressed to this node
|
|
2556
2672
|
if (p == Protocol.DATA || p >= Protocol.USER) {
|
|
2557
|
-
return this.
|
|
2673
|
+
return this._localProtocol < 0 || this._localProtocol == p;
|
|
2558
2674
|
}
|
|
2559
2675
|
return false;
|
|
2560
|
-
}, this.
|
|
2676
|
+
}, this._timeout);
|
|
2561
2677
|
}
|
|
2562
2678
|
|
|
2563
2679
|
/**
|
|
2564
2680
|
* Gets a Gateway to provide low-level access to UnetStack.
|
|
2565
2681
|
* @returns {Gateway} - underlying fjage Gateway supporting this socket
|
|
2566
2682
|
*/
|
|
2567
|
-
getGateway() { return this.
|
|
2683
|
+
getGateway() { return this._gw; }
|
|
2568
2684
|
|
|
2569
2685
|
/**
|
|
2570
2686
|
* Gets an AgentID providing a specified service for low-level access to UnetStack
|
|
@@ -2572,8 +2688,8 @@ class UnetSocket {
|
|
|
2572
2688
|
* @returns {Promise<?AgentID>} - a promise which returns an {@link AgentID} that provides the service when resolved
|
|
2573
2689
|
*/
|
|
2574
2690
|
async agentForService(svc) {
|
|
2575
|
-
if (this.
|
|
2576
|
-
return await this.
|
|
2691
|
+
if (this._gw == null) return null;
|
|
2692
|
+
return await this._gw.agentForService(svc);
|
|
2577
2693
|
}
|
|
2578
2694
|
|
|
2579
2695
|
/**
|
|
@@ -2582,8 +2698,8 @@ class UnetSocket {
|
|
|
2582
2698
|
* @returns {Promise<AgentID[]>} - a promise which returns an array of {@link AgentID|AgentIDs} that provides the service when resolved
|
|
2583
2699
|
*/
|
|
2584
2700
|
async agentsForService(svc) {
|
|
2585
|
-
if (this.
|
|
2586
|
-
return await this.
|
|
2701
|
+
if (this._gw == null) return null;
|
|
2702
|
+
return await this._gw.agentsForService(svc);
|
|
2587
2703
|
}
|
|
2588
2704
|
|
|
2589
2705
|
/**
|
|
@@ -2592,8 +2708,8 @@ class UnetSocket {
|
|
|
2592
2708
|
* @returns {AgentID} - AgentID for the given name
|
|
2593
2709
|
*/
|
|
2594
2710
|
agent(name) {
|
|
2595
|
-
if (this.
|
|
2596
|
-
return this.
|
|
2711
|
+
if (this._gw == null) return null;
|
|
2712
|
+
return this._gw.agent(name);
|
|
2597
2713
|
}
|
|
2598
2714
|
|
|
2599
2715
|
/**
|
|
@@ -2607,15 +2723,42 @@ class UnetSocket {
|
|
|
2607
2723
|
const req = new AddressResolutionReq(nodeName);
|
|
2608
2724
|
req.name = nodeName;
|
|
2609
2725
|
req.recipient = arp;
|
|
2610
|
-
const rsp = await this.
|
|
2726
|
+
const rsp = await this._gw.request(req, REQUEST_TIMEOUT);
|
|
2611
2727
|
if (rsp == null || ! Object.prototype.hasOwnProperty.call(rsp, 'address')) return null;
|
|
2612
2728
|
return rsp.address;
|
|
2613
2729
|
}
|
|
2730
|
+
|
|
2731
|
+
/**
|
|
2732
|
+
* Registers a callback function to be called when a parameter value changes for the local node. This
|
|
2733
|
+
* uses the ParamChangeNtf messages published by the Unet node to notify of parameter changes. The callback
|
|
2734
|
+
* function will be called with the new value of the parameter.
|
|
2735
|
+
*
|
|
2736
|
+
* @param {AgentID|string} agentId
|
|
2737
|
+
* @param {string} paramName
|
|
2738
|
+
* @param {function(object): void} callback
|
|
2739
|
+
*/
|
|
2740
|
+
onParamChange(agentId, paramName, callback) {
|
|
2741
|
+
if (agentId instanceof AgentID) agentId = agentId.name;
|
|
2742
|
+
this._paramChangeCallbacks[agentId + '.' + paramName] = callback;
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
/**
|
|
2746
|
+
* Removes a callback function registered to be called when a parameter value changes for the local node.
|
|
2747
|
+
*
|
|
2748
|
+
* @param {AgentID|string} agentId
|
|
2749
|
+
* @param {string} paramName
|
|
2750
|
+
*/
|
|
2751
|
+
removeParamChange(agentId, paramName) {
|
|
2752
|
+
if (agentId instanceof AgentID) agentId = agentId.name;
|
|
2753
|
+
delete this._paramChangeCallbacks[agentId + '.' + paramName];
|
|
2754
|
+
}
|
|
2614
2755
|
}
|
|
2615
2756
|
|
|
2757
|
+
UnetSocket.NON_BLOCKING = NON_BLOCKING;
|
|
2758
|
+
UnetSocket.SEMI_BLOCKING = SEMI_BLOCKING;
|
|
2759
|
+
UnetSocket.BLOCKING = BLOCKING;
|
|
2760
|
+
|
|
2616
2761
|
exports.AgentID = AgentID;
|
|
2617
|
-
exports.CachingAgentID = CachingAgentID;
|
|
2618
|
-
exports.CachingGateway = CachingGateway;
|
|
2619
2762
|
exports.Gateway = Gateway;
|
|
2620
2763
|
exports.Message = Message;
|
|
2621
2764
|
exports.MessageClass = MessageClass;
|
|
@@ -2624,5 +2767,6 @@ exports.Protocol = Protocol;
|
|
|
2624
2767
|
exports.Services = Services;
|
|
2625
2768
|
exports.UnetMessages = UnetMessages;
|
|
2626
2769
|
exports.UnetSocket = UnetSocket;
|
|
2770
|
+
exports.UnetTopics = UnetTopics;
|
|
2627
2771
|
exports.toGps = toGps;
|
|
2628
2772
|
exports.toLocal = toLocal;
|