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

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

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 los comandos.

En comparación con las configuraciones de los dispositivos, 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 persistencia o conocimiento a lo largo del tiempo (configuraciones) o prefieres la velocidad o las directivas limitadas al tiempo (comandos).

Los comandos pueden ser útiles cuando quieres realizar las siguientes acciones:

  • 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)

En la actualidad, Cloud IoT Core solo admite comandos en MQTT (no HTTP).

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

Cloud IoT Core también admite configuraciones de dispositivos. Las configuraciones son más coherentes y permanentes que los comandos. La configuración persiste en Cloud IoT Core y, cuando se usa MQTT, la configuración más reciente se entrega finalmente a todos los dispositivos suscritos, incluso a los que se suscriben después.

La siguiente tabla puede ayudarte a decidir si usarás 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
Es persistente, por lo que 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 No hay relación ni 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, es de tamaño pequeño (máx. 64 KB) Hasta 256 KB
BLOB arbitrario definido por el usuario BLOB arbitrario 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 de forma indefinida, no debes esperar que los datos de estado o telemetría del dispositivo 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 son parte de los datos del dispositivo a largo plazo.

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

Cómo enviar un comando

Para enviar un comando a un dispositivo, usa Google Cloud Console, 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 de Google Cloud Console.

    Ir a la página Registros

  2. Haz clic en el ID del registro del dispositivo.
  3. En el menú de registro a la izquierda, haz 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 comando, 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 = JacksonFactory.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:

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

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 están en cola ni se conservan para dispositivos que se conectan y se suscriben más adelante.

Calidad del 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, el éxito significa 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 realiza 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, así como las confirmaciones por dispositivo, se registran en Cloud Logging.

Precios

Los comandos se facturan como todos los demás mensajes enviados mediante MQTT. Para obtener más detalles, consulta Precios.