syntax = "proto3";

package cmvr.quic_edge.v1;

option java_package = "com.cmvr.quic.edge.v1";
option java_multiple_files = true;
option java_outer_classname = "QuicEdgeProtocol";

// 本文件与cmvr-es提交428ee328中的QUIC edge v1协议保持线兼容。
message EdgeControlEnvelope {
  uint32 protocol_version = 1;
  uint64 message_sequence = 2;

  oneof payload {
    NodeRegisterRequest node_register_request = 10;
    NodeRegisterResponse node_register_response = 11;
    NodeHeartbeat node_heartbeat = 12;
    NodeHeartbeatAck node_heartbeat_ack = 13;
    MediaSessionOpen media_session_open = 20;
    MediaTrackDescriptor media_track_descriptor = 21;
    MediaSessionClose media_session_close = 22;
    ProtocolError protocol_error = 30;
  }
}

message NetworkInterfaceAddress {
  enum AddressFamily {
    ADDRESS_FAMILY_UNSPECIFIED = 0;
    ADDRESS_FAMILY_IPV4 = 1;
    ADDRESS_FAMILY_IPV6 = 2;
  }
  string interface_name = 1;
  string ip_address = 2;
  AddressFamily family = 3;
  bool loopback = 4;
}

message GrpcEndpoint {
  string host = 1;
  uint32 port = 2;
  bool tls = 3;
}

enum DeviceKind {
  DEVICE_KIND_UNSPECIFIED = 0;
  DEVICE_KIND_AGV = 1;
  DEVICE_KIND_ARM = 2;
  DEVICE_KIND_BATTERY = 3;
  DEVICE_KIND_BIO_HEAD = 4;
  DEVICE_KIND_CAMERA = 5;
  DEVICE_KIND_CAN_BUS = 6;
  DEVICE_KIND_DEX_HAND = 7;
  DEVICE_KIND_GRIPPER = 8;
  DEVICE_KIND_MICROPHONE = 9;
  DEVICE_KIND_MOTOR = 10;
  DEVICE_KIND_MOTOR_SYSTEM = 11;
  DEVICE_KIND_ROBOT = 12;
  DEVICE_KIND_SPEAKER = 13;
}

enum ManagedDeviceState {
  MANAGED_DEVICE_STATE_UNSPECIFIED = 0;
  MANAGED_DEVICE_STATE_DISABLED = 1;
  MANAGED_DEVICE_STATE_INITIALIZING = 2;
  MANAGED_DEVICE_STATE_REGISTERED = 3;
  MANAGED_DEVICE_STATE_READY = 4;
  MANAGED_DEVICE_STATE_RUNNING = 5;
  MANAGED_DEVICE_STATE_STOPPED = 6;
  MANAGED_DEVICE_STATE_ERROR = 7;
}

enum DeviceHealthStatus {
  DEVICE_HEALTH_STATUS_UNSPECIFIED = 0;
  DEVICE_HEALTH_STATUS_HEALTHY = 1;
  DEVICE_HEALTH_STATUS_DEGRADED = 2;
  DEVICE_HEALTH_STATUS_FAULT = 3;
}

message ManagedDeviceStatus {
  string device_id = 1;
  DeviceKind kind = 2;
  string type_name = 3;
  bool enabled = 4;
  ManagedDeviceState manager_state = 5;
  DeviceHealthStatus health = 6;
  bool has_error = 7;
  string error_message = 8;
  uint64 status_updated_at_unix_ms = 9;
}

message DeviceManagerSnapshot {
  string manager_name = 1;
  string manager_version = 2;
  string manager_description = 3;
  repeated ManagedDeviceStatus devices = 4;
  uint64 sampled_at_unix_ms = 5;
}

message NodeDescriptor {
  string node_id = 1;
  string boot_id = 2;
  string software_version = 3;
  repeated NetworkInterfaceAddress local_interfaces = 4;
  GrpcEndpoint grpc_endpoint = 5;
}

message NodeRegisterRequest {
  NodeDescriptor node = 1;
  uint64 sent_at_unix_ms = 2;
}

message NodeRegisterResponse {
  bool accepted = 1;
  string session_id = 2;
  string message = 3;
  uint32 heartbeat_interval_ms = 4;
  string observed_source_ip = 5;
}

message NodeHeartbeat {
  string node_id = 1;
  string boot_id = 2;
  string session_id = 3;
  uint64 sequence = 4;
  uint64 sent_at_unix_ms = 5;
  string software_version = 6;
  repeated NetworkInterfaceAddress local_interfaces = 7;
  GrpcEndpoint grpc_endpoint = 8;
  DeviceManagerSnapshot device_manager = 9;
}

message NodeHeartbeatAck {
  bool accepted = 1;
  uint64 acknowledged_sequence = 2;
  string message = 3;
  uint64 server_time_unix_ms = 4;
  string observed_source_ip = 5;
  string session_id = 6;
}

message MediaSessionOpen {
  string node_id = 1;
  uint64 session_epoch = 2;
  string session_id = 3;
}

enum MediaKind {
  MEDIA_KIND_UNSPECIFIED = 0;
  MEDIA_KIND_VIDEO = 1;
  MEDIA_KIND_AUDIO = 2;
}

message MediaTrackDescriptor {
  uint32 track_id = 1;
  MediaKind kind = 2;
  string device_id = 3;
  string codec = 4;
  uint64 codec_generation = 5;
  string source_track_id = 6;
  uint32 codec_generation_token = 7;
  string payload_format = 8;
  uint32 width = 10;
  uint32 height = 11;
  uint32 frames_per_second = 12;
  uint32 sample_rate = 20;
  uint32 channels = 21;
  bytes codec_config = 30;
}

message MediaSessionClose {
  string reason = 1;
  string session_id = 2;
  uint64 session_epoch = 3;
}

message ProtocolError {
  uint32 code = 1;
  string message = 2;
  uint64 related_message_sequence = 3;
  bool fatal = 4;
}
