/*
  Сервис реализует функционал управления устройствами
*/
syntax = "proto3";

import "google/protobuf/timestamp.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/wrappers.proto";
import "google/api/visibility.proto";
import "keyapis/device/v1/keyapis_device_model_v1.proto";


package keyapis.device.v1;

option java_package = "ru.keyapis.device.v1";
option java_outer_classname = "KeyapisDeviceV1Proto";
option java_multiple_files = false;
option java_string_check_utf8 = true;
option go_package = "/keyapis_device_v1";
option cc_enable_arenas = true;
option csharp_namespace = "Keyapis.Device.V1";
option objc_class_prefix = "KEYAPISDEVICEV1";
option php_namespace = "Keyapis\\Device\\V1";
option ruby_package = "Keyapis::Device::V1";
option optimize_for = LITE_RUNTIME;

// Сервис устройств
service DeviceService {
  // Метод получаения устройства.
  // Метод доступен для: admin, service, owner, employee, bti, ltp_first
  rpc GetDevice(GetDeviceRequest) returns (GetDeviceResponse) {
    option (google.api.http) = {
      get: "/device/api/v1/device/{id}",
    };
  }
  // Метод получения списка устройств.
  // Метод доступен для: admin, service, owner, employee, bti, ltp_first
  rpc GetDeviceList(GetDeviceListRequest) returns (stream GetDeviceListResponse){
    option (google.api.http) = {
      get: "/device/api/v1/device/list",
    };
  }
  // Метод получения количества устройств.
  // Метод доступен для: admin, service, owner, employee, bti, ltp_first
  rpc GetDeviceCount(GetDeviceCountRequest) returns (GetDeviceCountResponse){
    option (google.api.http) = {
      get: "/device/api/v1/device/count",
    };
  }
  // Метод создания устройства.
  // Метод доступен для: admin, bti, service, owner, employee.
  // Для owner, employee доступно создание и редактирование только в КВГ, привязанных к компании пользователя
  rpc PostDevice(PostDeviceRequest) returns (PostDeviceResponse) {
    option (google.api.http) = {
      post: "/device/api/v1/device",
      body: "*"
    };
  }
  // Метод изменения устройства.
  // Метод доступен для: admin, bti, service
  rpc PutDevice(PutDeviceRequest) returns (PutDeviceResponse) {
    option deprecated = true;
    option (google.api.http) = {
      put: "/device/api/v1/device",
      body: "*"
    };
  }
  // Метод установки пресета на устройство.
  // Метод доступен для: admin, service
  rpc PostDeviceInstallPreset(PostDeviceInstallPresetRequest) returns (PostDeviceInstallPresetResponse) {
    option (google.api.http) = {
      post: "/device/api/v1/device/{id}/install_preset"
    };
  }
  // Метод замены устройста.
  // Логика работы метода: https://confluence.rt.ru/pages/viewpage.action?pageId=655256574.
  // Метод доступен для: admin, bti, service
  rpc PostDeviceReplace(PostDeviceReplaceRequest) returns (PostDeviceReplaceResponse) {
    option (google.api.http) = {
      post: "/device/api/v1/device/{id}/replace",
      body: "*"
    };
  }
  // Метод переконфигурирования устройста.
  // Логика работы метода: https://confluence.rt.ru/pages/viewpage.action?pageId=630337555.
  // Метод доступен для: admin, bti, service
  rpc PostDeviceReconfigure(PostDeviceReconfigureRequest) returns (PostDeviceReconfigureResponse) {
    option (google.api.http) = {
      post: "/device/api/v1/device/{id}/reconfigure"
    };
  }
  // Метод получения статусов конфигурации устройства.
  // Метод доступен для: admin, service, bti, ltp_first
  rpc GetDeviceConfigurationStatuses(GetDeviceConfigurationStatusesRequest) returns (GetDeviceConfigurationStatusesResponse) {
    option (google.api.http) = {
      get: "/device/api/v1/device/{id}/configuration_statuses",
    };
  }
  // Метод изменения статуса конфигурации устройства.
  // Метод доступен для: admin, service
  rpc PostDeviceConfigurationStatus(PostDeviceConfigurationStatusRequest) returns (PostDeviceConfigurationStatusResponse) {
    option (google.api.http) = {
      post: "/device/api/v1/device/configuration_status",
      body: "*"
    };
  }
  // Метод получения списка конфигураций сгруппированных по устройствам.
  // Метод доступен для: admin, service
  rpc GetDeviceConfigurationStatusGroupedList(GetDeviceConfigurationStatusGroupedListRequest) returns (stream GetDeviceConfigurationStatusGroupedListResponse) {
    option (google.api.http) = {
      get: "/device/api/v1/device/configuration_status/grouped/list"
    };
  }
  // Метод получения количества конфигураций сгруппированных по устройствам.
  // Метод доступен для: admin, service
  rpc GetDeviceConfigurationStatusGroupedCount(GetDeviceConfigurationStatusGroupedCountRequest) returns (GetDeviceConfigurationStatusGroupedCountResponse) {
    option (google.api.http) = {
      get: "/device/api/v1/device/configuration_status/grouped/count"
    };
  }
  // Метод удаления устройства.
  // Метод доступен для: admin, service
  rpc DeleteDevice(DeleteDeviceRequest) returns (DeleteDeviceResponse) {
    option (google.api.http) = {
      delete: "/device/api/v1/device/{id}"
    };
  }
  // Метод получаения упрощенного устройства.
  // Метод доступен для: admin, service, owner, employee, bti, ltp_first.
  // Метод доступен для: ApiKey
  rpc GetDeviceLite(GetDeviceLiteRequest) returns (GetDeviceLiteResponse) {
    option (google.api.http) = {
      get: "/device/api/v1/device_lite/{id}"
    };
  }
}

// Устройство.
// # Описание модели
message Device {
  // Идентификатор.
  // # Диапазон: 0..2147483647
  int32 id = 1;
  // Идентификатор пресета.
  // # Диапазон: 1..2147483647
  int32 preset_id = 2 [(google.api.field_behavior) = REQUIRED];
  // Справочник статусов установки пресета.
  // # Тип: byte
  enum PresetStatusType {
    option deprecated = true;
    option (google.api.enum_visibility).restriction = "DEPRECATED";
    // Значение не указано
    PRESET_STATUS_TYPE_UNKNOWN = 0 [deprecated = true, (google.api.value_visibility).restriction = "DEPRECATED"];
    // Устанавливается
    PROCESSING = 1 [deprecated = true, (google.api.value_visibility).restriction = "DEPRECATED"];
    // Установлен
    SUCCESS = 2 [deprecated = true, (google.api.value_visibility).restriction = "DEPRECATED"];
    // Ошибка
    ERROR = 3 [deprecated = true, (google.api.value_visibility).restriction = "DEPRECATED"];
  }
  // Статус установки пресета.
  // # Поле вычисляется в коде приложения
  PresetStatusType preset_status_type = 3 [(google.api.field_behavior) = OUTPUT_ONLY, deprecated = true, (google.api.field_visibility).restriction = "DEPRECATED"];
  // Дата установки пресета на устройство.
  // # Тип: DateTime
  google.protobuf.Timestamp preset_configured_at = 4 [(google.api.field_behavior) = OUTPUT_ONLY, deprecated = true, (google.api.field_visibility).restriction = "DEPRECATED"];
  // Настройка режима SL3
  bool is_sl3_mode_enabled = 5 [(google.api.field_behavior) = REQUIRED, deprecated = true, (google.api.field_visibility).restriction = "DEPRECATED"];
  // Справочник назначений типов устройств (в качестве чего выступает устройство).
  // # Тип: byte
  enum Type {
    // Значение не указано
    TYPE_UNKNOWN = 0;
    // Домофон
    INTERCOM = 1;
    // Видеокамера
    VIDEOCAMERA = 2 [deprecated = true, (google.api.value_visibility).restriction = "DEPRECATED"];
    // Шлагбаум
    BARRIER = 3;
    // Калитка
    GATE = 4;
    // СКУД
    ACCESS_CONTROL_PANEL = 5 [deprecated = true, (google.api.value_visibility).restriction = "DEPRECATED"];
    // Наружняя видеокамера
    OUTDOOR_CAMERA = 6 [deprecated = true, (google.api.value_visibility).restriction = "DEPRECATED"];
  }
  // Тип назначения устройства
  Type type = 6 [(google.api.field_behavior) = REQUIRED];
  // MAC-адрес.
  // # Диапазон: 17..17.
  // # Паттерн: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
  string mac_address = 7 [(google.api.field_behavior) = REQUIRED];
  // Наименование устройства.
  // # Диапазон: 3..256
  string title = 8 [(google.api.field_behavior) = REQUIRED];
  // Модель устройства.
  // # Тип: byte
  enum ModelType {
    // Значение не указано
    MODEL_TYPE_UNKNOWN = 0;
    // Модель RODOS-8
    RODOS8 = 1;
    // Модель Beward
    BEWARD = 2;
    // Модель QTECH
    QTECH = 3;
    // Модель Натекс
    NATEKS = 4;
    // Модель ТНБ
    TNB = 5;
    // Модель Maxet Line
    MAXETLINE = 6;
    // Модель Двойная открывашка
    TNB_DO2 = 7;
    // Модель Beward DS86017CP
    BEWARD_DS86017CP = 8;
    // Модель Beward DS85006MP
    BEWARD_DS85006MP = 9;
    // Модель Dahua DHI-VTO2101E-P
    DAHUA_VTO2101E_P = 10;
    // Модель Hikvision DS-KV8155-IM
    HIKVISION_DS_KV8155_IM = 11;
    // Модель RODOS-8-2
    RODOS8_2 = 12;
    // Модель Akuvox R29C
    AKUVOX_R29C = 13;
    // Модель Safe-logic
    SAFE_LOGIC = 14;
    // Модель Beward DS86006AP
    BEWARD_DS86006AP = 15;
    // Модель Спутник Ио
    SPUTNIK_IO = 16;
    // Модель Beward c FR
    BEWARD_FR = 17;
    // Модель QTECH с FR
    QTECH_FR = 18;
    // Модель Eltex IPA-ER-10
    ELTEX_IPA_ER_010 = 19;
    // Модель Beward с новым API ключей
    BEWARD_MIFARE = 20;
    // Модель BAS-IP AA-12FB
    BAS_IP_AA_12FB = 21;
    // Модель Akuvox X915S
    AKUVOX_X915S = 22;
    // Модель Rubetek RV-3434
    RUBETEK_RV_3434 = 23;
    // Модель Сокол плюс
    SOKOL_PLUS = 24;
    // Модель Beward Эконом
    BEWARD_LOW_COST = 25;
  }
  // Модель устройства
  ModelType model_type = 9 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор компании владельца.
  // # Диапазон: 1..2147483647
  int32 owner_company_id = 10 [(google.api.field_behavior) = REQUIRED];
  // Серийный номер.
  // # Диапазон: 1..16
  string serial_number = 11 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор квартирограммы.
  // # Диапазон: 1..2147483647
  int32 flatgramm_id = 12 [(google.api.field_behavior) = REQUIRED];
  // Справочник статусов устройства.
  // # Тип: byte
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // Не в сети
    OFFLINE = 1;
    // В сети
    ONLINE = 2;
  }
  // Смещение таймзоны в минутах.
  // # Диапазон: -720..840
  int32 utc_offset = 13 [(google.api.field_behavior) = REQUIRED];
  // Статус устройства
  StatusType status_type = 14 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Сетевой адрес.
  // # Диапазон: 0..250
  google.protobuf.StringValue ip_address = 15;
  // Сетевой порт.
  // # Диапазон: 0..65535
  google.protobuf.Int32Value port = 16;
  // Учетные данные.
  // Используется для устройств с типом модели SPUTNIK_IO
  message SputnikCredentials {
    // Логин.
    // # Тип: Guid
    string login = 1 [(google.api.field_behavior) = REQUIRED];
    // Пароль.
    // На чтение выводится только для пользователя с типом service
    google.protobuf.StringValue password = 2;
  }
  // Учетные данные.
  // Используется для устройств с типом модели SPUTNIK_IO
  SputnikCredentials sputnik_credentials = 17;
  // Координаты
  message Location {
    // Широта
    float latitude = 1 [(google.api.field_behavior) = REQUIRED];
    // Долгота
    float longitude = 2 [(google.api.field_behavior) = REQUIRED];
  }
  // Координаты
  Location location = 18;
  // Идентификатор камеры uid.
  // # Тип: Guid
  google.protobuf.StringValue camera_id = 19;
  // Список тегов устройства.
  // # Диапазон: 1..50
  repeated string tags = 20;
  // Настройки устройства
  message Settings {
    // Настройки ККМ.
    // Коммутатор координатно-матричный (устройство для подключения аналоговых трубок к домофону)
    message CoordinateMatrixSwitch {
      // Состояние
      bool is_enabled = 1 [(google.api.field_behavior) = REQUIRED];
    }
    // Настройки ККМ
    CoordinateMatrixSwitch coordinate_matrix_switch = 1;
    // Настройки вызова консьержа
    message ConciergeCall {
      // Статус настройки вызова консьержа
      bool is_enabled = 1 [(google.api.field_behavior) = REQUIRED];
      // Идентификатор ОРПОН
      int64 orpon = 2 [(google.api.field_behavior) = REQUIRED];
      // Номер квартиры.
      // # Диапазон: 1..5
      string room_number = 3 [(google.api.field_behavior) = REQUIRED];
      // Номер сип-трубки
      string sip_number = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
    }
    // Настройки вызова консьержа.
    // Требуется капабилити CONCIERGE_CALL
    ConciergeCall concierge_call = 2;
    // Настройки автосбора
    message Autocollect {
      // Статус настройки автосбора
      bool is_enabled = 1 [(google.api.field_behavior) = REQUIRED];
    }
    // Настройки автосбора
    Autocollect autocollect = 3;
    // Настройки распознования лиц
    message FaceRecognition {
      // Статус настройки
      bool is_enabled = 1 [(google.api.field_behavior) = REQUIRED];
    }
    // Настройки распознования лиц
    FaceRecognition face_recognition = 4;
    // Настройки режима SL3
    message Sl3Mode {
      // Статус настройки
      bool is_enabled = 1 [(google.api.field_behavior) = REQUIRED];
      // Идентификатор профиля шифрования
      google.protobuf.StringValue encryption_profile_id = 2;
    }
    // Настройки режима SL3
    Sl3Mode sl3_mode = 5;
    // Настройки вызова экстренной службы.
    // Только для устройств с CapabilityType=EMERGENCY_CALL
    message EmergencyCall {
      // Возможность вызова экстренной службы
      bool is_call_available = 1 [(google.api.field_behavior) = REQUIRED];
      // АБС-номер экстренной службы.
      // # Паттерн: /^\+[1-9][0-9]{10}$/
      string emergency_number = 2 [(google.api.field_behavior) = REQUIRED];
    }
    // Настройки вызова экстренной службы.
    // Только для устройств с CapabilityType=EMERGENCY_CALL
    EmergencyCall emergency_call = 6;
  }
  // Настройки устройства
  Settings settings = 21;
  // Версия аппаратного обеспенения
  string hardware_version = 22 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Версия программного обеспенения
  string software_version = 23 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Диспетчеризации
  message Dispatching {
    // Статус настройки диспетчеризации
    bool is_enabled = 1 [(google.api.field_behavior) = REQUIRED];
    // Публичный номер.
    // # Паттерн: /^[1-9]\d{3,7}$/
    google.protobuf.StringValue public_identity = 2;
  }
  // Диспетчеризации
  Dispatching dispatching = 24;
  // Транк.
  // Параметры для соединения между устрйоством и телефонной сетью общего пользования.
  // Требуется капабилити SIP_CALLS
  message SipTrunk {
    // ABC-номер.
    // # Паттерн: /^(\+7)(\d{10})$/
    string abc_number = 1 [(google.api.field_behavior) = REQUIRED];
    // Хост.
    // # Диапазон: 0..250
    google.protobuf.StringValue host = 2;
    // Порт.
    // # Диапазон: 0..65535
    google.protobuf.Int32Value port = 3;
    // Тип сети связи.
    // # Тип: byte
    enum SipType {
      // Значение не указано
      SIP_TYPE_UNKNOWN = 0;
      // Тип Viprtual IP Multimedia Subsystem
      VIMS = 1;
      // Тип Next Generation Networks
      NGN = 2;
    }
    // Тип сети связи
    SipType sip_type = 4 [(google.api.field_behavior) = REQUIRED];
  }
  // Транк
  SipTrunk sip_trunk = 25;
  // Переадресация.
  // Требуется капабилити SIP_CALLS
  message Redirect {
    // Переадресация на SIP
    bool is_enabled_sip = 1 [(google.api.field_behavior) = REQUIRED];
    // Переадресация на телефон
    bool is_enabled_phone = 2 [(google.api.field_behavior) = REQUIRED];
  }
  // Переадресация
  Redirect redirect = 26;
  // Настройки автозамены пароля
  message AutochangePasswordSettings {
    // Статус настройки автозамены пароля
    bool is_enabled = 1 [(google.api.field_behavior) = REQUIRED];
  }
  // Настройки автозамены пароля
  AutochangePasswordSettings autochange_password_settings = 27;
  // Учетные данные пользователей
  message Credentials {
    // Тип доступа пользователя.
    // # Тип: byte
    enum UserAccessType {
      // Значение не указано
      USER_ACCESS_TYPE_UNKNOWN = 0;
      // Доступ к api
      API = 1;
      // Доступ к web-интерфейсу
      WEB = 2;
      // Доступ к rtsp-потоку
      RTSP = 3;
      // Полный доступ
      SU = 4;
    }
    // Логин.
    // # Диапазон: 0..100
    google.protobuf.StringValue login = 1;
    // Пароль.
    // # Диапазон: 0..100
    google.protobuf.StringValue password = 2;
    // Тип доступа пользователя
    UserAccessType user_access_type = 3;
  }
  // Учетные данные пользователей
  repeated Credentials credentials = 28 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Сип-аккаунт
  google.protobuf.StringValue sip_account = 29 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Статус синхронизации
  SyncStatus sync_status = 30 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Ошибка сохранения.
  // Эти проверки выполняются при работе с базой данных и сторонними сервисами
  message SavingError {
    // Переданный мак-адрес не валидный
    message MacAddressInvalid {}
    // Переданный серийный номер не валидный
    message SerialNumberInvalid {}
    // Нельзя изменить тип назначения девайса
    message NotAllowedForType {}
    // Нельзя изменить модель девайса
    message NotAllowedForModel {}
    // Серийный номер для данной модели уже существует на платформе
    message SerialNumberForModelIsExist {}
    // MAC-адрес уже существует на платформе
    message MacAddressIsExist {}
    // Функциональность не поддерживается моделью устройства
    message CapabilityIsNotSupported {
      // Возможность
      keyapis.device.v1.Model.CapabilityType model_capability_type = 1;
    }
    // ABC-номер присвоен другому устройству
    message AbcNumberIsExistOnAnotherDevice {
      // Идентификатор устройства на котором находится ABC-номер
      int32 device_id = 1 [(google.api.field_behavior) = REQUIRED];
    }
    // Публичный номер уже существует на платформе
    message PublicIdentityIsExist {}
    // Не найдена квартира для консьержа
    message ConciergeRoomNotFound {}
    // Логин уже существует на платформе
    message LoginIsExist {}
    // Отсутствуют реквизиты для модели "Спутник"
    message CredentialsAreRequired {}
    // Переданное поле не поддерживается
    message FieldIsNotSupported {}

    // Причина ошибки
    oneof reason {
      // Переданный мак-адрес не валидный
      MacAddressInvalid mac_address_invalid = 1 [deprecated = true];
      // Переданный серийный номер не валидный
      SerialNumberInvalid serial_number_invalid = 2 [deprecated = true];
      // Нельзя изменить тип назначения девайса
      NotAllowedForType not_allowed_for_type = 3;
      // Нельзя изменить модель девайса
      NotAllowedForModel not_allowed_for_model = 4;
      // Серийный номер для данной модели уже существует на платформе
      SerialNumberForModelIsExist serial_number_for_model_is_exist = 5;
      // MAC-адрес уже существует на платформе
      MacAddressIsExist mac_address_is_exist = 6;
      // Настройка не поддерживается
      CapabilityIsNotSupported capability_is_not_supported = 7;
      // ABC-номер присвоен другому устройству
      AbcNumberIsExistOnAnotherDevice abc_number_is_exist_on_another_device = 8;
      // Публичный номер уже существует на платформе
      PublicIdentityIsExist public_identity_is_exist = 9;
      // Не найдена квартира для консьержа
      ConciergeRoomNotFound concierge_room_not_found = 10;
      // Логин уже существует на платформе
      LoginIsExist login_is_exist = 11;
      // Отсутствуют реквизиты для модели "Спутник"
      CredentialsAreRequired credentials_are_required = 12;
      // Переданное поле не поддерживается
      FieldIsNotSupported field_is_not_supported = 13;
    }
  }
}

// Облегчённое устройство.
// # Описание модели
message DeviceLite {
  // Идентификатор.
  // # Диапазон: 0..2147483647
  int32 id = 1;
  // Тип назначения устройства
  Device.Type type = 2 [(google.api.field_behavior) = REQUIRED];
  // # Диапазон: 3..256
  string title = 3 [(google.api.field_behavior) = REQUIRED];
  // Координаты
  Device.Location location = 4;
  // Статус устройства
  Device.StatusType status_type = 5;
}

// Статус конфигурации устройства.
// # Описание модели
message DeviceConfigurationStatus {
  // Идентификатор
  int32 id = 1;
  // Идентификатор устройства
  int32 device_id = 2 [(google.api.field_behavior) = REQUIRED];
  // Тип конфигурации.
  // # Тип: byte
  enum ConfigurationType {
    // Значение не указано
    CONFIGURATION_TYPE_UNKNOWN = 0;
    // Пресет
    PRESET = 1;
    // Сип-аккаунт
    SIP_ACCOUNT = 2;
    // сип-номера в помещениях
    SIP_ROOMS = 3;
    // Калитка
    GATE = 4;
    // Ключи
    RFIDS = 5;
    // Коды
    CODES = 6;
    // Распознование лиц
    FACE_RECOGNITION = 7;
    // Консьерж
    CONCIERGE = 8;
    // Автосбор
    AUTOCOLLECT = 9;
    // Режим Sl3
    SL3 = 10;
    // Вызов экстренной службы
    EMERGENCY_CALL = 11;
  }
  // Тип конфигурации
  ConfigurationType configuration_type = 3 [(google.api.field_behavior) = REQUIRED];
  // Справочник статусов конфигурации настройки устройства.
  // # Тип: byte
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // Настроен
    SUCCESS = 1;
    // Ошибка
    ERROR = 2;
    // В ожидании обработки
    PENDING = 3;
    // В процессе обработки
    PROCESSING = 4;
  }
  // Статус конфигурации настройки устройства
  StatusType status_type = 4 [(google.api.field_behavior) = REQUIRED];
  // Дата последней конфигурации устройства.
  // # Тип: DateTime
  google.protobuf.Timestamp configured_at = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Текст ошибки
  google.protobuf.StringValue error_message = 6;
  // Количество попыток
  int32 retry_count = 7 [(google.api.field_behavior) = REQUIRED];
  // Дополнительная полезная нагрузка
  message Payload {
    // Автоколлект
    message Autocollect {
      // Дата включения автосбора.
      // # Тип: DateTime
      google.protobuf.Timestamp enabled_at = 1;
      // Дата отключения автосбора.
      // # Тип: DateTime
      google.protobuf.Timestamp to_be_disabled_at = 2;
    }
    // Атрибут
    oneof attribute {
      // Автоколлект
      Autocollect autocollect = 1;
    }
  }
  // Дополнительная полезная нагрузка
  Payload payload = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Минимально возможная дата выполнения следующей попытки.
  // # Тип: DateTime
  google.protobuf.Timestamp next_retry_at = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Сгруппированный по устройству список конфигураций
message DeviceConfigurationStatusGrouped {
  // Идентификатор устройства
  int32 device_id = 1 [(google.api.field_behavior) = REQUIRED];
  // Список конфигураций
  repeated DeviceConfigurationStatus statuses = 2 [(google.api.field_behavior) = REQUIRED];
}

// Статус камеры.
// # Описание модели
message CameraStatus {
  // Идентификатор камеры uid.
  // # Тип: Guid
  google.protobuf.StringValue id = 1;
  // Статус камеры.
  // # Тип: byte
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // В процессе регистрации
    PROCESSING = 1;
    // Ошибка регистрации
    PROCESSING_ERROR = 2;
    // Активна
    ACTIVE = 3;
  }
  // Статус камеры
  StatusType status_type = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Сообщение об ошибке
  string error_message = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Статус синхронизации.
// # Описание модели
message SyncStatus {
  // Статус синхронизации.
  // # Тип: byte
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // Новый
    NEW = 1;
    // В процессе
    PENDING = 2;
    // Ошибка
    ERROR = 3;
    // Успешно
    SUCCESS = 4;
    // Выключено
    DISABLED = 5;
  }
  // Статус синхронизации
  StatusType status_type = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Сообщение об ошибке
  string error_message = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Количество попыток
  int32 retry_count = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата последней успешной синхронизации.
  // # Тип: DateTime
  google.protobuf.Timestamp successful_at = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата последней синхронизации.
  // # Тип: DateTime
  google.protobuf.Timestamp sync_at = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Запрос получения устройства
message GetDeviceRequest {
  // Идентификатор
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос получения устройства
message GetDeviceResponse {
  // Тип результата
  oneof type {
    // Устройство
    Device data = 1;
  }
}

// Запрос получения устройства
message GetDeviceLiteRequest {
  // Идентификатор
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос получения устройства
message GetDeviceLiteResponse {
  // Тип результата
  oneof type {
    // Устройство
    DeviceLite data = 1;
  }
}

// Запрос на создание/изменение устройства
message PostDeviceRequest {
  // Устройство
  Device data = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос на создание/изменение устройства
message PostDeviceResponse {
  // Ошибка запроса сохранения устройства
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
      // Ошибка сохранения
      Device.SavingError saving = 2;
    }
  }
  // Тип ответа
  oneof type {
    // Устройство
    Device data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения списка устройств
message GetDeviceListRequest {
  // Фильтр
  DeviceFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Пагинация
    DevicePaging paging = 2;
  }
}

// Ответ на запрос получения списка устройств
message GetDeviceListResponse {
  // Ошибка запроса на получение списка устройств
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Устройство
    Device data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения количества устройств
message GetDeviceCountRequest {
  // Фильтр
  DeviceFilter filter = 1;
}

// Ответ на запрос получения количества устройств
message GetDeviceCountResponse {
  // Ошибка
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Количество
    int32 data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос изменения устройства
message PutDeviceRequest {
  // Идентификатор устройства
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор пресета
  int32 preset_id = 2 [(google.api.field_behavior) = OPTIONAL];
  // Настройка режима SL3
  bool is_sl3_mode_enabled = 3 [(google.api.field_behavior) = OPTIONAL];
}

//ответ на завпрос изменения устройства
message PutDeviceResponse {
  // Тип результата
  oneof type {
    // Устройство
    Device data = 1;
  }
}

// Запрос установки пресета на устройство
message PostDeviceInstallPresetRequest {
  // Идентификатор
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос установки пресета на устройство
message PostDeviceInstallPresetResponse {
  // Ошибка при установке пресета
  message Error {
    // Пресет в процессе установки
    message PresetStatusIsProcessing {}
    // Причина ошибки
    oneof reason {
      // Пресет в процессе установки
      PresetStatusIsProcessing preset_status_is_processing = 1;
    }
  }
  //Тип ответа
  oneof type {
    //Ошибка при установке пресета
    Error error = 1;
  }
}

// Запрос на замену устройства
message PostDeviceReplaceRequest {
  // Идентификатор устройства
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
  // Хост
  string host = 2;
  // MAC-адрес.
  // # Диапазон: 17..17.
  // # Паттерн: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
  string mac_address = 3 [(google.api.field_behavior) = REQUIRED];
  // Серийный номер
  string serial_number = 4 [(google.api.field_behavior) = REQUIRED];
  // Логин (для модели спутник)
  string login = 5;
}

// Ответ на запрос на замену устройства
message PostDeviceReplaceResponse {
  // Ошибка замены устройства
  message Error {
    // На платформе уже существует устройство с таким хостом
    message HostExists {}
    // На платформе уже существует устройство с таким MAC-адресом
    message MacAddressExists {}
    // На платформе уже существует устройство с таким серийным номером
    message SerialNumberExists {}
    // На платформе уже существует устройство с таким логином (для устройст модели "Спутник")
    message LoginExists {}
    // Отсутствует поле Login для модели "Спутник"
    message LoginIsRequired {}

    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation_error = 1;
      // На платформе уже существует устройство с таким хостом
      HostExists host_exists = 2;
      // На платформе уже существует устройство с таким MAC-адресом
      MacAddressExists mac_address_exists = 3;
      // На платформе уже существует устройство с таким серийным номером
      SerialNumberExists serial_number_exists = 4;
      // На платформе уже существует устройство с таким логином (для устройст модели "Спутник")
      LoginExists login_exists = 5;
      // Отсутствует поле Login для модели "Спутник"
      LoginIsRequired login_is_required = 6;
      // Ошибка реинстала
      ReinstallError reinstall_error = 7;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка замены устройства
    Error error = 1;
  }
}

// Запрос на переконфигурирование устройства
message PostDeviceReconfigureRequest {
  // Идентификатор устройства
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос на переконфигурирование устройства
message PostDeviceReconfigureResponse {
  // Ошибка переконфигурирования устройства
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation_error = 1;
      // Ошибка реинстала
      ReinstallError reinstall_error = 2;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка переконфигурирования устройства
    Error error = 1;
  }
}

// Запрос получения статусов конфигурации устройства
message GetDeviceConfigurationStatusesRequest {
  // Идентификатор
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос получения статусов конфигурации устройства
message GetDeviceConfigurationStatusesResponse {
  // Статусы
  message Statuses {
    // Статусы конфигурации устройства
    repeated DeviceConfigurationStatus device_configuration_statuses = 1;
    // Статус камеры
    CameraStatus camera_status = 2;
    // Статус синхронизации
    SyncStatus sync_status = 3;
    // Статус устройства
    Device.StatusType device_status_type = 4;
  }
  // Ошибка
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation_error = 1;
    }
  }
  // Тип результата
  oneof type {
    // Устройство
    Statuses data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос на изменение статуса конфигурации устройства
message PostDeviceConfigurationStatusRequest {
  // Статус конфигурации устройства
  DeviceConfigurationStatus data = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос на изменение статуса конфигурации устройства
message PostDeviceConfigurationStatusResponse {
  // Ошибка запроса сохранения статуса конфигурации устройства
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Статус конфигурации устройства
    DeviceConfigurationStatus data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения списка конфигураций сгруппированных по устройству
message GetDeviceConfigurationStatusGroupedListRequest {
  // Фильтр
  DeviceConfigurationStatusGroupedFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Стандартный постраничный вывод
    DeviceConfigurationStatusGroupedPaging paging = 2;
  }
}

// Ответ на запрос получения списка конфигураций сгруппированных по устройству
message GetDeviceConfigurationStatusGroupedListResponse {
  // Ошибка
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Конфигурации устройства
    DeviceConfigurationStatusGrouped data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения количества конфигураций сгруппированных по устройству
message GetDeviceConfigurationStatusGroupedCountRequest {
  // Фильтр
  DeviceConfigurationStatusGroupedFilter filter = 1;
}

// Ответ на запрос получения количества конфигураций сгруппированных по устройству
message GetDeviceConfigurationStatusGroupedCountResponse {
  // Тип результата
  oneof type {
    // Количество
    int32 data = 1;
  }
}

// Запрос удаления устройства
message DeleteDeviceRequest {
  // Идентификатор устройства
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос удаления устройства
message DeleteDeviceResponse {}

// Ошибки реинстала
message ReinstallError {
  // Сип-логин отсутствует на устройстве
  message SipLoginIsMissing {}
  // Причина ошибки
  oneof reason {
    // Сип-логин отсутствует на устройстве
    SipLoginIsMissing sip_login_is_missing = 1;
  }
}

// Фильтр устройств
message DeviceFilter {
  // По идентификаторам компании владельца
  repeated int32 owner_company_ids = 1;
  // Поиск по тексту.
  // Если значение не передано то поиск по нему не производится.
  // # Диапазон: 3..64.
  // # Поиск производится по полям:
  // # - Наименование;
  // # - MAC-адрес;
  // # - Список тегов устройства;
  // # - Сетевой адрес;
  // # - Серийный номер
  google.protobuf.StringValue text = 2;
  // Идентификатор квартирограммы
  repeated int32 flatgramm_ids = 3;
  // Серийный номер
  repeated string serial_numbers = 4;
  // Статус устройства
  repeated Device.StatusType device_status_types = 5;
  // Тип назначения устройства
  repeated Device.Type device_types = 6;
  // Модель устройства
  repeated Device.ModelType device_model_types = 7;
  // Переадресация на консъержа
  google.protobuf.BoolValue is_concierge_enabled = 8;
  // Диспетчеризация
  google.protobuf.BoolValue is_dispatching_enabled = 9;
  // Поиск по публичному номеру диспетчеризации.
  // Если значение не передано то поиск по нему не производится.
  // # Диапазон: 3..64
  google.protobuf.StringValue dispatching_public_number = 10;
  // Версия аппаратного обеспенения.
  // # Диапазон: 3..64
  google.protobuf.StringValue hardware_version = 11;
  // Версия программного обеспенения.
  // # Диапазон: 3..64
  google.protobuf.StringValue software_version = 12;
  // Автозамена пароля
  google.protobuf.BoolValue is_autochange_password_enabled = 13;
  // ABC-номер
  repeated string abc_number = 14;
  // Идентификаторы камер
  repeated string camera_ids = 15;
  // Фильтр по статусу синхронизации (SyncStatus.status_type)
  repeated SyncStatus.StatusType sync_status_status_types = 16;
  // Пороговое значение количества попыток синхронизации.
  // Возвращает записи, у которых sync_retry_count меньше этого значения
  google.protobuf.Int32Value sync_retry_count_less_then = 17;
  // От даты успешной синхронизации включительно (>=)
  google.protobuf.Timestamp begin_sync_successful_at = 18;
  // До даты успешной синхронизации (<)
  google.protobuf.Timestamp end_sync_successful_at = 19;
  // От даты синхронизации включительно (>=)
  google.protobuf.Timestamp begin_sync_at = 20;
  // До даты синхронизации (<)
  google.protobuf.Timestamp end_sync_at = 21;
}

// Постраничный вывод
message DevicePaging {
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По идентификатору
    ID = 1;
    // По наименованию
    TITLE = 2;
    // По дате последней попытки синхронизации
    SYNC_AT = 3;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию.
  // # По умолчанию: ID
  OrderByType order_by_type = 1;
  // Справочник типов направлений сортировки.
  // # Тип: byte
  enum DirectionType {
    // Значение не указано
    DIRECTION_TYPE_UNKNOWN = 0;
    // От большего к меньшему
    DESC = 1;
    // От меньшего к большему
    ASC = 2;
  }
  // Тип направления сортировки.
  // # По умолчанию: DESC
  DirectionType direction_type = 2;
  // Количество записей на страницу.
  // Если значение 0 (не передано), то будет взято значение по умолчанию.
  // # Диапазон: 0..100.
  // # По умолчанию: 20
  int32 limit = 3;
  // Сдвиг.
  // # Диапазон: 0..2147483647
  int32 offset = 4;
}

// Фильтр конфигураций сгруппированных по устройству
message DeviceConfigurationStatusGroupedFilter {
  // По идентификаторам устройства
  repeated int32 device_ids = 1;
  // По типам конфигурации
  repeated DeviceConfigurationStatus.ConfigurationType configuration_types = 2;
  // По статусам конфигурации настройки
  repeated DeviceConfigurationStatus.StatusType status_types = 3;
  // Флаг, указывающий на готовность настройки к конфигурированию.
  // Значение next_retry_at меньше текущей даты
  google.protobuf.BoolValue is_ready_for_retry = 4;
  // Пороговое значение количества попыток.
  // Возвращает записи, у которых retry_count меньше этого значения
  google.protobuf.Int32Value retry_count_less_then = 5;
}

// Постраничный вывод конфигураций сгруппированных по устройству
message DeviceConfigurationStatusGroupedPaging {
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По идентификатору устройства
    DEVICE_ID = 1;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию.
  // # По умолчанию: DEVICE_ID
  OrderByType order_by_type = 1;
  // Справочник типов направлений сортировки.
  // # Тип: byte
  enum DirectionType {
    // Значение не указано
    DIRECTION_TYPE_UNKNOWN = 0;
    // От большего к меньшему
    DESC = 1;
    // От меньшего к большему
    ASC = 2;
  }
  // Тип направления сортировки.
  // # По умолчанию: DESC
  DirectionType direction_type = 2;
  // Количество записей на страницу.
  // Если значение 0 (не передано), то будет взято значение по умолчанию.
  // # Диапазон: 0..1000.
  // # По умолчанию: 20
  int32 limit = 3;
  // Сдвиг.
  // # Диапазон: 0..2147483647
  int32 offset = 4;
}

// Ошибки валидации.
// Эти проверки выполняются до обращения в базу данных
message ValidationError {
  // Путь к полю в формате наименования прото
  string path = 1 [(google.api.field_behavior) = REQUIRED];
  // Валидационное сообщение
  string message = 2 [(google.api.field_behavior) = REQUIRED];
}

// Пресет.
// Пресет с id=1 устанавливается при создании устройства по умолчанию
message Preset {
  // Идентификатор.
  // # Диапазон: 1..2147483647
  int32 id = 1;
  // Наименование.
  // # Диапазон: 3..256
  string title = 2 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор МРФ.
  // # Диапазон: 0..10
  repeated int32 mrf_ids = 3 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор РФ.
  // # Диапазон: 0..100
  repeated int32 rf_ids = 4 [(google.api.field_behavior) = REQUIRED];
  // Описание.
  // # Диапазон: 3..1024
  google.protobuf.StringValue description = 5 [(google.api.field_behavior) = OPTIONAL];
  // Дата и время создания.
  // # Тип: DateTime
  google.protobuf.Timestamp created_at = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата последнего изменения.
  // Заполняется и обновляется сервером.
  // Заполняется при создании и изменении.
  // Является версией объекта.
  // # Тип: DateTime
  google.protobuf.Timestamp changed_at = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Справочник статусов.
  // # Тип: byte
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // Активный
    ACTIVE = 1;
    // Архивный
    ARCHIVE = 2;
  }
  // Статус
  StatusType status_type = 8 [(google.api.field_behavior) = REQUIRED];
  // Параметр SIP
  message Sip {
    // Хост.
    // # Диапазон: 5..256
    string host = 1 [(google.api.field_behavior) = REQUIRED];
    // Порт.
    // # Диапазон: 1..65536
    int32 port = 2 [(google.api.field_behavior) = REQUIRED];
    // Хост reg.
    // # Диапазон: 5..256
    string reg_host = 3 [(google.api.field_behavior) = REQUIRED];
    // Порт reg.
    // # Диапазон: 1..65536
    int32 reg_port = 4 [(google.api.field_behavior) = REQUIRED];
    // Хост proxy.
    // # Диапазон: 5..256
    string proxy_host = 5 [(google.api.field_behavior) = REQUIRED];
    // Порт proxy.
    // # Диапазон: 1..65536
    int32 proxy_port = 6 [(google.api.field_behavior) = REQUIRED];
  }
  // Параметр SIP
  Sip sip = 9 [(google.api.field_behavior) = REQUIRED];
  // Параметр NTP
  message Ntp {
    // Хост.
    // # Диапазон: 5..256
    string host = 1 [(google.api.field_behavior) = REQUIRED];
    // Порт.
    // # Диапазон: 1..65536
    int32 port = 2 [(google.api.field_behavior) = REQUIRED];
  }
  // Параметр NTP
  Ntp ntp = 10 [(google.api.field_behavior) = REQUIRED];
  // Параметр Syslog
  message Syslog {
    // Хост.
    // # Диапазон: 5..256
    string host = 1 [(google.api.field_behavior) = REQUIRED];
    // Порт.
    // # Диапазон: 1..65536
    int32 port = 2 [(google.api.field_behavior) = REQUIRED];
    // Тип протокола.
    // # Тип: byte
    enum ProtocolType {
      // Значение не указано
      PROTOCOL_TYPE_UNKNOWN = 0;
      // Протокол UDP
      UDP = 1;
      // Протокол TCP
      TCP = 2;
    }
    // Протокол
    ProtocolType protocol_type = 3 [(google.api.field_behavior) = REQUIRED];
  }
  // Параметр Syslog
  Syslog syslog = 11 [(google.api.field_behavior) = REQUIRED];
  // Помещение
  message Room {
    // Номер телефона.
    // # Диапазон: 5..14
    string phone = 1 [(google.api.field_behavior) = REQUIRED];
    // Номер помещения.
    // # Диапазон: 1..10000
    int32 num = 2 [(google.api.field_behavior) = REQUIRED];
  }
  // Помещения.
  // # Диапазон: 0..10000
  repeated Room rooms = 12 [(google.api.field_behavior) = REQUIRED];
  // Параметры конфигурации видео
  message VideoConfig {
    // Справочник качеств.
    // # Тип: byte
    enum QualityType {
      // Значение не указано
      QUALITY_TYPE_UNKNOWN = 0;
      // Высокое качество
      HIGH = 1;
      // Среднее качество
      MEDIUM = 2;
    }
    // Тип пресета
    QualityType quality_type = 1 [(google.api.field_behavior) = REQUIRED];
    // Пользователь
    message RtspUser {
      // Имя пользователя.
      // # Диапазон: 3..256
      string username = 1 [(google.api.field_behavior) = REQUIRED];
      // Пароль.
      // # Диапазон: 3..256
      string password = 2 [(google.api.field_behavior) = REQUIRED];
    }
    // Пользователь
    RtspUser rtsp_user = 2 [(google.api.field_behavior) = REQUIRED];
  }
  // Параметры конфигурации видео
  VideoConfig video_config = 13 [(google.api.field_behavior) = REQUIRED];
  // Параметр DTMF
  message Dtmf {
    // Код.
    // # Диапазон: 1..1
    string code = 1 [(google.api.field_behavior) = REQUIRED];
    // Индекс реле.
    // # Диапазон: 0..64
    int32 relay_index = 2;
  }
  // Параметр DTMF.
  // # Диапазон: 0..64
  repeated Dtmf dtmf = 14 [(google.api.field_behavior) = REQUIRED];
  // Распознование лиц
  message FaceRecognition {
    // Адрес
    string host = 1 [(google.api.field_behavior) = REQUIRED];
    // Альтернативный адрес
    string alt_host = 2;
    // Путь запроса к серверу
    string endpoint = 3 [(google.api.field_behavior) = REQUIRED];
    // Токен
    string auth_token = 4 [(google.api.field_behavior) = REQUIRED];
    // Тип конфигурации.
    // # Тип: byte
    enum ConfigurationType {
      // Значение не указано
      CONFIGURATION_TYPE_UNKNOWN = 0;
      // По умолчанию
      DEFAULT = 1;
    }
    // Тип конфигурации
    ConfigurationType configuration_type = 5 [(google.api.field_behavior) = REQUIRED];
    // Идентификатор источника в identix
    string origin_id = 6 [(google.api.field_behavior) = REQUIRED];
    // Идентификаторы групп профилей в identix
    repeated int32 group_ids = 7;
  }
  // Распознование лиц
  FaceRecognition face_recognition = 15;
  // Ошибка сохранения.
  // Эти проверки выполняются при работе с базой данных и сторонними сервисами
  message SavingError {
    // Конфликт версий.
    // Причины:
    // - В базе хранится другая версия строки, значения changed_at отличаются
    message Conflict {}

    // Недоступно для дефолтного пресета.
    // Причины:
    // - Смена статуса на Архивный
    message NotAllowedForDefault {}

    // Причина ошибки
    oneof reason {
      // Конфликт версий
      Conflict conflict = 1;
      // Запрещено для дефолтного пресета
      NotAllowedForDefault not_allowed_for_default = 2;
    }
  }
}
