借助 Fleet Engine Deliveries API,您可以针对第一公里和最后一公里的配送,对车队活动进行建模。Deliveries API 通过适用于 Android 和 iOS 的 Driver SDK 公开,也可以通过 HTTP REST 或 gRPC 调用直接使用。
初始设置
Fleet Engine Deliveries API 通过 Google Cloud 控制台进行配置。如需了解在控制台中采取的步骤,以及如何创建 JSON Web 令牌以进行授权,请参阅身份验证和授权。如需详细了解如何使用控制台,请参阅 Google Cloud 控制台文档。
验证设置
创建服务帐号后,您应验证设置已完成,然后便可以创建配送车辆。通过在工作流的这一阶段进行验证,您可以确保已解决设置项目时可能出现的常见授权问题。按照验证您的设置指南操作。
本指南详细介绍了如何使用 gcloud
命令行实用程序测试设置的两个关键部分:授权令牌签名和试用交付车辆创建。
或者,您也可以使用 Fleet Engine Auth 示例脚本来测试您的设置。
客户端库
我们使用几种常用的编程语言发布客户端库。与原始 REST 或 gRPC 相比,这些库能够提供更好的开发者体验。如需了解如何获取服务器应用的客户端库,请参阅客户端库。
本文档中的 Java 示例假设您熟悉 gRPC。
数据结构
Deliveries API 使用两种数据结构来模拟货物的取货和配送:
- 用于运输货物的配送车辆。
- 货物自提和配送任务。
此外,您可以使用任务对全天的驾驶员间歇和计划停靠站进行建模。
送货车辆
货运车辆将货物从仓库运送到投递地点,以及从取货地点运输到仓库。在某些情况下,他们可能还会将货物直接从自提地点运送到送货地点。
您可以使用 Driver SDK 在 Fleet Engine 中创建 DeliveryVehicle
对象,并发送位置信息更新以进行运输和车队跟踪。
任务
每辆车都分配有任务。其中可能包括取货或送货任务、司机需要的休息时间,或投递箱或客户位置的预定停靠站。每项任务都必须具有唯一的任务 ID,但可以共用同一个跟踪 ID。任务及其调度顺序可用于计算每项任务的预计到达期限。
使用 Driver SDK 任务管理器在 Fleet Engine 中创建任务。
运单任务
装运任务与货物提货或发货相关。 您必须在创建配送任务时指定跟踪编号或 ID。您还必须指定停留时间,以便将完成任务、查找停车位或步行到交接点所需的额外时间考虑在内。
- 创建用于提货的提货任务,并指定提货位置和跟踪编号或 ID。
- 创建用于配送的配送任务,指定送货位置和跟踪编号或 ID。
不可用任务
针对车辆无法自提或送餐的时间段创建不可用任务。这可以是为车辆加油的休息时间,也可以是司机休息时间。在创建任务时指定广告插播时间点的长度。休息时间不一定在特定地点拍摄,但指定位置可以全天更准确地提供 ETA 时段。
在服务不可用任务期间,系统不会与最终用户共享任何位置信息。例如,使用舰队跟踪库的车队经理无法看到送货车辆位置。
计划内停止任务
创建计划停靠任务,对配送车辆产生的停靠站进行建模。 例如,您可以为每日预定收集站在特定位置创建计划停止任务,这与同一位置的其他配送或自提服务无关。您还可以为来自保管箱的集合创建计划停止任务,或者为服务中心和服务点的供给车辆转移或停靠站建模。
如需了解每个数据结构中包含的特定字段,您可以查看 DeliveryVehicle
(gRPC、REST)和 Task
(gRPC、REST)的 API 参考文档。
任务 ID 指南
任务 ID 必须是唯一的,并且不得泄露任何个人身份信息 (PII) 或明文数据。任务 ID 还必须符合以下格式要求:
- ID 必须是有效的 Unicode 字符串。
- ID 不得超过 64 个字符。
- ID 将根据 Unicode 标准化表单 C 进行标准化处理。
- ID 不得包含以下任何 ASCII 字符:“/”、“":"”、“\”、“?”或“#”。
以下是一些合适的任务 ID 示例:
- 566c33d9-2a31-4b6a-9cd4-80ba1a0c643b
- e4708eabcfa39bf2767c9546c9273f747b4626e8cc44e9630d50f6d129013d38
- NTA1YTliYWNkYmViMTI0ZmMzMWFmOWY2NzNkM2Jk
下表显示了错误任务 ID 的示例:
错误的任务 ID | 原因 |
---|---|
2019 年 8 月 31 日 - 20:48-46.70746,-130.10807,-85.17909,61.33680 | 违反个人身份信息和字符要求:英文逗号、英文句号、冒号和斜杠。 |
JohnDoe-577b484da26f-库珀蒂诺-圣克鲁斯 | 违反个人身份信息要求。 |
4R0oXLToF”112 Summer Dr. East Hartford, CT06118”577b484da26f8a | 违反个人身份信息和字符要求:空格、逗号和引号。超过 64 个字符。 |
车辆的使用寿命
DeliveryVehicle
对象表示第一英里或最后一公里的送货车辆。您可以使用以下文件创建 DeliveryVehicle
对象:
- Google Cloud 项目的 ID,其中包含用于调用 Fleet Engine API 的服务帐号。
- 客户拥有的车辆 ID。
每辆车的车辆 ID 都应是唯一的。它们不应重复用于其他车辆,除非该车辆没有处于活跃状态的任务。
调用 UpdateDeliveryVehicle
时,请务必检查是否存在 NOT_FOUND 错误,然后根据需要调用 CreateDeliveryVehicle
创建新车辆。未使用 UpdateDeliveryVehicle
更新的 DeliveryVehicle
对象将在七天后自动删除。请注意,使用已存在的项目 ID/车辆 ID 对调用 CreateDeliveryVehicle
会引发错误。
车辆属性
DeliveryVehicle
实体包含 DeliveryVehicleAttribute
的重复字段。ListDeliveryVehicles
API 包含一个 filter
字段,可以将返回的 DeliveryVehicle
实体限制为具有指定属性的实体。DeliveryVehicleAttribute
不会影响 Fleet Engine 路由行为。
请勿在属性中添加个人身份信息或敏感信息,因为用户可能可以看到此字段。
任务的生命周期
您可以使用 Deliveries API gRPC 或 REST 接口创建、更新和查询 Fleet Engine 中的任务。
Task
对象具有一个状态字段,用于跟踪其在其生命周期中的进度。值会从“打开”变为“关闭”。新任务在创建时处于“打开”状态,这表示:
- 此任务尚未分配给配送车辆。
- 配送车辆尚未经过任务中指定的车辆停靠点。
任务只能分配给处于打开状态的车辆。
可通过从车辆停靠站列表中移除任务来取消该任务。随后,系统会自动将其状态设为“已关闭”。
当任务车辆完成任务的车辆停车后,将任务的结果字段更新为 SUCCEEDED 或 FAILED,并指定事件的时间戳。任务结果可在任务完成前后随时设置,但只能设置一次。
然后,JavaScript 舰队跟踪库就可以指示任务的结果。任务状态会自动设置为“已关闭”。如需了解详情,请参阅使用 JavaScript 舰队跟踪库跟踪舰队。
与车辆一样,七天后仍未更新的任务会被删除,如果尝试使用已存在的 ID 创建任务,系统会返回错误。
注意:Fleet Engine 不支持明确删除任务。该服务会在七天后自动删除任务,但不会进行更新。如果您希望将任务数据保留 7 天以上,则必须自行实现该功能。
任务属性
Task
实体包含 TaskAttribute
的重复字段,其值可能来自以下三种类型之一:字符串、数字和布尔值。ListTasks
API 包含一个 filter
字段,可以将返回的 Task
实体限制为具有指定属性的实体。TaskAttribute
不会影响 Fleet Engine 路由行为。
请勿在属性中添加个人身份信息或敏感信息,因为用户可能可以看到此字段。
管理车辆和任务生命周期
如需管理系统中的车辆和任务生命周期,您可以使用 Fleet Engine Deliveries API 创建、更新和跟踪车辆及其相关任务。您的内部系统充当着 Fleet Engine Deliveries API 代表您增强的可信数据源。
同时,驱动程序应用会直接与 Fleet Engine 通信,以更新设备位置信息和路线信息。借助该模型,Fleet Engine 可以高效地管理实时位置信息,并将其直接发送到跟踪库,供需要订单状态更新的消费者使用。
例如,假设您遇到了以下情况:
- 司机靠近一个投递站,Fleet Engine 将设备位置信息发送到跟踪库,您的消费者应用会使用该跟踪库提醒消费者他们的包裹已接近。
- 司机完成发货后,点击司机应用中的“已发货”按钮。
- 这会将信息发送到您的后端系统,该后端系统会执行必要的业务验证和验证步骤。
- 您的系统确认任务已成功完成,并使用 Deliveries API 更新 Fleet Engine。
下图简要说明了这些流程。它还显示了系统、客户端和 Fleet Engine 之间的标准关系。
客户端令牌管理
源自驱动程序应用并直接发送到 Fleet Engine 的任何位置信息更新都需要授权令牌。处理从客户端到 Fleet Engine 的更新的建议方法是为驱动程序应用提供范围有限的令牌,使其只能更新 Fleet Engine 中的设备位置。对于此类令牌,您可以使用名为 Fleet Engine Delivery Untrusted Driver User 的服务帐号角色。这可确保来自移动设备(被视为低信任环境)的调用遵守最小权限原则。
其他服务帐号角色
如果您想授权驱动程序应用直接进行舰队引擎更新,而不局限于“不受信任的驱动程序”角色更新(例如,针对某些任务更新),则可以使用“可信驱动程序”角色。如需了解使用“可信驱动程序”角色的模型,请参阅“可信驱动程序”模型。
如需详细了解不受信任的和受信任的驱动程序角色的用途,请参阅 Cloud 项目设置。
对工作日进行建模
下表介绍了在配送和物流公司中,“第一公里”或“最后一公里”的司机在工作日可能会发生什么。您的公司可能在细节上有所不同,但您可以查看如何模拟工作日。
时间 | 活动记录 | 建模 |
---|---|---|
在当天开始后的 24 小时内 | 调度员将货物分配给送货车辆或路线。 | 您可以提前在 Fleet Engine 中创建送货、自提、休息等任务。例如,您可以创建送货自提任务、送货交货任务、预定不可用或计划停放。
一旦敲定了这组送货包裹以及这些包裹的递送顺序,就应该将任务分配给车辆。 |
当天开始时间 | 司机登录司机应用,在仓库开始一天的工作。 | 初始化 Delivery Driver API。根据需要在 Fleet Engine 中创建送货车辆。 |
司机将货物装入送货车辆,扫描货物。 | 如果未提前创建运单交付任务,请在扫描时创建运单交付任务。 | |
驾驶员确认要执行的任务的顺序。 | 如果未提前创建,请创建提货任务、计划不可用和计划停运时间。 | |
司机离开仓库,继续完成接下来要竞争的任务。 | 通过提交完成顺序来将所有任务或部分任务分配给车辆。 | |
司机负责送货。 | 到达配送站后,执行与到达停靠站的车辆相关的操作。 配送货物后,关闭配送任务,并视需要关闭商店配送状态和其他元信息。 在停靠站完成所有任务后开始前往下一个停靠站之前,请执行与车辆完成一个停靠站和前往下一个停靠点的车辆行驶相关的操作。 | |
司机遇到供给车辆,以便将其他货物转移到投递车辆上。 | 供给车辆和运载车辆之间的中转点应建模为预定停靠点。 转移并扫描运单后,创建送货任务(如果尚未创建)。然后通过将任务分配给车辆和更新任务顺序来更新任务完成顺序。 |
|
司机收到取车请求通知。 | 接受自提请求后,创建运单自提任务。然后通过将任务分配给车辆和更新任务顺序来更新任务执行顺序。 | |
中午 | 司机在午休了。 | 如果某个位置与不可用任务关联,请像对待其他任何任务一样对待该位置。执行与到达停靠站的车辆、车辆完成一个停靠站以及前往下一个停靠站的车辆相关的操作。
否则,在插播时间点结束之前,无需执行进一步操作。 通过确认下一个任务和剩余任务并更新任务排序,移除相应任务。 |
司机取货。 | 其建模方式类似于配送站。执行与抵达停靠点的车辆和关闭任务相关的操作,还可以选择存储运单状态和其他元信息。 在停靠站完成所有任务后,开始前往下一站之前,请执行与车辆完成停靠 和车辆前往下一站相关的操作。 注意:为了确保结算正确,所有自提都必须有相应的配送任务。如果当天将上车点送到司机的同一路线上的其他位置,我们建议您将该配送任务建模为路线上的任何其他配送任务。如果司机将上车点带回仓库,我们建议在仓库目的地创建配送任务。 | |
司机会安排经停点,从投递箱中取货。 | 它的建模方式与任何其他上车点一样。执行与车辆抵达停靠点和关闭任务相关的操作。在停靠点完成所有任务并开始开往下一站后,执行与车辆完成一个停靠站和前往下一个停靠站的车辆相关的操作。 | |
司机收到一条通知,告知正在将货物送往其他地点。 | 将原始送货任务状态设置为“已完成”,并为新的送货位置创建新的送货任务。如需了解详情,请参阅重新寄送运单。 | |
驾驶员尝试投递包裹,但未成功。 | 其建模类似于成功的传送停止,将传送任务标记为已完成。执行与车辆到达停靠站相关的操作。发货失败后,关闭任务,并(可选)商店运单状态和其他元信息。 在停靠站完成所有任务后,开始前往下一站之前,请执行与车辆完成停靠 和车辆前往下一站相关的操作。 | |
司机收到了延迟(不送达)货物的通知。 | 收到并确认通知后,将任务状态设置为“已完成”。 | |
司机收到了接下来要投递特定商品的通知,更改了承诺的交货订单。 | 更新任务顺序。 | |
司机选择按订单顺序投递商品。 | 更新任务排序,然后照常继续。 | |
司机将多件货物运送到一个地点。 | 其建模方式类似于单个配送站。到达停靠点后,执行与到达停靠点的车辆相关的操作。 每次发货后,关闭每项任务,并视需要关闭商店发货状态和其他元信息。在停靠站完成所有任务后,开始前往下一站之前,请执行与车辆完成停靠 和车辆前往下一站相关的操作。 | |
当天结束时间 | 司机回到仓库。 | 如果司机在途中取走了货物返回仓库时,您还必须将每个包裹作为配送任务进行创建和关闭,以确保结算正确。为此,您可以像对任何其他配送站一样,对仓库进行建模。 如果仓库未用作配送站,您仍然可以选择将仓库建模为预定停靠点。如此一来,司机就能看到返回仓库的路线,并能了解他们的预计到达时间。 |
了解位置信息更新
在运送车辆从停靠点出发(包括仓库)后,位置更新会发送到 Fleet Engine,直到抵达下一站。由于系统不会自动检测这些事件,因此您必须以编程方式进行标记。使用可检测交通方式变化的库来触发向 Fleet Engine 发送必要的通知。
当司机未驾车时,应暂停位置信息更新,因为当某人位于建筑物内时,位置信号的质量会急剧下降。
您可以在驱动程序 SDK 中设置位置信息更新频率。它默认每 10 秒发送一次更新。
车辆停靠点和送货地点
车辆停靠是指配送车辆完成装运任务或其他一些任务。它可能是加载基座等接入点,也可能是道路贴靠位置。
送货地点是指货物的运送或取货地点。往返送货地点可能需要一些步行时间从车辆停放点。
例如,当司机正在将货物运送到购物中心的商店时,送货车辆会在购物中心最近的入口附近的停车场停靠。这是车辆停靠站。然后,司机从车辆停靠站步行前往购物中心内商店所在的位置。这是投递地点。
为了让用户获得最佳运输跟踪体验,请考虑如何将配送任务分配给车辆停靠站,并注意,系统会向用户报告剩余车辆停靠站的数量,以帮助用户查看配送进度。
例如,如果司机向一个办公大楼进行许多送货,请考虑将所有送货任务分配给一个车辆停靠站。如果每个配送任务被分配给自己的车辆停靠站,那么货运跟踪体验对用户的帮助会大一些,因为只有在车辆在到达目的地之前车辆在有限数量的车辆停靠范围内时,才能提供跟踪功能。如果在短时间内完成多个车辆停靠点,用户将没有充足的时间来跟踪配送进度。
使用移动 SDK
在对驱动程序 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 对常见用例进行建模。
唯一实体标识符
REST 调用中使用的唯一实体标识符的格式和值对 Fleet Engine 是不透明的。避免使用自动递增的 ID,并确保该标识符不包含任何个人身份信息 (PII),例如驾驶员的电话号码。
创建车辆
您可以通过驱动程序 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> 是车队中配送车辆的唯一标识符。
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
POST 正文表示要创建的 DeliveryVehicle
实体。您可以指定以下可选字段:
- 属性
- 上一个位置
示例 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,Fleet Engine 会根据 API 指南忽略 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}"
创建提货任务
您可以通过驱动程序 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,您可以生成一个通用唯一标识符 (UUID)。
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 Task
实体:
必填字段:
字段 值 类型 类型.PICKUP 最后一个隐藏状态 状态.打开 trackingId 您用于跟踪货运的编号或标识符。 计划位置 需要完成任务的位置,在本例中为货运自提位置。 taskDuration 在自提地点提货的预计时间(以秒为单位)。 选填字段:
字段 值 目标时间窗口 应完成任务的时间范围。这目前不会影响路由行为。 属性 自定义 Task 属性列表。每个属性都必须具有唯一的键。
在创建时,系统会忽略实体中的所有其他字段。如果请求包含已分配的 deliveryVehicleId,Fleet Engine 会抛出异常。您可以使用 UpdateDeliveryVehicleRequests
分配任务。如需了解详情,请参阅向车辆分配任务。
示例 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
以下示例展示了如何使用 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,您可以生成一个通用唯一标识符 (UUID)。
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 Task
实体:
必填字段:
字段 值 类型 类型.投放 最后一个隐藏状态 状态.打开 trackingId 您用于跟踪货运的编号或标识符。 计划位置 需要完成任务的位置,在本例中为此项货物的投递位置。 taskDuration 将货物送到配送地点的预计时间(以秒为单位)。 选填字段:
字段 值 目标时间窗口 应完成任务的时间范围。这目前不会影响路由行为。 属性 自定义 Task 属性列表。每个属性都必须具有唯一的键。
在创建时,系统会忽略实体中的所有其他字段。如果请求包含已分配的 deliveryVehicleId,Fleet Engine 会抛出异常。您可以使用 UpdateDeliveryVehicleRequests
分配任务。如需了解详情,请参阅向车辆分配任务。
示例 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
请求相同的验证规则,但 parent
和 header
字段为选填字段除外。如果设置了此属性,它们必须与其在顶级 BatchCreateTasksRequest
中的相应字段完全相同。如需了解每种商品的具体验证规则,请参阅创建送货自提任务和创建送货配送任务。
如需了解详情,请参阅 BatchCreateTasks
的 API 参考文档(gRPC、REST)。
示例 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 或服务器环境创建指示无法提供服务的任务(例如,无法让驾驶员中断或车辆加油)。已排定的不可用任务不得包含跟踪 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,您可以生成一个通用唯一标识符 (UUID)。
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 Task
实体:
必填字段:
字段 值 类型 Type.UNAVAILABLE 最后一个隐藏状态 状态.打开 taskDuration 广告插播时长(以秒为单位)。 选填字段:
字段 值 计划位置 广告插播时间点(如果必须在特定位置截取)。
在创建时,系统会忽略实体中的所有其他字段。如果请求包含已分配的 deliveryVehicleId,Fleet Engine 会抛出异常。您可以使用 UpdateDeliveryVehicleRequests
分配任务。如需了解详情,请参阅向车辆分配任务。
示例 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 或服务器环境创建计划停止任务。计划停止任务不能包含跟踪 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,您可以生成一个通用唯一标识符 (UUID)。
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 Task
实体:
必填字段:
字段 值 类型 类型.SCHEDULED_STOP 最后一个隐藏状态 状态.打开 计划位置 车站的位置。 taskDuration 预计的停靠时间(以秒为单位)。 可选字段:
- 无
在创建时,系统会忽略实体中的所有其他字段。如果请求包含已分配的 deliveryVehicleId,Fleet Engine 会抛出异常。您可以使用 UpdateDeliveryVehicleRequests
分配任务。如需了解详情,请参阅向车辆分配任务。
示例 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> 是任务的唯一标识符。
请求标头必须包含值为 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> 是任务的唯一标识符。
请求标头必须包含值为 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> 是您要为其更新任务排序的配送车辆的唯一标识符。它是您在创建车辆时指定的标识符。
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 DeliveryVehicle
实体:
必填字段:
字段 值 剩余交通工具历程细分 按任务执行顺序排列的任务历程细分列表。列表中的第一个任务将首先执行。 剩余交通工具历程细分 [i].stop 列表中任务 i 的停止点。 剩余交通工具历程细分 [i].stop.plannedLocation 计划的经停点。 剩余交通工具历程细分 [i].stop.tasks 要在该车辆停靠站执行的任务列表。 剩余交通工具历程细分 [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 必须收到通知。您可以通过 驱动程序 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
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> 是您要为其更新任务排序的配送车辆的唯一标识符。它是您在创建车辆时指定的标识符。
请求标头必须包含值为 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 必须在车辆抵达停靠点时收到通知。您可以通过 驱动程序 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> 是您要为其更新任务排序的配送车辆的唯一标识符。它是您在创建车辆时指定的标识符。
请求标头必须包含值为 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 必须在车辆完成一次停车时收到通知。这会导致与停止点关联的所有任务都设置为“已关闭”。您可以通过 驱动程序 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> 是您要为其更新任务排序的配送车辆的唯一标识符。它是您在创建车辆时指定的标识符。
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 DeliveryVehicle
实体:
必填字段:
字段 值 剩余车辆出行路段 已完成的停靠点应该不会再出现在剩余车辆停靠点列表中。 可选字段:
- 无
更新会忽略实体中的所有其他字段。
示例 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}",
"taskDuration": "120s"
}
]
}
}
]
}
EOM
更新任务
大多数任务字段是不可变的。但是,可以通过直接更新任务实体来修改状态、任务结果、任务结果时间、任务结果位置和属性。例如,如果任务尚未分配给车辆,可以通过直接更新状态来关闭任务。
gRPC
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
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 Task
实体:
必填字段:
字段 值 最后一个隐藏状态 状态.CLOSED 选填字段:
字段 值 任务结果 Outcome.SUCCEEDED 或 Outcome.FAILED 任务结果时间 任务完成的时间。 任务结果位置 完成任务的位置。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 仅对状态为“SUCCEEDED”(成功)的传送任务收费。
标记任务结果时,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
请求标头必须包含值为 Bearer <token> 的字段 Authorization,其中 <token> 是由 Fleet Engine 令牌工厂生成的令牌。
请求正文必须包含 Task
实体:
必填字段:
字段 值 任务结果 Outcome.SUCCEEDED 或 Outcome.FAILED 任务结果时间 设置任务结果时的时间戳(来自提供程序)。这是任务完成的时间。 选填字段:
字段 值 任务结果位置 完成任务的位置。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 用作外部表中的键。
如需了解详情,请参阅任务的生命周期。
查找车辆
您可以通过驾驶 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> 是任务的唯一标识符。
<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> 是任务的唯一标识符。
<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 查找信息,您可以使用以下任一方法:
查询要求
跟踪 ID 提供的运单信息遵循控制所跟踪位置的可见性中所述的可见性规则。
使用 Fleet Engine 按跟踪 ID 查找运单信息。驱动程序 SDK 不支持按跟踪 ID 查找信息。如需使用 Fleet Engine 执行此操作,您需要使用服务器或浏览器环境。
使用尽可能窄的令牌以限制安全风险。例如,如果您使用交付消费者令牌,则任何 Fleet Engine Deliveries API 调用都仅返回与该最终用户相关的信息,例如货物的发货人或接收方。响应中的所有其他信息都会被隐去。 如需详细了解令牌,请参阅创建用于授权的 JSON Web 令牌 (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 超级用户身份验证令牌。
列出的任务会隐去以下字段:
- VehicleStop.planned_location
- VehicleStop.state
- VehicleStop.TaskInfo.taskId
列出的任务可以按大多数任务属性进行过滤。如需了解过滤条件查询语法,请参阅 AIP-160。以下列表显示了可用于过滤的有效任务属性:
- 属性
- delivery_vehicle_id [送货车辆 ID]
- 最后一个隐藏状态
- 计划位置
- task_duration
- 任务结果
- task_outcome_location
- task_outcome_location_source
- task_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.latitude 和point.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
若要对列出的任务应用过滤条件,请添加“filter”网址参数,并将网址转义过滤条件查询作为其值。
请求标头必须包含值为 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}"
列出送货车辆
您可以在服务器或浏览器环境中列出送货车辆。Driver SDK 不支持列出送货车辆。
列出送货车辆会请求对送货车辆的广泛访问权限,并且仅适用于受信任的用户。发出列表传送车辆请求时,使用传送舰队读取器或传送超级用户身份验证令牌。
列出的送货车辆具有以下字段,因为它们会对响应大小产生影响,所以隐去了以下字段:
- 当前路线段
- 其余交通工具历程细分
您可以按 attributes
属性过滤送货车辆列表。例如,如需查询键为 my_key
且值为 my_value
的属性,请使用 attributes.my_key = my_value
。如需查询多个属性,请使用逻辑 AND
和 OR
运算符联接查询,如 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
如需对列出的任务应用过滤条件,请添加一个“filter”网址参数,并将网址转义过滤条件查询作为其值。
请求标头必须包含值为 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 连接的数据组件。这样,您就可以通过 Web 应用或移动应用提供可自定义的动画舰队跟踪体验。
在 Fleet Engine Deliveries API 上实现您自己的车队跟踪功能。
日志记录
您可以启用一个选项,以允许 Fleet Engine 将 RPC 日志发送到 Cloud Logging。如需了解详情,请参阅 Logging。
授权角色和令牌
如 集成 Deliveries API 部分以及各个用例的授权说明中所述,调用 Fleet Engine 需要使用已使用服务帐号凭据签名的 JSON Web 令牌进行身份验证。用于创建这些令牌的服务帐号可能具有一个或多个角色,其中每个角色授予一组不同的权限。
如需了解详情,请参阅身份验证和授权。
问题排查
弹性
Fleet Engine 不被视为可信来源。如有必要,您负责恢复系统的状态,而不依赖于 Fleet Engine。
Fleet Engine 中的状态丢失
使用 Fleet Engine 时,请实现客户端,以便系统在发生故障时自行修复。例如,当 Fleet Engine 尝试更新车辆时,它可能会返回一条错误,指明车辆不存在。然后,客户端应以新状态重新创建车辆。这种情况很少发生,系统必须具备弹性,以防出现这种情况。
在极少数情况下,Fleet Engine 发生灾难性故障,您可能需要重新创建大多数或所有车辆和任务。如果创建速率变得过高,则由于配额问题,某些请求可能会再次失败,因为系统会执行配额检查来避免拒绝服务 (DOS) 攻击。在这种情况下,使用退避策略来重试,降低重新创建速度。
驾驶员应用中的状态丢失
如果驱动程序应用崩溃,必须在驱动程序 SDK 中重新创建当前状态。应用应尝试重新创建任务,以确保任务存在并恢复其当前状态。此外,应用还应为 Driver SDK 重新创建并明确设置车站列表。
请注意,这些恢复必须自主完成,无需依赖 Fleet Engine 中的信息,除非出现错误,指示实体是否以及何时存在于数据库中。如果某个实体已存在,则可以消除该错误,并使用其 ID 更新该实体。
FAQ
如果司机不按顺序地停下来完成某项任务,该怎么办?
在这种情况下,您应该首先更新任务的顺序,然后照常执行,标记到达车站、任务完成等。否则,系统可能会不一致。预计到达时间可能会不正确,并且系统可能会报告意外错误。