Fleet Engine 使用入门(货运跟踪)

使用 Fleet Engine Deliveries API。您可以通过使用 Android 版驱动程序 SDK 来使用此 API 或直接通过 HTTP REST 或 gRPC 调用进行。

初始设置

您可以在 Google Cloud 控制台中配置 Fleet Engine Deliveries API。

验证您的设置

创建服务账号后,请验证您的设置是否已完成 并创建送货车辆立即验证您的设置 确保您已解决 设置项目验证设置的方法有两种:

客户端库

为了相对于原始 gRPC 或 REST 获得更好的开发者体验,请使用 客户端库。对于 有关如何获取服务器应用的客户端库的说明,请参阅 客户端库

本文档中的 Java 示例假定您熟悉 gRPC。

数据结构

Fleet Engine Deliveries API 使用两种数据结构来建立取货和送货的模型 发货数量:

  • 用于运输货物的送货车辆。
  • 商品取货和送货任务。

您还可以使用任务来模拟驾驶员休息和计划停车点 在一整天中。

送货车辆

配送车辆负责将货物从仓库运送到送货地点; 以及从上车点到仓库。在某些情况下 将货物直接从自提地点运输到送货地点。

使用驱动程序 SDK 在 Fleet Engine 中创建 DeliveryVehicle 对象 以及发送位置更新以进行物流和车队跟踪。

Tasks

对于车辆在白天执行的操作,您可以根据以下情况分配任务: 操作类型:

  • 对于自提和送货,请分配配送任务
  • 当司机没空时(例如必须休息一下), 分配不可用任务
  • 对于非驾驶型任务,在投递箱或客户所在位置进行分配, 计划停止任务

您分配的每个任务都必须有唯一的任务 ID,但可以共享相同的 ID 跟踪 ID。Fleet Engine 计算预计到达时间时 每个任务的窗口,都会用到所有任务,以及每个任务的 它们计划进行估算。如需详细了解任务 ID,请参阅 任务 ID 准则

如需在 Fleet Engine 中创建任务,请使用驱动程序 SDK 任务管理器。

配送任务

为货物的自提和送货创建配送任务,以及 包含以下信息:

  • 自提或送货地点。
  • 跟踪编号或 ID。
  • 用于说明完成任务所需的停留时间,请查看 或步行至交接点。
  • 唯一的任务 ID。请参阅任务 ID 准则

如需了解详情,请参阅以下主题:

Android

iOS

不可用任务

不可用状态任务涵盖车辆不可用的时间段 自提或送货上门服务,例如给车辆或司机加油的休息时间 休息一下。

使用以下信息创建不可用任务:

  • 广告插播时长。
  • (可选)广告插播时间点的位置。您不必提供 但这样做可以提供更准确的预计到达时间窗口 在一整天中。

如需了解详情,请参阅以下主题:

Android

iOS

计划停止任务

创建计划停止任务,以模拟交付车辆所需的停靠站 。例如,为每天的排定时间创建计划停止任务 在特定地点设置取件站,与其他配送无关 或上车点。您还可以创建计划停止任务 或模型供给车辆接送, 或经停服务。

如需了解详情,请参阅以下主题:

Android

iOS

任务 ID 准则

创建任务 ID 时,请遵循以下内容和格式准则:

  • 创建唯一的任务 ID
  • 请勿泄露任何个人身份信息 (PII) 或 明文数据。
  • 请使用有效的 Unicode 字符串。
  • 字符数不得超过 64 个。
  • 请勿包含以下任意 ASCII 字符:“/”“:”, “\"”、“?”或“#”。
  • 根据 Unicode 标准化形式 C 进行标准化。

以下是一些合适的任务 ID 示例:

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

下表显示了不受支持的任务 ID 的示例:

不受支持的任务 ID 原因
8/31/2019-20:48-46.70746,-130.10807,-85.17909,61.33680 违反个人身份信息和字符要求:逗号、句号、冒号和斜杠。
JohnDoe-577b484da26f-Cupertino-SantaCruz 违反个人身份信息要求。
4R0oXLToF"112 Summer Dr. East Hartford, CT06118"577b484da26f8a 违反个人身份信息和字符要求:空格、逗号和引号。超过 64 个字符。

更多资源

查看每项数据中包含的特定字段 结构,请参阅 DeliveryVehicle 的 API 参考文档 (gRPCREST) 和 TaskgRPCREST)。

车辆使用寿命

DeliveryVehicle 对象表示第一英里或最后一英里的送货车辆。 您可以使用以下代码创建一个 DeliveryVehicle 对象:

  • 服务账号所属的 Google Cloud 项目的 ID 用于调用 Fleet Engine API。
  • 客户拥有的车辆 ID。

为每辆车使用独一无二的车辆 ID。请勿重复使用车辆 ID 除非原始车辆没有有效任务。

Fleet Engine 会自动删除DeliveryVehicle没有 已在七天后使用 UpdateDeliveryVehicle 进行更新。建议的 在 Fleet Engine 中保持车辆可用状态的方法是更新车辆的位置信息 定期更新。更新了 DeliveryVehicle 中的大多数其他字段 实体也会延长其使用期限,但前提是新字段值不同 现有资源

如需查看车辆是否存在,请按以下步骤操作:

  1. 调用 UpdateDeliveryVehicle
  2. 如果收到 NOT_FOUND 错误,请调用 CreateDeliveryVehicle。 以便重新创建该车辆 如果调用返回车辆,该车辆仍可更新。

车辆类型

VehicleType 实体包含 VehicleType 的可选字段,该字段包含一个 Category 枚举,可指定为 AUTOTWO_WHEELERBICYCLEPEDESTRIAN。如果未设置该字段,则默认为 AUTO

车辆的所有路线安排都使用相应的 RouteTravelMode

车辆属性

DeliveryVehicle 实体包含 DeliveryVehicleAttributeListDeliveryVehicles API 包含一个 filter 字段,可以将返回的 DeliveryVehicle 实体限定为具有 指定属性。DeliveryVehicleAttribute不会影响 Fleet Engine 路由行为

请勿包含个人身份信息 (PII) 或敏感信息 因为用户可能会看到此字段。

任务的生命周期

您可以使用以下命令在 Fleet Engine 中创建、更新和查询任务 Deliveries API gRPC 或 REST 接口。

Task 对象有一个状态字段,用于跟踪其进度 其生命周期。这些值会从“打开”变为“已关闭”。创建了新任务 ,这表示:

  • 此任务尚未分配给配送车辆。
  • 配送车辆尚未超过任务指定的车辆经停点。

任务指南

您只能将任务分配给处于“打开”状态的车辆。

您可以通过从车辆经停点列表中移除任务来取消任务, 自动关闭任务状态。

当任务的车辆完成任务时,车辆会停止:

  1. 将任务的结果字段更新为 SUCCEEDED 或 FAILED。

  2. 指定事件的时间戳。

    JavaScript 物流跟踪库会指明任务的结果并 任务状态会自动设置为“已关闭”。如需了解详情,请参阅 使用 JavaScript 物流跟踪库跟踪物流信息

与车辆一样,Fleet Engine 会删除 如果尝试使用已存在的 ID 创建任务 它会返回错误。

注意:Fleet Engine 不支持明确删除任务。服务 会在七天后自动删除任务,而不进行更新。 如果您要将任务数据保留超过 7 天, 您必须自行实现该功能

任务属性

Task 实体包含 TaskAttribute,其值可以是以下 3 种类型之一:字符串、数字 和布尔值。ListTasks API 包含可以限制返回的 filter 字段 将 Task 实体转换为具有指定属性的实体。任务属性不 Fleet Engine 路由行为。

请勿包含个人身份信息 (PII) 或其他敏感信息 因为用户可能会看到这些属性。

管理车辆和任务生命周期

温馨提示:您的内部系统是数据来源的可靠来源, Fleet Engine Deliveries API 可代您进行增强。

如需管理系统中的车辆和任务生命周期,请使用 Fleet Engine Deliveries API 创建、更新和跟踪你的车辆及相关任务。

同时,驱动程序应用直接与 Fleet Engine 通信 以更新设备位置和路线信息。利用此模型,Fleet Engine 高效管理实时位置信息。它会将该位置信息直接发送到 跟踪库,您随后可以使用该库向消费者更新商品 订单的一部分

例如,假设您遇到以下情况:

  • 一名司机靠近配送站。驱动程序应用将其位置信息发送到 Fleet Engine。
  • Fleet Engine 将设备位置信息发送到 跟踪库,您的消费者应用程序使用该库来提醒使用者 尽可能靠近他们的包裹
  • 司机完成装运后,点击“已送达” 按钮。
  • “运单已送达”操作会将信息发送到您的后端系统 用于执行必要的业务验证和验证步骤。
  • 您的系统确认任务为“SUCCEEDED”(成功),并使用 Deliveries API。

下图在通用层面说明了这些过程。它还 显示您的系统、客户、 和 Fleet Engine。

使用 Deliveries API

管理客户端令牌

源自驱动程序应用并直接发送的位置信息更新 Fleet Engine 需要授权令牌。以下是推荐的方法 来处理从客户端到 Fleet Engine 的更新:

  1. 使用 Fleet Engine Delivery Untrusted Driver User 生成令牌 服务账号角色。

  2. 为驱动程序应用提供范围有限的令牌。此范围 仅允许它在 Fleet Engine 中更新设备位置。

这种方法可确保将来自移动设备的来电视为 低信任环境,并遵守 最小权限原则

其他服务账号角色

改为授权驱动程序应用直接执行 除“不受信任的驾驶员”角色以外的 Fleet Engine 更新 例如对于某些任务更新,您可以使用“可信驱动程序”角色。对于 有关使用“可信驾驶员”角色的模型的信息,请参阅 “可信驾驶员”模型

如需详细了解不可信和可信驱动程序角色的用途,请参阅 Cloud 项目设置

模拟工作日

下表介绍了“第一公里”或“最后一公里”司机的工作日 这就是配送物流公司的情况。您的公司可能会 但您可以看看如何模拟工作日。

时间活动建模
当天开始后 24 小时内 调度员负责向送货车辆或路线分配货物。 您可以创建关于运送包裹、取货、休息和 Fleet Engine 中的其他应用。例如,您可以创建一个 shipment pickup task(发货自提任务), 运送任务计划不可用,或者 计划经停点

完成一系列配送包裹后,将任务分配给车辆 并且它们的提交顺序也最终确定了
当天开始时间 登录 Driver 应用,司机即可在补货站开启新的一天。 初始化 Delivery Driver API。 根据需要在 Fleet Engine 中创建送货车辆
司机将货物加载到送货车辆上,扫描货物。 如果未提前创建货运送货任务 创建货运配送任务
驾驶员确认要执行的任务的顺序。 如果订单项不是提前创建的 运送任务计划的不可用性,以及 计划经停点
司机离开仓库并提交下一批任务 已完成。 分配所有任务或部分任务 向车辆提交完成订单。
司机在运送包裹。 到达配送站后,请执行相关的操作 抵达经停点的车辆。 发货后,关闭 交付任务,并视需要执行 商店配送状态和其他元信息。 在站点或位置之前完成所有任务之后 开始驾车前往下一站时,执行与以下内容相关的操作: 车辆完成经停点 车辆正在前往下一站
司机遇到供给车辆,将其他货物转移到配送车辆上。 供给车辆和送货车辆之间的交接点 建模为计划经停点

转账和扫描货物后,创建送货任务 (如果尚未创建)。然后更新任务完成情况 通过将任务分配给车辆来排序 以及更新任务排序
司机收到自提请求通知。 接受自提请求后, 创建货物自提任务。 然后,更新任务执行 通过将任务分配给车辆来排序 以及更新任务排序
中午 司机在午休。 如果某个营业地点与不可用性任务相关联,请将其视为 任何其他任务执行与车辆相关的操作 抵达经停点车辆完成经停点 车辆正在前往下一站

否则,在广告插播结束前无需执行任何其他操作。 通过确认下一个任务和其余任务来移除该任务,并且 更新任务排序
司机取件。 这与配送停止类似。执行相关操作 抵达经停点的车辆关闭任务,还可以选择执行 存储运送状态和其他元信息。 在停车点完成所有任务后,开始驾车前 到下一站时,执行与车辆完成经停相关的操作 车辆正在前往下一站。 注意:为确保账单正确无误,所有自提订单都必须有相应的 交付任务。如果自提商品要配送到 司机当天的路线,我们建议根据模型估算该配送任务 其他交付任务。司机是否将上车点带到上车点 还是建议在仓库中创建一个配送任务 目标。
司机安排好经停点,从投递箱取货。 此模型与任何其他上车点一样。执行相关操作 抵达经停点的车辆 以及关闭任务。完成之后 执行与车辆完成停车相关的操作 车辆正在前往下一站
司机收到货物正转移到其他地点的通知。 将原始运单交付任务状态设置为“已完成”,并创建一个新的 新送货地点的送货任务。如需更多信息 请参阅重新递送包裹
司机尝试递送包裹,但未能成功。 这与成功的投放停止类似,将 而不是将其状态设为“已完成”。执行与以下内容相关的操作: 抵达经停点的车辆。更新后 无法送达 关闭任务,并视需要执行下列操作: 商店配送状态和其他元信息。 在停车点完成所有任务后,开始驾车前 到下一站时,执行与车辆完成经停相关的操作 车辆正在前往下一站
已通知司机暂缓发货。 收到并确认通知后, 将任务状态设为“COMPLETED”。
司机接下来收到了配送某件货物的通知,从而更改了承诺配送订单。 更新任务排序
司机选择不按订单配送商品。 更新任务排序,然后 继续照常进行
司机将多件货物都送到一个地点。 其模型类似于单个运单送货站。 到达相应经停点后,执行 车辆抵达经停点。 交付每件货品后,关闭每项任务 以及(可选)商店配送状态和其他元信息。 在停车点完成所有任务后,开始驾车前 到下一站时,执行与车辆完成经停相关的操作 车辆正在前往下一站
当天结束时间 司机返回补给站。 如果司机返回补货站并在期间将货物取回 您还必须创建并关闭每个包裹,以将其作为交付任务, 确保账单正确无误为此,您可以像对仓库进行建模一样 其他传送停止。 如果仓库不用作送货站 将仓库建模为预定停靠站。根据模型估算经停点可让您的司机了解 返回补给站的路线,让其他人了解预计用时 到达时间。

位置信息更新的运作方式

为了让 Fleet Engine 达到最佳性能,请为其提供一流车辆 位置更新。使用以下任一方法提供这些更新:

  1. 使用驱动程序 SDK - AndroidiOS -- 最简单的方法。
  2. 使用自定义代码;如果需要 或者您使用的是 Android 或 iOS 版。

无论您通过何种方式提供车辆位置信息更新, 负责更新 Fleet Engine, 前往经停点(包括仓库)的途中以及 在经停点抵达。Fleet Engine 未检测到这些事件 。

车辆停靠点和送货地点

车辆停靠点是指送货车辆完成运送任务的位置 或其他任务可以是接入点(如加载基座)或 道路相邻的位置。

送货地点是指商品送达的地点 或被选中的对象往返送货地点可能需要一些步行距离 从车辆停止。

例如,当司机在向商场内的商店配送商品时, 送货车辆停在附近购物中心的停车场 离商店最近的入口这是车辆停靠站。驾驶员 然后,从车辆停靠站步行至购物中心内的相应位置 该商店所在的位置这是送货地点。

为了让用户获得最佳物流跟踪体验,请考虑 配送任务分配给车辆经停点,并注意 将剩余车辆停靠点报告给用户,以协助其完成运送任务 查看发货进度。

例如,如果一名司机需要为一栋办公楼配送多件商品, 不妨考虑将所有配送任务都分配给单个车辆停车点。如果 都会分配到各自的车辆停靠点, 那么跟踪体验对用户的用处就会小, 其目的地。在短时间内完成多个车辆停靠站并不表示 并为用户提供大量时间来跟踪其交付进度。

使用移动 SDK

在调用驱动程序 SDK 之前,请务必对其进行初始化。

初始化 Delivery Driver API

在驱动程序 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));
     }
   });
<ph type="x-smartling-placeholder">

使用场景

本部分介绍了如何使用 Deliveries API 为常见用例建模。

唯一实体标识符

REST 调用中使用的唯一实体标识符的格式和值如下: 对 Fleet Engine 而言是不透明的。避免使用自动递增 ID,并确保 该标识符不包含任何个人身份信息 (PII); 例如驾驶员的电话号码

创建车辆

您可以通过以下任一方式创建车辆: 驱动程序 SDK,或者从使用 gRPC 或 REST 的服务器环境获取驱动程序。

gRPC

如需创建新车辆,请对 Fleet Engine 发出 CreateDeliveryVehicle 调用。 使用 CreateDeliveryVehicleRequest 对象定义 以及新的送货车辆。请注意,为 Name 字段指定的任何值都是 根据用户指定的 ID 的 API 指南,会被忽略。 您应使用 DeliveryVehicleId 字段设置车辆的 ID。

创建 DeliveryVehicle 时,您可以选择指定以下字段:

  • 属性
  • LastLocation
  • 类型

不要设置任何其他字段。否则,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

如需从服务器环境创建车辆,请执行 HTTP REST 调用 至 CreateDeliveryVehicle

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

&lt;id&gt; 是车队中运载车辆的唯一标识符

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

POST 正文表示要创建的 DeliveryVehicle 实体。您可以指定 以下可选字段:

  • 属性
  • lastLocation
  • 类型

示例 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

Fleet Engine 会根据用户指定的 ID 的 API 指南,忽略 DeliveryVehicle 实体的 name 字段。 不要设置任何其他字段。否则,Fleet Engine 会返回错误 因为这些字段要么是只读字段,要么只能使用 UpdateDeliveryVehicle

若要在不设置任何字段的情况下创建车辆,请保留 POST 的正文 请求为空。然后,新创建的车辆从 POST 网址中的 deliveryVehicleId 参数。

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

创建货物自提任务

您可以通过以下任一位置创建货物自提任务: 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中

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

如需从服务器环境创建货物自提任务,请执行 HTTP REST 调用 至 CreateTask

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

&lt;id&gt; 是任务的唯一标识符。不得为跟踪编号 。如果您的系统中没有任务 ID, 通用唯一标识符 (UUID)。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 Task 实体:

  • 必填字段:

    字段
    类型 Type.PICKUP
    State.OPEN
    trackingId 您用于跟踪运单的编号或标识符。
    plannedLocation 需要完成任务的位置,在本例中为 发货地址。
    taskDuration 取货所需的预计时间(以秒为单位) 送至上车点。

  • 选填字段:

    字段
    targetTimeWindow 应完成任务的时间范围。这并不 影响路由行为。
    属性 自定义任务属性列表。每个属性必须具有唯一的键。

在创建时,实体中的所有其他字段都将被忽略。Fleet Engine 抛出 如果请求包含已分配的 deliveryVehicleId,则会发生异常。您分配 使用 UpdateDeliveryVehicleRequest 完成任务。如需了解详情,请参阅 将任务分配给车辆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

创建货运配送任务

从以下位置创建货运送货任务: 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中

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

如需使用 gRPC 或 REST 从服务器环境创建运单递送任务,请执行 HTTP REST 调用 至 CreateTask

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

&lt;id&gt; 是任务的唯一标识符。不得为跟踪编号 。如果您的系统中没有任务 ID, 通用唯一标识符 (UUID)。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 Task 实体:

  • 必填字段:

    字段
    类型 Type.DELIVERY
    State.OPEN
    trackingId 您用于跟踪运单的编号或标识符。
    plannedLocation 需要完成任务的位置,在本例中为 此运单的送货地点。
    taskDuration 发货所需的预计时间(以秒为单位) 收货地址

  • 选填字段:

    字段
    targetTimeWindow 应完成任务的时间范围。这并不 影响路由行为。
    属性 自定义任务属性列表。每个属性必须具有唯一的键。

在创建时,实体中的所有其他字段都将被忽略。Fleet Engine 抛出 如果请求包含已分配的 deliveryVehicleId,则会发生异常。您分配 使用 UpdateDeliveryVehicleRequest 完成任务。如需了解详情,请参阅 将任务分配给车辆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 或 REST 从服务器环境创建一批任务。

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 的 Authorization <token>,其中 <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

计划不可用

您可以创建一个指明服务不可用的任务(例如,为驾驶员创建 例如断路或给车辆加油 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中计划不可用任务不得包含 跟踪 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

如需从服务器环境创建不可用任务,请执行 HTTP REST 调用 至 CreateTask

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

&lt;id&gt; 是任务的唯一标识符。如果您 在系统中拥有任务 ID,则可以生成一个通用唯一 标识符 (UUID)。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 Task 实体:

  • 必填字段:

    字段
    类型 Type.UNAVAILABLE
    State.OPEN
    taskDuration 广告插播时长(以秒为单位)。

  • 选填字段:

    字段
    plannedLocation 插播时间点的位置(如果必须在特定位置拍摄)。

在创建时,实体中的所有其他字段都将被忽略。Fleet Engine 抛出 如果请求包含已分配的 deliveryVehicleId,则会发生异常。您分配 使用 UpdateDeliveryVehicleRequest 完成任务。如需了解详情,请参阅 将任务分配给车辆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

计划的经停点

您可以通过以下任一方式创建计划停止任务: 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中计划停止任务可能不包含跟踪信息 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

如需从服务器环境创建计划停止任务,请执行 HTTP REST 调用 至 CreateTask

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

&lt;id&gt; 是任务的唯一标识符。如果您没有 任务 ID,您可以生成 通用唯一标识符 (UUID)。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 Task 实体:

  • 必填字段:

    字段
    类型 Type.SCHEDULED_STOP
    State.OPEN
    plannedLocation 相应经停点的位置。
    taskDuration 预期的经停时长(以秒为单位)。

  • 可选字段:

在创建时,实体中的所有其他字段都将被忽略。Fleet Engine 抛出 如果请求包含已分配的 deliveryVehicleId,则会发生异常。您分配 使用 UpdateDeliveryVehicleRequest 完成任务。如需了解详情,请参阅 将任务分配给车辆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`

&lt;id&gt; 是任务的唯一标识符

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 Task 实体:

  • 必填字段:

    字段
    targetTimeWindow 应完成任务的时间范围。此设置 不会影响路由行为

  • 可选字段:

对于更新,将忽略实体中的所有其他字段。

示例 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

设置任务跟踪可见性配置

运送跟踪库中的数据及相应数据的公开范围 可以按任务控制 GetTaskTrackingInfo 方法是设置一个 TaskTrackingViewConfig 任务。请参阅 进行中的车辆任务 。您可以在创建或更新 任务。以下示例展示了如何使用此配置更新任务:

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`

&lt;id&gt; 是任务的唯一标识符

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <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

向车辆分配任务

您可以通过更新任务排序来将任务分配给送货车辆 。车辆的任务排序由列表决定 车辆停靠点数,并且您可以为配送车辆分配一项或多项任务 到达每个经停点。有关详情,请参阅 更新任务排序

如需将货车从一辆车改为另一辆车,请关闭原始任务 然后重新创建,再为其分配新车辆。如果更新任务 对已分配的任务进行排序 则会收到错误消息。

更新任务排序

您可以通过以下任一位置更新分配给车辆的订单任务: 该 驱动程序 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

如需从服务器环境中更新车辆的任务排序,请执行 HTTP REST 调用 至 UpdateDeliveryVehicle

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

&lt;id&gt; 是车队中运载车辆的唯一标识符 您打算更新其任务排序时。它是一个标识符 。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 DeliveryVehicle 实体:

  • 必填字段:

    字段
    remainingVehicleJourneySegments 按执行顺序排列任务的过程细分列表。 列表中的第一个任务最先执行。
    remainingVehicleJourneySegments[i].stop 列表中任务 的停止点。
    remainingVehicleJourneySegments[i].stop.plannedLocation 计划的经停点位置。
    remainingVehicleJourneySegments[i].stop.tasks 要在此车辆停靠站执行的任务列表。
    remainingVehicleJourneySegments[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 必须收到通知 导航。您可以通过以下任一方式通知 Fleet Engine 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中不要同时使用这两种方法来避免竞态 以及维持单一可信来源。

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
    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`

&lt;id&gt; 是车队中运载车辆的唯一标识符 您打算更新其任务排序时。它是一个标识符 。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 DeliveryVehicle 实体:

  • 必填字段:

    字段
    remainingVehicleJourneySegments 剩余车辆经停点列表,其中状态已标记为 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

更新车辆位置

如果您不使用 Driver SDK 来更新车辆的位置,那么您可以 直接调用 Fleet Engine 并提供车辆的位置信息。对于任何有效车辆, Fleet Engine 预计每分钟至少更新一次位置信息,最多一次 每 5 秒一次。

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 myDeliveryVehicle = DeliveryVehicle.newBuilder()
    .setLastLocation(DeliveryVehicleLocation.newBuilder()
        .setSupplementalLocation(LatLng.newBuilder()
            .setLatitude(37.3382)
            .setLongitude(121.8863))
        .setSupplementalLocationTime(now())
        .setSupplementalLocationSensor(DeliveryVehicleLocationSensor.CUSTOMER_SUPPLIED_LOCATION)
        .setSupplementalLocationAccuracy(DoubleValue.of(15.0)))  // Optional
    .build();

// DeliveryVehicle request
UpdateDeliveryVehicleRequest updateDeliveryVehicleRequest =
  UpdateDeliveryVehicleRequest.newBuilder()  // No need for the header
      .setName(vehicleName)
      .setDeliveryVehicle(myDeliveryVehicle)
      .setUpdateMask(FieldMask.newBuilder()
          .addPaths("last_location"))
      .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

要使用 HTTP REST 在 Fleet Engine 中更新车辆的位置,请调用 UpdateDeliveryVehicle:

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

&lt;id&gt; 是您所在订单中的送货车辆的唯一标识符 舰队或您打算更新位置的。它是一个标识符 。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 DeliveryVehicle 实体:

  • 必填字段:

    字段
    lastLocation.supplementalLocation 车辆的位置。
    lastLocation.supplementalLocationTime 车辆在此位置的最后一个已知时间戳。
    lastLocation.supplementalLocationSensor 应填充 CUSTOMER_SUPPLIED_LOCATION。

  • 选填字段:

    字段
    lastLocation.supplementalLocationAccuracy 所提供位置的精确度(以米为单位)。

示例 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
{
  "lastLocation": {
    "supplementalLocation": {"latitude": 12.1, "longitude": 14.5},
    "supplementalLocationTime": "$(date -u --iso-8601=seconds)",
    "supplementalLocationSensor": "CUSTOMER_SUPPLIED_LOCATION",
    "supplementalLocationAccuracy": 15
  }
}
EOM

车辆抵达一个经停点

Fleet Engine 必须在有车辆到达停车点时收到通知。您可以通知 Fleet Engine 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中不要同时使用这两种方法来避免竞态 以及维持单一可信来源。

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`

&lt;id&gt; 是车队中运载车辆的唯一标识符 您打算更新其任务排序时。它是一个标识符 。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 DeliveryVehicle 实体:

  • 必填字段:

    字段
    remainingVehicleJourneySegments 您到达的经停点的状态设为 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 必须收到通知。这会导致 将与停止相关的所有任务设置为“关闭”状态。您可以 通过以下任一方式通知 Fleet Engine 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中 请勿同时使用这两种方法来避免出现竞态条件并保持单一可信来源。

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`

&lt;id&gt; 是车队中运载车辆的唯一标识符 您打算更新其任务排序时。它是一个标识符 。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 DeliveryVehicle 实体:

  • 必填字段:

    字段
    remaining_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) // You can only directly CLOSE a
  .build();                    // task that 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:

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

&lt;id&gt; 是任务的唯一标识符

您的请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

您必须在请求正文中添加 Task 实体:

  • 必填字段:

    字段
    State.CLOSED

  • 选填字段:

    字段
    taskOutcome Output.SUCCEEDED 或 Outcome.FAILED
    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

设置任务结果和结果位置

任务的关闭并不表示成功或失败,而是表明 该任务不会再被视为正在进行中。如需跟踪物流信息, 请务必指明任务的实际结果 并显示交付结果,且服务结算正确。 任务结果一经设置便无法更改。不过,您可以 任务结果时间和任务结果位置。

处于“已关闭”状态的任务,其结果可以设置为 SUCCEEDED 或 FAILED。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`

&lt;id&gt; 是任务的唯一标识符

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <token>Fleet Engine 令牌工厂颁发的令牌

请求正文必须包含 Task 实体:

  • 必填字段:

    字段
    taskOutcome Output.SUCCEEDED 或 Outcome.FAILED

  • 选填字段:

    字段
    taskOutcomeLocation 完成任务的位置。如果未设置,Fleet Engine 默认为最近一次使用车辆的位置。
    taskOutcomeTime 任务完成时的时间戳。

对于更新,将忽略实体中的所有其他字段。

示例 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 服务外引用,请使用与 将任务用作外部表中的键。

如需了解详情,请参阅任务的生命周期

查找车辆

您可以在以下位置查找车辆: 驱动程序 SDK 或者从使用 gRPC 或 REST 的服务器环境中

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>`

&lt;id&gt; 是任务的唯一标识符

&lt;vehicleId&gt; 是要查询的车辆的 ID。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <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}"

查找任务

您可以使用 gRPC 或 REST 从服务器环境中查找任务。驱动程序 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>`

&lt;id&gt; 是任务的唯一标识符

&lt;taskId&gt; 是要查找的任务的 ID。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <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 查找信息,您可以使用以下任一方法:

查询要求

  • 跟踪 ID 提供的运单信息符合可见性规则 声明 控制所跟踪地点的公开范围

  • 使用 Fleet Engine 根据跟踪 ID 查询物流信息。驾驶员 SDK 不支持按跟踪 ID 查询信息。要使用 Fleet 执行此操作 Engine,您需要使用服务器或浏览器环境。

  • 使用尽可能窄的令牌限制安全风险。例如,如果您 使用交付使用方令牌,则任何 Fleet Engine Deliveries API 调用会返回 只与最终用户相关的信息(如发货人或 收货人。回答中的所有其他信息都会被隐去。 有关令牌的详细信息,请参阅 创建用于授权的 JSON 网络令牌 (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:

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

&lt;tracking_id&gt; 是与任务关联的跟踪 ID。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <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 超级用户身份验证 发出列出任务请求时使用的令牌。

所列任务的以下字段会被隐去:

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

列出的任务可以按大多数任务属性进行过滤。对于过滤条件查询语法: 请参阅 AIP-160。以下列表显示了有效任务 可用于过滤的属性:

  • 属性
  • delivery_vehicle_id
  • planned_location
  • task_duration
  • task_outcome
  • task_outcome_location
  • task_outcome_location_source
  • task_outcome_time
  • tracking_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 和任务属性的任务。成功的 响应仍可以为空。空响应表示没有任务 与提供的 deliveryVehicleId 相关联。

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`

如需对列出的任务应用过滤条件,请添加“过滤条件”以网址转义的过滤器查询作为其值的网址参数。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <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 Super 发出列表交付车辆请求时使用的用户身份验证令牌。

由于以下字段的影响,所列送货车辆会被隐去 对响应大小的影响:

  • CurrentRouteSegment
  • RemainingVehicleJourneySegments

您可以按 attributes 属性过滤列表送货车辆。对于 例如,要查询键为 my_key、值为 my_value 的属性,请使用 attributes.my_key = my_value。如需查询多个属性,请联接查询 使用逻辑 ANDOR 运算符,如 attributes.key1 = value1 AND attributes.key2 = value2 中所示。如需了解详情,请参阅 AIP-160 过滤器查询语法的说明。

您可以使用 viewport 请求按位置过滤列出的送货车辆 参数。viewport 请求参数使用两个边界来定义视口 坐标:high(东北)和 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`

如需对列出的任务应用过滤条件,请添加“过滤条件”网址参数 经过网址转义的过滤器查询作为其值。

请求标头必须包含字段 Authorization(值为 Bearer <token>,其中 <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。通过该组件 提供可定制的动画式物流跟踪体验 从您的 Web 应用或移动应用中移除。

  • 在 Fleet Engine Deliveries API 之上实现您自己的货运跟踪。

关键是根据跟踪 ID 查找运单任务

如果您使用 Delivery Consumer 角色,则任何 Fleet Engine Deliveries API 会调用 只返回与发货人或收货人相关的信息。所有其他 回答中的信息会被隐去。一切由您负责 用于对最终用户进行身份验证此外,系统会通过过滤功能 进行微调。在执行不可用任务期间 不会与最终用户分享位置信息。

日志记录

您可以将 Fleet Engine 设置为将 RPC 日志发送到 Cloud Logging。有关 请参阅 日志记录

授权角色和令牌

管理车辆和任务生命周期中所述 以及各个应用场景的授权说明 调用 Fleet Engine 需要使用 已使用服务账号凭据进行签名。使用的服务账号 可以拥有一个或多个角色,每个角色都可以授予 一组不同的权限。

如需了解详情,请参阅 身份验证和授权

排查常见问题

如果您遇到任何问题,请查看以下部分以获取帮助。

弹性

Fleet Engine 不属于可信来源。一切由您负责 用于恢复系统状态,而不依赖于 Fleet Engine。

Fleet Engine 中的丢失状态

使用 Fleet Engine 时,请实现客户端以使系统修复 将由系统自身返回例如,当 Fleet Engine 尝试更新 它可能会响应一条错误消息,指示车辆 存在。然后,客户端应重新创建处于新状态的车辆。虽然 此问题很少发生,请确保您的系统能够灵活处理, 。

在极其罕见的 Fleet Engine 发生灾难性故障的情况下, 您可能需要重新创建大部分或所有车辆和任务。如果创建速率 某些请求可能会因配额问题而再次失败 配额检查是为了避免拒绝服务 (DOS) 攻击。 在这种情况下,可以使用退避策略来降低重新创建速率, 重试次数。

司机应用中的丢失状态

如果驾驶应用崩溃,则必须重新创建当前状态 。应用应尝试重新创建任务,以确保 并恢复其当前状态。应用还应 重新创建并明确设置驱动程序 SDK 的站点列表。

常见问题解答

如果司机为了不按顺序而停下车,该怎么办?

在这种情况下,请先更新任务的顺序,然后照常执行, 标记到达站点、任务完成和其他细节。 否则,系统可能会变得不一致,加大型文字广告可能会变得不正确。 系统可能会报告意外错误