@dronedeploy/rocos-js-sdk 3.1.5 → 3.1.7
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/constants/api.d.ts +1 -0
- package/cjs/constants/api.js +3 -2
- package/cjs/helpers/getRobotStatusColour.d.ts +25 -0
- package/cjs/helpers/getRobotStatusColour.js +54 -0
- package/cjs/helpers/index.d.ts +1 -0
- package/cjs/helpers/index.js +1 -0
- package/cjs/models/index.d.ts +2 -0
- package/cjs/models/index.js +2 -0
- package/cjs/models/maps/Panorama.d.ts +18 -0
- package/cjs/models/robot-status/RobotStatus.d.ts +43 -0
- package/cjs/models/robot-status/RobotStatus.js +2 -0
- package/cjs/models/robot-status/RobotStatusEnums.d.ts +54 -0
- package/cjs/models/robot-status/RobotStatusEnums.js +61 -0
- package/cjs/services/CallerService.d.ts +38 -0
- package/cjs/services/CallerService.js +56 -0
- package/cjs/services/MapService.d.ts +20 -1
- package/cjs/services/MapService.js +21 -0
- package/esm/constants/api.d.ts +1 -0
- package/esm/constants/api.js +1 -0
- package/esm/helpers/getRobotStatusColour.d.ts +25 -0
- package/esm/helpers/getRobotStatusColour.js +50 -0
- package/esm/helpers/index.d.ts +1 -0
- package/esm/helpers/index.js +1 -0
- package/esm/models/index.d.ts +2 -0
- package/esm/models/index.js +2 -0
- package/esm/models/maps/Panorama.d.ts +18 -0
- package/esm/models/robot-status/RobotStatus.d.ts +43 -0
- package/esm/models/robot-status/RobotStatus.js +1 -0
- package/esm/models/robot-status/RobotStatusEnums.d.ts +54 -0
- package/esm/models/robot-status/RobotStatusEnums.js +58 -0
- package/esm/services/CallerService.d.ts +38 -0
- package/esm/services/CallerService.js +57 -1
- package/esm/services/MapService.d.ts +20 -1
- package/esm/services/MapService.js +22 -1
- package/package.json +1 -1
package/cjs/constants/api.d.ts
CHANGED
|
@@ -131,6 +131,7 @@ export declare const API_GRAPHS_MAP_METADATA_URL = "https://{url}/graphs/project
|
|
|
131
131
|
export declare const API_GRAPHS_MAPS_COPY_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/copy";
|
|
132
132
|
export declare const API_GRAPHS_MAPS_DEPLOY_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/deploy";
|
|
133
133
|
export declare const API_GRAPHS_MAPS_GEOJSON_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/geojson";
|
|
134
|
+
export declare const API_GRAPHS_PANORAMAS_URL = "https://{url}/graphs/projects/{projectId}/panoramas";
|
|
134
135
|
export declare const API_GRAPHS_PANORAMA = "https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}";
|
|
135
136
|
export declare const API_GRAPHS_PANORAMA_OBSERVATIONS_URL = "https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}/observations";
|
|
136
137
|
export declare const API_GRAPHS_OBSERVATIONS_URL = "https://{url}/graphs/projects/{projectId}/observations";
|
package/cjs/constants/api.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.API_PROJECT_ROBOT_EVENT_URL = exports.API_PROJECT_ROBOT_REGISTER_URL = exports.API_PROJECT_ROBOT_DEFINITION_URL = exports.API_PROJECT_ROBOT_ATTRIBUTES_URL = exports.API_PROJECT_ROBOT_ID_URL = exports.API_ACCOUNT_ROBOT_URL = exports.API_PROJECT_ROBOT_URL = exports.API_PROJECT_MAPPED_ASSET_PATH_URL = exports.API_PROJECT_MAPPED_ASSETS_PATH_URL = exports.API_PROJECT_MISSION_ASSET_PATH_URL = exports.API_PROJECT_MISSION_ASSETS_PATH_URL = exports.API_PROJECT_FLOW_ASSET_PATH_URL = exports.API_PROJECT_ROBOT_ASSET_PATH_URL = exports.API_PROJECT_ASSET_INTEGRATION_PATH_URL = exports.API_PROJECT_ASSET_INTEGRATIONS_PATH_URL = exports.API_PROJECT_ASSET_INTEGRATION_PROVIDERS_PATH_URL = exports.API_PROJECT_ASSET_PROFILES_SYNC_DEFINITION_PATH_URL = exports.API_PROJECT_ASSET_ROBOTS_SYNC_DEFINITION_PATH_URL = exports.API_PROJECT_ASSET_PATH_URL = exports.API_PROJECT_ASSET_URL = exports.API_PROJECT_USERS_URL = exports.API_PROJECT_ID_URL = exports.API_PROJECT_URL = exports.API_ACCOUNT_EXTERNAL_PROJECTS_URL = exports.API_ACCOUNT_PROJECT_APPLICATION_ID_URL = exports.API_ACCOUNT_PROJECT_APPLICATION_URL = exports.API_ACCOUNT_PROJECT_USER_ID_URL = exports.API_ACCOUNT_PROJECT_USER_URL = exports.API_ACCOUNT_PROJECT_ID_URL = exports.API_ACCOUNT_PROJECT_URL = exports.API_SERVER_TIME_URL = exports.API_ACCOUNT_SETTINGS_URL = exports.API_AUTH_USER_ACCOUNT_USER_ID_URL = exports.API_AUTH_USER_ACCOUNT_USER_URL = exports.API_ACCOUNT_ACTIVATE_URL = exports.API_ACCOUNT_ID_URL = exports.API_ACCOUNT_URL = exports.API_USER_PAT_TOKEN_URL = exports.API_USER_PAT_URL = exports.API_USER_VERIFY_EMAIL_URL = exports.API_USER_INVITATION_CHECK_URL = exports.API_USER_INVITATION_ACCEPT_URL = exports.API_USER_INVITATION_URL = exports.API_USER_PASSWORD_FORGOT_URL = exports.API_OTP_AUTH_URL = exports.API_OTP_URL = exports.API_USER_TOKEN_URL = exports.API_USER_URL = exports.API_ADMIN_USER_INVITATION_URL = exports.API_APPLICATION_AUTH_URL = void 0;
|
|
4
4
|
exports.API_PROJECT_STREAM_DATA_URL = exports.API_PROJECT_STREAM_ID_URL = exports.API_PROJECT_STREAM_URL = exports.API_PROJECT_GROUP_TYPE_OWNER_OVERRIDE_URL = exports.API_PROJECT_GROUP_TYPE_OWNER_ID_URL = exports.API_PROJECT_GROUP_TYPE_VERSION_URL = exports.API_PROJECT_GROUP_TYPE_CONFIG_URL = exports.API_PROJECT_GROUP_TYPE_PUBLISH_URL = exports.API_PROJECT_GROUP_TYPE_ID_URL = exports.API_PROJECT_GROUP_TYPE_URL = exports.API_PROJECT_ENVIRONMENT_URL = exports.API_PROJECT_DEFINITION_LIBRARY = exports.API_PROJECT_DEFINITION_IMPORT_LIBRARY = exports.API_PROJECT_DEFINITION_IMPORT = exports.API_PROJECT_DEFINITION_EXPORT = exports.API_PROJECT_DEFINITION_GAMEPAD_URL = exports.API_PROJECT_DEFINITION_TRIGGER_URL = exports.API_PROJECT_DEFINITION_BUTTON_URL = exports.API_PROJECT_DEFINITION_ACTION_URL = exports.API_PROJECT_DEFINITION_EVENT_URL = exports.API_PROJECT_DEFINITION_COMMAND2_URL = exports.API_PROJECT_DEFINITION_COMMAND_URL = exports.API_PROJECT_DEFINITION_AGENT_URL = exports.API_PROJECT_DEFINITION_SETTING_URL = exports.API_PROJECT_DEFINITION_BLOB_URL = exports.API_PROJECT_DEFINITION_DASHBOARD_URL = exports.API_PROJECT_DEFINITION_COPY_URL = exports.API_PROJECT_DEFINITION_STREAM_URL = exports.API_PROJECT_DEFINITION_ID_URL = exports.API_PROJECT_DEFINITION_URL = exports.API_PROJECT_VROBOT_DEPLOY_URL = exports.API_PROJECT_VROBOT_DETAILS_URL = exports.API_PROJECT_COLLECTION_DOCS_URL = exports.API_PROJECT_COLLECTION_ID_URL = exports.API_PROJECT_DASHBOARD_CUSTOM_WIDGET_URL = exports.API_PROJECT_DASHBOARD_WIDGET_URL = exports.API_PROJECT_DASHBOARD_ID_URL = exports.API_PROJECT_DASHBOARD_URL = exports.API_PROJECT_OPERATION_ID_URL = exports.API_PROJECT_OPERATION_URL = exports.API_PROJECT_ROBOT_CONFIGS_CONNECTION_URL = exports.API_PROJECT_ROBOT_CONFIGS_CONNECTIONS_URL = exports.API_PROJECT_ROBOT_GAMEPAD_URL = exports.API_PROJECT_ROBOT_TRIGGER_URL = exports.API_PROJECT_ROBOT_BUTTON_URL = exports.API_PROJECT_ROBOT_COMMAND2_URL = exports.API_PROJECT_ROBOT_COMMAND_URL = exports.API_PROJECT_ROBOT_AGENT_URL = exports.API_PROJECT_ROBOT_SETTING_URL = exports.API_PROJECT_ROBOT_EVENT_HISTORY_URL = void 0;
|
|
5
|
-
exports.
|
|
6
|
-
exports.API_PROJECT_ROBOT_TAG_URL = exports.API_PROJECT_PROFILE_TAG_URL = exports.API_PROJECT_PROFILE_TAGS_URL = exports.API_PROJECT_TAG_ROBOTS_URL = exports.API_PROJECT_ROBOT_TAGS_URL = exports.API_DEVICE_CREDENTIALS_AUTH_URL = exports.API_DEVICE_CREDENTIALS_URL = exports.API_LINKED_PROJECT_URL = exports.API_PROJECT_WORKFLOW_IMPORT_URL = exports.API_PROJECT_WORKFLOW_EXPORT_URL = exports.API_PROJECT_WORKFLOW_AFFECTED_URL = void 0;
|
|
5
|
+
exports.API_PROJECT_PROFILE_DEPLOYED_WORKFLOW_URL = exports.API_PROJECT_ROBOT_NO_PROFILE_DEPLOYMENTS_URL = exports.API_PROJECT_PROFILE_DEPLOYMENTS_URL = exports.API_PROJECT_ROBOT_DEPLOYMENTS_URL = exports.API_PROJECT_WORKFLOW_ASSET_ID_URL = exports.API_PROJECT_WORKFLOW_ASSET_URL = exports.API_PROJECT_WORKFLOW_ID_URL = exports.API_PROJECT_WORKFLOW_URL = exports.API_GRAPHS_ASSETS_URL = exports.API_GRAPHS_ASSETS_UPLOAD_URL = exports.API_GRAPHS_TARGETS_URL = exports.API_GRAPHS_TARGET_UPLOAD_URL = exports.API_GRAPHS_OBSERVATION_KEYS_URL = exports.API_GRAPHS_OBSERVATIONS_URL = exports.API_GRAPHS_PANORAMA_OBSERVATIONS_URL = exports.API_GRAPHS_PANORAMA = exports.API_GRAPHS_PANORAMAS_URL = exports.API_GRAPHS_MAPS_GEOJSON_URL = exports.API_GRAPHS_MAPS_DEPLOY_URL = exports.API_GRAPHS_MAPS_COPY_URL = exports.API_GRAPHS_MAP_METADATA_URL = exports.API_GRAPHS_MAP_CONTENT_URL = exports.API_GRAPHS_MAP_ID_URL = exports.API_GRAPHS_MAPS_MERGE_URL = exports.API_GRAPHS_MAPS_DEPLOYED_URL = exports.API_GRAPHS_MAPS_NEW_URL = exports.API_GRAPHS_MAPS_URL = exports.API_DD_INTEGRATION_LEVELS_URL = exports.API_DD_INTEGRATION_LOCATIONS_URL = exports.API_DD_INTEGRATION_ISSUES_URL = exports.API_DD_INTEGRATION_OVERLAYS_URL = exports.API_DD_INTEGRATION_PLAN_BY_ID_URL = exports.API_DD_INTEGRATION_PLANS_URL = exports.API_SPOTTY_URL = exports.API_PROJECT_SCHEDULES_URL = exports.API_SOURCE_ID_URL = exports.API_SOURCE_URL = exports.API_SOURCE_SCHEMA_URL = exports.API_TEMPLATE_EXPORTER_URL = exports.API_TEMPLATE_PROVISION_ID_URL = exports.API_TEMPLATE_PROVISION_URL = exports.API_TEMPLATE_DEPLOY_URL = exports.API_PROJECT_PROFILE_DASHBOARD_CUSTOM_WIDGET_URL = exports.API_PROJECT_PROFILE_DASHBOARD_ID_URL = exports.API_PROJECT_PROFILE_DASHBOARD_URL = exports.API_PROJECT_CALLSIGN_STREAM_URL = exports.API_PROJECT_ROBOT_DASHBOARD_CUSTOM_WIDGET_URL = exports.API_PROJECT_ROBOT_DASHBOARD_ID_URL = exports.API_PROJECT_ROBOT_DASHBOARD_URL = exports.API_PROJECT_STREAM_CALLSIGN_URL = void 0;
|
|
6
|
+
exports.API_PROJECT_ROBOT_TAG_URL = exports.API_PROJECT_PROFILE_TAG_URL = exports.API_PROJECT_PROFILE_TAGS_URL = exports.API_PROJECT_TAG_ROBOTS_URL = exports.API_PROJECT_ROBOT_TAGS_URL = exports.API_DEVICE_CREDENTIALS_AUTH_URL = exports.API_DEVICE_CREDENTIALS_URL = exports.API_LINKED_PROJECT_URL = exports.API_PROJECT_WORKFLOW_IMPORT_URL = exports.API_PROJECT_WORKFLOW_EXPORT_URL = exports.API_PROJECT_WORKFLOW_AFFECTED_URL = exports.API_PROJECT_ROBOT_DEPLOYED_WORKFLOW_URL = void 0;
|
|
7
7
|
exports.API_APPLICATION_AUTH_URL = 'https://{url}/applications/auth';
|
|
8
8
|
exports.API_ADMIN_USER_INVITATION_URL = 'https://{url}/admin/users/invitations';
|
|
9
9
|
exports.API_USER_URL = 'https://{url}/users';
|
|
@@ -137,6 +137,7 @@ exports.API_GRAPHS_MAP_METADATA_URL = 'https://{url}/graphs/projects/{projectId}
|
|
|
137
137
|
exports.API_GRAPHS_MAPS_COPY_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/copy';
|
|
138
138
|
exports.API_GRAPHS_MAPS_DEPLOY_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/deploy';
|
|
139
139
|
exports.API_GRAPHS_MAPS_GEOJSON_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/geojson';
|
|
140
|
+
exports.API_GRAPHS_PANORAMAS_URL = 'https://{url}/graphs/projects/{projectId}/panoramas';
|
|
140
141
|
exports.API_GRAPHS_PANORAMA = 'https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}';
|
|
141
142
|
exports.API_GRAPHS_PANORAMA_OBSERVATIONS_URL = 'https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}/observations';
|
|
142
143
|
exports.API_GRAPHS_OBSERVATIONS_URL = 'https://{url}/graphs/projects/{projectId}/observations';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RobotStatus, RobotStatusColour } from '../models/robot-status/RobotStatus';
|
|
2
|
+
/**
|
|
3
|
+
* Derives the canonical status-indicator colour from a robot's status, as a
|
|
4
|
+
* pure function of its health, readiness, and connectivity.
|
|
5
|
+
*
|
|
6
|
+
* Connectivity gates first — reported health is not trusted when connectivity is
|
|
7
|
+
* impaired — then health, then readiness:
|
|
8
|
+
*
|
|
9
|
+
* | Condition | Colour |
|
|
10
|
+
* | ---------------------------------------- | ------------------- |
|
|
11
|
+
* | connectivity `OFFLINE` | solid gray |
|
|
12
|
+
* | connectivity `DEGRADED` | flashing red/gray |
|
|
13
|
+
* | health `CRITICAL` | solid red |
|
|
14
|
+
* | health `ABNORMAL` | solid yellow |
|
|
15
|
+
* | health `UNKNOWN` | flashing green/gray |
|
|
16
|
+
* | health `NORMAL` + readiness `BUSY` | solid blue |
|
|
17
|
+
* | health `NORMAL` + readiness `IDLE`/unkn. | solid green |
|
|
18
|
+
*
|
|
19
|
+
* Legacy robots (heartbeat-only) report `NORMAL`/`IDLE`, so they resolve to
|
|
20
|
+
* solid green and never reach the flashing-green/gray "health unknown" case.
|
|
21
|
+
*
|
|
22
|
+
* This is the single source of truth for indicator colour; it is surfaced as
|
|
23
|
+
* `RobotStatusService.colourFor()`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const getRobotStatusColour: (status: Pick<RobotStatus, "health" | "readiness" | "connectivity">) => RobotStatusColour;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRobotStatusColour = void 0;
|
|
4
|
+
const RobotStatusEnums_1 = require("../models/robot-status/RobotStatusEnums");
|
|
5
|
+
const GRAY = { kind: 'solid', token: 'gray' };
|
|
6
|
+
const RED = { kind: 'solid', token: 'red' };
|
|
7
|
+
const YELLOW = { kind: 'solid', token: 'yellow' };
|
|
8
|
+
const BLUE = { kind: 'solid', token: 'blue' };
|
|
9
|
+
const GREEN = { kind: 'solid', token: 'green' };
|
|
10
|
+
const FLASHING_RED_GRAY = { kind: 'flashing', tokens: ['red', 'gray'] };
|
|
11
|
+
const FLASHING_GREEN_GRAY = { kind: 'flashing', tokens: ['green', 'gray'] };
|
|
12
|
+
/**
|
|
13
|
+
* Derives the canonical status-indicator colour from a robot's status, as a
|
|
14
|
+
* pure function of its health, readiness, and connectivity.
|
|
15
|
+
*
|
|
16
|
+
* Connectivity gates first — reported health is not trusted when connectivity is
|
|
17
|
+
* impaired — then health, then readiness:
|
|
18
|
+
*
|
|
19
|
+
* | Condition | Colour |
|
|
20
|
+
* | ---------------------------------------- | ------------------- |
|
|
21
|
+
* | connectivity `OFFLINE` | solid gray |
|
|
22
|
+
* | connectivity `DEGRADED` | flashing red/gray |
|
|
23
|
+
* | health `CRITICAL` | solid red |
|
|
24
|
+
* | health `ABNORMAL` | solid yellow |
|
|
25
|
+
* | health `UNKNOWN` | flashing green/gray |
|
|
26
|
+
* | health `NORMAL` + readiness `BUSY` | solid blue |
|
|
27
|
+
* | health `NORMAL` + readiness `IDLE`/unkn. | solid green |
|
|
28
|
+
*
|
|
29
|
+
* Legacy robots (heartbeat-only) report `NORMAL`/`IDLE`, so they resolve to
|
|
30
|
+
* solid green and never reach the flashing-green/gray "health unknown" case.
|
|
31
|
+
*
|
|
32
|
+
* This is the single source of truth for indicator colour; it is surfaced as
|
|
33
|
+
* `RobotStatusService.colourFor()`.
|
|
34
|
+
*/
|
|
35
|
+
const getRobotStatusColour = (status) => {
|
|
36
|
+
const { health, readiness, connectivity } = status;
|
|
37
|
+
if (connectivity.overall === RobotStatusEnums_1.RobotConnectivity.OFFLINE)
|
|
38
|
+
return GRAY;
|
|
39
|
+
if (connectivity.overall === RobotStatusEnums_1.RobotConnectivity.DEGRADED)
|
|
40
|
+
return FLASHING_RED_GRAY;
|
|
41
|
+
// Connectivity is ONLINE: derive from reported health, then readiness.
|
|
42
|
+
switch (health) {
|
|
43
|
+
case RobotStatusEnums_1.RobotHealth.CRITICAL:
|
|
44
|
+
return RED;
|
|
45
|
+
case RobotStatusEnums_1.RobotHealth.ABNORMAL:
|
|
46
|
+
return YELLOW;
|
|
47
|
+
case RobotStatusEnums_1.RobotHealth.UNKNOWN:
|
|
48
|
+
return FLASHING_GREEN_GRAY;
|
|
49
|
+
case RobotStatusEnums_1.RobotHealth.NORMAL:
|
|
50
|
+
default:
|
|
51
|
+
return readiness === RobotStatusEnums_1.RobotReadiness.BUSY ? BLUE : GREEN;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.getRobotStatusColour = getRobotStatusColour;
|
package/cjs/helpers/index.d.ts
CHANGED
package/cjs/helpers/index.js
CHANGED
|
@@ -21,3 +21,4 @@ __exportStar(require("./getURLSearchParams"), exports);
|
|
|
21
21
|
__exportStar(require("./websandbox"), exports);
|
|
22
22
|
__exportStar(require("./kscript"), exports);
|
|
23
23
|
__exportStar(require("./splitRobotTopic"), exports);
|
|
24
|
+
__exportStar(require("./getRobotStatusColour"), exports);
|
package/cjs/models/index.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ export * from './Robot';
|
|
|
65
65
|
export * from './RobotConfig';
|
|
66
66
|
export * from './RobotPlugin';
|
|
67
67
|
export * from './RobotProfile';
|
|
68
|
+
export * from './robot-status/RobotStatus';
|
|
69
|
+
export * from './robot-status/RobotStatusEnums';
|
|
68
70
|
export * from './RobotTemplate';
|
|
69
71
|
export * from './RocosError';
|
|
70
72
|
export * from './schedule/IScheduleAction';
|
package/cjs/models/index.js
CHANGED
|
@@ -81,6 +81,8 @@ __exportStar(require("./Robot"), exports);
|
|
|
81
81
|
__exportStar(require("./RobotConfig"), exports);
|
|
82
82
|
__exportStar(require("./RobotPlugin"), exports);
|
|
83
83
|
__exportStar(require("./RobotProfile"), exports);
|
|
84
|
+
__exportStar(require("./robot-status/RobotStatus"), exports);
|
|
85
|
+
__exportStar(require("./robot-status/RobotStatusEnums"), exports);
|
|
84
86
|
__exportStar(require("./RobotTemplate"), exports);
|
|
85
87
|
__exportStar(require("./RocosError"), exports);
|
|
86
88
|
__exportStar(require("./schedule/IScheduleAction"), exports);
|
|
@@ -24,4 +24,22 @@ export interface Panorama {
|
|
|
24
24
|
path: string;
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Body for `PUT /graphs/projects/{projectId}/panoramas`. Same shape as {@link Panorama}, with
|
|
29
|
+
* an optional `map` field that accepts either a single map id or an array of map ids.
|
|
30
|
+
*
|
|
31
|
+
* - The dronedeploy map is always written; values in `map` are added on top of it
|
|
32
|
+
* (deduped). Each named map must already exist server-side; a typo is rejected with 400.
|
|
33
|
+
* - `transform.id` may be left blank ('') to have the server generate a UUID; the returned
|
|
34
|
+
* {@link AddPanoramaResponse.id} echoes whichever value the panorama was created under.
|
|
35
|
+
* - `transform.parent` is created as a FRAME node when it doesn't already exist anywhere
|
|
36
|
+
* in the project, so callers don't need to bootstrap the parent before posting.
|
|
37
|
+
*/
|
|
38
|
+
export interface AddPanoramaRequest extends Panorama {
|
|
39
|
+
map?: string | string[];
|
|
40
|
+
}
|
|
41
|
+
export interface AddPanoramaResponse {
|
|
42
|
+
/** Panorama node id — either the value the caller supplied, or the UUID the server generated. */
|
|
43
|
+
id: string;
|
|
44
|
+
}
|
|
27
45
|
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { RobotConnectivity, RobotHealth, RobotReadiness, ServiceConnection } from './RobotStatusEnums';
|
|
2
|
+
/** The semantic colour tokens a status indicator can use. */
|
|
3
|
+
export type RobotStatusColourToken = 'gray' | 'green' | 'blue' | 'yellow' | 'red';
|
|
4
|
+
/**
|
|
5
|
+
* The canonical colour a status indicator should display, as a semantic token
|
|
6
|
+
* rather than a concrete colour — each consumer maps the token to its own theme.
|
|
7
|
+
*
|
|
8
|
+
* "Flashing" is structural rather than a single value: a degraded robot flashes
|
|
9
|
+
* red/gray, while an online robot whose health is explicitly unknown flashes
|
|
10
|
+
* green/gray.
|
|
11
|
+
*/
|
|
12
|
+
export type RobotStatusColour = {
|
|
13
|
+
kind: 'solid';
|
|
14
|
+
token: RobotStatusColourToken;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'flashing';
|
|
17
|
+
tokens: ['red', 'gray'];
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'flashing';
|
|
20
|
+
tokens: ['green', 'gray'];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The robot's connectivity to the cloud platform: an aggregate verdict plus the
|
|
24
|
+
* per-service breakdown it was derived from. Only the *expected* services for a
|
|
25
|
+
* given robot are present in `services`.
|
|
26
|
+
*/
|
|
27
|
+
export interface RobotConnectivityStatus {
|
|
28
|
+
overall: RobotConnectivity;
|
|
29
|
+
/** Keyed by service id (e.g. `robot-configs`, `robot-services`, `telemetry-liveness`). */
|
|
30
|
+
services: Record<string, ServiceConnection>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The combined, canonical status of a robot: what the robot reports about itself
|
|
34
|
+
* (health + readiness), its connectivity, and the resulting indicator colour.
|
|
35
|
+
*
|
|
36
|
+
* This is the object emitted by `RobotStatusService.getRobotStatusChanges()`.
|
|
37
|
+
*/
|
|
38
|
+
export interface RobotStatus {
|
|
39
|
+
health: RobotHealth;
|
|
40
|
+
readiness: RobotReadiness;
|
|
41
|
+
connectivity: RobotConnectivityStatus;
|
|
42
|
+
colour: RobotStatusColour;
|
|
43
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The health of a robot, as reported by the agent's `robot/status` topic.
|
|
3
|
+
*
|
|
4
|
+
* The string values are the SDK-facing representation; the agent encodes these
|
|
5
|
+
* as integers on the wire (shown below). The {@link RobotStatusService} maps
|
|
6
|
+
* the integer wire values onto these enums on receipt.
|
|
7
|
+
*/
|
|
8
|
+
export declare enum RobotHealth {
|
|
9
|
+
/** `0` on the wire. Health has not been determined. */
|
|
10
|
+
UNKNOWN = "unknown",
|
|
11
|
+
/** `1` on the wire. The robot is healthy. */
|
|
12
|
+
NORMAL = "normal",
|
|
13
|
+
/** `2` on the wire. Something needs attention, but the robot is still functional. */
|
|
14
|
+
ABNORMAL = "abnormal",
|
|
15
|
+
/** `3` on the wire. The robot requires immediate attention. */
|
|
16
|
+
CRITICAL = "critical"
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The readiness of a robot — whether it is available to take on work — as
|
|
20
|
+
* reported by the agent's `robot/status` topic.
|
|
21
|
+
*
|
|
22
|
+
* As with {@link RobotHealth}, the agent encodes these as integers on the wire.
|
|
23
|
+
*/
|
|
24
|
+
export declare enum RobotReadiness {
|
|
25
|
+
/** `0` on the wire. Readiness has not been determined. */
|
|
26
|
+
UNKNOWN = "unknown",
|
|
27
|
+
/** `1` on the wire. The robot is available. */
|
|
28
|
+
IDLE = "idle",
|
|
29
|
+
/** `2` on the wire. The robot is occupied and should not be interrupted. */
|
|
30
|
+
BUSY = "busy"
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Whether the robot is connected to a single cloud service, as reported by that
|
|
34
|
+
* service's `connections` endpoint (or, for `telemetry-liveness`, derived from
|
|
35
|
+
* heartbeat freshness).
|
|
36
|
+
*/
|
|
37
|
+
export declare enum ServiceConnection {
|
|
38
|
+
CONNECTED = "connected",
|
|
39
|
+
DISCONNECTED = "disconnected",
|
|
40
|
+
/** The service's connectivity has not yet been determined (e.g. not polled). */
|
|
41
|
+
UNKNOWN = "unknown"
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The robot's overall connectivity to the cloud platform, aggregated across all
|
|
45
|
+
* expected services.
|
|
46
|
+
*/
|
|
47
|
+
export declare enum RobotConnectivity {
|
|
48
|
+
/** Every expected service reports connected. */
|
|
49
|
+
ONLINE = "online",
|
|
50
|
+
/** Some, but not all, expected services report connected. */
|
|
51
|
+
DEGRADED = "degraded",
|
|
52
|
+
/** No expected service reports connected. */
|
|
53
|
+
OFFLINE = "offline"
|
|
54
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RobotConnectivity = exports.ServiceConnection = exports.RobotReadiness = exports.RobotHealth = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The health of a robot, as reported by the agent's `robot/status` topic.
|
|
6
|
+
*
|
|
7
|
+
* The string values are the SDK-facing representation; the agent encodes these
|
|
8
|
+
* as integers on the wire (shown below). The {@link RobotStatusService} maps
|
|
9
|
+
* the integer wire values onto these enums on receipt.
|
|
10
|
+
*/
|
|
11
|
+
var RobotHealth;
|
|
12
|
+
(function (RobotHealth) {
|
|
13
|
+
/** `0` on the wire. Health has not been determined. */
|
|
14
|
+
RobotHealth["UNKNOWN"] = "unknown";
|
|
15
|
+
/** `1` on the wire. The robot is healthy. */
|
|
16
|
+
RobotHealth["NORMAL"] = "normal";
|
|
17
|
+
/** `2` on the wire. Something needs attention, but the robot is still functional. */
|
|
18
|
+
RobotHealth["ABNORMAL"] = "abnormal";
|
|
19
|
+
/** `3` on the wire. The robot requires immediate attention. */
|
|
20
|
+
RobotHealth["CRITICAL"] = "critical";
|
|
21
|
+
})(RobotHealth || (exports.RobotHealth = RobotHealth = {}));
|
|
22
|
+
/**
|
|
23
|
+
* The readiness of a robot — whether it is available to take on work — as
|
|
24
|
+
* reported by the agent's `robot/status` topic.
|
|
25
|
+
*
|
|
26
|
+
* As with {@link RobotHealth}, the agent encodes these as integers on the wire.
|
|
27
|
+
*/
|
|
28
|
+
var RobotReadiness;
|
|
29
|
+
(function (RobotReadiness) {
|
|
30
|
+
/** `0` on the wire. Readiness has not been determined. */
|
|
31
|
+
RobotReadiness["UNKNOWN"] = "unknown";
|
|
32
|
+
/** `1` on the wire. The robot is available. */
|
|
33
|
+
RobotReadiness["IDLE"] = "idle";
|
|
34
|
+
/** `2` on the wire. The robot is occupied and should not be interrupted. */
|
|
35
|
+
RobotReadiness["BUSY"] = "busy";
|
|
36
|
+
})(RobotReadiness || (exports.RobotReadiness = RobotReadiness = {}));
|
|
37
|
+
/**
|
|
38
|
+
* Whether the robot is connected to a single cloud service, as reported by that
|
|
39
|
+
* service's `connections` endpoint (or, for `telemetry-liveness`, derived from
|
|
40
|
+
* heartbeat freshness).
|
|
41
|
+
*/
|
|
42
|
+
var ServiceConnection;
|
|
43
|
+
(function (ServiceConnection) {
|
|
44
|
+
ServiceConnection["CONNECTED"] = "connected";
|
|
45
|
+
ServiceConnection["DISCONNECTED"] = "disconnected";
|
|
46
|
+
/** The service's connectivity has not yet been determined (e.g. not polled). */
|
|
47
|
+
ServiceConnection["UNKNOWN"] = "unknown";
|
|
48
|
+
})(ServiceConnection || (exports.ServiceConnection = ServiceConnection = {}));
|
|
49
|
+
/**
|
|
50
|
+
* The robot's overall connectivity to the cloud platform, aggregated across all
|
|
51
|
+
* expected services.
|
|
52
|
+
*/
|
|
53
|
+
var RobotConnectivity;
|
|
54
|
+
(function (RobotConnectivity) {
|
|
55
|
+
/** Every expected service reports connected. */
|
|
56
|
+
RobotConnectivity["ONLINE"] = "online";
|
|
57
|
+
/** Some, but not all, expected services report connected. */
|
|
58
|
+
RobotConnectivity["DEGRADED"] = "degraded";
|
|
59
|
+
/** No expected service reports connected. */
|
|
60
|
+
RobotConnectivity["OFFLINE"] = "offline";
|
|
61
|
+
})(RobotConnectivity || (exports.RobotConnectivity = RobotConnectivity = {}));
|
|
@@ -43,6 +43,44 @@ export declare class CallerService extends BaseStreamService<ICallerStream> {
|
|
|
43
43
|
ack$: Observable<IRocosCallerMessageResponseAck>;
|
|
44
44
|
cancel: () => Promise<void>;
|
|
45
45
|
};
|
|
46
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
47
|
+
*
|
|
48
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
49
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
50
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
51
|
+
* and tear it down only when the action itself completes/errors.
|
|
52
|
+
*
|
|
53
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
54
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
55
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
56
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
57
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
58
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
59
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
60
|
+
* still receives it.
|
|
61
|
+
*
|
|
62
|
+
* Lifecycle:
|
|
63
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
64
|
+
* errors (or completes) before any ack arrives.
|
|
65
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
66
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
67
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
68
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
69
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
70
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
71
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
72
|
+
* where the action should keep running but the result is no longer needed.
|
|
73
|
+
*
|
|
74
|
+
* @see call
|
|
75
|
+
* @see callRaw
|
|
76
|
+
*/
|
|
77
|
+
callAction<T = unknown>(params: ICallerCallParams): {
|
|
78
|
+
ack: Promise<IRocosCallerMessageResponseAck>;
|
|
79
|
+
result$: Observable<IRocosCallerMessageResponseResult>;
|
|
80
|
+
return$: Observable<T>;
|
|
81
|
+
cancel: () => Promise<void>;
|
|
82
|
+
close: () => void;
|
|
83
|
+
};
|
|
46
84
|
protected createStream(): Promise<ICallerStream>;
|
|
47
85
|
protected getStream(config: IStreamConfig): ICallerStream;
|
|
48
86
|
}
|
|
@@ -104,6 +104,62 @@ class CallerService extends BaseStreamService_1.BaseStreamService {
|
|
|
104
104
|
cancel,
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
108
|
+
*
|
|
109
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
110
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
111
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
112
|
+
* and tear it down only when the action itself completes/errors.
|
|
113
|
+
*
|
|
114
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
115
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
116
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
117
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
118
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
119
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
120
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
121
|
+
* still receives it.
|
|
122
|
+
*
|
|
123
|
+
* Lifecycle:
|
|
124
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
125
|
+
* errors (or completes) before any ack arrives.
|
|
126
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
127
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
128
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
129
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
130
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
131
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
132
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
133
|
+
* where the action should keep running but the result is no longer needed.
|
|
134
|
+
*
|
|
135
|
+
* @see call
|
|
136
|
+
* @see callRaw
|
|
137
|
+
*/
|
|
138
|
+
callAction(params) {
|
|
139
|
+
const stream = this.call(params);
|
|
140
|
+
// Replay the one-shot result so subscription order never matters and a late
|
|
141
|
+
// subscriber still receives it.
|
|
142
|
+
const result = new rxjs_1.ReplaySubject(1);
|
|
143
|
+
// One SDK-owned subscription pins the shared source alive for the whole action.
|
|
144
|
+
// It fires the request once (first subscriber) and forwards the result into the
|
|
145
|
+
// replay subject, completing/erroring it when the action ends. Because this
|
|
146
|
+
// subscription outlives any `firstValueFrom(ack)` teardown, subscriber churn can
|
|
147
|
+
// never reset the source and re-issue the goal.
|
|
148
|
+
const pin = stream.result$.subscribe(result);
|
|
149
|
+
// `ack` rejects if the action errors or completes before any ack arrives. Since
|
|
150
|
+
// callAction is meant to be consumed via result$/return$ too, a caller may never
|
|
151
|
+
// touch `ack` — without a handler that rejection would surface as an unhandled
|
|
152
|
+
// promise rejection. Awaiting `action.ack` still rejects for callers who do care.
|
|
153
|
+
const ack = (0, rxjs_1.firstValueFrom)(stream.ack$);
|
|
154
|
+
ack.catch(() => { });
|
|
155
|
+
return {
|
|
156
|
+
ack,
|
|
157
|
+
result$: result.asObservable(),
|
|
158
|
+
return$: stream.return$,
|
|
159
|
+
cancel: stream.cancel,
|
|
160
|
+
close: () => pin.unsubscribe(),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
107
163
|
async createStream() {
|
|
108
164
|
return (await this.createStreamFromConfig(identifier_1.IDENTIFIER_NAME_CALLER, {
|
|
109
165
|
url: this.config.url,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { AddPanoramaRequest, AddPanoramaResponse, CreateObservation, Observation } from '../models/maps/Panorama';
|
|
1
2
|
import { Asset, IBaseService, IRocosSDKConfig, Map, MapContent, RocosError } from '../models';
|
|
2
|
-
import { CreateObservation, Observation } from '../models/maps/Panorama';
|
|
3
3
|
import { BaseServiceAbstract } from './BaseServiceAbstract';
|
|
4
4
|
/**
|
|
5
5
|
* Maps service for managing robot maps in the cloud and on robots
|
|
@@ -202,6 +202,25 @@ export declare class MapService extends BaseServiceAbstract implements IBaseServ
|
|
|
202
202
|
* @returns A list of assets
|
|
203
203
|
*/
|
|
204
204
|
getAssetsKeys(projectId: string): Promise<string[]>;
|
|
205
|
+
/**
|
|
206
|
+
* Adds a panorama to the project's dronedeploy map (and optionally other named maps).
|
|
207
|
+
*
|
|
208
|
+
* The dronedeploy map is always written. To also write the panorama into additional maps,
|
|
209
|
+
* pass their ids in `body.map` (single string or array). Each named map must already exist —
|
|
210
|
+
* unknown ids reject the whole call with 400. Entries are deduplicated against dronedeploy
|
|
211
|
+
* and each other.
|
|
212
|
+
*
|
|
213
|
+
* Two server-side conveniences:
|
|
214
|
+
* - `body.transform.id` may be left blank ('') to have the server generate a UUID. The
|
|
215
|
+
* created id is returned in the response so the caller can subsequently get/delete it.
|
|
216
|
+
* - `body.transform.parent` is auto-created as a FRAME node when it doesn't already exist
|
|
217
|
+
* anywhere in the project; no separate "create parent frame" call is required.
|
|
218
|
+
*
|
|
219
|
+
* @param projectId The ID of the project the panorama belongs to.
|
|
220
|
+
* @param body Panorama transform + data, with an optional `map` selector.
|
|
221
|
+
* @returns The panorama node id that was created (echoed when supplied, generated when blank).
|
|
222
|
+
*/
|
|
223
|
+
addPanorama(projectId: string, body: AddPanoramaRequest): Promise<AddPanoramaResponse>;
|
|
205
224
|
/**
|
|
206
225
|
* Deletes a panorama by panoramaID.
|
|
207
226
|
*
|
|
@@ -282,6 +282,27 @@ class MapService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
282
282
|
getAssetsKeys(projectId) {
|
|
283
283
|
return this.callGet((0, formatServiceUrl_1.formatServiceUrl)(api_1.API_GRAPHS_OBSERVATION_KEYS_URL, { url: this.config.url, projectId }, this.config.insecure), 'Failed to get asset keys.');
|
|
284
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Adds a panorama to the project's dronedeploy map (and optionally other named maps).
|
|
287
|
+
*
|
|
288
|
+
* The dronedeploy map is always written. To also write the panorama into additional maps,
|
|
289
|
+
* pass their ids in `body.map` (single string or array). Each named map must already exist —
|
|
290
|
+
* unknown ids reject the whole call with 400. Entries are deduplicated against dronedeploy
|
|
291
|
+
* and each other.
|
|
292
|
+
*
|
|
293
|
+
* Two server-side conveniences:
|
|
294
|
+
* - `body.transform.id` may be left blank ('') to have the server generate a UUID. The
|
|
295
|
+
* created id is returned in the response so the caller can subsequently get/delete it.
|
|
296
|
+
* - `body.transform.parent` is auto-created as a FRAME node when it doesn't already exist
|
|
297
|
+
* anywhere in the project; no separate "create parent frame" call is required.
|
|
298
|
+
*
|
|
299
|
+
* @param projectId The ID of the project the panorama belongs to.
|
|
300
|
+
* @param body Panorama transform + data, with an optional `map` selector.
|
|
301
|
+
* @returns The panorama node id that was created (echoed when supplied, generated when blank).
|
|
302
|
+
*/
|
|
303
|
+
addPanorama(projectId, body) {
|
|
304
|
+
return this.callPut((0, formatServiceUrl_1.formatServiceUrl)(api_1.API_GRAPHS_PANORAMAS_URL, { url: this.config.url, projectId }, this.config.insecure), body, 'Failed to add panorama.');
|
|
305
|
+
}
|
|
285
306
|
/**
|
|
286
307
|
* Deletes a panorama by panoramaID.
|
|
287
308
|
*
|
package/esm/constants/api.d.ts
CHANGED
|
@@ -131,6 +131,7 @@ export declare const API_GRAPHS_MAP_METADATA_URL = "https://{url}/graphs/project
|
|
|
131
131
|
export declare const API_GRAPHS_MAPS_COPY_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/copy";
|
|
132
132
|
export declare const API_GRAPHS_MAPS_DEPLOY_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/deploy";
|
|
133
133
|
export declare const API_GRAPHS_MAPS_GEOJSON_URL = "https://{url}/graphs/projects/{projectId}/maps/{mapId}/geojson";
|
|
134
|
+
export declare const API_GRAPHS_PANORAMAS_URL = "https://{url}/graphs/projects/{projectId}/panoramas";
|
|
134
135
|
export declare const API_GRAPHS_PANORAMA = "https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}";
|
|
135
136
|
export declare const API_GRAPHS_PANORAMA_OBSERVATIONS_URL = "https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}/observations";
|
|
136
137
|
export declare const API_GRAPHS_OBSERVATIONS_URL = "https://{url}/graphs/projects/{projectId}/observations";
|
package/esm/constants/api.js
CHANGED
|
@@ -131,6 +131,7 @@ export const API_GRAPHS_MAP_METADATA_URL = 'https://{url}/graphs/projects/{proje
|
|
|
131
131
|
export const API_GRAPHS_MAPS_COPY_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/copy';
|
|
132
132
|
export const API_GRAPHS_MAPS_DEPLOY_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/deploy';
|
|
133
133
|
export const API_GRAPHS_MAPS_GEOJSON_URL = 'https://{url}/graphs/projects/{projectId}/maps/{mapId}/geojson';
|
|
134
|
+
export const API_GRAPHS_PANORAMAS_URL = 'https://{url}/graphs/projects/{projectId}/panoramas';
|
|
134
135
|
export const API_GRAPHS_PANORAMA = 'https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}';
|
|
135
136
|
export const API_GRAPHS_PANORAMA_OBSERVATIONS_URL = 'https://{url}/graphs/projects/{projectId}/panoramas/{panoramaId}/observations';
|
|
136
137
|
export const API_GRAPHS_OBSERVATIONS_URL = 'https://{url}/graphs/projects/{projectId}/observations';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RobotStatus, RobotStatusColour } from '../models/robot-status/RobotStatus';
|
|
2
|
+
/**
|
|
3
|
+
* Derives the canonical status-indicator colour from a robot's status, as a
|
|
4
|
+
* pure function of its health, readiness, and connectivity.
|
|
5
|
+
*
|
|
6
|
+
* Connectivity gates first — reported health is not trusted when connectivity is
|
|
7
|
+
* impaired — then health, then readiness:
|
|
8
|
+
*
|
|
9
|
+
* | Condition | Colour |
|
|
10
|
+
* | ---------------------------------------- | ------------------- |
|
|
11
|
+
* | connectivity `OFFLINE` | solid gray |
|
|
12
|
+
* | connectivity `DEGRADED` | flashing red/gray |
|
|
13
|
+
* | health `CRITICAL` | solid red |
|
|
14
|
+
* | health `ABNORMAL` | solid yellow |
|
|
15
|
+
* | health `UNKNOWN` | flashing green/gray |
|
|
16
|
+
* | health `NORMAL` + readiness `BUSY` | solid blue |
|
|
17
|
+
* | health `NORMAL` + readiness `IDLE`/unkn. | solid green |
|
|
18
|
+
*
|
|
19
|
+
* Legacy robots (heartbeat-only) report `NORMAL`/`IDLE`, so they resolve to
|
|
20
|
+
* solid green and never reach the flashing-green/gray "health unknown" case.
|
|
21
|
+
*
|
|
22
|
+
* This is the single source of truth for indicator colour; it is surfaced as
|
|
23
|
+
* `RobotStatusService.colourFor()`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const getRobotStatusColour: (status: Pick<RobotStatus, "health" | "readiness" | "connectivity">) => RobotStatusColour;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { RobotConnectivity, RobotHealth, RobotReadiness } from '../models/robot-status/RobotStatusEnums';
|
|
2
|
+
const GRAY = { kind: 'solid', token: 'gray' };
|
|
3
|
+
const RED = { kind: 'solid', token: 'red' };
|
|
4
|
+
const YELLOW = { kind: 'solid', token: 'yellow' };
|
|
5
|
+
const BLUE = { kind: 'solid', token: 'blue' };
|
|
6
|
+
const GREEN = { kind: 'solid', token: 'green' };
|
|
7
|
+
const FLASHING_RED_GRAY = { kind: 'flashing', tokens: ['red', 'gray'] };
|
|
8
|
+
const FLASHING_GREEN_GRAY = { kind: 'flashing', tokens: ['green', 'gray'] };
|
|
9
|
+
/**
|
|
10
|
+
* Derives the canonical status-indicator colour from a robot's status, as a
|
|
11
|
+
* pure function of its health, readiness, and connectivity.
|
|
12
|
+
*
|
|
13
|
+
* Connectivity gates first — reported health is not trusted when connectivity is
|
|
14
|
+
* impaired — then health, then readiness:
|
|
15
|
+
*
|
|
16
|
+
* | Condition | Colour |
|
|
17
|
+
* | ---------------------------------------- | ------------------- |
|
|
18
|
+
* | connectivity `OFFLINE` | solid gray |
|
|
19
|
+
* | connectivity `DEGRADED` | flashing red/gray |
|
|
20
|
+
* | health `CRITICAL` | solid red |
|
|
21
|
+
* | health `ABNORMAL` | solid yellow |
|
|
22
|
+
* | health `UNKNOWN` | flashing green/gray |
|
|
23
|
+
* | health `NORMAL` + readiness `BUSY` | solid blue |
|
|
24
|
+
* | health `NORMAL` + readiness `IDLE`/unkn. | solid green |
|
|
25
|
+
*
|
|
26
|
+
* Legacy robots (heartbeat-only) report `NORMAL`/`IDLE`, so they resolve to
|
|
27
|
+
* solid green and never reach the flashing-green/gray "health unknown" case.
|
|
28
|
+
*
|
|
29
|
+
* This is the single source of truth for indicator colour; it is surfaced as
|
|
30
|
+
* `RobotStatusService.colourFor()`.
|
|
31
|
+
*/
|
|
32
|
+
export const getRobotStatusColour = (status) => {
|
|
33
|
+
const { health, readiness, connectivity } = status;
|
|
34
|
+
if (connectivity.overall === RobotConnectivity.OFFLINE)
|
|
35
|
+
return GRAY;
|
|
36
|
+
if (connectivity.overall === RobotConnectivity.DEGRADED)
|
|
37
|
+
return FLASHING_RED_GRAY;
|
|
38
|
+
// Connectivity is ONLINE: derive from reported health, then readiness.
|
|
39
|
+
switch (health) {
|
|
40
|
+
case RobotHealth.CRITICAL:
|
|
41
|
+
return RED;
|
|
42
|
+
case RobotHealth.ABNORMAL:
|
|
43
|
+
return YELLOW;
|
|
44
|
+
case RobotHealth.UNKNOWN:
|
|
45
|
+
return FLASHING_GREEN_GRAY;
|
|
46
|
+
case RobotHealth.NORMAL:
|
|
47
|
+
default:
|
|
48
|
+
return readiness === RobotReadiness.BUSY ? BLUE : GREEN;
|
|
49
|
+
}
|
|
50
|
+
};
|
package/esm/helpers/index.d.ts
CHANGED
package/esm/helpers/index.js
CHANGED
package/esm/models/index.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ export * from './Robot';
|
|
|
65
65
|
export * from './RobotConfig';
|
|
66
66
|
export * from './RobotPlugin';
|
|
67
67
|
export * from './RobotProfile';
|
|
68
|
+
export * from './robot-status/RobotStatus';
|
|
69
|
+
export * from './robot-status/RobotStatusEnums';
|
|
68
70
|
export * from './RobotTemplate';
|
|
69
71
|
export * from './RocosError';
|
|
70
72
|
export * from './schedule/IScheduleAction';
|
package/esm/models/index.js
CHANGED
|
@@ -65,6 +65,8 @@ export * from './Robot';
|
|
|
65
65
|
export * from './RobotConfig';
|
|
66
66
|
export * from './RobotPlugin';
|
|
67
67
|
export * from './RobotProfile';
|
|
68
|
+
export * from './robot-status/RobotStatus';
|
|
69
|
+
export * from './robot-status/RobotStatusEnums';
|
|
68
70
|
export * from './RobotTemplate';
|
|
69
71
|
export * from './RocosError';
|
|
70
72
|
export * from './schedule/IScheduleAction';
|
|
@@ -24,4 +24,22 @@ export interface Panorama {
|
|
|
24
24
|
path: string;
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Body for `PUT /graphs/projects/{projectId}/panoramas`. Same shape as {@link Panorama}, with
|
|
29
|
+
* an optional `map` field that accepts either a single map id or an array of map ids.
|
|
30
|
+
*
|
|
31
|
+
* - The dronedeploy map is always written; values in `map` are added on top of it
|
|
32
|
+
* (deduped). Each named map must already exist server-side; a typo is rejected with 400.
|
|
33
|
+
* - `transform.id` may be left blank ('') to have the server generate a UUID; the returned
|
|
34
|
+
* {@link AddPanoramaResponse.id} echoes whichever value the panorama was created under.
|
|
35
|
+
* - `transform.parent` is created as a FRAME node when it doesn't already exist anywhere
|
|
36
|
+
* in the project, so callers don't need to bootstrap the parent before posting.
|
|
37
|
+
*/
|
|
38
|
+
export interface AddPanoramaRequest extends Panorama {
|
|
39
|
+
map?: string | string[];
|
|
40
|
+
}
|
|
41
|
+
export interface AddPanoramaResponse {
|
|
42
|
+
/** Panorama node id — either the value the caller supplied, or the UUID the server generated. */
|
|
43
|
+
id: string;
|
|
44
|
+
}
|
|
27
45
|
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { RobotConnectivity, RobotHealth, RobotReadiness, ServiceConnection } from './RobotStatusEnums';
|
|
2
|
+
/** The semantic colour tokens a status indicator can use. */
|
|
3
|
+
export type RobotStatusColourToken = 'gray' | 'green' | 'blue' | 'yellow' | 'red';
|
|
4
|
+
/**
|
|
5
|
+
* The canonical colour a status indicator should display, as a semantic token
|
|
6
|
+
* rather than a concrete colour — each consumer maps the token to its own theme.
|
|
7
|
+
*
|
|
8
|
+
* "Flashing" is structural rather than a single value: a degraded robot flashes
|
|
9
|
+
* red/gray, while an online robot whose health is explicitly unknown flashes
|
|
10
|
+
* green/gray.
|
|
11
|
+
*/
|
|
12
|
+
export type RobotStatusColour = {
|
|
13
|
+
kind: 'solid';
|
|
14
|
+
token: RobotStatusColourToken;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'flashing';
|
|
17
|
+
tokens: ['red', 'gray'];
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'flashing';
|
|
20
|
+
tokens: ['green', 'gray'];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The robot's connectivity to the cloud platform: an aggregate verdict plus the
|
|
24
|
+
* per-service breakdown it was derived from. Only the *expected* services for a
|
|
25
|
+
* given robot are present in `services`.
|
|
26
|
+
*/
|
|
27
|
+
export interface RobotConnectivityStatus {
|
|
28
|
+
overall: RobotConnectivity;
|
|
29
|
+
/** Keyed by service id (e.g. `robot-configs`, `robot-services`, `telemetry-liveness`). */
|
|
30
|
+
services: Record<string, ServiceConnection>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The combined, canonical status of a robot: what the robot reports about itself
|
|
34
|
+
* (health + readiness), its connectivity, and the resulting indicator colour.
|
|
35
|
+
*
|
|
36
|
+
* This is the object emitted by `RobotStatusService.getRobotStatusChanges()`.
|
|
37
|
+
*/
|
|
38
|
+
export interface RobotStatus {
|
|
39
|
+
health: RobotHealth;
|
|
40
|
+
readiness: RobotReadiness;
|
|
41
|
+
connectivity: RobotConnectivityStatus;
|
|
42
|
+
colour: RobotStatusColour;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The health of a robot, as reported by the agent's `robot/status` topic.
|
|
3
|
+
*
|
|
4
|
+
* The string values are the SDK-facing representation; the agent encodes these
|
|
5
|
+
* as integers on the wire (shown below). The {@link RobotStatusService} maps
|
|
6
|
+
* the integer wire values onto these enums on receipt.
|
|
7
|
+
*/
|
|
8
|
+
export declare enum RobotHealth {
|
|
9
|
+
/** `0` on the wire. Health has not been determined. */
|
|
10
|
+
UNKNOWN = "unknown",
|
|
11
|
+
/** `1` on the wire. The robot is healthy. */
|
|
12
|
+
NORMAL = "normal",
|
|
13
|
+
/** `2` on the wire. Something needs attention, but the robot is still functional. */
|
|
14
|
+
ABNORMAL = "abnormal",
|
|
15
|
+
/** `3` on the wire. The robot requires immediate attention. */
|
|
16
|
+
CRITICAL = "critical"
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The readiness of a robot — whether it is available to take on work — as
|
|
20
|
+
* reported by the agent's `robot/status` topic.
|
|
21
|
+
*
|
|
22
|
+
* As with {@link RobotHealth}, the agent encodes these as integers on the wire.
|
|
23
|
+
*/
|
|
24
|
+
export declare enum RobotReadiness {
|
|
25
|
+
/** `0` on the wire. Readiness has not been determined. */
|
|
26
|
+
UNKNOWN = "unknown",
|
|
27
|
+
/** `1` on the wire. The robot is available. */
|
|
28
|
+
IDLE = "idle",
|
|
29
|
+
/** `2` on the wire. The robot is occupied and should not be interrupted. */
|
|
30
|
+
BUSY = "busy"
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Whether the robot is connected to a single cloud service, as reported by that
|
|
34
|
+
* service's `connections` endpoint (or, for `telemetry-liveness`, derived from
|
|
35
|
+
* heartbeat freshness).
|
|
36
|
+
*/
|
|
37
|
+
export declare enum ServiceConnection {
|
|
38
|
+
CONNECTED = "connected",
|
|
39
|
+
DISCONNECTED = "disconnected",
|
|
40
|
+
/** The service's connectivity has not yet been determined (e.g. not polled). */
|
|
41
|
+
UNKNOWN = "unknown"
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The robot's overall connectivity to the cloud platform, aggregated across all
|
|
45
|
+
* expected services.
|
|
46
|
+
*/
|
|
47
|
+
export declare enum RobotConnectivity {
|
|
48
|
+
/** Every expected service reports connected. */
|
|
49
|
+
ONLINE = "online",
|
|
50
|
+
/** Some, but not all, expected services report connected. */
|
|
51
|
+
DEGRADED = "degraded",
|
|
52
|
+
/** No expected service reports connected. */
|
|
53
|
+
OFFLINE = "offline"
|
|
54
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The health of a robot, as reported by the agent's `robot/status` topic.
|
|
3
|
+
*
|
|
4
|
+
* The string values are the SDK-facing representation; the agent encodes these
|
|
5
|
+
* as integers on the wire (shown below). The {@link RobotStatusService} maps
|
|
6
|
+
* the integer wire values onto these enums on receipt.
|
|
7
|
+
*/
|
|
8
|
+
export var RobotHealth;
|
|
9
|
+
(function (RobotHealth) {
|
|
10
|
+
/** `0` on the wire. Health has not been determined. */
|
|
11
|
+
RobotHealth["UNKNOWN"] = "unknown";
|
|
12
|
+
/** `1` on the wire. The robot is healthy. */
|
|
13
|
+
RobotHealth["NORMAL"] = "normal";
|
|
14
|
+
/** `2` on the wire. Something needs attention, but the robot is still functional. */
|
|
15
|
+
RobotHealth["ABNORMAL"] = "abnormal";
|
|
16
|
+
/** `3` on the wire. The robot requires immediate attention. */
|
|
17
|
+
RobotHealth["CRITICAL"] = "critical";
|
|
18
|
+
})(RobotHealth || (RobotHealth = {}));
|
|
19
|
+
/**
|
|
20
|
+
* The readiness of a robot — whether it is available to take on work — as
|
|
21
|
+
* reported by the agent's `robot/status` topic.
|
|
22
|
+
*
|
|
23
|
+
* As with {@link RobotHealth}, the agent encodes these as integers on the wire.
|
|
24
|
+
*/
|
|
25
|
+
export var RobotReadiness;
|
|
26
|
+
(function (RobotReadiness) {
|
|
27
|
+
/** `0` on the wire. Readiness has not been determined. */
|
|
28
|
+
RobotReadiness["UNKNOWN"] = "unknown";
|
|
29
|
+
/** `1` on the wire. The robot is available. */
|
|
30
|
+
RobotReadiness["IDLE"] = "idle";
|
|
31
|
+
/** `2` on the wire. The robot is occupied and should not be interrupted. */
|
|
32
|
+
RobotReadiness["BUSY"] = "busy";
|
|
33
|
+
})(RobotReadiness || (RobotReadiness = {}));
|
|
34
|
+
/**
|
|
35
|
+
* Whether the robot is connected to a single cloud service, as reported by that
|
|
36
|
+
* service's `connections` endpoint (or, for `telemetry-liveness`, derived from
|
|
37
|
+
* heartbeat freshness).
|
|
38
|
+
*/
|
|
39
|
+
export var ServiceConnection;
|
|
40
|
+
(function (ServiceConnection) {
|
|
41
|
+
ServiceConnection["CONNECTED"] = "connected";
|
|
42
|
+
ServiceConnection["DISCONNECTED"] = "disconnected";
|
|
43
|
+
/** The service's connectivity has not yet been determined (e.g. not polled). */
|
|
44
|
+
ServiceConnection["UNKNOWN"] = "unknown";
|
|
45
|
+
})(ServiceConnection || (ServiceConnection = {}));
|
|
46
|
+
/**
|
|
47
|
+
* The robot's overall connectivity to the cloud platform, aggregated across all
|
|
48
|
+
* expected services.
|
|
49
|
+
*/
|
|
50
|
+
export var RobotConnectivity;
|
|
51
|
+
(function (RobotConnectivity) {
|
|
52
|
+
/** Every expected service reports connected. */
|
|
53
|
+
RobotConnectivity["ONLINE"] = "online";
|
|
54
|
+
/** Some, but not all, expected services report connected. */
|
|
55
|
+
RobotConnectivity["DEGRADED"] = "degraded";
|
|
56
|
+
/** No expected service reports connected. */
|
|
57
|
+
RobotConnectivity["OFFLINE"] = "offline";
|
|
58
|
+
})(RobotConnectivity || (RobotConnectivity = {}));
|
|
@@ -43,6 +43,44 @@ export declare class CallerService extends BaseStreamService<ICallerStream> {
|
|
|
43
43
|
ack$: Observable<IRocosCallerMessageResponseAck>;
|
|
44
44
|
cancel: () => Promise<void>;
|
|
45
45
|
};
|
|
46
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
47
|
+
*
|
|
48
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
49
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
50
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
51
|
+
* and tear it down only when the action itself completes/errors.
|
|
52
|
+
*
|
|
53
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
54
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
55
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
56
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
57
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
58
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
59
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
60
|
+
* still receives it.
|
|
61
|
+
*
|
|
62
|
+
* Lifecycle:
|
|
63
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
64
|
+
* errors (or completes) before any ack arrives.
|
|
65
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
66
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
67
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
68
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
69
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
70
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
71
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
72
|
+
* where the action should keep running but the result is no longer needed.
|
|
73
|
+
*
|
|
74
|
+
* @see call
|
|
75
|
+
* @see callRaw
|
|
76
|
+
*/
|
|
77
|
+
callAction<T = unknown>(params: ICallerCallParams): {
|
|
78
|
+
ack: Promise<IRocosCallerMessageResponseAck>;
|
|
79
|
+
result$: Observable<IRocosCallerMessageResponseResult>;
|
|
80
|
+
return$: Observable<T>;
|
|
81
|
+
cancel: () => Promise<void>;
|
|
82
|
+
close: () => void;
|
|
83
|
+
};
|
|
46
84
|
protected createStream(): Promise<ICallerStream>;
|
|
47
85
|
protected getStream(config: IStreamConfig): ICallerStream;
|
|
48
86
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ResultStatus, RocosResponseLevel, } from '../models';
|
|
2
|
-
import { from, lastValueFrom, map, mergeMap, share, switchMap, take, takeUntil, throwError } from 'rxjs';
|
|
2
|
+
import { ReplaySubject, firstValueFrom, from, lastValueFrom, map, mergeMap, share, switchMap, take, takeUntil, throwError, } from 'rxjs';
|
|
3
3
|
import { catchError, filter } from 'rxjs/operators';
|
|
4
4
|
import { getResponses, handleChunkedMessages } from '../helpers/callerMessageHelpers';
|
|
5
5
|
import { BaseStreamService } from './BaseStreamService';
|
|
@@ -101,6 +101,62 @@ export class CallerService extends BaseStreamService {
|
|
|
101
101
|
cancel,
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
105
|
+
*
|
|
106
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
107
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
108
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
109
|
+
* and tear it down only when the action itself completes/errors.
|
|
110
|
+
*
|
|
111
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
112
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
113
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
114
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
115
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
116
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
117
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
118
|
+
* still receives it.
|
|
119
|
+
*
|
|
120
|
+
* Lifecycle:
|
|
121
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
122
|
+
* errors (or completes) before any ack arrives.
|
|
123
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
124
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
125
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
126
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
127
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
128
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
129
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
130
|
+
* where the action should keep running but the result is no longer needed.
|
|
131
|
+
*
|
|
132
|
+
* @see call
|
|
133
|
+
* @see callRaw
|
|
134
|
+
*/
|
|
135
|
+
callAction(params) {
|
|
136
|
+
const stream = this.call(params);
|
|
137
|
+
// Replay the one-shot result so subscription order never matters and a late
|
|
138
|
+
// subscriber still receives it.
|
|
139
|
+
const result = new ReplaySubject(1);
|
|
140
|
+
// One SDK-owned subscription pins the shared source alive for the whole action.
|
|
141
|
+
// It fires the request once (first subscriber) and forwards the result into the
|
|
142
|
+
// replay subject, completing/erroring it when the action ends. Because this
|
|
143
|
+
// subscription outlives any `firstValueFrom(ack)` teardown, subscriber churn can
|
|
144
|
+
// never reset the source and re-issue the goal.
|
|
145
|
+
const pin = stream.result$.subscribe(result);
|
|
146
|
+
// `ack` rejects if the action errors or completes before any ack arrives. Since
|
|
147
|
+
// callAction is meant to be consumed via result$/return$ too, a caller may never
|
|
148
|
+
// touch `ack` — without a handler that rejection would surface as an unhandled
|
|
149
|
+
// promise rejection. Awaiting `action.ack` still rejects for callers who do care.
|
|
150
|
+
const ack = firstValueFrom(stream.ack$);
|
|
151
|
+
ack.catch(() => { });
|
|
152
|
+
return {
|
|
153
|
+
ack,
|
|
154
|
+
result$: result.asObservable(),
|
|
155
|
+
return$: stream.return$,
|
|
156
|
+
cancel: stream.cancel,
|
|
157
|
+
close: () => pin.unsubscribe(),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
104
160
|
async createStream() {
|
|
105
161
|
return (await this.createStreamFromConfig(IDENTIFIER_NAME_CALLER, {
|
|
106
162
|
url: this.config.url,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { AddPanoramaRequest, AddPanoramaResponse, CreateObservation, Observation } from '../models/maps/Panorama';
|
|
1
2
|
import { Asset, IBaseService, IRocosSDKConfig, Map, MapContent, RocosError } from '../models';
|
|
2
|
-
import { CreateObservation, Observation } from '../models/maps/Panorama';
|
|
3
3
|
import { BaseServiceAbstract } from './BaseServiceAbstract';
|
|
4
4
|
/**
|
|
5
5
|
* Maps service for managing robot maps in the cloud and on robots
|
|
@@ -202,6 +202,25 @@ export declare class MapService extends BaseServiceAbstract implements IBaseServ
|
|
|
202
202
|
* @returns A list of assets
|
|
203
203
|
*/
|
|
204
204
|
getAssetsKeys(projectId: string): Promise<string[]>;
|
|
205
|
+
/**
|
|
206
|
+
* Adds a panorama to the project's dronedeploy map (and optionally other named maps).
|
|
207
|
+
*
|
|
208
|
+
* The dronedeploy map is always written. To also write the panorama into additional maps,
|
|
209
|
+
* pass their ids in `body.map` (single string or array). Each named map must already exist —
|
|
210
|
+
* unknown ids reject the whole call with 400. Entries are deduplicated against dronedeploy
|
|
211
|
+
* and each other.
|
|
212
|
+
*
|
|
213
|
+
* Two server-side conveniences:
|
|
214
|
+
* - `body.transform.id` may be left blank ('') to have the server generate a UUID. The
|
|
215
|
+
* created id is returned in the response so the caller can subsequently get/delete it.
|
|
216
|
+
* - `body.transform.parent` is auto-created as a FRAME node when it doesn't already exist
|
|
217
|
+
* anywhere in the project; no separate "create parent frame" call is required.
|
|
218
|
+
*
|
|
219
|
+
* @param projectId The ID of the project the panorama belongs to.
|
|
220
|
+
* @param body Panorama transform + data, with an optional `map` selector.
|
|
221
|
+
* @returns The panorama node id that was created (echoed when supplied, generated when blank).
|
|
222
|
+
*/
|
|
223
|
+
addPanorama(projectId: string, body: AddPanoramaRequest): Promise<AddPanoramaResponse>;
|
|
205
224
|
/**
|
|
206
225
|
* Deletes a panorama by panoramaID.
|
|
207
226
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { API_GRAPHS_MAPS_COPY_URL, API_GRAPHS_MAPS_DEPLOYED_URL, API_GRAPHS_MAPS_DEPLOY_URL, API_GRAPHS_MAPS_GEOJSON_URL, API_GRAPHS_MAPS_MERGE_URL, API_GRAPHS_MAPS_NEW_URL, API_GRAPHS_MAPS_URL, API_GRAPHS_MAP_CONTENT_URL, API_GRAPHS_MAP_ID_URL, API_GRAPHS_MAP_METADATA_URL, API_GRAPHS_OBSERVATIONS_URL, API_GRAPHS_OBSERVATION_KEYS_URL, API_GRAPHS_PANORAMA, API_GRAPHS_PANORAMA_OBSERVATIONS_URL, } from '../constants/api';
|
|
1
|
+
import { API_GRAPHS_MAPS_COPY_URL, API_GRAPHS_MAPS_DEPLOYED_URL, API_GRAPHS_MAPS_DEPLOY_URL, API_GRAPHS_MAPS_GEOJSON_URL, API_GRAPHS_MAPS_MERGE_URL, API_GRAPHS_MAPS_NEW_URL, API_GRAPHS_MAPS_URL, API_GRAPHS_MAP_CONTENT_URL, API_GRAPHS_MAP_ID_URL, API_GRAPHS_MAP_METADATA_URL, API_GRAPHS_OBSERVATIONS_URL, API_GRAPHS_OBSERVATION_KEYS_URL, API_GRAPHS_PANORAMA, API_GRAPHS_PANORAMAS_URL, API_GRAPHS_PANORAMA_OBSERVATIONS_URL, } from '../constants/api';
|
|
2
2
|
import { RocosError, errorCodes } from '../models';
|
|
3
3
|
import { BaseServiceAbstract } from './BaseServiceAbstract';
|
|
4
4
|
import { RocosLogger } from '../logger/RocosLogger';
|
|
@@ -279,6 +279,27 @@ export class MapService extends BaseServiceAbstract {
|
|
|
279
279
|
getAssetsKeys(projectId) {
|
|
280
280
|
return this.callGet(formatServiceUrl(API_GRAPHS_OBSERVATION_KEYS_URL, { url: this.config.url, projectId }, this.config.insecure), 'Failed to get asset keys.');
|
|
281
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Adds a panorama to the project's dronedeploy map (and optionally other named maps).
|
|
284
|
+
*
|
|
285
|
+
* The dronedeploy map is always written. To also write the panorama into additional maps,
|
|
286
|
+
* pass their ids in `body.map` (single string or array). Each named map must already exist —
|
|
287
|
+
* unknown ids reject the whole call with 400. Entries are deduplicated against dronedeploy
|
|
288
|
+
* and each other.
|
|
289
|
+
*
|
|
290
|
+
* Two server-side conveniences:
|
|
291
|
+
* - `body.transform.id` may be left blank ('') to have the server generate a UUID. The
|
|
292
|
+
* created id is returned in the response so the caller can subsequently get/delete it.
|
|
293
|
+
* - `body.transform.parent` is auto-created as a FRAME node when it doesn't already exist
|
|
294
|
+
* anywhere in the project; no separate "create parent frame" call is required.
|
|
295
|
+
*
|
|
296
|
+
* @param projectId The ID of the project the panorama belongs to.
|
|
297
|
+
* @param body Panorama transform + data, with an optional `map` selector.
|
|
298
|
+
* @returns The panorama node id that was created (echoed when supplied, generated when blank).
|
|
299
|
+
*/
|
|
300
|
+
addPanorama(projectId, body) {
|
|
301
|
+
return this.callPut(formatServiceUrl(API_GRAPHS_PANORAMAS_URL, { url: this.config.url, projectId }, this.config.insecure), body, 'Failed to add panorama.');
|
|
302
|
+
}
|
|
282
303
|
/**
|
|
283
304
|
* Deletes a panorama by panoramaID.
|
|
284
305
|
*
|