@dronedeploy/rocos-js-sdk 4.1.1 → 4.3.0-rc.1
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/IRocosSDK.d.ts +2 -1
- package/cjs/RocosSDK.d.ts +5 -1
- package/cjs/RocosSDK.js +9 -0
- package/cjs/constants/api.d.ts +8 -2
- package/cjs/constants/api.js +13 -5
- package/cjs/models/RocosError.d.ts +1 -0
- package/cjs/models/RocosError.js +1 -0
- package/cjs/models/ServiceEnum.d.ts +1 -0
- package/cjs/models/ServiceEnum.js +1 -0
- package/cjs/models/index.d.ts +1 -0
- package/cjs/models/index.js +1 -0
- package/cjs/models/maps/MapPath.d.ts +143 -0
- package/cjs/models/maps/MapPath.js +2 -0
- package/cjs/models/robot-status/RobotStatusEnums.d.ts +1 -1
- package/cjs/models/robot-status/RobotStatusEnums.js +1 -1
- package/cjs/services/MapService.d.ts +101 -0
- package/cjs/services/MapService.js +140 -0
- package/cjs/services/RobotStatusService.d.ts +37 -0
- package/cjs/services/RobotStatusService.js +94 -0
- package/cjs/services/index.d.ts +1 -0
- package/cjs/services/index.js +1 -0
- package/cjs/services/robot-status/connectivity.d.ts +76 -0
- package/cjs/services/robot-status/connectivity.js +140 -0
- package/cjs/services/robot-status/reportedStatus.d.ts +38 -0
- package/cjs/services/robot-status/reportedStatus.js +109 -0
- package/esm/IRocosSDK.d.ts +2 -1
- package/esm/RocosSDK.d.ts +5 -1
- package/esm/RocosSDK.js +10 -1
- package/esm/constants/api.d.ts +8 -2
- package/esm/constants/api.js +10 -2
- package/esm/models/RocosError.d.ts +1 -0
- package/esm/models/RocosError.js +1 -0
- package/esm/models/ServiceEnum.d.ts +1 -0
- package/esm/models/ServiceEnum.js +1 -0
- package/esm/models/index.d.ts +1 -0
- package/esm/models/index.js +1 -0
- package/esm/models/maps/MapPath.d.ts +143 -0
- package/esm/models/maps/MapPath.js +1 -0
- package/esm/models/robot-status/RobotStatusEnums.d.ts +1 -1
- package/esm/models/robot-status/RobotStatusEnums.js +1 -1
- package/esm/services/MapService.d.ts +101 -0
- package/esm/services/MapService.js +141 -1
- package/esm/services/RobotStatusService.d.ts +37 -0
- package/esm/services/RobotStatusService.js +90 -0
- package/esm/services/index.d.ts +1 -0
- package/esm/services/index.js +1 -0
- package/esm/services/robot-status/connectivity.d.ts +76 -0
- package/esm/services/robot-status/connectivity.js +131 -0
- package/esm/services/robot-status/reportedStatus.d.ts +38 -0
- package/esm/services/robot-status/reportedStatus.js +102 -0
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { IBaseService, IRocosSDKConfig, RobotConnectivityStatus, RobotStatus, RocosError } from '../models';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { ReportedRobotStatus } from './robot-status/reportedStatus';
|
|
4
|
+
import { BaseServiceAbstract } from './BaseServiceAbstract';
|
|
5
|
+
/** Per-call tuning for the robot status observables. */
|
|
6
|
+
export interface RobotStatusOptions {
|
|
7
|
+
/** Services whose connectivity gates ONLINE/DEGRADED. Defaults to the standard expected-services set. */
|
|
8
|
+
expectedServices?: string[];
|
|
9
|
+
/** How long without a heartbeat before telemetry-liveness is considered dead (ms). */
|
|
10
|
+
heartbeatTimeoutMs?: number;
|
|
11
|
+
/** How often the connections endpoints are polled (ms, floored internally). */
|
|
12
|
+
connectivityPollMs?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The single source of truth for a robot's status. It composes the reported
|
|
16
|
+
* status (health/readiness from the heartbeat), per-service connectivity, and
|
|
17
|
+
* the canonical indicator colour, so consumers subscribe to one observable
|
|
18
|
+
* rather than deriving "is the robot online" themselves.
|
|
19
|
+
*/
|
|
20
|
+
export declare class RobotStatusService extends BaseServiceAbstract implements IBaseService {
|
|
21
|
+
constructor(config: IRocosSDKConfig);
|
|
22
|
+
getStatus(): boolean;
|
|
23
|
+
/** Health + readiness as reported by the robot (new topic, legacy heartbeat fallback). */
|
|
24
|
+
getReportedStatusChanges(projectId: string, callsign: string): Observable<ReportedRobotStatus>;
|
|
25
|
+
/** Per-service connectivity plus the aggregate verdict, polled. */
|
|
26
|
+
getConnectivityChanges(projectId: string, callsign: string, opts?: RobotStatusOptions): Observable<RobotConnectivityStatus>;
|
|
27
|
+
/** One-shot connectivity snapshot: resolves once every expected service is known, or after a timeout. */
|
|
28
|
+
getConnectivity(projectId: string, callsign: string, opts?: RobotStatusOptions): Promise<RobotConnectivityStatus>;
|
|
29
|
+
/**
|
|
30
|
+
* The headline stream: the combined {@link RobotStatus} including the canonical
|
|
31
|
+
* colour token. This is what status indicators subscribe to.
|
|
32
|
+
*/
|
|
33
|
+
getRobotStatusChanges(projectId: string, callsign: string, opts?: RobotStatusOptions): Observable<RobotStatus>;
|
|
34
|
+
protected getError(e: Error): RocosError;
|
|
35
|
+
private get telemetryService();
|
|
36
|
+
private connectivityDeps;
|
|
37
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RobotStatusService = void 0;
|
|
4
|
+
const connectivity_1 = require("./robot-status/connectivity");
|
|
5
|
+
const models_1 = require("../models");
|
|
6
|
+
const rxjs_1 = require("rxjs");
|
|
7
|
+
const reportedStatus_1 = require("./robot-status/reportedStatus");
|
|
8
|
+
const BaseServiceAbstract_1 = require("./BaseServiceAbstract");
|
|
9
|
+
const RocosLogger_1 = require("../logger/RocosLogger");
|
|
10
|
+
const RocosStore_1 = require("../store/RocosStore");
|
|
11
|
+
const getRobotStatusColour_1 = require("../helpers/getRobotStatusColour");
|
|
12
|
+
/** Upper bound on how long the one-shot {@link RobotStatusService.getConnectivity} waits to settle. */
|
|
13
|
+
const ONE_SHOT_TIMEOUT_MS = 10000;
|
|
14
|
+
const isKnown = (status) => {
|
|
15
|
+
return Object.values(status.services).every((connection) => connection !== models_1.ServiceConnection.UNKNOWN);
|
|
16
|
+
};
|
|
17
|
+
const robotStatusEquals = (a, b) => {
|
|
18
|
+
if (a.health !== b.health || a.readiness !== b.readiness)
|
|
19
|
+
return false;
|
|
20
|
+
if (a.connectivity.overall !== b.connectivity.overall)
|
|
21
|
+
return false;
|
|
22
|
+
const keys = Object.keys(a.connectivity.services);
|
|
23
|
+
if (keys.length !== Object.keys(b.connectivity.services).length)
|
|
24
|
+
return false;
|
|
25
|
+
return keys.every((key) => a.connectivity.services[key] === b.connectivity.services[key]);
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The single source of truth for a robot's status. It composes the reported
|
|
29
|
+
* status (health/readiness from the heartbeat), per-service connectivity, and
|
|
30
|
+
* the canonical indicator colour, so consumers subscribe to one observable
|
|
31
|
+
* rather than deriving "is the robot online" themselves.
|
|
32
|
+
*/
|
|
33
|
+
class RobotStatusService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
34
|
+
constructor(config) {
|
|
35
|
+
super(config);
|
|
36
|
+
this.logger = RocosLogger_1.RocosLogger.getInstance(`RobotStatusService(${this.config.url})`);
|
|
37
|
+
}
|
|
38
|
+
getStatus() {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
/** Health + readiness as reported by the robot (new topic, legacy heartbeat fallback). */
|
|
42
|
+
getReportedStatusChanges(projectId, callsign) {
|
|
43
|
+
return (0, reportedStatus_1.getReportedStatusChanges)(this.telemetryService, projectId, callsign);
|
|
44
|
+
}
|
|
45
|
+
/** Per-service connectivity plus the aggregate verdict, polled. */
|
|
46
|
+
getConnectivityChanges(projectId, callsign, opts) {
|
|
47
|
+
return (0, connectivity_1.getConnectivityChanges)(this.connectivityDeps(projectId, callsign, opts), projectId, callsign, opts?.expectedServices, opts?.connectivityPollMs);
|
|
48
|
+
}
|
|
49
|
+
/** One-shot connectivity snapshot: resolves once every expected service is known, or after a timeout. */
|
|
50
|
+
getConnectivity(projectId, callsign, opts) {
|
|
51
|
+
// Capture the latest snapshot explicitly: on timeout, refCount teardown would otherwise
|
|
52
|
+
// hand a fresh (all-UNKNOWN seed) re-subscription to the fallback rather than the last value.
|
|
53
|
+
let latest;
|
|
54
|
+
const changes$ = this.getConnectivityChanges(projectId, callsign, opts).pipe((0, rxjs_1.tap)((status) => {
|
|
55
|
+
latest = status;
|
|
56
|
+
}), (0, rxjs_1.shareReplay)({ bufferSize: 1, refCount: true }));
|
|
57
|
+
return (0, rxjs_1.firstValueFrom)(changes$.pipe((0, rxjs_1.first)(isKnown),
|
|
58
|
+
// Don't wait forever on a persistently-unknown service — fall back to the latest snapshot seen.
|
|
59
|
+
(0, rxjs_1.timeout)({ first: ONE_SHOT_TIMEOUT_MS, with: () => (latest ? (0, rxjs_1.of)(latest) : changes$.pipe((0, rxjs_1.take)(1))) })));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The headline stream: the combined {@link RobotStatus} including the canonical
|
|
63
|
+
* colour token. This is what status indicators subscribe to.
|
|
64
|
+
*/
|
|
65
|
+
getRobotStatusChanges(projectId, callsign, opts) {
|
|
66
|
+
const reported$ = this.getReportedStatusChanges(projectId, callsign).pipe(
|
|
67
|
+
// Seed so the combined stream emits (e.g. gray) before the first heartbeat arrives.
|
|
68
|
+
(0, rxjs_1.startWith)({ health: models_1.RobotHealth.UNKNOWN, readiness: models_1.RobotReadiness.UNKNOWN }));
|
|
69
|
+
const connectivity$ = this.getConnectivityChanges(projectId, callsign, opts);
|
|
70
|
+
return (0, rxjs_1.combineLatest)([reported$, connectivity$]).pipe((0, rxjs_1.map)(([reported, connectivity]) => ({
|
|
71
|
+
health: reported.health,
|
|
72
|
+
readiness: reported.readiness,
|
|
73
|
+
connectivity,
|
|
74
|
+
colour: (0, getRobotStatusColour_1.getRobotStatusColour)({ health: reported.health, readiness: reported.readiness, connectivity }),
|
|
75
|
+
})), (0, rxjs_1.distinctUntilChanged)(robotStatusEquals));
|
|
76
|
+
}
|
|
77
|
+
getError(e) {
|
|
78
|
+
return new models_1.RocosError(e, models_1.errorCodes.ROBOT_STATUS_SERVICE_ERROR);
|
|
79
|
+
}
|
|
80
|
+
get telemetryService() {
|
|
81
|
+
return RocosStore_1.RocosStore.getSDKInstance(this.config).getTelemetryService();
|
|
82
|
+
}
|
|
83
|
+
connectivityDeps(projectId, callsign, opts) {
|
|
84
|
+
return {
|
|
85
|
+
httpGet: (url) => {
|
|
86
|
+
return this.callGet(url, `Failed to get connection status for ${callsign} in project ${projectId}.`);
|
|
87
|
+
},
|
|
88
|
+
baseUrl: this.config.url,
|
|
89
|
+
insecure: this.config.insecure,
|
|
90
|
+
telemetryLiveness$: (0, reportedStatus_1.getTelemetryLiveness)(this.telemetryService, projectId, callsign, opts?.heartbeatTimeoutMs),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.RobotStatusService = RobotStatusService;
|
package/cjs/services/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export * from './ProfileService';
|
|
|
17
17
|
export * from './ProjectService';
|
|
18
18
|
export * from './RTPWebRTCService';
|
|
19
19
|
export * from './RobotService';
|
|
20
|
+
export * from './RobotStatusService';
|
|
20
21
|
export * from './ScheduleService';
|
|
21
22
|
export * from './SearchService';
|
|
22
23
|
export * from './SpotProvisioningService';
|
package/cjs/services/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __exportStar(require("./ProfileService"), exports);
|
|
|
33
33
|
__exportStar(require("./ProjectService"), exports);
|
|
34
34
|
__exportStar(require("./RTPWebRTCService"), exports);
|
|
35
35
|
__exportStar(require("./RobotService"), exports);
|
|
36
|
+
__exportStar(require("./RobotStatusService"), exports);
|
|
36
37
|
__exportStar(require("./ScheduleService"), exports);
|
|
37
38
|
__exportStar(require("./SearchService"), exports);
|
|
38
39
|
__exportStar(require("./SpotProvisioningService"), exports);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { IConnectedCallsign, RobotConnectivity, RobotConnectivityStatus, ServiceConnection } from '../../models';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
/**
|
|
4
|
+
* Service id → public path prefix, for services that expose the standard
|
|
5
|
+
* `connections` endpoint. New services adopting the convention are added here.
|
|
6
|
+
* The `telemetry` (Teletubby) endpoint joins this once built — see EAI-718/719.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CONNECTION_SERVICE_PREFIXES: Record<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* The telemetry-liveness signal is derived from heartbeat freshness rather than
|
|
11
|
+
* an HTTP endpoint, so it is handled specially (its observable is supplied by
|
|
12
|
+
* the caller). See `getTelemetryLiveness`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const TELEMETRY_LIVENESS_SERVICE = "telemetry-liveness";
|
|
15
|
+
/**
|
|
16
|
+
* The services evaluated by default. The `telemetry` connections endpoint joins
|
|
17
|
+
* this list once Teletubby exposes it (follow-up).
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_EXPECTED_SERVICES: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Floor for the connections-endpoint poll interval. Guards against a caller
|
|
22
|
+
* passing `0` (or any tiny value), which would otherwise poll the API on every
|
|
23
|
+
* event-loop tick.
|
|
24
|
+
*/
|
|
25
|
+
export declare const MIN_CONNECTIVITY_POLL_MS = 250;
|
|
26
|
+
/** Clamps a requested poll interval up to {@link MIN_CONNECTIVITY_POLL_MS}. */
|
|
27
|
+
export declare const clampPollInterval: (pollMs: number) => number;
|
|
28
|
+
/** Authenticated GET used to poll a service's `connections` endpoint. */
|
|
29
|
+
export type ConnectionsHttpGet = (url: string) => Promise<IConnectedCallsign>;
|
|
30
|
+
/**
|
|
31
|
+
* Builds the `connections` endpoint URL for a service — per-callsign when a
|
|
32
|
+
* callsign is given, otherwise the bulk per-project variant.
|
|
33
|
+
*/
|
|
34
|
+
export declare const buildConnectionsUrl: (serviceId: string, baseUrl: string, projectId: string, callsign?: string, insecure?: boolean) => string;
|
|
35
|
+
/** Maps a `connections` endpoint response onto a {@link ServiceConnection}. */
|
|
36
|
+
export declare const mapConnectionStatus: (connection?: IConnectedCallsign | null) => ServiceConnection;
|
|
37
|
+
/**
|
|
38
|
+
* Aggregates per-service connection states into an overall verdict:
|
|
39
|
+
* - `ONLINE` — at least one service connected and none disconnected.
|
|
40
|
+
* - `DEGRADED` — a genuine mix: some connected, some disconnected.
|
|
41
|
+
* - `OFFLINE` — nothing connected.
|
|
42
|
+
*
|
|
43
|
+
* `UNKNOWN` services (e.g. not yet polled) never force `DEGRADED`, so startup
|
|
44
|
+
* settles on `OFFLINE` (gray) rather than a spurious flashing-red degraded state.
|
|
45
|
+
*
|
|
46
|
+
* Note: this optimism also means a service held `UNKNOWN` indefinitely (e.g. an
|
|
47
|
+
* endpoint whose polls keep failing) does not by itself pull the aggregate below
|
|
48
|
+
* `ONLINE` — a deliberate v1 tradeoff to keep transient errors from flapping the
|
|
49
|
+
* indicator. Surfacing a long-lived failure distinctly (likely via health rather
|
|
50
|
+
* than connectivity) is left as a future refinement.
|
|
51
|
+
*/
|
|
52
|
+
export declare const aggregateConnectivity: (services: Record<string, ServiceConnection>) => RobotConnectivity;
|
|
53
|
+
/**
|
|
54
|
+
* Polls a single service's `connections` endpoint on an interval, emitting its
|
|
55
|
+
* {@link ServiceConnection} (change-only). A failed/timed-out poll yields
|
|
56
|
+
* `UNKNOWN` (held transitional) rather than `DISCONNECTED`, to avoid a spurious
|
|
57
|
+
* degraded flash on a transient error.
|
|
58
|
+
*
|
|
59
|
+
* `pollMs` is floored at {@link MIN_CONNECTIVITY_POLL_MS} so the endpoint can't
|
|
60
|
+
* be polled unreasonably fast.
|
|
61
|
+
*/
|
|
62
|
+
export declare const getServiceConnectionChanges: (httpGet: ConnectionsHttpGet, url: string, pollMs?: number) => Observable<ServiceConnection>;
|
|
63
|
+
export interface ConnectivityDeps {
|
|
64
|
+
httpGet: ConnectionsHttpGet;
|
|
65
|
+
baseUrl: string;
|
|
66
|
+
insecure?: boolean;
|
|
67
|
+
/** The telemetry-liveness signal (from `getTelemetryLiveness`), folded in as one service. */
|
|
68
|
+
telemetryLiveness$: Observable<ServiceConnection>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Emits the robot's {@link RobotConnectivityStatus} — the per-service breakdown
|
|
72
|
+
* plus the aggregate verdict — for the configured `expectedServices`. HTTP
|
|
73
|
+
* services are polled; `telemetry-liveness` uses the supplied observable; any
|
|
74
|
+
* unrecognised service id resolves to `UNKNOWN`.
|
|
75
|
+
*/
|
|
76
|
+
export declare const getConnectivityChanges: (deps: ConnectivityDeps, projectId: string, callsign: string, expectedServices?: string[], pollMs?: number) => Observable<RobotConnectivityStatus>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getConnectivityChanges = exports.getServiceConnectionChanges = exports.aggregateConnectivity = exports.mapConnectionStatus = exports.buildConnectionsUrl = exports.clampPollInterval = exports.MIN_CONNECTIVITY_POLL_MS = exports.DEFAULT_EXPECTED_SERVICES = exports.TELEMETRY_LIVENESS_SERVICE = exports.CONNECTION_SERVICE_PREFIXES = void 0;
|
|
4
|
+
const api_1 = require("../../constants/api");
|
|
5
|
+
const models_1 = require("../../models");
|
|
6
|
+
const rxjs_1 = require("rxjs");
|
|
7
|
+
const formatServiceUrl_1 = require("../../helpers/formatServiceUrl");
|
|
8
|
+
/**
|
|
9
|
+
* Service id → public path prefix, for services that expose the standard
|
|
10
|
+
* `connections` endpoint. New services adopting the convention are added here.
|
|
11
|
+
* The `telemetry` (Teletubby) endpoint joins this once built — see EAI-718/719.
|
|
12
|
+
*/
|
|
13
|
+
exports.CONNECTION_SERVICE_PREFIXES = {
|
|
14
|
+
'robot-configs': 'robot-configs',
|
|
15
|
+
'robot-services': 'robot-services',
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The telemetry-liveness signal is derived from heartbeat freshness rather than
|
|
19
|
+
* an HTTP endpoint, so it is handled specially (its observable is supplied by
|
|
20
|
+
* the caller). See `getTelemetryLiveness`.
|
|
21
|
+
*/
|
|
22
|
+
exports.TELEMETRY_LIVENESS_SERVICE = 'telemetry-liveness';
|
|
23
|
+
/**
|
|
24
|
+
* The services evaluated by default. The `telemetry` connections endpoint joins
|
|
25
|
+
* this list once Teletubby exposes it (follow-up).
|
|
26
|
+
*/
|
|
27
|
+
exports.DEFAULT_EXPECTED_SERVICES = [exports.TELEMETRY_LIVENESS_SERVICE, 'robot-configs', 'robot-services'];
|
|
28
|
+
const DEFAULT_CONNECTIVITY_POLL_MS = 5000;
|
|
29
|
+
/**
|
|
30
|
+
* Floor for the connections-endpoint poll interval. Guards against a caller
|
|
31
|
+
* passing `0` (or any tiny value), which would otherwise poll the API on every
|
|
32
|
+
* event-loop tick.
|
|
33
|
+
*/
|
|
34
|
+
exports.MIN_CONNECTIVITY_POLL_MS = 250;
|
|
35
|
+
/** Clamps a requested poll interval up to {@link MIN_CONNECTIVITY_POLL_MS}. */
|
|
36
|
+
const clampPollInterval = (pollMs) => Math.max(pollMs, exports.MIN_CONNECTIVITY_POLL_MS);
|
|
37
|
+
exports.clampPollInterval = clampPollInterval;
|
|
38
|
+
/**
|
|
39
|
+
* Builds the `connections` endpoint URL for a service — per-callsign when a
|
|
40
|
+
* callsign is given, otherwise the bulk per-project variant.
|
|
41
|
+
*/
|
|
42
|
+
const buildConnectionsUrl = (serviceId, baseUrl, projectId, callsign, insecure) => {
|
|
43
|
+
const template = callsign ? api_1.API_SERVICE_CONNECTION_URL : api_1.API_SERVICE_CONNECTIONS_URL;
|
|
44
|
+
const params = { url: baseUrl, service: exports.CONNECTION_SERVICE_PREFIXES[serviceId], projectId };
|
|
45
|
+
if (callsign)
|
|
46
|
+
params.callsign = callsign;
|
|
47
|
+
return (0, formatServiceUrl_1.formatServiceUrl)(template, params, insecure);
|
|
48
|
+
};
|
|
49
|
+
exports.buildConnectionsUrl = buildConnectionsUrl;
|
|
50
|
+
/** Maps a `connections` endpoint response onto a {@link ServiceConnection}. */
|
|
51
|
+
const mapConnectionStatus = (connection) => {
|
|
52
|
+
if (connection?.status === models_1.ConnectionStatus.CONNECTED)
|
|
53
|
+
return models_1.ServiceConnection.CONNECTED;
|
|
54
|
+
if (connection?.status === models_1.ConnectionStatus.DISCONNECTED)
|
|
55
|
+
return models_1.ServiceConnection.DISCONNECTED;
|
|
56
|
+
return models_1.ServiceConnection.UNKNOWN;
|
|
57
|
+
};
|
|
58
|
+
exports.mapConnectionStatus = mapConnectionStatus;
|
|
59
|
+
/**
|
|
60
|
+
* Aggregates per-service connection states into an overall verdict:
|
|
61
|
+
* - `ONLINE` — at least one service connected and none disconnected.
|
|
62
|
+
* - `DEGRADED` — a genuine mix: some connected, some disconnected.
|
|
63
|
+
* - `OFFLINE` — nothing connected.
|
|
64
|
+
*
|
|
65
|
+
* `UNKNOWN` services (e.g. not yet polled) never force `DEGRADED`, so startup
|
|
66
|
+
* settles on `OFFLINE` (gray) rather than a spurious flashing-red degraded state.
|
|
67
|
+
*
|
|
68
|
+
* Note: this optimism also means a service held `UNKNOWN` indefinitely (e.g. an
|
|
69
|
+
* endpoint whose polls keep failing) does not by itself pull the aggregate below
|
|
70
|
+
* `ONLINE` — a deliberate v1 tradeoff to keep transient errors from flapping the
|
|
71
|
+
* indicator. Surfacing a long-lived failure distinctly (likely via health rather
|
|
72
|
+
* than connectivity) is left as a future refinement.
|
|
73
|
+
*/
|
|
74
|
+
const aggregateConnectivity = (services) => {
|
|
75
|
+
const values = Object.values(services);
|
|
76
|
+
const hasConnected = values.includes(models_1.ServiceConnection.CONNECTED);
|
|
77
|
+
const hasDisconnected = values.includes(models_1.ServiceConnection.DISCONNECTED);
|
|
78
|
+
if (hasConnected && hasDisconnected)
|
|
79
|
+
return models_1.RobotConnectivity.DEGRADED;
|
|
80
|
+
if (hasConnected)
|
|
81
|
+
return models_1.RobotConnectivity.ONLINE;
|
|
82
|
+
return models_1.RobotConnectivity.OFFLINE;
|
|
83
|
+
};
|
|
84
|
+
exports.aggregateConnectivity = aggregateConnectivity;
|
|
85
|
+
/**
|
|
86
|
+
* Polls a single service's `connections` endpoint on an interval, emitting its
|
|
87
|
+
* {@link ServiceConnection} (change-only). A failed/timed-out poll yields
|
|
88
|
+
* `UNKNOWN` (held transitional) rather than `DISCONNECTED`, to avoid a spurious
|
|
89
|
+
* degraded flash on a transient error.
|
|
90
|
+
*
|
|
91
|
+
* `pollMs` is floored at {@link MIN_CONNECTIVITY_POLL_MS} so the endpoint can't
|
|
92
|
+
* be polled unreasonably fast.
|
|
93
|
+
*/
|
|
94
|
+
const getServiceConnectionChanges = (httpGet, url, pollMs = DEFAULT_CONNECTIVITY_POLL_MS) => {
|
|
95
|
+
return (0, rxjs_1.timer)(0, (0, exports.clampPollInterval)(pollMs)).pipe((0, rxjs_1.switchMap)(() => {
|
|
96
|
+
return (0, rxjs_1.from)(httpGet(url)).pipe((0, rxjs_1.map)(exports.mapConnectionStatus), (0, rxjs_1.catchError)(() => (0, rxjs_1.of)(models_1.ServiceConnection.UNKNOWN)));
|
|
97
|
+
}), (0, rxjs_1.startWith)(models_1.ServiceConnection.UNKNOWN), (0, rxjs_1.distinctUntilChanged)());
|
|
98
|
+
};
|
|
99
|
+
exports.getServiceConnectionChanges = getServiceConnectionChanges;
|
|
100
|
+
const connectivityEquals = (a, b) => {
|
|
101
|
+
if (a.overall !== b.overall)
|
|
102
|
+
return false;
|
|
103
|
+
const keys = Object.keys(a.services);
|
|
104
|
+
if (keys.length !== Object.keys(b.services).length)
|
|
105
|
+
return false;
|
|
106
|
+
return keys.every((key) => a.services[key] === b.services[key]);
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Emits the robot's {@link RobotConnectivityStatus} — the per-service breakdown
|
|
110
|
+
* plus the aggregate verdict — for the configured `expectedServices`. HTTP
|
|
111
|
+
* services are polled; `telemetry-liveness` uses the supplied observable; any
|
|
112
|
+
* unrecognised service id resolves to `UNKNOWN`.
|
|
113
|
+
*/
|
|
114
|
+
const getConnectivityChanges = (deps, projectId, callsign, expectedServices = exports.DEFAULT_EXPECTED_SERVICES, pollMs = DEFAULT_CONNECTIVITY_POLL_MS) => {
|
|
115
|
+
// combineLatest([]) completes without emitting; emit an explicit empty/offline status instead.
|
|
116
|
+
if (expectedServices.length === 0) {
|
|
117
|
+
return (0, rxjs_1.of)({ overall: models_1.RobotConnectivity.OFFLINE, services: {} });
|
|
118
|
+
}
|
|
119
|
+
const perService = expectedServices.map((serviceId) => {
|
|
120
|
+
let source$;
|
|
121
|
+
if (serviceId === exports.TELEMETRY_LIVENESS_SERVICE) {
|
|
122
|
+
source$ = deps.telemetryLiveness$;
|
|
123
|
+
}
|
|
124
|
+
else if (serviceId in exports.CONNECTION_SERVICE_PREFIXES) {
|
|
125
|
+
const url = (0, exports.buildConnectionsUrl)(serviceId, deps.baseUrl, projectId, callsign, deps.insecure);
|
|
126
|
+
source$ = (0, exports.getServiceConnectionChanges)(deps.httpGet, url, pollMs);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
source$ = (0, rxjs_1.of)(models_1.ServiceConnection.UNKNOWN);
|
|
130
|
+
}
|
|
131
|
+
return source$.pipe((0, rxjs_1.startWith)(models_1.ServiceConnection.UNKNOWN), (0, rxjs_1.map)((connection) => ({ serviceId, connection })));
|
|
132
|
+
});
|
|
133
|
+
return (0, rxjs_1.combineLatest)(perService).pipe((0, rxjs_1.map)((entries) => {
|
|
134
|
+
const services = {};
|
|
135
|
+
for (const { serviceId, connection } of entries)
|
|
136
|
+
services[serviceId] = connection;
|
|
137
|
+
return { overall: (0, exports.aggregateConnectivity)(services), services };
|
|
138
|
+
}), (0, rxjs_1.distinctUntilChanged)(connectivityEquals));
|
|
139
|
+
};
|
|
140
|
+
exports.getConnectivityChanges = getConnectivityChanges;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { RobotHealth, RobotReadiness, ServiceConnection } from '../../models';
|
|
3
|
+
import { TelemetryService } from '../TelemetryService';
|
|
4
|
+
/** The new agent topic carrying health + readiness (replaces the heartbeat). */
|
|
5
|
+
export declare const ROBOT_STATUS_SOURCE = "/diagnostics/robot/status";
|
|
6
|
+
/** The legacy heartbeat topic — liveness only, no status payload. */
|
|
7
|
+
export declare const LEGACY_HEARTBEAT_SOURCE = "/rocos/agent/telemetry/heartbeat";
|
|
8
|
+
export interface ReportedRobotStatus {
|
|
9
|
+
health: RobotHealth;
|
|
10
|
+
readiness: RobotReadiness;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Maps a `robot/status` wire value (integer, or its string equivalent) to a
|
|
14
|
+
* {@link RobotHealth}. Anything unrecognised — including `0` / `'unknown'` —
|
|
15
|
+
* resolves to {@link RobotHealth.UNKNOWN}.
|
|
16
|
+
*/
|
|
17
|
+
export declare const parseRobotHealth: (value: unknown) => RobotHealth;
|
|
18
|
+
/** As {@link parseRobotHealth}, for {@link RobotReadiness}. */
|
|
19
|
+
export declare const parseRobotReadiness: (value: unknown) => RobotReadiness;
|
|
20
|
+
/**
|
|
21
|
+
* Emits the robot's reported health/readiness, subscribing to the new
|
|
22
|
+
* `robot/status` topic and the legacy heartbeat concurrently.
|
|
23
|
+
*
|
|
24
|
+
* The new topic takes precedence: once any `robot/status` message has been seen,
|
|
25
|
+
* legacy heartbeats no longer affect the reported value. While only the legacy
|
|
26
|
+
* heartbeat is present, a live heartbeat is reported as `NORMAL`/`IDLE` — which
|
|
27
|
+
* preserves today's "online ⇒ green" behaviour for agents not yet emitting the
|
|
28
|
+
* new topic.
|
|
29
|
+
*/
|
|
30
|
+
export declare const getReportedStatusChanges: (telemetry: TelemetryService, projectId: string, callsign: string) => Observable<ReportedRobotStatus>;
|
|
31
|
+
/**
|
|
32
|
+
* Emits the `telemetry-liveness` connectivity signal: whether a heartbeat (from
|
|
33
|
+
* either the new `robot/status` topic or the legacy heartbeat) has been received
|
|
34
|
+
* within `heartbeatTimeoutMs`. Mirrors {@link TelemetryService.monitorTelemetryWithTimeout}
|
|
35
|
+
* but spans both topics and maps onto {@link ServiceConnection} so it can be
|
|
36
|
+
* folded into connectivity aggregation as just another service entry.
|
|
37
|
+
*/
|
|
38
|
+
export declare const getTelemetryLiveness: (telemetry: TelemetryService, projectId: string, callsign: string, heartbeatTimeoutMs?: number, intervalMs?: number) => Observable<ServiceConnection>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTelemetryLiveness = exports.getReportedStatusChanges = exports.parseRobotReadiness = exports.parseRobotHealth = exports.LEGACY_HEARTBEAT_SOURCE = exports.ROBOT_STATUS_SOURCE = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const models_1 = require("../../models");
|
|
6
|
+
/** The new agent topic carrying health + readiness (replaces the heartbeat). */
|
|
7
|
+
exports.ROBOT_STATUS_SOURCE = '/diagnostics/robot/status';
|
|
8
|
+
/** The legacy heartbeat topic — liveness only, no status payload. */
|
|
9
|
+
exports.LEGACY_HEARTBEAT_SOURCE = '/rocos/agent/telemetry/heartbeat';
|
|
10
|
+
const DEFAULT_HEARTBEAT_TIMEOUT_MS = 5000;
|
|
11
|
+
const DEFAULT_INTERVAL_MS = 2000;
|
|
12
|
+
/**
|
|
13
|
+
* Maps a `robot/status` wire value (integer, or its string equivalent) to a
|
|
14
|
+
* {@link RobotHealth}. Anything unrecognised — including `0` / `'unknown'` —
|
|
15
|
+
* resolves to {@link RobotHealth.UNKNOWN}.
|
|
16
|
+
*/
|
|
17
|
+
const parseRobotHealth = (value) => {
|
|
18
|
+
switch (value) {
|
|
19
|
+
case 1:
|
|
20
|
+
case '1':
|
|
21
|
+
case 'normal':
|
|
22
|
+
return models_1.RobotHealth.NORMAL;
|
|
23
|
+
case 2:
|
|
24
|
+
case '2':
|
|
25
|
+
case 'abnormal':
|
|
26
|
+
return models_1.RobotHealth.ABNORMAL;
|
|
27
|
+
case 3:
|
|
28
|
+
case '3':
|
|
29
|
+
case 'critical':
|
|
30
|
+
return models_1.RobotHealth.CRITICAL;
|
|
31
|
+
default:
|
|
32
|
+
return models_1.RobotHealth.UNKNOWN;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
exports.parseRobotHealth = parseRobotHealth;
|
|
36
|
+
/** As {@link parseRobotHealth}, for {@link RobotReadiness}. */
|
|
37
|
+
const parseRobotReadiness = (value) => {
|
|
38
|
+
switch (value) {
|
|
39
|
+
case 1:
|
|
40
|
+
case '1':
|
|
41
|
+
case 'idle':
|
|
42
|
+
return models_1.RobotReadiness.IDLE;
|
|
43
|
+
case 2:
|
|
44
|
+
case '2':
|
|
45
|
+
case 'busy':
|
|
46
|
+
return models_1.RobotReadiness.BUSY;
|
|
47
|
+
default:
|
|
48
|
+
return models_1.RobotReadiness.UNKNOWN;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
exports.parseRobotReadiness = parseRobotReadiness;
|
|
52
|
+
/**
|
|
53
|
+
* Emits the robot's reported health/readiness, subscribing to the new
|
|
54
|
+
* `robot/status` topic and the legacy heartbeat concurrently.
|
|
55
|
+
*
|
|
56
|
+
* The new topic takes precedence: once any `robot/status` message has been seen,
|
|
57
|
+
* legacy heartbeats no longer affect the reported value. While only the legacy
|
|
58
|
+
* heartbeat is present, a live heartbeat is reported as `NORMAL`/`IDLE` — which
|
|
59
|
+
* preserves today's "online ⇒ green" behaviour for agents not yet emitting the
|
|
60
|
+
* new topic.
|
|
61
|
+
*/
|
|
62
|
+
const getReportedStatusChanges = (telemetry, projectId, callsign) => {
|
|
63
|
+
const new$ = telemetry
|
|
64
|
+
.subscribe({ projectId, callsigns: [callsign], sources: [exports.ROBOT_STATUS_SOURCE] })
|
|
65
|
+
.pipe((0, rxjs_1.map)((message) => ({
|
|
66
|
+
from: 'new',
|
|
67
|
+
status: {
|
|
68
|
+
health: (0, exports.parseRobotHealth)(message.payload?.health),
|
|
69
|
+
readiness: (0, exports.parseRobotReadiness)(message.payload?.readiness),
|
|
70
|
+
},
|
|
71
|
+
})));
|
|
72
|
+
const legacy$ = telemetry.subscribe({ projectId, callsigns: [callsign], sources: [exports.LEGACY_HEARTBEAT_SOURCE] }).pipe((0, rxjs_1.map)(() => ({
|
|
73
|
+
from: 'legacy',
|
|
74
|
+
status: { health: models_1.RobotHealth.NORMAL, readiness: models_1.RobotReadiness.IDLE },
|
|
75
|
+
})));
|
|
76
|
+
return (0, rxjs_1.merge)(new$, legacy$).pipe((0, rxjs_1.scan)((acc, event) => {
|
|
77
|
+
if (event.from === 'new')
|
|
78
|
+
return { seenNew: true, status: event.status };
|
|
79
|
+
// Legacy heartbeat: only honoured until the new topic has been seen.
|
|
80
|
+
return acc.seenNew ? acc : { seenNew: false, status: event.status };
|
|
81
|
+
}, { seenNew: false, status: undefined }), (0, rxjs_1.map)((acc) => acc.status), (0, rxjs_1.filter)((status) => status !== undefined), (0, rxjs_1.distinctUntilChanged)((a, b) => a.health === b.health && a.readiness === b.readiness),
|
|
82
|
+
// A telemetry error would otherwise terminate this stream permanently; fall back to
|
|
83
|
+
// UNKNOWN/UNKNOWN (matching getTelemetryLiveness) so subscribers get an honest value.
|
|
84
|
+
(0, rxjs_1.catchError)(() => (0, rxjs_1.of)({ health: models_1.RobotHealth.UNKNOWN, readiness: models_1.RobotReadiness.UNKNOWN })));
|
|
85
|
+
};
|
|
86
|
+
exports.getReportedStatusChanges = getReportedStatusChanges;
|
|
87
|
+
/**
|
|
88
|
+
* Emits the `telemetry-liveness` connectivity signal: whether a heartbeat (from
|
|
89
|
+
* either the new `robot/status` topic or the legacy heartbeat) has been received
|
|
90
|
+
* within `heartbeatTimeoutMs`. Mirrors {@link TelemetryService.monitorTelemetryWithTimeout}
|
|
91
|
+
* but spans both topics and maps onto {@link ServiceConnection} so it can be
|
|
92
|
+
* folded into connectivity aggregation as just another service entry.
|
|
93
|
+
*/
|
|
94
|
+
const getTelemetryLiveness = (telemetry, projectId, callsign, heartbeatTimeoutMs = DEFAULT_HEARTBEAT_TIMEOUT_MS, intervalMs = DEFAULT_INTERVAL_MS) => {
|
|
95
|
+
const startedAt = Date.now();
|
|
96
|
+
const lastMessageAt$ = telemetry
|
|
97
|
+
.subscribe({ projectId, callsigns: [callsign], sources: [exports.ROBOT_STATUS_SOURCE, exports.LEGACY_HEARTBEAT_SOURCE] })
|
|
98
|
+
.pipe((0, rxjs_1.map)(() => Date.now()));
|
|
99
|
+
return (0, rxjs_1.combineLatest)([lastMessageAt$.pipe((0, rxjs_1.startWith)(startedAt)), (0, rxjs_1.interval)(intervalMs)]).pipe((0, rxjs_1.map)(([lastMessageAt]) => {
|
|
100
|
+
const now = Date.now();
|
|
101
|
+
// No message yet, but still within the initial grace period.
|
|
102
|
+
if (lastMessageAt === startedAt && now - startedAt <= heartbeatTimeoutMs)
|
|
103
|
+
return models_1.ServiceConnection.UNKNOWN;
|
|
104
|
+
if (now - lastMessageAt > heartbeatTimeoutMs)
|
|
105
|
+
return models_1.ServiceConnection.DISCONNECTED;
|
|
106
|
+
return models_1.ServiceConnection.CONNECTED;
|
|
107
|
+
}), (0, rxjs_1.startWith)(models_1.ServiceConnection.UNKNOWN), (0, rxjs_1.distinctUntilChanged)(), (0, rxjs_1.catchError)(() => (0, rxjs_1.of)(models_1.ServiceConnection.UNKNOWN)));
|
|
108
|
+
};
|
|
109
|
+
exports.getTelemetryLiveness = getTelemetryLiveness;
|
package/esm/IRocosSDK.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, DeviceCredentialsService, EnvironmentService, EvaluatorService, EventService, FileAccessorService, IntegrationService, MapService, ProfileService, ProjectService, RTPWebRTCService, RobotService, SearchService, SpotProvisioningService, SpotProvisioningServiceNode, StreamService, TagService, TargetService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService } from './services';
|
|
1
|
+
import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, DeviceCredentialsService, EnvironmentService, EvaluatorService, EventService, FileAccessorService, IntegrationService, MapService, ProfileService, ProjectService, RTPWebRTCService, RobotService, RobotStatusService, SearchService, SpotProvisioningService, SpotProvisioningServiceNode, StreamService, TagService, TargetService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService } from './services';
|
|
2
2
|
import { IBaseService, IDebugLevel, ServiceEnum } from './models';
|
|
3
3
|
export declare abstract class IRocosSDK {
|
|
4
4
|
abstract getService<T extends IBaseService>(_name: ServiceEnum): T;
|
|
5
5
|
abstract getAuthService(): AuthService;
|
|
6
6
|
abstract getRobotService(): RobotService;
|
|
7
|
+
abstract getRobotStatusService(): RobotStatusService;
|
|
7
8
|
abstract getEventService(): EventService;
|
|
8
9
|
abstract getEnvironmentService(): EnvironmentService;
|
|
9
10
|
abstract getProjectService(): ProjectService;
|
package/esm/RocosSDK.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, DeviceCredentialsService, EnvironmentService, EvaluatorService, EventService, FileAccessorService, IntegrationService, MapService, ProfileService, ProjectService, RTPWebRTCService, RobotService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TagService, TargetService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService } from './services';
|
|
1
|
+
import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, DeviceCredentialsService, EnvironmentService, EvaluatorService, EventService, FileAccessorService, IntegrationService, MapService, ProfileService, ProjectService, RTPWebRTCService, RobotService, RobotStatusService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TagService, TargetService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService } from './services';
|
|
2
2
|
import { AuthorisedConfig, IBaseService, IDebugLevel, IRocosSDKConfig, ServiceEnum } from './models';
|
|
3
3
|
import { IRocosSDK } from './IRocosSDK';
|
|
4
4
|
import { Logger } from 'loglevel';
|
|
@@ -26,6 +26,10 @@ export declare class RocosSDK implements IRocosSDK {
|
|
|
26
26
|
* Gets the robot service.
|
|
27
27
|
*/
|
|
28
28
|
getRobotService(): RobotService;
|
|
29
|
+
/**
|
|
30
|
+
* Gets the robot status service.
|
|
31
|
+
*/
|
|
32
|
+
getRobotStatusService(): RobotStatusService;
|
|
29
33
|
/**
|
|
30
34
|
* Gets the event service.
|
|
31
35
|
*/
|
package/esm/RocosSDK.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, DeviceCredentialsService, EnvironmentService, EvaluatorService, EventService, FileAccessorService, IntegrationService, MapService, PlatFormTimeService, ProfileService, ProjectService, RTPWebRTCService, RobotService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TagService, TargetService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService, } from './services';
|
|
1
|
+
import { AssetStorageService, AuthService, CallerService, CommandService, ConfigGroupService, ControlService, DashboardService, DeviceCredentialsService, EnvironmentService, EvaluatorService, EventService, FileAccessorService, IntegrationService, MapService, PlatFormTimeService, ProfileService, ProjectService, RTPWebRTCService, RobotService, RobotStatusService, ScheduleService, SearchService, SpotProvisioningService, StreamService, TagService, TargetService, TelemetryService, TimeSyncerService, UserService, WebRTCSignallingService, WorkflowService, } from './services';
|
|
2
2
|
import { ServiceEnum } from './models';
|
|
3
3
|
import { RocosLogger } from './logger/RocosLogger';
|
|
4
4
|
import { RocosStore } from './store/RocosStore';
|
|
@@ -35,6 +35,9 @@ export class RocosSDK {
|
|
|
35
35
|
case ServiceEnum.ROBOT:
|
|
36
36
|
this.services[name] = new RobotService(config);
|
|
37
37
|
break;
|
|
38
|
+
case ServiceEnum.ROBOT_STATUS:
|
|
39
|
+
this.services[name] = new RobotStatusService(config);
|
|
40
|
+
break;
|
|
38
41
|
case ServiceEnum.ENVIRONMENT:
|
|
39
42
|
this.services[name] = new EnvironmentService(config);
|
|
40
43
|
break;
|
|
@@ -130,6 +133,12 @@ export class RocosSDK {
|
|
|
130
133
|
getRobotService() {
|
|
131
134
|
return this.getService(ServiceEnum.ROBOT);
|
|
132
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Gets the robot status service.
|
|
138
|
+
*/
|
|
139
|
+
getRobotStatusService() {
|
|
140
|
+
return this.getService(ServiceEnum.ROBOT_STATUS);
|
|
141
|
+
}
|
|
133
142
|
/**
|
|
134
143
|
* Gets the event service.
|
|
135
144
|
*/
|
package/esm/constants/api.d.ts
CHANGED
|
@@ -56,8 +56,10 @@ export declare const API_PROJECT_ROBOT_COMMAND2_URL = "https://{url}/projects/{p
|
|
|
56
56
|
export declare const API_PROJECT_ROBOT_BUTTON_URL = "https://{url}/projects/{projectId}/robots/{callsign}/buttons";
|
|
57
57
|
export declare const API_PROJECT_ROBOT_TRIGGER_URL = "https://{url}/projects/{projectId}/robots/{callsign}/triggers";
|
|
58
58
|
export declare const API_PROJECT_ROBOT_GAMEPAD_URL = "https://{url}/projects/{projectId}/robots/{callsign}/gamepads";
|
|
59
|
-
export declare const
|
|
60
|
-
export declare const
|
|
59
|
+
export declare const API_SERVICE_CONNECTIONS_URL = "https://{url}/{service}/connections/projects/{projectId}";
|
|
60
|
+
export declare const API_SERVICE_CONNECTION_URL = "https://{url}/{service}/connections/projects/{projectId}/callsigns/{callsign}";
|
|
61
|
+
export declare const API_PROJECT_ROBOT_CONFIGS_CONNECTIONS_URL: string;
|
|
62
|
+
export declare const API_PROJECT_ROBOT_CONFIGS_CONNECTION_URL: string;
|
|
61
63
|
export declare const API_PROJECT_OPERATION_URL = "https://{url}/projects/{projectId}/operations";
|
|
62
64
|
export declare const API_PROJECT_OPERATION_ID_URL = "https://{url}/projects/{projectId}/operations/{operationId}";
|
|
63
65
|
export declare const API_PROJECT_DASHBOARD_URL = "https://{url}/projects/{projectId}/dashboards";
|
|
@@ -134,6 +136,10 @@ export declare const API_GRAPHS_MAP_NODE_URL = "https://{url}/graphs/projects/{p
|
|
|
134
136
|
export declare const API_GRAPHS_MAP_EDGES_ADD_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/edges/add";
|
|
135
137
|
export declare const API_GRAPHS_MAP_EDGES_ADD_TRANSFORM_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/edges/add/transform";
|
|
136
138
|
export declare const API_GRAPHS_MAP_EDGE_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/edges/{edgeId}";
|
|
139
|
+
export declare const API_GRAPHS_MAP_PATHS_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths";
|
|
140
|
+
export declare const API_GRAPHS_MAP_PATH_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths/{pathId}";
|
|
141
|
+
export declare const API_GRAPHS_MAP_PATH_APPEND_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths/{pathId}/append";
|
|
142
|
+
export declare const API_GRAPHS_MAP_PATH_APPEND_TRANSFORMABLE_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths/{pathId}/append/transformable";
|
|
137
143
|
export declare const API_GRAPHS_MAPS_COPY_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/copy";
|
|
138
144
|
export declare const API_GRAPHS_MAPS_DEPLOY_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/deploy";
|
|
139
145
|
export declare const API_GRAPHS_MAPS_GEOJSON_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/geojson";
|
package/esm/constants/api.js
CHANGED
|
@@ -56,8 +56,12 @@ export const API_PROJECT_ROBOT_COMMAND2_URL = 'https://{url}/projects/{projectId
|
|
|
56
56
|
export const API_PROJECT_ROBOT_BUTTON_URL = 'https://{url}/projects/{projectId}/robots/{callsign}/buttons';
|
|
57
57
|
export const API_PROJECT_ROBOT_TRIGGER_URL = 'https://{url}/projects/{projectId}/robots/{callsign}/triggers';
|
|
58
58
|
export const API_PROJECT_ROBOT_GAMEPAD_URL = 'https://{url}/projects/{projectId}/robots/{callsign}/gamepads';
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
// Generic connections endpoint templates. `{service}` is the service's public path prefix
|
|
60
|
+
// (e.g. robot-configs, robot-services); the per-service specialisations below derive from these.
|
|
61
|
+
export const API_SERVICE_CONNECTIONS_URL = 'https://{url}/{service}/connections/projects/{projectId}';
|
|
62
|
+
export const API_SERVICE_CONNECTION_URL = 'https://{url}/{service}/connections/projects/{projectId}/callsigns/{callsign}';
|
|
63
|
+
export const API_PROJECT_ROBOT_CONFIGS_CONNECTIONS_URL = API_SERVICE_CONNECTIONS_URL.replace('{service}', 'robot-configs');
|
|
64
|
+
export const API_PROJECT_ROBOT_CONFIGS_CONNECTION_URL = API_SERVICE_CONNECTION_URL.replace('{service}', 'robot-configs');
|
|
61
65
|
export const API_PROJECT_OPERATION_URL = 'https://{url}/projects/{projectId}/operations';
|
|
62
66
|
export const API_PROJECT_OPERATION_ID_URL = 'https://{url}/projects/{projectId}/operations/{operationId}';
|
|
63
67
|
export const API_PROJECT_DASHBOARD_URL = 'https://{url}/projects/{projectId}/dashboards';
|
|
@@ -134,6 +138,10 @@ export const API_GRAPHS_MAP_NODE_URL = 'https://{url}/graphs/projects/{projectId
|
|
|
134
138
|
export const API_GRAPHS_MAP_EDGES_ADD_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/edges/add';
|
|
135
139
|
export const API_GRAPHS_MAP_EDGES_ADD_TRANSFORM_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/edges/add/transform';
|
|
136
140
|
export const API_GRAPHS_MAP_EDGE_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/edges/{edgeId}';
|
|
141
|
+
export const API_GRAPHS_MAP_PATHS_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths';
|
|
142
|
+
export const API_GRAPHS_MAP_PATH_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths/{pathId}';
|
|
143
|
+
export const API_GRAPHS_MAP_PATH_APPEND_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths/{pathId}/append';
|
|
144
|
+
export const API_GRAPHS_MAP_PATH_APPEND_TRANSFORMABLE_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/paths/{pathId}/append/transformable';
|
|
137
145
|
export const API_GRAPHS_MAPS_COPY_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/copy';
|
|
138
146
|
export const API_GRAPHS_MAPS_DEPLOY_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/deploy';
|
|
139
147
|
export const API_GRAPHS_MAPS_GEOJSON_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/geojson';
|