Google Cloud IoT Core se retirará el 16 de agosto de 2023. Comunícate con el equipo de cuentas de Google Cloud para obtener más información.

Envía comandos a dispositivos

Puedes usar Cloud IoT Core para enviar comandos a dispositivos. Los comandos son directivas transitorias y únicas que se envían a dispositivos conectados a Cloud IoT Core y suscritos al tema de comandos.

En comparación con las configuraciones del dispositivo, los comandos son más rápidos, se pueden enviar con más frecuencia y son independientes de otras funciones de Cloud IoT Core. Cuando elijas entre comandos y configuraciones, considera si necesitas perseverancia o conocimiento en el tiempo (configuraciones) o prefieres la velocidad o las directivas con límites de tiempo (comandos).

Los comandos pueden ser útiles en los siguientes casos:

  • Enviar mensajes rápidamente a muchos dispositivos en un momento específico
  • Enviar mensajes de gran volumen a muchos dispositivos a la vez
  • Enviar directivas con límite de tiempo que venzan
  • Enviar configuración incremental de dispositivo

Los comandos tienen las siguientes características:

  • Se envían directamente a dispositivos suscritos y conectados
  • No se conservan en Cloud IoT Core
  • Se descartan para dispositivos que no están suscritos y conectados cuando se envía el comando
  • No son únicos (se pueden enviar duplicados, aunque esto es poco probable)
  • No se envían en ningún orden en particular (pero se entregan aproximadamente en el orden de envío)
  • En cualquier formato (BLOB de datos)

Actualmente, Cloud IoT Core es compatible con los comandos solo en MQTT (no HTTP).

Comandos en comparación con parámetros de configuración

Cloud IoT Core también es compatible con las configuraciones de los dispositivos. Los parámetros de configuración son más coherentes y permanentes que los comandos. La configuración se conserva en Cloud IoT Core y, cuando se usa MQTT, la configuración más reciente se entrega a todos los dispositivos suscritos, incluso a los que se suscriben después.

La siguiente tabla puede ayudarte a decidir si usar un comando o una configuración:

Configuraciones Comandos
Se reintenta la configuración más reciente hasta que se entrega (MQTT) Se reintenta para QoS 1, pero no se garantiza que se entregue
Por lo tanto, si un dispositivo se conecta (MQTT) o sondea (HTTP) más tarde, se entregará la configuración más reciente. No persistente. Se entrega solo a los dispositivos conectados en el momento en que se envía el comando
Cada versión nueva reemplaza a la versión anterior. Sin relación o orden entre los comandos
Le indica a un dispositivo qué debe "ser"; corresponde al estado en Cloud IoT Core Le indica a un dispositivo qué "hacer" en un momento específico
Mayor latencia Menor latencia
Por lo general, son pequeños (tamaño máximo: 64 KB). Hasta 256 KB
BLOB arbitrario y definido por el usuario BLOB arbitrario y definido por el usuario
1 actualización por segundo por dispositivo 1,000 por segundo, por proyecto (configurable)
2,500 por segundo, por registro

Debido a que los comandos no persisten en Cloud IoT Core y no se reintentan indefinidamente, no debes esperar que la telemetría del dispositivo o los datos de estado reflejen un comando en particular. Es posible que el dispositivo no haya recibido el comando o que haya recibido comandos o configuraciones posteriores. Los comandos están diseñados para ser transitorios y no forman parte de datos de dispositivos a largo plazo.

Para administrar el orden de los comandos y los duplicados, usa la lógica del dispositivo o las aplicaciones cliente.

Envía un comando

Para enviar un comando a un dispositivo, usa la consola de Google Cloud, gcloud o la API de Cloud IoT Core.

Consola

Para enviar un comando a un dispositivo, haz lo siguiente:

  1. Ve a la página Registros en la consola de Google Cloud.

    Ir a la página Registros

  2. Haga clic en el ID del registro del dispositivo.
  3. En el menú de registro ubicado a la izquierda, haga clic en Dispositivos.
  4. Haz clic en el ID del dispositivo al que deseas enviar el comando.
  5. En la parte superior de la página, haz clic en Enviar comando.
  6. Selecciona el formato del comando:

    • Texto
    • Base64
  7. En el campo Datos de comandos, ingresa el comando.

  8. En el campo opcional Subcarpeta, ingresa el nombre de una subcarpeta para este comando. Los dispositivos que están suscritos al tema comodín recibirán comandos que se enviarán a las subcarpetas.

  9. Haz clic en Enviar comando.

gcloud

Para enviar un comando a un dispositivo, ejecuta el 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]\

Si los datos del comando contienen caracteres especiales, usa --command-file en lugar de --command-data.

API

Usa el método SendCommandToDevice para enviar un 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!"

Recibe un comando

Para recibir un comando, el dispositivo debe cumplir estos requisitos:

  • Estar conectado a Cloud IoT Core con el protocolo MQTT
  • Estar suscrito al tema MQTT /devices/{device-id}/commands/# (se requiere el comodín #)

Cuando se suscriba al tema comodín, el dispositivo recibirá comandos enviados a devices/{device-id}/commands, así como comandos enviados a subcarpetas (como devices/{device-id}/commands/{subfolder}). No se admite la suscripción a una subcarpeta específica.

Los comandos se entregan a los dispositivos que están conectados y suscritos en ese momento específico. No se ponen en cola ni se conservan para dispositivos que se conectan y se suscriben más adelante.

Calidad de servicio (QoS)

La entrega de comandos depende del nivel de QoS que uses:

Nivel de QoS Garantía
0 No se garantiza (solo el mejor esfuerzo), incluso cuando la solicitud muestra OK
1 Entrega al menos una vez garantizada si la solicitud sendCommandtoDevice muestra OK

En otras palabras, en QoS 0, un mensaje se considera exitoso en cuanto se envía, sin importar la respuesta del dispositivo. En QoS 1, la ejecución correcta indica que el dispositivo confirmó la entrega del mensaje. Ten en cuenta que la entrega “al menos una vez” significa que el dispositivo puede recibir el comando varias veces. Cloud IoT Core no hace un seguimiento de cuántas veces se recibió el comando.

Errores

  • Si se alcanza el tiempo de espera del comando (60 s, como se indica en Cuotas y límites), se muestra DEADLINE_EXCEEDED.

  • Si el dispositivo no está conectado, o está conectado, pero no está suscrito al tema comodín de MQTT, se muestra FAILED_PRECONDITION.

Registros

Los comandos que se envían a los dispositivos y las confirmaciones de estos se registran en Cloud Logging.

Precios

Los comandos se facturan como todos los otros mensajes que se envían a través de MQTT. Para obtener más información, consulta Precios.