Начало работы с Fleet Engine,Начало работы с Fleet Engine

API Fleet Engine On-demand Rides and Delivery позволяет управлять поездками и состоянием транспортных средств для приложений «Поездки и ход заказа». Он обрабатывает транзакции между Driver SDK, Consumer SDK и вашей серверной службой, которая может взаимодействовать с Fleet Engine, выполняя вызовы gRPC или REST .

Предварительные условия

При разработке убедитесь, что вы установили Cloud SDK (gcloud) и прошли аутентификацию в своем проекте.

оболочка

gcloud auth login

Вы должны увидеть сообщение об успехе, например:

You are now logged in as [my-user@example.com].
Your current project is [project-id].  You ...

Убедитесь, что API-интерфейсы решения Fleet Engine для поездок и доставки по требованию настроены соответствующим образом.

оболочка

gcloud --project=project-id services enable fleetengine.googleapis.com

Если эта команда приводит к ошибке, обратитесь к администратору проекта и представителю службы поддержки Google, чтобы получить доступ.

Ведение журнала

Fleet Engine может записывать сообщения журнала о полученных вызовах API в журналы платформы Google Cloud . См. документацию по ведению журналов в облаке , чтобы получить общие сведения о том, как читать и анализировать журналы.

Ведение журнала может быть не включено по умолчанию для проектов, созданных до 10 февраля 2022 г. Дополнительные сведения см. в документации по ведению журнала .

Клиентские библиотеки

Мы публикуем клиентские библиотеки на нескольких распространенных языках программирования. Эти библиотеки помогут обеспечить лучший опыт разработки по сравнению с необработанным REST или gRPC. Инструкции о том, как получить клиентские библиотеки для вашего серверного приложения, см. в разделе Клиентские библиотеки .

Примеры Java в этой документации предполагают знакомство с gRPC.

Аутентификация и авторизация

Вы можете настроить возможности, предоставляемые Trip and Order Progress, через Google Cloud Console. Эти API и SDK требуют использования веб-токенов JSON, подписанных с использованием сервисных учетных записей, созданных в Cloud Console.

Настройка облачного проекта

Чтобы настроить облачный проект, сначала создайте проект, а затем создайте учетные записи служб.

Чтобы создать проект Google Cloud:

  1. Создайте проект Google Cloud с помощью Google Cloud Console.
  2. Используя панель API и служб, включите API местных поездок и доставок.

Учетные записи служб связаны с одной или несколькими ролями. Они используются для создания веб-токенов JSON, которые предоставляют разные наборы разрешений в зависимости от ролей. Обычно, чтобы уменьшить вероятность злоупотреблений, вы можете создать несколько учетных записей служб, каждая из которых имеет минимальный набор необходимых ролей.

В разделе «Прогресс поездки и заказа» используются следующие роли:

Роль Описание
Пользователь Fleet Engine Consumer SDK

roles/fleetengine.consumerSdkUser
Предоставляет разрешение на поиск транспортных средств и получение информации о транспортных средствах и поездках. Токены, созданные учетной записью службы с этой ролью, обычно используются с мобильных устройств вашего приложения для совместного использования поездок или доставки.
Пользователь SDK драйвера Fleet Engine

roles/fleetengine.driverSdkUser
Предоставляет разрешение на обновление местоположений и маршрутов транспортных средств, а также на получение информации о транспортных средствах и поездках. Токены, созданные учетной записью службы с этой ролью, обычно используются с мобильных устройств вашего приложения для совместного использования поездок или доставки.
Суперпользователь службы двигателей флота

roles/fleetengine.serviceSuperUser
Предоставляет разрешение всем API транспортных средств и поездок. Токены, созданные учетной записью службы с этой ролью, обычно используются с ваших внутренних серверов.

Например, создайте учетную запись службы для каждой из трех ролей и назначьте им соответствующие роли.

gcloud --project=project-id iam service-accounts create fleet-engine-consumer-sdk
gcloud projects add-iam-policy-binding project-id \
       --member=serviceAccount:fleet-engine-consumer-sdk@project-id.iam.gserviceaccount.com \
       --role=roles/fleetengine.consumerSdkUser

gcloud --project=project-id iam service-accounts create fleet-engine-driver-sdk
gcloud projects add-iam-policy-binding project-id \
       --member=serviceAccount:fleet-engine-driver-sdk@project-id.iam.gserviceaccount.com \
       --role=roles/fleetengine.driverSdkUser

gcloud --project=project-id iam service-accounts create fleet-engine-su
gcloud projects add-iam-policy-binding project-id \
       --member=serviceAccount:fleet-engine-su@project-id.iam.gserviceaccount.com \
       --role=roles/fleetengine.serviceSuperUser

SDK для драйверов и потребителей построены на основе этих стандартных ролей.

В качестве альтернативы можно создавать собственные роли, которые позволяют объединять произвольный набор разрешений. Пакеты SDK для драйверов и потребителей будут отображать сообщения об ошибках всякий раз, когда отсутствует необходимое разрешение. В связи с этим мы настоятельно рекомендуем использовать стандартный набор ролей, представленный выше, а не использовать собственные роли.

Для удобства, если вам нужно создать токены JWT для ненадежных клиентов, добавление пользователей в роль создателя токенов сервисной учетной записи позволяет им создавать токены с помощью инструментов командной строки gcloud .

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

Где my-user@example.com — это адрес электронной почты, используемый для аутентификации в gcloud ( gcloud auth list --format='value(account)' ).

Библиотека аутентификации Fleet Engine

Fleet Engine использует веб-токены JSON (JWT) для ограничения доступа к API Fleet Engine. Новая библиотека аутентификации Fleet Engine, доступная на Github , упрощает создание JWT Fleet Engine и надежно подписывает их.

Библиотека предоставляет следующие преимущества:

  • Упрощает процесс создания токенов Fleet Engine.
  • Предоставляет механизмы подписи токенов, отличные от использования файлов учетных данных (например, олицетворение учетной записи службы).
  • Прикрепляет подписанные токены к исходящим запросам, сделанным из заглушки gRPC или клиента GAPIC.

Создание веб-токена JSON (JWT) для авторизации

Если библиотека аутентификации Fleet Engine не используется, веб-токены JSON (JWT) необходимо создавать непосредственно в вашей кодовой базе. Это требует от вас глубокого понимания JWT и того, как они связаны с Fleet Engine. Вот почему мы НАСТОЯТЕЛЬНО рекомендуем воспользоваться библиотекой аутентификации Fleet Engine.

В Fleet Engine веб-токены JSON (JWT) обеспечивают кратковременную аутентификацию и гарантируют, что устройства могут изменять только транспортные средства, поездки или задачи, для которых они авторизованы. JWT содержат заголовок и раздел утверждения. Раздел заголовка содержит такую ​​информацию, как используемый закрытый ключ (полученный из учетных записей служб) и алгоритм шифрования. Раздел утверждения содержит такую ​​информацию, как время создания токена, время жизни токена, службы, к которым он претендует на доступ, а также другую информацию об авторизации для ограничения доступа; например, идентификатор транспортного средства.

Раздел заголовка JWT содержит следующие поля:

Поле Описание
Алг Алгоритм использования. `РС256`.
набрать Тип токена. `JWT`.
ребенок Идентификатор закрытого ключа вашего сервисного аккаунта. Вы можете найти это значение в поле `private_key_id` JSON-файла вашего сервисного аккаунта. Обязательно используйте ключ от учетной записи службы с правильным уровнем разрешений.

Раздел утверждений JWT содержит следующие поля:

Поле Описание
это Адрес электронной почты вашей учетной записи службы.
суб Адрес электронной почты вашей учетной записи службы.
аудит SERVICE_NAME вашего сервисного аккаунта, в данном случае https://fleetengine.googleapis.com/.
там Временная метка создания токена, указанная в секундах, прошедших с 00:00:00 UTC 1 января 1970 года. Допустимо отклонение в 10 минут. Если временная метка находится слишком далеко в прошлом или в будущем, сервер может сообщить об ошибке.
опыт Временная метка истечения срока действия токена, указанная в секундах, прошедших с 00:00:00 UTC 1 января 1970 года. Запрос завершается неудачей, если временная метка находится более чем на один час в будущем.
авторизация В зависимости от варианта использования может содержать `vehicleid` или `tripid`.

Создание токена JWT означает его подписание. Инструкции и примеры кода для создания и подписания JWT см. в разделе Авторизация учетной записи службы без OAuth . Затем вы можете прикрепить подписанный токен к вызовам gRPC или другим методам, используемым для доступа к Fleet Engine.

Претензии JWT

При создании полезных данных JWT добавьте дополнительное утверждение в раздел авторизации с ключевым идентификатором vehicleid или tripid , равным значению идентификатора транспортного средства или идентификатора поездки, для которого выполняется вызов.

Driver SDK всегда использует утверждение vehicleid , независимо от того, работаете ли вы в поездке или в транспортном средстве. Серверная часть Fleet Engine гарантирует, что транспортное средство связано с запрошенной поездкой, прежде чем вносить изменения.

Consumer SDK всегда использует утверждение tripid .

Поставщик совместных поездок или доставки должен использовать vehicleid или tripid со знаком «*», чтобы сопоставить все транспортные средства и поездки. Обратите внимание, что JWT может содержать оба токена, даже если это не требуется, что может упростить реализацию подписи токена.

Варианты использования JWT

Ниже показан пример токена для сервера провайдера :

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "private_key_id_of_provider_service_account"
}
.
{
  "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
  "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
  "aud": "https://fleetengine.googleapis.com/",
  "iat": 1511900000,
  "exp": 1511903600,
  "authorization": {
     "vehicleid": "*",
     "tripid": "*"
   }
}

Ниже показан пример токена для потребительского приложения :

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "private_key_id_of_consumer_service_account"
}
.
{
  "iss": "consumer@yourgcpproject.iam.gserviceaccount.com",
  "sub": "consumer@yourgcpproject.iam.gserviceaccount.com",
  "aud": "https://fleetengine.googleapis.com/",
  "iat": 1511900000,
  "exp": 1511903600,
  "authorization": {
     "tripid": "trip_54321"
   }
}

Ниже показан пример токена для приложения Driver :

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "private_key_id_of_driver_service_account"
}
.
{
  "iss": "driver@yourgcpproject.iam.gserviceaccount.com",
  "sub": "driver@yourgcpproject.iam.gserviceaccount.com",
  "aud": "https://fleetengine.googleapis.com/",
  "iat": 1511900000,
  "exp": 1511903600,
  "authorization": {
     "vehicleid": "driver_12345"
   }
}
  • В поле kid в заголовке укажите идентификатор закрытого ключа вашего сервисного аккаунта. Это значение можно найти в поле private_key_id файла JSON вашего сервисного аккаунта.
  • В полях iss и sub укажите адрес электронной почты вашей учетной записи службы. Это значение можно найти в поле client_email JSON-файла вашего сервисного аккаунта.
  • В поле aud укажите https://SERVICE_NAME/ .
  • В поле iat используйте метку времени создания токена, указанную в секундах, прошедших с 00:00:00 UTC 1 января 1970 года. Допустимо отклонение в 10 минут. Если временная метка находится слишком далеко в прошлом или в будущем, сервер может сообщить об ошибке.
  • В поле exp используйте метку времени истечения срока действия токена, указанную в секундах с 00:00:00 UTC 1 января 1970 года. Максимально допустимое значение — iat + 3600.

При подписании JWT для передачи на мобильное устройство обязательно используйте учетную запись службы для роли Driver или Consumer SDK. В противном случае мобильное устройство будет иметь возможность изменять состояние, в котором оно не должно быть.

Аналогично, при подписании JWT, который будет использоваться для привилегированных вызовов, обязательно используйте учетную запись службы с ролью суперпользователя. В противном случае операция завершится неудачей.

Создание JWT для тестирования

Генерация токенов из терминала может быть полезна при тестировании.

Чтобы выполнить эти шаги, ваша учетная запись пользователя должна иметь роль создателя токена учетной записи службы:

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

Создайте новый файл с именем unsigned_token.json и содержимым ниже. Свойство iat — это текущее время в секундах после эпохи, которое можно получить, запустив date +%s в терминале. Свойство exp — это время истечения срока действия в секундах после эпохи, которое можно вычислить, добавив 3600 к iat . Срок действия не может быть более одного часа в будущем.

{
  "aud": "https://fleetengine.googleapis.com/",
  "iss": "super-user-service-account@project-id.iam.gserviceaccount.com",
  "sub": "super-user-service-account@project-id.iam.gserviceaccount.com",
  "iat": iat,
  "exp": exp,
  "authorization": {
     "vehicleid": "*",
     "tripid": "*"
   }
}

Затем выполните следующую команду gcloud, чтобы подписать токен от имени вашей сервисной учетной записи суперпользователя:

gcloud beta iam service-accounts sign-jwt --iam-account=super-user-service-account@project-id.iam.gserviceaccount.com unsigned_token.json signed_token.jwt

Подписанный JWT в кодировке Base64 теперь должен храниться в файле signed_token.jwt . Токен действителен в течение следующего часа.

Теперь вы можете протестировать токен, запустив команду curl для конечной точки REST List Vehicles:

curl -X GET "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles" -H "Authorization: Bearer $(cat signed_token.jwt)"

Транспортные средства и их жизненный цикл

Транспортное средство — это объект, представляющий пару водитель-транспортное средство. В настоящее время водитель и транспортное средство не могут отслеживаться отдельно. Поставщик совместных поездок или доставки создает транспортное средство, используя идентификатор поставщика (который должен совпадать с идентификатором проекта Google Cloud Project, который содержит учетную запись службы, используемую для вызова API Fleet Engine) и идентификатор транспортного средства, принадлежащий поставщику совместных поездок или доставки. .

Транспортное средство, которое не было обновлено через UpdateVehicle в течение семи дней, будет автоматически удалено. Вызов CreateVehicle с парой идентификатора поставщика/идентификатора транспортного средства, которая уже существует, является ошибкой. Случай транспортных средств, которые не обновляются часто, можно решить двумя способами: часто вызывать CreateVehicle с ожидаемой парой идентификатора поставщика/идентификатора транспортного средства и отбрасывать ошибку, если транспортное средство уже существует; или вызов CreateVehicle после того, как UpdateVehicle возвратится с ошибкой NOT_FOUND .

Обновления местоположения автомобиля

Для обеспечения максимальной производительности Fleet Engine предоставьте ему поток обновлений о местоположении транспортных средств. Используйте любой из следующих способов для предоставления этих обновлений:

  1. Используйте Driver SDK — Android , iOS — самый простой вариант.
  2. Используйте собственный код . Это полезно, если местоположения передаются через серверную часть или если вы используете устройства, отличные от Android или iOS.

Типы транспортных средств

Сущность Vehicle содержит обязательное поле VehicleType , которое содержит перечисление Category , которое может быть указано как AUTO , TAXI , TRUCK , TWO_WHEELER , BICYCLE или PEDESTRIAN . Тип транспортного средства может служить критерием фильтра в SearchVehicles и ListVehicles .

Все маршруты для транспортных средств будут использовать соответствующий RouteTravelMode если для категории установлено значение AUTO , TWO_WHEELER , BICYCLE или PEDESTRIAN . Если для категории установлено значение TAXI или TRUCK , маршрутизация обрабатывается так же, как в режиме AUTO .

Атрибуты автомобиля

Сущность Vehicle содержит повторяющееся поле VehicleAttribute . Эти атрибуты не интерпретируются Fleet Engine. API SearchVehicles включает поле, требующее, чтобы сопоставленные Vehicles содержали все включенные атрибуты, для которых установлено указанное значение.

Обратите внимание, что поле атрибута является дополнением к нескольким другим поддерживаемым полям в сообщении Vehicle , таким как vehicle_type и supported_trip_types .

Оставшиеся путевые точки автомобиля

Объект «Транспортное средство» содержит повторяющееся поле TripWaypoint ( RPC | REST ), называемое waypoints ( RPC | REST ). Это поле включает оставшиеся путевые точки в поездках в том порядке, в котором транспортное средство достигает их. Fleet Engine вычисляет это поле, когда транспортному средству назначаются поездки, и обновляет его, когда поездки меняют свой статус. Эти путевые точки можно идентифицировать по полям TripId и WaypointType .

Расширение допуска автомобиля к участию в матчах

Как правило, услуги Rideshare или поставщика доставки отвечают за сопоставление запросов на поездку с транспортными средствами. Служба может использовать атрибуты транспортного средства, чтобы включить транспортное средство в большее количество поисков. Например, поставщик может реализовать набор атрибутов, соответствующих уровням льгот или возможностей, предоставляемых транспортным средством. Например, три уровня могут представлять собой набор атрибутов с логическими значениями: is_bronze_level , is_silver_level и is_gold_level . Транспортное средство может соответствовать всем трем требованиям. Когда Fleet Engine получает запрос на поездку, требующую возможностей серебряного уровня, поиск включает это транспортное средство. Использование атрибутов таким образом включает в себя транспортные средства, предлагающие различные возможности.

Существует два способа обновления атрибутов автомобиля. Одним из них является API UpdateVehicle . При использовании этого API всему набору атрибутов транспортного средства присваивается значение. Невозможно просто обновить один атрибут. Другой метод — API UpdateVehicleAttributes . Этот метод требует обновления только атрибутов. Атрибутам, включенным в запрос, будет присвоено новое значение или добавлено; неуказанные атрибуты не будут изменены.

Практическое руководство: создать транспортное средство

Объект Vehicle должен быть создан для каждого Транспортного средства, которое будет отслеживаться в парке.

Используйте конечную точку CreateVehicle с CreateVehicleRequest для создания транспортного средства.

provider_id Vehicle должен быть идентификатором проекта (например, my-on-demand-project) проекта Google Cloud, который содержит сервисные учетные записи, которые будут использоваться для вызова Fleet Engine. Обратите внимание: хотя несколько сервисных учетных записей могут иметь доступ к Fleet Engine для одного и того же поставщика услуг Rideshare или доставки, Fleet Engine в настоящее время не поддерживает сервисные учетные записи из нескольких проектов Google Cloud, имеющих доступ к одним и тем же Vehicles .

Vehicle может быть создано в состоянии OFFLINE или ONLINE . Если он создан ONLINE он может быть немедленно возвращен в ответ на запросы SearchVehicles .

Начальное last_location может быть включено в вызов CreateVehicle . Несмотря на то, что это разрешено, Vehicle не должно создаваться в состоянии ONLINE без last_location .

Подробную информацию о поле типа транспортного средства см. в разделе «Типы транспортных средств».

Подробную информацию о поле атрибутов см. в разделе «Атрибуты транспортного средства» .

Значение, возвращаемое функцией CreateVehicle , является созданным объектом Vehicle .

Пример

оболочка

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles?vehicleId=vid-8241890" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
    "vehicleState": "OFFLINE",
    "supportedTripTypes": ["EXCLUSIVE"],
    "maximumCapacity": 4,
    "vehicleType": {"category": "AUTO"},
    "attributes": [{"key": "on_trip", "value": "false"}]
}
EOM

См. справку по поставщикам.транспортных средств.создать .

Джава

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService =
    VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
Vehicle vehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.OFFLINE)  // Initial state
    .addSupportedTripTypes(TripType.EXCLUSIVE)
    .setMaximumCapacity(4)
    .setVehicleType(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .addAttributes(VehicleAttribute.newBuilder()
        .setKey("on_trip").setValue("false"))  // Opaque to the Fleet Engine
    // Add .setBackToBackEnabled(true) to make this vehicle eligible for trip
    // matching while even if it is on a trip.  By default this is disabled.
    .build();

CreateVehicleRequest createVehicleRequest =
    CreateVehicleRequest.newBuilder()  // no need for the header
        .setParent(parent)
        .setVehicleId("vid-8241890")  // Vehicle ID assigned by Rideshare or Delivery Provider
        .setVehicle(vehicle)  // Initial state
        .build();

// In this case, the Vehicle is being created in the OFFLINE state and
// no initial position is being provided.  When the Driver App checks
// in with the Rideshare or Delivery Provider, the state can be set to ONLINE and
// the Driver App will update the Vehicle Location.

try {
  Vehicle createdVehicle =
      vehicleService.createVehicle(createVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle created successfully.

Журналы платформы Google Cloud для создания транспортных средств

API Fleet Engine записывает запись в журналы платформы Google Cloud при получении вызова к конечной точке CreateVehicle . Запись журнала включает информацию о значениях в запросе CreateVehicle . Если вызов успешен, он также будет содержать информацию о возвращенном Vehicle .

оболочка

gcloud --project=project-id logging read --freshness=1h '
  jsonPayload.request.vehicleId="vid-8241890"
  jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.CreateVehicleLog"
'

Должна напечатать запись, подобную следующей:

---
insertId: c2cf4d3a180251c1bdb892137c14f022
jsonPayload:
  '@type': type.googleapis.com/maps.fleetengine.v1.CreateVehicleLog
  request:
    vehicle:
      attributes:
      - key: on_trip
        value: 'false'
      maximumCapacity: 4
      state: VEHICLE_STATE_OFFLINE
      supportedTrips:
      - EXCLUSIVE_TRIP
      vehicleType:
        vehicleCategory: AUTO
    vehicleId: vid-8241890
  response:
    attributes:
    - key: on_trip
      value: 'false'
    availableCapacity: 4
    currentRouteSegmentHandle: AdSiwAwCO9gZ7Pw5UZZimOXOo41cJTjg/r3SuwVPQmuuaV0sU3+3UCY+z53Cl9i6mWHLoCKbBt9Vsj5PMRgOJ8zX
    maximumCapacity: 4
    name: providers/project-id/vehicles/vid-8241890
    state: VEHICLE_STATE_OFFLINE
    supportedTrips:
    - EXCLUSIVE_TRIP
    vehicleType:
      vehicleCategory: AUTO
labels:
  vehicle_id: vid-8241890
logName: projects/project-id/logs/fleetengine.googleapis.com%2Fcreate_vehicle
receiveTimestamp: '2021-09-22T03:25:16.361159871Z'
resource:
  labels:
    location: global
    resource_container: projects/project-id
  type: fleetengine.googleapis.com/Fleet
timestamp: '2021-09-22T03:25:15.724998Z'

Уведомления Cloud Pub/Sub о создании автомобиля

API Fleet Engine публикует уведомление через Cloud Pub/Sub при создании нового автомобиля. Чтобы получать эти уведомления, следуйте инструкциям здесь .

Практическое руководство: обновить местоположение автомобиля

Если вы не используете Driver SDK для обновления местоположения автомобиля, вы можете напрямую позвонить в Fleet Engine и сообщить о местонахождении автомобиля. Для любого активного транспортного средства Fleet Engine ожидает обновления местоположения не реже одного раза в минуту и ​​не чаще одного раза в 5 секунд. Для этих обновлений требуются только права пользователя Fleet Engine Driver SDK.

Пример

оболочка

curl -X PUT \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=last_location" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
    "supplementalLocation": {"latitude": 12.1, "longitude": 14.5},
    "supplementalLocationTime": "$(date -u --iso-8601=seconds)",
    "supplementalLocationSensor": "CUSTOMER_SUPPLIED_LOCATION",
    "supplementalLocationAccuracy": 15
}
EOM

См. справку по поставщикам.транспортных средств.обновления .

Джава

static final String PROJECT_ID = "project-id";
static final String VEHICLE_ID = "vid-8241890";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String vehicleName = "providers/" + PROJECT_ID + "/vehicles/" + VEHICLE_ID;
Vehicle updatedVehicle = Vehicle.newBuilder()
    .setLastLocation(VehicleLocation.newBuilder()
        .setSupplementalLocation(LatLng.newBuilder()
            .setLatitude(37.3382)
            .setLongitude(121.8863))
        .setSupplementalLocationTime(now())
        .setSupplementalLocationSensor(LocationSensor.CUSTOMER_SUPPLIED_LOCATION)
        .setSupplementalLocationAccuracy(DoubleValue.of(15.0)))  // Optional)
    .build();

UpdateVehicleRequest updateVehicleRequest = UpdateVehicleRequest.newBuilder()
    .setName(vehicleName)
    .setVehicle(updatedVehicle)
    .setUpdateMask(FieldMask.newBuilder()
        .addPaths("last_location"))
    .build();

try {
  Vehicle updatedVehicle =
      vehicleService.updateVehicle(updateVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      // Most implementations will call CreateVehicle in this case
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle updated successfully.

Практическое руководство: обновить другие поля «Транспортное средство»

Обновления других атрибутов состояния «Транспортное средство» происходят реже, чем обновления положения. Для обновления атрибутов, отличных от last_location требуются права суперпользователя Fleet Engine.

UpdateVehicleRequest включает в себя update_mask , указывающий, какие поля необходимо обновить. Поведение поля такое же, как в документации Protobuf для масок полей.

Как отмечено в разделе «Атрибуты транспортного средства» , обновление поля attributes требует записи всех атрибутов, которые необходимо сохранить. Невозможно просто обновить значение одной пары ключ-значение в вызове UpdateVehicle . Для обновления значений определенных атрибутов можно использовать API UpdateVehicleAttributes .

Пример

В этом примере включается back_to_back .

оболочка

curl -X PUT \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=vehicle_state,attributes,back_to_back_enabled" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
    "vehicleState": "ONLINE",
    "attributes": [
      {"key": "on_trip", "value": "true"},
      {"key": "cash_only", "value": "false"}
    ],
    "backToBackEnabled": true
}
EOM

См. справку по поставщикам.транспортных средств.обновления .

Джава

static final String PROJECT_ID = "project-id";
static final String VEHICLE_ID = "vid-8241890";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String vehicleName = "providers/" + PROJECT_ID + "/vehicles/" + VEHICLE_ID;
Vehicle updatedVehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.ONLINE)
    .addAllAttributes(ImmutableList.of(
        VehicleAttribute.newBuilder().setKey("on_trip").setValue("true").build(),
        VehicleAttribute.newBuilder().setKey("cash_only").setValue("false").build()))
    .setBackToBackEnabled(true)
    .build();

UpdateVehicleRequest updateVehicleRequest = UpdateVehicleRequest.newBuilder()
    .setName(vehicleName)
    .setVehicle(updatedVehicle)
    .setUpdateMask(FieldMask.newBuilder()
        .addPaths("vehicle_state")
        .addPaths("attributes")
        .addPaths("back_to_back_enabled"))
    .build();

// Attributes and vehicle state are being updated, so both are
// included in the field mask.  Note that of on_trip were
// not being updated, but rather cash_only was being changed,
// the desired value of "on_trip" would still need to be written
// as the attributes are completely replaced in an update operation.

try {
  Vehicle updatedVehicle =
      vehicleService.updateVehicle(updateVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      // Most implementations will call CreateVehicle in this case
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle updated successfully.

Журналы платформы Google Cloud для обновлений транспортных средств

API Fleet Engine записывает запись в журналы платформы Google Cloud при получении вызова к конечной точке UpdateVehicle . Запись журнала включает информацию о значениях в запросе UpdateVehicle . Если вызов успешен, он также будет содержать информацию о возвращенном Vehicle .

оболочка

gcloud --project=project-id logging read --freshness=1h '
  jsonPayload.request.vehicleId="vid-8241890"
  jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.UpdateVehicleLog"
'

Уведомления Cloud Pub/Sub об обновлениях транспортных средств

API Fleet Engine публикует уведомление через Cloud Pub/Sub при обновлении существующего автомобиля. Чтобы получать эти уведомления, следуйте инструкциям здесь .

Практическое руководство: поиск транспортных средств

Fleet Engine поддерживает поиск транспортных средств. API SearchVehicles позволяет найти доступных поблизости водителей, которые лучше всего подходят для такой задачи, как обслуживание поездки или запрос на доставку. API SearchVehicles возвращает ранжированный список водителей, сопоставляющих атрибуты задач с атрибутами транспортных средств в вашем автопарке. Дополнительную информацию см. в разделе «Поиск ближайших водителей» .

Пример

При поиске доступных транспортных средств Fleet Engine по умолчанию исключает транспортные средства, находящиеся в активных поездках. Службы совместного использования или доставки должны явно включать их в поисковые запросы. В следующем примере показано, как включить эти транспортные средства в поиск транспортных средств, соответствующих поездке из торгового центра Grand Indonesia East Mall в конференц-центр Balai Sidang Jakarta.

оболочка

Сначала обновите местоположение транспортного средства, которое мы создали на предыдущих этапах, чтобы оно соответствовало критериям. В реальном мире это будет выполняться Driver SDK, работающим на устройстве Android или iOS в автомобиле.

curl -X PUT \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=last_location,attributes" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "lastLocation": {
    "updateTime": "$( date -u +"%Y-%m-%dT%H:%M:%SZ" )",
    "location": {
      "latitude": "-6.195139",
      "longitude": "106.820826"
    }
  },
  "attributes": [{"key": "on_trip", "value": "false"}]
}
EOM

Выполнение поиска должно привести как минимум к этому транспортному средству.

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles:search" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "pickupPoint": {
    "point": {"latitude": "-6.195139", "longitude": "106.820826"}
  },
  "dropoffPoint": {
    "point": {"latitude": "-6.1275", "longitude": "106.6537"}
  },
  "pickupRadiusMeters": 2000,
  "count": 10,
  "minimumCapacity": 2,
  "tripTypes": ["EXCLUSIVE"],
  "vehicleTypes": [{"category": "AUTO"}],
  "filter": "attributes.on_trip=\"false\"",
  "orderBy": "PICKUP_POINT_ETA",
  "includeBackToBack": true
}
EOM

См. справку по поставщикам.транспортных средств.поиска .

Джава

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
SearchVehiclesRequest searchVehiclesRequest = SearchVehiclesRequest.newBuilder()
    .setParent(parent)
    .setPickupPoint( // Grand Indonesia East Mall
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
    .setDropoffPoint( // Balai Sidang Jakarta Convention Center
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.213796).setLongitude(106.807195)))
    .setPickupRadiusMeters(2000)
    .setCount(10)
    .setMinimumCapacity(2)
    .addTripTypes(TripType.EXCLUSIVE)
    .addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .setFilter("attributes.on_trip=\"false\"")
    .setOrderBy(VehicleMatchOrder.PICKUP_POINT_ETA)
    .setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
    .build();

// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully

try {
  SearchVehiclesResponse searchVehiclesResponse =
      vehicleService.searchVehicles(searchVehiclesRequest);

  // Search results: Each vehicle match contains a vehicle entity and information
  // about the distance and ETA to the pickup point and dropoff point.
  List<VehicleMatch> vehicleMatches = searchVehiclesResponse.getMatchesList();
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Запрос на фильтрацию транспортных средств

SearchVehicles и ListVehicles поддерживают фильтрацию по атрибутам транспортных средств с помощью фильтрующего запроса. Синтаксис запроса фильтра см. в разделе AIP-160 .

Обратите внимание, что запросы фильтров поддерживают ТОЛЬКО фильтрацию по атрибутам транспортных средств и не могут использоваться для других полей. Запрос фильтра функционирует как предложение AND с другими ограничениями, такими как minimum_capacity или vehicle_types в SearchVehiclesRequest .

Практическое руководство: список транспортных средств

SearchVehicles оптимизирован для быстрого поиска небольшого количества транспортных средств в ранжированном порядке и в основном используется для поиска ближайших водителей, которые лучше всего подходят для выполнения задачи. Однако иногда требуется найти все транспортные средства, соответствующие некоторым критериям, даже если необходимо просмотреть результаты. ListVehicles предназначен для этого варианта использования.

API ListVehicles позволяет найти все транспортные средства, соответствующие определенным параметрам запроса. API ListVehicles возвращает разбитый на страницы список транспортных средств в проекте, который соответствует некоторым требованиям.

Чтобы выполнить фильтрацию по атрибутам транспортного средства, обратитесь к запросу «Фильтрация транспортных средств» .

Пример

В этом примере выполняется фильтрация по vehicle_type и атрибутам с использованием строки filter .

оболочка

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles:list" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "vehicleTypes": [{"category": "AUTO"}],
  "filter": "attributes.on_trip=\"false\"",
}
EOM

См. справку по поставщикам.транспортных средств.списка .

Джава

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
ListVehiclesRequest listVehiclesRequest = ListVehiclesRequest.newBuilder()
    .setParent(parent)
    .addTripTypes(TripType.EXCLUSIVE)
    .addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .setFilter("attributes.on_trip=\"false\"")
    .setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
    .build();

// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully

try {
  ListVehiclesResponse listVehiclesResponse =
      vehicleService.listVehicles(listVehiclesRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Поездки и их жизненный цикл

API и жизненный цикл Trip аналогичны API и жизненному циклу Vehicle. Поставщик услуг совместного пользования отвечает за создание поездок с использованием интерфейсов Fleet Engine. Fleet Engine предоставляет как службу RPC, TripService , так и ресурсы REST, provider.trips . Эти интерфейсы позволяют создавать объекты Trip, запрашивать информацию, выполнять функции поиска и обновлять данные.

У Trip есть поле статуса, позволяющее отслеживать ее продвижение по жизненному циклу. Значения изменяются от NEW к COMPLETE плюс CANCELED и UNKNOWN_TRIP_STATUS . Обратитесь к trip_status для RPC или TripStatus для REST .

  • NEW
  • ENROUTE_TO_PICKUP
  • ARRIVED_AT_PICKUP
  • ENROUTE_TO_INTERMEDIATE_DESTINATION
  • ARRIVED_AT_INTERMEDIATE_DESTINATION
  • ENROUTE_TO_DROPOFF
  • COMPLETE

Ваша служба может обновить поездку до CANCELED в любом из этих статусов. Когда ваш сервис создает поездку, система устанавливает статус NEW . vehicle_id не является обязательным. Как и в случае с транспортными средствами, сервисы автоматически удаляют поездки через семь дней без обновления. Если ваша служба попытается создать поездку с уже существующим идентификатором, будет возвращена ошибка. Поездка считается «активной», если она находится в состоянии, отличном от COMPLETE или CANCELED . Это различие важно для поля active_trips в сущности Vehicle и SearchTripsRequest .

Служба может изменить vehicle_id , присвоенный поездке, только в том случае, если статус NEW или CANCELED . Если Водитель отменяет Поездку во время пути, статус Поездки должен быть установлен на NEW или CANCELED прежде чем vehicle_id будет изменен или очищен.

Статус важен при реализации поддержки компенсационных поездок. Эта поддержка позволяет Поставщику назначить новую поездку Транспортному средству, пока Транспортное средство находится в активной поездке. Код для создания обратной поездки такой же, как и для одиночной поездки, и использует тот же идентификатор транспортного средства. Fleet Engine добавляет пункт отправления и пункт назначения новой поездки в путевые точки транспортного средства. Дополнительную информацию о последовательных поездках см. в разделе «Создание поездок с несколькими точками» .

Оставшиеся путевые точки поездки

Сущность Trip содержит повторяющееся поле TripWaypoint ( RPC | REST ), называемое remainingWaypoints ( RPC | REST ). Это поле включает в себя все путевые точки, которые транспортному средству необходимо будет проехать по порядку до конечной точки высадки в этой поездке. Он рассчитывается на основе оставшихся путевых точек автомобиля . В вариантах использования «Совместно» и «Carpool» этот список содержит путевые точки из других поездок, которые будут пройдены до этой поездки, но исключает любые путевые точки после этой поездки. Путевую точку в списке можно идентифицировать по ее TripId и WaypointType .

Связь между статусом поездки и оставшимися путевыми точками транспортного средства

Оставшиеся путевые точки Транспортного средства ( RPC | REST ) будут обновлены, когда Fleet Engine получит запрос на изменение статуса поездки. Предыдущая путевая точка будет удалена из списка оставшихся путевых точек Транспортного средства, когда tripStatus ( RPC | REST ) изменится с другого статуса на ENROUTE_TO_XXX. То есть, когда статус поездки изменяется с ENROUTE_TO_PICKUP на ARRIVED_AT_PICKUP, точка посадки поездки по-прежнему будет в списке оставшихся путевых точек транспортного средства, но когда статус поездки изменяется на ENROUTE_TO_INTERMEDIATE_DESTINATION или ENROUTE_TO_DROPOFF, ее точка посадки будет удалена из оставшихся путевых точек транспортного средства.

То же самое касается ARRIVED_AT_INTERMEDIATE_DESTINATION и ENROUTE_TO_INTERMDEDIATE_DESTINATION. При ARRIVED_AT_INTERMEDIATE_DESTINATION текущий промежуточный пункт назначения не будет удален из списка оставшихся путевых точек транспортного средства до тех пор, пока транспортное средство не сообщит, что оно направляется к следующей путевой точке.

Когда статус поездки изменится на COMPLETED , в списке оставшихся путевых точек Транспортного средства не будет ни одной путевой точки этой поездки.

Практическое руководство: Создайте поездку

Необходимо создать объект Trip , чтобы каждый запрос на поездку можно было отслеживать и сопоставлять с транспортными средствами в парке. Используйте конечную точку CreateTrip с CreateTripRequest , чтобы создать поездку.

Для создания поездки необходимы следующие атрибуты:

  • parent — строка, включающая идентификатор поставщика, созданный при создании проекта Google Cloud.
  • trip_id — строка, созданная поставщиком услуг Rideshare.
  • trip — Контейнер с основными метаданными, описывающими поездку.
    • trip_type — перечисление, указывающее, могут ли в поездке участвовать другие пассажиры из разных пунктов отправления и назначения в одном и том же транспортном средстве ( SHARED ) или только одна группа ( EXCLUSIVE ).
    • pickup_point — TerminalLocation, представляющий точку отправления поездки. См. ссылку RPC или ссылку REST.

При создании поездки вы можете указать number_of_passengers , dropoff_point и vehicle_id . Хотя эти поля не являются обязательными, если вы их предоставите, они сохранятся. Все остальные поля «Поездка» игнорируются. Например, все поездки начинаются со trip_status , равного NEW , даже если вы передадите trip_status , равный CANCELED в запросе на создание.

Пример

В следующем примере создается поездка в торговый центр Grand Indonesia East. Поездка рассчитана на двоих пассажиров и является эксклюзивной. provider_id Trip должен совпадать с идентификатором проекта. В этом примере поставщик услуг Rideshare создал проект Google Cloud project-id . В этом проекте должны быть сервисные учетные записи, используемые для вызова Fleet Engine. Статус поездки — NEW .

Позже, после того как служба сопоставит поездку с транспортным средством, она может вызвать UpdateTrip и изменить vehicle_id , когда поездка будет назначена транспортному средству.

оболочка

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/trips?tripId=tid-1f97" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "tripType": "EXCLUSIVE",
  "numberOfPassengers": 2,
  "pickupPoint": {
    "point": {"latitude": "-6.195139", "longitude": "106.820826"}
  },
  "dropoffPoint": {
    "point": {"latitude": "-6.1275", "longitude": "106.6537"}
  }
}
EOM

См. справку по поставщикам.trips.create .

Джава

static final String PROJECT_ID = "project-id";

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
Trip trip = Trip.newBuilder()
    .setTripType(TripType.EXCLUSIVE) // Use TripType.SHARED for carpooling
    .setPickupPoint(                 // Grand Indonesia East Mall
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
    // Provide the number of passengers if available.
    .setNumberOfPassengers(2)
    // Provide the drop-off point if available.
    .setDropoffPoint(
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.1275).setLongitude(106.6537)))
    .build();

CreateTripRequest createTripRequest =
    CreateTripRequest.newBuilder()  // no need for the header
        .setParent(parent)
        .setTripId("tid-1f97")  // Trip ID assigned by the Provider
        .setTrip(trip)              // Initial state
        .build();

// Error handling
// If Fleet Engine does not have trip with that id and the credentials of the
// requestor pass, the service creates the trip successfully.

try {
  Trip createdTrip =
      tripService.createTrip(createTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Журналы платформы Google Cloud для создания поездок

API Fleet Engine записывает запись в журнал с использованием журналов платформы Google Cloud при получении вызова к конечной точке CreateTrip . Запись журнала включает информацию о значениях в запросе CreateTrip . Если вызов успешен, он также будет включать информацию о возвращенной Trip .

Практическое руководство: обновить поездку

Сущность Trip содержит поля, которые позволяют службе отслеживать ход поездки и сообщать о ходе поездки Driver SDK и Consumer SDK. Чтобы обновить свойства, используйте сообщение UpdateTripRequest . При этом поля Trip обновляются в соответствии с field_mask запроса. См. UpdateTripRequest .

Поставщик услуг совместного пользования отвечает за обновление следующих атрибутов:

  • Статус поездки.
  • Идентификатор транспортного средства. Либо в момент создания, либо после сопоставления автомобиля с поездкой.
  • Изменения в посадке, высадке или путевых точках.

Fleet Engine автоматически обновляет следующие поля при использовании функции совместного использования путешествий через Driver SDK или Consumer SDK:

  • Маршруты
  • расчетное время прибытия
  • Оставшееся расстояние
  • Местоположение автомобиля
  • Оставшиеся путевые точки

См. раздел Trip в RPC или Resource.Trip в REST .

Журналы платформы Google Cloud для обновлений поездок

API Fleet Engine записывает запись в журнал, используя журналы платформы Google Cloud, при получении вызова к конечной точке UpdateTrip . Запись журнала включает информацию о значениях в запросе UpdateTrip . Если вызов успешен, он также будет включать информацию о возвращенной Trip .

Практическое руководство: поиск поездок

Fleet Engine поддерживает поиск поездок. Как отмечалось ранее, поездка автоматически удаляется через семь дней, поэтому SearchTrips не предоставляет полную историю всех поездок.

Хотя SearchTrips — это гибкий API, в приведенном ниже списке рассмотрены два варианта использования.

  • Определение активных поездок транспортного средства . Поставщик может определить активные поездки транспортного средства в данный момент. В SearchTripsRequest в качестве vehicle_id устанавливается рассматриваемое транспортное средство, а для параметра active_trips_only должно быть установлено значение true .

  • Согласование состояния поставщика и Fleet Engine . Поставщик может использовать SearchTrips , чтобы обеспечить соответствие их состояния Trip и состояния Fleet Engine. Это особенно важно для TripStatus. Если состояние поездки, назначенной Транспортному средству, не установлено должным образом как COMPLETE или CANCELED , Транспортное средство не включается в SearchVehicles .

Чтобы использовать SearchTrips таким образом, оставьте vehicle_id пустым, задайте для active_trips_only значение true и установите для minimum_staleness время, превышающее продолжительность большинства поездок. Например, вы можете использовать один час. Результаты включают в себя поездки, которые не являются ЗАВЕРШЕННЫМИ и ОТМЕНЕННЫМИ и не обновлялись более часа. Поставщик должен проверить эти Поездки, чтобы убедиться, что их статус в Fleet Engine правильно обновляется.

Поиск неисправностей

В случае ошибки DEADLINE_EXCEEDED состояние Fleet Engine неизвестно. Поставщик должен снова вызвать CreateTrip , который вернет либо 201 (CREATED), либо 409 (CONFLICT). В последнем случае предыдущий запрос был выполнен до DEADLINE_EXCEEDED . Дополнительные сведения об обработке ошибок поездок см. в руководствах по Consumer API: Android или iOS .

Поддержка поездок на автомобиле

Вы можете назначить несколько поездок SHARED транспортному средству, которое поддерживает TripType.SHARED . Вам необходимо указать порядок всех непройденных путевых точек для всех поездок, назначенных Транспортному средству в этой общей поездке, через Trip.vehicle_waypoints , когда вы назначаете vehicle_id для общей поездки (в запросе CreateTrip или UpdateTrip ). Обратитесь к vehicle_waypoints для RPC или vehicleWaypoints для REST .

Поддержка нескольких направлений

Определите промежуточный пункт назначения

Поле intermediateDestinations и поле intermediateDestinationIndex в Trip ( RPC | REST ) объединяются для указания пункта назначения.

Обновить промежуточный пункт назначения

Вы можете обновить промежуточные пункты назначения через UpdateTrip . При обновлении промежуточных пунктов назначения вы должны предоставить полный список промежуточных пунктов назначения, включая те, которые были посещены, а не только новые добавленные или подлежащие изменению. Когда intermediateDestinationIndex указывает на индекс после позиции вновь добавленного/измененного промежуточного пункта назначения, новый/обновленный промежуточный пункт назначения не будет добавлен к waypoints транспортного средства или remainingWaypoints путевым точкам поездки. Причина в том, что любые промежуточные пункты назначения до intermediateDestinationIndex считаются уже посещенными.

Изменение статуса поездки

Поле intermediateDestinationsVersion в ( RPC | REST ) требуется в запросе на обновление статуса поездки, отправляемом в Fleet Engine, чтобы указать, что промежуточный пункт назначения пройден. Целевой промежуточный пункт назначения указывается через поле intermediateDestinationIndex . Когда tripStatus ( RPC | REST ) имеет значение ENROUTE_TO_INTERMEDIATE_DESTINATION, число между [0..N-1] указывает, какой промежуточный пункт назначения транспортное средство пересечет следующим. Когда tripStatus имеет значение ARRIVED_AT_INTERMEDIATE_DESTINATION, число между [0..N-1] указывает, в каком промежуточном пункте назначения находится транспортное средство.

Пример

В следующем примере кода показано, как обновить статус поездки, чтобы она следовала к первому промежуточному пункту назначения, предполагая, что вы создали поездку с несколькими пунктами назначения и поездка миновала точку посадки.

Джава

static final String PROJECT_ID = "project-id";
static final String TRIP_ID = "multi-destination-trip-A";

String tripName = "providers/" + PROJECT_ID + "/trips/" + TRIP_ID;
Trip trip = …; // Fetch trip object from FleetEngine or your storage.

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

// Trip settings to update.
Trip trip = Trip.newBuilder()
    // Trip status cannot go back to a previous status once it is passed
    .setTripStatus(TripStatus.ENROUTE_TO_INTERMEDIATE_DESTINATION)
    // Enrouting to the first intermediate destination.
    .setIntermediateDestinationIndex(0)
    // intermediate_destinations_version MUST be provided to ensure you
    // have the same picture on intermediate destinations list as FleetEngine has.
    .setIntermediateDestinationsVersion(
        trip.getIntermediateDestinationsVersion())
    .build();

// Trip update request
UpdateTripRequest updateTripRequest =
    UpdateTripRequest.newBuilder()
        .setName(tripName)
        .setTrip(trip)
        .setUpdateMask(
            FieldMask.newBuilder()
                .addPaths("trip_status")
                .addPaths("intermediate_destination_index")
                // intermediate_destinations_version must not be in the
                // update mask.
                .build())
        .build();

// Error handling
try {
  Trip updatedTrip = tripService.updateTrip(updateTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:  // Trip does not exist.
      break;
    case FAILED_PRECONDITION:  // The given trip status is invalid, or the
                                // intermediate_destinations_version
                                // doesn’t match FleetEngine’s.
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Практическое руководство: подписаться на уведомления от API Fleet Engine.

API Fleet Engine использует Google Cloud Pub/Sub для публикации уведомлений по теме, созданной потребительским проектом Google Cloud. Публикация/подписка по умолчанию не включена для Fleet Engine в вашем проекте Google Cloud. Отправьте запрос в службу поддержки или обратитесь к своему инженеру по работе с клиентами , чтобы включить Pub/Sub.

Чтобы создать тему в своем облачном проекте, следуйте этим инструкциям. Идентификатор темы должен быть «fleet_engine_notifications».

Тема должна быть создана в том же облачном проекте, который вызывает API Fleet Engine.

После создания темы вам необходимо будет предоставить Fleet Engine API разрешение на публикацию по этой теме. Для этого нажмите на только что созданную тему и добавьте новое разрешение. Возможно, вам придется нажать «ПОКАЗАТЬ ИНФОРМАЦИОННУЮ ПАНЕЛЬ» , чтобы открыть редактор разрешений. Участником должен быть geo-fleet-engine@system.gserviceaccount.com , а ролью — Pub/Sub publisher .

Чтобы настроить облачный проект для подписки на уведомления, следуйте этим инструкциям.

API Fleet Engine будет публиковать каждое уведомление в двух разных форматах данных: protobuf и json . Формат данных для каждого уведомления обозначается в атрибутах PubsubMessage с ключом data_format и значением protobuf или json .

Схема уведомлений:

Протобуф

// A batch of notifications that is published by the Fleet Engine service using
// Cloud Pub/Sub in a single PubsubMessage.
message BatchNotification {
  // Required. At least one notification must exist.
  // List of notifications containing information related to changes in
  // Fleet Engine data.
  repeated Notification notifications = 1;
}

// A notification related to changes in Fleet Engine data.
// The data provides additional information specific to the type of the
// notification.
message Notification {
  // Required. At least one type must exist.
  // Type of notification.
  oneof type {
    // Notification related to changes in vehicle data.
    VehicleNotification vehicle_notification = 1;
  }
}

// Notification sent when a new vehicle was created.
message CreateVehicleNotification {
  // Required.
  // Vehicle must contain all fields that were set when it was created.
  Vehicle vehicle = 1;
}

// Notification sent when an existing vehicle is updated.
message UpdateVehicleNotification {
  // Required.
  // Vehicle must only contain name and fields that are present in the
  // field_mask field below.
  Vehicle vehicle = 1;

  // Required.
  // Contains vehicle field paths that were specifically requested
  // by the Provider.
  google.protobuf.FieldMask field_mask = 2;
}

// Notification related to changes in vehicle data.
message VehicleNotification {
  // Required. At least one type must be set.
  // Type of notification.
  oneof type {
    // Notification sent when a new vehicle was created.
    CreateVehicleNotification create_notification = 1;
    // Notification sent when an existing vehicle is updated.
    UpdateVehicleNotification update_notification = 2;
  }
}

JSON

BatchNotification: {
  "description": "A batch of notifications that is published by the Fleet Engine service using Cloud Pub/Sub in a single PubsubMessage.",
  "type": "object",
  "required": ["notifications"],
  "properties": {
    "notifications": {
      "description": "At least one notification must exist. List of notifications containing information related to changes in Fleet Engine data.",
      "type": "Notification[]"
    }
  }
}

Notification: {
  "description": "A notification related to changes in Fleet Engine data. The data provides additional information specific to the type of the notification.",
  "type": "object",
  "properties": {
    "vehicleNotification": {
      "description": "Notification related to changes in vehicle data.",
      "type": "VehicleNotification"
    }
  }
}

VehicleNotification: {
  "description": "Notification related to changes in vehicle data.",
  "type": "object",
  "properties": {
    "createNotification": {
      "description": "Notification sent when a new vehicle was created.",
      "type": "CreateVehicleNotification"
    },
    "updateNotification": {
      "description": "Notification sent when an existing vehicle is updated.",
      "type": "UpdateVehicleNotification"
    }
  }
}

CreateVehicleNotification: {
  "description": "Notification sent when a new vehicle was created.",
  "type": "object",
  "required": ["vehicle"],
  "properties": {
    "vehicle": {
      "description": "Vehicle must contain all fields that were set when it was created.",
      "type": "Vehicle"
    }
  }
}

UpdateVehicleNotification: {
  "description": "Notification sent when an existing vehicle is updated.",
  "type": "object",
  "required": ["vehicle", "fieldMask"],
  "properties": {
    "vehicle": {
      "description": "Vehicle must only contain name and fields that are present in the fieldMask field below.",
      "type": "Vehicle"
    },
    "fieldMask": {
      "description": "Contains vehicle field paths that were specifically requested by the Provider.",
      "type": "FieldMask"
    }
  }
}