syntax = "proto3";
package particle.ctrl.mesh;

import "control/extensions.proto";
import "control/common.proto";

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

// Common fields:
//
// Network name: up to 16 characters, UTF-8 encoded
// Commissioning credential: 6 to 255 characters, UTF-8 encoded
// PAN ID: 16-bit unsigned integer
// Extended PAN ID: 16 characters, hex-encoded
// EUI-64: 16 characters, hex-encoded
// Joining device credential: 6 to 32 characters, base32-thread encoded

// Network info
message NetworkInfo {
  // Network name
  string name = 1;
  // Extended PAN ID
  string ext_pan_id = 2;
  // PAN ID
  uint32 pan_id = 3;
  // Channel number
  uint32 channel = 4;
  // network ID
  string network_id = 5;
}

// Authenticate the client as a commissioner
message AuthRequest {
  option (type_id) = 1001;
  // Commissioning credential
  string password = 1;
}

// Result codes:
// NOT_FOUND: The device is not a member of a network
// NOT_ALLOWED: Invalid commissioning credential
message AuthReply {
}

// Create a new network
message CreateNetworkRequest {
  option (type_id) = 1002;

  // Network name
  string name = 1;
  // Commissioning credential for this network
  string password = 2;
  // Channel number
  uint32 channel = 3;
  // Network ID
  string network_id = 4;
}

// Result codes:
// ALREADY_EXIST: The device is already a member of a network
// NOT_ALLOWED: The client is not authenticated
message CreateNetworkReply {
  // Network info
  NetworkInfo network = 1;
}

// Start the commissioner role
message StartCommissionerRequest {
  option (type_id) = 1003;

  // Time is seconds after which the role is automatically stopped
  uint32 timeout = 1;
}

// Result codes:
// NOT_ALLOWED: The client is not authenticated
message StartCommissionerReply {
}

// Stop the commissioner role
message StopCommissionerRequest {
  option (type_id) = 1004;
}

// Result codes:
// NOT_ALLOWED: The client is not authenticated
message StopCommissionerReply {
}

// Prepare the device to join a network
message PrepareJoinerRequest {
  option (type_id) = 1005;

  NetworkInfo network = 1;
}

// Result codes:
// ALREADY_EXIST: The device is already a member of a network
// NOT_ALLOWED: The client is not authenticated
message PrepareJoinerReply {
  // EUI-64
  string eui64 = 1;
  // Newly generated joining device credential
  string password = 2;
}

// Add a joiner device
message AddJoinerRequest {
  option (type_id) = 1006;

  // EUI-64 of the joiner device
  string eui64 = 1;
  // Joining device credential
  string password = 2;
  // Time is seconds after which the joiner is automatically removed from the commissioner dataset
  uint32 timeout = 3;
}

// Result codes:
// NO_MEMORY: No memory available to add the joiner
// INVALID_STATE: The commissioner role is not started
// NOT_ALLOWED: The client is not authenticated
message AddJoinerReply {
}

// Remove the joiner device
message RemoveJoinerRequest {
  option (type_id) = 1007;

  // EUI-64 of the joiner device
  string eui64 = 1;
}

// Result codes:
// NOT_FOUND: The joiner was not found
// INVALID_STATE: The commissioner role is not started
// NOT_ALLOWED: The client is not authenticated
message RemoveJoinerReply {
}

// Join the network
message JoinNetworkRequest {
  option (type_id) = 1008;

  // Time in seconds after which the attempt to join is cancelled
  uint32 timeout = 1;
}

// Result codes:
// NOT_FOUND: No joinable network was found
// TIMEOUT: The join process timed out
// NOT_ALLOWED: Invalid security credentials
message JoinNetworkReply {
}

// Leave the network
message LeaveNetworkRequest {
  option (type_id) = 1009;
}

// Result codes:
// NOT_FOUND: The device is not a member of a network
// NOT_ALLOWED: The client is not authenticated
message LeaveNetworkReply {
}

// Get the info about current network
message GetNetworkInfoRequest {
  option (type_id) = 1010;
}

// Result codes:
// NOT_FOUND: The device is not a member of a network
message GetNetworkInfoReply {
  // Network info
  NetworkInfo network = 1;
}

// Scan networks
message ScanNetworksRequest {
  option (type_id) = 1011;

  // Time in milliseconds to spend scanning each channel. A value of 0 sets the default OpenThread
  // timeout (300 ms)
  uint32 duration = 1;
}

message ScanNetworksReply {
  repeated NetworkInfo networks = 1;
}

// Diagnostics

enum DiagnosticType {
  // IMPORTANT: values here should match ot::NetworkDiagnostic::NetworkDiagnosticTlv::Type (network_diagnostic_tlvs.hpp)
  option allow_alias = true;
  MAC_EXTENDED_ADDRESS = 0;
  RLOC = 1;
  MAC_ADDRESS = 1;
  MODE = 2;
  TIMEOUT = 3;
  CONNECTIVITY = 4;
  ROUTE64 = 5;
  LEADER_DATA = 6;
  NETWORK_DATA = 7;
  IPV6_ADDRESS_LIST = 8;
  MAC_COUNTERS = 9;
  BATTERY_LEVEL = 14;
  SUPPLY_VOLTAGE = 15;
  CHILD_TABLE = 16;
  CHANNEL_PAGES = 17;
  TYPE_LIST = 18;
  MAX_CHILD_TIMEOUT = 19;
}

// Mapping of Diagnostic TLVs
message DiagnosticInfo {
  // MAC Extended Address (64-bit): MAC Extended Address TLV
  bytes ext_mac_address = 1 [(nanopb).max_size = 8];
  // MAC Address (16-bit): Address16 TLV (RLOC)
  uint32 rloc = 2;

  // Mode TLV
  enum Mode {
    option allow_alias = true;
    INVALID = 0x00;
    RECEIVER_ON_WHEN_IDLE = 0x10;
    SECURE_DATA_REQUESTS = 0x20;

    DEVICE_TYPE = 0x30;
    DEVICE_TYPE_FTD = 0x30;

    NETWORK_DATA = 0x40;
    NETWORK_DATA_FULL = 0x40;
  }

  // Mode (Capability Information): Mode TLV
  uint32 mode = 3;

  // Timeout: Timeout TLV
  uint32 timeout = 4;

  // Connectivity TLV
  message Connectivity {
    uint32 parent_priority = 1;
    uint32 link_quality_1 = 2;
    uint32 link_quality_2 = 3;
    uint32 link_quality_3 = 4;
    uint32 leader_cost = 5;
    uint32 id_sequence = 6;
    uint32 active_routers = 7;
    uint32 sed_buffer_size = 8;
    uint32 sed_datagram_count = 9;
  }

  // Connectivity : Connectivity TLV
  Connectivity connectivity = 5;

  // Route64 TLV
  message Route64 {
    uint32 id_sequence = 1;
    // Originally this is represented as bitmask, we are simplifying
    // representation here a bit
    message RouteData {
      uint32 router_rloc = 1;
      uint32 link_quality_out = 2;
      uint32 link_quality_in = 3;
      uint32 route_cost = 4;
    }

    repeated RouteData routes = 2;
  }

  // Route64: Route64 TLV
  Route64 route64 = 6;

  // Leader Data TLV
  message LeaderData {
    uint32 partition_id = 1;
    uint32 weighting = 2;
    uint32 data_version = 3;
    uint32 stable_data_version = 4;
    uint32 leader_rloc = 5;
  }

  enum RoutePreference {
    MEDIUM = 0;
    HIGH = 1;
    LOW = -1;
  }

  // Network Data TLV
  message NetworkData {
    // Has Route TLV
    message HasRoute {
      message HasRouteEntry {
        uint32 rloc = 1;
        RoutePreference preference = 2;
      }

      repeated HasRouteEntry entries = 1;
    }

    // Border Router TLV
    message BorderRouter {
      message BorderRouterEntry {
        enum Flags {
          NONE = 0x00;
          PREFERRED = 0x01;
          SLAAC = 0x02;
          DHCP = 0x04;
          CONFIGURE = 0x08;
          DEFAULT_ROUTE = 0x10;
          ON_MESH = 0x20;
          ND_DNS = 0x40;
        }

        uint32 rloc = 1;
        RoutePreference preference = 2;
        uint32 flags = 3;
      }

      repeated BorderRouterEntry entries = 1;
    }

    // 6LoWPAN ID TLV
    message Context {
      uint32 cid = 1;
      bool compress = 2;
      uint32 context_length = 3;
    }

    // Prefix TLV
    message Prefix {
      uint32 domain_id = 1;
      uint32 prefix_length = 2;
      bytes prefix = 3 [(nanopb).max_size = 16];

      // Sub-TLVs
      repeated Context context = 4;
      HasRoute has_route = 5;
      BorderRouter border_router = 6;
    }

    // Server TLV
    message Server {
      uint32 rloc = 1;
      bytes data = 2;
    }

    // Service TLV
    message Service {
      // NOTE: THREAD_ENTERPRISE_NUMBER = 44970
      uint32 sid = 1;
      uint32 enterprise_number = 2;
      bytes data = 3;

      repeated Server servers = 4;
    }

    message Data {
      repeated Prefix prefixes = 1;
      repeated Service services = 2;
      // TODO: Commissioning Data TLV?
    }

    Data stable = 1;
    Data temporary = 2;
  }

  // Leader Data: Leader Data TLV
  LeaderData leader_data = 7;
  // Network Data: Network Data TLV
  NetworkData network_data = 8;

  // IPv6 address list: IPv6 Address List TLV
  repeated Ipv6Address ipv6_address_list = 9;

  // MAC Counters TLV
  message MacCounters {
    uint32 if_in_unknown_protos = 1;
    uint32 if_in_errors = 2;
    uint32 if_out_errors = 3;
    uint32 if_in_ucast_pkts = 4;
    uint32 if_in_broadcast_pkts = 5;
    uint32 if_in_discards = 6;
    uint32 if_out_ucast_pkts = 7;
    uint32 if_out_broadcast_pkts = 8;
    uint32 if_out_discards = 9;
  }

  // MAC Counters: MAC Counters TLV
  MacCounters mac_counters = 10;

  // NOTE: 11-14 reserved

  // Battery Level: Battery Level TLV
  uint32 battery_level = 15;

  // Supply Voltage: Supply Voltage TLV
  uint32 supply_voltage = 16;

  // Child Table TLV
  message ChildTable {
    message ChildEntry {
      uint32 timeout = 1;
      uint32 child_id = 2;
      // Mode TLV
      uint32 mode = 3;
    }
    repeated ChildEntry children = 1;
  }

  // Child Table: Child Table TLV
  ChildTable child_table = 17;

  // Channel Pages: Channel Pages TLV
  bytes channel_pages = 18 [(nanopb).max_size = 3];

  // Type List: Type List TLV
  // List of DiagnosticType
  repeated DiagnosticType type_list = 19;

  // Max Child Timeout: Timeout TLV
  uint32 max_child_timeout = 20;

  // Particle-specific Device Id
  bytes device_id = 100 [(nanopb).max_size = 12];
}

message GetNetworkDiagnosticsRequest {
  option (type_id) = 1012;

  enum Flags {
    INVALID = 0x00;
    QUERY_CHILDREN = 0x01;
    RESOLVE_DEVICE_ID = 0x02;
  }

  // Bitmask of Flags
  uint32 flags = 1;

  // List of DiagnosticType to request
  repeated DiagnosticType diagnostic_types = 2;

  // Maximum time in seconds to wait for diagnostic replies
  uint32 timeout = 3;
}

message GetNetworkDiagnosticsReply {
  repeated DiagnosticInfo nodes = 1;
}
