@dronedeploy/rocos-js-sdk 4.4.4 → 4.4.6
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/LICENSE +3 -0
- package/cjs/api/StreamRegister.d.ts +18 -3
- package/cjs/api/StreamRegister.js +71 -38
- package/cjs/api/atoms/StreamHeartbeat.js +2 -2
- package/cjs/api/streams/telemetry/TelemetryStreamAbstract.d.ts +8 -1
- package/cjs/api/streams/telemetry/TelemetryStreamAbstract.js +87 -40
- package/cjs/api/streams/webRTCSignalling/WebRTCSignallingStreamAbstract.js +1 -1
- package/cjs/constants/api.d.ts +3 -2
- package/cjs/constants/api.js +5 -4
- package/cjs/constants/identifier.d.ts +1 -0
- package/cjs/constants/identifier.js +2 -1
- package/cjs/helpers/getUniqueId.js +2 -1
- package/cjs/models/callsigns/CallsignsLookup.d.ts +4 -0
- package/cjs/models/callsigns/CallsignsLookup.js +19 -0
- package/cjs/models/robot-status/RobotStatus.d.ts +23 -0
- package/cjs/models/robot-status/RobotStatusEnums.d.ts +18 -6
- package/cjs/models/robot-status/RobotStatusEnums.js +18 -6
- package/cjs/services/AssetStorageService.js +6 -1
- package/cjs/services/BaseServiceAbstract.js +1 -1
- package/cjs/services/BaseStreamService.d.ts +12 -1
- package/cjs/services/BaseStreamService.js +19 -30
- package/cjs/services/EnvironmentService.d.ts +4 -0
- package/cjs/services/EnvironmentService.js +5 -1
- package/cjs/services/MapService.d.ts +15 -3
- package/cjs/services/MapService.js +25 -13
- package/cjs/services/RobotStatusService.d.ts +20 -1
- package/cjs/services/RobotStatusService.js +5 -0
- package/cjs/services/SearchService.js +1 -1
- package/cjs/services/TargetService.js +2 -2
- package/cjs/services/TelemetryService.d.ts +1 -2
- package/cjs/services/TelemetryService.js +30 -28
- package/cjs/services/WebRTCSignallingService.js +7 -9
- package/cjs/services/robot-status/connectivity.d.ts +16 -12
- package/cjs/services/robot-status/connectivity.js +26 -15
- package/cjs/services/robot-status/reportedStatus.d.ts +14 -1
- package/cjs/services/robot-status/reportedStatus.js +36 -1
- package/esm/api/StreamRegister.d.ts +18 -3
- package/esm/api/StreamRegister.js +71 -38
- package/esm/api/atoms/StreamHeartbeat.js +2 -2
- package/esm/api/streams/telemetry/TelemetryStreamAbstract.d.ts +8 -1
- package/esm/api/streams/telemetry/TelemetryStreamAbstract.js +88 -41
- package/esm/api/streams/webRTCSignalling/WebRTCSignallingStreamAbstract.js +2 -2
- package/esm/constants/api.d.ts +3 -2
- package/esm/constants/api.js +3 -2
- package/esm/constants/identifier.d.ts +1 -0
- package/esm/constants/identifier.js +1 -0
- package/esm/helpers/getUniqueId.js +2 -1
- package/esm/models/callsigns/CallsignsLookup.d.ts +4 -0
- package/esm/models/callsigns/CallsignsLookup.js +19 -0
- package/esm/models/robot-status/RobotStatus.d.ts +23 -0
- package/esm/models/robot-status/RobotStatusEnums.d.ts +18 -6
- package/esm/models/robot-status/RobotStatusEnums.js +18 -6
- package/esm/services/AssetStorageService.js +6 -1
- package/esm/services/BaseServiceAbstract.js +1 -1
- package/esm/services/BaseStreamService.d.ts +12 -1
- package/esm/services/BaseStreamService.js +19 -30
- package/esm/services/EnvironmentService.d.ts +4 -0
- package/esm/services/EnvironmentService.js +5 -1
- package/esm/services/MapService.d.ts +15 -3
- package/esm/services/MapService.js +26 -14
- package/esm/services/RobotStatusService.d.ts +20 -1
- package/esm/services/RobotStatusService.js +6 -1
- package/esm/services/SearchService.js +2 -2
- package/esm/services/TargetService.js +3 -3
- package/esm/services/TelemetryService.d.ts +1 -2
- package/esm/services/TelemetryService.js +31 -29
- package/esm/services/WebRTCSignallingService.js +8 -10
- package/esm/services/robot-status/connectivity.d.ts +16 -12
- package/esm/services/robot-status/connectivity.js +26 -15
- package/esm/services/robot-status/reportedStatus.d.ts +14 -1
- package/esm/services/robot-status/reportedStatus.js +35 -1
- package/package.json +7 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BehaviorSubject, catchError, combineLatest, defer, distinctUntilChanged, from, interval, map, mergeAll, of, startWith, } from 'rxjs';
|
|
2
|
-
import { CallsignStatus, CallsignsLookup,
|
|
2
|
+
import { CallsignStatus, CallsignsLookup, RocosError, SubscriberStatusEnum, TelemetryMonitorStatus, errorCodes, } from '../models';
|
|
3
3
|
import { filter, finalize } from 'rxjs/operators';
|
|
4
4
|
import { BaseStreamService } from './BaseStreamService';
|
|
5
5
|
import { IDENTIFIER_NAME_TELEMETRY } from '../constants/identifier';
|
|
@@ -52,31 +52,42 @@ export class TelemetryService extends BaseStreamService {
|
|
|
52
52
|
// scope is used as a key to generate unique streams
|
|
53
53
|
// ideally there should be just one concurrent stream opened
|
|
54
54
|
const scope = this.buildScope(params, callsignsLookup);
|
|
55
|
-
const callsigns = callsignsLookup.lookupValue;
|
|
56
55
|
const subscriptionParams = {
|
|
57
56
|
uniqueId: getUniqueId(params.projectId, callsignsLookup, sources, scope),
|
|
58
|
-
callsigns: callsignsLookup
|
|
57
|
+
callsigns: callsignsLookup.getCallsigns(),
|
|
59
58
|
sources,
|
|
60
59
|
};
|
|
61
60
|
// `defer` acquires the stream only when subscribed; `finalize` releases it on unsubscribe, error
|
|
62
|
-
// and complete — so acquire and release stay balanced on every path.
|
|
61
|
+
// and complete — so acquire and release stay balanced on every path. The registry refcount taken
|
|
62
|
+
// here keeps the stream alive until the finalize, so everything in between is race-free.
|
|
63
63
|
return defer(() => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
acquired = stream;
|
|
64
|
+
const { stream, isNew, ready, release } = this.acquireStream(IDENTIFIER_NAME_TELEMETRY, this.buildStreamConfig(params.projectId, callsignsLookup, sources, scope));
|
|
65
|
+
try {
|
|
67
66
|
stream.addSubscription(subscriptionParams);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.
|
|
67
|
+
// Forward the stream's status onto the per-scope subject once, at creation; it ends when the
|
|
68
|
+
// stream stops (statusStream$ completes), so it is not re-created or leaked across subscribers.
|
|
69
|
+
if (isNew) {
|
|
70
|
+
stream.statusStream$.subscribe((msg) => {
|
|
71
|
+
this.streamStatusSubject$.next({
|
|
72
|
+
scope,
|
|
73
|
+
status: msg,
|
|
74
|
+
});
|
|
73
75
|
});
|
|
74
76
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
// finalize below is not wired up yet, so a throw here must hand the refcount back itself.
|
|
80
|
+
release();
|
|
81
|
+
throw e;
|
|
82
|
+
}
|
|
83
|
+
// status$ / getStatus() are driven by the acquireStream factory (BaseStreamService), not here.
|
|
84
|
+
const messages$ = ready.then(() => from(stream.messageStream$));
|
|
85
|
+
return from(messages$).pipe(mergeAll(), filter((message) => {
|
|
86
|
+
return callsignsLookup.includesCallsign(message.callsign) && sources.includes(message.source);
|
|
87
|
+
}), finalize(() => {
|
|
88
|
+
void stream.removeSubscription(subscriptionParams, params.terminateReceiverGroupOnUnsubscribe);
|
|
89
|
+
release();
|
|
90
|
+
}));
|
|
80
91
|
});
|
|
81
92
|
}
|
|
82
93
|
/**
|
|
@@ -156,8 +167,8 @@ export class TelemetryService extends BaseStreamService {
|
|
|
156
167
|
return `${params.projectId}-default-${flattenCallsignsLookup(callsignsLookup).join()}`;
|
|
157
168
|
return `${params.projectId}-default`;
|
|
158
169
|
}
|
|
159
|
-
|
|
160
|
-
|
|
170
|
+
buildStreamConfig(projectId, callsignsLookup, sources, scope) {
|
|
171
|
+
return {
|
|
161
172
|
url: this.config.url,
|
|
162
173
|
projectId,
|
|
163
174
|
callsignsLookup,
|
|
@@ -169,16 +180,7 @@ export class TelemetryService extends BaseStreamService {
|
|
|
169
180
|
insecure: this.config.insecure,
|
|
170
181
|
transport: this.config.transport,
|
|
171
182
|
fetch: this.config.fetch,
|
|
172
|
-
}
|
|
173
|
-
if (!newStream.isNew) {
|
|
174
|
-
newStream.stream.statusStream$.subscribe((msg) => {
|
|
175
|
-
this.streamStatusSubject$.next({
|
|
176
|
-
scope,
|
|
177
|
-
status: msg,
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
return newStream.stream;
|
|
183
|
+
};
|
|
182
184
|
}
|
|
183
185
|
getStream(config) {
|
|
184
186
|
if (config.transport === 'grpc-web') {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IDENTIFIER_NAME_WEBRTC_SIGNALLING } from '../constants/identifier';
|
|
2
2
|
import { RocosLogger } from '../logger/RocosLogger';
|
|
3
3
|
import { RocosStore } from '../store/RocosStore';
|
|
4
4
|
import { StreamRegister } from '../api/StreamRegister';
|
|
@@ -34,11 +34,9 @@ export class WebRTCSignallingService {
|
|
|
34
34
|
}
|
|
35
35
|
async createSignallingStream() {
|
|
36
36
|
const scope = 'default';
|
|
37
|
-
const identifier = StreamRegister.getIdentifier(
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
if (!stream) {
|
|
41
|
-
stream = this.getStream({
|
|
37
|
+
const identifier = StreamRegister.getIdentifier(IDENTIFIER_NAME_WEBRTC_SIGNALLING, scope);
|
|
38
|
+
const { stream, ready } = StreamRegister.getInstance().acquireStream(identifier, () => {
|
|
39
|
+
const newStream = this.getStream({
|
|
42
40
|
url: this.config.url,
|
|
43
41
|
token: this.config.token,
|
|
44
42
|
scope,
|
|
@@ -46,13 +44,13 @@ export class WebRTCSignallingService {
|
|
|
46
44
|
port: this.config.port,
|
|
47
45
|
insecure: this.config.insecure,
|
|
48
46
|
});
|
|
49
|
-
|
|
47
|
+
newStream.statusStream$.subscribe((msg) => {
|
|
50
48
|
this.status = msg === SubscriberStatusEnum.STOPPED || msg === SubscriberStatusEnum.ALIVE;
|
|
51
49
|
this.status$.next(msg);
|
|
52
50
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
return newStream;
|
|
52
|
+
}, (newStream) => this.initStream(newStream));
|
|
53
|
+
await ready;
|
|
56
54
|
return stream;
|
|
57
55
|
}
|
|
58
56
|
async initStream(stream) {
|
|
@@ -36,18 +36,19 @@ export declare const buildConnectionsUrl: (serviceId: string, baseUrl: string, p
|
|
|
36
36
|
export declare const mapConnectionStatus: (connection?: IConnectedCallsign | null) => ServiceConnection;
|
|
37
37
|
/**
|
|
38
38
|
* Aggregates per-service connection states into an overall verdict:
|
|
39
|
-
* - `
|
|
40
|
-
*
|
|
39
|
+
* - `DEGRADED` — any service reports an explicit `FAILED` fault, or a genuine mix (some connected,
|
|
40
|
+
* some disconnected).
|
|
41
|
+
* - `ONLINE` — at least one service connected and none disconnected or failed.
|
|
41
42
|
* - `OFFLINE` — nothing connected.
|
|
42
43
|
*
|
|
43
|
-
* `
|
|
44
|
-
*
|
|
44
|
+
* A `FAILED` service forces `DEGRADED` even when nothing else is connected, so a fault (e.g. a failed
|
|
45
|
+
* deployment) raises attention rather than reading as a plain, switched-off `OFFLINE`.
|
|
45
46
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* `
|
|
49
|
-
*
|
|
50
|
-
*
|
|
47
|
+
* `UNKNOWN` services (e.g. not yet polled) never force `DEGRADED`, so startup settles on `OFFLINE`
|
|
48
|
+
* (gray) rather than a spurious flashing-red degraded state. This optimism also means a service held
|
|
49
|
+
* `UNKNOWN` indefinitely (e.g. an endpoint whose polls keep failing) does not by itself pull the
|
|
50
|
+
* aggregate below `ONLINE` — a deliberate tradeoff to keep transient errors from flapping the
|
|
51
|
+
* indicator; a service that wants to be surfaced reports `FAILED` explicitly.
|
|
51
52
|
*/
|
|
52
53
|
export declare const aggregateConnectivity: (services: Record<string, ServiceConnection>) => RobotConnectivity;
|
|
53
54
|
/**
|
|
@@ -66,11 +67,14 @@ export interface ConnectivityDeps {
|
|
|
66
67
|
insecure?: boolean;
|
|
67
68
|
/** The telemetry-liveness signal (from `getTelemetryLiveness`), folded in as one service. */
|
|
68
69
|
telemetryLiveness$: Observable<ServiceConnection>;
|
|
70
|
+
/** Caller-injected connectivity signals, keyed by service id, folded in on equal footing. */
|
|
71
|
+
extraServices?: Record<string, Observable<ServiceConnection>>;
|
|
69
72
|
}
|
|
70
73
|
/**
|
|
71
74
|
* Emits the robot's {@link RobotConnectivityStatus} — the per-service breakdown
|
|
72
|
-
* plus the aggregate verdict — for the configured `expectedServices
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
+
* plus the aggregate verdict — for the configured `expectedServices`, plus any
|
|
76
|
+
* caller-injected `extraServices` (folded in on equal footing). HTTP services
|
|
77
|
+
* are polled; `telemetry-liveness` and injected services use their supplied
|
|
78
|
+
* observable; any unrecognised service id resolves to `UNKNOWN`.
|
|
75
79
|
*/
|
|
76
80
|
export declare const getConnectivityChanges: (deps: ConnectivityDeps, projectId: string, callsign: string, expectedServices?: string[], pollMs?: number) => Observable<RobotConnectivityStatus>;
|
|
@@ -52,21 +52,24 @@ export const mapConnectionStatus = (connection) => {
|
|
|
52
52
|
};
|
|
53
53
|
/**
|
|
54
54
|
* Aggregates per-service connection states into an overall verdict:
|
|
55
|
-
* - `
|
|
56
|
-
*
|
|
55
|
+
* - `DEGRADED` — any service reports an explicit `FAILED` fault, or a genuine mix (some connected,
|
|
56
|
+
* some disconnected).
|
|
57
|
+
* - `ONLINE` — at least one service connected and none disconnected or failed.
|
|
57
58
|
* - `OFFLINE` — nothing connected.
|
|
58
59
|
*
|
|
59
|
-
* `
|
|
60
|
-
*
|
|
60
|
+
* A `FAILED` service forces `DEGRADED` even when nothing else is connected, so a fault (e.g. a failed
|
|
61
|
+
* deployment) raises attention rather than reading as a plain, switched-off `OFFLINE`.
|
|
61
62
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* `
|
|
65
|
-
*
|
|
66
|
-
*
|
|
63
|
+
* `UNKNOWN` services (e.g. not yet polled) never force `DEGRADED`, so startup settles on `OFFLINE`
|
|
64
|
+
* (gray) rather than a spurious flashing-red degraded state. This optimism also means a service held
|
|
65
|
+
* `UNKNOWN` indefinitely (e.g. an endpoint whose polls keep failing) does not by itself pull the
|
|
66
|
+
* aggregate below `ONLINE` — a deliberate tradeoff to keep transient errors from flapping the
|
|
67
|
+
* indicator; a service that wants to be surfaced reports `FAILED` explicitly.
|
|
67
68
|
*/
|
|
68
69
|
export const aggregateConnectivity = (services) => {
|
|
69
70
|
const values = Object.values(services);
|
|
71
|
+
if (values.includes(ServiceConnection.FAILED))
|
|
72
|
+
return RobotConnectivity.DEGRADED;
|
|
70
73
|
const hasConnected = values.includes(ServiceConnection.CONNECTED);
|
|
71
74
|
const hasDisconnected = values.includes(ServiceConnection.DISCONNECTED);
|
|
72
75
|
if (hasConnected && hasDisconnected)
|
|
@@ -99,24 +102,32 @@ const connectivityEquals = (a, b) => {
|
|
|
99
102
|
};
|
|
100
103
|
/**
|
|
101
104
|
* Emits the robot's {@link RobotConnectivityStatus} — the per-service breakdown
|
|
102
|
-
* plus the aggregate verdict — for the configured `expectedServices
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
+
* plus the aggregate verdict — for the configured `expectedServices`, plus any
|
|
106
|
+
* caller-injected `extraServices` (folded in on equal footing). HTTP services
|
|
107
|
+
* are polled; `telemetry-liveness` and injected services use their supplied
|
|
108
|
+
* observable; any unrecognised service id resolves to `UNKNOWN`.
|
|
105
109
|
*/
|
|
106
110
|
export const getConnectivityChanges = (deps, projectId, callsign, expectedServices = DEFAULT_EXPECTED_SERVICES, pollMs = DEFAULT_CONNECTIVITY_POLL_MS) => {
|
|
111
|
+
const extraServices = deps.extraServices ?? {};
|
|
112
|
+
const serviceIds = [...expectedServices, ...Object.keys(extraServices).filter((id) => !expectedServices.includes(id))];
|
|
107
113
|
// combineLatest([]) completes without emitting; emit an explicit empty/offline status instead.
|
|
108
|
-
if (
|
|
114
|
+
if (serviceIds.length === 0) {
|
|
109
115
|
return of({ overall: RobotConnectivity.OFFLINE, services: {} });
|
|
110
116
|
}
|
|
111
|
-
const perService =
|
|
117
|
+
const perService = serviceIds.map((serviceId) => {
|
|
112
118
|
let source$;
|
|
113
119
|
if (serviceId === TELEMETRY_LIVENESS_SERVICE) {
|
|
114
120
|
source$ = deps.telemetryLiveness$;
|
|
115
121
|
}
|
|
116
|
-
else if (serviceId
|
|
122
|
+
else if (Object.prototype.hasOwnProperty.call(CONNECTION_SERVICE_PREFIXES, serviceId)) {
|
|
117
123
|
const url = buildConnectionsUrl(serviceId, deps.baseUrl, projectId, callsign, deps.insecure);
|
|
118
124
|
source$ = getServiceConnectionChanges(deps.httpGet, url, pollMs);
|
|
119
125
|
}
|
|
126
|
+
else if (Object.prototype.hasOwnProperty.call(extraServices, serviceId)) {
|
|
127
|
+
// Contain an injected observable's errors as UNKNOWN, mirroring the built-in sources, so a
|
|
128
|
+
// faulty caller signal can't error out combineLatest and tear down the whole aggregate.
|
|
129
|
+
source$ = extraServices[serviceId].pipe(catchError(() => of(ServiceConnection.UNKNOWN)));
|
|
130
|
+
}
|
|
120
131
|
else {
|
|
121
132
|
source$ = of(ServiceConnection.UNKNOWN);
|
|
122
133
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
-
import { RobotHealth, RobotReadiness, ServiceConnection } from '../../models';
|
|
2
|
+
import { RobotHealth, RobotReadiness, RobotStatusContributors, ServiceConnection } from '../../models';
|
|
3
3
|
import { TelemetryService } from '../TelemetryService';
|
|
4
4
|
/** The new agent topic carrying health + readiness (replaces the heartbeat). */
|
|
5
5
|
export declare const ROBOT_STATUS_SOURCE = "/diagnostics/robot/status";
|
|
6
6
|
/** The legacy heartbeat topic — liveness only, no status payload. */
|
|
7
7
|
export declare const LEGACY_HEARTBEAT_SOURCE = "/rocos/agent/telemetry/heartbeat";
|
|
8
|
+
/** The per-contributor breakdown behind the reported status (health + readiness). */
|
|
9
|
+
export declare const ROBOT_STATUS_CONTRIBUTORS_SOURCE = "/diagnostics/robot/status/contributors";
|
|
8
10
|
export interface ReportedRobotStatus {
|
|
9
11
|
health: RobotHealth;
|
|
10
12
|
readiness: RobotReadiness;
|
|
@@ -28,6 +30,17 @@ export declare const parseRobotReadiness: (value: unknown) => RobotReadiness;
|
|
|
28
30
|
* new topic.
|
|
29
31
|
*/
|
|
30
32
|
export declare const getReportedStatusChanges: (telemetry: TelemetryService, projectId: string, callsign: string) => Observable<ReportedRobotStatus>;
|
|
33
|
+
/**
|
|
34
|
+
* Emits the per-contributor breakdown behind the robot's reported health and
|
|
35
|
+
* readiness, from the agent's `robot/status/contributors` topic. Each
|
|
36
|
+
* contributor's integer wire value is mapped onto {@link RobotHealth} /
|
|
37
|
+
* {@link RobotReadiness}; a missing `health`/`readiness` array becomes `[]`.
|
|
38
|
+
*
|
|
39
|
+
* Starts with an empty breakdown so consumers combining this with other streams
|
|
40
|
+
* emit immediately, and — like {@link getReportedStatusChanges} — a telemetry
|
|
41
|
+
* error falls back to an empty breakdown rather than terminating the stream.
|
|
42
|
+
*/
|
|
43
|
+
export declare const getStatusContributorsChanges: (telemetry: TelemetryService, projectId: string, callsign: string) => Observable<RobotStatusContributors>;
|
|
31
44
|
/**
|
|
32
45
|
* Emits the `telemetry-liveness` connectivity signal: whether a heartbeat (from
|
|
33
46
|
* either the new `robot/status` topic or the legacy heartbeat) has been received
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { catchError, combineLatest, distinctUntilChanged, filter, interval, map, merge, of, scan, startWith, } from 'rxjs';
|
|
2
|
-
import { RobotHealth, RobotReadiness, ServiceConnection } from '../../models';
|
|
2
|
+
import { RobotHealth, RobotReadiness, ServiceConnection, } from '../../models';
|
|
3
3
|
/** The new agent topic carrying health + readiness (replaces the heartbeat). */
|
|
4
4
|
export const ROBOT_STATUS_SOURCE = '/diagnostics/robot/status';
|
|
5
5
|
/** The legacy heartbeat topic — liveness only, no status payload. */
|
|
6
6
|
export const LEGACY_HEARTBEAT_SOURCE = '/rocos/agent/telemetry/heartbeat';
|
|
7
|
+
/** The per-contributor breakdown behind the reported status (health + readiness). */
|
|
8
|
+
export const ROBOT_STATUS_CONTRIBUTORS_SOURCE = `${ROBOT_STATUS_SOURCE}/contributors`;
|
|
7
9
|
const DEFAULT_HEARTBEAT_TIMEOUT_MS = 5000;
|
|
8
10
|
const DEFAULT_INTERVAL_MS = 2000;
|
|
9
11
|
/**
|
|
@@ -78,6 +80,38 @@ export const getReportedStatusChanges = (telemetry, projectId, callsign) => {
|
|
|
78
80
|
// UNKNOWN/UNKNOWN (matching getTelemetryLiveness) so subscribers get an honest value.
|
|
79
81
|
catchError(() => of({ health: RobotHealth.UNKNOWN, readiness: RobotReadiness.UNKNOWN })));
|
|
80
82
|
};
|
|
83
|
+
const toContributor = (raw, parse) => ({
|
|
84
|
+
id: raw.id ?? '',
|
|
85
|
+
component: raw.component ?? '',
|
|
86
|
+
reason: raw.reason ?? '',
|
|
87
|
+
status: parse(raw.value),
|
|
88
|
+
});
|
|
89
|
+
const EMPTY_CONTRIBUTORS = { health: [], readiness: [] };
|
|
90
|
+
/**
|
|
91
|
+
* Emits the per-contributor breakdown behind the robot's reported health and
|
|
92
|
+
* readiness, from the agent's `robot/status/contributors` topic. Each
|
|
93
|
+
* contributor's integer wire value is mapped onto {@link RobotHealth} /
|
|
94
|
+
* {@link RobotReadiness}; a missing `health`/`readiness` array becomes `[]`.
|
|
95
|
+
*
|
|
96
|
+
* Starts with an empty breakdown so consumers combining this with other streams
|
|
97
|
+
* emit immediately, and — like {@link getReportedStatusChanges} — a telemetry
|
|
98
|
+
* error falls back to an empty breakdown rather than terminating the stream.
|
|
99
|
+
*/
|
|
100
|
+
export const getStatusContributorsChanges = (telemetry, projectId, callsign) => {
|
|
101
|
+
return telemetry
|
|
102
|
+
.subscribe({
|
|
103
|
+
projectId,
|
|
104
|
+
callsigns: [callsign],
|
|
105
|
+
sources: [ROBOT_STATUS_CONTRIBUTORS_SOURCE],
|
|
106
|
+
})
|
|
107
|
+
.pipe(map((message) => {
|
|
108
|
+
const payload = message.payload ?? {};
|
|
109
|
+
return {
|
|
110
|
+
health: (payload.health ?? []).map((c) => toContributor(c, parseRobotHealth)),
|
|
111
|
+
readiness: (payload.readiness ?? []).map((c) => toContributor(c, parseRobotReadiness)),
|
|
112
|
+
};
|
|
113
|
+
}), startWith(EMPTY_CONTRIBUTORS), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), catchError(() => of(EMPTY_CONTRIBUTORS)));
|
|
114
|
+
};
|
|
81
115
|
/**
|
|
82
116
|
* Emits the `telemetry-liveness` connectivity signal: whether a heartbeat (from
|
|
83
117
|
* either the new `robot/status` topic or the legacy heartbeat) has been received
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dronedeploy/rocos-js-sdk",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.6",
|
|
4
4
|
"description": "Javascript SDK for rocos",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "esm/index.js",
|
|
@@ -42,5 +42,10 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"repository": {},
|
|
45
|
-
"private": false
|
|
45
|
+
"private": false,
|
|
46
|
+
"overrides": {
|
|
47
|
+
"openapi-typescript": {
|
|
48
|
+
"typescript": "$typescript"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
46
51
|
}
|