開始使用 Fleet Engine

透過 Fleet Engine On-Demand Rides 和 Deliveries API,您可以管理行程和訂單進度應用程式的行程和車輛狀態。它會處理 Driver SDK、Consumer SDK 和後端服務之間的交易,後者可透過發出 gRPCREST 呼叫,與 Fleet Engine 通訊。

必要條件

針對開發作業,請確保安裝 Cloud SDK (gcloud) 並通過專案驗證。

殼層

gcloud auth login

畫面上應會顯示成功訊息,例如:

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

檢查隨選乘車和配送解決方案 Fleet Engine API 的設定是否正確。

殼層

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 專案設定

如要設定 Cloud 專案,請先建立專案,再建立服務帳戶。

如要建立 Google Cloud 專案,請按照下列步驟操作:

  1. 使用 Google Cloud 控制台建立 Google Cloud 專案。
  2. 透過 API 和服務資訊主頁,啟用 Local Rides 和 Deliveries API。

服務帳戶與一或多個角色相關聯。它們可用來建立 JSON Web Token,並根據角色授予不同的權限組合。一般而言,為了降低濫用的可能性,您可以建立多個服務帳戶,每個帳戶只設定必要的最低角色組合。

行程和訂單進度會使用下列角色:

角色說明
Fleet Engine 消費者 SDK 使用者

roles/fleetengine.consumerSdkUser
可授予搜尋車輛及擷取車輛和行程相關資訊的權限。具備這個角色的服務帳戶所建立的權杖通常用於共乘/代僱駕駛服務或消費者應用程式的行動裝置。
Fleet Engine 驅動程式 SDK 使用者

roles/fleetengine.driverSdkUser
授予更新車輛位置和路線以及擷取車輛和行程相關資訊的權限。具備這個角色的服務帳戶所建立的權杖通常用於共乘/代僱駕駛服務或外送司機應用程式的行動裝置。
Fleet Engine 服務超級使用者

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 Web Token (JWT) 限制對 Fleet Engine API 的存取權。GitHub 上提供全新的 Fleet Engine 驗證程式庫,可簡化 Fleet Engine JWT 的建構及安全簽署程序。

這個程式庫的優點如下:

  • 簡化 Fleet Engine 權杖的建立程序。
  • 提供除了使用憑證檔案 (例如模擬服務帳戶) 外的權杖簽署機制。
  • 這個外掛程式能將已簽署的權杖附加至從 gRPC 虛設常式或 GAPIC 用戶端發出的傳出要求。

建立用於授權的 JSON Web Token (JWT)

不使用 Fleet Engine 驗證程式庫時,您必須直接在程式碼集中建立 JSON Web Token (JWT)。這需要您深入瞭解 JWT,以及 JWT 與 Fleet Engine 之間的關係。因此,我們強烈建議您善用 Fleet Engine 驗證程式庫。

在 Fleet Engine 中,JSON Web Token (JWT) 會提供短期驗證機制,確保裝置只能修改已獲授權的車輛、行程或工作。JWT 包含標頭和憑證附加資訊部分,標頭區段包含要使用的私密金鑰 (從服務帳戶取得) 和加密演算法等資訊。憑證附加資訊區段包含多項資訊,例如權杖的建立時間、權杖存留時間、聲明存取權的服務,以及用於縮小存取範圍的其他授權資訊 (例如車輛 ID)。

JWT 標頭區段包含下列欄位:

欄位說明
alg 要使用的演算法。「RS256」。
typ 權杖的類型。「JWT」。
兒童 服務帳戶的私密金鑰 ID。您可以在服務帳戶 JSON 檔案的「private_key_id」欄位中找到這個值。請務必使用具備正確層級權限的服務帳戶金鑰。

JWT 憑證附加資訊區段包含下列欄位:

欄位說明
iss 您服務帳戶的電子郵件地址。
sub 您服務帳戶的電子郵件地址。
aud 您服務帳戶的 SERVICE_NAME,在本例中為 https://fleetengine.googleapis.com/
iat 建立權杖時的時間戳記,指定自世界標準時間 1970 年 1 月 1 日 00:00:00 起經過的秒數。請等待 10 分鐘的偏差。如果時間戳記過於在過去或未來的時間,伺服器可能會回報錯誤。
exp 權杖效期的時間戳記,指定自世界標準時間 1970 年 1 月 1 日 00:00:00 起經過的秒數。如果時間戳記超過未來一小時,要求就會失敗。
授權 視用途而定,可以包含 `vehicleid` 或 `tripid`。

建立 JWT 權杖時,系統會將其視為簽署權杖。如需建立及簽署 JWT 的操作說明和程式碼範例,請參閱沒有 OAuth 的服務帳戶授權。然後,您可以將已簽署的權杖附加至 gRPC 呼叫或其他用於存取 Fleet Engine 的方法。

JWT 憑證附加資訊

建立 JWT 酬載時,請在授權區段中新增其他憑證附加資訊,並將索引鍵 vehicleidtripid 設為發出呼叫的車輛 ID 或行程 ID 值。

無論是在行程或車輛上操作,驅動程式 SDK 一律會使用 vehicleid 憑證附加資訊。Fleet Engine 後端會確保車輛在修改前與要求的行程建立關聯。

Consumer SDK 一律使用 tripid 憑證附加資訊。

代僱駕駛服務或外送供應商應使用 vehicleidtripid 搭配「*」,以比對所有車輛和行程。請注意,即使不需要,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"
   }
}

以下是驅動程式應用程式權杖的範例:

{
  "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 欄位中找到這個值。
  • isssub 欄位指定服務帳戶的電子郵件地址。 您可以在服務帳戶 JSON 檔案的 client_email 欄位中找到這個值。
  • 針對 aud 欄位,指定 https://SERVICE_NAME/
  • 針對 iat 欄位,請使用建立權杖時的時間戳記,指定為自世界標準時間 1970 年 1 月 1 日 00:00:00 起經過的秒數。請等待 10 分鐘的偏差。如果時間戳記過於久遠或未來,伺服器可能會回報錯誤。
  • 針對 exp 欄位,使用權杖到期的時間戳記,指定為自世界標準時間 1970 年 1 月 1 日 00:00:00 起的秒數。允許的最大值為 iat + 3600。

簽署要傳遞至行動裝置的 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 屬性是訓練週期後的到期時間 (以秒數為單位),您可以將 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

已簽署的 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)"

車輛及其生命週期

車輛是指代表駕駛座組合的實體。目前,您無法分開追蹤駕駛與車輛。共乘/代僱駕駛服務或外送供應商會使用提供者 ID 建立車輛 (此 ID 必須與包含用來呼叫 Fleet Engine API 的服務帳戶的 Google Cloud 專案 ID 相同) 以及代僱駕駛服務或外送供應商擁有的車輛 ID。

系統會在七天後未透過 UpdateVehicle 更新的車輛會自動刪除。使用已存在的供應商 ID/車輛 ID 組合呼叫 CreateVehicle 會發生錯誤。未經常更新的車輛可以透過下列兩種方式處理:經常使用預期的供應商 ID/車輛 ID 組合呼叫 CreateVehicle,並在車輛已存在時捨棄錯誤;或者,在 UpdateVehicle 傳回 NOT_FOUND 錯誤後呼叫 CreateVehicle

車輛位置更新通知

為了讓 Fleet Engine 發揮最佳效能,請提供一連串車輛位置更新資料。請透過下列其中一種方式提供更新:

  1. 使用最簡單的方法:AndroidiOS
  2. 如果是透過後端轉發位置,或者您使用的裝置不是 Android 或 iOS,請使用自訂程式碼

交通工具類型

車輛實體包含 VehicleType 的必填欄位,其中含有可指定為 AUTOTAXITRUCKTWO_WHEELERBICYCLEPEDESTRIANCategory 列舉。交通工具類型可做為 SearchVehiclesListVehicles 中的篩選條件。

如果類別設為 AUTOTWO_WHEELERBICYCLEPEDESTRIAN,車輛的所有路線規劃都會使用對應的 RouteTravelMode。如果類別設為 TAXITRUCK,則轉送方式將與 AUTO 模式相同。

車輛屬性

車輛實體含有 VehicleAttribute 的重複欄位。這些屬性不會由 Fleet Engine 解譯。SearchVehicles API 中有一個用來要求相符的 Vehicles 的欄位,必須包含設為指定值的所有已納入屬性。

請注意,屬性欄位並非 Vehicle 訊息中其他幾個支援的欄位,例如 vehicle_typesupported_trip_types

車輛剩餘路線控點

車輛實體包含 TripWaypoint (RPC | REST) 的重複欄位,稱為 waypoints(RPC | REST)。這個欄位會按照車輛抵達這些路線的順序,納入行程中剩餘的路線控點。Fleet Engine 會在將行程指派給車輛時計算這個欄位,並在行程狀態改變時更新此欄位。這些路線控點可以透過 TripId 欄位和 WaypointType 欄位識別。

擴大車輛的配對資格

共乘/代僱駕駛服務或外送供應商的服務通常會負責比對行程要求與車輛。服務可以利用車輛屬性,在大量搜尋中加入車輛。舉例來說,供應商可以根據車輛提供的獎勵等級或能力等級來實作相應的屬性組合。舉例來說,三個層級可以是包含布林值的一組屬性:is_bronze_levelis_silver_levelis_gold_level。車輛可以同時符合這三者的資格。如果 Fleet Engine 收到需要銀級功能的行程要求,搜尋就會包含該車輛。以這種方式使用屬性包括提供各種功能的車輛。

更新車輛屬性的方式有兩種。一種是 UpdateVehicle API。使用這個 API 時,整組車輛屬性會設為值。您無法只更新單一屬性。另一個方法是 UpdateVehicleAttributes API。這個方法只會更新要更新的屬性。要求中包含的屬性會設為新的值或新增的值;未指定的屬性則維持不變。

操作說明:打造汽車

請為每輛車建立 Vehicle 實體,才能在車隊中追蹤。

使用 CreateVehicle 端點與 CreateVehicleRequest 建立車輛。

Vehicleprovider_id 必須是 Google Cloud 專案的專案 ID (例如 my-on-Demand-project),其中包含用於呼叫 Fleet Engine 的服務帳戶。請注意,雖然多個服務帳戶可以存取同一個共乘或外送供應商的 Fleet Engine,但 Fleet Engine 目前不支援來自多個 Google Cloud 專案存取相同 Vehicles 的服務帳戶。

您可在 OFFLINEONLINE 狀態中建立 Vehicle。如果已建立 ONLINE,可能會立即傳回 SearchVehicles 查詢的回應。

CreateVehicle 呼叫中可能會包含初始 last_location。在取得允許的情況下,在沒有 last_location 的情況下,Vehicle 不應在 ONLINE 狀態中建立。

如要進一步瞭解車輛類型欄位,請參閱「交通工具類型」一節。

如要進一步瞭解屬性欄位,請參閱車輛屬性

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

請參閱 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 記錄檔

收到對 CreateVehicle 端點發出的呼叫時,Fleet Engine API 會透過 Google Cloud Platform 記錄寫入記錄項目。記錄項目包含 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 通知

建立新車輛時,Fleet Engine API 會透過 Cloud Pub/Sub 發布通知。如要接收這類通知,請按照這裡的操作說明進行。

操作說明:更新車輛位置

如果您不使用驅動程式 SDK 更新車輛的位置,可以直接呼叫車輛位置給 Fleet Engine。針對任何運作中的車輛,Fleet Engine 預期每分鐘位置更新至少一次,且最多每 5 秒更新一次。這些更新只需要 Fleet Engine 驅動程式 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

請參閱 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 呼叫中單一鍵/值組合的值。如要更新特定屬性的值,可以使用 UpdateVehicleAttributes API。

範例

這個範例會啟用 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

請參閱 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 記錄檔

收到對 UpdateVehicle 端點發出的呼叫時,Fleet Engine API 會透過 Google Cloud Platform 記錄寫入記錄項目。記錄項目包含 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 通知

現有車輛更新時,Fleet Engine API 會透過 Cloud Pub/Sub 發布通知。如要接收這類通知,請按照這裡的操作說明進行。

操作說明:搜尋車輛

Fleet Engine 支援搜尋車輛。透過 SearchVehicles API,您可以找出附近哪些司機最適合供乘車或送貨要求等任務使用。SearchVehicles API 會傳回一份排序的駕駛清單,其中包含與機群中車輛屬性相符的任務屬性。詳情請參閱「尋找附近的駕駛」。

範例

搜尋可用車輛時,Fleet Engine 預設會排除主動行程中的車輛。共乘/代僱駕駛服務的服務必須明確將其納入搜尋要求中。以下範例說明如何將這些車輛納入搜尋中,也就是從印尼東部商場到巴來山雅加達會展中心的行程。

殼層

首先,請更新我們在先前步驟中建立的車輛位置,以便符合資格。在現實生活中,這項作業是由在車輛的 Android 或 iOS 裝置上執行的驅動程式 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 中的範例。

請注意,篩選查詢「只」支援篩選車輛屬性,無法用於其他欄位。篩選器查詢可做為具有其他限制的 AND 子句,例如 SearchVehiclesRequest 中的 minimum_capacityvehicle_types

教學:列出車輛

SearchVehicles 經過最佳化處理,可快速找到依排名順序排列的少量車輛,主要用於尋找最適合特定工作的鄰近駕駛。不過,有時您會希望找出所有符合某些條件的車輛,即使有需要分頁瀏覽結果也一樣。ListVehicles 是專為該用途而設計。

ListVehicles API 可讓您找出符合某些特定要求選項的所有車輛。ListVehicles API 會傳回專案中符合某些需求的分頁式分頁清單。

如要篩選車輛屬性,請參閱「車輛篩選查詢」一文。

範例

這個範例會對 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

請參閱 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 具有狀態欄位,可在生命週期內追蹤進度。值會從 NEW 移至 COMPLETE 加上 CANCELEDUNKNOWN_TRIP_STATUS。請參閱 RPC 的 trip_statusREST 適用的 TripStatus

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

您的服務可以從下列任一狀態更新前往CANCELED的行程。服務建立行程時,引擎會將狀態設為 NEWvehicle_id 是選用項目。如同交通工具,服務會在七天過後自動刪除 不會更新的行程如果您的服務嘗試建立具有已存在 ID 的行程,系統會傳回錯誤。如果行程的狀態不是 COMPLETECANCELED,就會視為「有效」。在車輛實體和 SearchTripsRequestactive_trips 欄位中,這項差異非常重要。

當狀態為 NEWCANCELED 時,服務只能變更指派給行程的 vehicle_id。如果駕駛人在路線期間取消行程,則行程狀態必須在 vehicle_id 變更或清除之前設為 NEWCANCELED

在實作返回行程支援時,狀態至關重要。這項支援可讓提供者在車輛處於有效行程時,為車輛指派新的行程。用於建立返回行程的程式碼與單趟行程相同,且會使用相同的車輛 ID。Fleet Engine 會將新行程的起點和目的地新增至車輛的路線控點。如要進一步瞭解返回的行程,請參閱「建立多路線行程」。

行程剩餘路線控點

行程實體包含 TripWaypoint (RPC | REST) 的重複欄位,稱為 remainingWaypoints(RPC | REST)。這個欄位包含車輛必須「按照順序」行駛的所有路線控點,然後以此行程的最終下車地點。計算方法是車輛的其餘路線控點。在「返回返回」和「共乘」用途中,此清單包含會在該行程之前掃遍的其他行程路線控點,但排除這個行程之後的任何路線控點。清單中的路線控點可透過其 TripIdWaypointType 識別。

行程狀態與車輛剩餘路線控點之間的關係

Fleet Engine 收到行程狀態變更要求時,系統會更新車輛的其餘路線控點 (RPC | REST)。當 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 專案時建立的供應商 ID 的字串。
  • trip_id - 共乘服務供應商建立的字串。
  • trip - 含有行程說明基本中繼資料的容器。
    • trip_type:以列舉表示行程的其他乘客是否可能來自同一輛車 (SHARED) 或單人 (EXCLUSIVE),且其他乘客可能來自同一輛車。
    • pickup_point:代表行程起點的 TerminalLocation。請參閱 RPC 參考資料REST 參考資料

建立行程時,您可以提供 number_of_passengersdropoff_pointvehicle_id。雖然這些欄位並非必要,但如果您提供這些欄位,系統會保留這些欄位。系統會忽略所有其他行程欄位。舉例來說,所有行程的開頭都是 NEWtrip_status,即使您在建立要求中傳入 CANCELEDtrip_status 也一樣。

範例

以下範例會建立前往大印尼東購物中心的行程。這趟行程為兩名乘客,且不含其他乘客。Tripprovider_id 必須與專案 ID 相同。在範例中,共乘提供者建立了 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

請參閱 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 記錄檔

收到對 CreateTrip 端點發出的呼叫時,Fleet Engine API 會使用 Google Cloud Platform 記錄寫入記錄項目。記錄項目包含 CreateTrip 要求中值的相關資訊。如果呼叫成功,這項要求也會包含傳回的 Trip 相關資訊。

操作說明:更新行程

Trip 實體包含可讓服務追蹤的功能,以及由 Driver SDK 和消費者 SDK 回報行程進度的欄位。如要更新屬性,請使用 UpdateTripRequest 訊息。這會根據要求的 field_mask 更新行程欄位。請參閱 UpdateTripRequest

共乘服務提供者負責更新下列屬性:

  • 行程狀態。
  • 車輛 ID。可能是在建立時或配對車輛與行程後執行。
  • 上車、下車或路線控點的變更。

透過 Driver SDK 或 Consumer SDK 使用歷程共用功能時,Fleet Engine 會自動更新下列欄位:

  • 路徑介面集
  • 預計抵達時間
  • 剩餘距離
  • 車輛位置
  • 其餘路線控點

請參閱 RPC 中的 TripREST 中的 Resource.Trip

行程更新相關 Google Cloud Platform 記錄檔

收到對 UpdateTrip 端點發出的呼叫時,Fleet Engine API 會使用 Google Cloud Platform 記錄寫入記錄項目。記錄項目包含 UpdateTrip 要求中值的相關資訊。如果呼叫成功,也會包含傳回的 Trip 相關資訊。

操作說明:搜尋行程

Fleet Engine 支援搜尋行程。如前所述,行程會在七天後自動刪除,因此 SearchTrips 不會顯示所有行程的完整記錄。

雖然 SearchTrips 是彈性 API,但下列清單考量的是兩種用途。

  • 判斷車輛的現行行程:供應商可以判斷車輛目前的行程。在 SearchTripsRequest 中,vehicle_id 會設為考慮使用的車輛,而 active_trips_only 應設為 true

  • 協調提供者和 Fleet Engine 狀態:提供者可以使用 SearchTrips 確保行程狀態和 Fleet Engine 的狀態相符。這對 TripStatus 而言尤其重要。如果指派給車輛的行程狀態未正確設為 COMPLETECANCELEDSearchVehicles 就不會納入車輛。

如要透過這種方式使用 SearchTrips,請保留 vehicle_id 空白、將 active_trips_only 設為 true,並將 minimum_staleness 設為大於大多數行程所需時間的時間。例如一小時。結果包含沒有 COMPLETE 或 已取消的行程,且超過一小時未更新的行程。供應商應檢查這些行程,確保 Fleet Engine 中的狀態已正確更新。

疑難排解

如果發生 DEADLINE_EXCEEDED 錯誤,機群引擎的狀態不明。提供者應再次呼叫 CreateTrip,這會回傳 201 (CREATED) 或 409 (CONFLICT)。如果是後者,先前的要求在 DEADLINE_EXCEEDED 之前成功。如要進一步瞭解如何處理行程錯誤,請參閱 Consumer API 指南:AndroidiOS

共乘支援

您可以將多個 SHARED 行程指派給支援 TripType.SHARED 的車輛,為共用行程的 vehicle_id (在 CreateTripUpdateTrip 要求中) 時,您必須透過 Trip.vehicle_waypoints 為共用行程中的所有行程指定所有未傳遞路線控點的順序,指定順序。 請參閱 RPC 的 vehicle_waypointsREST 適用的 vehicleWaypoints

支援多個目的地

識別中繼目的地

行程中的 intermediateDestinationsintermediateDestinationIndex 欄位 (RPC | REST) 會合併以用於表示目的地。

更新中繼目的地

您可以透過 UpdateTrip 更新中繼目的地。更新中繼目的地時,您必須提供完整的中繼目的地清單 (包括造訪過的目的地),而不只是新增或修改過的中繼目的地。當 intermediateDestinationIndex 指向新增/修改的中繼目的地位置之後的索引時,新的/更新的中繼目的地就不會新增至車輛的 waypoints 或行程的 remainingWaypoints。這是因為系統會將 intermediateDestinationIndex 之前的任何中繼目的地視為已造訪。

行程狀態變更

傳送至 Fleet Engine 的行程狀態更新要求中,(RPC | REST) 中的 intermediateDestinationsVersion 欄位為必要欄位,以表示已通過中繼目的地。目標中繼目的地是透過 intermediateDestinationIndex 欄位指定。當 tripStatus (RPC | 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 會以 protobufjson 兩種不同的資料格式發布每則通知。每則通知的資料格式會在 PubsubMessage 屬性中註明,索引鍵為 data_format,值為 protobufjson

通知結構定義:

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