syntax = "proto3";
package particle.ctrl;

import "control/extensions.proto";

option java_package = "io.particle.firmwareprotos.ctrl";

// Note: Use the same values as defined by the security_key_type enum
enum SecurityKeyType {
  INVALID_SECURITY_KEY = 0; // Invalid key
  TCP_DEVICE_PRIVATE_KEY = 1; // TCP device private key
  TCP_DEVICE_PUBLIC_KEY = 2; // TCP device public key
  TCP_SERVER_PUBLIC_KEY = 3; // TCP server public key
  UDP_DEVICE_PRIVATE_KEY = 4; // UDP device private key
  UDP_DEVICE_PUBLIC_KEY = 5; // UDP device public key
  UDP_SERVER_PUBLIC_KEY = 6; // UDP server public key
}

// Note: Use the same values as defined by the server_protocol_type enum
enum ServerProtocolType {
  INVALID_PROTOCOL = 0;
  TCP_PROTOCOL = 1; // TCP
  UDP_PROTOCOL = 2; // UDP
}

// Device mode
enum DeviceMode {
  NORMAL_MODE = 0;  // Normal mode
  LISTENING_MODE = 1; // Listening mode
}

// System capability flags
enum SystemCapabilityFlag {
  NO_SYSTEM_CAPABILITY_FLAGS = 0;
  COMPRESSED_OTA = 0x01;
}

// System features
enum Feature {
  INVALID_FEATURE = 0; // Invalid feature
  ETHERNET_DETECTION = 1; // Ethernet FeatherWing detection on boot
}

// Get the device ID
message GetDeviceIdRequest {
  option (type_id) = 20; // CTRL_REQUEST_DEVICE_ID
}

message GetDeviceIdReply {
  // Device ID (hex-encoded)
  string id = 1 [(nanopb).max_length = 24];
}

// Get the device's serial number
message GetSerialNumberRequest {
  option (type_id) = 21; // CTRL_REQUEST_SERIAL_NUMBER
}

message GetSerialNumberReply {
  // Device serial ID
  string serial = 1 [(nanopb).max_length = 16];
}

// Get the firmware version
message GetSystemVersionRequest {
  option (type_id) = 30; // CTRL_REQUEST_SYSTEM_VERSION
}

message GetSystemVersionReply {
  // Device OS version in SemVer format
  string version = 1;
}

// Get the NCP (network coprocessor) firmware version
message GetNcpFirmwareVersionRequest {
  option (type_id) = 31; // CTRL_REQUEST_NCP_FIRMWARE_VERSION
}

message GetNcpFirmwareVersionReply {
  // NCP version in SemVer format
  string version = 1;
  // NCP module version
  uint32 module_version = 2;
}

// Get system capabilities
message GetSystemCapabilitiesRequest {
  option (type_id) = 32; // CTRL_REQUEST_GET_SYSTEM_CAPABILITIES
}

message GetSystemCapabilitiesReply {
  // SystemCapabilityFlag flags
  fixed32 flags = 1;
}

message SetClaimCodeRequest {
  option (type_id) = 200; // CTRL_REQUEST_SET_CLAIM_CODE
  string code = 1 [(nanopb).max_length = 64]; // Claim code
}

message SetClaimCodeReply {
}

message IsClaimedRequest {
  option (type_id) = 201; // CTRL_REQUEST_IS_CLAIMED
}

message IsClaimedReply {
  // `true` if device is claimed
  bool claimed = 1;
}

message SetSecurityKeyRequest {
  option (type_id) = 210; // CTRL_REQUEST_SET_SECURITY_KEY
  SecurityKeyType type = 1; // Key type
  bytes data = 2; // Key data in DER format
}

message SetSecurityKeyReply {
}


message GetSecurityKeyRequest {
  option (type_id) = 211; // CTRL_REQUEST_GET_SECURITY_KEY
  SecurityKeyType type = 1; // Key type
}

message GetSecurityKeyReply {
  bytes data = 1; // Key data in DER format
}

message SetServerAddressRequest {
  option (type_id) = 220; // CTRL_REQUEST_SET_SERVER_ADDRESS
  ServerProtocolType protocol = 1; // Protocol type
  string address = 2 [(nanopb).max_length = 64]; // Server address
  int32 port = 3; // Port number
}

message SetServerAddressReply {
}

message GetServerAddressRequest {
  option (type_id) = 221; // CTRL_REQUEST_GET_SERVER_ADDRESS
  ServerProtocolType protocol = 1; // Protocol type
}

message GetServerAddressReply {
  string address = 1; // Server address
  int32 port = 2; // Port number
}

message SetServerProtocolRequest {
  option (type_id) = 222;  // CTRL_REQUEST_SET_SERVER_PROTOCOL
  ServerProtocolType protocol = 1; // Protocol type
}

message SetServerProtocolReply {
}

message GetServerProtocolRequest {
  option (type_id) = 223;  // CTRL_REQUEST_GET_SERVER_PROTOCOL
}

message GetServerProtocolReply {
  ServerProtocolType protocol = 1; // Protocol type
}

// Set the SoftAP SSID prefix and suffix
message SetSoftApSsidRequest {
  option (type_id) = 240;  // CTRL_REQUEST_SET_SOFTAP_SSID
  string prefix = 1 [(nanopb).max_length = 32]; // SSID prefix
  string suffix = 2 [(nanopb).max_length = 16]; // SSID sufix
}

message SetSoftApSsidReply {
}

// Put the device into listening mode
message StartListeningModeRequest {
  option (type_id) = 70; // CTRL_REQUEST_START_LISTENING
}

message StartListeningModeReply {
}

// Put the device into normal mode
message StopListeningModeRequest {
  option (type_id) = 71; // CTRL_REQUEST_STOP_LISTENING
}

message StopListeningModeReply {
}

// Get the current device mode
message GetDeviceModeRequest {
  option (type_id) = 72; // CTRL_REQUEST_GET_DEVICE_MODE
}

message GetDeviceModeReply {
  DeviceMode mode = 1;
}

// Set flag for setup being done
message SetDeviceSetupDoneRequest {
  option (type_id) = 73; // CTRL_REQUEST_SET_DEVICE_SETUP_DONE
  bool done = 1;
}

message SetDeviceSetupDoneReply {
}

// Get the flag indicating if the device has been set up
message IsDeviceSetupDoneRequest {
  option (type_id) = 74; // CTRL_REQUEST_IS_DEVICE_SETUP_DONE
}

message IsDeviceSetupDoneReply {
  bool done = 1;
}

// Set the mode to enter when in safe mode
message SetStartupModeRequest {
  option (type_id) = 75; // CTRL_REQUEST_SET_STARTUP_MODE
  DeviceMode mode = 1;
}

message SetStartupModeReply {
}

message GetProtectedStateRequest {
  option (type_id) = 76; // CTRL_REQUEST_GET_PROTECTED_STATE
}

message GetProtectedStateReply {
  bool state = 1;
  bool overridden = 2;
}

message SetProtectedStateRequest {
  option (type_id) = 77; // CTRL_REQUEST_SET_PROTECTED_STATE
  option (nanopb_msgopt).no_unions = true;

  enum Action {
    RESET = 0;
    PREPARE = 1;
    CONFIRM = 2;
  }

  message Prepare {
    bytes server_nonce = 1 [(nanopb).max_size = 32];
  }

  message Confirm {
    bytes server_signature = 1;
    bytes server_public_key_fingerprint = 2 [(nanopb).max_size = 32];
  }

  Action action = 1;

  oneof data {
    Prepare prepare = 2;
    Confirm confirm = 3;
  }
}

message SetProtectedStateReply {
  message Prepare {
    bytes device_nonce = 1 [(nanopb).max_size = 32];
    bytes device_signature = 2;
    bytes device_public_key_fingerprint = 3 [(nanopb).max_size = 32];
  }

  optional Prepare prepare = 1;
}

// Resets the device, just like hitting the reset button or powering down and back up
message SystemResetRequest {
  option (type_id) = 40; // CTRL_REQUEST_RESET
}

message SystemResetReply {
}

// Enable/disable system features
message SetFeatureRequest {
  option (type_id) = 33; // CTRL_REQUEST_SET_FEATURE
  Feature feature = 1;
  bool enabled = 2;
}

message SetFeatureReply {
}

// Check if the system feature is enabled or disabled
message GetFeatureRequest {
  option (type_id) = 34; // CTRL_REQUEST_GET_FEATURE
  Feature feature = 1;
}

message GetFeatureReply {
  bool enabled = 1;
}

// Make the device's status LED display a rainbow pattern aka Nyan mode
message StartNyanSignalRequest {
  option (type_id) = 230; // CTRL_REQUEST_START_NYAN_SIGNAL
}

message StartNyanSignalReply {
}

// Exit the Nyan mode
message StopNyanSignalRequest {
  option (type_id) = 231; // CTRL_REQUEST_STOP_NYAN_SIGNAL
}

message StopNyanSignalReply {
}

/**
 * Get defined environment variables.
 */
message GetEnvRequest {
  option (type_id) = 600; // CTRL_REQUEST_ENV_GET
}

/**
 * Response for a `GetEnvRequest`.
 */
message GetEnvReply {
  message Var {
    string name = 1 [(nanopb).max_length = 128]; ///< Variable name.
    string value = 2; ///< Variable value.
    bool is_app = 3; ///< Whether this is an application variable.
  }

  repeated Var vars = 1; ///< List of variables.
  optional bytes snapshot_hash = 2 [(nanopb).max_size = 32]; ///< Snapshot hash.
}

/**
 * Clear all defined environment variables.
 */
message ClearEnvRequest {
  option (type_id) = 601; // CTRL_REQUEST_ENV_CLEAR
}

/**
 * Response for a `ClearEnvRequest`.
 */
message ClearEnvReply {
  bool need_reset = 1; ///< Whether a system reset is needed to apply the changes.
}
