開始使用 Fleet Engine

Fleet Engine Deliveries API 可讓您針對送貨第一英里和最後一里的車隊活動建立模型。Deliveries API 會透過 Android 和 iOS 適用的 Driver SDK 公開,也可以透過 HTTP REST 或 gRPC 呼叫直接使用。

初始設定

Fleet Engine Deliveries API 是透過 Google Cloud 控制台設定。如要瞭解在主控台中要採取的步驟,以及如何建立 JSON Web Token 以進行授權,請參閱驗證與授權。如要進一步瞭解如何使用控制台,請參閱 Google Cloud 控制台說明文件

確認設定正確無誤

建立服務帳戶後,請確認設定已完成,您可以建立貨運車輛。透過在工作流程的這個階段進行驗證,可確保設定專案時可能發生的常見授權問題順利解決。按照驗證設定指南操作。 本指南詳細說明如何使用 gcloud 指令列公用程式,測試設定的兩個重要部分:授權權杖簽署和試用配送車輛建立。

或者,您也可以使用 Fleet Engine 驗證範例指令碼測試設定。

用戶端程式庫

我們使用多種常見的程式設計語言發布用戶端程式庫。這些程式庫會比原始 REST 或 gRPC 提供更優質的開發人員體驗。如要瞭解如何取得伺服器應用程式的用戶端程式庫,請參閱用戶端程式庫一文。

本文件中的 Java 範例假設您已熟悉 gRPC。

資料結構

Deliveries API 使用兩種資料結構來為貨運的取貨和交付模型建立模型:

  • 用於運送貨物的運送車輛。
  • 出貨和貨品交付工作。

此外,您也可以使用工作模擬當天的駕駛作業和排定的停靠站。

運輸車輛

貨運車輛會將貨物從倉庫傳送到送貨地點,以及從取貨地點到倉庫。在某些情況下,他們也可以將貨物從取貨地點直接傳輸至送貨地點。

您可以使用 Driver SDK 在 Fleet Engine 中建立 DeliveryVehicle 物件,並傳送位置更新資訊以便進行運送和車隊追蹤。

工作

每輛車都有獲派的工作。包括自取或外送工作、司機須提供的休息時間,或排定的停靠站或客戶所在地點的停靠站。每項工作都必須有不重複的工作 ID,但可能會共用相同的追蹤 ID。這些工作和排程的順序會用來計算每項工作的預計到達時間。

使用 Driver SDK 工作管理員在 Fleet Engine 中建立工作。

貨運工作

出貨工作與出貨或交貨地點有關。建立運送工作時,您必須指定追蹤號碼或 ID。 您也必須指定停留時間,以將完成工作、尋找停車位或步行前往交接地點的時間納入考量。

  • 建立取貨工作來取貨,並指定取貨地點、追蹤號碼或 ID。
  • 建立貨品交付工作,指定寄送地點和追蹤號碼或 ID。

無法使用的工作

在車輛無法提供自取或配送服務的特定時間範圍內建立無法使用的工作。這可能是因加油管或駕駛人休息而暫時停用。

建立工作時,請指定中斷時間點的長度。廣告插播不必在特定位置進行,但指定位置可以提供更準確的一整天預計到達時間。

已排定的停止工作

建立已排定的停靠工作,以便模擬交通工具停靠站的停靠站。例如,您可以在特定位置為每日排定的每日收集停靠站建立排定的停靠站工作,與同一位置的其他交付或取貨無關。您也可以為集合建立排定的停靠站工作,或在服務中心和服務點建立饋送車輛轉乘或停靠模型。

如要瞭解每個資料結構中包含的特定欄位,請參閱 DeliveryVehicle (gRPCREST) 和 Task (gRPCREST) 的 API 參考說明文件。

工作 ID 指南

工作 ID 不得重複,且不得揭露任何個人識別資訊 (PII) 或清除文字資料。

工作 ID 必須符合下列格式規定:

  • ID 必須是有效的萬國碼 (Unicode) 字串。
  • ID 長度不得超過 64 個字元。
  • 系統會根據 Unicode 正規化表單 C 正規化 ID。
  • ID 不得包含下列任一 ASCII 字元:「/」、「:」、「」、「」、「?」或「#」。

以下是有效工作 ID 的範例:

  • 566c33d9-2a31-4b6a-9cd4-80ba1a0c643b
  • e4708eabcfa39bf2767c9546c9273f747b4626e8cc44e9630d50f6d129013d38
  • NTA1YTliYWNkYmViMTI0ZmMzMWFmOWY2NzNkM2Jk

下表顯示無效工作 ID 的示例:

工作 ID 無效 原因
8/31/2019-20:48-46.70746,-130.10807,-85.17909,61.33680 違反 PII 和字元規定:逗號、半形句號、冒號和斜線。
JohnDoe-577b484da26f-Cupertino-SantaCruz 違反 PII 規定。
4R0oXLToF”112 Summer Dr. East Hartford, CT06118”577b484da26f8a 違反 PII 和字元規定:空格、半形逗號和引號。超過 64 個半形字元。

車輛生命週期

DeliveryVehicle 物件代表第一英里或最後一英里的運送車輛。您可以使用下列指令建立 DeliveryVehicle 物件:

  • Google Cloud 專案的專案 ID,其中包含用來呼叫 Fleet Engine API 的服務帳戶。
  • 客戶擁有的車輛 ID。

每輛車的車輛 ID 皆不得重複。除非該車沒有正在執行的工作,否則請勿重複用於其他車輛。

呼叫 UpdateDeliveryVehicle 時,請務必檢查 NOT_FOUND 錯誤,並視需要呼叫 CreateDeliveryVehicle 建立新車輛。未使用 UpdateDeliveryVehicle 更新的 DeliveryVehicle 物件會在七天後自動刪除。請注意,使用已存在的專案 ID/車輛 ID 組合呼叫 CreateDeliveryVehicle 會產生錯誤。

交通工具類型

車輛實體包含 VehicleType 的選用欄位,其中包含 Category 列舉,可指定為 AUTOTWO_WHEELERBICYCLEPEDESTRIAN。如果未設定這個欄位,預設為 AUTO

車輛的所有路線都會針對車輛類型使用對應的 RouteTravelMode

車輛屬性

DeliveryVehicle 實體包含 DeliveryVehicleAttribute 的重複欄位。ListDeliveryVehicles API 包含 filter 欄位,可以將傳回的 DeliveryVehicle 實體限制為具有指定屬性的實體,DeliveryVehicleAttribute 不會影響 Fleet Engine 轉送行為。

請勿在屬性中加入個人識別資訊或機密資訊,因為使用者可能會看到這個欄位。

工作的生命週期

您可以使用 Deliveries API gRPC 或 REST 介面建立、更新 Fleet Engine 中的工作,並進行交叉比對。

Task 物件具有狀態欄位,可追蹤生命週期中的進度。值會從「OPEN」移至「已關閉」。新工作會以 OPEN 狀態建立,這代表:

  • 這項工作尚未指派給快遞車輛。
  • 貨運車輛尚未通過任務的指定車輛停靠站。

只能指派處於「開放式」狀態的車輛。

將工作從車輛停靠站清單中移除即可取消。其狀態隨後會自動設為「已關閉」。

當工作的車輛完成車輛停靠站後,請將工作的出站欄位更新為「SUCCEEDED」(成功) 或「FAILED」(失敗),並指定事件的時間戳記。工作結果可在工作完成之前或之後隨時設定,但只能設定一次。

接著,JavaScript 運送追蹤程式庫可以指出工作結果。工作狀態會自動設為「已關閉」。詳情請參閱「使用 JavaScript 運送追蹤程式庫追蹤運送狀態」。

如同車輛,會刪除七天後未更新的工作,嘗試使用已存在的 ID 建立工作,並傳回錯誤。

注意:Fleet Engine 不支援明確刪除工作。服務會在七天後自動刪除工作,而不會更新。如果您想保留工作資料超過七天,必須自行實作該功能。

工作屬性

Task 實體包含 TaskAttribute 的重複欄位,該欄位可包含字串、數字和布林值的 3 種類型之一。ListTasks API 包含 filter 欄位,可將傳回的 Task 實體限制為具有指定屬性的實體。TaskAttribute 不會影響 Fleet Engine 轉送行為。

請勿在屬性中加入個人識別資訊或機密資訊,因為使用者可能會看到這個欄位。

管理車輛和任務的生命週期

如要在系統中管理車輛和工作的生命週期,請使用 Fleet Engine Deliveries API 建立、更新及追蹤車輛及其相關工作。內部系統可做為 Fleet Engine Deliveries API 為您擴充數據的可靠資料來源。

與此同時,驅動程式應用程式會直接與 Fleet Engine 進行通訊,藉此更新裝置位置和路徑資訊。這個模型可讓 Fleet Engine 有效管理即時位置資訊,並將資料直接傳送至追蹤程式庫,然後提供給需要訂單狀態更新的消費者。

舉例來說,假設您遇到下列情況:

  • 駕駛人靠近快遞站,Fleet Engine 會將裝置位置資訊傳送至追蹤程式庫,讓消費者應用程式用來通知消費者包裹的距離。
  • 司機完成運送後,在駕駛人應用程式中按一下「Shipment delivered」按鈕。
  • 這樣就能將資訊傳送到後端系統,進而執行必要的商家驗證和驗證步驟。
  • 系統確認工作為「SUCCEEDED」(成功),並使用 Deliveries API 更新 Fleet Engine。

下圖以一般層級說明這些程序。也會顯示您系統、用戶端和 Fleet Engine 之間的標準關係。

使用 Deliveries API 圖表

用戶端權杖管理

任何源自驅動程式應用程式且直接傳送至 Fleet Engine 的位置更新都必須需要授權權杖。如果要處理從用戶端到 Fleet Engine 的更新,建議您為驅動程式應用程式提供限定範圍的權杖,使其只能更新 Fleet Engine 中的裝置位置。針對這個類型的權杖,您會使用名為 Fleet Engine Delivery UnTrusted Driver User 的服務帳戶角色。這可確保來自行動裝置 (視為低信任的環境) 的呼叫,符合最低權限原則

其他服務帳戶角色

如果您要授權驅動程式應用程式直接對 Fleet Engine 進行直接更新,而不受到「不受信任的驅動程式」角色限制 (例如執行特定工作更新作業),則可以使用「信任的驅動程式」角色。如要瞭解使用「信任的驅動程式」角色的模型,請參閱「信任的驅動程式模型」一文。

如要進一步瞭解不受信任和信任的驅動程式角色的使用方式,請參閱 Cloud 專案設定一文。

模擬工作日

下表說明第一或最後里程司機可能在運送及物流公司的工作日。貴公司的詳細資料可能有些差異,但您一定可以看出,每天的工作方式可能不同。

時間活動模擬
當天開始後 24 小時內 調度員將貨物指派到運送車輛或路線, 您可以提前在 Fleet Engine 中建立貨物運送、取貨、包裹寄送等工作。舉例來說,您可以建立出貨工作出貨工作已排定的無法使用時間已排定的停靠站

運送包裹組合和送達順序確定後,應將工作指派給車輛。
當天開始時間 駕駛人只要登入駕駛應用程式,駕駛當天就能從車站展開一天。 初始化 Delivery Driver API。視需要在 Fleet Engine 中建立運送車輛
司機將貨物載入到貨運車輛上,掃描運送過程。 如未事先建立運送工作,請在掃描時建立運送任務
驅動程式會確認要執行的工作順序。 如果該工作並未提前建立,請建立取貨工作已排定的無法使用時間已排定的停靠站
駕駛會留下資產回收站,並承諾下一項待完成的工作。 提交完成訂單,指派所有工作或部分任務給車輛。
司機送貨。 抵達傳遞停靠站後,請執行與車輛抵達停靠站相關的動作。提交運送資訊後,請關閉運送工作,並視需要輸入商店運送狀態和其他中繼資訊。完成停車到下一個停靠站的所有工作後,請執行與車輛完成停靠站車輛路線前往下一個停靠站的動作。
司機遇見餵食器,將額外的貨物運送到貨車上。 如果在饋送器和運送車輛之間轉乘,則應模擬為排定的停靠站

在轉移及掃描運送商品後,建立提交工作 (如果尚未建立)。接著,請將工作指派給車輛更新工作排序,以更新工作完成順序。
司機會收到上車要求通知。 接受取貨要求後,請建立運送取貨工作。接著,請將工作指派給車輛更新工作排序,以更新工作執行順序。
中午 駕駛會在午休時間中午休。 如果地點連結至無法使用的工作,請將其視為任何其他工作。執行與車輛相關的操作 抵達停靠站車輛完成停靠站車輛行駛到下一個停靠站

否則,在廣告插播結束之前,你無須採取其他行動。 接著,確認接下來和其餘的工作,然後更新工作排序,即可移除工作。
司機到貨。 模擬方式與傳遞停靠站類似。執行與抵達停靠站關閉工作相關的動作,並視需要選擇儲存運送狀態和其他中繼資訊。完成停車到下一個停靠站的所有工作後,請執行與車輛完成停靠站車輛路線前往下一個停靠站的動作。注意:為確保帳單正確無誤,所有取貨服務都必須有相應的運送工作。如果要將取貨服務送到司機當天同一路線的其他位置,建議您將外送任務建立模型,與路線上的任何其他外送工作相同。如果司機將上車地點帶回去庫,建議您在 Depot 目的地建立運送工作。
司機安排了一個站點,讓你透過集運箱領取貨物。 模擬的操作方式與任何其他上車停靠站相同。執行與車輛抵達停靠站關閉工作相關的動作。完成停靠站的所有工作,並開始開車前往下一個停靠站後,請執行與車輛完成停靠站車輛路線前往下一個停靠站的動作。
配送人員會收到送貨到替代地點的通知。 將原始運送工作狀態設為「COMPLETED」,並為新的交貨地點建立新的運送任務。詳情請參閱重新轉送運送路徑
司機嘗試交付包裹,但無法順利交付。 模擬方式與成功提交停靠站類似,將提交工作標示為已完成。執行與車輛抵達停靠站相關的動作。如未能出貨,請關閉工作,並視需要儲存運送狀態和其他中繼資訊。完成停車到下一個停靠站的所有工作後,請執行與車輛完成停靠站車輛路線前往下一個停靠站的動作。
受訪駕駛人收到保留 (未配送) 商品的通知。 收到並確認通知後,請將工作狀態設為「COMPLETED」。
通知司機接下來要交付特定運送商品,並變更承諾的配送訂單。 更新工作排序
司機選擇送貨。 更新工作排序,然後照常繼續進行。
司機將多部貨運運送至同一地點。 這個模式與單一貨運停靠站類似。抵達停靠站後,請執行與車輛抵達停靠站相關的動作。每次出貨後,請關閉每項工作,並視需要儲存運送狀態和其他中繼資訊。完成停車到下一個停靠站的所有工作後,請執行與車輛完成停靠站車輛路線前往下一個停靠站的動作。
當天結束時間 司機回歸台。 如果司機將包裹在路線中取貨,並送到倉庫,您也必須建立和結清各個包裹做為提交工作,確保帳單正確無誤。為此,你可以像其他放送停靠站一樣,建立資料庫。即使該倉庫未用來當做傳遞停靠站,您還是可以選擇將該倉庫模擬為排定的停靠站。如此一來,司機就可以查看返回至倉庫的路線,並查看預計到達時間。

瞭解位置更新通知

外送車輛從某個停靠站 (包括倉庫) 抵達時,系統會將位置更新資訊傳送到 Fleet Engine,直到抵達下一個停靠站為止。由於系統不會自動偵測這些事件,因此您必須以程式輔助方式標示。使用可偵測交通方式變更的程式庫,觸發將必要的通知傳送至 Fleet Engine。

駕駛人未開車時,應暫停位置更新功能,因為在建築物內,位置訊號品質會大幅降低。

你可以在 Driver SDK 中設定位置更新頻率。根據預設,系統每 10 秒會傳送更新一次。

車輛停靠站和配送地點

車輛停靠站是指運輸車輛完成貨運工作或其他任務。它可能是存取點,例如載入座架或道路駕駛位置。

交貨地點是指貨品的送貨或取貨地點。抵達和出發地點可能需要從車輛停靠站步行。

舉例來說,當司機送貨到購物中心的店面時,最接近商店入口處的購物中心停車場就會停靠車輛。這是車輛停靠站。接著,駕駛人從車輛停靠站走到商店所在的購物中心內。這是交貨地點。

為了讓使用者享有最佳的運送追蹤體驗,請考慮將運送工作指派給車輛停靠站的方式,但請注意,系統會回報運送任務的剩餘車輛停靠站數量,協助使用者查看運送進度。

舉例來說,如果司機要為同一棟辦公大樓提供多項運送工作,不妨考慮將所有遞送工作指派給單一車輛停靠站。如果每項交貨工作都指派給自己的車輛停靠站,運送追蹤體驗對使用者而言比較不實用,因為系統只有在車輛在一定數量的車輛停靠站內後才能進行追蹤。如果在短時間內完成許多車輛停靠,使用者沒有時間可以追蹤交貨進度。

使用行動 SDK

呼叫 Driver SDK 之前,請務必先將其初始化。

初始化 Delivery Driver API

在 Driver SDK 中初始化 Delivery Driver API 之前,請務必初始化 Navigation SDK。 接著初始化 Delivery Driver API,如以下範例所示:

static final String PROVIDER_ID = "provider-1234";
static final String VEHICLE_ID = "vehicle-8241890";

NavigationApi.getNavigator(
   this, // Activity.
   new NavigatorListener() {
     @Override
     public void onNavigatorReady(Navigator navigator) {
       DeliveryDriverApi.createInstance(DriverContext.builder(getApplication())
         .setNavigator(navigator)
         .setProviderId(PROVIDER_ID)
         .setVehicleId(VEHICLE_ID)
         .setAuthTokenFactory((context) -> "JWT") // AuthTokenFactory returns JWT for call context.
         .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(getApplication()))
         .setNavigationTransactionRecorder(NavigationApi.getNavigationTransactionRecorder(getApplication()))
         .setStatusListener((statusLevel,statusCode,statusMsg) -> // Optional, surfaces polling errors.
             Log.d("TAG", String.format("New status update. %s, %s, %s", statusLevel, statusCode, statusMsg)))
         .build));
     }

     @Override
     public void onError(int errorCode) {
       Log.e("TAG", String.format("Error loading Navigator instance: %s", errorCode));
     }
   });

應用情境

本節說明如何使用 Deliveries API 建立常見用途模型。

專屬實體 ID

Fleet Engine 無法解讀 REST 呼叫中使用的專屬實體 ID 的格式和值。請避免使用自動遞增 ID,並確認 ID 不含任何個人識別資訊 (PII),例如駕駛人的電話號碼。

建立車輛

您可以透過 Driver SDK 或伺服器環境建立車輛。

gRPC

如要建立新車輛,您必須向 Fleet Engine 發出 CreateDeliveryVehicle 呼叫。請使用 CreateDeliveryVehicleRequest 物件定義新快遞車輛的屬性。請注意,根據使用者指定 ID 的 API 規範,系統會忽略 Name 欄位指定的任何值。您應該使用 DeliveryVehicleId 欄位設定車輛 ID。

建立 DeliveryVehicle 時,您可以選擇指定下列欄位:

  • 屬性
  • 最後位置
  • 類型

所有其他欄位不必設定;否則 Fleet Engine 會傳回錯誤,因為那些欄位處於唯讀狀態,或只能透過 UpdateDeliveryVehicle 呼叫更新。

如要建立車輛但不設定任何選填欄位,可以在 CreateDeliveryVehicleRequest 中取消設定 DeliveryVehicle 欄位。

以下範例說明如何使用 Java gRPC 程式庫建立車輛:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String VEHICLE_ID = "vehicle-8241890"; // Avoid auto-incrementing IDs.

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Vehicle settings
String parent = "providers/" + PROJECT_ID;
DeliveryVehicle vehicle = DeliveryVehicle.newBuilder()
  .addAttributes(DeliveryVehicleAttribute.newBuilder()
    .setKey("route_number").setValue("1"))  // Opaque to the Fleet Engine
  .build();

// Vehicle request
CreateDeliveryVehicleRequest createVehicleRequest =
  CreateDeliveryVehicleRequest.newBuilder()  // No need for the header
      .setParent(parent)
      .setDeliveryVehicleId(VEHICLE_ID)     // Vehicle ID assigned by the Provider
      .setDeliveryVehicle(vehicle)
      .build();

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

try {
  DeliveryVehicle createdVehicle =
    deliveryService.createDeliveryVehicle(createVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case ALREADY_EXISTS:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境建立車輛,請向 CreateDeliveryVehicle 發出 HTTP REST 呼叫:

POST https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles?deliveryVehicleId=<id>

<id> 是車隊運送車輛的專屬 ID

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

POST 主體代表要建立的 DeliveryVehicle 實體。您可以指定下列選填欄位:

  • attributes
  • 最後位置

範例 curl 指令:

# Set $JWT, $PROJECT_ID, and $VEHICLE_ID in the local
# environment
curl -X POST "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles?deliveryVehicleId=${VEHICLE_ID}" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
--data-binary @- << EOM
{
  "attributes": [{"key": "model", "value": "sedan"}],
  "lastLocation": {"location": {"latitude": 12.1, "longitude": 14.5}}
}
EOM

根據使用者指定 ID 的 API 規範,Fleet Engine 會忽略 DeliveryVehicle 實體的 name 欄位。所有其他欄位都無法設定;否則 Fleet Engine 會傳回錯誤,因為那些欄位處於唯讀狀態,或只能透過 UpdateDeliveryVehicle 呼叫更新。

如要建立車輛但不設定任何欄位,請將 POST 要求的內文留空。新建的車輛會具備從 POST 網址 deliveryVehicleId 參數擷取的車輛 ID。

範例 curl 指令:

# Set $JWT, $PROJECT_ID, and $VEHICLE_ID in the local
# environment
curl -X POST "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles?deliveryVehicleId=${VEHICLE_ID}" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}"

建立運送取貨工作

您可以使用 Driver SDK 或伺服器環境建立送貨取貨工作。

gRPC

以下範例說明如何使用 Java gRPC 程式庫建立運送取貨工作:

static final String PROJECT_ID = "my-delivery-co-gcp-project";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String parent = "providers/" + PROJECT_ID;
Task task = Task.newBuilder()
  .setType(Task.Type.PICKUP)
  .setState(Task.State.OPEN)
  .setTrackingId("my-tracking-id")
  .setPlannedLocation(               // Grand Indonesia East Mall
    LocationInfo.newBuilder().setPoint(
      LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
  .setTaskDuration(
    Duration.newBuilder().setSeconds(2 * 60))
  .setTargetTimeWindow(
    TimeWindow.newBuilder()
      .setStartTime(Timestamp.newBuilder().setSeconds(1680123600))
      .setEndTime(Timestamp.newBuilder().setSeconds(1680130800)))
  .addAttributes(TaskAttribute.newBuilder().setKey("foo").setStringValue("value"))
  .addAttributes(TaskAttribute.newBuilder().setKey("bar").setNumberValue(10))
  .addAttributes(TaskAttribute.newBuilder().setKey("baz").setBoolValue(false))
  .build();

// Task request
CreateTaskRequest createTaskRequest =
  CreateTaskRequest.newBuilder()  // No need for the header
      .setParent(parent)          // Avoid using auto-incrementing IDs for the taskId
      .setTaskId("task-8241890")  // Task ID assigned by the Provider
      .setTask(task)              // Initial state
      .build();

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

try {
  Task createdTask = deliveryService.createTask(createTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case ALREADY_EXISTS:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境建立運送取貨工作,請對 `CreateTask' 發出 HTTP REST 呼叫:

POST https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks?taskId=<id>

<id> 是工作的專屬 ID。不得為運送的追蹤號碼。如果系統中沒有工作 ID,您可以產生通用唯一識別碼 (UUID)。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    類型 類型.PICKUP
    最終的隱藏狀態 州/省.OPEN
    追蹤 ID 您用來追蹤貨物的編號或 ID。
    PlannedLocation 工作要完成的位置,在本例中為運送取貨地點。
    工作時間長度 預計在取貨地點收取貨物的預計時間 (以秒為單位)。

  • 選填欄位:

    欄位
    目標時間範圍 工作應完成的時間範圍。這目前不會影響轉送行為。
    attributes 自訂 Task 屬性的清單。每個屬性都必須有專屬金鑰。

建立時會忽略實體中的所有其他欄位。如果要求包含指派的 DeliveryVehicleId,則 Fleet Engine 會擲回例外狀況。您可以使用 UpdateDeliveryVehicleRequest 指派工作。詳情請參閱「將工作指派給車輛」。

範例 curl 指令:

# Set $JWT, $PROJECT_ID, $TRACKING_ID, and $TASK_ID in the local
# environment
curl -X POST "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks?taskId=${TASK_ID}" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "type": "PICKUP",
  "state": "OPEN",
  "trackingId": "${TRACKING_ID}",
  "plannedLocation": {
     "point": {
        "latitude": -6.195139,
        "longitude": 106.820826
     }
  },
  "taskDuration": "90s",
  "targetTimeWindow": {
    "startTime": "2023-03-29T21:00:00Z",
    "endTime": "2023-03-29T23:00:00Z"
  }
}
EOM

建立運送任務

您可以使用 Driver SDK 或伺服器環境建立運送工作。

gRPC

以下範例說明如何使用 Java gRPC 程式庫建立出貨工作:

static final String PROJECT_ID = "my-delivery-co-gcp-project";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String parent = "providers/" + PROJECT_ID;
Task task = Task.newBuilder()
  .setType(Task.Type.DELIVERY)
  .setState(Task.State.OPEN)
  .setTrackingId("my-tracking-id")
  .setPlannedLocation(               // Grand Indonesia East Mall
    LocationInfo.newBuilder().setPoint(
      LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
  .setTaskDuration(
    Duration.newBuilder().setSeconds(2 * 60))
  .setTargetTimeWindow(
    TimeWindow.newBuilder()
      .setStartTime(Timestamp.newBuilder().setSeconds(1680123600))
      .setEndTime(Timestamp.newBuilder().setSeconds(1680130800)))
  .addAttributes(TaskAttribute.newBuilder().setKey("foo").setStringValue("value"))
  .addAttributes(TaskAttribute.newBuilder().setKey("bar").setNumberValue(10))
  .addAttributes(TaskAttribute.newBuilder().setKey("baz").setBoolValue(false))
  .build();

// Task request
CreateTaskRequest createTaskRequest =
  CreateTaskRequest.newBuilder()  // No need for the header
      .setParent(parent)          // Avoid using auto-incrementing IDs for the taskId
      .setTaskId("task-8241890")  // Task ID assigned by the Provider
      .setTask(task)              // Initial state
      .build();

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

try {
  Task createdTask = deliveryService.createTask(createTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case ALREADY_EXISTS:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要透過伺服器環境建立出貨工作,請對 `CreateTask' 發出 HTTP REST 呼叫:

POST https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks?taskId=<id>

<id> 是工作的專屬 ID。不得為運送的追蹤號碼。如果系統中沒有工作 ID,您可以產生通用唯一識別碼 (UUID)。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    類型 Type.DELIVERY
    最終的隱藏狀態 州/省.OPEN
    追蹤 ID 您用來追蹤貨物的編號或 ID。
    PlannedLocation 工作完成的位置,在本例中為這批商品的取貨地點。
    工作時間長度 預計交貨地點所需的預計時間,以秒為單位。

  • 選填欄位:

    欄位
    目標時間範圍 工作應完成的時間範圍。這目前不會影響轉送行為。
    attributes 自訂 Task 屬性的清單。每個屬性都必須有專屬金鑰。

建立時會忽略實體中的所有其他欄位。如果要求包含指派的 DeliveryVehicleId,則 Fleet Engine 會擲回例外狀況。您可以使用 UpdateDeliveryVehicleRequest 指派工作。詳情請參閱「將工作指派給車輛」。

範例 curl 指令:

# Set $JWT, $PROJECT_ID, $TRACKING_ID, and $TASK_ID in the local
# environment
curl -X POST "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks?taskId=${TASK_ID}" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "type": "DELIVERY",
  "state": "OPEN",
  "trackingId": "${TRACKING_ID}",
  "plannedLocation": {
     "point": {
        "latitude": -6.195139,
        "longitude": 106.820826
     }
  },
  "taskDuration": "90s",
  "targetTimeWindow": {
    "startTime": "2023-03-29T21:00:00Z",
    "endTime": "2023-03-29T23:00:00Z"
  }
}
EOM

批次建立工作

您可以透過伺服器環境建立一批工作。

gRPC

以下範例說明如何使用 Java gRPC 程式庫建立兩個工作:一個用於交付,另一個用於在同一位置取貨:

static final String PROJECT_ID = "my-delivery-co-gcp-project";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Delivery Task settings
Task deliveryTask = Task.newBuilder()
  .setType(Task.Type.DELIVERY)
  .setState(Task.State.OPEN)
  .setTrackingId("delivery-tracking-id")
  .setPlannedLocation(               // Grand Indonesia East Mall
    LocationInfo.newBuilder().setPoint(
      LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
  .setTaskDuration(
    Duration.newBuilder().setSeconds(2 * 60))
  .build();

// Delivery Task request
CreateTaskRequest createDeliveryTaskRequest =
  CreateTaskRequest.newBuilder()  // No need for the header or parent fields
      .setTaskId("task-8312508")  // Task ID assigned by the Provider
      .setTask(deliveryTask)      // Initial state
      .build();

// Pickup Task settings
Task pickupTask = Task.newBuilder()
  .setType(Task.Type.PICKUP)
  .setState(Task.State.OPEN)
  .setTrackingId("pickup-tracking-id")
  .setPlannedLocation(               // Grand Indonesia East Mall
    LocationInfo.newBuilder().setPoint(
      LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
  .setTaskDuration(
    Duration.newBuilder().setSeconds(2 * 60))
  .build();

// Pickup Task request
CreateTaskRequest createPickupTaskRequest =
  CreateTaskRequest.newBuilder()  // No need for the header or parent fields
      .setTaskId("task-8241890")  // Task ID assigned by the Provider
      .setTask(pickupTask)        // Initial state
      .build();

// Batch Create Tasks settings
String parent = "providers/" + PROJECT_ID;

// Batch Create Tasks request
BatchCreateTasksRequest batchCreateTasksRequest =
  BatchCreateTasksRequest.newBuilder()
      .setParent(parent)
      .addRequests(createDeliveryTaskRequest)
      .addRequests(createPickupTaskRequest)
      .build();

// Error handling
// If Fleet Engine does not have any task(s) with these task ID(s) and the
// credentials of the requestor pass, the service creates the task(s)
// successfully.

try {
  BatchCreateTasksResponse createdTasks = deliveryService.batchCreateTasks(
    batchCreateTasksRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case ALREADY_EXISTS:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境建立傳送和取貨工作,請對 BatchCreateTasks 發出 HTTP REST 呼叫:

POST https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks:batchCreate

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 BatchCreateTasksRequest 實體:

  • 必填欄位:

    欄位
    項要求 陣列<CreateTasksRequest>

  • 選填欄位:

    欄位
    標頭 「DeliveryRequestHeader」

requests 中的每個 CreateTasksRequest 元素都必須傳遞與 CreateTask 要求相同的驗證規則,但 parentheader 欄位為選用欄位。如有設定,這些欄位必須與頂層 BatchCreateTasksRequest 中的對應欄位相同。請參閱建立運送取貨工作,並建立運送交貨工作,藉此瞭解各項規則的特定驗證規則。

詳情請參閱 BatchCreateTasks 的 API 參考說明文件 (gRPCREST)。

範例 curl 指令:

# Set $JWT, $PROJECT_ID, $DELIVERY_TRACKING_ID, $DELIVERY_TASK_ID,
# $PICKUP_TRACKING_ID, and $PICKUP_TASK_ID in the local environment
curl -X POST "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks:batchCreate" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "requests" : [
    {
      "taskId": "${DELIVERY_TASK_ID}",
      "task" : {
        "type": "DELIVERY",
        "state": "OPEN",
        "trackingId": "${DELIVERY_TRACKING_ID}",
        "plannedLocation": {
          "point": {
              "latitude": -6.195139,
              "longitude": 106.820826
          }
        },
        "taskDuration": "90s"
      }
    },
    {
      "taskId": "${PICKUP_TASK_ID}",
      "task" : {
        "type": "PICKUP",
        "state": "OPEN",
        "trackingId": "${PICKUP_TRACKING_ID}",
        "plannedLocation": {
          "point": {
              "latitude": -6.195139,
              "longitude": 106.820826
          }
        },
        "taskDuration": "90s"
      }
    }
  ]
}
EOM

預定無法使用

您可以從 Driver SDK 或伺服器環境建立表示無法使用 (例如駕駛故障或車輛補充) 的工作。排定的無法使用時間工作不得包含追蹤 ID。您可以選擇提供地點。

gRPC

以下範例說明如何使用 Java gRPC 程式庫建立無法使用的工作:

static final String PROJECT_ID = "my-delivery-co-gcp-project";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String parent = "providers/" + PROJECT_ID;
Task task = Task.newBuilder()
  .setType(Task.Type.UNAVAILABLE)
  .setState(Task.State.OPEN)
  .setTaskDuration(
    Duration.newBuilder().setSeconds(60 * 60))  // 1hr break
  .build();

// Task request
CreateTaskRequest createTaskRequest =
  CreateTaskRequest.newBuilder()  // No need for the header
      .setParent(parent)          // Avoid using auto-incrementing IDs for the taskId
      .setTaskId("task-8241890")  // Task ID assigned by the Provider
      .setTask(task)              // Initial state
      .build();

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

try {
  Task createdTask = deliveryService.createTask(createTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case ALREADY_EXISTS:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境建立無法使用的工作,請對 CreateTask 發出 HTTP REST 呼叫:

POST https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks?taskId=<id>

<id> 是工作的專屬 ID。如果系統中沒有工作 ID,您可以產生通用唯一識別碼 (UUID)。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    類型 Type.UNAVAILABLE
    最終的隱藏狀態 州/省.OPEN
    工作時間長度 廣告插播長度 (以秒為單位)。

  • 選填欄位:

    欄位
    PlannedLocation 休息時間的位置 (如果必須於特定位置拍攝)。

建立時會忽略實體中的所有其他欄位。如果要求包含指派的 DeliveryVehicleId,則 Fleet Engine 會擲回例外狀況。您可以使用 UpdateDeliveryVehicleRequest 指派工作。詳情請參閱「將工作指派給車輛」。

範例 curl 指令:

# Set $JWT, $PROJECT_ID, and $TASK_ID in the local environment
curl -X POST "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks?taskId=${TASK_ID}" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "type": "UNAVAILABLE",
  "state": "OPEN",
  "plannedLocation": {
     "point": {
        "latitude": -6.195139,
        "longitude": 106.820826
     }
  },
  "taskDuration": "300s"
}
EOM

已排定的停靠站

您可以透過 Driver SDK 或伺服器環境建立已排定的停止工作。已排定的停止工作可能不包含追蹤 ID。

gRPC

以下範例說明如何使用 Java gRPC 程式庫建立排定的停止工作:

static final String PROJECT_ID = "my-delivery-co-gcp-project";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String parent = "providers/" + PROJECT_ID;
Task task = Task.newBuilder()
  .setType(Task.Type.SCHEDULED_STOP)
  .setState(Task.State.OPEN)
  .setPlannedLocation(               // Grand Indonesia East Mall
    LocationInfo.newBuilder().setPoint(
      LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
  .setTaskDuration(
    Duration.newBuilder().setSeconds(2 * 60))
  .build();

// Task request
CreateTaskRequest createTaskRequest =
  CreateTaskRequest.newBuilder()  // No need for the header
      .setParent(parent)
      .setTaskId("task-8241890")  // Task ID assigned by the Provider
      .setTrip(task)              // Initial state
      .build();

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

try {
  Task createdTask = deliveryService.createTask(createTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case ALREADY_EXISTS:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境建立排定的停止工作,請對 `CreateTask' 發出 HTTP REST 呼叫:

POST https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks?taskId=<id>

<id> 是工作的專屬 ID。如果系統中沒有工作 ID,您可以產生通用唯一識別碼 (UUID)。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    類型 類型.SCHEDULED_STOP
    最終的隱藏狀態 州/省.OPEN
    PlannedLocation 停靠站的位置。
    工作時間長度 預期的停靠站長度 (以秒為單位)。

  • 選填欄位:

建立時會忽略實體中的所有其他欄位。如果要求包含指派的 DeliveryVehicleId,則 Fleet Engine 會擲回例外狀況。您可以使用 UpdateDeliveryVehicleRequest 指派工作。詳情請參閱「將工作指派給車輛」。

範例 curl 指令:

# Set $JWT, $PROJECT_ID, and $TASK_ID in the local environment
curl -X POST "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks?taskId=${TASK_ID}" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "type": "SCHEDULED_STOP",
  "state": "OPEN",
  "plannedLocation": {
     "point": {
        "latitude": -6.195139,
        "longitude": 106.820826
     }
  },
  "taskDuration": "600s"
}
EOM

設定目標時間範圍

目標時間範圍是指工作應完成的 TimeWindow。例如,如果您向傳送者傳送運送時間時段,可以使用工作目標時間範圍來擷取這個時間範圍,並透過該欄位產生快訊或分析行程後成效。

目標時間範圍包含開始時間和結束時間,可以在任何工作類型上設定。目標時間範圍目前不會影響轉送行為。

gRPC

以下範例說明如何使用 Java gRPC 程式庫設定工作時間範圍:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String TASK_ID = "task-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String taskName = "providers/" + PROJECT_ID + "/tasks/" + TASK_ID;
Task task = Task.newBuilder()
  .setName(taskName)
  .setTargetTimeWindow(
    TimeWindow.newBuilder()
      .setStartTime(Timestamp.newBuilder().setSeconds(1680123600))
      .setEndTime(Timestamp.newBuilder().setSeconds(1680130800)))
  .build();

// Task request
UpdateTaskRequest updateTaskRequest =
  UpdateTaskRequest.newBuilder()  // No need for the header
      .setTask(task)
      .setUpdateMask(FieldMask.newBuilder().addPaths("targetTimeWindow"))
      .build();

try {
  Task updatedTask = deliveryService.updateTask(updateTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要使用 HTTP 設定工作時間範圍,請呼叫 UpdateTask

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks/<id>?updateMask=targetTimeWindow

<id> 是工作的專屬 ID

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠所創造的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    目標時間範圍 工作應完成的時間範圍。這目前不會影響轉送行為

  • 選填欄位:

而在更新作業中,系統會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, and TASK_ID in the local environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks/${TASK_ID}?updateMask=targetTimeWindow" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "targetTimeWindow": {
    "startTime": "2023-03-29T21:00:00Z",
    "endTime": "2023-03-29T23:00:00Z"
  }
}
EOM

調整工作追蹤瀏覽權限設定

您可以針對每項工作設定 TaskTrackingViewConfig,藉此控制 Shipment Tracking 程式庫中和呼叫 GetTaskTrackingInfo 傳回的資料。詳情請參閱「使用中的車輛工作」一文。這可以在建立或更新工作時完成。以下是使用此設定更新工作的範例:

gRPC

以下範例說明如何使用 Java gRPC 程式庫設定工作追蹤檢視設定:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String TASK_ID = "task-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String taskName = "providers/" + PROJECT_ID + "/tasks/" + TASK_ID;
Task task = Task.newBuilder()
  .setName(taskName)
  .setTaskTrackingViewConfig(
    TaskTrackingViewConfig.newBuilder()
      .setRoutePolylinePointsVisibility(
        VisibilityOption.newBuilder().setRemainingStopCountThreshold(3))
      .setEstimatedArrivalTimeVisibility(
        VisibilityOption.newBuilder().remainingDrivingDistanceMetersThreshold(5000))
      .setRemainingStopCountVisibility(
        VisibilityOption.newBuilder().setNever(true)))
  .build();

// Task request
UpdateTaskRequest updateTaskRequest =
  UpdateTaskRequest.newBuilder()  // No need for the header
      .setTask(task)
      .setUpdateMask(FieldMask.newBuilder().addPaths("taskTrackingViewConfig"))
      .build();

try {
  Task updatedTask = deliveryService.updateTask(updateTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
      case NOT_FOUND:
        break;
      case PERMISSION_DENIED:
        break;
  }
  return;
}

REST

如要使用 HTTP 設定工作追蹤檢視設定視窗,請呼叫 UpdateTask

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks/<id>?updateMask=taskTrackingViewConfig

<id> 是工作的專屬 ID

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠所創造的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    TaskTrackingViewConfig 工作追蹤的設定會指定使用者在哪些情況下可以看到哪些資料元素。

  • 選填欄位:

而在更新作業中,系統會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, and TASK_ID in the local environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks/${TASK_ID}?updateMask=taskTrackingViewConfig" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "taskTrackingViewConfig": {
    "routePolylinePointsVisibility": {
      "remainingStopCountThreshold": 3
    },
    "estimatedArrivalTimeVisibility": {
      "remainingDrivingDistanceMetersThreshold": 5000
    },
    "remainingStopCountVisibility": {
      "never": true
    }
  }
}
EOM

將工作指派給車輛

系統會更新車輛的工作排序,將任務指派給外送車輛。車輛的任務順序取決於車輛的車輛停靠站清單。每個車輛停靠站都可以指派一或多項任務。

針對先前指派給不同車輛的工作更新工作排序會產生錯誤。

如要將貨物從某輛車改為另一輛車,請關閉原始工作,然後重新建立該工作,再指派新車輛。

更新工作排序

您可以從 Driver SDK 或伺服器環境更新指派給車輛的執行順序。這兩種方法不應混合使用,以避免競爭狀況。

更新工作排序作業時,也會將先前指派給車輛的工作指派給車輛,同時關閉先前指派給車輛、不依照更新順序執行的工作。如果先前已將工作指派給其他車輛,則將工作指派給其他車輛會產生錯誤。請先關閉現有工作,接著建立新工作,然後再將其指派給新車輛。

工作排序可隨時更新。

gRPC

以下範例說明如何使用 Java gRPC 程式庫更新車輛的工作排序:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String VEHICLE_ID = "vehicle-8241890";
static final String TASK1_ID = "task-756390";
static final String TASK2_ID = "task-849263";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Vehicle settings
String vehicleName = "providers/" + PROJECT_ID + "/deliveryVehicles/" + VEHICLE_ID;
DeliveryVehicle deliveryVehicle = DeliveryVehicle.newBuilder()
    .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // 1st stop
       .setStop(VehicleStop.newBuilder()
           .setPlannedLocation(LocationInfo.newBuilder()
               .setPoint(LatLng.newBuilder()
                   .setLatitude(37.7749)
                   .setLongitude(122.4194)))
           .addTasks(TaskInfo.newBuilder().setTaskId(TASK1_ID))
           .setState(VehicleStop.State.NEW)))
    .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // 2nd stop
       .setStop(VehicleStop.newBuilder()
           .setPlannedLocation(LocationInfo.newBuilder()
               .setPoint(LatLng.newBuilder()
                   .setLatitude(37.3382)
                   .setLongitude(121.8863)))
           .addTasks(TaskInfo.newBuilder().setTaskId(TASK2_ID))
           .setState(VehicleStop.State.NEW)))
    .build();

// DeliveryVehicle request
UpdateDeliveryVehicleRequest updateDeliveryRequest =
  UpdateDeliveryVehicleRequest.newBuilder()  // No need for the header
      .setName(vehicleName)
      .setDeliveryVehicle(deliveryVehicle)
      .setUpdateMask(FieldMask.newBuilder().addPaths("remaining_vehicle_journey_segments"))
      .build();

try {
  DeliveryVehicle updatedDeliveryVehicle =
      deliveryService.updateDeliveryVehicle(updateDeliveryVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境更新車輛的工作排序,請對「UpdateDeliveryVehicle」執行 HTTP REST 呼叫:

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles/<id>?updateMask=remainingVehicleJourneySegments

<id> 是您想更新工作排序方式的車隊運送車輛的專屬 ID。這是您在建立車輛時指定的 ID。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 DeliveryVehicle 實體:

  • 必填欄位:

    欄位
    其餘車輛歷程區隔 工作歷程區隔清單,按照應執行順序排列。系統會先執行清單中的第一項工作。
    剩餘的 VehicleJourneySegments[i].stop 清單中的工作「i」的停靠站。
    剩餘的 VehicleJourneySegments[i].stop.plannedLocation 停靠站的預定地點,
    剩餘的 VehicleJourneySegments[i].stop.tasks 要在這個車輛停靠站執行的工作清單。
    剩餘的 VehicleJourneySegments[i].stop.state State.NEW

  • 選填欄位:

而在更新作業中,系統會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, VEHICLE_ID, TASK1_ID, and TASK2_ID in the local
# environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles/${VEHICLE_ID}?updateMask=remainingVehicleJourneySegments" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "remainingVehicleJourneySegments": [
    {
      "stop": {
        "state": "NEW",
        "plannedLocation": {
          "point": {
            "latitude": 37.7749,
            "longitude": -122.084061
          }
        },
        "tasks": [
          {
            "taskId": "${TASK1_ID}"
          }
        ]
      }
    },
    {
      "stop": {
        "state": "NEW",
        "plannedLocation": {
          "point": {
            "latitude": 37.3382,
            "longitude": 121.8863
          }
        },
        "tasks": [
          {
            "taskId": "${TASK2_ID}"
          }
        ]
      }
    }
  ]
}
EOM

車輛正在前往下一個停靠站

當車輛從停靠站或開始導航時,Fleet Engine 必須收到通知。您可以透過 Driver SDK 或伺服器環境通知 Fleet Engine。請勿混合使用這兩種方法,以免發生競爭狀況,並維持單一可靠資料來源。

gRPC

以下範例說明如何使用 Java gRPC 程式庫通知 Fleet Engine,讓 Fleet Engine 知道車輛正在轉送至下一個停靠站。

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String VEHICLE_ID = "vehicle-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Vehicle settings
DeliveryVehicle deliveryVehicle = DeliveryVehicle.newBuilder()
    // Next stop marked as ENROUTE
    .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // 1st stop
       .setStop(VehicleStop.newBuilder()
           .setPlannedLocation(LocationInfo.newBuilder()
               .setPoint(LatLng.newBuilder()
                   .setLatitude(37.7749)
                   .setLongitude(122.4194)))
           .addTasks(TaskInfo.newBuilder().setTaskId(TASK1_ID))
           .setState(VehicleStop.State.ENROUTE)))
    // All other stops marked as NEW
    .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // 2nd stop
       .setStop(VehicleStop.newBuilder()
           .setPlannedLocation(LocationInfo.newBuilder()
               .setPoint(LatLng.newBuilder()
                   .setLatitude(37.3382)
                   .setLongitude(121.8863)))
           .addTasks(TaskInfo.newBuilder().setTaskId(TASK2_ID))
           .setState(VehicleStop.State.NEW)))
    .build();


// DeliveryVehicle request
UpdateDeliveryVehicleRequest updateDeliveryVehicleRequest =
  UpdateDeliveryVehicleRequest.newBuilder()  // No need for the header
      .setName(vehicleName)
      .setDeliveryVehicle(deliveryVehicle)
      .setUpdateMask(FieldMask.newBuilder().addPaths("remaining_vehicle_journey_segments"))
      .build();

try {
  DeliveryVehicle updatedDeliveryVehicle =
      deliveryService.updateDeliveryVehicle(updateDeliveryVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要通知 Fleet Engine,車輛正從伺服器環境導向到下一個停靠站,請對「UpdateDeliveryVehicle」發出 HTTP REST 呼叫:

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles/<id>?updateMask=remainingVehicleJourneySegments

<id> 是您想更新工作排序方式的車隊運送車輛的專屬 ID。這是您在建立車輛時指定的 ID。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 DeliveryVehicle 實體:

  • 必填欄位:

    欄位
    其餘車輛歷程區隔 剩餘車輛停靠站清單,狀態會標示為 State.NEW。清單中的第一個停靠站的狀態必須標示為 State.ENROUTE。

  • 選填欄位:

通知會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, VEHICLE_ID, TASK1_ID, and TASK2_ID in the local
# environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles/${VEHICLE_ID}?updateMask=remainingVehicleJourneySegments" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "remainingVehicleJourneySegments": [
    {
      "stop": {
        "state": "ENROUTE",
        "plannedLocation": {
          "point": {
            "latitude": 37.7749,
            "longitude": -122.084061
          }
        },
        "tasks": [
          {
            "taskId": "${TASK1_ID}"
          }
        ]
      }
    },
    {
      "stop": {
        "state": "NEW",
        "plannedLocation": {
          "point": {
            "latitude": 37.3382,
            "longitude": 121.8863
          }
        },
        "tasks": [
          {
            "taskId": "${TASK2_ID}"
          }
        ]
      }
    }
  ]
}
EOM

車輛抵達停靠站

當車輛抵達停靠站時,Fleet Engine 必須收到通知。您可以從 Driver SDK 或伺服器環境通知 Fleet Engine。為了避免競爭狀況,並維持單一可靠資料來源,請勿混合使用這兩種方法。

gRPC

以下範例說明如何使用 Java gRPC 程式庫通知 Fleet Engine 車輛抵達停靠站:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String VEHICLE_ID = "vehicle-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Vehicle settings
String vehicleName = "providers/" + PROJECT_ID + "/deliveryVehicles/" + VEHICLE_ID;
DeliveryVehicle deliveryVehicle = DeliveryVehicle.newBuilder()
    // Marking the arrival at stop.
    .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()
       .setStop(VehicleStop.newBuilder()
           .setPlannedLocation(LocationInfo.newBuilder()
               .setPoint(LatLng.newBuilder()
                   .setLatitude(37.7749)
                   .setLongitude(122.4194)))
           .addTasks(TaskInfo.newBuilder().setTaskId(TASK1_ID))
           .setState(VehicleStop.State.ARRIVED)))
    // All other remaining stops marked as NEW.
    .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // 2nd stop
       .setStop(VehicleStop.newBuilder()
           .setPlannedLocation(LocationInfo.newBuilder()
               .setPoint(LatLng.newBuilder()
                   .setLatitude(37.3382)
                   .setLongitude(121.8863)))
           .addTasks(TaskInfo.newBuilder().setTaskId(TASK2_ID))
           .setState(VehicleStop.State.NEW))) // Remaining stops must be NEW.
    .build();

// DeliveryVehicle request
UpdateDeliveryVehicleRequest updateDeliveryVehicleRequest =
  UpdateDeliveryVehicleRequest.newBuilder()  // No need for the header
      .setName(vehicleName)
      .setDeliveryVehicle(deliveryVehicle)
      .setUpdateMask(FieldMask.newBuilder()
          .addPaths("remaining_vehicle_journey_segments"))
      .build();

try {
  DeliveryVehicle updatedDeliveryVehicle =
      deliveryService.updateDeliveryVehicle(updateDeliveryVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要通知 Fleet Engine 偵測到車輛抵達伺服器環境的停靠站,請對「UpdateDeliveryVehicle」發出 HTTP REST 呼叫:

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles/<id>?updateMask=remainingVehicleJourneySegments

<id> 是您想更新工作排序方式的車隊運送車輛的專屬 ID。這是您在建立車輛時指定的 ID。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 DeliveryVehicle 實體:

  • 必填欄位:

    欄位
    其餘車輛歷程區隔 你抵達的停靠站狀態設為 State.ARRIVED,接著是其餘車輛停靠站清單,狀態會標示為 State.NEW。

  • 選填欄位:

而在更新作業中,系統會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, VEHICLE_ID, TASK1_ID, and TASK2_ID in the local
# environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles/${VEHICLE_ID}?updateMask=remainingVehicleJourneySegments" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "remainingVehicleJourneySegments": [
    {
      "stop": {
        "state": "ARRIVED",
        "plannedLocation": {
          "point": {
            "latitude": 37.7749,
            "longitude": -122.084061
          }
        },
        "tasks": [
          {
            "taskId": "${TASK1_ID}"
          }
        ]
      }
    },
    {
      "stop": {
        "state": "NEW",
        "plannedLocation": {
          "point": {
            "latitude": 37.3382,
            "longitude": 121.8863
          }
        },
        "tasks": [
          {
            "taskId": "${TASK2_ID}"
          }
        ]
      }
    }
  ]
}
EOM

車輛完成停靠站

當車輛完成停靠站時,Fleet Engine 必須收到通知。這會將與停靠站相關聯的所有工作都設為「已關閉」狀態。您可以透過 Driver SDK 或伺服器環境通知 Fleet Engine。請勿混合使用這兩種方法,以避免競爭狀況,並維持單一可靠資料來源。

gRPC

以下範例說明如何使用 Java gRPC 程式庫向 Fleet Engine 通知車輛已完成停靠站。

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String VEHICLE_ID = "vehicle-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Vehicle settings
String vehicleName = "providers/" + PROJECT_ID + "/deliveryVehicles/" + VEHICLE_ID;
DeliveryVehicle deliveryVehicle = DeliveryVehicle.newBuilder()
    // This stop has been completed and is commented out to indicate it
    // should be removed from the list of vehicle journey segments.
    // .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()
    //    .setStop(VehicleStop.newBuilder()
    //        .setPlannedLocation(LocationInfo.newBuilder()
    //            .setPoint(LatLng.newBuilder()
    //                .setLatitude(37.7749)
    //                .setLongitude(122.4194)))
    //        .addTasks(TaskInfo.newBuilder().setTaskId(TASK1_ID))
    //        .setState(VehicleStop.State.ARRIVED)))
    // All other remaining stops marked as NEW.
    // The next stop could be marked as ENROUTE if the vehicle has begun
    // its journey to the next stop.
    .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // Next stop
       .setStop(VehicleStop.newBuilder()
           .setPlannedLocation(LocationInfo.newBuilder()
               .setPoint(LatLng.newBuilder()
                   .setLatitude(37.3382)
                   .setLongitude(121.8863)))
           .addTasks(TaskInfo.newBuilder().setTaskId(TASK2_ID))
           .setState(VehicleStop.State.NEW)))
    .build();

// DeliveryVehicle request
UpdateDeliveryVehicleRequest updateDeliveryVehicleRequest =
  UpdateDeliveryVehicleRequest.newBuilder()  // no need for the header
      .setName(vehicleName)
      .setDeliveryVehicle(deliveryVehicle)
      .setUpdateMask(FieldMask.newBuilder()
          .addPaths("remaining_vehicle_journey_segments"))
      .build();

try {
  DeliveryVehicle updatedDeliveryVehicle =
      deliveryService.updateDeliveryVehicle(updateDeliveryVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要通知 Fleet Engine 關於伺服器環境結束的停靠站,請對「UpdateDeliveryVehicle」發出 HTTP REST 呼叫:

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles/<id>?updateMask=remaining_vehicle_journey_segments

<id> 是您想更新工作排序方式的車隊運送車輛的專屬 ID。這是您在建立車輛時指定的 ID。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 DeliveryVehicle 實體:

  • 必填欄位:

    欄位
    other_vehicle_journey_Segments 已完成的停靠站不會再顯示於其餘車輛停靠站清單中。

  • 選填欄位:

而在更新作業中,系統會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, VEHICLE_ID, TASK1_ID, and TASK2_ID in the local
# environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles/${VEHICLE_ID}?updateMask=remainingVehicleJourneySegments" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "remainingVehicleJourneySegments": [
    {
      "stop": {
        "state": "NEW",
        "plannedLocation": {
          "point": {
            "latitude": 37.3382,
            "longitude": 121.8863
          }
        },
        "tasks": [
          {
            "taskId": "${TASK2_ID}"
          }
        ]
      }
    }
  ]
}
EOM

更新工作

大部分工作欄位皆無法變更。不過,您可以直接更新工作實體來修改狀態、工作結果、工作結果時間、工作結果位置和屬性。舉例來說,如果工作尚未指派給車輛,您可以直接更新狀態來關閉工作。

gRPC

以下是透過 gRPC 更新工作的範例。

REST

以下示範透過 REST 更新工作。

關閉工作

如要關閉已指派給車輛的工作,請通知 Fleet Engine 車輛已完成工作的停靠站,或將該工作從車輛停靠站清單中移除。做法如下:設定車輛的停靠站清單,就像更新車輛的工作排序時一樣。

如果工作尚未指派車輛且需要關閉,請將工作更新為「已關閉」狀態。不過,您無法重新開啟已關閉的工作。

關閉工作不代表作業成功或失敗。這表示工作不再視為進行中。運送追蹤時,請務必指出工作的實際結果,以便顯示貨品交付結果。

gRPC

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String TASK_ID = "task-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String taskName = "providers/" + PROJECT_ID + "/tasks/" + TASK_ID;
Task task = Task.newBuilder()
  .setName(taskName)
  .setState(Task.State.CLOSED) // It's only possible to directly CLOSE a
  .build();                    // task which is NOT assigned to a vehicle.

// Task request
UpdateTaskRequest updateTaskRequest =
  UpdateTaskRequest.newBuilder()  // No need for the header
      .setTask(task)
      .setUpdateMask(FieldMask.newBuilder().addPaths("state"))
      .build();

try {
  Task updatedTask = deliveryService.updateTask(updateTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境將工作標示為已關閉,請向 UpdateTask 發出 HTTP REST 呼叫:

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks/<id>?updateMask=state

<id> 是工作的專屬 ID

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    最終的隱藏狀態 州/省已關閉。

  • 選填欄位:

    欄位
    項工作結果 結果或結果失敗。
    TaskOutcomeTime 工作完成的時間。
    TaskOutcomeLocation 工作完成的位置,除非供應商手動覆寫,否則 Fleet Engine 會將這個欄位預設為最後一個車輛位置。

而在更新作業中,系統會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, and TASK_ID in the local environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks/${TASK_ID}?updateMask=state,taskOutcome,taskOutcomeTime" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "state": "CLOSED",
  "taskOutcome": "SUCCEEDED",
  "taskOutcomeTime": "$(date -u --iso-8601=seconds)"
}
EOM

設定工作結果和結果位置

關閉工作不表示成功或失敗,這表示工作不再視為進行中。運送追蹤時,請務必指出工作的實際結果,以便顯示運送結果,並為服務提供適當的帳單。設定後即無法變更工作結果。您可以在設定工作結果時間和工作外出位置後,修改這些值。

狀態為「已關閉」的工作可將結果設定為「成功」或「失敗」。Fleet Engine 只會針對狀態為「成功」的傳遞工作收取費用。

標記工作的結果時,Fleet Engine 會自動將工作結果位置填入最後已知車輛位置。您可以覆寫這個行為。

gRPC

您可以選擇在設定結果位置時設定工作結果位置。這將防止 Fleet Engine 將其設為最後車輛位置的預設值。您也可以覆寫稍後設定的工作結果位置 Fleet Engine。Fleet Engine 絕對不會覆寫您提供的工作結果位置。無法為未設定工作結果設定的工作設定工作結果位置。您可以在同一個要求中同時設定工作結果和工作結果位置。

以下範例說明如何使用 Java gRPC 程式庫將工作結果設為「SUCCEEDED」,並設定工作完成的位置:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String TASK_ID = "task-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task settings
String taskName = "providers/" + PROJECT_ID + "/tasks/" + TASK_ID;
Task task = Task.newBuilder()
  .setName(taskName)
  .setTaskOutcome(TaskOutcome.SUCCEEDED)
  .setTaskOutcomeTime(now())
  .setTaskOutcomeLocation(               // Grand Indonesia East Mall
    LocationInfo.newBuilder().setPoint(
      LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
  .build();

// Task request
UpdateTaskRequest updateTaskRequest =
  UpdateTaskRequest.newBuilder()  // No need for the header
      .setTask(task)
      .setUpdateMask(FieldMask.newBuilder().addPaths("task_outcome", "task_outcome_time", "task_outcome_location"))
      .build();

try {
  Task updatedTask = deliveryService.updateTask(updateTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境將工作標示為完成,請對 UpdateTask 發出 HTTP REST 呼叫:

PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks/<id>?updateMask=taskOutcome,taskOutcomeTime,taskOutcomeLocation

<id> 是工作的專屬 ID

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須包含 Task 實體:

  • 必填欄位:

    欄位
    項工作結果 結果或結果失敗。
    TaskOutcomeTime 工作結果設定時間的時間戳記 (來自提供者)。這是工作完成的時間。

  • 選填欄位:

    欄位
    TaskOutcomeLocation 工作完成的位置,除非供應商手動覆寫,否則 Fleet Engine 會將這個欄位預設為最後一個車輛位置。

而在更新作業中,系統會忽略實體中的所有其他欄位。

範例 curl 指令:

# Set JWT, PROJECT_ID, and TASK_ID in the local environment
curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks/${TASK_ID}?updateMask=taskOutcome,taskOutcomeTime,taskOutcomeLocation" \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer ${JWT}" \
  --data-binary @- << EOM
{
  "taskOutcome": "SUCCEEDED",
  "taskOutcomeTime": "$(date -u --iso-8601=seconds)",
  "taskOutcomeLocation": {
    "point": {
      "latitude": -6.195139,
      "longitude": 106.820826
    }
  }
}
EOM

重新轉送貨物

建立出貨工作後,就無法變更預定的地點。如要重新轉送運送路徑,請關閉運送工作而不設定結果,然後建立含有更新後的預定地點的新工作。建立新工作後,將工作指派給同一輛車。詳情請參閱關閉出貨工作指派工作

使用餵食器和運送車輛

如果您使用饋送車輛在一天當中將貨物運輸到貨物運輸車輛,請以運輸車輛排定的停靠工作來建立貨運模型。為確保地點追蹤的準確性,請僅於將已轉移的貨物載入到貨運車輛後,才指派運送工作。詳情請參閱排定的停靠站

儲存運送狀態和其他中繼資訊

出貨工作完成後,工作狀態和結果會記錄在工作中。不過,建議您更新運送專用的其他中繼資訊。如要儲存可在 Fleet Engine 服務外部參照的其他中繼資訊,請在外部資料表中將與工作相關聯的 tracking_id 做為索引鍵使用。

詳情請參閱工作的生命週期

查詢車輛

您可以透過 Driver SDK 或伺服器環境查詢車輛。

gRPC

以下範例說明如何使用 Java gRPC 程式庫查詢車輛:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String VEHICLE_ID = "vehicle-8241890";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Vehicle request
String name = "providers/" + PROJECT_ID + "/deliveryVehicles/" + VEHICLE_ID;
GetDeliveryVehicleRequest getVehicleRequest = GetDeliveryVehicleRequest.newBuilder()  // No need for the header
    .setName(name)
    .build();

try {
  DeliveryVehicle vehicle = deliveryService.getDeliveryVehicle(getVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;
     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境查詢車輛,請對「GetVehicle」發出 HTTP REST 呼叫:

GET https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles/<vehicleId>

<id> 是工作的專屬 ID

<vehicleId> 是要查詢的車輛 ID。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須為空白。

如果查詢成功,回應主體會包含車輛實體。

範例 curl 指令:

# Set JWT, PROJECT_ID, and VEHICLE_ID in the local environment
curl -H "Authorization: Bearer ${JWT}" \
  "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles/${VEHICLE_ID}"

查詢工作

您可以從伺服器環境查詢工作。驅動程式 SDK 不支援查詢工作。

gRPC

以下範例說明如何使用 Java gRPC 程式庫查詢工作:

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String TASK_ID = "task-8597549";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Task request
String taskName = "providers/" + PROJECT_ID + "/tasks/" + TASK_ID;
GetTaskRequest getTaskRequest = GetTaskRequest.newBuilder()  // No need for the header
    .setName(taskName)
    .build();

try {
  Task task = deliveryService.getTask(getTaskRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;

     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要從伺服器環境查詢工作,請對 `GetTask' 發出 HTTP REST 呼叫:

GET https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks/<taskId>

<id> 是工作的專屬 ID

<taskId> 是要查詢的工作 ID。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

要求主體必須為空白。

如果查詢成功,回應主體會包含工作實體。

範例 curl 指令:

# Set JWT, PROJECT_ID, and TASK_ID in the local environment
curl -H "Authorization: Bearer ${JWT}" \
  "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks/${TASK_ID}"

依追蹤 ID 查詢出貨工作資訊

您可以用下列方式查詢出貨工作資訊,這些資訊有各自的用途:

  • :由具備工作資料完整資料檢視存取權的使用者 (例如機群運算子) 使用。
  • 透過追蹤 ID:用戶端軟體用來為使用者提供有限資訊 (例如包裹送到府的時間)。

本節將討論依據追蹤 ID 查詢工作資訊。如要依工作 ID 查詢工作,請參閱查詢工作

如要按追蹤 ID 查詢資訊,您可以使用下列其中一種方式:

查詢規定

  • 追蹤 ID 提供的運送資訊必須符合「控制追蹤位置的顯示設定」一文中所述的瀏覽權限規則。

  • 使用 Fleet Engine 根據追蹤 ID 查詢運送資訊。驅動程式 SDK 不支援根據追蹤 ID 查詢資訊。如要利用 Fleet Engine 執行此操作,您必須使用伺服器或瀏覽器環境。

  • 盡可能使用範圍最窄的權杖來降低安全性風險。例如,如果您使用 Delivery Consumer Token,任何 Fleet Engine Deliveries API 呼叫都只會傳回與使用者相關的資訊,例如運送者或貨物的接收者。回應中的所有其他資訊都會受到遮蓋。如要進一步瞭解權杖,請參閱建立 JSON Web Token (JWT) 以進行授權

使用 gRPC 透過 Java 查詢

以下範例說明如何使用 Java gRPC 程式庫,透過追蹤 ID 查詢出貨工作的相關資訊。

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String TRACKING_ID = "TID-7449w087464x5";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Tasks request
String parent = "providers/" + PROJECT_ID;
GetTaskTrackingInfoRequest getTaskTrackingInfoRequest = GetTaskTrackingInfoRequest.newBuilder()  // No need for the header
    .setParent(parent)
    .setTrackingId(TRACKING_ID)
    .build();

try {
  TaskTrackingInfo taskTrackingInfo = deliveryService.getTaskTrackingInfo(getTaskTrackingInfoRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;

     case PERMISSION_DENIED:
       break;
  }
  return;
}

使用 HTTP 查詢

如要從瀏覽器查詢出貨工作,請對 GetTaskTrackingInfo 發出 HTTP REST 呼叫:

GET https://fleetengine.googleapis.com/v1/providers/<project_id>/taskTrackingInfo/<tracking_id>

<tracking_id> 是與工作相關聯的追蹤 ID。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

如果查詢成功,回應主體會包含 taskTrackingInfo 實體。

範例 curl 指令:

# Set JWT, PROJECT_ID, and TRACKING_ID in the local environment
curl -H "Authorization: Bearer ${JWT}" \
  "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/taskTrackingInfo/${TRACKING_ID}"

列出工作

您可以列出伺服器或瀏覽器環境中的工作。驅動程式 SDK 不支援列出工作。

列出工作要求存取工作的權限。只有信任的使用者才能列出工作。提出清單工作要求時,請使用 Delivery Fleet Reader 或 Delivery Super User Authentication Token。

所列工作會遮蓋以下欄位:

  • VehicleStop.planned_location
  • VehicleStop.state
  • VehicleStop.TaskInfo.taskId

列出的工作大多按照工作屬性進行篩選。如需篩選查詢語法,請參閱 AIP-160。下列清單說明可用於篩選的有效工作屬性:

  • attributes
  • Delivery_vehicle_id
  • 最終的隱藏狀態
  • 預計位置
  • 工作持續時間
  • 工作結束
  • 「Task_outcome_location」
  • task_outcome_location_source
  • <工作時間>_outcome_time
  • 追蹤 ID
  • 類型

請使用下列欄位格式以 Google API 改善提案為基礎:

欄位類型 格式 範例
時間戳記 RFC-3339 task_outcome_time = 2022-03-01T11:30:00-08:00
時間長度 後面加上「s」的秒數 task_duration = 120s
列舉 字串 state = CLOSED AND type = PICKUP
位置 point.latitudepoint.longitude planned_location.point.latitude > 36.1 AND planned_location.point.longitude < -122.0

如需篩選查詢運算子的完整清單,請參閱 AIP-160

如未指定任何篩選條件查詢,則會列出所有工作。

工作清單已分頁。可在清單工作要求中指定頁面大小。如果指定頁面大小,傳回的工作數量不會大於指定頁面大小。如未顯示任何頁面大小,則會使用合理的預設值。如果要求的網頁大小超過內部最大值,則會使用內部最大值。

工作清單可包含用來讀取下一頁結果的權杖。將頁面權杖與與上一個要求相同的要求搭配使用,藉此擷取下一頁的工作。如果傳回的網頁符記為空白,則無法再擷取工作。

gRPC

以下範例說明如何使用 Java gRPC 程式庫列出 DeliveryVehicleId 和工作屬性的工作。成功的回應還是可以空白。如果回應為空白,表示沒有任何工作與提供的 shippingVehicleId 建立關聯。

static final String PROJECT_ID = "my-delivery-co-gcp-project";
static final String TRACKING_ID = "TID-7449w087464x5";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Tasks request
String parent = "providers/" + PROJECT_ID;
ListTasksRequest listTasksRequest = ListTasksRequest.newBuilder()  // No need for the header
    .setParent(parent)
    .setFilter("delivery_vehicle_id = 123 AND attributes.foo = true")
    .build();

try {
  ListTasksResponse listTasksResponse = deliveryService.listTasks(listTasksRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
     case NOT_FOUND:
       break;

     case PERMISSION_DENIED:
       break;
  }
  return;
}

REST

如要透過瀏覽器列出工作,請對 ListTasks 發出 HTTP REST 呼叫:

GET https://fleetengine.googleapis.com/v1/providers/<project_id>/tasks

如要將篩選器套用至列出的工作,請加上「篩選器」網址參數,並以網址逸出的篩選器查詢做為值。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

如果查詢成功,回應主體會包含結構如下的資料:

// JSON representation
{
  "tasks": [
    {
      object (Task)
    }
  ],
  "nextPageToken": string,
  "totalSize": integer
}

成功的回應可能仍是空白的。如果回應為空白,表示找不到任何符合指定篩選條件的工作。

範例 curl 指令:

# Set JWT, PROJECT_ID, and VEHICLE_ID in the local environment
curl -H "Authorization: Bearer ${JWT}" \
  "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/tasks?filter=state%20%3D%20OPEN%20AND%20delivery_vehicle_id%20%3D%20${VEHICLE_ID}"

刊登運送車輛

你可以透過伺服器或瀏覽器環境列出快遞車輛。驅動程式 SDK 不支援列出快遞車輛。

刊登車輛會要求廣泛的運送車輛存取權,且僅供信任的使用者使用。提出清單傳遞車輛要求時,請使用 Delivery Fleet Reader 或 Delivery 超級使用者驗證權杖。

所列運送車輛會因回應大小影響而遮蓋下列欄位:

  • CurrentRouteSegment
  • 其餘車輛旅程

你可以依據 attributes 屬性篩選清單運送車輛。舉例來說,如要查詢索引鍵 my_keymy_value 值的屬性,請使用 attributes.my_key = my_value。如要查詢多個屬性,請使用邏輯 ANDOR 運算子來彙整查詢,就像在 attributes.key1 = value1 AND attributes.key2 = value2 中一樣。如需篩選器查詢語法的完整說明,請參閱 AIP-160

您可以使用 viewport 要求參數,依位置篩選列出的快遞車輛。viewport 要求參數會使用兩個邊界座標來定義可視區域:high (northeast) 和 low (西南部) 緯度/經度。如果要求包含的高緯度位置低於較低緯度,就會遭到拒絕。

根據預設,系統會使用合理的頁面大小將運送車輛清單分頁。如果您指定頁面大小,要求只會傳回指定上限 (或更少) 的車輛數量。如果所要求的頁面大小超過內部最大值,則會使用內部最大值。預設頁面大小和最大頁面大小都是 100 輛車。

運送車輛清單可包含用於讀取下一頁結果的權杖。只有在更多運送車輛可供擷取的頁面時,回應中才會出現網頁權杖。如要擷取下一頁的工作,請將頁面符記與與之前要求相同的要求搭配使用。

gRPC

以下範例說明如何使用 Java gRPC 程式庫,透過具有特定屬性的特定區域列出供應車輛。成功的回應可能仍是空白的回應。發生這種情況時,表示目前所有具有指定屬性的車輛都位於指定可視區域中。

static final String PROJECT_ID = "my-delivery-co-gcp-project";

DeliveryServiceBlockingStub deliveryService =
  DeliveryServiceGrpc.newBlockingStub(channel);

// Tasks request
String parent = "providers/" + PROJECT_ID;
ListDeliveryVehiclesRequest listDeliveryVehiclesRequest =
  ListDeliveryVehiclesRequest.newBuilder()  // No need for the header
      .setParent(parent)
      .setViewport(
            Viewport.newBuilder()
              .setHigh(LatLng.newBuilder()
                  .setLatitude(37.45)
                  .setLongitude(-122.06)
                  .build())
              .setLow(LatLng.newBuilder()
                  .setLatitude(37.41)
                  .setLongitude(-122.11)
                  .build())
      .setFilter("attributes.my_key = my_value")
      .build();

try {
  ListDeliveryVehiclesResponse listDeliveryVehiclesResponse =
      deliveryService.listDeliveryVehicles(listDeliveryVehiclesRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
      case NOT_FOUND:
          break;

      case PERMISSION_DENIED:
          break;
  }
  return;
}

REST

如要透過瀏覽器列出工作,請對 ListDeliveryVehicles 發出 HTTP REST 呼叫:

GET https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles

如要對列出的工作套用篩選器,請加入「篩選器」網址參數,並以網址逸出的篩選器查詢做為值。

要求標頭必須包含值為 Bearer <token>Authorization 欄位,其中 <token>由 Fleet Engine 權杖工廠核發的權杖

如果查詢成功,回應主體會包含結構如下的資料:

// JSON representation
{
  "deliveryVehicles": [
    {
      object (DeliveryVehicle)
    }
  ],
  "nextPageToken": string,
  "totalSize": integer
}

成功的回應可能仍是空白的。在這種情況下,代表沒有找到符合指定的篩選查詢和可視區域大小的運送車輛。

範例 curl 指令:

# Set JWT, PROJECT_ID, and VEHICLE_ID in the local environment
curl -H "Authorization: Bearer ${JWT}" \
  "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles?filter=attributes.my_key%20%3D%20my_value%20&viewport.high.latitude=37.45&viewport.high.longitude=-122.06&viewport.low.latitude=37.41&viewport.low.longitude=-122.11"

運送追蹤

使用 Fleet Engine Deliveries API 啟用運送追蹤的方法有兩種:

  • 優先使用:使用 JavaScript 運送追蹤程式庫。這個程式庫可讓您以視覺化方式呈現 Fleet Engine 中追蹤的車輛位置和感興趣的地點。其中包含的 JavaScript 地圖元件,用於直接取代標準 google.maps.Map 物件,以及可與 Fleet Engine 連結的資料元件。這可讓您透過網頁或行動應用程式提供可自訂的運送追蹤體驗。

  • 在 Fleet Engine Deliveries API 上方導入您自己的運送追蹤功能。因此,關鍵就在於依追蹤 ID 查詢運送工作

如果您使用 Delivery Consumer Role,則任何 Fleet Engine Deliveries API 呼叫都只會傳回與貨運公司或接收者相關的資訊。回應中的所有其他資訊都會受到遮蓋。您有責任驗證使用者。此外,系統會根據目前正在執行的工作篩選位置資訊。在無法使用的工作期間,系統不會與使用者分享任何位置資訊。

Logging

您可以啟用選項,讓 Fleet Engine 將 RPC 記錄檔傳送至 Cloud Logging。詳情請參閱 Logging 一文。

授權角色和權杖

如「管理車輛和工作生命週期」和個別用途的授權注意事項所述,呼叫 Fleet Engine 需要使用服務帳戶憑證簽署的 JSON Web Token 進行驗證。用來建立這些憑證的服務帳戶可能有一或多個角色,每個角色會授予一組不同的權限。

詳情請參閱驗證和授權

疑難排解

彈性

Fleet Engine 並非可靠資料來源。您必須在必要時還原系統狀態,不必依賴 Fleet Engine。

Fleet Engine 中的遺失狀態

使用 Fleet Engine 時,請實作用戶端,讓系統在失敗時自行修復。舉例來說,當 Fleet Engine 嘗試更新車輛時,可能會回應並顯示錯誤訊息,指出車輛不存在。然後用戶端應以新的狀態重新建立車輛。在極少數情況下,系統必須保持彈性,以防萬一。

在 Fleet Engine 發生災難性的極少數情況下,您可能需要重新建立大部分或所有車輛和工作。如果建立頻率過高,部分要求可能會因配額問題而再次失敗,因為系統設定了配額檢查,以免發生阻斷服務 (DOS) 攻擊。在這種情況下,請使用輪詢策略來減緩重新建立率。

驅動程式應用程式中的狀態遺失

如果驅動程式應用程式當機,應用程式必須在驅動程式 SDK 中重新建立目前狀態。應用程式應嘗試重新建立工作,以確保工作確實存在,並還原其目前狀態。應用程式也應重新建立並明確設定 Driver SDK 的停靠站清單。

請注意,這些還原作業必須能自主執行,不必依賴 Fleet Engine 中的資訊,而不是指出資料庫中是否已有實體及何時發生錯誤。如果實體已存在,則系統會擷取該錯誤,並使用實體 ID 更新實體。

常見問題

如果司機失序的任務,該怎麼辦?

在這種情況下,請先更新工作的順序,然後照常繼續,將抵達時間標示為停靠點、工作完成等等。否則,系統可能會不一致。預計到達時間可能會不正確,且可能會回報非預期的錯誤。