The Fleet Engine On-demand Rides and Deliveries API lets you manage trips and vehicle state for your Trip and Order Progress applications. It handles transactions between the Driver SDK, the Consumer SDK, and your backend service -- which can communicate with the Fleet Engine by making either gRPC or REST calls.
Prerequisites
For development, ensure that you install the Cloud SDK (gcloud) and are authenticated to your project.
shell
gcloud auth login
You should see a success message such as:
You are now logged in as [my-user@example.com].
Your current project is [project-id]. You ...
Check that On-demand Rides and Deliveries Solution Fleet Engine APIs are configured appropriately.
shell
gcloud --project=project-id services enable fleetengine.googleapis.com
If this command results in an error, check with your project administrator and your Google support representative to get access.
Logging
The Fleet Engine can write log messages about API calls it receives into Google Cloud platform logs. See Cloud Logging documentation for an overview of how to read and analyze logs.
Logging might not be enabled by default for projects created prior to Feb 10, 2022. See the logging documentation for more details.
Client Libraries
We publish client libraries in several common programming languages. These libraries will help provide a better developer experience over raw REST or gRPC. For instructions on how to obtain client libraries for your server application, see Client Libraries.
The Java examples in this documentation assume familiarity with gRPC.
Authentication and Authorization
You can configure capabilities provided by Trip and Order Progress through the Google Cloud Console. These APIs and SDKs require the use of JSON Web Tokens that have been signed using service accounts created from Cloud Console.
Cloud project setup
To set up your cloud project, first create your project and then create service accounts.
To create your Google Cloud project:
- Create a Google Cloud Project using the Google Cloud Console.
- Using the APIs and Services Dashboard, enable the Local Rides and Deliveries API.
Service accounts are associated with one or more roles. They are used to create JSON Web Tokens that grant different sets of permissions depending on the roles. Typically, to reduce the possibility of abuse you can create multiple service accounts, each with the minimum set of roles required.
Trip and Order Progress uses the following roles:
Role | Description |
---|---|
Fleet Engine Consumer SDK User
roles/fleetengine.consumerSdkUser |
Grants permission to search for vehicles and to retrieve information about vehicles and trips. Tokens created by a service account with this role are typically used from your ridesharing or delivery consumer app mobile devices. |
Fleet Engine Driver SDK User
roles/fleetengine.driverSdkUser |
Grants permission to update vehicle locations and routes and to retrieve information about vehicles and trips. Tokens created by a service account with this role are typically used from your ridesharing or delivery driver app mobile devices. |
Fleet Engine Service Super User
roles/fleetengine.serviceSuperUser |
Grants permission to all vehicles and trips APIs. Tokens created by a service account with this role are typically used from your backend servers. |
For example, create a service account for each of the three roles and assign them their respective roles.
gcloud --project=project-id iam service-accounts create fleet-engine-consumer-sdk gcloud projects add-iam-policy-binding project-id \ --member=serviceAccount:fleet-engine-consumer-sdk@project-id.iam.gserviceaccount.com \ --role=roles/fleetengine.consumerSdkUser gcloud --project=project-id iam service-accounts create fleet-engine-driver-sdk gcloud projects add-iam-policy-binding project-id \ --member=serviceAccount:fleet-engine-driver-sdk@project-id.iam.gserviceaccount.com \ --role=roles/fleetengine.driverSdkUser gcloud --project=project-id iam service-accounts create fleet-engine-su gcloud projects add-iam-policy-binding project-id \ --member=serviceAccount:fleet-engine-su@project-id.iam.gserviceaccount.com \ --role=roles/fleetengine.serviceSuperUser
The Driver and Consumer SDKs are built around these standard roles.
Alternatively, it is possible to create custom roles which allow an arbitrary set of permissions to be bundled together. The Driver and Consumer SDKs will show error messages whenever a required permission is missing. As a result, we strongly recommend using the standard set of roles presented above and not using custom roles.
For convenience, if you need to create JWT tokens for untrusted clients, adding users to the Service Account Token Creator Role lets them create tokens with gcloud command line tools.
gcloud projects add-iam-policy-binding project-id \
--member=user:my-user@example.com \
--role=roles/iam.serviceAccountTokenCreator
Where my-user@example.com
is the email used to
authenticate with gcloud (gcloud auth list
--format='value(account)'
).
Fleet Engine Auth Library
Fleet Engine uses JSON Web Tokens (JWTs) to restrict access to Fleet Engine APIs. The new Fleet Engine Auth Library, available on Github, simplifies construction of Fleet Engine JWTs and securely signs them.
The library provides the following benefits:
- Simplifies the process of creating Fleet Engine Tokens.
- Provides token signing mechanisms other than using credential files (such as impersonating a service account.)
- Attaches signed tokens to outbound requests made from either a gRPC stub or GAPIC client.
Creating a JSON Web Token (JWT) for authorization
When not using the Fleet Engine Auth Library, JSON Web Tokens (JWTs) need to be crafted directly within your codebase. This requires you to have both a deep understanding of JWTs and how they relate to Fleet Engine. This is why we HIGHLY recommend taking advantage of the Fleet Engine Auth Library.
Within Fleet Engine, JSON Web Tokens (JWTs) provide short-lived authentication and ensure that devices may only modify vehicles, trips, or tasks for which they are authorized. JWTs contain a header and a claim section. The header section contains information such as the private key to use (obtained from service accounts) and the encryption algorithm. The claim section contains information such as the token's create time, tokens time to live, services that it is claiming access to, and other authorization information to scope down access; for example, the vehicle ID.
A JWT header section contains the following fields:
Field | Description |
---|---|
alg | The algorithm to use. `RS256`. |
typ | The type of token. `JWT`. |
kid | Your service account's private key ID. You can find this value in the `private_key_id` field of your service account JSON file. Make sure to use a key from a service account with the correct level of permissions. |
A JWT claims section contains the following fields:
Field | Description |
---|---|
iss | Your service account's email address. |
sub | Your service account's email address. |
aud | Your service account's SERVICE_NAME, in this case https://fleetengine.googleapis.com/ |
iat | The timestamp when the token was created, specified in seconds elapsed since 00:00:00 UTC, January 1, 1970. Allow 10 minutes for skew. If the timestamp is too far in the past, or in the future, the server might report an error. |
exp | The timestamp when the token expires, specified in seconds elapsed since 00:00:00 UTC, January 1, 1970. The request fails if the timestamp is more than one hour in the future. |
authorization | Depending on the use case, may contain `vehicleid` or `tripid`. |
Creating a JWT token refers to signing it. For instructions and code samples for creating and signing the JWT, see Service account authorization without OAuth. You can then attach a signed token to gRPC calls or other methods used to access Fleet Engine.
JWT Claims
When creating the JWT payload, add an additional claim in the authorization
section with the key vehicleid
or tripid
set to the value of the
vehicle ID or trip ID for which the call is being made.
The Driver SDK always uses the vehicleid
claim, whether operating on
a trip or vehicle. The Fleet Engine backend assures that the vehicle
is associated with the requested trip before doing the modification.
The Consumer SDK always uses tripid
claim.
The Rideshare or Delivery Provider should use the vehicleid
or tripid
with a "*" to
match all Vehicles and Trips. Note that the JWT can contain both tokens,
even if not required, which may simplify the token signing implementation.
JWT Use Cases
The following shows an example token for Provider server:
{
"alg": "RS256",
"typ": "JWT",
"kid": "private_key_id_of_provider_service_account"
}
.
{
"iss": "provider@yourgcpproject.iam.gserviceaccount.com",
"sub": "provider@yourgcpproject.iam.gserviceaccount.com",
"aud": "https://fleetengine.googleapis.com/",
"iat": 1511900000,
"exp": 1511903600,
"authorization": {
"vehicleid": "*",
"tripid": "*"
}
}
The following shows an example token for Consumer app:
{
"alg": "RS256",
"typ": "JWT",
"kid": "private_key_id_of_consumer_service_account"
}
.
{
"iss": "consumer@yourgcpproject.iam.gserviceaccount.com",
"sub": "consumer@yourgcpproject.iam.gserviceaccount.com",
"aud": "https://fleetengine.googleapis.com/",
"iat": 1511900000,
"exp": 1511903600,
"authorization": {
"tripid": "trip_54321"
}
}
The following shows an example token for Driver app:
{
"alg": "RS256",
"typ": "JWT",
"kid": "private_key_id_of_driver_service_account"
}
.
{
"iss": "driver@yourgcpproject.iam.gserviceaccount.com",
"sub": "driver@yourgcpproject.iam.gserviceaccount.com",
"aud": "https://fleetengine.googleapis.com/",
"iat": 1511900000,
"exp": 1511903600,
"authorization": {
"vehicleid": "driver_12345"
}
}
- For the
kid
field in the header, specify your service account's private key ID. You can find this value in theprivate_key_id
field of your service account JSON file. - For the
iss
andsub
fields, specify your service account's email address. You can find this value in theclient_email
field of your service account JSON file. - For the
aud
field, specify https://SERVICE_NAME/. - For the
iat
field, use the timestamp when the token was created, specified as seconds elapsed since 00:00:00 UTC, January 1, 1970. Allow 10 minutes for skew. If the timestamp is too far in the past, or in the future, the server might report an error. - For the
exp
field, use the timestamp when the token expires, specified as seconds since 00:00:00 UTC, January 1, 1970. The maximum allowed value isiat
+ 3600.
When signing the JWT to be passed to a mobile device, make sure to use the service account for the Driver or Consumer SDK role. Otherwise, the mobile device will have the ability to alter state it should not have.
Likewise, when signing the JWT to be used for privileged calls, make sure to use the service account with the Super User role. Otherwise, the operation will fail.
Generating a JWT for testing
Generating tokens from the terminal can be helpful when testing.
In order to follow these steps, your user account must have the Service Account Token Creator role:
gcloud projects add-iam-policy-binding project-id \
--member=user:my-user@example.com \
--role=roles/iam.serviceAccountTokenCreator
Create a new file called unsigned_token.json
with the content below. The iat
property is the current time in number of seconds after the epoch, which can be
retrieved by running date +%s
in your terminal. The exp
property is the
expiration time in number of seconds after the epoch, which can be calculated by
adding 3600 to iat
. The expiration time cannot be more than one hour in the
future.
{ "aud": "https://fleetengine.googleapis.com/", "iss": "super-user-service-account@project-id.iam.gserviceaccount.com", "sub": "super-user-service-account@project-id.iam.gserviceaccount.com", "iat": iat, "exp": exp, "authorization": { "vehicleid": "*", "tripid": "*" } }
Then run the following gcloud command to sign the token on behalf of your Super User service account:
gcloud beta iam service-accounts sign-jwt --iam-account=super-user-service-account@project-id.iam.gserviceaccount.com unsigned_token.json signed_token.jwt
A signed Base64-encoded JWT should now be stored within the file
signed_token.jwt
. The token is valid for the next hour.
You can now test the token by running a curl
command against the List Vehicles
REST endpoint:
curl -X GET "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles" -H "Authorization: Bearer $(cat signed_token.jwt)"
Vehicles and their lifecycle
The Vehicle is the entity representing a driver-vehicle pair. Currently, a Driver and Vehicle cannot be tracked separately. The Rideshare or Delivery Provider creates a Vehicle using a Provider ID (which must be the same as the Project ID of the Google Cloud Project which contains the service account used to call the Fleet Engine APIs) and a Rideshare or Delivery Provider-owned Vehicle ID.
A Vehicle which has not been updated via UpdateVehicle
after seven days will
be automatically deleted. It is an Error to call CreateVehicle
with a
Provider ID/Vehicle ID pair that already exists. The case of vehicles that
are not updated frequently can be dealt with in two ways: frequently calling
CreateVehicle
with an expected Provider ID/Vehicle ID pair and discarding
the error if the Vehicle already exists; or, calling CreateVehicle
after an
UpdateVehicle
returns with a NOT_FOUND
error.
Vehicle types
The Vehicle entity contains a required field of VehicleType
, which contains a
Category
enum that can be specified as either AUTO
, TAXI
, TRUCK
,
TWO_WHEELER
, BICYCLE
, or PEDESTRIAN
. The vehicle type can serve as a
filter criteria in SearchVehicles
and ListVehicles
.
All routing for vehicles will use the corresponding RouteTravelMode
if the
category is set to either AUTO
, TWO_WHEELER
, BICYCLE
, or PEDESTRIAN
.
If the category is set to TAXI
or TRUCK
, the routing is treated the same as
the AUTO
mode.
Vehicle attributes
The Vehicle entity contains a repeated field of VehicleAttribute
. These
attributes are not interpreted by the Fleet Engine. The SearchVehicles
API includes a field to require that matched Vehicles
must contain all
the included attributes set to the specified value.
Note that the attribute field is in addition to several other supported fields
in the Vehicle
message, such as vehicle_type
and supported_trip_types
.
Vehicle remaining waypoints
The Vehicle entity contains a repeated field of TripWaypoint
(RPC | REST),
called waypoints
(RPC | REST).
This field includes the remaining waypoints in the trips, in the order that
the vehicle reaches them. Fleet Engine computes this field as trips are
assigned to the vehicle, and updates it as trips change their status.
These waypoints can be identified by TripId
field and WaypointType
field.
Expanding a vehicle's eligibility for matches
Typically, the services of Rideshare or Delivery Provider are responsible for matching trip
requests to vehicles. The service can use the vehicle attributes to include a
vehicle in a larger number of searches. For example, the provider can implement
a set to attributes corresponding to levels of perks or capabilities provided by
a vehicle. For example, three levels could be a set of attributes with boolean
values: is_bronze_level
, is_silver_level
, and is_gold_level
. A vehicle
can be eligible for all three. When the Fleet Engine receives a request for a
trip that requires silver level capabilities, the search includes that vehicle.
Using attributes this way includes vehicles that are offering a variety of
capabilities.
There are two ways to update vehicle attributes. One is the UpdateVehicle
API. When using this API, the entire set of Vehicle Attributes is
set to the value. It's not possible to just update a single attribute.
The other method is the UpdateVehicleAttributes
API. This method takes just
the attributes to be updated. Attributes included in the request will be
set to the new value or added; unspecified attributes will not be altered.
HOW-TO: Create a Vehicle
A Vehicle
entity must be created for each Vehicle to be tracked in the fleet.
Use the CreateVehicle
endpoint with the CreateVehicleRequest
to create a
Vehicle.
The provider_id
of the Vehicle
must be the Project ID
(e.g. my-on-demand-project) of the Google Cloud Project that contains the
Service Accounts that will be used to call the Fleet Engine. Note that while
multiple service accounts may access the Fleet Engine for the same Rideshare
or Delivery Provider, the Fleet Engine does not currently support service accounts from
multiple Google Cloud Projects accessing the same Vehicles
.
The Vehicle
can be created in the OFFLINE
or ONLINE
state. If
created ONLINE
it may be immediately returned in response to SearchVehicles
queries.
An initial last_location
may be included in the CreateVehicle
call.
While permitted, a Vehicle
should not be created in the ONLINE
state without
a last_location
.
See the Vehicle Types for details on the vehicle type field.
See the Vehicle Attributes for details on the attributes field.
The value returned from CreateVehicle
is the created Vehicle
entity.
Example
shell
curl -X POST \
"https://fleetengine.googleapis.com/v1/providers/project-id/vehicles?vehicleId=vid-8241890" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
--data-binary @- << EOM
{
"vehicleState": "OFFLINE",
"supportedTripTypes": ["EXCLUSIVE"],
"maximumCapacity": 4,
"vehicleType": {"category": "AUTO"},
"attributes": [{"key": "on_trip", "value": "false"}]
}
EOM
See providers.vehicles.create reference.
Java
static final String PROJECT_ID = "project-id";
VehicleServiceBlockingStub vehicleService =
VehicleService.newBlockingStub(channel);
String parent = "providers/" + PROJECT_ID;
Vehicle vehicle = Vehicle.newBuilder()
.setVehicleState(VehicleState.OFFLINE) // Initial state
.addSupportedTripTypes(TripType.EXCLUSIVE)
.setMaximumCapacity(4)
.setVehicleType(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
.addAttributes(VehicleAttribute.newBuilder()
.setKey("on_trip").setValue("false")) // Opaque to the Fleet Engine
// Add .setBackToBackEnabled(true) to make this vehicle eligible for trip
// matching while even if it is on a trip. By default this is disabled.
.build();
CreateVehicleRequest createVehicleRequest =
CreateVehicleRequest.newBuilder() // no need for the header
.setParent(parent)
.setVehicleId("vid-8241890") // Vehicle ID assigned by Rideshare or Delivery Provider
.setVehicle(vehicle) // Initial state
.build();
// In this case, the Vehicle is being created in the OFFLINE state and
// no initial position is being provided. When the Driver App checks
// in with the Rideshare or Delivery Provider, the state can be set to ONLINE and
// the Driver App will update the Vehicle Location.
try {
Vehicle createdVehicle =
vehicleService.createVehicle(createVehicleRequest);
} catch (StatusRuntimeException e) {
Status s = e.getStatus();
switch (s.getCode()) {
case ALREADY_EXISTS:
break;
case PERMISSION_DENIED:
break;
}
return;
}
// If no Exception, Vehicle created successfully.
Google Cloud platform logs for Vehicle creation
The Fleet Engine API writes a log entry via Google Cloud platform logs when a
call to the CreateVehicle
endpoint is received. The log entry includes
information about the values in the CreateVehicle
request. If the call
succeeds, it will also include information about the Vehicle
that was
returned.
shell
gcloud --project=project-id logging read --freshness=1h '
jsonPayload.request.vehicleId="vid-8241890"
jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.CreateVehicleLog"
'
Should print a record similar to the following:
---
insertId: c2cf4d3a180251c1bdb892137c14f022
jsonPayload:
'@type': type.googleapis.com/maps.fleetengine.v1.CreateVehicleLog
request:
vehicle:
attributes:
- key: on_trip
value: 'false'
maximumCapacity: 4
state: VEHICLE_STATE_OFFLINE
supportedTrips:
- EXCLUSIVE_TRIP
vehicleType:
vehicleCategory: AUTO
vehicleId: vid-8241890
response:
attributes:
- key: on_trip
value: 'false'
availableCapacity: 4
currentRouteSegmentHandle: AdSiwAwCO9gZ7Pw5UZZimOXOo41cJTjg/r3SuwVPQmuuaV0sU3+3UCY+z53Cl9i6mWHLoCKbBt9Vsj5PMRgOJ8zX
maximumCapacity: 4
name: providers/project-id/vehicles/vid-8241890
state: VEHICLE_STATE_OFFLINE
supportedTrips:
- EXCLUSIVE_TRIP
vehicleType:
vehicleCategory: AUTO
labels:
vehicle_id: vid-8241890
logName: projects/project-id/logs/fleetengine.googleapis.com%2Fcreate_vehicle
receiveTimestamp: '2021-09-22T03:25:16.361159871Z'
resource:
labels:
location: global
resource_container: projects/project-id
type: fleetengine.googleapis.com/Fleet
timestamp: '2021-09-22T03:25:15.724998Z'
Cloud Pub/Sub notifications for Vehicle creation
The Fleet Engine API publishes a notification via Cloud Pub/Sub when a new vehicle is created. In order to receive these notifications, please follow the instructions here.
HOW-TO: Update a Vehicle
UpdateVehicle
is used to update the state of a Vehicle
. Updates fall into
two categories.
Updating Vehicle position
The Driver SDK updates the Vehicle's last_location
frequently. These updates
require only Fleet Engine Driver SDK User privileges. The Fleet Engine
optimizes updates to vehicle position.
Update other Vehicle state
Updates to other attributes of the Vehicle state occur less frequently than
position updates. Updates to attributes other than last_location
require
Fleet Engine Super User privileges.
The UpdateVehicleRequest
includes an update_mask
to indicate which fields to
update. The behavior of the field is as in the Protobuf documentation for
field masks.
As noted in Vehicle Attributes, updating the
attributes
field requires writing all of the attributes to be preserved. It
is not possible to just update the value of one key-value pair in an
UpdateVehicle
call. To update values of specific attributes, the
UpdateVehicleAttributes
API can be used.
Example
This example enables back_to_back
.
shell
curl -X PUT \
"https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=vehicle_state,attributes,back_to_back_enabled" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
--data-binary @- << EOM
{
"vehicleState": "ONLINE",
"attributes": [
{"key": "on_trip", "value": "true"},
{"key": "cash_only", "value": "false"}
],
"backToBackEnabled": true
}
EOM
See providers.vehicles.update reference.
Java
static final String PROJECT_ID = "project-id";
static final String VEHICLE_ID = "vid-8241890";
VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);
String vehicleName = "providers/" + PROJECT_ID + "/vehicles/" + VEHICLE_ID;
Vehicle updatedVehicle = Vehicle.newBuilder()
.setVehicleState(VehicleState.ONLINE)
.addAllAttributes(ImmutableList.of(
VehicleAttribute.newBuilder().setKey("on_trip").setValue("true").build(),
VehicleAttribute.newBuilder().setKey("cash_only").setValue("false").build()))
.setBackToBackEnabled(true)
.build();
UpdateVehicleRequest updateVehicleRequest = UpdateVehicleRequest.newBuilder()
.setName(vehicleName)
.setVehicle(updatedVehicle)
.setUpdateMask(FieldMask.newBuilder()
.addPaths("vehicle_state")
.addPaths("attributes")
.addPaths("back_to_back_enabled"))
.build();
// Attributes and vehicle state are being updated, so both are
// included in the field mask. Note that of on_trip were
// not being updated, but rather cash_only was being changed,
// the desired value of "on_trip" would still need to be written
// as the attributes are completely replaced in an update operation.
try {
Vehicle updatedVehicle =
vehicleService.updateVehicle(updateVehicleRequest);
} catch (StatusRuntimeException e) {
Status s = e.getStatus();
switch (s.getCode()) {
case NOT_FOUND:
// Most implementations will call CreateVehicle in this case
break;
case PERMISSION_DENIED:
break;
}
return;
}
// If no Exception, Vehicle updated successfully.
Google Cloud platform logs for Vehicle Updates
The Fleet Engine API writes a log entry via Google Cloud platform logs when a
call to the UpdateVehicle
endpoint is received. The log entry includes
information about the values in the UpdateVehicle
request. If the call
succeeds, it will also include information about the Vehicle
that was
returned.
shell
gcloud --project=project-id logging read --freshness=1h '
jsonPayload.request.vehicleId="vid-8241890"
jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.UpdateVehicleLog"
'
Cloud Pub/Sub notifications for Vehicle updates
The Fleet Engine API publishes a notification via Cloud Pub/Sub when an existing vehicle is updated. In order to receive these notifications, please follow the instructions here.
HOW-TO: Search vehicles
The Fleet Engine supports searching for vehicles. The SearchVehicles
API lets you find available nearby drivers who are best suited to a task such as
servicing a ride or a delivery request. The SearchVehicles
API returns a
ranked list of drivers matching task attributes with attributes of vehicles in
your fleet. For more information, see
Finding nearby drivers.
Example
When searching for available vehicles, the Fleet Engine excludes vehicles on active trips by default. The services of the Rideshare or Delivery Provider need to explicitly include them in search requests. The following example shows how to include those vehicles in a search for vehicles matching a trip from the Grand Indonesia East Mall to the Balai Sidang Jakarta Convention Center.
shell
First update the location of the vehicle we created in prior steps so that it is eligible. In the real world, this would be done by the Driver SDK running on an Android or iOS device in the vehicle.
curl -X PUT \
"https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=last_location,attributes" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
--data-binary @- << EOM
{
"lastLocation": {
"updateTime": "$( date -u +"%Y-%m-%dT%H:%M:%SZ" )",
"location": {
"latitude": "-6.195139",
"longitude": "106.820826"
}
},
"attributes": [{"key": "on_trip", "value": "false"}]
}
EOM
Performing the search should yield at least that vehicle.
curl -X POST \
"https://fleetengine.googleapis.com/v1/providers/project-id/vehicles:search" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
--data-binary @- << EOM
{
"pickupPoint": {
"point": {"latitude": "-6.195139", "longitude": "106.820826"}
},
"dropoffPoint": {
"point": {"latitude": "-6.1275", "longitude": "106.6537"}
},
"pickupRadiusMeters": 2000,
"count": 10,
"minimumCapacity": 2,
"tripTypes": ["EXCLUSIVE"],
"vehicleTypes": [{"category": "AUTO"}],
"filter": "attributes.on_trip=\"false\"",
"orderBy": "PICKUP_POINT_ETA",
"includeBackToBack": true
}
EOM
See providers.vehicles.search reference.
Java
static final String PROJECT_ID = "project-id";
VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);
String parent = "providers/" + PROJECT_ID;
SearchVehiclesRequest searchVehiclesRequest = SearchVehiclesRequest.newBuilder()
.setParent(parent)
.setPickupPoint( // Grand Indonesia East Mall
TerminalLocation.newBuilder().setPoint(
LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
.setDropoffPoint( // Balai Sidang Jakarta Convention Center
TerminalLocation.newBuilder().setPoint(
LatLng.newBuilder().setLatitude(-6.213796).setLongitude(106.807195)))
.setPickupRadiusMeters(2000)
.setCount(10)
.setMinimumCapacity(2)
.addTripTypes(TripType.EXCLUSIVE)
.addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
.setFilter("attributes.on_trip=\"false\"")
.setOrderBy(VehicleMatchOrder.PICKUP_POINT_ETA)
.setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
.build();
// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully
try {
SearchVehiclesResponse searchVehiclesResponse =
vehicleService.searchVehicles(searchVehiclesRequest);
// Search results: Each vehicle match contains a vehicle entity and information
// about the distance and ETA to the pickup point and dropoff point.
List<VehicleMatch> vehicleMatches = searchVehiclesResponse.getMatchesList();
} catch (StatusRuntimeException e) {
Status s = e.getStatus();
switch (s.getCode()) {
case NOT_FOUND:
break;
case PERMISSION_DENIED:
break;
}
return;
}
Vehicle filtering query
SearchVehicles
and ListVehicles
support filtering on vehicle attributes
using a filter query. For filter query syntax, see
AIP-160 for examples.
Note that filter queries ONLY support filtering on vehicle attributes, and
cannot be used for other fields. The filter query functions as an AND
clause
with other constraints, such as minimum_capacity
or vehicle_types
in
SearchVehiclesRequest
.
HOW-TO: List vehicles
SearchVehicles
is optimized for finding a small number of vehicles in ranked
order very quickly and is mainly used to find nearby drivers who are best suited
to a task. However, sometimes you want to find all vehicles that meet some
criteria even if paging through the results is necessary. ListVehicles
is
designed for that use case.
The ListVehicles
API lets you find all vehicles that satisfy some specific
request options. The ListVehicles
API returns a paginated list of vehicles in
the project that matches some requirements.
To filter on vehicle attributes, please refer to Vehicle filtering query.
Example
This example performs filtering on vehicle_type
and attributes using the
filter
string.
shell
curl -X POST \
"https://fleetengine.googleapis.com/v1/providers/project-id/vehicles:list" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
--data-binary @- << EOM
{
"vehicleTypes": [{"category": "AUTO"}],
"filter": "attributes.on_trip=\"false\"",
}
EOM
See providers.vehicles.list reference.
Java
static final String PROJECT_ID = "project-id";
VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);
String parent = "providers/" + PROJECT_ID;
ListVehiclesRequest listVehiclesRequest = ListVehiclesRequest.newBuilder()
.setParent(parent)
.addTripTypes(TripType.EXCLUSIVE)
.addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
.setFilter("attributes.on_trip=\"false\"")
.setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
.build();
// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully
try {
ListVehiclesResponse listVehiclesResponse =
vehicleService.listVehicles(listVehiclesRequest);
} catch (StatusRuntimeException e) {
Status s = e.getStatus();
switch (s.getCode()) {
case NOT_FOUND:
break;
case PERMISSION_DENIED:
break;
}
return;
}
Trips and their lifecycle
The Trip API and lifecycle are similar to the Vehicle API and lifecycle.
The Rideshare Provider is responsible for creating trips using the Fleet Engine
interfaces. The Fleet Engine provides both an RPC service,
TripService
, and REST resources, provider.trips
. These interfaces enable Trip entity creation, information requests, search
functionality, and update capability.
A Trip
has a status field to track its progression through the lifecycle.
The values move from NEW
to COMPLETE
plus CANCELED
and UNKNOWN_TRIP_STATUS
. Refer to trip_status
for RPC
or TripStatus for REST.
NEW
ENROUTE_TO_PICKUP
ARRIVED_AT_PICKUP
ENROUTE_TO_INTERMEDIATE_DESTINATION
ARRIVED_AT_INTERMEDIATE_DESTINATION
ENROUTE_TO_DROPOFF
COMPLETE
Your service can update the trip to CANCELED
from any of these statuses.
When your service creates a trip, the engine sets the status as NEW
. A
vehicle_id
is optional. As with vehicles, the services delete trips automatically
after seven days without an update. If your service attempts to create a trip with an
ID that already exists, an error is returned. A trip is considered ‘active’ if
it is in a status other than COMPLETE
or CANCELED
. This distinction is
important in the active_trips
field in the Vehicle entity and SearchTripsRequest
.
The service can only change the vehicle_id
assigned to a Trip when the
status is NEW
or CANCELED
. If a Driver cancels a Trip while en route,
the Trip status must be set to NEW
or CANCELED
before the vehicle_id
is changed or cleared.
The status is important when implementing back-to-back trip support. This support enables the Provider to assign a new trip to a Vehicle while that Vehicle is on an active Trip. The code for creating a back-to-back Trip is the same as a single trip and uses the same vehicle ID. The Fleet Engine adds the origin and destination of the new trip to the vehicle's waypoints. For more information about back-to-back trips, see Create Multi-waypoint trips.
Trip remaining waypoints
The Trip entity contains a repeated field of TripWaypoint
(RPC | REST),
called remainingWaypoints
(RPC | REST).
This field includes all waypoints that vehicle will need to travel in order
before this trip's final drop off point. It computes from
Vehicle's remaining waypoints.
In the Back-to-back and Carpool use cases, this list contains waypoints from
other trips that will be traversed before this trip, but excludes any waypoints
after this trip. The waypoint in the list can be identified by its TripId
and WaypointType
.
The relation between trip status and Vehicle remaining waypoints
The Vehicle's remaining waypoints (RPC | REST) will
be updated when Fleet Engine receives a trip status change request. The
previous waypoint will be removed from Vehicle's remaining waypoints list when
the tripStatus
(RPC | REST)
is changed from other status to ENROUTE_TO_XXX. That is, when
trip status is changed from ENROUTE_TO_PICKUP to ARRIVED_AT_PICKUP, the trip's
pickup point will still be in Vehicle's remaining waypoint list, but when trip
status is changed to ENROUTE_TO_INTERMEDIATE_DESTINATION or ENROUTE_TO_DROPOFF,
its pickup point then will be removed from the vehicle's remaining waypoints.
This is the same for ARRIVED_AT_INTERMEDIATE_DESTINATION and ENROUTE_TO_INTERMDEDIATE_DESTINATION. When ARRIVED_AT_INTERMEDIATE_DESTINATION, the current intermediate destination won't be removed from Vehicle's remaining waypoint list until the vehicle reports that it enroutes to the next waypoint.
When trip status is changed to COMPLETED
, no waypoints from this trip will be
in Vehicle's remaining waypoint list.
HOW-TO: Create a trip
A Trip
entity must be created in order for each trip request to be tracked and
matched to Vehicles in the fleet. Use the CreateTrip
endpoint with CreateTripRequest
to create a Trip.
The following attributes are required to create a trip:
parent
- A string that includes the Provider ID created when the Google Cloud Project was created.trip_id
- A string created by the Rideshare Provider.trip
- Container with basic metadata describing the trip.trip_type
- Enum representing whether the trip might have other riders from a different origin and destination in the same vehicle (SHARED
) or single party only (EXCLUSIVE
).pickup_point
- TerminalLocation representing the origin point for the trip. Refer to RPC reference or REST reference
When you create a trip, you can provide thenumber_of_passengers
, dropoff_point
and vehicle_id
. Although these fields are not required, if you provide them,
they are retained. All other Trip fields are ignored. For example, all trips
start with a trip_status
of NEW
even if you pass in a trip_status
of
CANCELED
in the creation request.
Example
The following example creates a trip to the Grand Indonesia East Mall. The trip
is for two passengers and is exclusive. The provider_id
of the Trip
must be
the same as the Project ID. In the example, the Rideshare Provider created the
Google Cloud Project, project-id. This project must have the
Service Accounts used to call the Fleet Engine. The trip's status is NEW
.
Later, after the service matches the trip to a vehicle, the service can call
UpdateTrip
and change the vehicle_id
when the trip is assigned to a vehicle.
shell
curl -X POST \
"https://fleetengine.googleapis.com/v1/providers/project-id/trips?tripId=tid-1f97" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
--data-binary @- << EOM
{
"tripType": "EXCLUSIVE",
"numberOfPassengers": 2,
"pickupPoint": {
"point": {"latitude": "-6.195139", "longitude": "106.820826"}
},
"dropoffPoint": {
"point": {"latitude": "-6.1275", "longitude": "106.6537"}
}
}
EOM
See providers.trips.create reference.
Java
static final String PROJECT_ID = "project-id";
TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);
String parent = "providers/" + PROJECT_ID;
Trip trip = Trip.newBuilder()
.setTripType(TripType.EXCLUSIVE) // Use TripType.SHARED for carpooling
.setPickupPoint( // Grand Indonesia East Mall
TerminalLocation.newBuilder().setPoint(
LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
// Provide the number of passengers if available.
.setNumberOfPassengers(2)
// Provide the drop-off point if available.
.setDropoffPoint(
TerminalLocation.newBuilder().setPoint(
LatLng.newBuilder().setLatitude(-6.1275).setLongitude(106.6537)))
.build();
CreateTripRequest createTripRequest =
CreateTripRequest.newBuilder() // no need for the header
.setParent(parent)
.setTripId("tid-1f97") // Trip ID assigned by the Provider
.setTrip(trip) // Initial state
.build();
// Error handling
// If Fleet Engine does not have trip with that id and the credentials of the
// requestor pass, the service creates the trip successfully.
try {
Trip createdTrip =
tripService.createTrip(createTripRequest);
} catch (StatusRuntimeException e) {
Status s = e.getStatus();
switch (s.getCode()) {
case ALREADY_EXISTS:
break;
case PERMISSION_DENIED:
break;
}
return;
}
Google Cloud platform logs for Trip Creation
The Fleet Engine API writes a log entry using Google Cloud platform logs when a
call to the CreateTrip
endpoint is received. The log entry includes
information about the values in the CreateTrip
request. If the call
succeeds, it will also include information about the Trip
that was returned.
HOW-TO: Update a trip
The Trip entity contains fields that enable tracking by the service and for
reporting the trip's progression by the Driver SDK and to the
Consumer SDK. To update the properties, use UpdateTripRequest
message. This updates the Trip fields according to the request’s field_mask
.
Refer to UpdateTripRequest.
The Rideshare Provider is responsible for updating the following attributes:
- Trip status.
- Vehicle ID. Either at the time of creation, or after matching the vehicle to a trip.
- Changes to pickup, dropoff, or waypoints.
The Fleet Engine automatically updates the following fields when using the Journey Sharing feature through the Driver SDK or Consumer SDK:
- Routes
- ETA
- Remaining distance
- Vehicle location
- Remaining waypoints
Refer to Trip
in RPC or
Resource.Trip
in REST.
Google Cloud platform logs for Trip Updates
The Fleet Engine API writes a log entry using Google Cloud platform logs when a
call to the UpdateTrip
endpoint is received. The log entry includes
information about the values in the UpdateTrip
request. If the call succeeds,
it will also include information about the Trip
that was returned.
HOW-TO: Search trips
The Fleet Engine supports searching for trips. As previously noted, a Trip is
automatically deleted after seven days, so SearchTrips
does not
expose a complete history of all Trips.
While SearchTrips
is a flexible API, the list below considers two use cases.
Determining a Vehicle’s Active Trips -- The Provider can determine a vehicle’s currently active trips. Within the
SearchTripsRequest
, thevehicle_id
is set to the vehicle under consideration andactive_trips_only
should be set totrue
.Reconciling the Provider and Fleet Engine State -- The Provider can use
SearchTrips
to ensure their Trip state and that of Fleet Engine match. This is especially important for TripStatus. If the state of a trip assigned to a Vehicle is not properly set toCOMPLETE
orCANCELED
, the Vehicle is not included bySearchVehicles
.
To use SearchTrips
in this way, leave vehicle_id
empty, set active_trips_only
to true
, and set minimum_staleness
to a time greater than most trip durations.
For example, you might use one hour. The results include Trips that are not
COMPLETE nor CANCELED, and have not been updated in over an hour. The Provider
should examine these Trips to ensure that their status in the Fleet Engine is
properly updated.
Troubleshooting
In the case of a DEADLINE_EXCEEDED
Error, the state of the Fleet Engine is
unknown. The Provider should call CreateTrip
again, which either returns a
201 (CREATED) or 409 (CONFLICT). In the latter case, the previous request succeeded
before DEADLINE_EXCEEDED
. See the Consumer API guides for more information
about handling trip errors: Android
or iOS.
Carpool ride support
You can assign multiple SHARED
trips to a vehicle that supports TripType.SHARED
.
You need to specify the order of all unpassed waypoints for all Trips assigned to
the Vehicle in this shared ride via Trip.vehicle_waypoints
when you assign the
vehicle_id
for a shared trip (in a CreateTrip
or UpdateTrip
request).
Refer to vehicle_waypoints
for RPC
or vehicleWaypoints
for REST.
Multiple destinations support
Identify an intermediate destination
The field intermediateDestinations
and field intermediateDestinationIndex
in Trip (RPC | REST)
are combined to be used to indicate the destination.
Update intermediate destination
You can update the intermediate destinations via UpdateTrip
. When updating
intermediate destinations, you must provide a complete list of intermediate destinations,
including those that have been visited, not just the one newly
added or to-be-modified.
When the intermediateDestinationIndex
points to an index after the position of
newly added/modified intermediate destination, the new/updated intermediate
destination will not be added to Vehicle’s waypoints
or Trip’s remainingWaypoints
.
The reason is that any intermediate destinations before intermediateDestinationIndex
are treated as already visited.
Trip status changes
The field intermediateDestinationsVersion
in (RPC | REST)
is required in the Trip status update request sent to Fleet Engine to indicate
an intermediate destination has passed. The targeted intermediate destination
is specified via the field intermediateDestinationIndex
.
When tripStatus
(RPC | REST) is ENROUTE_TO_INTERMEDIATE_DESTINATION, a number between
[0..N-1] indicates which intermediate destination the vehicle will cross next.
When tripStatus
is ARRIVED_AT_INTERMEDIATE_DESTINATION, a number between
[0..N-1] indicates which intermediate destination the vehicle is at.
Example
The following code example demonstrates how to update a trip's status to enroute to its first intermediate destination, assuming that you have created a multi-destination trip and the trip has passed its pickup point.
Java
static final String PROJECT_ID = "project-id";
static final String TRIP_ID = "multi-destination-trip-A";
String tripName = "providers/" + PROJECT_ID + "/trips/" + TRIP_ID;
Trip trip = …; // Fetch trip object from FleetEngine or your storage.
TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);
// Trip settings to update.
Trip trip = Trip.newBuilder()
// Trip status cannot go back to a previous status once it is passed
.setTripStatus(TripStatus.ENROUTE_TO_INTERMEDIATE_DESTINATION)
// Enrouting to the first intermediate destination.
.setIntermediateDestinationIndex(0)
// intermediate_destinations_version MUST be provided to ensure you
// have the same picture on intermediate destinations list as FleetEngine has.
.setIntermediateDestinationsVersion(
trip.getIntermediateDestinationsVersion())
.build();
// Trip update request
UpdateTripRequest updateTripRequest =
UpdateTripRequest.newBuilder()
.setName(tripName)
.setTrip(trip)
.setUpdateMask(
FieldMask.newBuilder()
.addPaths("trip_status")
.addPaths("intermediate_destination_index")
// intermediate_destinations_version must not be in the
// update mask.
.build())
.build();
// Error handling
try {
Trip updatedTrip = tripService.updateTrip(updateTripRequest);
} catch (StatusRuntimeException e) {
Status s = e.getStatus();
switch (s.getCode()) {
case NOT_FOUND: // Trip does not exist.
break;
case FAILED_PRECONDITION: // The given trip status is invalid, or the
// intermediate_destinations_version
// doesn’t match FleetEngine’s.
break;
case PERMISSION_DENIED:
break;
}
return;
}
HOW-TO: Subscribe to notification messages from the Fleet Engine API
The Fleet Engine API uses Google Cloud Pub/Sub to publish notifications on the topic created by the consumer Google Cloud Project. Pub/Sub is not enabled by default for Fleet Engine on your Google Cloud project. Please file a support case or contact your Customer Engineer to enable Pub/Sub.
In order to create a topic on your Cloud Project, follow these instructions. The topic ID must be 'fleet_engine_notifications'.
The topic must be created in the same Cloud project that is calling Fleet Engine APIs.
Once the topic is created, you will need to grant the Fleet Engine API
permission to publish on the topic. In order to do so, click on the topic you
just created and add a new permission. You might have to click on SHOW INFO PANEL to open the permissions editor.
The principal should be geo-fleet-engine@system.gserviceaccount.com
and the role should be Pub/Sub publisher
.
In order to setup your Cloud Project to subscribe to notifications, follow these instructions
The Fleet Engine API will publish each notification in two different data
formats, protobuf
and
json
. The data format for each notification is denoted in the
PubsubMessage attributes
with the key as data_format
and value as protobuf
or json
.
Notification schema:
Protobuf
// A batch of notifications that is published by the Fleet Engine service using
// Cloud Pub/Sub in a single PubsubMessage.
message BatchNotification {
// Required. At least one notification must exist.
// List of notifications containing information related to changes in
// Fleet Engine data.
repeated Notification notifications = 1;
}
// A notification related to changes in Fleet Engine data.
// The data provides additional information specific to the type of the
// notification.
message Notification {
// Required. At least one type must exist.
// Type of notification.
oneof type {
// Notification related to changes in vehicle data.
VehicleNotification vehicle_notification = 1;
}
}
// Notification sent when a new vehicle was created.
message CreateVehicleNotification {
// Required.
// Vehicle must contain all fields that were set when it was created.
Vehicle vehicle = 1;
}
// Notification sent when an existing vehicle is updated.
message UpdateVehicleNotification {
// Required.
// Vehicle must only contain name and fields that are present in the
// field_mask field below.
Vehicle vehicle = 1;
// Required.
// Contains vehicle field paths that were specifically requested
// by the Provider.
google.protobuf.FieldMask field_mask = 2;
}
// Notification related to changes in vehicle data.
message VehicleNotification {
// Required. At least one type must be set.
// Type of notification.
oneof type {
// Notification sent when a new vehicle was created.
CreateVehicleNotification create_notification = 1;
// Notification sent when an existing vehicle is updated.
UpdateVehicleNotification update_notification = 2;
}
}
JSON
BatchNotification: {
"description": "A batch of notifications that is published by the Fleet Engine service using Cloud Pub/Sub in a single PubsubMessage.",
"type": "object",
"required": ["notifications"],
"properties": {
"notifications": {
"description": "At least one notification must exist. List of notifications containing information related to changes in Fleet Engine data.",
"type": "Notification[]"
}
}
}
Notification: {
"description": "A notification related to changes in Fleet Engine data. The data provides additional information specific to the type of the notification.",
"type": "object",
"properties": {
"vehicleNotification": {
"description": "Notification related to changes in vehicle data.",
"type": "VehicleNotification"
}
}
}
VehicleNotification: {
"description": "Notification related to changes in vehicle data.",
"type": "object",
"properties": {
"createNotification": {
"description": "Notification sent when a new vehicle was created.",
"type": "CreateVehicleNotification"
},
"updateNotification": {
"description": "Notification sent when an existing vehicle is updated.",
"type": "UpdateVehicleNotification"
}
}
}
CreateVehicleNotification: {
"description": "Notification sent when a new vehicle was created.",
"type": "object",
"required": ["vehicle"],
"properties": {
"vehicle": {
"description": "Vehicle must contain all fields that were set when it was created.",
"type": "Vehicle"
}
}
}
UpdateVehicleNotification: {
"description": "Notification sent when an existing vehicle is updated.",
"type": "object",
"required": ["vehicle", "fieldMask"],
"properties": {
"vehicle": {
"description": "Vehicle must only contain name and fields that are present in the fieldMask field below.",
"type": "Vehicle"
},
"fieldMask": {
"description": "Contains vehicle field paths that were specifically requested by the Provider.",
"type": "FieldMask"
}
}
}