O Google Cloud IoT Core será desativado em 16 de agosto de 2023. Entre em contato com sua equipe de conta do Google Cloud para mais informações.

Como enviar comandos para dispositivos

É possível usar o Cloud IoT Core para enviar comandos a dispositivos. Os comandos são diretivas temporárias, únicas, enviadas para dispositivos conectados ao Cloud IoT Core e inscritos no tópico de comandos.

Em comparação com as configurações do dispositivo, os comandos são mais rápidos, podem ser enviados com mais frequência e são independentes de outros recursos do Cloud IoT Core. Ao escolher entre comandos e configurações, considere se você precisa de persistência/conhecimento ao longo do tempo (configurações) ou se prefere diretivas de velocidade e/ou tempo (comandos).

Os comandos podem ser úteis quando você quer:

  • Enviar mensagens rapidamente para vários dispositivos em um horário específico
  • Enviar mensagens de grande volume para muitos dispositivos em um horário específico
  • Enviar diretivas com prazo limitado que precisam expirar
  • Enviar configurações de dispositivo incrementais

Os comandos têm as seguintes características:

  • Enviado diretamente para os dispositivos conectados e inscritos
  • Não persistido no Cloud IoT Core
  • Ignorado para dispositivos que não estão inscritos e conectados no momento em que o comando é enviado.
  • Não é exclusivo (cópias podem ser enviadas, embora isso seja improvável)
  • Não são enviados em uma ordem específica (mas são entregues aproximadamente na ordem de envio).
  • Em qualquer formato (blob de dados)

Atualmente, o Cloud IoT Core é compatível com comandos apenas no MQTT (não HTTP).

Comandos em comparação com configurações

O Cloud IoT Core também é compatível com configurações de dispositivo. As configurações são mais consistentes e permanentes do que os comandos. As configurações são mantidas no Cloud IoT Core e, ao usar o MQTT, a configuração mais recente é entregue a todos os dispositivos inscritos, mesmo os que se inscreverão mais tarde.

A tabela a seguir pode ajudá-lo a decidir se quer usar um comando ou uma configuração:

Configurações Comandos
A configuração mais recente é repetida até ser entregue (MQTT) Nova tentativa de QoS 1, mas não há garantia de entrega
persistente; portanto, se um dispositivo se conectar (MQTT) ou pesquisas (HTTP) posteriormente, a configuração mais recente ainda será entregue; Não persistente; entregue apenas para os dispositivos conectados no momento em que o comando é enviado
Cada nova versão substitui a anterior Sem relacionamento nem ordem entre os comandos
Informa a um dispositivo o que "ser". corresponde ao estado no Cloud IoT Core Informa ao dispositivo o que fazer em um momento específico
Latência maior Latência menor
Normalmente pequenas (máximo de 64 KB) Até 256 KB
Arbitrário, blob definido pelo usuário Arbitrário, blob definido pelo usuário
1 atualização por segundo, por dispositivo 1.000 por segundo, por projeto (configurável)
2.500 por segundo, por registro

Como os comandos não são mantidos no Cloud IoT Core e não são repetidos indefinidamente, a telemetria de dispositivos ou os dados de estado não refletem um comando específico. O dispositivo pode não ter recebido o comando ou pode ter recebido comandos ou configurações subsequentes. Os comandos devem ser temporários e não fazem parte dos dados do dispositivo em longo prazo.

Para gerenciar a ordem dos comandos e as cópias, use a lógica do dispositivo ou aplicativos cliente.

Como enviar um comando

Para enviar um comando a um dispositivo, use o console do Google Cloud, a gcloud ou a API Cloud IoT Core.

Console

Enviar um comando para um dispositivo

  1. Acesse a página Registros no Console do Google Cloud.

    Acessar a página Registros

  2. Clique no ID do registro do dispositivo.
  3. No menu de registro à esquerda, clique em Dispositivos.
  4. Clique no ID do dispositivo a que você quer enviar o comando.
  5. Na parte superior da página, clique em Enviar comando.
  6. Selecione o formato do comando:

    • Texto
    • Base64
  7. No campo Dados de comando, digite o comando.

  8. No campo opcional Subpasta, digite o nome de uma subpasta para este comando. Os dispositivos inscritos no tópico curinga receberão comandos enviados para subpastas.

  9. Clique em Enviar comando.

gcloud

Para enviar um comando a um dispositivo, execute o comando gcloud iot devices commands send:

gcloud iot devices commands send \
    { --command-file=COMMAND_FILE | --command-data=COMMAND_DATA } \
    --region=REGION  \
    --registry=REGISTRY_ID \
    --device=DEVICE_ID \
    [--subfolder=SUBFOLDER]\

Se os dados do comando contiver caracteres especiais, use --command-file em vez de --command-data

API

Use o método SendCommandToDevice para enviar um comando.

C#

public static object SendCommand(string deviceId, string projectId,
    string cloudRegion, string registryName, string data)
{
    var cloudIot = CreateAuthorizedClient();

    var devicePath = String.Format("projects/{0}/locations/{1}/registries/{2}/devices/{3}",
        projectId, cloudRegion, registryName, deviceId);
    // Data sent through the wire has to be base64 encoded.
    SendCommandToDeviceRequest req = new SendCommandToDeviceRequest()
    {
        BinaryData = Convert.ToBase64String(Encoding.UTF8.GetBytes(data))
    };

    Console.WriteLine("Sending command to {0}\n", devicePath);

    var res =
        cloudIot.Projects.Locations.Registries.Devices.SendCommandToDevice(req, devicePath).Execute();

    Console.WriteLine("Command response: " + res.ToString());
    return 0;
}

Go


// sendCommand sends a command to a device listening for commands.
func sendCommand(w io.Writer, projectID string, region string, registryID string, deviceID string, sendData string) (*cloudiot.SendCommandToDeviceResponse, error) {
	// Authorize the client using Application Default Credentials.
	// See https://g.co/dv/identity/protocols/application-default-credentials
	ctx := context.Background()
	httpClient, err := google.DefaultClient(ctx, cloudiot.CloudPlatformScope)
	if err != nil {
		return nil, err
	}
	client, err := cloudiot.New(httpClient)
	if err != nil {
		return nil, err
	}

	req := cloudiot.SendCommandToDeviceRequest{
		BinaryData: b64.StdEncoding.EncodeToString([]byte(sendData)),
	}

	name := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, deviceID)

	response, err := client.Projects.Locations.Registries.Devices.SendCommandToDevice(name, &req).Do()
	if err != nil {
		return nil, err
	}

	fmt.Fprintln(w, "Sent command to device")

	return response, nil
}

Java

protected static void sendCommand(
    String deviceId, String projectId, String cloudRegion, String registryName, String data)
    throws GeneralSecurityException, IOException {
  GoogleCredentials credential =
      GoogleCredentials.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
  HttpRequestInitializer init = new HttpCredentialsAdapter(credential);
  final CloudIot service =
      new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init)
          .setApplicationName(APP_NAME)
          .build();

  final String devicePath =
      String.format(
          "projects/%s/locations/%s/registries/%s/devices/%s",
          projectId, cloudRegion, registryName, deviceId);

  SendCommandToDeviceRequest req = new SendCommandToDeviceRequest();

  // Data sent through the wire has to be base64 encoded.
  Base64.Encoder encoder = Base64.getEncoder();
  String encPayload = encoder.encodeToString(data.getBytes(StandardCharsets.UTF_8.name()));
  req.setBinaryData(encPayload);
  System.out.printf("Sending command to %s%n", devicePath);

  service
      .projects()
      .locations()
      .registries()
      .devices()
      .sendCommandToDevice(devicePath, req)
      .execute();

  System.out.println("Command response: sent");
}

Node.js

// const cloudRegion = 'us-central1';
// const deviceId = 'my-device';
// const commandMessage = 'message for device';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const iot = require('@google-cloud/iot');
const iotClient = new iot.v1.DeviceManagerClient({
  // optional auth parameters.
});

async function sendCommand() {
  // Construct request
  const formattedName = iotClient.devicePath(
    projectId,
    cloudRegion,
    registryId,
    deviceId
  );

  const binaryData = Buffer.from(commandMessage);

  const request = {
    name: formattedName,
    binaryData: binaryData,
  };

  const [response] = await iotClient.sendCommandToDevice(request);
  console.log('Sent command: ', response);
}

sendCommand();

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;

/**
 * Sends a command to a device.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $deviceId IOT Device ID
 * @param string $command The command sent to a device
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function send_command_to_device(
    $registryId,
    $deviceId,
    $command,
    $projectId,
    $location = 'us-central1'
) {
    print('Sending command to device' . PHP_EOL);

    // Instantiate a client.
    $deviceManager = new DeviceManagerClient();
    $deviceName = $deviceManager->deviceName($projectId, $location, $registryId, $deviceId);

    // Response empty on success
    $deviceManager->sendCommandToDevice($deviceName, $command);

    printf('Command sent' . PHP_EOL);
}

Python

print("Sending command to device")
client = iot_v1.DeviceManagerClient()
device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

# command = 'Hello IoT Core!'
data = command.encode("utf-8")

return client.send_command_to_device(
    request={"name": device_path, "binary_data": data}
)

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry containing the device to send commands to"
# device_id   = "The identifier of the device to send commands to"
# data        = "The command, e.g. {move: forward} to send to the device"

require "google/apis/cloudiot_v1"

# Initialize the client and authenticate with the specified scope
Cloudiot   = Google::Apis::CloudiotV1
iot_client = Cloudiot::CloudIotService.new
iot_client.authorization = Google::Auth.get_application_default(
  "https://www.googleapis.com/auth/cloud-platform"
)

# The resource name of the location associated with the project
parent   = "projects/#{project_id}/locations/#{location_id}"
resource = "#{parent}/registries/#{registry_id}/devices/#{device_id}"

command_req = Cloudiot::SendCommandToDeviceRequest.new
command_req.binary_data = data

# Set configuration for the provided device
iot_client.send_project_location_registry_device_command_to_device resource, command_req

puts "Command sent!"

Como receber um comando

Para receber um comando, o dispositivo precisa:

  • Estar conectado ao Cloud IoT Core usando o protocolo MQTT
  • ser inscrito no tópico MQTT /devices/{device-id}/commands/# (o caractere curinga # é obrigatório);

Quando você faz a assinatura do tópico com caracteres curinga, o dispositivo recebe comandos enviados para devices/{device-id}/commands, além de comandos enviados para subpastas (como devices/{device-id}/commands/{subfolder}). Não é possível assinar uma subpasta específica.

Os comandos são entregues a dispositivos que estão conectados e inscritos naquele momento específico. Elas não são enfileiradas ou preservadas para dispositivos que se conectam e se inscrevem posteriormente.

Qualidade de Serviço (QoS, na sigla em inglês)

A entrega de comandos depende do nível de QoS que você está usando:

Nível de QoS Garantia
0 Sem garantia (somente melhor esforço), mesmo quando a solicitação retornar OK
1 Entrega do tipo "pelo menos uma vez" garantida se a solicitação sendCommandtoDevice retornar OK

Em outras palavras, no QoS 0, uma mensagem é considerada bem-sucedida assim que é enviada, independentemente da resposta do dispositivo. Na QoS 1, o sucesso significa que o dispositivo confirmou a entrega da mensagem. Observe que a entrega "pelo menos uma vez" significa que o dispositivo pode receber o comando várias vezes. O Cloud IoT Core não rastreia quantas vezes o comando foi recebido.

Erros

  • Se o tempo limite do comando (60 segundos, conforme indicado em Cotas e limites) for atingido, DEADLINE_EXCEEDED será retornado.

  • Se o dispositivo não estiver conectado ou estiver conectado, mas não estiver inscrito no tópico de caracteres curinga MQTT, FAILED_PRECONDITION será retornado.

Geração de registros

Os comandos enviados e as confirmações por dispositivos são registrados no Cloud Logging.

Preços

Os comandos são cobrados como todas as outras mensagens enviadas por MQTT. Para mais detalhes, consulte Preços.