Comienza a usar Fleet Engine

La API de On-demand Rides and Deliveries de Fleet Engine te permite administrar los viajes y el estado del vehículo para tus aplicaciones de Progreso del viaje y del pedido. Este controla transacciones entre el SDK del controlador, el SDK del consumidor y tu servicio de backend, que puede comunicarse con Fleet Engine mediante llamadas de gRPC o REST.

Requisitos previos

Para el desarrollo, asegúrate de instalar el SDK de Cloud (gcloud) y de estar autenticado en tu proyecto.

shell

gcloud auth login

Deberías ver un mensaje de éxito como el siguiente:

You are now logged in as [my-user@example.com].
Your current project is [project-id].  You ...

Verifica que las APIs de Solution Fleet Engine de On-demand Rides and Deliveries estén configuradas de forma correcta.

shell

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

Si este comando da como resultado un error, consulta al administrador del proyecto y al representante de Atención al cliente de Google para obtener acceso.

Logging

Flota Engine puede escribir mensajes de registro sobre las llamadas a la API que recibe en los registros de la plataforma de Google Cloud. Consulta la documentación de Cloud Logging para obtener una descripción general de cómo leer y analizar los registros.

Es posible que Logging no esté habilitado de forma predeterminada para los proyectos creados antes del 10 de febrero de 2022. Consulta la documentación de registro para obtener más detalles.

Bibliotecas cliente

Publicamos bibliotecas cliente en varios lenguajes de programación comunes. Estas bibliotecas ayudarán a proporcionar una mejor experiencia del desarrollador en comparación con REST o gRPC sin procesar. Si quieres obtener instrucciones sobre cómo obtener bibliotecas cliente para tu aplicación de servidor, consulta Bibliotecas cliente.

Para los ejemplos de Java en esta documentación, se da por sentado que el usuario tiene conocimientos previos sobre gRPC.

Autenticación y autorización

Puedes configurar las capacidades que proporciona el Progreso del viaje y del pedido a través de la consola de Google Cloud. Estas APIs y SDKs requieren el uso de tokens web JSON que se firmaron con cuentas de servicio creadas desde Cloud Console.

Configuración del proyecto de Cloud

Para configurar tu proyecto de la nube, primero créalo y, luego, crea cuentas de servicio.

Para crear tu proyecto de Google Cloud, sigue estos pasos:

  1. Crea un proyecto de Google Cloud con la consola de Google Cloud.
  2. En el panel de APIs y servicios, habilita la API de Local Rides and Deliveries.

Las cuentas de servicio están asociadas con uno o más roles. Se usan para crear tokens web JSON que otorgan diferentes conjuntos de permisos según las funciones. Por lo general, para reducir la posibilidad de abuso, puedes crear varias cuentas de servicio, cada una con el conjunto mínimo de funciones requeridas.

El Progreso del viaje y el pedido usa los siguientes roles:

RolDescripción
Usuario del SDK para el consumidor de Fleet Engine

roles/fleetengine.consumerSdkUser
Otorga permiso para buscar vehículos y recuperar información sobre vehículos y viajes. Los tokens creados por una cuenta de servicio con esta función se suelen usar desde los dispositivos móviles de la app para consumidores de transporte compartido o entrega.
Usuario de SDK para el controlador de Fleet Engine

roles/fleetengine.driverSdkUser
Otorga permiso para actualizar las ubicaciones y rutas de los vehículos, así como obtener información sobre vehículos y viajes. Los tokens que crea una cuenta de servicio con esta función se suelen usar desde los dispositivos móviles de la app de transporte compartido o de entrega.
Administrador a pedido de Fleet Engine

roles/fleetengine.ondemandAdmin
Otorga permisos de lectura y escritura para todos los recursos de vehículos y viajes. Las principales con esta función no necesitan usar JWT y, en su lugar, deben usar las credenciales predeterminadas de la aplicación. Se ignoran las reclamaciones personalizadas de JWT. Este rol debe restringirse a entornos de confianza (backend del cliente).
Superusuario del servicio de FletEngine **(OBSOLETO)**

roles/fleetengine.serviceSuperUser
Otorga permisos a todas las APIs de viajes y vehículos. Los tokens que crea una cuenta de servicio con esta función, por lo general, se usan desde tus servidores de backend. Esta función es obsoleta. En su lugar, prefieres roles/fleetengine.ondemandAdmin.

Por ejemplo, crea una cuenta de servicio para cada una de las tres funciones y asígnales sus respectivas funciones.

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

Los SDK del controlador y del consumidor se basan en estas funciones estándar.

Como alternativa, es posible crear funciones personalizadas que permitan agrupar un conjunto arbitrario de permisos. Los SDK para consumidores y controladores mostrarán mensajes de error cuando falte un permiso necesario. Por lo tanto, recomendamos enfáticamente usar el conjunto estándar de funciones que se presentó antes y no las funciones personalizadas.

Para mayor comodidad, si necesitas crear tokens JWT para clientes que no son de confianza, agregar usuarios a la función de creador de tokens de cuentas de servicio les permite crear tokens con las herramientas de línea de comandos de gcloud.

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

Donde my-user@example.com es el correo electrónico que se usa para autenticarse con gcloud (gcloud auth list --format='value(account)').

Biblioteca de autenticación de Fleet Engine

Fleet Engine usa tokens web JSON (JWT) para restringir el acceso a las API de Fleet Engine. La nueva biblioteca de autenticación de Fleet Engine, disponible en GitHub, simplifica la construcción de JWT de Fleet Engine y los firma de forma segura.

La biblioteca proporciona los siguientes beneficios:

  • Simplifica el proceso de creación de tokens de Fleet Engine.
  • Proporciona mecanismos de firma de tokens distintos del uso de archivos de credenciales (como la identidad de una cuenta de servicio).
  • Adjunta tokens firmados a las solicitudes salientes realizadas desde un stub de gRPC o un cliente de GCC.

Crea un token web JSON (JWT) para la autorización

Cuando no se usa la biblioteca de autenticación de Fleet Engine, los tokens web JSON (JWT) deben crearse directamente dentro de tu base de código. Para ello, debes comprender en profundidad los JWT y cómo se relacionan con Fleet Engine. Por este motivo, recomendamos ALTAMENTE aprovechar la biblioteca de autenticación de Fleet Engine.

Dentro de Fleet Engine, los tokens web JSON (JWT) proporcionan autenticación de corta duración y garantizan que los dispositivos solo puedan modificar vehículos, viajes o tareas para los que estén autorizados. Los JWT contienen un encabezado y una sección de reclamación. La sección del encabezado contiene información como la clave privada que se usará (obtenida de las cuentas de servicio) y el algoritmo de encriptación. La sección de reclamación contiene información como la hora de creación del token, el tiempo de actividad del token, los servicios a los que reclama acceso y otra información de autorización para determinar el acceso, como el ID del vehículo.

Una sección de encabezado JWT contiene los siguientes campos:

CampoDescripción
alg El algoritmo que se usará. `RS256`:
typ El tipo de token. “JWT”.
niño El ID de la clave privada de tu cuenta de servicio Puedes encontrar este valor en el campo “private_key_id” del archivo JSON de tu cuenta de servicio. Asegúrate de usar una clave de una cuenta de servicio con el nivel correcto de permisos.

Una sección de reclamaciones de JWT contiene los siguientes campos:

CampoDescripción
iss La dirección de correo electrónico de tu cuenta de servicio.
sub La dirección de correo electrónico de tu cuenta de servicio.
aud El SERVICE_NAME de tu cuenta de servicio, en este caso https://fleetengine.googleapis.com/
iat La marca de tiempo cuando se creó el token, especificada en segundos transcurridos desde las 00:00:00 UTC del 1 de enero de 1970. Espera 10 minutos para el sesgo. Si la marca de tiempo es demasiado lejana en el pasado o en el futuro, el servidor podría informar un error.
exp Es la marca de tiempo de cuando vence el token, especificada en segundos transcurridos desde las 00:00:00 UTC del 1 de enero de 1970. La solicitud falla si la marca de tiempo es dentro de más de una hora en el futuro.
autorización Según el caso de uso, puede contener "vehicleid" o "tripid".

Crear un token JWT hace referencia a firmarlo. Si quieres obtener instrucciones y muestras de código para crear y firmar el JWT, consulta Autorización de la cuenta de servicio sin OAuth. Luego, puedes adjuntar un token firmado a las llamadas de gRPC o a otros métodos usados para acceder a Fleet Engine.

Reclamaciones de JWT

Cuando crees la carga útil de JWT, agrega una reclamación adicional en la sección de autorización con la clave vehicleid o tripid establecida en el valor del ID de vehículo o de viaje para el que se realiza la llamada.

El SDK del conductor siempre usa la reclamación vehicleid, ya sea que opere en un viaje o un vehículo. El backend de Fleet Engine garantiza que el vehículo esté asociado con el viaje solicitado antes de realizar la modificación.

El SDK para consumidores siempre usa la reclamación tripid.

El proveedor de transporte compartido o de entrega debe usar el vehicleid o la tripid con un "*" para que coincidan con todos los vehículos y viajes. Ten en cuenta que el JWT puede contener ambos tokens, incluso si no es necesario, lo que puede simplificar la implementación de la firma de tokens.

Casos de uso de JWT

A continuación, se muestra un token de ejemplo para el servidor del proveedor:

{
  "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": "*"
   }
}

A continuación, se muestra un ejemplo de token para una App de consumidor:

{
  "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"
   }
}

A continuación, se muestra un token de ejemplo para una app del controlador:

{
  "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"
   }
}
  • En el campo kid del encabezado, especifica el ID de clave privada de tu cuenta de servicio. Puedes encontrar este valor en el campo private_key_id del archivo JSON de tu cuenta de servicio.
  • Para los campos iss y sub, especifica la dirección de correo electrónico de tu cuenta de servicio. Puedes encontrar este valor en el campo client_email del archivo JSON de tu cuenta de servicio.
  • En el campo aud, especifica https://SERVICE_NAME/.
  • En el campo iat, usa la marca de tiempo de la creación del token, especificada como segundos transcurridos desde las 00:00:00 UTC, 1 de enero de 1970. Espera 10 minutos para el sesgo. Si la marca de tiempo es demasiado lejana en el pasado o en el futuro, el servidor podría informar un error.
  • En el campo exp, usa la marca de tiempo de vencimiento del token, que se especifica como segundos desde las 00:00:00 UTC del 1 de enero de 1970. El valor máximo permitido es iat + 3,600.

Cuando firmes el JWT que se pasará a un dispositivo móvil, asegúrate de usar la cuenta de servicio para el rol de controlador o SDK de consumidor. De lo contrario, el dispositivo móvil podrá modificar el estado que no debería tener.

Del mismo modo, cuando firmes el JWT que se usará para llamadas con privilegios, asegúrate de usar la cuenta de servicio con la función de superusuario. De lo contrario, la operación fallará.

Cómo generar un JWT para realizar pruebas

Generar tokens desde la terminal puede ser útil durante las pruebas.

Para seguir estos pasos, tu cuenta de usuario debe tener la función de creador de tokens de cuenta de servicio:

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

Crea un archivo nuevo llamado unsigned_token.json con el siguiente contenido. La propiedad iat es la hora actual en segundos después de la época, que se puede recuperar ejecutando date +%s en tu terminal. La propiedad exp es el tiempo de vencimiento en segundos después del ciclo de entrenamiento, que se puede calcular agregando 3,600 a iat. El tiempo de vencimiento no puede ser de más de una hora en el futuro.

{
  "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": "*"
   }
}

Luego, ejecuta el siguiente comando de gcloud para firmar el token en nombre de la cuenta de servicio del superusuario:

gcloud beta iam service-accounts sign-jwt --iam-account=super-user-service-account@project-id.iam.gserviceaccount.com unsigned_token.json signed_token.jwt

Un JWT firmado codificado en Base64 debería almacenarse dentro del archivo signed_token.jwt. El token es válido durante la próxima hora.

Ahora puedes probar el token mediante la ejecución de un comando curl en el extremo de REST para listar vehículos:

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

Vehículos y su ciclo de vida

El vehículo es la entidad que representa un par conductor-vehículo. Actualmente, no se puede hacer un seguimiento de un conductor y un vehículo por separado. El proveedor de transporte compartido o de entrega crea un vehículo con un ID de proveedor (que debe ser el mismo que el ID del proyecto de Google Cloud que contiene la cuenta de servicio que se usa para llamar a las APIs de Fleet Engine) y un ID de vehículo del proveedor de transporte compartido o de entrega.

Se borrará automáticamente un vehículo que no se haya actualizado a través de UpdateVehicle después de siete días. Llamar a CreateVehicle con un par de ID de proveedor/ID de vehículo que ya existe es un error. El caso de los vehículos que no se actualizan con frecuencia se puede tratar de dos maneras: llamar con frecuencia a CreateVehicle con un par de ID de proveedor/ID de vehículo esperado y descartar el error si el vehículo ya existe; o llamar a CreateVehicle después de un UpdateVehicle muestra un error NOT_FOUND.

Actualizaciones de la ubicación del vehículo

Para obtener el mejor rendimiento con Fleet Engine, proporciónale un flujo de actualizaciones de la ubicación del vehículo. Usa cualquiera de las siguientes formas para proporcionar estas actualizaciones:

  1. Usa el SDK de Driver (Android o iOS) es la opción más sencilla.
  2. Usa un código personalizado, que es útil si las ubicaciones se retransmiten a través de tu backend o si usas dispositivos que no sean Android o iOS.

Tipos de vehículos

La entidad Vehicle contiene un campo obligatorio de VehicleType, que contiene una enum Category que se puede especificar como AUTO, TAXI, TRUCK, TWO_WHEELER, BICYCLE o PEDESTRIAN. El tipo de vehículo puede funcionar como un criterio de filtro en SearchVehicles y ListVehicles.

Todas las rutas para vehículos utilizarán el RouteTravelMode correspondiente si la categoría se establece en AUTO, TWO_WHEELER, BICYCLE o PEDESTRIAN. Si la categoría se establece como TAXI o TRUCK, el enrutamiento se trata de la misma manera que el modo AUTO.

Atributos del vehículo

La entidad Vehicle contiene un campo repetido de VehicleAttribute. Fleet Engine no interpreta estos atributos. La API de SearchVehicles incluye un campo que requiere que el Vehicles coincidente contenga todos los atributos incluidos establecidos en el valor especificado.

Ten en cuenta que el campo de atributo se suma a muchos otros campos admitidos en el mensaje Vehicle, como vehicle_type y supported_trip_types.

Puntos de referencia restantes del vehículo

La entidad Vehicle contiene un campo repetido de TripWaypoint (RPC | REST), llamado waypoints(RPC | REST). Este campo incluye los puntos de referencia restantes en los viajes, en el orden en que el vehículo los alcanza. Fleet Engine calcula este campo a medida que se asignan los viajes al vehículo y lo actualiza a medida que los viajes cambian su estado. Estos puntos de referencia se pueden identificar mediante los campos TripId y WaypointType.

Ampliación de la elegibilidad de un vehículo para coincidencias

Por lo general, los servicios de transporte compartido o proveedor de entregas son responsables de hacer coincidir las solicitudes de viajes con los vehículos. El servicio puede usar los atributos de vehículo para incluir uno en una mayor cantidad de búsquedas. Por ejemplo, el proveedor puede implementar un conjunto de atributos correspondientes a los niveles de beneficios o capacidades que proporciona un vehículo. Por ejemplo, tres niveles podrían ser un conjunto de atributos con valores booleanos: is_bronze_level, is_silver_level y is_gold_level. Un vehículo puede ser apto para los tres. Cuando Fleet Engine recibe una solicitud para un viaje que requiere capacidades de nivel plateado, la búsqueda incluye ese vehículo. El uso de atributos de esta manera incluye vehículos que ofrecen una variedad de capacidades.

Existen dos formas de actualizar los atributos del vehículo. Una es la API de UpdateVehicle. Cuando se usa esta API, todo el conjunto de atributos de vehículo se establece en ese valor. No es posible actualizar un solo atributo. El otro método es la API de UpdateVehicleAttributes. Este método solo toma los atributos que se actualizarán. Los atributos incluidos en la solicitud se establecerán con el valor nuevo o se agregarán. Los atributos no especificados no se modificarán.

Instructivo: Crea un vehículo

Se debe crear una entidad Vehicle para cada vehículo que se rastreará en la flota.

Usa el extremo CreateVehicle con el CreateVehicleRequest para crear un vehículo.

El provider_id de Vehicle debe ser el ID del proyecto (p.ej., mi proyecto a pedido) del proyecto de Google Cloud que contiene las cuentas de servicio que se usarán para llamar a Fleet Engine. Ten en cuenta que, si bien varias cuentas de servicio pueden acceder a Fleet Engine para el mismo proveedor de transporte compartido o de entrega, Fleet Engine no admite por el momento cuentas de servicio de varios proyectos de Google Cloud que acceden a la misma Vehicles.

Vehicle se puede crear en el estado OFFLINE o ONLINE. Si creas ONLINE, puede mostrarse de inmediato en respuesta a consultas SearchVehicles.

Se puede incluir un last_location inicial en la llamada a CreateVehicle. Si bien se permite, no se debe crear un Vehicle en el estado ONLINE sin un last_location.

Consulta la sección Tipos de vehículos para obtener detalles sobre el campo de tipo de vehículo.

Consulta la sección Atributos de vehículo para obtener detalles sobre el campo de atributos.

El valor que muestra CreateVehicle es la entidad Vehicle creada.

Ejemplo

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

Consulta la referencia de providers.vehicles.create.

Java

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService =
    VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
Vehicle vehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.OFFLINE)  // Initial state
    .addSupportedTripTypes(TripType.EXCLUSIVE)
    .setMaximumCapacity(4)
    .setVehicleType(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .addAttributes(VehicleAttribute.newBuilder()
        .setKey("on_trip").setValue("false"))  // Opaque to the Fleet Engine
    // Add .setBackToBackEnabled(true) to make this vehicle eligible for trip
    // matching while even if it is on a trip.  By default this is disabled.
    .build();

CreateVehicleRequest createVehicleRequest =
    CreateVehicleRequest.newBuilder()  // no need for the header
        .setParent(parent)
        .setVehicleId("vid-8241890")  // Vehicle ID assigned by Rideshare or Delivery Provider
        .setVehicle(vehicle)  // Initial state
        .build();

// In this case, the Vehicle is being created in the OFFLINE state and
// no initial position is being provided.  When the Driver App checks
// in with the Rideshare or Delivery Provider, the state can be set to ONLINE and
// the Driver App will update the Vehicle Location.

try {
  Vehicle createdVehicle =
      vehicleService.createVehicle(createVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle created successfully.

Registros de plataforma de Google Cloud para la creación de vehículos

La API de Fleet Engine escribe una entrada de registro a través de los registros de la plataforma de Google Cloud cuando se recibe una llamada al extremo CreateVehicle. La entrada de registro incluye información sobre los valores de la solicitud CreateVehicle. Si la llamada se ejecuta correctamente, también incluirá información sobre el Vehicle que se mostró.

shell

gcloud --project=project-id logging read --freshness=1h '
  jsonPayload.request.vehicleId="vid-8241890"
  jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.CreateVehicleLog"
'

Se debe imprimir un registro similar al siguiente:

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

Notificaciones de Cloud Pub/Sub para la creación de vehículos

La API de Fleet Engine publica una notificación a través de Cloud Pub/Sub cuando se crea un vehículo nuevo. Para recibir estas notificaciones, sigue las instrucciones que se indican aquí.

Instructivo: Actualiza la ubicación de un vehículo

Si no usas el SDK del conductor para actualizar la ubicación del vehículo, puedes realizar una llamada directa a Fleet Engine con la ubicación del vehículo. Para cualquier vehículo activo, Flet Engine espera una actualización de la ubicación al menos una vez por minuto y, como máximo, una vez cada 5 segundos. Estas actualizaciones solo requieren privilegios de usuario del SDK de Fleet Engine Driver.

Ejemplo

shell

curl -X PUT \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=last_location" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
    "supplementalLocation": {"latitude": 12.1, "longitude": 14.5},
    "supplementalLocationTime": "$(date -u --iso-8601=seconds)",
    "supplementalLocationSensor": "CUSTOMER_SUPPLIED_LOCATION",
    "supplementalLocationAccuracy": 15
}
EOM

Consulta la referencia de providers.vehicles.update.

Java

static final String PROJECT_ID = "project-id";
static final String VEHICLE_ID = "vid-8241890";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String vehicleName = "providers/" + PROJECT_ID + "/vehicles/" + VEHICLE_ID;
Vehicle updatedVehicle = Vehicle.newBuilder()
    .setLastLocation(VehicleLocation.newBuilder()
        .setSupplementalLocation(LatLng.newBuilder()
            .setLatitude(37.3382)
            .setLongitude(121.8863))
        .setSupplementalLocationTime(now())
        .setSupplementalLocationSensor(LocationSensor.CUSTOMER_SUPPLIED_LOCATION)
        .setSupplementalLocationAccuracy(DoubleValue.of(15.0)))  // Optional)
    .build();

UpdateVehicleRequest updateVehicleRequest = UpdateVehicleRequest.newBuilder()
    .setName(vehicleName)
    .setVehicle(updatedVehicle)
    .setUpdateMask(FieldMask.newBuilder()
        .addPaths("last_location"))
    .build();

try {
  Vehicle updatedVehicle =
      vehicleService.updateVehicle(updateVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      // Most implementations will call CreateVehicle in this case
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle updated successfully.

Instructivo: Actualiza otros campos de vehículos

Las actualizaciones a otros atributos del estado del vehículo se producen con menos frecuencia que las actualizaciones de posición. Las actualizaciones de atributos que no sean last_location requieren privilegios de superusuario de Flet Engine.

UpdateVehicleRequest incluye un update_mask para indicar qué campos actualizar. El comportamiento del campo es como el que se muestra en la documentación de Protobuf para las máscaras de campo.

Como se indica en Atributos de vehículo, la actualización del campo attributes requiere escribir todos los atributos que se conservarán. No es posible actualizar el valor de un par clave-valor en una llamada a UpdateVehicle. Para actualizar los valores de atributos específicos, se puede usar la API de UpdateVehicleAttributes.

Ejemplo

En este ejemplo, se habilita 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

Consulta la referencia de providers.vehicles.update.

Java

static final String PROJECT_ID = "project-id";
static final String VEHICLE_ID = "vid-8241890";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String vehicleName = "providers/" + PROJECT_ID + "/vehicles/" + VEHICLE_ID;
Vehicle updatedVehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.ONLINE)
    .addAllAttributes(ImmutableList.of(
        VehicleAttribute.newBuilder().setKey("on_trip").setValue("true").build(),
        VehicleAttribute.newBuilder().setKey("cash_only").setValue("false").build()))
    .setBackToBackEnabled(true)
    .build();

UpdateVehicleRequest updateVehicleRequest = UpdateVehicleRequest.newBuilder()
    .setName(vehicleName)
    .setVehicle(updatedVehicle)
    .setUpdateMask(FieldMask.newBuilder()
        .addPaths("vehicle_state")
        .addPaths("attributes")
        .addPaths("back_to_back_enabled"))
    .build();

// Attributes and vehicle state are being updated, so both are
// included in the field mask.  Note that of on_trip were
// not being updated, but rather cash_only was being changed,
// the desired value of "on_trip" would still need to be written
// as the attributes are completely replaced in an update operation.

try {
  Vehicle updatedVehicle =
      vehicleService.updateVehicle(updateVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      // Most implementations will call CreateVehicle in this case
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle updated successfully.

Registros de plataforma de Google Cloud para actualizaciones de vehículos

La API de Fleet Engine escribe una entrada de registro a través de los registros de la plataforma de Google Cloud cuando se recibe una llamada al extremo UpdateVehicle. La entrada de registro incluye información sobre los valores de la solicitud UpdateVehicle. Si la llamada se ejecuta correctamente, también incluirá información sobre el Vehicle que se mostró.

shell

gcloud --project=project-id logging read --freshness=1h '
  jsonPayload.request.vehicleId="vid-8241890"
  jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.UpdateVehicleLog"
'

Notificaciones de Cloud Pub/Sub para actualizaciones de vehículos

La API de Fleet Engine publica una notificación a través de Cloud Pub/Sub cuando se actualiza un vehículo existente. Para recibir estas notificaciones, sigue las instrucciones que se indican aquí.

Instructivo: Buscar vehículos

Fleet Engine admite la búsqueda de vehículos. La API de SearchVehicles te permite encontrar conductores cercanos disponibles que se adapten mejor a una tarea, como entregar un viaje o una solicitud de entrega. La API de SearchVehicles muestra una lista clasificada de conductores que coinciden con los atributos de tareas con los atributos de los vehículos de tu flota. Para obtener más información, consulta Cómo buscar conductores cercanos.

Ejemplo

Cuando se buscan vehículos disponibles, Fleet Engine excluye de forma predeterminada los vehículos en viajes activos. Los servicios del proveedor de transporte compartido o de entrega deben incluirlos de forma explícita en las solicitudes de búsqueda. En el siguiente ejemplo, se muestra cómo incluir esos vehículos en una búsqueda de vehículos que coincidan con un viaje desde el centro comercial Grand Indonesia East al centro de convenciones Balai Sidang Yakarta.

shell

Primero, actualiza la ubicación del vehículo que creamos en los pasos anteriores para que sea apto. En el mundo real, esto se realizaría con el SDK de Driver que se ejecuta en el dispositivo Android o iOS del vehículo.

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

Si realizas la búsqueda, se debería ceder al menos el vehículo.

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

Consulta la referencia de providers.vehicles.search.

Java

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
SearchVehiclesRequest searchVehiclesRequest = SearchVehiclesRequest.newBuilder()
    .setParent(parent)
    .setPickupPoint( // Grand Indonesia East Mall
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
    .setDropoffPoint( // Balai Sidang Jakarta Convention Center
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.213796).setLongitude(106.807195)))
    .setPickupRadiusMeters(2000)
    .setCount(10)
    .setMinimumCapacity(2)
    .addTripTypes(TripType.EXCLUSIVE)
    .addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .setFilter("attributes.on_trip=\"false\"")
    .setOrderBy(VehicleMatchOrder.PICKUP_POINT_ETA)
    .setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
    .build();

// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully

try {
  SearchVehiclesResponse searchVehiclesResponse =
      vehicleService.searchVehicles(searchVehiclesRequest);

  // Search results: Each vehicle match contains a vehicle entity and information
  // about the distance and ETA to the pickup point and dropoff point.
  List<VehicleMatch> vehicleMatches = searchVehiclesResponse.getMatchesList();
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Consulta de filtrado de vehículos

SearchVehicles y ListVehicles admiten el filtrado de atributos de vehículos mediante una consulta de filtro. Para ver la sintaxis de las consultas de filtros, consulta AIP-160 para ver ejemplos.

Ten en cuenta que las consultas de filtros SOLO admiten el filtrado por atributos de vehículos y no se pueden usar para otros campos. La consulta de filtro funciona como una cláusula AND con otras restricciones, como minimum_capacity o vehicle_types en SearchVehiclesRequest.

Instructivo: Muestra una lista de vehículos

SearchVehicles está optimizado para encontrar una pequeña cantidad de vehículos en orden de clasificación con rapidez y se usa principalmente para encontrar conductores cercanos que sean más adecuados para una tarea. Sin embargo, en ocasiones, es posible que quieras encontrar todos los vehículos que cumplan con algunos criterios, incluso si es necesaria la paginación por los resultados. ListVehicles está diseñado para ese caso de uso.

La API de ListVehicles te permite encontrar todos los vehículos que satisfacen algunas opciones de solicitud específicas. La API de ListVehicles muestra una lista paginada de vehículos en el proyecto que coincide con algunos requisitos.

Para filtrar los atributos de vehículos, consulta la Consulta de filtrado de vehículos.

Ejemplo

En este ejemplo, se realiza un filtrado en vehicle_type y atributos con la cadena filter.

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

Consulta la referencia de providers.vehicles.list.

Java

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
ListVehiclesRequest listVehiclesRequest = ListVehiclesRequest.newBuilder()
    .setParent(parent)
    .addTripTypes(TripType.EXCLUSIVE)
    .addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .setFilter("attributes.on_trip=\"false\"")
    .setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
    .build();

// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully

try {
  ListVehiclesResponse listVehiclesResponse =
      vehicleService.listVehicles(listVehiclesRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Viajes y su ciclo de vida

La API de Trip y el ciclo de vida son similares a la API de Vehicle y el ciclo de vida. El proveedor de transporte compartido es responsable de crear viajes mediante las interfaces de Fleet Engine. Fleet Engine proporciona un servicio de RPC, TripService, y recursos de REST, provider.trips. Estas interfaces habilitan la creación de entidades de Trip, las solicitudes de información, la funcionalidad de búsqueda y la capacidad de actualización.

Un Trip tiene un campo de estado para hacer un seguimiento de su progreso a lo largo del ciclo de vida. Los valores se mueven de NEW a COMPLETE más CANCELED y UNKNOWN_TRIP_STATUS. Consulta trip_status para RPC o TripStatus para REST.

  • NEW
  • ENROUTE_TO_PICKUP
  • ARRIVED_AT_PICKUP
  • ENROUTE_TO_INTERMEDIATE_DESTINATION
  • ARRIVED_AT_INTERMEDIATE_DESTINATION
  • ENROUTE_TO_DROPOFF
  • COMPLETE

Tu servicio puede actualizar el viaje a CANCELED desde cualquiera de estos estados. Cuando tu servicio crea un viaje, el motor establece el estado como NEW. Un objeto vehicle_id es opcional. Al igual que con los vehículos, los servicios borran los viajes automáticamente después de siete días sin una actualización. Si tu servicio intenta crear un viaje con un ID que ya existe, se muestra un error. Un viaje se considera "activo" si tiene un estado distinto de COMPLETE o CANCELED. Esta distinción es importante en el campo active_trips de la entidad Vehicle y SearchTripsRequest.

Tu servicio solo puede cambiar el vehicle_id asignado a un viaje cuando este está activo. Por ejemplo, puedes hacerlo cuando un conductor cancela un viaje mientras está en la ruta y este se reasigna a otro vehículo.

El estado es importante cuando se implementa la asistencia para viajes consecutivos. Esta compatibilidad le permite al Proveedor asignar un viaje nuevo a un Vehículo mientras este se encuentra en un Viaje activo. El código para crear un viaje consecutivo es el mismo que el de un solo viaje y utiliza el mismo ID de vehículo. Fleet Engine agrega el origen y el destino del viaje nuevo a los puntos de referencia del vehículo. Para obtener más información sobre viajes consecutivos, consulta Cómo crear viajes con varios puntos de referencia.

Puntos de referencia restantes del viaje

La entidad Trip contiene un campo repetido de TripWaypoint (RPC | REST), llamado remainingWaypoints(RPC | REST). Este campo incluye todos los puntos de referencia que el vehículo deberá recorrer en orden antes del punto de llegada final de este viaje. Calcula a partir de los puntos de referencia restantes del vehículo. En los casos de uso Back-to-Back-to-Back-To-Back-To-Back-Back-to-Back-to-back y Waze, esta lista contiene puntos de referencia de otros viajes que se recorrerán antes de este viaje, pero excluye todos los puntos de referencia posteriores a este viaje. El punto de referencia en la lista se puede identificar por su TripId y WaypointType.

La relación entre el estado del viaje y los puntos de referencia restantes del vehículo

Los puntos de referencia restantes del vehículo (RPC | REST) se actualizarán cuando Fleet Engine reciba una solicitud de cambio de estado de viaje. El punto de referencia anterior se quitará de la lista de puntos de referencia restantes del vehículo cuando tripStatus(RPC | REST) cambie de otro estado a ENROUTE_TO_XXX. Es decir, cuando el estado del viaje cambie de ENROUTE_TO_PICKUP a ARRIVED_AT_PICKUP, el punto de partida del viaje seguirá estando en la lista de puntos de referencia restantes del vehículo, pero cuando el estado del viaje cambie a ENROUTE_TO_INTERMEDIATE_DESTINATION o ENROUTE_TO_DROPOFF, el punto de partida se quitará de los puntos de partida restantes.

Esto es lo mismo para ARRIVED_AT_INTERMEDIATE_DESTINATION y ENROUTE_TO_INTERMDEDIATE_DESTINATION. Cuando el valor sea ARRIVED_AT_INTERMEDIATE_DESTINATION, el destino intermedio actual no se quitará de la lista de puntos de referencia restantes del vehículo hasta que este informe que se dirige al siguiente punto de referencia.

Cuando el estado del viaje cambie a COMPLETED, no aparecerá ningún punto de referencia de este viaje en la lista de puntos de referencia restantes del vehículo.

INSTRUCTIVO: Cómo crear un viaje

Se debe crear una entidad Trip para que se realice un seguimiento de cada solicitud de viaje y se coincida con los vehículos de la flota. Usa el extremo CreateTrip con CreateTripRequest para crear un viaje.

Los siguientes atributos son obligatorios para crear un viaje:

  • parent: Es una cadena que incluye el ID del proveedor que se creó cuando se creó el proyecto de Google Cloud.
  • trip_id: Es una cadena que crea el proveedor de transporte compartido.
  • trip: Contenedor con metadatos básicos que describen el viaje.
    • trip_type: Es una enumeración que representa si el viaje puede tener otros pasajeros de un origen y un destino diferentes en el mismo vehículo (SHARED) o solo de un solo grupo (EXCLUSIVE).
    • pickup_point: TerminalLocation que representa el punto de origen del viaje. Consulta la referencia de RPC o la referencia de REST

Cuando creas un viaje, puedes proporcionar el number_of_passengers, el dropoff_point y el vehicle_id. Aunque estos campos no son obligatorios, se conservarán si los proporcionas. Se ignoran todos los demás campos Viaje. Por ejemplo, todos los viajes comienzan con un trip_status de NEW, incluso si pasas un trip_status de CANCELED en la solicitud de creación.

Ejemplo

En el siguiente ejemplo, se crea un viaje al Grand Indonesia East Mall. El viaje es exclusivo para dos pasajeros. El provider_id de Trip debe ser el mismo que el ID del proyecto. En el ejemplo, el proveedor de transporte compartido creó el proyecto de Google Cloud, project-id. Este proyecto debe tener las cuentas de servicio que se usan para llamar a Fleet Engine. El estado del viaje es NEW.

Más tarde, después de que el servicio asocia el viaje a un vehículo, puede llamar a UpdateTrip y cambiar el vehicle_id cuando el viaje se asigna a un vehículo.

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

Consulta la referencia de providers.trips.create.

Java

static final String PROJECT_ID = "project-id";

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
Trip trip = Trip.newBuilder()
    .setTripType(TripType.EXCLUSIVE) // Use TripType.SHARED for carpooling
    .setPickupPoint(                 // Grand Indonesia East Mall
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
    // Provide the number of passengers if available.
    .setNumberOfPassengers(2)
    // Provide the drop-off point if available.
    .setDropoffPoint(
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.1275).setLongitude(106.6537)))
    .build();

CreateTripRequest createTripRequest =
    CreateTripRequest.newBuilder()  // no need for the header
        .setParent(parent)
        .setTripId("tid-1f97")  // Trip ID assigned by the Provider
        .setTrip(trip)              // Initial state
        .build();

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

try {
  Trip createdTrip =
      tripService.createTrip(createTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

Registros de Google Cloud Platform para la creación de viajes

La API de Fleet Engine escribe una entrada de registro mediante los registros de la plataforma de Google Cloud cuando se recibe una llamada al extremo CreateTrip. La entrada de registro incluye información sobre los valores de la solicitud CreateTrip. Si la llamada se ejecuta correctamente, también incluirá información sobre el Trip que se mostró.

Instructivo: Actualiza un viaje

La entidad Trip contiene campos que permiten el seguimiento por parte del servicio y para informar el progreso del viaje a través del SDK del controlador y al SDK de consumidor. Para actualizar las propiedades, usa un mensaje UpdateTripRequest. Esto actualizará los campos Viaje según el field_mask de la solicitud. Consulta UpdateTripRequest.

El proveedor de transporte compartido es responsable de actualizar los siguientes atributos:

  • Estado del viaje.
  • El ID del vehículo. Esto ocurre en el momento de la creación o después de hacer coincidir el vehículo con un viaje.
  • Cambios en el punto de partida, el destino o los puntos de referencia.

Fleet Engine actualiza automáticamente los siguientes campos cuando usas la función de recorrido compartido a través del SDK de Drive o del consumidor:

  • Rutas
  • ETA
  • Distancia restante
  • Ubicación del vehículo
  • Puntos de referencia restantes

Consulta Trip en RPC o Resource.Trip en REST.

Registros de Google Cloud Platform para las actualizaciones de viaje

La API de Fleet Engine escribe una entrada de registro mediante los registros de la plataforma de Google Cloud cuando se recibe una llamada al extremo UpdateTrip. La entrada de registro incluye información sobre los valores de la solicitud UpdateTrip. Si la llamada se ejecuta correctamente, también incluirá información sobre el objeto Trip que se mostró.

Instructivo: Busca viajes

Fleet Engine admite la búsqueda de viajes. Como se mencionó anteriormente, un Viaje se borra automáticamente después de siete días, por lo que SearchTrips no muestra un historial completo de todos los Viajes.

Si bien SearchTrips es una API flexible, en la siguiente lista se consideran dos casos de uso.

  • Determina los viajes activos de un vehículo: El Proveedor puede determinar los viajes activos actualmente de un vehículo. Dentro de SearchTripsRequest, vehicle_id se establece en el vehículo en cuestión y active_trips_only debe establecerse en true.

  • Conciliación del estado del proveedor y del motor de flota: El proveedor puede usar SearchTrips para garantizar que el estado de su Viaje y el de Fleet Engine coincidan. Esto es muy importante para TripStatus. Si el estado de un viaje asignado a un vehículo no está configurado correctamente como COMPLETE o CANCELED, el vehículo no se incluye en SearchVehicles.

Para usar SearchTrips de esta manera, deja vehicle_id vacío, configura active_trips_only como true y minimum_staleness en una hora mayor que la duración de la mayoría de los viajes. Por ejemplo, puedes usar una hora. Los resultados incluyen Viajes que no están COMPLETOS ni CANCELADOS y que no se actualizaron en más de una hora. El proveedor debe examinar estos viajes para asegurarse de que su estado en Fleet Engine se actualice de forma correcta.

Solución de problemas

En el caso de un error DEADLINE_EXCEEDED, el estado de Fleet Engine se desconoce. El proveedor debe volver a llamar a CreateTrip, que muestra un error 201 (CREATED) o 409 (CONFLICT). En el último caso, la solicitud anterior se realizó correctamente antes del DEADLINE_EXCEEDED. Consulta las guías de la API del consumidor para obtener más información para manejar los errores de viaje: Android o iOS.

Asistencia para viajes compartidos

Puedes asignar varios viajes con SHARED a un vehículo que admita TripType.SHARED. Cuando asignas el vehicle_id para un viaje compartido (en una solicitud CreateTrip o UpdateTrip), debes especificar el orden de todos los puntos de referencia no pasados para todos los Viajes asignados al Vehículo en este viaje compartido a través de Trip.vehicle_waypoints. Consulta vehicle_waypoints para RPC o vehicleWaypoints para REST.

Compatibilidad con varios destinos

Identifica un destino intermedio

El campo intermediateDestinations y el campo intermediateDestinationIndex en Viaje (RPC | REST) se combinan para que se usen para indicar el destino.

Actualizar destino intermedio

Puedes actualizar los destinos intermedios a través de UpdateTrip. Cuando actualizas destinos intermedios, debes proporcionar una lista completa de ellos, incluidos los que se visitaron, no solo los que se agregaron recientemente o los que se modificarán. Cuando intermediateDestinationIndex apunte a un índice posterior a la posición de destino intermedio recién agregado o modificado, este no se agregará al waypoints ni al remainingWaypoints del Viaje. Esto se debe a que los destinos intermedios anteriores a intermediateDestinationIndex se tratan como ya visitados.

Cambios en el estado del viaje

El campo intermediateDestinationsVersion en (RPC | REST) es obligatorio en la solicitud de actualización del estado del viaje que se envía a Fleet Engine para indicar que se pasó un destino intermedio. El destino intermedio objetivo se especifica en el campo intermediateDestinationIndex. Cuando tripStatus (RPC | REST) es ENROUTE_TO_INTERMEDIATE_DESTINATION, un número entre [0..N-1] indica qué destino intermedio cruzará el vehículo. Cuando tripStatus es ARRIVED_AT_INTERMEDIATE_DESTINATION, un número entre [0..N-1] indica en qué destino intermedio se encuentra el vehículo.

Ejemplo

En el siguiente ejemplo de código, se muestra cómo actualizar el estado de un viaje para que se dirija a su primer destino intermedio, siempre que hayas creado un viaje con varios destinos y que este haya pasado su punto de partida.

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;
}

INSTRUCTIVO: Suscríbete a los mensajes de notificación de la API de Fleet Engine

La API de Fleet Engine usa Google Cloud Pub/Sub para publicar notificaciones sobre el tema creado por el proyecto de Google Cloud del consumidor. Pub/Sub no está habilitado de forma predeterminada para Fleet Engine en tu proyecto de Google Cloud. Presenta un caso de asistencia o comunícate con tu Ingeniero de Atención al cliente para habilitar Pub/Sub.

Para crear un tema en tu proyecto de Cloud, sigue estas instrucciones. El ID del tema debe ser “fleet_engine_notifications”.

El tema debe crearse en el mismo proyecto de Cloud que llama a las APIs de Fleet Engine.

Una vez que se cree el tema, deberás otorgarle permiso a la API de Fleet Engine para publicar en él. Para ello, haz clic en el tema que acabas de crear y agrega un permiso nuevo. Es posible que tengas que hacer clic en MOSTRAR PANEL DE INFORMACIÓN para abrir el editor de permisos. La principal debe ser geo-fleet-engine@system.gserviceaccount.com y el rol debe ser Pub/Sub publisher.

Si quieres configurar tu proyecto de Cloud para suscribirte a las notificaciones, sigue estas instrucciones

La API de Fleet Engine publicará cada notificación en dos formatos de datos diferentes: protobuf y json. El formato de los datos de cada notificación se indica en los atributos de PubsubMessage con la clave como data_format y el valor como protobuf o json.

Esquema de notificación:

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