開始使用 Fleet Engine

透過 Fleet Engine 隨選乘車和 Deliveries API,你可以管理行程和訂單進度應用程式的車輛狀態。這個程式可處理驅動程式 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 ...

確認隨選乘車和運送服務 Solution Fleet Engine API 設定正確。

殼層

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

如果這個指令導致錯誤,請與專案管理員和 Google 支援代表聯絡,以取得存取權。

Logging

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。

服務帳戶與一或多個角色相關聯。這些權杖可用來建立 JSON Web Token,以便根據角色授予不同的權限組合。一般而言,為減少濫用的可能性,您可以建立多個服務帳戶,每個帳戶至少要具備一組必要的角色。

Trip 和 Order Progress 使用下列角色:

角色說明
Fleet Engine Consumer SDK 使用者

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

roles/fleetengine.driverSdkUser
授予更新車輛位置和路線以及擷取車輛和行程資訊的權限。由具備這個角色的服務帳戶建立的憑證,通常用於您的共乘或貨運司機應用程式的行動裝置。
Fleet Engine 隨選管理員

roles/fleetengine.ondemandAdmin
授予所有車輛和行程資源的讀取及寫入權限。具備這個角色的主體不需要使用 JWT,應改用應用程式預設憑證。系統會忽略自訂 JWT 憑證附加資訊。這個角色應限制在受信任的環境 (客戶後端) 內。
FleetEngine 服務超級使用者 **(已淘汰)**

roles/fleetengine.serviceSuperUser
授予所有車輛和行程 API 的權限。具備這個角色的服務帳戶建立的權杖,通常會用於後端伺服器。這個角色已淘汰。建議改用 roles/fleetengine.ondemandAdmin

舉例來說,您可以分別針對這三個角色建立服務帳戶,並為其指派各自的角色。

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 的存取權。新版 Fleet Engine 驗證程式庫可透過 GitHub 取得,可簡化 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 時,請務必使用驅動程式或 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 屬性是 Epoch 紀元後目前的時間長度 (以秒為單位),如要擷取時間,請在終端機中執行 date +%sexp 屬性是 Epoch 紀元後經過的到期時間 (以秒為單位),如要計算,請將 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 檔案中。權杖有效期限為一小時。

您現在可以對清單車輛 REST 端點執行 curl 指令來測試權杖:

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

車輛及其生命週期

車輛是代表駕駛車組合的實體。目前您無法分別追蹤駕駛與車輛。代僱駕駛服務或貨運供應商使用供應商 ID (必須與用於呼叫 Fleet Engine API 的服務帳戶) 的 Google Cloud 專案 ID 相同,以及共乘/貨運供應商自有車輛 ID 建立車輛。

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

車輛位置更新

為獲得最佳的 Fleet Engine 效能,請提供一連串的車輛位置更新。請使用下列其中一種方式提供這些更新:

  1. 使用驅動程式 SDK - AndroidiOS -- 最簡單的選項。
  2. 使用自訂程式碼 -- 如果位置是透過後端轉送,或者您使用 Android 或 iOS 以外的裝置,就很適合使用。

交通工具類型

車輛實體包含 VehicleType 的必填欄位,其中包含 Category 列舉,可指定為 AUTOTAXITRUCKTWO_WHEELERBICYCLEPEDESTRIAN。車輛類型可做為 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 目前不支援來自存取相同 Vehicles 的多個 Google Cloud 專案的服務帳戶。

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

CreateVehicle 呼叫可包含初始 last_location。在允許的情況下,Vehicle 不可在沒有 last_location 的情況下以 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 平台記錄檔

Fleet Engine API 會在收到呼叫 CreateVehicle 端點時,透過 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 發布通知。如要接收這類通知,請按照這裡的指示操作。

操作說明:更新車輛位置

如未使用 Driver 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.

HOW-TO:更新其他車輛欄位

車輛狀態其他屬性的更新頻率少於位置更新的頻率。如要更新 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 平台記錄檔

Fleet Engine API 會在收到呼叫 UpdateVehicle 端點時,透過 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 會排除有效行程的車輛。共乘服務或外送服務供應商的服務必須在搜尋要求中明確納入這些服務。以下範例說明如何在搜尋從大印尼東部購物中心到巴萊西德雅加達會議中心 (Balai Sidang Jakarta Convention Center) 行程的車輛時,納入這些車輛。

殼層

首先,請更新我們在先前步驟中建立的車輛位置,確保車輛符合資格。實際上,在車輛內 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

HOW-TO:刊登車輛清單

SearchVehicles 經過最佳化調整,可快速地依排序順序找到少量車輛,主要用於尋找最適合一項工作的鄰近司機。然而,有時您會想找出所有符合某些條件的車輛,即使需要對結果進行分頁處理也一樣。ListVehicles 專為該用途而設計。

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

如要篩選車輛屬性,請參閱車輛篩選查詢

範例

此範例使用 filter 字串對 vehicle_type 和屬性執行篩選。

殼層

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_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 欄位而言相當重要。

行程有效時,您的服務只能變更指派給行程的 vehicle_id。舉例來說,如果駕駛人在路線取消時取消行程,而行程重新指派給其他車輛,您就可以執行這項操作。

在實作返回行程支援時,狀態是相當重要的。這項支援可讓供應商在車輛仍在執行期間,指派新的行程。建立返回行程的程式碼與單一行程相同,並使用相同車輛 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。雖然這些欄位並非必要,但如果您提供這些欄位,系統會保留。系統會忽略所有其他行程欄位。舉例來說,即使您在建立要求中傳入 CANCELEDtrip_status,所有行程的 trip_status 都會以 NEW 為開頭。

範例

以下範例會建立前往大印尼東購物中心的行程。這趟行程適用於兩名乘客,且專屬於一人。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 和 Consumer SDK 回報行程的進度。如要更新屬性,請使用 UpdateTripRequest 訊息。這會根據要求的 field_mask 更新行程欄位。請參閱 UpdateTripRequest

代僱駕駛服務提供者負責更新下列屬性:

  • 行程狀態。
  • 車輛 ID。建立時或將車輛與行程配對後。
  • 上車、下車或路線控點有所變更。

透過驅動程式 SDK 或消費者 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 尤其重要。如果指派給車輛的行程狀態未正確設為 COMPLETECANCELED,則 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 指南:AndroidiOS

共乘行程支援

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

支援多個目的地

識別中繼目的地

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

更新中繼目的地

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

行程狀態變更

在傳送至 Fleet Engine 的 Trip 狀態更新要求中,必須提供 intermediateDestinationsVersion (RPC | REST) 的欄位,表示已傳遞中繼目的地。指定的中繼目的地是透過 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"
    }
  }
}