Fleet Engine を使ってみる

Fleet Engine On-demand Rides and Deliveries API を使用すると、移動と注文の進行状況アプリケーションでルートと車両の状態を管理できます。Driver SDK、Consumer SDK、バックエンド サービス間のトランザクションを処理します。バックエンド サービスは、gRPC または REST 呼び出しのいずれかを使用して Fleet Engine と通信できます。

前提条件

開発では、Cloud SDK をインストール(gcloud)し、プロジェクトに対して認証されていることを確認します。

shell

gcloud auth login

次のような成功メッセージが表示されます。

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

オンデマンド配車と配達ソリューションの Fleet Engine API が適切に構成されていることを確認する。

shell

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

このコマンドの結果がエラーの場合は、プロジェクト管理者と Google サポート担当者にアクセス権の付与を依頼してください。

ロギング

Fleet Engine は、受信した API 呼び出しに関するログメッセージを Google Cloud Platform ログに書き込むことができます。ログの読み取り方法と分析方法の概要については、Cloud Logging のドキュメントをご覧ください。

2022 年 2 月 10 日より前に作成されたプロジェクトでは、ロギングがデフォルトで有効になっていない可能性があります。詳細については、ロギングのドキュメントをご覧ください。

クライアント ライブラリ

クライアント ライブラリは複数の一般的なプログラミング言語で公開されています。これらのライブラリは、未加工の REST や gRPC よりも優れたデベロッパー エクスペリエンスを提供するのに役立ちます。サーバー アプリケーション用のクライアント ライブラリを入手する方法については、クライアント ライブラリをご覧ください。

このドキュメントの Java の例は、gRPC に精通していることを前提としています。

認証と認可

移動と注文の進行状況で提供される機能は、Google Cloud コンソールで構成できます。これらの API と SDK では、Cloud コンソールで作成されたサービス アカウントを使用して署名された JSON Web Token を使用する必要があります。

Cloud プロジェクトの設定

クラウド プロジェクトを設定するには、まずプロジェクトを作成してから、サービス アカウントを作成します。

Google Cloud プロジェクトを作成するには:

  1. Google Cloud コンソールを使用して Google Cloud プロジェクトを作成します。
  2. [API とサービス] ダッシュボードを使用して、Local Rides and Deliveries API を有効にします。

サービス アカウントは 1 つ以上のロールに関連付けられています。ロールに応じて異なる権限セットを付与する JSON Web Token の作成に使用されます。通常、不正使用の可能性を減らすために、複数のサービス アカウントを作成し、それぞれに必要最小限のロールのセットを設定します。

移動状況と注文状況では、次のロールを使用します。

ロール説明
Fleet Engine Consumer SDK ユーザー

roles/fleetengine.consumerSdkUser
車両を検索する権限と、車両とルートに関する情報を取得する権限を付与します。このロールを持つサービス アカウントによって作成されたトークンは通常、ライドシェアリング アプリや配達アプリのモバイル デバイスから使用されます。
Fleet Engine Driver SDK ユーザー

roles/fleetengine.driverSdkUser
車両の位置とルートを更新する権限と、車両とルートに関する情報を取得する権限を付与します。このロールを持つサービス アカウントによって作成されたトークンは通常、ライドシェアリング アプリや配達ドライバー アプリのモバイル デバイスから使用されます。
Fleet Engine On-demand 管理者

roles/fleetengine.ondemandAdmin
すべての車両リソースとルートリソースに対する読み取り / 書き込み権限を付与します。このロールを持つプリンシパルは JWT を使用する必要はありません。代わりにアプリケーションのデフォルト認証情報を使用する必要があります。カスタム JWT クレームは無視されます。このロールは、信頼できる環境(お客様のバックエンド)に限定する必要があります。
FleetEngine サービス スーパー ユーザー **(非推奨)**

roles/fleetengine.serviceSuperUser
すべての車両 API とルート API に権限を付与します。このロールを持つサービス アカウントによって作成されたトークンは通常、バックエンド サーバーから使用されます。このロールは非推奨になりました。代わりに roles/fleetengine.ondemandAdmin の使用をおすすめします。

たとえば、3 つのロールのそれぞれにサービス アカウントを作成し、それぞれのロールを割り当てます。

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

Driver SDK と Consumer SDK は、これらの標準ロールを中心に構築されています。

また、任意の権限セットをバンドルできるカスタムロールを作成することもできます。Driver SDK と Consumer 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 Auth ライブラリ

Fleet Engine は、JSON Web Token(JWT)を使用して Fleet Engine API へのアクセスを制限します。新しい Fleet Engine Auth Library(GitHub で入手可能)を使用すると、Fleet Engine JWT の構築を簡素化し、安全に署名できます。

このライブラリには次のような利点があります。

  • Fleet Engine トークンの作成プロセスを簡素化します。
  • 認証情報ファイル以外のトークン署名メカニズムを提供します(サービス アカウントの権限借用など)。
  • 署名付きトークンを gRPC スタブまたは GAPIC クライアントから送信されるアウトバウンド リクエストにアタッチします。

認可用の JSON Web Token(JWT)を作成する

Fleet Engine Auth Library を使用しない場合は、コードベース内で JSON ウェブトークン(JWT)を直接作成する必要があります。そのためには、JWT と Fleet Engine との関係の両方について深く理解する必要があります。このため、Fleet Engine Auth Library の利用を強くおすすめします。

Fleet Engine 内では、JSON Web Token(JWT)が有効期間の短い認証を提供し、デバイスは認可されている車両、ルート、タスクのみを変更できるようにします。JWT にはヘッダーとクレーム セクションが含まれています。ヘッダー セクションには、使用する秘密鍵(サービス アカウントから取得)や暗号化アルゴリズムなどの情報が含まれています。クレーム セクションには、トークンの作成日時、トークンの有効期間、アクセスを要求しているサービス、アクセスの範囲を絞り込むためのその他の認証情報(車両 ID など)などの情報が含まれます。

JWT ヘッダー セクションには、次のフィールドがあります。

項目説明
alg 使用するアルゴリズム。`RS256`。
typ トークンのタイプ。JWT。
子供 サービス アカウントの秘密鍵 ID。この値は、サービス アカウント JSON ファイルの private_key_id フィールドにあります。適切なレベルの権限を持つサービス アカウントのキーを使用してください。

JWT クレーム セクションには、次のフィールドがあります。

項目説明
iss サービス アカウントのメールアドレス。
Pub/Subです サービス アカウントのメールアドレス。
AUD サービス アカウントの SERVICE_NAME。この場合は https://fleetengine.googleapis.com/ です。
iat トークンが作成されたときのタイムスタンプ。1970 年 1 月 1 日 00:00:00 UTC からの経過時間(秒)で指定します。スキューには 10 分かかります。タイムスタンプが過去または未来すぎると、サーバーからエラーが報告されることがあります。
exp トークンが期限切れになるときのタイムスタンプ。1970 年 1 月 1 日 00:00:00 UTC からの経過時間(秒)で指定します。タイムスタンプが 1 時間以上先の場合はリクエストが失敗します。
authorization ユースケースに応じて、`vehicleid` または `tripid` を含めることができます。

JWT トークンの作成と署名です。JWT を作成して署名する手順とコードサンプルについては、OAuth を使用しないサービス アカウント認証をご覧ください。その後、署名付きトークンを gRPC 呼び出しまたは Fleet Engine へのアクセスに使用されるその他のメソッドに関連付けることができます。

JWT クレーム

JWT ペイロードを作成するときに、認証セクションにクレームを追加し、キー vehicleid または tripid を、呼び出しを行う車両 ID またはルート ID の値に設定します。

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 app のトークンの例です。

{
  "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 フィールドに、サービス アカウントの秘密鍵 ID を指定します。この値は、サービス アカウントの JSON ファイルの private_key_id フィールドにあります。
  • iss フィールドと sub フィールドに、サービス アカウントのメールアドレスを指定します。この値は、サービス アカウント JSON ファイルの client_email フィールドにあります。
  • aud フィールドに https://SERVICE_NAME/ を指定します。
  • iat フィールドでは、トークン作成時のタイムスタンプを使用します。1970 年 1 月 1 日 00:00:00 UTC からの経過時間(秒)で指定します。スキューには 10 分かかります。タイムスタンプが過去または未来すぎると、サーバーがエラーを報告する可能性があります。
  • exp フィールドでは、トークンの有効期限が切れるときのタイムスタンプを使用します。このタイムスタンプは 1970 年 1 月 1 日 00:00:00 UTC からの経過秒数で指定します。指定できる最大値は iat + 3,600 です。

モバイル デバイスに渡す JWT に署名する場合は、ドライバまたはコンシューマ 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 プロパティは、エポックからの経過秒数で表した有効期限です。これは、iat に 3, 600 を加算して計算できます。有効期限を 1 時間より後の時間にすることはできません。

{
  "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

署名付きの Base64 エンコード JWT は、signed_token.jwt ファイル内に格納する必要があります。トークンは今後 1 時間有効です。

これで、List Vehicles REST エンドポイントに対して curl コマンドを実行して、トークンをテストできます。

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

車両とそのライフサイクル

Vehicle は、ドライバーと車両のペアを表すエンティティです。現在、ドライバーと車両を個別にトラッキングすることはできません。配車サービス プロバイダまたは配達プロバイダは、プロバイダ ID(Fleet Engine API の呼び出しに使用されるサービス アカウントを含む Google Cloud プロジェクトのプロジェクト ID と同じである必要があります)と、配車サービスまたは配達プロバイダが所有する車両 ID を使用して車両を作成します。

7 日後に UpdateVehicle で更新されなかった車両は、自動的に削除されます。既存のプロバイダ ID と車両 ID のペアを使用して CreateVehicle を呼び出すとエラーになります。頻繁に更新されない車両は、次の 2 つの方法で対処できます。1 つは、想定されるプロバイダ ID と車両 ID のペアを指定して CreateVehicle を頻繁に呼び出し、車両がすでに存在する場合はエラーを破棄する方法、もう 1 つは、UpdateVehicle の後に NOT_FOUND エラーが返された後に CreateVehicle を呼び出す方法です。

車両の位置情報の更新

Fleet Engine で最高のパフォーマンスを得るには、車両位置情報の更新ストリームを提供します。これらの更新を提供するには、次のいずれかの方法を使用します。

  1. Driver SDK(AndroidiOS)を使用する(最もシンプルなオプション)。
  2. カスタムコードを使用します。これは、位置情報がバックエンドを介して中継される場合や、Android または iOS 以外のデバイスを使用している場合に役立ちます。

車種

Vehicle エンティティには VehicleType の必須フィールドが含まれます。このフィールドには、AUTOTAXITRUCKTWO_WHEELERBICYCLEPEDESTRIAN として指定できる Category 列挙型が含まれています。車両タイプは、SearchVehiclesListVehicles でフィルタ条件として使用できます。

カテゴリが AUTOTWO_WHEELERBICYCLEPEDESTRIAN のいずれかに設定されている場合、車両のすべてのルーティングでは、対応する RouteTravelMode が使用されます。カテゴリが TAXI または TRUCK に設定されている場合、ルーティングは AUTO モードと同じように扱われます。

車両属性

Vehicle エンティティには、VehicleAttribute の繰り返しフィールドが含まれています。これらの属性は、Fleet Engine では解釈されません。SearchVehicles API には、一致した Vehicles に、指定された値に設定されたすべての属性を含める必要があるフィールドがあります。

属性フィールドは、Vehicle メッセージでサポートされている他のフィールド(vehicle_typesupported_trip_types など)に加えて使用されます。

車両の残りの地点

Vehicle エンティティには、waypointsRPC | REST)と呼ばれる TripWaypointRPC | REST)の繰り返しフィールドが含まれています。このフィールドには、ルートの残りの地点が、車両が到達した順に含まれます。Fleet Engine は、ルートが車両に割り当てられるとこのフィールドを計算し、ルートのステータスが変更されるとこのフィールドを更新します。これらのウェイポイントは、TripId フィールドと WaypointType フィールドで識別できます。

車両のマッチング条件の拡大

通常、配車サービスまたは配達プロバイダのサービスは、ルート リクエストを車両に一致させます。サービスは車両属性を使用して、より多くの検索に車両を含めることができます。たとえば、車両が提供する特典や能力のレベルに対応する属性のセットを実装できます。たとえば、is_bronze_levelis_silver_levelis_gold_level の 3 つのレベルをブール値を持つ属性のセットとすることができます。1 台の車両が、この 3 つすべての条件を満たすことができます。Fleet Engine がシルバーレベルの機能を必要とするルートのリクエストを受信すると、検索にその車両が含まれます。この方法で属性を使用することには、さまざまな機能を提供する車両が含まれます。

車両属性を更新する方法は 2 つあります。1 つは UpdateVehicle API です。この API を使用すると、車両属性のセット全体がこの値に設定されます。単一の属性のみを更新することはできません。 もう 1 つのメソッドは UpdateVehicleAttributes API です。このメソッドは、更新する属性のみを受け取ります。リクエストに含まれる属性は、新しい値に設定されるか追加されます。指定されていない属性は変更されません。

ハウツー: 車両を作成する

Vehicle エンティティは、フリートで追跡する車両ごとに作成する必要があります。

CreateVehicle エンドポイントと CreateVehicleRequest を使用して車両を作成します。

Vehicleprovider_id は、Fleet Engine の呼び出しに使用されるサービス アカウントを含む Google Cloud プロジェクトのプロジェクト ID(例: my-on-demand-project)にする必要があります。複数のサービス アカウントが同じライドシェアまたは配信プロバイダの Fleet Engine にアクセスできますが、Fleet Engine は現在、同じ Vehicles にアクセスする複数の Google Cloud プロジェクトのサービス アカウントをサポートしていません。

Vehicle は、OFFLINE 状態または ONLINE 状態で作成できます。ONLINE に作成された場合、SearchVehicles クエリのレスポンスですぐに返される場合があります。

最初の last_locationCreateVehicle 呼び出しに含めることができます。Vehicle は許可されていますが、last_location なしで ONLINE 状態で作成することはできません。

車両タイプフィールドの詳細については、車両タイプをご覧ください。

属性フィールドの詳細については、車両属性をご覧ください。

CreateVehicle から返される値は、作成された Vehicle エンティティです。

shell

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

providers.vehicles.create リファレンスをご覧ください。

Java

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 Platform ログ

Fleet Engine API は、CreateVehicle エンドポイントへの呼び出しを受信すると、Google Cloud Platform ログを介してログエントリを書き込みます。ログエントリには、CreateVehicle リクエストの値に関する情報が含まれます。呼び出しが成功すると、返された Vehicle に関する情報も含まれます。

shell

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 通知

Fleet Engine API は、新しい車両が作成されると Cloud Pub/Sub 経由で通知を発行します。これらの通知を受け取るには、こちらの手順を行ってください。

HOW-TO: 車両の位置情報を更新する

Driver SDK を使用して車両の位置情報を更新しない場合は、車両の位置情報を渡して Fleet Engine を直接呼び出すことができます。アクティブな車両の場合、Fleet Engine は少なくとも 1 分に 1 回、最大で 5 秒に 1 回、位置情報の更新を想定します。これらの更新で必要なのは、Fleet Engine Driver SDK のユーザー権限のみです。

shell

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

providers.vehicles.update リファレンスをご覧ください。

Java

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 の呼び出しで 1 つの Key-Value ペアの値を更新することはできません。特定の属性の値を更新するには、UpdateVehicleAttributes API を使用します。

この例では、back_to_back を有効にしています。

shell

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

providers.vehicles.update リファレンスをご覧ください。

Java

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 Platform ログ

Fleet Engine API は、UpdateVehicle エンドポイントへの呼び出しを受信すると、Google Cloud Platform ログを介してログエントリを書き込みます。ログエントリには、UpdateVehicle リクエストの値に関する情報が含まれます。呼び出しが成功すると、返された Vehicle に関する情報も含まれます。

shell

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 通知

Fleet Engine API は、既存の車両が更新されると Cloud Pub/Sub 経由で通知を公開します。これらの通知を受け取るには、こちらの手順を行ってください。

ハウツー: 車両を検索する

Fleet Engine は車両の検索に対応しています。SearchVehicles API を使用すると、配車サービスや配達リクエストなどのタスクに最適な、近くで空いているドライバーを見つけることができます。SearchVehicles API は、タスク属性とフリート内の車両の属性に一致するドライバーのランク付けされたリストを返します。詳細については、付近のドライバーを見つけるをご覧ください。

利用可能な車両を検索するとき、Fleet Engine はデフォルトでアクティブなルートの車両を除外します。ライドシェアまたは配信プロバイダのサービスは、これらを明示的に検索リクエストに含める必要があります。次の例は、グランド インドネシア イーストモールからバライシダン ジャカルタ コンベンション センターまでのルートと一致する車両の検索にこれらの車両を含める方法を示しています。

shell

まず、前の手順で作成した車両の位置情報を更新して、位置情報を利用できるようにします。実際には、これは車両の Android デバイスまたは iOS デバイスで実行される Driver SDK によって行われます。

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

providers.vehicles.search リファレンスをご覧ください。

Java

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;
}

車両フィルタリング クエリ

SearchVehiclesListVehicles は、フィルタクエリを使用した車両属性のフィルタリングをサポートしています。フィルタクエリの構文については、AIP-160 をご覧ください。

フィルタクエリは車両属性のフィルタリングのみをサポートし、他のフィールドでは使用できません。フィルタクエリは、SearchVehiclesRequestminimum_capacityvehicle_types など、他の制約を含む AND 句として機能します。

ハウツー: 車両を一覧表示する

SearchVehicles は、少数の車両をランク付けされた順ですばやく検出するように最適化されており、タスクに最適な近くのドライバーを見つけるために主に使用されます。ただし、結果をページ分割する必要がある場合でも、一定の条件を満たすすべての車両を検索したい場合もあります。ListVehicles は、そのようなユースケース向けに設計されています。

ListVehicles API を使用すると、特定のリクエスト オプションを満たすすべての車両を検索できます。ListVehicles API は、いくつかの要件に一致するプロジェクト内の車両のページ分けされたリストを返します。

車両属性でフィルタするには、車両フィルタリングのクエリをご覧ください。

この例では、filter 文字列を使用して、vehicle_type と属性にフィルタリングを行います。

shell

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

providers.vehicles.list リファレンスをご覧ください。

Java

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;
}

ルートとそのライフサイクル

Trip API とライフサイクルは、Vehicle API とそのライフサイクルと似ています。ライドシェア プロバイダは、Fleet Engine インターフェースを使用してルートを作成します。Fleet Engine は、RPC サービス TripService と REST リソース provider.trips の両方を提供します。これらのインターフェースにより、Trip エンティティの作成、情報のリクエスト、検索機能、更新機能が有効になります。

Trip には、ライフサイクル全体の進行状況を追跡するためのステータス フィールドがあります。値は NEW から COMPLETE、さらに CANCELEDUNKNOWN_TRIP_STATUS へと移動します。RPC の trip_status または REST の TripStatus をご覧ください。

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

お客様のサービスによって、CANCELED へのルートが上記のいずれかのステータスから更新される可能性があります。 サービスでルートが作成されると、エンジンによってステータスが NEW に設定されます。vehicle_id は省略可能です。車両と同様に、サービスは更新なしで 7 日後にルートを自動的に削除します。サービスがすでに存在する ID でルートを作成しようとすると、エラーが返されます。ルートのステータスが COMPLETE または CANCELED 以外の場合、そのルートは「有効」と見なされます。この区別は、Vehicle エンティティの active_trips フィールドと SearchTripsRequest で重要です。

ルートに割り当てられている vehicle_id は、ルートがアクティブな場合にのみ変更できます。たとえば、ドライバーが移動中にルートをキャンセルし、ルートが別の車両に再割り当てされた場合に、この方法を使用できます。

ステータスは、連続した移動のサポートを実装する場合に重要です。このサポートにより、プロバイダは車両がアクティブなルートを走行している場合でも、その車両に新しいルートを割り当てることができます。連続するルートを作成するコードは 1 つのルートと同じで、同じ車両 ID を使用します。Fleet Engine は、新しいルートの出発地と目的地を車両のウェイポイントに追加します。連続したルートについて詳しくは、複数の地点の移動を作成するをご覧ください。

ルートの残りのウェイポイント

Trip エンティティには、remainingWaypointsRPC | REST)と呼ばれる TripWaypointRPC | REST)の繰り返しフィールドが含まれています。このフィールドには、このルートの最終降車地点までに順番通りに通過する必要があるすべての地点が含まれます。車両の残りのウェイポイントから計算されます。Back-to-back や Carpool のユースケースの場合、このリストには、このルートより前に通過する他のルートのウェイポイントが含まれますが、このルートより後のウェイポイントは除外されます。リスト内のウェイポイントは TripIdWaypointType で識別できます。

ルート状況と車両の残りの地点の関係

Fleet Engine がルート状況の変更リクエストを受信すると、車両の残りのウェイポイントRPC | REST)が更新されます。tripStatusRPC | 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 を使用して Trip を作成します。

ルートを作成するには、次の属性が必要です。

  • parent - Google Cloud プロジェクトの作成時に作成されたプロバイダ ID を含む文字列。
  • trip_id - ライドシェア プロバイダが作成する文字列。
  • trip - ルートを記述する基本的なメタデータを含むコンテナ。
    • trip_type - 出発地と目的地が異なる乗客が同じ車両で移動しているかどうか(SHARED)か、単一の当事者のみ(EXCLUSIVE)があるかを表す列挙型。
    • pickup_point - ルートの出発地を表す TerminalLocation。RPC リファレンスまたは REST リファレンスをご覧ください。

ルートを作成する際に、number_of_passengersdropoff_pointvehicle_id を指定できます。これらのフィールドは必須ではありませんが、指定すると保持されます。その他の [ルート] フィールドはすべて無視されます。たとえば、作成リクエストで CANCELEDtrip_status を渡した場合でも、すべてのルートは NEWtrip_status で始まります。

次の例では、グランド インドネシア イースト モールへのルートが作成されます。この旅程は 2 人の乗客で、独占的なものです。Tripprovider_id は、プロジェクト ID と同じにする必要があります。この例では、配車サービス プロバイダが Google Cloud プロジェクト project-id を作成しました。このプロジェクトには、Fleet Engine の呼び出しに使用するサービス アカウントが必要です。ルートのステータスは NEW です。

その後、ルートが車両に一致すると、ルートが車両に割り当てられると、UpdateTrip を呼び出して vehicle_id を変更できます。

shell

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

providers.trips.create リファレンスをご覧ください。

Java

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 Platform のログ

Fleet Engine API は、CreateTrip エンドポイントへの呼び出しを受信すると、Google Cloud Platform ログを使用してログエントリを書き込みます。ログエントリには、CreateTrip リクエストの値に関する情報が含まれます。呼び出しが成功すると、返された Trip に関する情報も含まれます。

HOW-TO: ルートを更新する

Trip エンティティには、サービスによるトラッキングと、Driver SDK と Consumer SDK へのルートの進捗状況の報告に使用できるフィールドが含まれています。プロパティを更新するには、UpdateTripRequest メッセージを使用します。これにより、リクエストの field_mask に従って Trip フィールドが更新されます。UpdateTripRequest をご覧ください。

ライドシェア プロバイダは、以下の属性を更新します。

  • ルートの状況。
  • 車両 ID。作成時、または車両をルートに一致させた後のいずれかになります。
  • 乗車、降車、地点の変更。

Driver SDK または Consumer SDK を介してジャーニー共有機能を使用すると、次のフィールドが自動的に更新されます。

  • ルート
  • 到着予定
  • 残りの距離
  • 車両の位置情報
  • 残りのウェイポイント

RPC の Trip または REST の Resource.Trip をご覧ください。

ルート更新情報の Google Cloud Platform ログ

Fleet Engine API は、UpdateTrip エンドポイントへの呼び出しを受信すると、Google Cloud Platform ログを使用してログエントリを書き込みます。ログエントリには、UpdateTrip リクエストの値に関する情報が含まれます。呼び出しが成功すると、返された Trip に関する情報も含まれます。

ハウツー: ルートを検索する

Fleet Engine はルートの検索をサポートしています。前述のように、ルートは 7 日後に自動的に削除されます。そのため、SearchTrips では、すべてのルートの完全な履歴は公開されません。

SearchTrips は柔軟な API ですが、以下のリストでは 2 つのユースケースを想定しています。

  • 車両のアクティブなルートの特定 -- プロバイダは、車両で現在アクティブなルートを特定できます。SearchTripsRequest 内では、vehicle_id は検討中の車両に設定し、active_trips_onlytrue に設定する必要があります。

  • プロバイダと Fleet Engine の状態の調整 - プロバイダは SearchTrips を使用して、トリップ状態と Fleet Engine の状態を一致させることができます。これは、TripStatus で特に重要です。車両に割り当てられたルートの状態が COMPLETE または CANCELED に正しく設定されていない場合、車両は SearchVehicles では含まれません。

この方法で SearchTrips を使用するには、vehicle_id を空のままにして、active_trips_onlytrue に設定し、minimum_staleness をほとんどの貸し出し期間よりも長い時間に設定します。たとえば、1 時間を使用するとします。結果には、完了またはキャンセルされておらず、1 時間以上更新されていないルートが含まれます。プロバイダは、これらのルートを調べて、Fleet Engine でのステータスが正しく更新されていることを確認する必要があります。

トラブルシューティング

DEADLINE_EXCEEDED エラーの場合、Fleet Engine の状態は不明です。プロバイダは CreateTrip を再度呼び出す必要があります。これにより、201(CREATED)または 409(CONFLICT)が返されます。後者の場合、前のリクエストは DEADLINE_EXCEEDED の前に成功しています。ルートエラーの処理について詳しくは、Consumer API ガイド(Android または iOS)をご覧ください。

相乗り乗車サポート

TripType.SHARED をサポートする車両には、複数の SHARED ルートを割り当てることができます。(CreateTrip または UpdateTrip リクエストで)相乗りルートの vehicle_id を割り当てる際に、この共有配車内の車両に割り当てられているすべてのルートについて、通過していないすべての地点の順序を、Trip.vehicle_waypoints で指定する必要があります。RPC の場合は vehicle_waypointsREST の場合は vehicleWaypoints をご覧ください。

複数の宛先のサポート

中間デスティネーションを特定する

Trip(RPC | REST)のフィールド intermediateDestinations とフィールド intermediateDestinationIndex を組み合わせて、目的地を指定します。

中間デスティネーションを更新

中間デスティネーションは UpdateTrip で更新できます。中間デスティネーションを更新する場合は、新たに追加または変更されるデスティネーションだけでなく、アクセスしたことのある中間デスティネーションの完全なリストを指定する必要があります。intermediateDestinationIndex が、新たに追加または変更された中間目的地の位置より後のインデックスを指している場合、新規または更新された中間目的地は車両の waypoints またはルートの remainingWaypoints に追加されません。これは、intermediateDestinationIndex より前の中間デスティネーションは、アクセス済みとして扱われるためです。

ルート状況の変更

中間目的地が渡されたことを示すために、Fleet Engine に送信されるルート ステータス更新リクエストで、(RPC | REST)の intermediateDestinationsVersion フィールドが必要です。ターゲットとなる中間デスティネーションは、フィールド intermediateDestinationIndex で指定します。tripStatusRPC | REST)が ENROUTE_TO_INTERMEDIATE_DESTINATION の場合、[0..N-1] の間の数値は、車両が次に通過する中間目的地を示します。tripStatus が ARRIVED_AT_INTERMEDIATE_DESTINATION の場合、[0..N-1] の数字は車両がどの中間目的地にあるかを示します。

次のコード例は、複数の目的地を含むルートが作成され、そのルートが乗車地点を通過している場合を前提として、ルートのステータスを更新して、最初の中間目的地に向かう途中の状態にする方法を示しています。

Java

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;
}

方法: Fleet Engine API からの通知メッセージに登録する

Fleet Engine API は Google Cloud Pub/Sub を使用して、コンシューマの Google Cloud プロジェクトによって作成されたトピックに関する通知を公開します。Google Cloud プロジェクトの Fleet Engine では、Pub/Sub がデフォルトで有効になっていません。Pub/Sub を有効にするには、サポートケースを提出するか、カスタマー エンジニアにお問い合わせください。

Cloud プロジェクトにトピックを作成するには、こちらの手順に沿って操作してください。 トピック ID は「fleet_engine_notifications」にする必要があります。

トピックは、Fleet Engine API を呼び出すのと同じ Cloud プロジェクトに作成する必要があります。

トピックを作成したら、トピックで公開するための権限を Fleet Engine API に付与する必要があります。これを行うには、作成したトピックをクリックして、新しい権限を追加します。場合によっては、[情報パネルを表示] をクリックして権限エディタを開く必要があります。 プリンシパルは geo-fleet-engine@system.gserviceaccount.com、ロールは Pub/Sub publisher にする必要があります。

通知に登録するように Cloud プロジェクトを設定するには、こちらの手順に沿って操作してください。

Fleet Engine API は、各通知を 2 つの異なるデータ形式(protobufjson)で公開します。各通知のデータ形式は PubsubMessage 属性で示されており、キーは data_format、値は protobuf または json です。

通知スキーマ:

Protobuf

// 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"
    }
  }
}