Primeiros passos com o Fleet Engine

A API Fleet Engine On-Demand Rides and Deliveries permite gerenciar viagens e o estado do veículo para seus aplicativos Trip and Order Progress. Ele processa transações entre o SDK do driver, o SDK consumidor e o serviço de back-end, que pode se comunicar com o Fleet Engine fazendo chamadas gRPC ou REST.

Pré-requisitos

Para desenvolvimento, verifique se você instala o SDK do Cloud (gcloud) e está autenticado no seu projeto.

shell

gcloud auth login

Você verá uma mensagem de sucesso como esta:

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

Verifique se as APIs On Demand Rides and Deliveries Solution Fleet Engine estão configuradas corretamente.

shell

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

Se esse comando resultar em erro, entre em contato com o administrador do projeto e o representante do Suporte do Google para conseguir acesso.

Geração de registros

O Fleet Engine pode gravar mensagens de registro sobre as chamadas de API recebidas em registros do Google Cloud Platform. Consulte a documentação do Cloud Logging para ter uma visão geral de como ler e analisar registros.

A geração de registros pode não estar ativada por padrão para projetos criados antes de 10 de fevereiro de 2022. Consulte a documentação de geração de registros para mais detalhes.

Bibliotecas de cliente

Publicamos bibliotecas em várias linguagens de programação comuns. Essas bibliotecas vão ajudar a fornecer uma melhor experiência de desenvolvedor em relação a REST ou gRPC bruto. Para instruções sobre como receber bibliotecas de cliente para seu aplicativo de servidor, consulte Bibliotecas de cliente.

Os exemplos de Java nesta documentação pressupõem familiaridade com gRPC.

Autenticação e autorização

É possível configurar os recursos fornecidos pelo andamento de viagens e pedidos usando o Console do Google Cloud. Essas APIs e SDKs exigem o uso de JSON Web Tokens, assinados usando contas de serviço criadas no Console do Cloud.

Configuração do projeto do Cloud

Para configurar o projeto na nuvem, primeiro crie o projeto e, em seguida, crie as contas de serviço.

Para criar seu projeto do Google Cloud:

  1. Criar um projeto do Google Cloud usando o console do Google Cloud.
  2. Usando o painel de APIs e serviços, ative a API Local Rides and Deliveries.

As contas de serviço são associadas a um ou mais papéis. Eles são usados para criar JSON Web Tokens que concedem diferentes conjuntos de permissões, dependendo dos papéis. Normalmente, para reduzir a possibilidade de abuso, é possível criar várias contas de serviço, cada uma com o conjunto mínimo de papéis necessários.

O andamento da viagem e do pedido usa os seguintes papéis:

PapelDescrição
Usuário do SDK de consumidor do Fleet Engine

roles/fleetengine.consumerSdkUser
Concede permissão para pesquisar veículos e recuperar informações sobre veículos e viagens. Os tokens criados por uma conta de serviço com esse papel geralmente são usados nos seus dispositivos móveis de apps de consumo de transporte por aplicativo de transporte por aplicativo compartilhado ou de entrega.
Usuário do SDK do driver do Fleet Engine

roles/fleetengine.driverSdkUser
Concede permissão para atualizar os locais e trajetos de veículos e recuperar informações sobre veículos e viagens. Os tokens criados por uma conta de serviço com esse papel geralmente são usados nos seus dispositivos móveis do app de transporte por aplicativo ou motorista.
Administrador sob demanda do Fleet Engine

roles/fleetengine.ondemandAdmin
Concede permissão de leitura e gravação para todos os recursos de veículos e viagens. Os principais com esse papel não precisam usar JWTs e precisam usar o Application Default Credentials. As declarações JWT personalizadas são ignoradas. Esse papel precisa ser restrito a ambientes confiáveis (back-end do cliente).
Superusuário de serviço do FleetEngine **(DESCONTINUADO)**

roles/fleetengine.serviceSuperUser
Concede permissão a todas as APIs de veículos e viagens. Os tokens emitidos por uma conta de serviço com esse papel geralmente são usados nos seus servidores de back-end. Este papel foi suspenso. Prefira roles/fleetengine.ondemandAdmin.

Por exemplo, crie uma conta de serviço para cada um dos três papéis e atribua a eles os papéis de cada um.

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

Os SDKs do driver e do consumidor são criados com base nesses papéis padrão.

Como alternativa, é possível criar papéis personalizados que permitam que um conjunto arbitrário de permissões sejam agrupados. Os SDKs do driver e do consumidor vão mostrar mensagens de erro sempre que uma permissão necessária estiver ausente. Como resultado, é altamente recomendável usar o conjunto padrão de papéis apresentado acima e não usar papéis personalizados.

Por conveniência, se você precisar criar tokens JWT para clientes não confiáveis, adicione usuários ao papel de criador do token da conta de serviço para que eles criem tokens com as ferramentas de linha de comando gcloud.

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

Em que my-user@example.com é o e-mail usado para autenticação com a gcloud (gcloud auth list --format='value(account)').

Biblioteca de autenticação do Fleet Engine

O Fleet Engine usa JSON Web Tokens (JWTs) para restringir o acesso às APIs do Fleet Engine. A nova biblioteca de autenticação do Fleet Engine, disponível no GitHub (em inglês), simplifica a construção de JWTs do Fleet Engine e os assina com segurança.

A biblioteca oferece os seguintes benefícios:

  • Simplifica o processo de criação de tokens do Fleet Engine.
  • Fornece mecanismos de assinatura de token que não usam arquivos de credenciais (como a representação de uma conta de serviço).
  • Anexa tokens assinados a solicitações de saída feitas de um stub gRPC ou cliente GAPIC.

Criar um JSON Web Token (JWT) para autorização

Quando você não estiver usando a biblioteca de autenticação do Fleet Engine, os JSON Web Tokens (JWTs) precisam ser criados diretamente na sua base de código. Isso exige que você tenha um conhecimento profundo sobre os JWTs e a relação deles com o Fleet Engine. É por isso que recomendamos usar a biblioteca de autenticação do Fleet Engine.

No Fleet Engine, os JSON Web Tokens (JWTs) oferecem autenticação de curta duração e garantem que os dispositivos modifiquem apenas veículos, viagens ou tarefas autorizados. Os JWTs contêm um cabeçalho e uma seção de declaração. A seção do cabeçalho contém informações como a chave privada a ser usada (recebida das contas de serviço) e o algoritmo de criptografia. A seção de reivindicação contém informações como o horário de criação do token, a vida útil dos tokens, os serviços aos quais ele está reivindicando acesso e outras informações de autorização para reduzir o escopo do acesso, como o ID do veículo.

Uma seção de cabeçalho JWT contém os seguintes campos:

FieldDescrição
alg O algoritmo a ser usado. "RS256".
typ O tipo de token. "JWT".
criança ID da chave privada da conta de serviço. Esse valor está no campo "private_key_id" do arquivo JSON da conta de serviço. Use uma chave de uma conta de serviço com o nível correto de permissões.

Uma seção de declarações JWT contém os seguintes campos:

FieldDescrição
iss Endereço de e-mail da sua conta de serviço.
o Pub/Sub. Endereço de e-mail da sua conta de serviço.
aud O SERVICE_NAME da sua conta de serviço, neste caso https://fleetengine.googleapis.com/
iat O carimbo de data/hora em que o token foi criado, especificado em segundos desde 00:00:00 UTC, 1o de janeiro de 1970. Aguarde 10 minutos para o desvio. Se o carimbo de data/hora estiver muito no passado ou no futuro, o servidor poderá informar um erro.
exp O carimbo de data/hora de expiração do token, especificado em segundos desde 00:00:00 UTC, 1o de janeiro de 1970. A solicitação falhará se o carimbo de data/hora tiver mais de uma hora no futuro.
autorização Dependendo do caso de uso, pode conter `vehicleid` ou `tripid`.

A criação de um token JWT se refere a assiná-lo. Para instruções e exemplos de código para criar e assinar o JWT, consulte Autorização da conta de serviço sem OAuth. Em seguida, anexe um token assinado às chamadas gRPC ou outros métodos usados para acessar o Fleet Engine.

Declarações JWT

Ao criar o payload do JWT, adicione outra declaração na seção de autorização com a chave vehicleid ou tripid definida como o valor do ID do veículo ou da viagem em que a chamada está sendo feita.

O SDK do motorista sempre usa a declaração vehicleid, seja em uma viagem ou veículo. O back-end do Fleet Engine garante que o veículo esteja associado à viagem solicitada antes de fazer a modificação.

O SDK do consumidor sempre usa a declaração tripid.

O provedor de serviço de transporte por aplicativo ou de entrega precisa usar vehicleid ou tripid com um "*" para corresponder a todos os veículos e viagens. O JWT pode conter os dois tokens, mesmo que não sejam necessários, o que pode simplificar a implementação da assinatura de tokens.

Casos de uso do JWT

Veja a seguir um token de exemplo para o servidor do provedor:

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

Veja a seguir um token de exemplo para o App para o 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"
   }
}

Confira a seguir um token de exemplo para o app do motorista:

{
  "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"
   }
}
  • No campo kid do cabeçalho, especifique o ID da chave privada da conta de serviço. Esse valor está no campo private_key_id do arquivo JSON da conta de serviço.
  • Nos campos iss e sub, especifique o endereço de e-mail da sua conta de serviço. Esse valor está no campo client_email do arquivo JSON da conta de serviço.
  • No campo aud, especifique https://SERVICE_NAME/.
  • Para o campo iat, use o carimbo de data/hora em que o token foi criado, especificado como segundos decorridos desde 00:00:00 UTC, 1o de janeiro de 1970. Aguarde 10 minutos para o desvio. Se o carimbo de data/hora estiver muito no passado ou no futuro, o servidor informará um erro.
  • No campo exp, use o carimbo de data/hora da expiração do token, especificado em segundos desde 1o de janeiro de 1970, 00:00:00 UTC. O valor máximo permitido é iat + 3.600.

Ao assinar o JWT que será transmitido para um dispositivo móvel, use a conta de serviço para o papel do SDK de consumidor ou de driver. Caso contrário, o dispositivo móvel poderá mudar o estado que não deveria.

Da mesma forma, ao assinar o JWT que será usado para chamadas privilegiadas, use a conta de serviço com o papel de superusuário. Caso contrário, a operação vai falhar.

Como gerar um JWT para teste

Gerar tokens do terminal pode ser útil durante os testes.

Para seguir estas etapas, sua conta de usuário precisa ter o papel de criador de token de conta de serviço:

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

Crie um novo arquivo chamado unsigned_token.json com o conteúdo abaixo. A propriedade iat é o tempo atual em segundos após o período, que pode ser recuperado executando date +%s no terminal. A propriedade exp é o prazo de validade em segundos após o período, que pode ser calculado adicionando 3.600 a iat. O prazo de validade não pode ser superior a uma hora no 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": "*"
   }
}

Em seguida, execute o seguinte comando gcloud para assinar o token em nome da sua conta de serviço de superusuário:

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

Um JWT codificado em Base64 assinado agora será armazenado no arquivo signed_token.jwt. O token é válido para a próxima hora.

Agora é possível testar o token executando um comando curl no endpoint REST Listar veículos:

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

Veículos e o ciclo de vida deles

O veículo é a entidade que representa um par entre motorista e veículo. Atualmente, Motorista e Veículo não podem ser rastreados separadamente. O provedor de transporte por aplicativo ou de entrega cria um veículo usando um ID de provedor (que precisa ser igual ao ID do projeto do Google Cloud que contém a conta de serviço usada para chamar as APIs do Fleet Engine) e um ID de veículo do provedor de transporte por aplicativo ou de transporte por aplicativo.

Um veículo que não for atualizado pelo UpdateVehicle após sete dias será excluído automaticamente. É um erro chamar CreateVehicle com um par de ID do provedor/ID do veículo que já existe. O caso de veículos que não são atualizados com frequência pode ser resolvido de duas maneiras: chamar CreateVehicle frequentemente com um par esperado de ID de provedor/ID do veículo e descartar o erro se o veículo já existir; ou chamar CreateVehicle depois que um UpdateVehicle retornar com um erro NOT_FOUND.

Atualizações de localização de veículos

Para ter o melhor desempenho com o Fleet Engine, forneça um fluxo de atualizações de localização do veículo. Use uma das seguintes maneiras para fornecer essas atualizações:

  1. Use o SDK do Driver: Android e iOS, que é a opção mais simples.
  2. Use o código personalizado: útil se os locais forem transmitidos pelo seu back-end ou se você usar dispositivos que não sejam Android ou iOS.

Tipos de veículo

A entidade Vehicle contém um campo obrigatório de VehicleType, que contém um tipo enumerado de Category que pode ser especificado como AUTO, TAXI, TRUCK, TWO_WHEELER, BICYCLE ou PEDESTRIAN. O tipo de veículo pode servir como um critério de filtro em SearchVehicles e ListVehicles.

Todas as rotas de veículos usarão o RouteTravelMode correspondente se a categoria estiver definida como AUTO, TWO_WHEELER, BICYCLE ou PEDESTRIAN. Se a categoria for definida como TAXI ou TRUCK, o roteamento será tratado da mesma forma que o modo AUTO.

Atributos do veículo

A entidade "Veículo" contém um campo repetido de VehicleAttribute. Esses atributos não são interpretados pelo Fleet Engine. A API SearchVehicles inclui um campo para exigir que Vehicles correspondente contenha todos os atributos incluídos definidos para o valor especificado.

O campo do atributo é adicionado a vários outros campos aceitos na mensagem Vehicle, como vehicle_type e supported_trip_types.

waypoints restantes do veículo

A entidade Vehicle contém um campo repetido de TripWaypoint (RPC | REST), chamado waypoints(RPC | REST). Esse campo inclui os waypoints restantes nas viagens, na ordem em que o veículo os alcança. O Fleet Engine calcula esse campo à medida que as viagens são atribuídas ao veículo e o atualiza à medida que o status delas muda. Esses waypoints podem ser identificados pelos campos TripId e WaypointType.

Ampliar a qualificação de um veículo para correspondência

Normalmente, os serviços de transporte por aplicativo ou provedor de entrega são responsáveis por corresponder solicitações de viagem aos veículos. O serviço pode usar os atributos do veículo para incluí-lo em um número maior de pesquisas. Por exemplo, o provedor pode implementar um conjunto de atributos correspondentes aos níveis de benefícios ou recursos oferecidos pelo veículo. Por exemplo, três níveis podem ser um conjunto de atributos com valores booleanos: is_bronze_level, is_silver_level e is_gold_level. Um veículo pode ser qualificado para todos os três. Quando o Fleet Engine recebe uma solicitação para uma viagem que requer recursos do nível Prata, a pesquisa inclui esse veículo. O uso de atributos dessa maneira inclui veículos que oferecem uma variedade de recursos.

Há duas maneiras de atualizar os atributos do veículo. Uma é a API UpdateVehicle. Ao usar essa API, todo o conjunto de atributos do veículo é definido como o valor. Não é possível atualizar um único atributo. O outro método é a API UpdateVehicleAttributes. Esse método usa apenas os atributos a serem atualizados. Os atributos incluídos na solicitação serão definidos como o novo valor ou adicionados. Atributos não especificados não serão alterados.

TUTORIAL: Criar um veículo

É preciso criar uma entidade Vehicle para cada veículo que será rastreado na frota.

Use o endpoint CreateVehicle com o CreateVehicleRequest para criar um veículo.

O provider_id de Vehicle precisa ser o ID do projeto (por exemplo, my-on-demand-project) do projeto do Google Cloud que contém as contas de serviço que serão usadas para chamar o Fleet Engine. Embora várias contas de serviço possam acessar o Fleet Engine para o mesmo provedor de transporte por aplicativo ou provedor de entrega, o Fleet Engine atualmente não é compatível com contas de serviço de vários projetos do Google Cloud que acessam o mesmo Vehicles.

A Vehicle pode ser criada no estado OFFLINE ou ONLINE. Se ONLINE for criado, ele poderá ser retornado imediatamente em resposta a consultas SearchVehicles.

Um last_location inicial pode ser incluído na chamada CreateVehicle. Embora permitido, um Vehicle não pode ser criado no estado ONLINE sem um last_location.

Consulte Tipos de veículo para mais detalhes.

Consulte a seção Atributos do veículo para mais detalhes sobre o campo de atributos.

O valor retornado de CreateVehicle é a entidade Vehicle criada.

Exemplo

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

Consulte a referência 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 do Google Cloud Platform para criação de veículos

A API Fleet Engine grava uma entrada de registro usando os registros do Google Cloud Platform quando uma chamada para o endpoint CreateVehicle é recebida. A entrada de registro inclui informações sobre os valores na solicitação CreateVehicle. Se a chamada for bem-sucedida, ela também vai incluir informações sobre o Vehicle que foi retornado.

shell

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

Deve imprimir um registro semelhante ao seguinte:

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

Notificações do Cloud Pub/Sub para a criação de veículos

A API Fleet Engine publica uma notificação pelo Cloud Pub/Sub quando um novo veículo é criado. Para receber essas notificações, siga as instruções aqui.

Instruções: atualizar a localização de um veículo

Se você não estiver usando o SDK do Driver para atualizar a localização do veículo, poderá fazer uma chamada direta para o Fleet Engine com a localização do veículo. Para qualquer veículo ativo, o Fleet Engine espera uma atualização de local pelo menos uma vez por minuto e no máximo uma vez a cada cinco segundos. Essas atualizações exigem apenas privilégios de usuário do SDK do driver do Fleet Engine.

Exemplo

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

Consulte a referência 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.

Instruções: atualize outros campos do veículo

As atualizações de outros atributos do estado do veículo ocorrem com menos frequência do que as atualizações de posição. As atualizações de atributos diferentes de last_location exigem privilégios de superusuário do Fleet Engine.

O UpdateVehicleRequest inclui um update_mask para indicar quais campos atualizar. O comportamento do campo é igual ao da documentação do Protobuf para máscaras de campo.

Conforme observado em Atributos do veículo, a atualização do campo attributes exige que todos os atributos sejam gravados. Não é possível apenas atualizar o valor de um par de chave-valor em uma chamada UpdateVehicle. Para atualizar valores de atributos específicos, a API UpdateVehicleAttributes pode ser usada.

Exemplo

Este exemplo ativa 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

Consulte a referência 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 do Google Cloud Platform para atualizações de veículos

A API Fleet Engine grava uma entrada de registro usando os registros do Google Cloud Platform quando uma chamada para o endpoint UpdateVehicle é recebida. A entrada de registro inclui informações sobre os valores na solicitação UpdateVehicle. Se a chamada for bem-sucedida, ela também vai incluir informações sobre o Vehicle que foi retornado.

shell

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

Notificações do Cloud Pub/Sub para atualizações de veículos

A API Fleet Engine publica uma notificação pelo Cloud Pub/Sub quando um veículo atual é atualizado. Para receber essas notificações, siga as instruções aqui.

COMO FAZER: Pesquisar veículos

O Fleet Engine é compatível com a pesquisa de veículos. A API SearchVehicles permite que você encontre motoristas por perto que são mais adequados para uma tarefa, como atender a uma solicitação de viagem ou entrega. A API SearchVehicles retorna uma lista classificada de motoristas que correspondem aos atributos da tarefa com os atributos dos veículos da sua frota. Para mais informações, acesse Encontrar motoristas nas proximidades.

Exemplo

Ao pesquisar veículos disponíveis, o Fleet Engine exclui os veículos em viagens ativas por padrão. Os serviços do serviço de transporte por aplicativo ou do provedor de entrega precisam ser incluídos explicitamente nas solicitações de pesquisa. O exemplo a seguir mostra como incluir esses veículos em uma pesquisa que correspondam a uma viagem do Grand Indonesia East Mall para o Balai Sidang Jakarta Convention Center.

shell

Primeiro, atualize a localização do veículo que criamos nas etapas anteriores para que ele esteja qualificado. Em uma situação real, isso seria feito pelo SDK do Driver executado em um dispositivo Android ou iOS no veí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

A realização da pesquisa deve render pelo menos esse veí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

Consulte a referência 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 sobre filtragem de veículos

SearchVehicles e ListVehicles são compatíveis com filtragem em atributos do veículo usando uma consulta de filtro. Para conferir a sintaxe da consulta de filtro, acesse AIP-160 para conferir exemplos.

As consultas de filtro oferecem suporte APENAS à filtragem em atributos do veículo e não podem ser usadas para outros campos. A consulta de filtro funciona como uma cláusula AND com outras restrições, como minimum_capacity ou vehicle_types em SearchVehiclesRequest.

INSTRUÇÃO: listar veículos

O SearchVehicles é otimizado para encontrar um pequeno número de veículos na ordem de classificação muito rapidamente e é usado principalmente para encontrar motoristas próximos que são mais adequados para uma tarefa. No entanto, às vezes você quer encontrar todos os veículos que atendem a alguns critérios, mesmo que seja necessário percorrer os resultados. A ListVehicles foi projetada para esse caso de uso.

A API ListVehicles permite encontrar todos os veículos que atendem a algumas opções de solicitação específicas. A API ListVehicles retorna uma lista paginada de veículos no projeto que corresponde a alguns requisitos.

Para filtrar por atributos do veículo, consulte Consulta sobre filtros de veículos.

Exemplo

Este exemplo realiza a filtragem em vehicle_type e em atributos usando a string 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

Consulte a referência 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;
}

Viagens e o ciclo de vida delas

A API Trip e o ciclo de vida são semelhantes à API Vehicle e ao ciclo de vida. O provedor de transporte por aplicativo é responsável por criar viagens usando as interfaces do Fleet Engine. O Fleet Engine oferece um serviço de RPC, TripService, e recursos REST, provider.trips . Essas interfaces permitem a criação de entidades de viagem, solicitações de informações, funcionalidade de pesquisa e recursos de atualização.

Uma Trip tem um campo de status para acompanhar a progressão dela ao longo do ciclo de vida. Os valores são movidos de NEW para COMPLETE, mais CANCELED e UNKNOWN_TRIP_STATUS. Consulte trip_status para RPC ou TripStatus para REST.

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

Seu serviço pode atualizar a viagem para CANCELED usando qualquer um desses status. Quando o serviço cria uma viagem, o mecanismo define o status como NEW. Um vehicle_id é opcional. Assim como os veículos, os serviços excluem as viagens automaticamente após sete dias sem atualização. Se o serviço tentar criar uma viagem com um ID já existente, um erro será retornado. Uma viagem é considerada "ativa" quando está em um status diferente de COMPLETE ou CANCELED. Essa distinção é importante no campo active_trips na entidade veículo e SearchTripsRequest.

Seu serviço só pode mudar o vehicle_id atribuído a uma viagem quando ela está ativa. Por exemplo, faça isso quando um motorista cancela uma viagem durante o trajeto e ela é reatribuída a outro veículo.

O status é importante ao implementar o suporte para viagens de ida e volta. Esse suporte permite que o Provedor atribua uma nova viagem a um Veículo enquanto ele estiver em uma Viagem ativa. O código para criar uma viagem de ida e volta é igual ao de uma única viagem e usa o mesmo ID do veículo. O Fleet Engine adiciona a origem e o destino da nova viagem aos waypoints do veículo. Para mais informações sobre viagens de ida e volta, consulte Criar viagens com vários waypoints.

waypoints restantes da viagem

A entidade Trip contém um campo repetido de TripWaypoint (RPC | REST), chamado remainingWaypoints(RPC | REST). Este campo inclui todos os waypoints que o veículo precisa percorrer em ordem antes do ponto de desembarque final dessa viagem. O cálculo é feito com base nos waypoints restantes do veículo. Nos casos de uso "De ida e volta" e "Carona", essa lista contém waypoints de outras viagens que serão percorridas antes dessa viagem, mas exclui os waypoints depois dela. O waypoint na lista pode ser identificado por seus TripId e WaypointType.

A relação entre o status da viagem e os waypoints restantes do veículo

Os waypoints restantes do veículo (RPC | REST) serão atualizados quando o Fleet Engine receber uma solicitação de alteração do status da viagem. O waypoint anterior será removido da lista de waypoints restantes do veículo quando o tripStatus(RPC | REST) for alterado de outro status para ENROUTE_TO_XXX. Ou seja, quando o status da viagem é alterado de ENROUTE_TO_PICKUP para ARRIVED_AT_PICKUP, o ponto de embarque da viagem ainda fica na lista de waypoints restantes do veículo, mas quando o status da viagem é alterado para ENROUTE_TO_INTERMEDIATE_DESTINATION ou ENROUTE_TO_DROPOFF, os waypoints restantes são removidos.

É o mesmo para ARRIVED_AT_INTERMEDIATE_DESTINATION e ENROUTE_TO_INTERMDEDIATE_DESTINATION. Quando estiver em ARRIVED_AT_INTERMEDIATE_DESTINATION, o destino intermediário atual não será removido da lista de waypoints restantes do veículo até que ele informe que segue para o próximo waypoint.

Quando o status da viagem mudar para COMPLETED, nenhum waypoint desta viagem vai estar na lista de waypoints restantes do veículo.

COMO FAZER: Criar uma viagem

Uma entidade Trip precisa ser criada para que cada solicitação de viagem seja rastreada e associada aos veículos da frota. Use o endpoint CreateTrip com CreateTripRequest para criar uma viagem.

Os atributos a seguir são obrigatórios para criar uma viagem:

  • parent: uma string que inclui o ID do provedor criado quando o projeto do Google Cloud foi criado.
  • trip_id: uma string criada pelo provedor de serviço de transporte por aplicativo.
  • trip: contêiner com metadados básicos que descrevem a viagem.
    • trip_type: enum que representa se a viagem pode ter outros passageiros de origens e destinos diferentes no mesmo veículo (SHARED) ou somente para uma parte (EXCLUSIVE).
    • pickup_point: TerminalLocation que representa o ponto de origem da viagem. Consulte a referência da RPC ou a referência REST

Ao criar uma viagem, você pode fornecer number_of_passengers, dropoff_point e vehicle_id. Embora esses campos não sejam obrigatórios, se você os fornecer, eles serão mantidos. Todos os outros campos "Viagem" são ignorados. Por exemplo, todas as viagens começam com um trip_status de NEW, mesmo que você transmita um trip_status de CANCELED na solicitação de criação.

Exemplo

O exemplo a seguir cria uma viagem para o Grand Indonesia East Mall. A viagem tem capacidade para dois passageiros e é exclusiva. O provider_id de Trip precisa ser igual ao ID do projeto. No exemplo, ele criou o projeto do Google Cloud, project-id. Esse projeto precisa ter as contas de serviço usadas para chamar o Fleet Engine. O status da viagem é NEW.

Depois, depois de fazer a correspondência da viagem com um veículo, o serviço pode chamar UpdateTrip e mudar o vehicle_id quando a viagem for atribuída a um veí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

Consulte a referência 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 do Google Cloud Platform para criação de viagens

A API Fleet Engine grava uma entrada de registro usando os registros do Google Cloud Platform quando uma chamada para o endpoint CreateTrip é recebida. A entrada de registro inclui informações sobre os valores na solicitação CreateTrip. Se a chamada for bem-sucedida, ela também vai incluir informações sobre o Trip retornado.

TUTORIAL: Atualizar uma viagem

A entidade Trip contém campos que permitem o rastreamento pelo serviço e para informar a progressão da viagem pelo SDK do motorista e do SDK do consumidor. Para atualizar as propriedades, use a mensagem UpdateTripRequest. Isso atualiza os campos de viagem de acordo com o field_mask da solicitação. Consulte UpdateTripRequest.

O provedor de serviço de transporte por aplicativo é responsável por atualizar os seguintes atributos:

  • Status da viagem.
  • ID do veículo. No momento da criação ou depois de corresponder o veículo a uma viagem.
  • Alterações no embarque, desembarque ou waypoints.

O Fleet Engine atualiza automaticamente os seguintes campos ao usar o recurso de Compartilhamento de jornada pelo SDK do Driver ou do SDK do consumidor:

  • Rotas
  • HEC
  • Distância restante
  • Localização do veículo
  • Pontos de referência restantes

Consulte Trip em RPC ou Resource.Trip em REST.

Registros do Google Cloud Platform para atualizações de viagem

A API Fleet Engine grava uma entrada de registro usando os registros do Google Cloud Platform quando uma chamada para o endpoint UpdateTrip é recebida. A entrada de registro inclui informações sobre os valores na solicitação UpdateTrip. Se a chamada for bem-sucedida, ela também incluirá informações sobre o Trip retornado.

COMO FAZER: Pesquisar viagens

O Fleet Engine é compatível com a pesquisa de viagens. Conforme mencionado anteriormente, uma viagem é excluída automaticamente após sete dias. Portanto, o SearchTrips não expõe um histórico completo de todas as viagens.

Embora a SearchTrips seja uma API flexível, a lista abaixo considera dois casos de uso.

  • Determinação das viagens ativas de um veículo -- O provedor pode determinar as viagens atualmente ativas de um veículo. No SearchTripsRequest, o vehicle_id é definido como o veículo em questão, e o active_trips_only precisa ser definido como true.

  • Reconciliação do provedor e do estado do Fleet Engine: o provedor pode usar SearchTrips para garantir a correspondência entre o estado da viagem e o do Fleet Engine. Isso é especialmente importante para o TripStatus. Se o estado de uma viagem atribuído a um veículo não estiver definido corretamente como COMPLETE ou CANCELED, o veículo não será incluído em SearchVehicles.

Para usar SearchTrips dessa maneira, deixe vehicle_id em branco, defina active_trips_only como true e defina minimum_staleness como um horário maior do que a maioria das durações de viagem. Por exemplo, você pode usar uma hora. Os resultados incluem viagens que não foram CONCLUÍDAS nem CANCELADAS e não foram atualizadas há mais de uma hora. O provedor precisa examinar essas viagens para garantir que o status delas no Fleet Engine seja atualizado corretamente.

Solução de problemas

No caso de um erro DEADLINE_EXCEEDED, o estado da frota é desconhecido. O provedor precisa chamar CreateTrip novamente, que retorna 201 (CREATED) ou 409 (CONFLICT). No último caso, a solicitação anterior foi bem-sucedida antes de DEADLINE_EXCEEDED. Consulte os guias da API Consumer para mais informações sobre como lidar com erros de viagem: Android ou iOS.

Suporte de viagem do Waze

Você pode atribuir várias viagens SHARED a um veículo compatível com TripType.SHARED. Você precisa especificar a ordem de todos os waypoints não passados em todas as viagens atribuídas ao veículo nessa viagem compartilhada por Trip.vehicle_waypoints ao atribuir o vehicle_id para uma viagem compartilhada (em uma solicitação CreateTrip ou UpdateTrip). Consulte vehicle_waypoints para RPC ou vehicleWaypoints para REST.

Suporte a vários destinos

Identificar um destino intermediário

Os campos intermediateDestinations e intermediateDestinationIndex em Trip (RPC | REST) são combinados para serem usados para indicar o destino.

Atualizar destino intermediário

É possível atualizar os destinos intermediários com UpdateTrip. Ao atualizar destinos intermediários, você precisa fornecer uma lista completa de destinos intermediários, incluindo aqueles que foram visitados, não apenas o recém-adicionado ou a ser modificado. Quando o intermediateDestinationIndex aponta para um índice após a posição do destino intermediário recém-adicionado/modificado, o destino intermediário novo/atualizado não é adicionado ao waypoints do veículo ou ao remainingWaypoints do Trip. O motivo é que todos os destinos intermediários antes de intermediateDestinationIndex são tratados como já visitados.

Alterações no status da viagem

O campo intermediateDestinationsVersion em (RPC | REST) é obrigatório na solicitação de atualização do status de viagem enviada ao Fleet Engine para indicar que um destino intermediário foi transmitido. O destino intermediário pretendido é especificado pelo campo intermediateDestinationIndex. Quando tripStatus (RPC | REST) for ENROUTE_TO_INTERMEDIATE_DESTINATION, um número entre [0..N-1] indica qual destino intermediário o veículo cruzará em seguida. Quando tripStatus for ARRIVED_AT_INTERMEDIATE_DESTINATION, um número entre [0..N-1] indica em qual destino intermediário o veículo está.

Exemplo

O exemplo de código a seguir demonstra como atualizar o status de uma viagem para seguir até o primeiro destino intermediário, supondo que você tenha criado uma viagem com vários destinos e que ela tenha passado do ponto de embarque.

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

Instruções: inscreva-se para receber mensagens de notificação da API Fleet Engine

A API Fleet Engine usa o Google Cloud Pub/Sub para publicar notificações sobre o tópico criado pelo projeto de consumidor do Google Cloud. O Pub/Sub não está ativado por padrão para o Fleet Engine no seu projeto do Google Cloud. Registre um caso de suporte ou entre em contato com seu Engenheiro de clientes para ativar o Pub/Sub.

Para criar um tópico no projeto do Cloud, siga estas instruções. O ID do tópico precisa ser "fleet_engine_notifications".

O tópico precisa ser criado no mesmo projeto do Cloud que está chamando as APIs Fleet Engine.

Depois que o tópico for criado, será necessário conceder à API Fleet Engine a permissão para publicar no tópico. Para fazer isso, clique no tópico que você acabou de criar e adicione uma nova permissão. Talvez seja necessário clicar em MOSTRAR PAINEL DE INFORMAÇÕES para abrir o editor de permissões. O principal precisa ser geo-fleet-engine@system.gserviceaccount.com, e o papel precisa ser Pub/Sub publisher.

Para configurar seu projeto do Cloud para receber notificações, siga estas instruções.

A API Fleet Engine publicará cada notificação em dois formatos de dados diferentes, protobuf e json. O formato de dados de cada notificação é indicado nos atributos PubsubMessage, com a chave como data_format e o valor como protobuf ou json.

Esquema de notificação:

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