@dronedeploy/rocos-js-sdk 3.0.30 → 3.1.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/cjs/api/streams/caller/CallerStreamAbstract.js +1 -2
- package/cjs/api/streams/caller/CallerStreamNode.js +18 -8
- package/cjs/api/streams/command/CommandStreamNode.js +17 -7
- package/cjs/api/streams/control/ControlStreamNode.js +17 -7
- package/cjs/api/streams/fileAccessor/FileAccessorStreamNode.js +17 -7
- package/cjs/api/streams/search/SearchStreamNode.js +17 -7
- package/cjs/api/streams/telemetry/TelemetryStream.js +1 -0
- package/cjs/api/streams/telemetry/TelemetryStreamConnect.d.ts +26 -0
- package/cjs/api/streams/telemetry/TelemetryStreamConnect.js +145 -0
- package/cjs/api/streams/telemetry/TelemetryStreamNode.js +18 -9
- package/cjs/grpc/conker_pb.grpc-client.js +17 -7
- package/cjs/grpc/connect/teletubby_pb.d.ts +635 -0
- package/cjs/grpc/connect/teletubby_pb.js +196 -0
- package/cjs/grpc/filagree_pb.grpc-client.js +17 -7
- package/cjs/grpc/pigeon_pb.grpc-client.js +17 -7
- package/cjs/grpc/rambo.v1_pb.grpc-client.js +17 -7
- package/cjs/grpc/serviette.v1_pb.grpc-client.js +17 -7
- package/cjs/grpc/slowlane_pb.grpc-client.js +17 -7
- package/cjs/grpc/teletubby_pb.grpc-client.js +17 -7
- package/cjs/helpers/callerMessageHelpers.js +2 -3
- package/cjs/helpers/flattenOneOf.js +2 -3
- package/cjs/helpers/generateUUID.js +1 -2
- package/cjs/helpers/getSha256Hex.d.ts +1 -1
- package/cjs/helpers/getSha256HexNode.d.ts +1 -1
- package/cjs/helpers/kscript/index.js +17 -7
- package/cjs/helpers/kscript/utils.js +1 -2
- package/cjs/helpers/splitRobotTopic.js +1 -2
- package/cjs/helpers/stringToUint8Array.js +1 -8
- package/cjs/helpers/websandbox/connection.d.ts +1 -1
- package/cjs/logger/RocosLogger.js +9 -30
- package/cjs/models/IRocosSDKConfig.d.ts +2 -0
- package/cjs/models/IStreamConfig.d.ts +3 -0
- package/cjs/models/asset-storage/SyncIntegrations.d.ts +1 -2
- package/cjs/services/CallerService.js +1 -2
- package/cjs/services/SpotProvisioningServiceNode.d.ts +0 -1
- package/cjs/services/TelemetryService.js +5 -0
- package/esm/api/streams/caller/CallerStreamAbstract.js +1 -2
- package/esm/api/streams/caller/CallerStreamNode.js +1 -1
- package/esm/api/streams/telemetry/TelemetryStream.js +1 -0
- package/esm/api/streams/telemetry/TelemetryStreamConnect.d.ts +26 -0
- package/esm/api/streams/telemetry/TelemetryStreamConnect.js +141 -0
- package/esm/api/streams/telemetry/TelemetryStreamNode.js +1 -2
- package/esm/grpc/connect/teletubby_pb.d.ts +635 -0
- package/esm/grpc/connect/teletubby_pb.js +193 -0
- package/esm/helpers/generateUUID.js +1 -2
- package/esm/helpers/getSha256Hex.d.ts +1 -1
- package/esm/helpers/getSha256HexNode.d.ts +1 -1
- package/esm/helpers/stringToUint8Array.js +1 -8
- package/esm/helpers/websandbox/connection.d.ts +1 -1
- package/esm/logger/RocosLogger.js +9 -7
- package/esm/models/IRocosSDKConfig.d.ts +2 -0
- package/esm/models/IStreamConfig.d.ts +3 -0
- package/esm/models/asset-storage/SyncIntegrations.d.ts +1 -2
- package/esm/services/CallerService.js +1 -2
- package/esm/services/SpotProvisioningServiceNode.d.ts +0 -1
- package/esm/services/TelemetryService.js +5 -0
- package/package.json +5 -7
|
@@ -9,7 +9,6 @@ const BaseStreamService_1 = require("./BaseStreamService");
|
|
|
9
9
|
const CallerStream_1 = require("../api/streams/caller/CallerStream");
|
|
10
10
|
const identifier_1 = require("../constants/identifier");
|
|
11
11
|
const helpers_1 = require("../helpers");
|
|
12
|
-
const uuid_1 = require("uuid");
|
|
13
12
|
class CallerService extends BaseStreamService_1.BaseStreamService {
|
|
14
13
|
constructor(config) {
|
|
15
14
|
super('CallerService', config);
|
|
@@ -66,7 +65,7 @@ class CallerService extends BaseStreamService_1.BaseStreamService {
|
|
|
66
65
|
}
|
|
67
66
|
getCallerParams(params, component, topic) {
|
|
68
67
|
return {
|
|
69
|
-
uid: params.options?.uid ??
|
|
68
|
+
uid: params.options?.uid ?? crypto.randomUUID(),
|
|
70
69
|
projectId: params.projectId,
|
|
71
70
|
callsign: params.callsign,
|
|
72
71
|
subSystem: '',
|
|
@@ -8,6 +8,7 @@ const BaseStreamService_1 = require("./BaseStreamService");
|
|
|
8
8
|
const identifier_1 = require("../constants/identifier");
|
|
9
9
|
const RocosStore_1 = require("../store/RocosStore");
|
|
10
10
|
const TelemetryStream_1 = require("../api/streams/telemetry/TelemetryStream");
|
|
11
|
+
const TelemetryStreamConnect_1 = require("../api/streams/telemetry/TelemetryStreamConnect");
|
|
11
12
|
const arrayUnique_1 = require("../helpers/arrayUnique");
|
|
12
13
|
const flattenCallsignsLookup_1 = require("../helpers/flattenCallsignsLookup");
|
|
13
14
|
const getUniqueId_1 = require("../helpers/getUniqueId");
|
|
@@ -162,6 +163,7 @@ class TelemetryService extends BaseStreamService_1.BaseStreamService {
|
|
|
162
163
|
options: this.config.options,
|
|
163
164
|
port: this.config.port,
|
|
164
165
|
insecure: this.config.insecure,
|
|
166
|
+
transport: this.config.transport,
|
|
165
167
|
});
|
|
166
168
|
if (!newStream.isNew) {
|
|
167
169
|
newStream.stream.statusStream$.subscribe((msg) => {
|
|
@@ -174,6 +176,9 @@ class TelemetryService extends BaseStreamService_1.BaseStreamService {
|
|
|
174
176
|
return newStream.stream;
|
|
175
177
|
}
|
|
176
178
|
getStream(config) {
|
|
179
|
+
if (config.transport === 'connect') {
|
|
180
|
+
return new TelemetryStreamConnect_1.TelemetryStreamConnect(config);
|
|
181
|
+
}
|
|
177
182
|
return new TelemetryStream_1.TelemetryStream(config);
|
|
178
183
|
}
|
|
179
184
|
}
|
|
@@ -6,7 +6,6 @@ import { IDENTIFIER_NAME_CALLER } from '../../../constants/identifier';
|
|
|
6
6
|
import { RocosStore } from '../../../store/RocosStore';
|
|
7
7
|
import { StreamRegister } from '../../StreamRegister';
|
|
8
8
|
import { filter } from 'rxjs/operators';
|
|
9
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
10
9
|
export class CallerStreamAbstract {
|
|
11
10
|
constructor(config) {
|
|
12
11
|
this.subscriberStatus = SubscriberStatusEnum.STOPPED;
|
|
@@ -78,7 +77,7 @@ export class CallerStreamAbstract {
|
|
|
78
77
|
version: UIDVersion.HEADER_HASH_RAND,
|
|
79
78
|
content: {
|
|
80
79
|
oneofKind: 'hash',
|
|
81
|
-
hash: uid ??
|
|
80
|
+
hash: uid ?? crypto.randomUUID(),
|
|
82
81
|
},
|
|
83
82
|
},
|
|
84
83
|
payload: this.getPayload(payload),
|
|
@@ -102,7 +102,7 @@ export class CallerStreamNode extends CallerStreamAbstract {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
getPayload(payload) {
|
|
105
|
-
return
|
|
105
|
+
return new TextEncoder().encode(payload);
|
|
106
106
|
}
|
|
107
107
|
getMetadata(projectId, callsign, subsystem) {
|
|
108
108
|
const meta = new grpc.Metadata();
|
|
@@ -12,6 +12,7 @@ export class TelemetryStream extends TelemetryStreamAbstract {
|
|
|
12
12
|
const port = config.port ? `:${config.port}` : '';
|
|
13
13
|
const transport = new GrpcWebFetchTransport({
|
|
14
14
|
baseUrl: `${protocol}://${this.url}${port}`,
|
|
15
|
+
format: config.grpcWebFormat,
|
|
15
16
|
});
|
|
16
17
|
this.client = new TelemetryGatewayClient(transport);
|
|
17
18
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ITelemetryStreamConfig } from '../../../models';
|
|
2
|
+
import { TelemetryAckStatus, TelemetryQueryRequest, TelemetryRequest } from '../../../grpc/teletubby_pb';
|
|
3
|
+
import { TelemetryStreamAbstract } from './TelemetryStreamAbstract';
|
|
4
|
+
/**
|
|
5
|
+
* Connect-protocol telemetry receive stream. Mirrors TelemetryStream (grpc-web) but uses
|
|
6
|
+
* @connectrpc/connect. Selected when config.transport === 'connect'.
|
|
7
|
+
*
|
|
8
|
+
* The shared TelemetryStreamAbstract is typed with the protobuf-ts message types, while the
|
|
9
|
+
* Connect client uses @bufbuild/protobuf types. Both serialise to identical protobuf wire
|
|
10
|
+
* bytes, so we bridge across the boundary with toBinary/fromBinary rather than hand-written
|
|
11
|
+
* field mapping. This keeps all reconnect/subscription/heartbeat logic shared and untouched.
|
|
12
|
+
*/
|
|
13
|
+
export declare class TelemetryStreamConnect extends TelemetryStreamAbstract {
|
|
14
|
+
private client;
|
|
15
|
+
private abortController?;
|
|
16
|
+
constructor(config: ITelemetryStreamConfig);
|
|
17
|
+
protected stopInternal(): void;
|
|
18
|
+
protected registerReceiver(): () => void;
|
|
19
|
+
private onError;
|
|
20
|
+
private onEnd;
|
|
21
|
+
private getHeaders;
|
|
22
|
+
protected requestTelemetry(req: TelemetryRequest): Promise<void>;
|
|
23
|
+
protected requestTelemetryQuery(req: TelemetryQueryRequest): Promise<void>;
|
|
24
|
+
protected sendAcknowledgmentInternal(uid: string, status: TelemetryAckStatus, noRetry: boolean): boolean;
|
|
25
|
+
protected sendHeartbeat(): void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createClient } from '@connectrpc/connect';
|
|
2
|
+
import { SubscriberStatusEnum } from '../../../models';
|
|
3
|
+
import { RegistrationMessageSchema, TelemetryGateway, TelemetryQueryRequestSchema, TelemetryRequestSchema, } from '../../../grpc/connect/teletubby_pb';
|
|
4
|
+
import { TelemetryMessage, TelemetryQueryRequest, TelemetryRequest, } from '../../../grpc/teletubby_pb';
|
|
5
|
+
import { create, fromBinary } from '@bufbuild/protobuf';
|
|
6
|
+
import { RocosLogger } from '../../../logger/RocosLogger';
|
|
7
|
+
import { TelemetryStreamAbstract } from './TelemetryStreamAbstract';
|
|
8
|
+
import { createConnectTransport } from '@connectrpc/connect-web';
|
|
9
|
+
/**
|
|
10
|
+
* Connect-protocol telemetry receive stream. Mirrors TelemetryStream (grpc-web) but uses
|
|
11
|
+
* @connectrpc/connect. Selected when config.transport === 'connect'.
|
|
12
|
+
*
|
|
13
|
+
* The shared TelemetryStreamAbstract is typed with the protobuf-ts message types, while the
|
|
14
|
+
* Connect client uses @bufbuild/protobuf types. Both serialise to identical protobuf wire
|
|
15
|
+
* bytes, so we bridge across the boundary with toBinary/fromBinary rather than hand-written
|
|
16
|
+
* field mapping. This keeps all reconnect/subscription/heartbeat logic shared and untouched.
|
|
17
|
+
*/
|
|
18
|
+
export class TelemetryStreamConnect extends TelemetryStreamAbstract {
|
|
19
|
+
constructor(config) {
|
|
20
|
+
super(config);
|
|
21
|
+
this.logger = RocosLogger.getInstance(`TelemetryStreamConnect(${this.identifier})`);
|
|
22
|
+
const protocol = config.insecure ? 'http' : 'https';
|
|
23
|
+
const port = config.port ? `:${config.port}` : '';
|
|
24
|
+
const transport = createConnectTransport({
|
|
25
|
+
baseUrl: `${protocol}://${this.url}${port}`,
|
|
26
|
+
// Binary proto codec. The Connect default is JSON, which fails to decode real telemetry
|
|
27
|
+
// payloads containing control characters (verified against a live robot on dev) and is
|
|
28
|
+
// less efficient. Binary is required for correctness here.
|
|
29
|
+
useBinaryFormat: true,
|
|
30
|
+
});
|
|
31
|
+
this.client = createClient(TelemetryGateway, transport);
|
|
32
|
+
}
|
|
33
|
+
stopInternal() {
|
|
34
|
+
if (this.abortController) {
|
|
35
|
+
this.logger.info('Starting stop stream process');
|
|
36
|
+
this.abortController.abort();
|
|
37
|
+
this.abortController = undefined;
|
|
38
|
+
this.logger.info('Finished stop stream process');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
registerReceiver() {
|
|
42
|
+
this.logger.info('registerReceiver');
|
|
43
|
+
// Reset counter
|
|
44
|
+
this.receivedMessagesCount = 0;
|
|
45
|
+
const abortController = new AbortController();
|
|
46
|
+
this.abortController = abortController;
|
|
47
|
+
void (async () => {
|
|
48
|
+
try {
|
|
49
|
+
const stream = this.client.registerReceiver(create(RegistrationMessageSchema, {}), {
|
|
50
|
+
headers: this.getHeaders(this.projectId),
|
|
51
|
+
signal: abortController.signal,
|
|
52
|
+
});
|
|
53
|
+
for await (const msg of stream) {
|
|
54
|
+
// Bridge connect-es message -> protobuf-ts TelemetryMessage with a direct field map.
|
|
55
|
+
// (Avoids a per-message re-serialize/re-parse; created/seq are int64/uint64 -> string
|
|
56
|
+
// for protobuf-ts's long_type_string config.)
|
|
57
|
+
const ptMsg = TelemetryMessage.create({
|
|
58
|
+
source: msg.source,
|
|
59
|
+
callsign: msg.callsign,
|
|
60
|
+
payload: msg.payload,
|
|
61
|
+
uid: msg.uid,
|
|
62
|
+
created: msg.created.toString(),
|
|
63
|
+
seq: msg.seq.toString(),
|
|
64
|
+
meta: msg.meta,
|
|
65
|
+
});
|
|
66
|
+
this.onData(ptMsg, false);
|
|
67
|
+
}
|
|
68
|
+
this.onEnd(true);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
if (abortController.signal.aborted) {
|
|
72
|
+
this.logger.debug('registerReceiver', 'aborted');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
void this.onError(e);
|
|
76
|
+
this.onEnd(false);
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
this.listenMessagesAndRenew();
|
|
80
|
+
return () => {
|
|
81
|
+
abortController.abort();
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async onError(e) {
|
|
85
|
+
this.logger.error(`Telemetry Stream Error: ${e}, SubscriberId: ${this.subscriberId}`);
|
|
86
|
+
this.subscriberStatus = SubscriberStatusEnum.ERROR;
|
|
87
|
+
this.statusStream$.next(this.subscriberStatus);
|
|
88
|
+
}
|
|
89
|
+
onEnd(ok) {
|
|
90
|
+
this.logger.debug('registerReceiver', 'end');
|
|
91
|
+
if (ok) {
|
|
92
|
+
this.stopInternal();
|
|
93
|
+
this.registerReceiver();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
getHeaders(projectId) {
|
|
97
|
+
const result = {
|
|
98
|
+
// Canary marker: the istio VirtualService routes only requests carrying this header to
|
|
99
|
+
// the Connect-Go handler (:8083), leaving existing grpc-web traffic untouched. Harmless
|
|
100
|
+
// when the backend does a full cutover or is hit directly. Must match the chart's
|
|
101
|
+
// virtualService.routes.connect.matchHeader.
|
|
102
|
+
'x-tt-connect': '1',
|
|
103
|
+
};
|
|
104
|
+
if (this.token) {
|
|
105
|
+
result.authorization = this.token;
|
|
106
|
+
}
|
|
107
|
+
if (projectId) {
|
|
108
|
+
result['r-p'] = projectId;
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
async requestTelemetry(req) {
|
|
113
|
+
this.logger.debug('Sending telemetry request');
|
|
114
|
+
try {
|
|
115
|
+
const connectReq = fromBinary(TelemetryRequestSchema, TelemetryRequest.toBinary(req));
|
|
116
|
+
await this.client.requestTelemetry(connectReq, { headers: this.getHeaders(this.projectId) });
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
this.logger.error('error requestTelemetry ', e);
|
|
120
|
+
throw e;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async requestTelemetryQuery(req) {
|
|
124
|
+
this.logger.debug('Requesting telemetry with query');
|
|
125
|
+
try {
|
|
126
|
+
const connectReq = fromBinary(TelemetryQueryRequestSchema, TelemetryQueryRequest.toBinary(req));
|
|
127
|
+
await this.client.requestTelemetryQuery(connectReq, { headers: this.getHeaders(this.projectId) });
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
this.logger.error('error requestTelemetryQuery ', e);
|
|
131
|
+
throw e;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
sendAcknowledgmentInternal(uid, status, noRetry) {
|
|
135
|
+
this.logger.error('Error can not send Acknowledgment on connect client', { uid, status, noRetry });
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
sendHeartbeat() {
|
|
139
|
+
// Server-streaming Connect has no client->server channel for heartbeats.
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -4,7 +4,6 @@ import { ReceiverStreamMessage, } from '../../../grpc/teletubby_pb';
|
|
|
4
4
|
import { RocosLogger } from '../../../logger/RocosLogger';
|
|
5
5
|
import { TelemetryReceiverClient } from '../../../grpc/teletubby_pb.grpc-client';
|
|
6
6
|
import { TelemetryStreamAbstract } from './TelemetryStreamAbstract';
|
|
7
|
-
import { v4 as uuid4 } from 'uuid';
|
|
8
7
|
export class TelemetryStreamNode extends TelemetryStreamAbstract {
|
|
9
8
|
constructor(config) {
|
|
10
9
|
super(config);
|
|
@@ -104,7 +103,7 @@ export class TelemetryStreamNode extends TelemetryStreamAbstract {
|
|
|
104
103
|
getMetaData() {
|
|
105
104
|
const meta = new grpc.Metadata();
|
|
106
105
|
meta.add('r-p', this.projectId);
|
|
107
|
-
meta.add('r-tid',
|
|
106
|
+
meta.add('r-tid', crypto.randomUUID());
|
|
108
107
|
meta.add('r-cs', 'rocos-js-sdk-agent');
|
|
109
108
|
if (this.token)
|
|
110
109
|
meta.add('authorization', this.token);
|