Gerätestatus abrufen

Mit Cloud IoT Core können Sie den Status jedes verbundenen Geräts überwachen. Der Status wird vom Gerät als Binärdaten gemeldet. Aktualisierungen des Gerätezustands werden in der Regel durch eine Änderung am Gerät ausgelöst – entweder durch eine Konfigurationsaktualisierung von Cloud IoT Core oder durch eine ähnliche Änderung von einer anderen externen Quelle, wie z. B. ein Firmware-Update.

Der Gerätestatus unterscheidet sich von der Gerätekonfiguration. Konfigurationsdaten werden von Cloud IoT Core an das Gerät gesendet. Statusdaten werden vom Gerät an Cloud IoT Core gesendet. Sie können sich die Konfiguration als externe Anweisung und den Status als interne Darstellung vorstellen.

Cloud IoT Core kann Ihnen helfen, grundlegende Fragen zu Konfiguration und Zustand zu beantworten: Was "denkt" das Gerät derzeit, was es tun sollte? Wie unterscheidet sich dies von der aktuellen Konfiguration für das Gerät?

Limits

Statusaktualisierungen sind auf 1 Aktualisierung pro Sekunde und Gerät beschränkt. Für optimale Ergebnisse sollte der Gerätestatus jedoch viel seltener aktualisiert werden, höchstens einmal alle 10 Sekunden.

Die Aktualisierungsrate wird als Zeit zwischen der letzten Serverbestätigung und der nächsten Aktualisierungsanfrage berechnet.

Gerätestatus melden

MQTT-Bridge

Um den Status an Cloud IoT Core über die MQTT-Bridge zu melden, veröffentlichen Sie Nachrichten an das MQTT-Topic /devices/DEVICE_ID/state. Sie können ein Cloud Pub/Sub-Thema auswählen, um Statusereignisse zu speichern, wenn Sie eine Registry erstellen oder aktualisieren.

Weitere Informationen finden Sie unter Über die MQTT-Bridge veröffentlichen.

HTTP-Bridge

Wenn der Status über die HTTP-Bridge an Cloud IoT Core gemeldet wird, sollten Geräte eine setState-Anfrage verwenden. Die binären Zustandsdaten werden im Hauptteil der Anfrage als ein base64-codierter String übergeben.

Weitere Informationen finden Sie unter Über die HTTP-Bridge veröffentlichen.

Gerätestatusdaten abrufen

In diesem Abschnitt wird erläutert, wie Sie die Statusdaten nach Geräten abrufen, die an Cloud IoT Core gemeldet werden. (Geräte selbst können keine Statusdaten aus der Cloud lesen.)

Statusdaten werden im Binärformat zurückgegeben. Statusdaten haben möglicherweise eine andere Struktur als die Konfigurationsdaten, die die Statusänderung auslösen.

Angenommen, Sie haben ein Gerät mit mehreren Lüftern. Ihre Konfigurationsdaten können ein JSON-Objekt sein, das einen einfachen booleschen Wert enthält, der die Kühlung aktiviert oder deaktiviert:

Beispiel für Konfigurationsdaten

{
  'cooling': true
}

Die Statusdaten des Geräts können jedoch Diagnoseinformationen sowie die Lüfterdaten enthalten, die Sie als Reaktion auf eine 'cooling'-Änderung erwarten:

Beispiel für Zustandsdaten

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

Die firmware_version des Geräts bezieht sich nicht auf die Konfigurationsdaten, aber das Gerät gibt die vollständige interne Darstellung des Status zurück. Dieses Beispiel veranschaulicht, wie der Gerätestatus für die Fehlersuche im Allgemeinen sowie für die Bestätigung, dass Geräte bestimmte Konfigurationen bestätigt haben, nützlich sein kann.

Sie können Gerätestatusdaten mithilfe eines Cloud Pub/Sub-Themas, der Cloud Platform Console, der Cloud IoT Core API oder gcloud abrufen.

Cloud Pub/Sub-Thema

Cloud IoT Core speichert Statusdaten im Speicher. Sie können in der Geräteregistrierung auch über eine Cloud Console, gcloud oder die API ein optionales Cloud Pub/Sub-Thema für die Benachrichtigung konfigurieren. Dieses Thema kann mit dem Thema des Telemetrieereignisses identisch sein oder sich davon unterscheiden.

Statusdaten werden auf Best-Effort-Basis in Cloud Pub/Sub veröffentlicht: Wenn die Veröffentlichung zu einem Thema fehlschlägt, wird es nicht wiederholt. Wenn kein Thema definiert ist, werden Aktualisierungen des Gerätestatus weiterhin intern von Cloud IoT Core gespeichert, aber nur die letzten 10 Zustände werden beibehalten.

Console

  1. Rufen Sie in der Cloud Console die Seite Registrys auf.

    Zur Seite Registries

  2. Klicken Sie auf die ID der Registry für das Gerät.

  3. Klicken Sie im Registry-Menü links auf Geräte.

  4. Klicken Sie auf die ID des Geräts, um die Seite Gerätedetails aufzurufen.

  5. Klicken Sie auf Konfigurations- und Statusverlauf. Verwenden Sie die Kästchen, um den Konfigurationsverlauf, den Statusverlauf oder beides anzuzeigen. Standardmäßig werden beide angezeigt.

    • Ein grünes Häkchen zeigt an, dass die Konfiguration vom Gerät bestätigt wurde (nur MQTT).
    • Ein gelbes Warnsymbol bedeutet, dass das Gerät die Konfiguration noch nicht bestätigt hat (nur MQTT).
    • Klicken Sie auf eine Zeile, um die vollständigen Konfigurations- oder Statusdaten in JSON sowie den Zeitstempel und die Version abzurufen.
  6. Klicken Sie auf Vergleichen, um die Konfigurationsdaten mit den Statusdaten zu vergleichen. Sie können diese Ansicht verwenden, um Konfigurationsfehler zu beheben und, wenn Sie MQTT verwenden, zu prüfen, ob die Geräte bestimmte Konfigurationsversionen bestätigt haben. (Die HTTP-Bridge unterstützt keine Bestätigung von Konfigurationen.)

gcloud

Führen Sie den Befehl gcloud iot devices states list aus, um die neuesten Statusnachrichten für ein Gerät (bis zu 10) abzurufen.

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

Für die Befehle gcloud iot registries create und update ist ein Cloud Pub/Sub-Flag für Statusbenachrichtigungen (--state-pubsub-topic) verfügbar:

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

Verwenden Sie die Methode states.list, um die neuesten Gerätestatus abzurufen (bis zu 10). Jede Device-Ressource hat das Feld DeviceState, das den Status enthält, der zuletzt vom Gerät empfangen wurde. Die Ressource DeviceRegistry enthält das Feld StateNotificationConfig, mit dem beim Erstellen oder Aktualisieren einer Registry ein Cloud Pub/Sub-Thema für die Statusbenachrichtigung angegeben werden kann.

Das folgende Beispiel zeigt, wie Sie den Gerätestatus aus einer Geräte-Registry abrufen:

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

In diesem Beispiel wird die Google API-Clientbibliothek für Python verwendet.
# 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