@transitive-sdk/utils-web 0.14.14 → 0.16.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/utils-web.js +73 -36
- package/package.json +1 -1
package/dist/utils-web.js
CHANGED
|
@@ -406,6 +406,8 @@ var require_common = __commonJS({
|
|
|
406
406
|
callback && callback(count);
|
|
407
407
|
}, delay);
|
|
408
408
|
};
|
|
409
|
+
var storageRequestToSelector = (topic) => pathToTopic2(topicToPath2(topic).map((value) => value == "$store" ? "+" : value).map((value) => value == "$storeTail" ? "#" : value));
|
|
410
|
+
var selectorToStorageRequest = (topic) => pathToTopic2(topicToPath2(topic).map((value) => value[0] == "+" ? "$store" : value).map((value) => value[0] == "#" ? "$storeTail" : value));
|
|
409
411
|
var getRandomId = (bytes = 6) => {
|
|
410
412
|
const buffer = new Uint8Array(bytes);
|
|
411
413
|
crypto.getRandomValues(buffer);
|
|
@@ -494,7 +496,9 @@ var require_common = __commonJS({
|
|
|
494
496
|
formatDuration,
|
|
495
497
|
tryJSONParse,
|
|
496
498
|
decodeJWT: decodeJWT3,
|
|
497
|
-
visitAncestor
|
|
499
|
+
visitAncestor,
|
|
500
|
+
storageRequestToSelector,
|
|
501
|
+
selectorToStorageRequest
|
|
498
502
|
};
|
|
499
503
|
}
|
|
500
504
|
});
|
|
@@ -713,7 +717,8 @@ var require_MqttSync = __commonJS({
|
|
|
713
717
|
versionCompare,
|
|
714
718
|
encodeTopicElement,
|
|
715
719
|
visitAncestor,
|
|
716
|
-
getRandomId
|
|
720
|
+
getRandomId,
|
|
721
|
+
selectorToStorageRequest
|
|
717
722
|
} = require_common();
|
|
718
723
|
var { DataCache } = require_DataCache();
|
|
719
724
|
var log2 = getLogger2("MqttSync");
|
|
@@ -771,7 +776,8 @@ var require_MqttSync = __commonJS({
|
|
|
771
776
|
migrate,
|
|
772
777
|
onReady,
|
|
773
778
|
sliceTopic,
|
|
774
|
-
onHeartbeatGranted
|
|
779
|
+
onHeartbeatGranted,
|
|
780
|
+
inclMeta
|
|
775
781
|
}) {
|
|
776
782
|
this.mqtt = mqttClient;
|
|
777
783
|
this.sliceTopic = sliceTopic;
|
|
@@ -796,9 +802,13 @@ var require_MqttSync = __commonJS({
|
|
|
796
802
|
path = path.slice(sliceTopic);
|
|
797
803
|
topic = pathToTopic2(path);
|
|
798
804
|
}
|
|
799
|
-
if (
|
|
805
|
+
if (!inclMeta && path.some((field) => field[0] == "$")) {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
const rpcHandler = this.getRPCHandler(topic);
|
|
809
|
+
if (rpcHandler) {
|
|
800
810
|
const json = mqttParsePayload(payload);
|
|
801
|
-
this.handleRPCRequest(
|
|
811
|
+
this.handleRPCRequest(path, rpcHandler, json);
|
|
802
812
|
} else if (this.rpcCallbacks[topic]) {
|
|
803
813
|
const json = mqttParsePayload(payload);
|
|
804
814
|
this.handleRPCResponse(topic, json);
|
|
@@ -976,15 +986,15 @@ var require_MqttSync = __commonJS({
|
|
|
976
986
|
callback && callback(count);
|
|
977
987
|
});
|
|
978
988
|
}
|
|
979
|
-
/**
|
|
989
|
+
/** Register a callback for the next heartbeat from the broker */
|
|
980
990
|
waitForHeartbeatOnce(callback) {
|
|
981
991
|
setTimeout(() => this.heartbeatWaitersOnce.push(callback), 1);
|
|
982
992
|
}
|
|
983
|
-
|
|
993
|
+
/* check whether we are subscribed to the given topic */
|
|
984
994
|
isSubscribed(topic) {
|
|
985
995
|
return Object.keys(this.subscribedPaths).some((subscribedTopic) => topicMatch(subscribedTopic, topic));
|
|
986
996
|
}
|
|
987
|
-
|
|
997
|
+
/* Check whether we are publishing the given topic in a non-atomic way.
|
|
988
998
|
This is used to determine whether to store the published value or not. */
|
|
989
999
|
isPublished(topic) {
|
|
990
1000
|
return Object.keys(this.publishedPaths).some(
|
|
@@ -1018,7 +1028,7 @@ var require_MqttSync = __commonJS({
|
|
|
1018
1028
|
delete this.subscribedPaths[topic];
|
|
1019
1029
|
}
|
|
1020
1030
|
}
|
|
1021
|
-
|
|
1031
|
+
/* Publish retained to MQTT, store as published, and return a promise */
|
|
1022
1032
|
_actuallyPublish(topic, value) {
|
|
1023
1033
|
if (!this.mqtt.connected) {
|
|
1024
1034
|
log2.warn("not connected, not publishing", topic);
|
|
@@ -1033,7 +1043,7 @@ var require_MqttSync = __commonJS({
|
|
|
1033
1043
|
);
|
|
1034
1044
|
return true;
|
|
1035
1045
|
}
|
|
1036
|
-
|
|
1046
|
+
/* Send all items in the queue in sequence, if any and if not already
|
|
1037
1047
|
running. */
|
|
1038
1048
|
// async _processQueue() {
|
|
1039
1049
|
// if (this._processing) return; // already running (and probably waiting)
|
|
@@ -1082,7 +1092,7 @@ var require_MqttSync = __commonJS({
|
|
|
1082
1092
|
addToQueue(topic, value) {
|
|
1083
1093
|
this.publishQueue.set(topic, value);
|
|
1084
1094
|
}
|
|
1085
|
-
|
|
1095
|
+
/* Add to publication queue */
|
|
1086
1096
|
_enqueue(topic, value) {
|
|
1087
1097
|
log2.debug("enqueuing", topic);
|
|
1088
1098
|
this.addToQueue(topic, value);
|
|
@@ -1174,12 +1184,17 @@ var require_MqttSync = __commonJS({
|
|
|
1174
1184
|
/* --------------------------------------------------------------------------
|
|
1175
1185
|
* Remote Procedure Calls (RPC)
|
|
1176
1186
|
*/
|
|
1187
|
+
/** Given a (ground) topic find the matching RPC handler, if any. This is
|
|
1188
|
+
* needed because RPC topics can include wildcards. */
|
|
1189
|
+
getRPCHandler(topic) {
|
|
1190
|
+
return _3.find(this.rpcHandlers, (_handler, topicSelector) => topicMatch(topicSelector, topic));
|
|
1191
|
+
}
|
|
1177
1192
|
/* Handle RPC requests */
|
|
1178
|
-
async handleRPCRequest(
|
|
1179
|
-
log2.debug("handling RPC request for",
|
|
1180
|
-
const
|
|
1181
|
-
const result = handler(json.args);
|
|
1182
|
-
const responseTopic = `${
|
|
1193
|
+
async handleRPCRequest(path, handler, json) {
|
|
1194
|
+
log2.debug("handling RPC request for", path, json);
|
|
1195
|
+
const commandTopic = pathToTopic2(path.slice(0, -1));
|
|
1196
|
+
const result = handler(json.args, commandTopic);
|
|
1197
|
+
const responseTopic = `${commandTopic}/response/${json.id}`;
|
|
1183
1198
|
if (result instanceof Promise) {
|
|
1184
1199
|
result.then((resultValue) => this.mqtt.publish(
|
|
1185
1200
|
responseTopic,
|
|
@@ -1202,24 +1217,29 @@ var require_MqttSync = __commonJS({
|
|
|
1202
1217
|
this.mqtt.unsubscribe(topic);
|
|
1203
1218
|
}
|
|
1204
1219
|
/** Register an RPC request handler. Example:
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1220
|
+
* ```js
|
|
1221
|
+
* mqttSync.register('/mySquare', (arg, commandTopic) => {
|
|
1222
|
+
* log.debug('we got request on topic', commandTopic);
|
|
1223
|
+
* log.debug('running /mySquare with args', arg);
|
|
1224
|
+
* return arg * arg;
|
|
1225
|
+
* });
|
|
1226
|
+
* ```
|
|
1227
|
+
* Note that the command topic needs to be in the capabilities namespace like
|
|
1228
|
+
* any other topic. In robot capabilities, as usual, these can start in `/`
|
|
1229
|
+
* because the local mqtt bridge operated by the robot agent will place all
|
|
1230
|
+
* topics in their respective namespace. In the cloud and on the web you will
|
|
1231
|
+
* need to use the respective namespace, i.e.,
|
|
1232
|
+
* `/orgId/deviceId/@scope/capName/capVersion/`.
|
|
1233
|
+
*
|
|
1234
|
+
* You can use wildcards in the registered topic. The handler will receive the
|
|
1235
|
+
* actual, ground topic the request was made on as the second argument. This
|
|
1236
|
+
* allows you to make the RPCs behavior depend on the topic.
|
|
1237
|
+
*
|
|
1238
|
+
* #### Async/Await
|
|
1239
|
+
* Yes, you can make the handler `async` and use `await` inside of it. This
|
|
1240
|
+
* will be handled correctly, i.e., MqttSync will await the result of the
|
|
1241
|
+
* handler before responding to the RPC request client.
|
|
1242
|
+
*/
|
|
1223
1243
|
register(command, handler) {
|
|
1224
1244
|
log2.debug("registering RPC handler for", command);
|
|
1225
1245
|
const requestTopic = `${command}/request`;
|
|
@@ -1234,13 +1254,22 @@ var require_MqttSync = __commonJS({
|
|
|
1234
1254
|
}
|
|
1235
1255
|
/** Make an RPC request. Example:
|
|
1236
1256
|
* ```js
|
|
1237
|
-
* mqttSync.call('/mySquare', 11, result => {
|
|
1257
|
+
* mqttSync.call('/orgId/deviceId/@capScope/capName/capVersion/mySquare', 11, result => {
|
|
1238
1258
|
* log.debug(`Called /mySquare with arg 11 and got ${result}`);
|
|
1239
1259
|
* });
|
|
1240
1260
|
* ```
|
|
1261
|
+
* This would call the RPC 'mySquare' registered by version `capVersion` of the
|
|
1262
|
+
* capability `@capScope/capName` running on device `deviceId` by user `orgId`.
|
|
1263
|
+
* That RPC would have been registered on the device using
|
|
1264
|
+
* `mqttSync.register('/mySquare', ...)` as shown above (because namespaces
|
|
1265
|
+
* on the device are auto-extended to the org, device and capability).
|
|
1266
|
+
*
|
|
1267
|
+
* RPCs are typically registered on the robot and called from the web or cloud
|
|
1268
|
+
* but the inverse is also possible, with the same namespace caveat.
|
|
1269
|
+
*
|
|
1241
1270
|
* Alternative you can omit the callback and use async/await:
|
|
1242
1271
|
* ```js
|
|
1243
|
-
* const result = await mqttSync.call('/mySquare', 11);
|
|
1272
|
+
* const result = await mqttSync.call('${prefix}/mySquare', 11);
|
|
1244
1273
|
* log.debug(`Called /mySquare with arg 11 and got ${result}`);
|
|
1245
1274
|
* ```
|
|
1246
1275
|
* See the note about namespaces in `register`.
|
|
@@ -1273,6 +1302,14 @@ var require_MqttSync = __commonJS({
|
|
|
1273
1302
|
});
|
|
1274
1303
|
}
|
|
1275
1304
|
}
|
|
1305
|
+
/** Request the history of the described topics (selector with wildcards) to
|
|
1306
|
+
* be stored in ClickHouse for the `ttl` number of days (if the mqtt2clickhouse
|
|
1307
|
+
* service is running -- as it usually is inside the
|
|
1308
|
+
* transitiverobotics/clickhouse docker image). */
|
|
1309
|
+
requestHistoryStorage(topic, ttl = 1) {
|
|
1310
|
+
const storageRequest = selectorToStorageRequest(topic);
|
|
1311
|
+
this.mqtt.publish(storageRequest, String(ttl), { retain: true });
|
|
1312
|
+
}
|
|
1276
1313
|
};
|
|
1277
1314
|
module2.exports = MqttSync3;
|
|
1278
1315
|
}
|