diff --git a/protos/cmvr/api/system_command.proto b/protos/cmvr/api/system_command.proto index 52b99221..d99f623e 100644 --- a/protos/cmvr/api/system_command.proto +++ b/protos/cmvr/api/system_command.proto @@ -1,6 +1,9 @@ syntax = "proto3"; +import "cmvr/api/agv_command.proto"; +import "cmvr/api/arm_command.proto"; import "cmvr/api/common.proto"; +import "cmvr/api/safety_command.proto"; package cmvr.api; @@ -21,6 +24,77 @@ message DeviceList { DeviceType device_type = 2; } +// Stable device categories used by GetDeviceList. This intentionally does not +// reuse the legacy DeviceType enum above: its zero value is AGV and it does not +// cover all DeviceManager categories. +enum SystemDeviceType { + SYSTEM_DEVICE_TYPE_UNSPECIFIED = 0; + SYSTEM_DEVICE_TYPE_AGV = 1; + SYSTEM_DEVICE_TYPE_ARM = 2; + SYSTEM_DEVICE_TYPE_BATTERY = 3; + SYSTEM_DEVICE_TYPE_BIO_HEAD = 4; + SYSTEM_DEVICE_TYPE_CAMERA = 5; + SYSTEM_DEVICE_TYPE_CAN_BUS = 6; + SYSTEM_DEVICE_TYPE_DEX_HAND = 7; + SYSTEM_DEVICE_TYPE_GRIPPER = 8; + SYSTEM_DEVICE_TYPE_MICROPHONE = 9; + SYSTEM_DEVICE_TYPE_MOTOR = 10; + SYSTEM_DEVICE_TYPE_MOTOR_SYSTEM = 11; + SYSTEM_DEVICE_TYPE_MUJOCO_VIEWER = 12; + SYSTEM_DEVICE_TYPE_MUJOCO_WORLD = 13; + SYSTEM_DEVICE_TYPE_ROBOT = 14; + SYSTEM_DEVICE_TYPE_SPEAKER = 15; +} + +enum SystemDeviceState { + SYSTEM_DEVICE_STATE_UNSPECIFIED = 0; + SYSTEM_DEVICE_STATE_DISABLED = 1; + SYSTEM_DEVICE_STATE_INITIALIZING = 2; + SYSTEM_DEVICE_STATE_REGISTERED = 3; + SYSTEM_DEVICE_STATE_READY = 4; + SYSTEM_DEVICE_STATE_RUNNING = 5; + SYSTEM_DEVICE_STATE_STOPPED = 6; + SYSTEM_DEVICE_STATE_ERROR = 7; +} + +enum SystemDeviceHealth { + SYSTEM_DEVICE_HEALTH_UNSPECIFIED = 0; + SYSTEM_DEVICE_HEALTH_HEALTHY = 1; + SYSTEM_DEVICE_HEALTH_DEGRADED = 2; + SYSTEM_DEVICE_HEALTH_FAULT = 3; +} + +message SystemDeviceInfo { + string device_id = 1; + SystemDeviceType device_type = 2; + + // Concrete backend name for display and diagnostics only. Consumers must + // use device_type, rather than this free-form string, for decisions. + string type_name = 3; + + // GetDeviceList currently publishes only enabled entries. Keep this field + // explicit so each row remains self-describing and future-compatible. + bool enabled = 4; + SystemDeviceState manager_state = 5; + SystemDeviceHealth health = 6; + bool has_error = 7; + string error_message = 8; + uint64 status_updated_at_unix_ms = 9; +} + +message GetDeviceListCommand { + message Request {} + + message Feedback { + CommandHeader.Feedback header = 1; + string manager_name = 2; + string manager_version = 3; + string manager_description = 4; + repeated SystemDeviceInfo device_list = 5; + uint64 sampled_at_unix_ms = 6; + } +} + message GetSystemInfoCommand { message Request {} @@ -32,6 +106,20 @@ message GetSystemInfoCommand { string os = 5; string kernel_version = 6; string architecture = 7; + + // Changes whenever the in-process ActionQueue idempotency ledger is + // recreated. Clients bind submissions and retries to this value. + string action_service_instance_id = 8; + + // Effective server-side control-plane settings. These fields describe + // what is running, not merely what the configuration requested. + string grpc_transport_security = 9; + string grpc_authentication = 10; + string grpc_recovery_exposure = 11; + bool grpc_insecure_non_loopback = 12; + string control_service_instance_id = 13; + string safety_enforcement_mode = 14; + uint32 safety_schema_version = 15; } } @@ -64,9 +152,111 @@ message UpdateParamsCommand { message StopAllCommand { message Request { CommandHeader.Request header = 1; + string operation_id = 2; + string expected_service_instance_id = 3; + uint32 timeout_ms = 4; } message Feedback { CommandHeader.Feedback header = 1; + string operation_id = 2; + uint64 previous_safety_epoch = 3; + uint64 current_safety_epoch = 4; + SystemAdmissionState system_state = 5; + repeated SafetyOperationTargetResult targets = 6; } -} \ No newline at end of file +} + +// Final outcome of one ActionQueue execution. +enum ActionResultCode { + ACTION_RESULT_CODE_UNSPECIFIED = 0; + ACTION_RESULT_CODE_COMPLETED = 1; + ACTION_RESULT_CODE_FAILED = 2; + ACTION_RESULT_CODE_CANCELED = 3; + ACTION_RESULT_CODE_TIMED_OUT = 4; + ACTION_RESULT_CODE_REJECTED = 5; +} + +// Describes whether this RPC admitted a new action or observed an existing +// idempotency record. Clients must not infer this from an error string. +enum ActionDeduplicationStatus { + ACTION_DEDUPLICATION_STATUS_UNSPECIFIED = 0; + ACTION_DEDUPLICATION_STATUS_ACCEPTED_NEW = 1; + ACTION_DEDUPLICATION_STATUS_JOINED_IN_FLIGHT = 2; + ACTION_DEDUPLICATION_STATUS_CACHED_RESULT = 3; + ACTION_DEDUPLICATION_STATUS_RESULT_EVICTED = 4; + ACTION_DEDUPLICATION_STATUS_LEDGER_EXHAUSTED = 5; + ACTION_DEDUPLICATION_STATUS_ACTION_ID_CONFLICT = 6; + ACTION_DEDUPLICATION_STATUS_SERVICE_INSTANCE_MISMATCH = 7; +} + +// Edge-local delay between two device commands. +message DelayAction { + // Delay duration in milliseconds. The server applies a bounded maximum. + uint32 duration_ms = 1; +} + +// One finite, synchronous command in an ActionQueue request. +message ActionStep { + // Client-provided identifier used for diagnostics. It must be unique within + // one ActionQueue request. + string step_id = 1; + + // Per-step timeout in milliseconds. Zero inherits the remaining action + // timeout or the server default. + uint32 timeout_ms = 2; + + // Tags are grouped by domain so compatible commands can be added without + // renumbering existing alternatives: Arm 10-19, AGV 20-29, built-ins 90+. + oneof command { + MoveJ.Request arm_move_j = 10; + MoveL.Request arm_move_l = 11; + + AgvNavigateToPoseCommand.Request agv_navigate_to_pose = 20; + AgvNavigateToStationCommand.Request agv_navigate_to_station = 21; + AgvFollowPathCommand.Request agv_follow_path = 22; + + DelayAction delay = 90; + } +} + +// Atomically submits a complete command sequence for edge-local serial +// execution. Device motion alternatives must use synchronous execution. +message ActionQueueCommand { + message Request { + // Client-generated globally unique idempotency key. During one Action + // service instance, retrying an identical accepted request with the + // same action_id does not dispatch its steps a second time. Recent + // terminal results can be returned; older accepted IDs are rejected + // fail-closed after their result is evicted. Deduplication is not + // persisted across an edge-service restart; the required instance + // epoch below prevents an old retry from being replayed after restart. + string action_id = 1; + repeated ActionStep steps = 2; + + // Total queue-wait plus execution timeout in milliseconds. Zero uses a + // bounded server default. + uint32 total_timeout_ms = 3; + + // Required instance epoch obtained from GetSystemInfo. A mismatch + // means the process-local deduplication ledger was recreated, so the + // server rejects the request instead of risking a replay. + string expected_service_instance_id = 4; + } + + message Feedback { + CommandHeader.Feedback header = 1; + string action_id = 2; + + // Number of steps which completed successfully before the final result. + uint32 completed_steps = 3; + + // Present only when a particular step caused failure, cancellation, + // timeout, or rejection. Presence distinguishes index zero from no + // failed step. + optional uint32 failed_step_index = 4; + ActionResultCode result = 5; + string service_instance_id = 6; + ActionDeduplicationStatus deduplication_status = 7; + } +} diff --git a/protos/cmvr/api/system_service.proto b/protos/cmvr/api/system_service.proto index f02896e2..60476ad0 100644 --- a/protos/cmvr/api/system_service.proto +++ b/protos/cmvr/api/system_service.proto @@ -1,5 +1,6 @@ syntax = "proto3"; +import "cmvr/api/common.proto"; import "cmvr/api/system_command.proto"; import "cmvr/api/safety_command.proto";