Acquisizione dello stato dei dispositivi

Con Cloud IoT Core, puoi monitorare lo stato di ogni dispositivo connesso. Lo stato viene riportato dal dispositivo come dati binari. Gli aggiornamenti dello stato del dispositivo sono in genere attivati da una modifica del dispositivo, che può essere un aggiornamento della configurazione di Cloud IoT Core o una modifica simile proveniente da un'altra origine esterna, ad esempio un aggiornamento del firmware.

Lo stato del dispositivo è diverso dalla configurazione del dispositivo. I dati di configurazione vengono inviati al dispositivo da Cloud IoT Core. I dati di stato vengono inviati dal dispositivo a Cloud IoT Core. La configurazione può essere considerata un'istruzione esterna e lo stato è una rappresentazione interna.

Cloud IoT Core può aiutarti a rispondere a domande di base su configurazione e stato: cosa dovrebbe fare il dispositivo attualmente? Quali sono le differenze con la configurazione più recente del dispositivo?

Limiti

Gli aggiornamenti di stato sono limitati a 1 aggiornamento al secondo per dispositivo. Tuttavia, per risultati migliori, lo stato del dispositivo dovrebbe essere aggiornato molto meno spesso, al massimo una volta ogni 10 secondi.

La frequenza di aggiornamento viene calcolata come il tempo che intercorre tra l'accettazione del server più recente e la richiesta di aggiornamento successiva.

Segnala lo stato del dispositivo

Bridge MQTT

Per segnalare lo stato a Cloud IoT Core tramite il bridge MQTT, pubblica messaggi nell'argomento /devices/DEVICE_ID/state MQTT. Puoi selezionare un argomento Cloud Pub/Sub per archiviare gli eventi di stato quando crei o aggiorni un registro.

Per maggiori dettagli, consulta la sezione Pubblicazione tramite bridge MQTT.

Bridge HTTP

Per segnalare lo stato a Cloud IoT Core tramite il bridge HTTP, i dispositivi devono utilizzare una richiesta setState. I dati dello stato binario vengono passati nel corpo della richiesta come stringa con codifica base64.

Per maggiori dettagli, consulta la sezione Pubblicare su bridge HTTP.

Recupero dei dati sullo stato del dispositivo

Questa sezione spiega come ottenere i dati di stato che vengono segnalati a Cloud IoT Core dai dispositivi. I dispositivi stessi non possono leggere i dati di stato dal cloud.

I dati sullo stato vengono restituiti in formato binario. I dati relativi allo stato possono avere una struttura diversa da quella dei dati di configurazione che attivano la modifica dello stato.

Ad esempio, supponiamo che tu abbia un dispositivo con diversi ventilatori. I dati di configurazione potrebbero essere un oggetto JSON contenente un semplice valore booleano che abilita o disabilita il raffreddamento:

Esempio di dati di configurazione

{
  'cooling': true
}

Tuttavia, i dati di stato del dispositivo potrebbero includere informazioni diagnostiche, nonché i dati della ventola che ti aspetteresti di avere in risposta a una modifica di 'cooling':

Esempio di dati statali

{
  'fan1_target_rpm': 1000,
  'fan2_target_rpm': 1200,
  'firmware_version': '1.2.3b'
}

L'elemento firmware_version del dispositivo non è correlato ai dati di configurazione, ma restituisce la rappresentazione interna completa del suo stato. Questo esempio mostra come lo stato del dispositivo può essere utile per il debug in generale, nonché per confermare che i dispositivi hanno confermato configurazioni specifiche.

Puoi ottenere i dati sullo stato del dispositivo utilizzando un argomento Cloud Pub/Sub, la console di Cloud Platform, l'API Cloud IoT Core o gcloud.

Argomento Cloud Pub/Sub

Cloud IoT Core conserva i dati dello stato nell'archiviazione. Puoi anche configurare un argomento Cloud Pub/Sub di notifica statale in ogni registro dei dispositivi tramite Cloud Console, gcloud o API. Questo argomento può essere uguale o diverso dall'argomento evento di telemetria.

I dati relativi allo stato vengono pubblicati su Cloud Pub/Sub secondo il criterio migliore: se la pubblicazione nell'argomento non va a buon fine, non verrà eseguito un nuovo tentativo. Se non viene definito alcun argomento, gli aggiornamenti dello stato del dispositivo vengono mantenuti in modo interno da Cloud IoT Core, ma vengono conservati solo gli ultimi dieci stati.

console

  1. Vai alla pagina Registry in Google Cloud Console.

    Vai alla pagina Registry

  2. Fai clic sull'ID del registry del dispositivo.

  3. Nel menu del Registro di sistema a sinistra, fai clic su Dispositivi.

  4. Fai clic sull'ID del dispositivo per andare alla pagina Dettagli dispositivo.

  5. Fai clic su Configurazione &cronologia dello stato. Utilizza le caselle di controllo per visualizzare la cronologia delle configurazioni, la cronologia degli stati o entrambe. Per impostazione predefinita, vengono mostrati entrambi.

    • Un segno di spunta verde indica che il dispositivo ha confermato la configurazione (solo MQTT).
    • Un simbolo di avviso giallo indica che il dispositivo non ha ancora confermato la configurazione (solo MQTT).
    • Fai clic su una riga per visualizzare i dati di configurazione o di stato completi in formato JSON, nonché il timestamp e la versione.
  6. Fai clic su Confronta per confrontare i dati di configurazione con i dati di stato. Questa vista può aiutarti a eseguire il debug delle configurazioni e, se utilizzi MQTT, assicurarti che i dispositivi abbiano confermato versioni specifiche della configurazione. Il bridge HTTP non supporta il riconoscimento delle configurazioni.

gcloud

Per ricevere i messaggi di stato più recenti per un dispositivo (fino a 10), esegui il comando gcloud iot devices states list.

gcloud iot devices states list \
    --registry=REGISTRY_ID \
    --device=DEVICE_ID \
    --region=REGION

Un flag Cloud Pub/Sub di notifica (--state-pubsub-topic) è disponibile per i comandi gcloud iot registries create e update:

gcloud iot registries create REGISTRY_ID \
    --project=PROJECT_ID \
    --region=REGION \
    [--event-notification-config=topic=TOPIC,[subfolder=SUBFOLDER] [--event-notification-config=...]]
    [--state-pubsub-topic=STATE_PUBSUB_TOPIC]
gcloud iot registries update REGISTRY_ID \
    --project=PROJECT_ID \
    --region=REGION \
    [--event-notification-config=topic=TOPIC,[subfolder=SUBFOLDER] [--event-notification-config=...]]
    [--state-pubsub-topic=STATE_PUBSUB_TOPIC]

API

Utilizza il metodo states.list del dispositivo per visualizzare gli stati più recenti del dispositivo (fino a 10). Ogni risorsa Device ha un campo DeviceState che contiene lo stato ricevuto più di recente dal dispositivo. La risorsa DeviceRegistry ha un campo StateNotificationConfig che può essere utilizzato per specificare un argomento Cloud Pub/Sub di notifica dello stato durante la creazione o l'aggiornamento di un registro.

L'esempio seguente mostra come recuperare lo stato del dispositivo da un registro dispositivi:

C#

public static object GetDeviceStates(string projectId, string cloudRegion, string registryId, string deviceId)
{
    var cloudIot = CreateAuthorizedClient();

    // The resource name of the location associated with the key rings.
    var name = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}/devices/{deviceId}";

    try
    {
        Console.WriteLine("States: ");
        var res = cloudIot.Projects.Locations.Registries.Devices.States.List(name).Execute();
        res.DeviceStates.ToList().ForEach(state =>
        {
            Console.WriteLine($"\t{state.UpdateTime}: {state.BinaryData}");
        });
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go


// getDeviceStates retrieves and lists device states.
func getDeviceStates(w io.Writer, projectID string, region string, registryID string, device string) ([]*cloudiot.DeviceState, 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
	}

	path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, device)
	response, err := client.Projects.Locations.Registries.Devices.States.List(path).Do()
	if err != nil {
		return nil, err
	}

	fmt.Fprintln(w, "Successfully retrieved device states!")

	for _, state := range response.DeviceStates {
		fmt.Fprintf(w, "%s : %s\n", state.UpdateTime, state.BinaryData)
	}

	return response.DeviceStates, nil
}

Java

/** Retrieves device metadata from a registry. * */
protected static List<DeviceState> getDeviceStates(
    String deviceId, String projectId, String cloudRegion, String registryName)
    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);

  System.out.println("Retrieving device states " + devicePath);

  ListDeviceStatesResponse resp =
      service.projects().locations().registries().devices().states().list(devicePath).execute();

  return resp.getDeviceStates();
}

Node.js

// const cloudRegion = 'us-central1';
// const deviceId = 'my-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 listDeviceStates() {
  const devicePath = iotClient.devicePath(
    projectId,
    cloudRegion,
    registryId,
    deviceId
  );

  const [response] = await iotClient.listDeviceStates({name: devicePath});
  const states = response.deviceStates;
  if (states.length === 0) {
    console.log(`No States for device: ${deviceId}`);
  } else {
    console.log(`States for device: ${deviceId}`);
  }

  for (let i = 0; i < states.length; i++) {
    const state = states[i];
    console.log(
      'State:',
      state,
      '\nData:\n',
      state.binaryData.toString('utf8')
    );
  }
}

listDeviceStates();

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;

/**
 * Retrieve a device's state blobs.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $deviceId IOT Device ID
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function get_device_state(
    $registryId,
    $deviceId,
    $projectId,
    $location = 'us-central1'
) {
    print('Getting device state' . PHP_EOL);

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

    $response = $deviceManager->listDeviceStates($deviceName);

    foreach ($response->getDeviceStates() as $state) {
        print('State:' . PHP_EOL);
        printf('    Data: %s' . PHP_EOL, $state->getBinaryData());
        printf('    Update Time: %s' . PHP_EOL,
            $state->getUpdateTime()->toDateTime()->format('Y-m-d H:i:s'));
    }
}

Python

Questo esempio utilizza la libreria client delle API di Google per Python.
# project_id = 'YOUR_PROJECT_ID'
# cloud_region = 'us-central1'
# registry_id = 'your-registry-id'
# device_id = 'your-device-id'
client = iot_v1.DeviceManagerClient()
device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

device = client.get_device(request={"name": device_path})
print("Last state: {}".format(device.state))

print("State history")
states = client.list_device_states(request={"name": device_path}).device_states
for state in states:
    print("State: {}".format(state))

return states

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to get device states from"
# device_id   = "The identifier of the device to get states for"

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

# List the configurations for the provided device
result = iot_client.list_project_location_registry_device_states(
  resource
)
if result.device_states
  result.device_states.each do |state|
    puts "#{state.update_time}: #{state.binary_data}"
  end
else
  puts "No state messages"
end