Creating Registries and Devices

This page explains how to create, edit, and delete device registries and devices within them.

A device is a "Thing" in "Internet of Things": a processing unit that is capable of connecting to the internet (directly or indirectly) and exchanging data with the cloud. A device registry is a container of devices with shared properties. For more details about devices and registries, see Devices.

If you haven't already, complete the Getting Started steps before proceeding.

Creating a device registry

To use Cloud IoT Core, you must create at least one device registry. You can create a registry using GCP Console, the API, or gcloud.

Console

  1. Go to the Device registries page in GCP Console.

    Go to the Device registries page

  2. At the top of the page, click Create device registry.

  3. Enter a Registry ID and select a cloud region. For information on registry naming and size requirements, see Permitted characters and size requirements.

  4. Select the Protocols that devices in this registry will use to connect to Cloud IoT Core: MQTT, HTTP, or both.

  5. Select a Telemetry topic or create a new one.

    If you select only one Cloud Pub/Sub topic, all device telemetry (the event data sent from devices to the cloud) will be published to that topic. You can specify multiple topics in order to publish separate streams of data from a device. Each topic maps to a subfolder specified in either the MQTT topic path or the HTTP request when the data is published.

    If you specify multiple Pub/Sub topics, you should also select one default topic that has no accompanying subfolder. This default topic will be used for published telemetry events that don't have a subfolder or if the subfolder used doesn't have a matching Pub/Sub topic. If you don't select a default topic, these telemetry events will be lost.

    For information on subfolder naming and size requirements, see Permitted characters and size requirements.

  6. (Optional) Select a Device state topic or create a new one. This topic can be the same as or different from the telemetry topic.

    State data is published to Cloud Pub/Sub on a best-effort basis: if publication to the topic fails, it will not be retried. If no topic is defined, device state updates are still persisted internally by Cloud IoT Core, but only the last 10 states are retained.

    For more information, see Getting device state.

  7. Click Create to continue.

gcloud

To create a registry, run the gcloud iot registries create command:

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]

In the current release of Cloud IoT Core, the available regions are us-central1, europe-west1, and asia-east1.

You can use the --enable-http-config and --enable-mqtt-config flags to enable and disable protocols for the registry. By default, both protocols are enabled.

You can specify multiple Pub/Sub topics and their matching subfolders by repeating the --event-notification-config flag. If you specify multiple Pub/Sub topics, you should select one default topic that has no accompanying subfolder. This default topic will be used for published telemetry events that don't have a subfolder or if the subfolder used doesn't have a matching Pub/Sub topic. If you don't select a default topic, these telemetry events will be lost.

API

Use the DeviceRegistry create method to create a registry:

C#

public static object CreateRegistry(string projectId, string cloudRegion, string registryId, string pubsubTopic)
{
    var cloudIot = CreateAuthorizedClient();
    // The resource name of the location associated with the key rings.
    var parent = $"projects/{projectId}/locations/{cloudRegion}";

    Console.WriteLine(parent);

    try
    {
        Console.WriteLine($"Creating {registryId}");


        DeviceRegistry body = new DeviceRegistry()
        {
            Id = registryId,
        };
        body.EventNotificationConfigs = new List<EventNotificationConfig>();
        var toAdd = new EventNotificationConfig()
        {
            PubsubTopicName = pubsubTopic.StartsWith("projects/") ?
                pubsubTopic : $"projects/{projectId}/topics/{pubsubTopic}",
        };
        body.EventNotificationConfigs.Add(toAdd);
        var registry = cloudIot.Projects.Locations.Registries.Create(body, parent).Execute();
        Console.WriteLine("Registry: ");
        Console.WriteLine($"{registry.Id}");
        Console.WriteLine($"\tName: {registry.Name}");
        Console.WriteLine($"\tHTTP Enabled: {registry.HttpConfig.HttpEnabledState}");
        Console.WriteLine($"\tMQTT Enabled: {registry.MqttConfig.MqttEnabledState}");
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go

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

registry := cloudiot.DeviceRegistry{
	Id: registryID,
	EventNotificationConfigs: []*cloudiot.EventNotificationConfig{
		{
			PubsubTopicName: topicName,
		},
	},
}

parent := fmt.Sprintf("projects/%s/locations/%s", projectID, region)
response, err := client.Projects.Locations.Registries.Create(parent, &registry).Do()
if err != nil {
	return nil, err
}

fmt.Println("Created registry:")
fmt.Println("\tID: ", response.Id)
fmt.Println("\tHTTP: ", response.HttpConfig.HttpEnabledState)
fmt.Println("\tMQTT: ", response.MqttConfig.MqttEnabledState)
fmt.Println("\tName: ", response.Name)

Java

/** Create a registry for Cloud IoT. */
public static void createRegistry(String cloudRegion, String projectId, String registryName,
                                  String pubsubTopicPath)
    throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential);
  final CloudIot service = new CloudIot.Builder(
      GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init)
      .setApplicationName(APP_NAME).build();

  final String projectPath = "projects/" + projectId + "/locations/" + cloudRegion;
  final String fullPubsubPath = "projects/" + projectId + "/topics/" + pubsubTopicPath;

  DeviceRegistry registry = new DeviceRegistry();
  EventNotificationConfig notificationConfig = new EventNotificationConfig();
  notificationConfig.setPubsubTopicName(fullPubsubPath);
  List<EventNotificationConfig> notificationConfigs = new ArrayList<EventNotificationConfig>();
  notificationConfigs.add(notificationConfig);
  registry.setEventNotificationConfigs(notificationConfigs);
  registry.setId(registryName);

  DeviceRegistry reg = service.projects().locations().registries().create(projectPath,
      registry).execute();
  System.out.println("Created registry: " + reg.getName());
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
// function errCb = lookupRegistry; // Lookup registry if already exists.
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const pubsubTopic = `projects/${projectId}/topics/${pubsubTopicId}`;

const request = {
  parent: parentName,
  resource: {
    eventNotificationConfigs: [{
      'pubsubTopicName': pubsubTopic
    }],
    'id': registryId
  }
};

client.projects.locations.registries.create(request, (err, data) => {
  if (err) {
    if (err.code === 409) {
      // The registry already exists - look it up instead.
      foundCb(client, registryId, projectId, cloudRegion);
    } else {
      console.log('Could not create registry');
      console.log(err);
    }
  } else {
    console.log('Successfully created registry');
    console.log(data);
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;
use Google\Cloud\Iot\V1\DeviceRegistry;
use Google\Cloud\Iot\V1\EventNotificationConfig;

/**
 * Creates a registry if it doesn't exist and prints the result.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $pubsubTopic PubSub topic name for the new registry's event change notification.
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function create_registry(
    $registryId,
    $pubsubTopic,
    $projectId,
    $location = 'us-central1'
) {
    print('Creating Registry' . PHP_EOL);

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

    $pubsubTopicPath = sprintf('projects/%s/topics/%s', $projectId, $pubsubTopic);
    $eventNotificationConfig = (new EventNotificationConfig)
        ->setPubsubTopicName($pubsubTopicPath);

    $registry = (new DeviceRegistry)
        ->setId($registryId)
        ->setEventNotificationConfigs([$eventNotificationConfig]);

    $registry = $deviceManager->createDeviceRegistry($locationName, $registry);

    printf('Id: %s, Name: %s' . PHP_EOL,
        $registry->getId(),
        $registry->getName());
}

Python

This sample uses the Google API Client Library for Python.
def create_registry(
        service_account_json, project_id, cloud_region, pubsub_topic,
        registry_id):
    """ Creates a registry and returns the result. Returns an empty result if
    the registry already exists."""
    client = get_client(service_account_json)
    registry_parent = 'projects/{}/locations/{}'.format(
            project_id,
            cloud_region)
    body = {
        'eventNotificationConfigs': [{
            'pubsubTopicName': pubsub_topic
        }],
        'id': registry_id
    }
    request = client.projects().locations().registries().create(
        parent=registry_parent, body=body)

    try:
        response = request.execute()
        print('Created registry')
        return response
    except HttpError:
        print('Error, registry not created')
        return ""

Ruby

# project_id   = "Your Google Cloud project ID"
# location_id  = "The Cloud region that you created the registry in"
# registry_id  = "The Google Cloud IoT Core device registry identifier"
# pubsub_topic = "The Google Cloud PubSub topic to use for this registry"

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 project / location where the registry is created.
parent = "projects/#{project_id}/locations/#{location_id}"

registry = Cloudiot::DeviceRegistry.new
registry.id = registry_id
registry.event_notification_configs = [Cloudiot::EventNotificationConfig::new]
registry.event_notification_configs[0].pubsub_topic_name = pubsub_topic

registry = iot_client.create_project_location_registry(
    parent, registry
)

puts "Created registry: #{registry.name}"

IAM role for Pub/Sub publishing

When you first enable the Cloud IoT Core API for a project, a new service account for the project is automatically assigned a role (cloudiot.serviceAgent) that enables publishing to all Pub/Sub topics defined in registries within the project. If you later remove this default role from the relevant project service account, you might encounter errors. For details, see Troubleshooting.

Creating a device registry with multiple Pub/Sub topics

As noted in creating a device registry, you must create at least one device registry to use Cloud IoT Core. A registry can have one or more Pub/Sub topics to which devices in the registry can publish data.

You can combine Pub/Sub topics with MQTT/HTTP subfolders to publish telemetry events to separate topics. Each topic maps to a subfolder, so when you publish data to the subfolder, it gets forwarded to the topic. For example, you might have a device that publishes multiple types of data, such as temperature, humidity, and logging data. By directing these data streams to their own individual topics, you can eliminate the need to separate the data into different categories after publishing.

You can map a single Pub/Sub topic to multiple subfolders, but the reverse is not true; each subfolder must be unique and a single subfolder cannot be mapped to different topics.

For detailed information on publishing to multiple Pub/Sub topics, see the sections on using the MQTT bridge and using the HTTP bridge.

Creating device key pairs

Before creating a device, first create a public/private key pair for it. When connecting to Cloud IoT Core, each device creates a JSON Web Token (JWT) signed with its private key, which Cloud IoT Core authenticates using the device's public key.

Creating or editing a device

You can create a device or edit an existing one using GCP Console, the API, or gcloud. Make sure you've created a registry and a key pair before completing the steps in this section.

Console

  1. Go to the Device registries page in GCP Console.

    Go to the Device registries page

  2. Click the ID of the registry for the device.

  3. On the Registry details page, click Add device to create a new device.

    To edit an existing device, click its ID on the Registry details page, and then click Edit device at the top of the page.

  4. Enter a Device ID that briefly describes the device or otherwise helps you identify it. (This field can't be edited later.) For information on device naming and size requirements, see Permitted characters and size requirements.

  5. For Device communication, select Allow or Block. This option allows you to block communication when needed, such as when a device is not functioning properly. In most cases, you'll want to allow communication when first creating the device.

  6. If you're creating a new device, select the Public key format that matches the key pair for this device. Paste the certificate or key in the Public key value field. You can also set an expiration date for the key.

    To add a key to an existing device, click Add public key on the Device details page.

  7. Use the Key and Value fields to add optional device metadata, such as a serial number. For information on metadata key-value naming and size requirements, see Permitted characters and size requirements.

  8. Click Add to create the device or Update to save changes to an existing device.

gcloud

To create a device, run the gcloud iot devices create command.

To create a device with RS256 credentials, run the following command:

gcloud iot devices create DEVICE_ID \
  --project=PROJECT_ID \
  --region=REGION \
  --registry=REGISTRY_ID \
  --public-key path=rsa_cert.pem,type=rs256

To create a device with ES256 credentials, run the following command:

gcloud iot devices create DEVICE_ID \
  --project=PROJECT_ID \
  --region=REGION \
  --registry=REGISTRY_ID \
  --public-key path=ec_public.pem,type=es256

To edit a device, run the gcloud iot devices update command:

gcloud iot devices update DEVICE_ID \
  --project=PROJECT_ID \
  --region=REGION \
  --registry=REGISTRY_ID \

API

Use the following methods to create or edit devices:

When creating a device, public keys are specified in the credentials field of the Device resource in the Cloud IoT Core API. You can also add or modify this field when you update the device resource. If one or more registry-level certificates are present when adding a new device credential (either via device creation or via modifications), the public key credential must be signed by one of the registry-level certificates. See DeviceCredential in the Device resource for more information.

For RSA, theDevice.credentials[i].public_key.key field must be set to the contents of rsa_cert.pem (including the header and the footer). The Device.credentials[i].public_key.format field must be set to RSA_X509_PEM.

For ES256, the Device.credentials[i].public_key.key field must be set to the contents of ec_public.pem (including the header and the footer). The Device.credentials[i].public_key.format field must be set to ES256_PEM.

The following sample shows how to create a device with RSA credentials:

C#

public static object CreateRsaDevice(string projectId, string cloudRegion, string registryId, string deviceId, string keyPath)
{
    var cloudIot = CreateAuthorizedClient();
    var parent = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";

    try
    {
        String keyText = File.ReadAllText(keyPath);
        Device body = new Device()
        {
            Id = deviceId
        };
        body.Credentials = new List<DeviceCredential>();
        body.Credentials.Add(new DeviceCredential()
        {
            PublicKey = new PublicKeyCredential()
            {
                Key = keyText,
                Format = "RSA_X509_PEM"
            },
        });

        var device = cloudIot.Projects.Locations.Registries.Devices.Create(body, parent).Execute();
        Console.WriteLine("Device created: ");
        Console.WriteLine($"{device.Id}");
        Console.WriteLine($"\tBlocked: {device.Blocked == true}");
        Console.WriteLine($"\tConfig version: {device.Config.Version}");
        Console.WriteLine($"\tName: {device.Name}");
        Console.WriteLine($"\tState:{device.State}");
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go

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

keyBytes, err := ioutil.ReadFile(keyPath)
if err != nil {
	return nil, err
}

device := cloudiot.Device{
	Id: deviceID,
	Credentials: []*cloudiot.DeviceCredential{
		{
			PublicKey: &cloudiot.PublicKeyCredential{
				Format: "RSA_X509_PEM",
				Key:    string(keyBytes),
			},
		},
	},
}

parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registry)
response, err := client.Projects.Locations.Registries.Devices.Create(parent, &device).Do()
if err != nil {
	return nil, err
}

fmt.Println("Successfully created device.")

Java

/** Create a device that is authenticated using RS256. */
public static void createDeviceWithRs256(String deviceId, String certificateFilePath,
                                         String projectId, String cloudRegion,
                                         String registryName)
    throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential);
  final CloudIot service = new CloudIot.Builder(
      GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init)
      .setApplicationName(APP_NAME).build();

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

  PublicKeyCredential publicKeyCredential = new PublicKeyCredential();
  String key = Files.toString(new File(certificateFilePath), Charsets.UTF_8);
  publicKeyCredential.setKey(key);
  publicKeyCredential.setFormat("RSA_X509_PEM");

  DeviceCredential devCredential = new DeviceCredential();
  devCredential.setPublicKey(publicKeyCredential);

  System.out.println("Creating device with id: " + deviceId);
  Device device = new Device();
  device.setId(deviceId);
  device.setCredentials(Arrays.asList(devCredential));
  Device createdDevice =
      service
          .projects()
          .locations()
          .registries()
          .devices()
          .create(registryPath, device)
          .execute();

  System.out.println("Created device: " + createdDevice.toPrettyString());
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const deviceId = 'my-rsa-device';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;
const body = {
  id: deviceId,
  credentials: [
    {
      publicKey: {
        format: 'RSA_X509_PEM',
        key: fs.readFileSync(rsaCertificateFile).toString()
      }
    }
  ]
};

const request = {
  parent: registryName,
  resource: body
};

console.log(JSON.stringify(request));

client.projects.locations.registries.devices.create(request, (err, data) => {
  if (err) {
    console.log('Could not create device');
    console.log(err);
  } else {
    console.log('Created device');
    console.log(data);
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;
use Google\Cloud\Iot\V1\Device;
use Google\Cloud\Iot\V1\DeviceCredential;
use Google\Cloud\Iot\V1\PublicKeyCredential;
use Google\Cloud\Iot\V1\PublicKeyFormat;

/**
 * Create a new device with the given id, using RS256 for
 * authentication.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $deviceId IOT Device ID
 * @param string $certificateFile Path to RS256 certificate file.
 * @param string $projectId (optional) Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function create_rsa_device(
    $registryId,
    $deviceId,
    $certificateFile,
    $projectId,
    $location = 'us-central1'
) {
    print('Creating new RS256 Device' . PHP_EOL);

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

    $publicKey = (new PublicKeyCredential())
        ->setFormat(PublicKeyFormat::RSA_X509_PEM)
        ->setKey(file_get_contents($certificateFile));

    $credential = (new DeviceCredential())
        ->setPublicKey($publicKey);

    $device = (new Device())
        ->setId($deviceId)
        ->setCredentials([$credential]);

    $device = $deviceManager->createDevice($registryName, $device);

    printf('Device: %s : %s' . PHP_EOL,
        $device->getNumId(),
        $device->getId());
}

Python

This sample uses the Google API Client Library for Python.
def create_rs256_device(
        service_account_json, project_id, cloud_region, registry_id, device_id,
        certificate_file):
    """Create a new device with the given id, using RS256 for
    authentication."""
    registry_name = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)

    client = get_client(service_account_json)
    with io.open(certificate_file) as f:
        certificate = f.read()

    # Note: You can have multiple credentials associated with a device.
    device_template = {
        'id': device_id,
        'credentials': [{
            'publicKey': {
                'format': 'RSA_X509_PEM',
                'key': certificate
            }
        }]
    }

    devices = client.projects().locations().registries().devices()
    return devices.create(parent=registry_name, body=device_template).execute()

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to create a device in"
# device_id   = "The identifier of the device to create"
# cert_path   = "The path to the RSA certificate"

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}/registries/#{registry_id}"

credential = Google::Apis::CloudiotV1::DeviceCredential.new
credential.public_key = Google::Apis::CloudiotV1::PublicKeyCredential.new
credential.public_key.format = "RSA_X509_PEM"
credential.public_key.key = File.read(cert_path)

device = Cloudiot::Device.new
device.id = device_id
device.credentials = [credential]

# Create the device
device = iot_client.create_project_location_registry_device parent, device

puts "Device: #{device.id}"
puts "\tBlocked: #{device.blocked}"
puts "\tLast Event Time: #{device.last_event_time}"
puts "\tLast State Time: #{device.last_state_time}"
puts "\tName: #{device.name}"

The following sample shows how to create a device with Elliptic Curve (EC) credentials:

C#

public static object CreateEsDevice(string projectId, string cloudRegion, string registryId, string deviceId, string keyPath)
{
    var cloudIot = CreateAuthorizedClient();
    var parent = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";

    try
    {
        String keyText = File.ReadAllText(keyPath);
        Device body = new Device()
        {
            Id = deviceId
        };
        body.Credentials = new List<DeviceCredential>();
        body.Credentials.Add(new DeviceCredential()
        {
            PublicKey = new PublicKeyCredential()
            {
                Key = keyText,
                Format = "ES256_PEM"
            },
        });

        var device = cloudIot.Projects.Locations.Registries.Devices.Create(body, parent).Execute();
        Console.WriteLine("Device created: ");
        Console.WriteLine($"{device.Id}");
        Console.WriteLine($"\tBlocked: {device.Blocked == true}");
        Console.WriteLine($"\tConfig version: {device.Config.Version}");
        Console.WriteLine($"\tName: {device.Name}");
        Console.WriteLine($"\tState:{device.State}");
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go

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

keyBytes, err := ioutil.ReadFile(keyPath)
if err != nil {
	return nil, err
}

device := cloudiot.Device{
	Id: deviceID,
	Credentials: []*cloudiot.DeviceCredential{
		{
			PublicKey: &cloudiot.PublicKeyCredential{
				Format: "ES256_PEM",
				Key:    string(keyBytes),
			},
		},
	},
}

parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registry)
response, err := client.Projects.Locations.Registries.Devices.Create(parent, &device).Do()
if err != nil {
	return nil, err
}

fmt.Println("Successfully created device.")

Java

/** Create a device that is authenticated using ES256. */
public static void createDeviceWithEs256(String deviceId, String publicKeyFilePath,
    String projectId, String cloudRegion, String registryName)
    throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential);
  final CloudIot service = new CloudIot.Builder(
      GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init)
      .setApplicationName(APP_NAME).build();

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

  PublicKeyCredential publicKeyCredential = new PublicKeyCredential();
  final String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8);
  publicKeyCredential.setKey(key);
  publicKeyCredential.setFormat("ES256_PEM");

  DeviceCredential devCredential  = new DeviceCredential();
  devCredential.setPublicKey(publicKeyCredential);

  System.out.println("Creating device with id: " + deviceId);
  Device device = new Device();
  device.setId(deviceId);
  device.setCredentials(Arrays.asList(devCredential));

  Device createdDevice =
      service
          .projects()
          .locations()
          .registries()
          .devices()
          .create(registryPath, device)
          .execute();

  System.out.println("Created device: " + createdDevice.toPrettyString());
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const deviceId = 'my-es-device';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;
const body = {
  id: deviceId,
  credentials: [
    {
      publicKey: {
        format: 'ES256_PEM',
        key: fs.readFileSync(esCertificateFile).toString()
      }
    }
  ]
};

const request = {
  parent: registryName,
  resource: body
};

client.projects.locations.registries.devices.create(request, (err, data) => {
  if (err) {
    console.log('Could not create device');
    console.log(err);
  } else {
    console.log('Created device');
    console.log(data);
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;
use Google\Cloud\Iot\V1\Device;
use Google\Cloud\Iot\V1\DeviceCredential;
use Google\Cloud\Iot\V1\PublicKeyCredential;
use Google\Cloud\Iot\V1\PublicKeyFormat;

/**
 * Create a new device with the given id, using ES256 for
 * authentication.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $deviceId IOT Device ID
 * @param string $publicKeyFile Path to public ES256 key file.
 * @param string $projectId (optional) Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function create_es_device(
    $registryId,
    $deviceId,
    $publicKeyFile,
    $projectId,
    $location = 'us-central1'
) {
    print('Creating new ES256 Device' . PHP_EOL);

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

    $publicKey = (new PublicKeyCredential())
        ->setFormat(PublicKeyFormat::ES256_PEM)
        ->setKey(file_get_contents($publicKeyFile));

    $credential = (new DeviceCredential())
        ->setPublicKey($publicKey);

    $device = (new Device())
        ->setId($deviceId)
        ->setCredentials([$credential]);

    $device = $deviceManager->createDevice($registryName, $device);

    printf('Device: %s : %s' . PHP_EOL,
        $device->getNumId(),
        $device->getId());
}

Python

This sample uses the Google API Client Library for Python.
def create_es256_device(
        service_account_json, project_id, cloud_region, registry_id,
        device_id, public_key_file):
    """Create a new device with the given id, using ES256 for
    authentication."""
    registry_name = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)

    client = get_client(service_account_json)
    with io.open(public_key_file) as f:
        public_key = f.read()

    # Note: You can have multiple credentials associated with a device.
    device_template = {
        'id': device_id,
        'credentials': [{
            'publicKey': {
                'format': 'ES256_PEM',
                'key': public_key
            }
        }]
    }

    devices = client.projects().locations().registries().devices()
    return devices.create(parent=registry_name, body=device_template).execute()

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to create a device in"
# device_id   = "The identifier of the device to create"
# cert_path   = "The path to the EC certificate"

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}/registries/#{registry_id}"

device = Cloudiot::Device.new
device.id = device_id

pubkey = Google::Apis::CloudiotV1::PublicKeyCredential.new
pubkey.key = File.read(cert_path)
pubkey.format = "ES256_PEM"

cred = Google::Apis::CloudiotV1::DeviceCredential.new
cred.public_key = pubkey

device.credentials = [cred]

# Create the device
device = iot_client.create_project_location_registry_device parent, device

puts "Device: #{device.id}"
puts "\tBlocked: #{device.blocked}"
puts "\tLast Event Time: #{device.last_event_time}"
puts "\tLast State Time: #{device.last_state_time}"
puts "\tName: #{device.name}"

The following sample shows how to patch a device with RSA credentials:

C#

public static object PatchRsaDevice(string projectId, string cloudRegion, string registryId, string deviceId, string keyPath)
{
    var cloudIot = CreateAuthorizedClient();
    var name = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}/devices/{deviceId}";

    try
    {
        String keyText = File.ReadAllText(keyPath);
        Device body = new Device();
        body.Credentials = new List<DeviceCredential>();
        body.Credentials.Add(new DeviceCredential()
        {
            PublicKey = new PublicKeyCredential()
            {
                Key = keyText,
                Format = "RSA_X509_PEM"
            },
        });

        var req = cloudIot.Projects.Locations.Registries.Devices.Patch(body, name);
        req.UpdateMask = "credentials";
        var device = req.Execute();
        Console.WriteLine("Device patched: ");
        Console.WriteLine($"{device.Id}");
        Console.WriteLine($"\tBlocked: {device.Blocked == true}");
        Console.WriteLine($"\tConfig version: {device.Config.Version}");
        Console.WriteLine($"\tName: {device.Name}");
        Console.WriteLine($"\tState:{device.State}");
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go

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

keyBytes, err := ioutil.ReadFile(keyPath)
if err != nil {
	return nil, err
}

device := cloudiot.Device{
	Id: deviceID,
	Credentials: []*cloudiot.DeviceCredential{
		{
			PublicKey: &cloudiot.PublicKeyCredential{
				Format: "RSA_X509_PEM",
				Key:    string(keyBytes),
			},
		},
	},
}

parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registry, deviceID)
response, err := client.Projects.Locations.Registries.Devices.
	Patch(parent, &device).UpdateMask("credentials").Do()
if err != nil {
	return nil, err
}

fmt.Println("Successfully patched device.")

Java

/** Patch the device to add an RSA256 key for authentication. */
public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, String projectId,
                                      String cloudRegion,
                                      String registryName)
    throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(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);

  PublicKeyCredential publicKeyCredential = new PublicKeyCredential();
  String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8);
  publicKeyCredential.setKey(key);
  publicKeyCredential.setFormat("RSA_X509_PEM");

  DeviceCredential devCredential = new DeviceCredential();
  devCredential.setPublicKey(publicKeyCredential);

  Device device = new Device();
  device.setCredentials(Arrays.asList(devCredential));

  Device patchedDevice =
      service
          .projects()
          .locations()
          .registries()
          .devices()
          .patch(devicePath, device)
          .setUpdateMask("credentials")
          .execute();

  System.out.println("Patched device is " + patchedDevice.toPrettyString());
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const deviceId = 'my-rsa-device';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName =
    `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;
const request = {
  name: `${registryName}/devices/${deviceId}`,
  updateMask: 'credentials',
  resource: {
    credentials: [
      {
        publicKey: {
          format: 'RSA_X509_PEM',
          key: fs.readFileSync(rsaPublicKeyFile).toString()
        }
      }
    ]
  }
};

client.projects.locations.registries.devices.patch(request, (err, data) => {
  if (err) {
    console.log('Error patching device:', deviceId);
    console.log(err);
  } else {
    console.log('Patched device:', deviceId);
    console.log(data);
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;
use Google\Cloud\Iot\V1\Device;
use Google\Cloud\Iot\V1\DeviceCredential;
use Google\Cloud\Iot\V1\PublicKeyCredential;
use Google\Cloud\Iot\V1\PublicKeyFormat;
use Google\Protobuf\FieldMask;

/**
 * Patch the device to add an RSA256 public key to the device.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $deviceId IOT Device ID
 * @param string $certificateFile Path to RS256 certificate file.
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function patch_rsa(
    $registryId,
    $deviceId,
    $certificateFile,
    $projectId,
    $location = 'us-central1'
) {
    print('Patch device with RSA256 certificate' . PHP_EOL);

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

    $publicKey = (new PublicKeyCredential())
        ->setFormat(PublicKeyFormat::RSA_X509_PEM)
        ->setKey(file_get_contents($certificateFile));

    $credential = (new DeviceCredential())
        ->setPublicKey($publicKey);

    $device = (new Device())
        ->setName($deviceName)
        ->setCredentials([$credential]);

    $updateMask = (new FieldMask())
        ->setPaths(['credentials']);

    $device = $deviceManager->updateDevice($device, $updateMask);
    printf('Updated device %s' . PHP_EOL, $device->getName());
}

Python

This sample uses the Google API Client Library for Python.
def patch_rsa256_auth(
        service_account_json, project_id, cloud_region, registry_id, device_id,
        public_key_file):
    """Patch the device to add an RSA256 public key to the device."""
    print('Patch device with RSA256 certificate')
    client = get_client(service_account_json)
    registry_path = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)

    with io.open(public_key_file) as f:
        public_key = f.read()

    patch = {
        'credentials': [{
            'publicKey': {
                'format': 'RSA_X509_PEM',
                'key': public_key
            }
        }]
    }

    device_name = '{}/devices/{}'.format(registry_path, device_id)

    return client.projects().locations().registries().devices().patch(
            name=device_name, updateMask='credentials', body=patch).execute()

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to create a device in"
# device_id   = "The identifier of the device to patch"
# cert_path   = "The path to the RSA certificate"

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}/registries/#{registry_id}"
path   = "#{parent}/devices/#{device_id}"

credential = Google::Apis::CloudiotV1::DeviceCredential.new
credential.public_key = Google::Apis::CloudiotV1::PublicKeyCredential.new
credential.public_key.format = "RSA_X509_PEM"
credential.public_key.key = File.read(cert_path)

device = Cloudiot::Device.new
device.credentials = [credential]

# Create the device
device = iot_client.patch_project_location_registry_device(
  path, device, update_mask: "credentials"
)

puts "Device: #{device.id}"
puts "\tBlocked: #{device.blocked}"
puts "\tLast Event Time: #{device.last_event_time}"
puts "\tLast State Time: #{device.last_state_time}"
puts "\tName: #{device.name}"
puts "\tCertificate formats:"
if device.credentials
  device.credentials.each { |cert| puts "\t\t#{cert.public_key.format}"}
else
  puts "\t\tNo certificates for device"
end

See the Device Management Samples for more code samples.

Credential and certificate expiration dates

When you create a device and add a public key, you can set an expiration date for the key. If the key was generated with a self-signed X.509 certificate, then the certificate itself also has an expiration date. However, these two expiration dates are separate.

If either the key expires or the self-signed X.509 certificate on the key expires, the device will not be able to connect to Cloud IoT Core. Additionally, if you try to create or update a device with an expired X.509 certificate, Cloud IoT Core returns an error.

Getting device details

You can get details about one or more devices using GCP Console, the API, or gcloud.

Console

  1. Go to the Device registries page in GCP Console.

    Go to the Device registries page

  2. Click the ID of the registry for the device.

  3. Click the ID of the device to go to the Device details page. This page summarizes recent device activity, including the last time a message was published and the time of the most recent error.

  4. Click the Configuration history tab to see recent configuration versions and update times for the device.

The fields for the last heartbeat time and the last time a configuration was ACKed are for the MQTT bridge only. The HTTP bridge does not support heartbeat or explicit ACKs.

gcloud

To list the devices in a registry, run the gcloud iot devices list command:

gcloud iot devices list \
  --project=PROJECT_ID \
  --registry=REGISTRY_ID \
  --region=REGION

To get details about a device, run the gcloud iot devices describe command:

gcloud iot devices describe DEVICE_ID \
  --project=PROJECT_ID \
  --registry=REGISTRY_ID \
  --region=REGION

API

Use the following methods to get details about devices:

The following sample shows how to list the devices in a registry:

C#

public static object ListDevices(string projectId, string cloudRegion, string registryId)
{
    var cloudIot = CreateAuthorizedClient();
    // The resource name of the location associated with the key rings.
    var parent = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";
    try
    {
        var result = cloudIot.Projects.Locations.Registries.Devices.List(parent).Execute();
        Console.WriteLine("Devices: ");
        result.Devices.ToList().ForEach(response =>
        {
            Console.WriteLine($"{response.Id}");
            Console.WriteLine($"\t{response.Config}");
            Console.WriteLine($"\t{response.Name}");
        });
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        return e.Error.Code;
    }
    return 0;
}

Go

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

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

fmt.Println("Devices:")
for _, device := range response.Devices {
	fmt.Println("\t", device.Id)
}

Java

/** Print all of the devices in this registry to standard out. */
public static void listDevices(String projectId, String cloudRegion, String registryName) throws
    GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential);
  final CloudIot service = new CloudIot.Builder(
      GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init)
      .setApplicationName(APP_NAME).build();

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

  List<Device> devices =
      service
          .projects()
          .locations()
          .registries()
          .devices()
          .list(registryPath)
          .execute()
          .getDevices();

  if (devices != null) {
    System.out.println("Found " + devices.size() + " devices");
    for (Device d : devices) {
      System.out.println("Id: " + d.getId());
      if (d.getConfig() != null) {
        // Note that this will show the device config in Base64 encoded format.
        System.out.println("Config: " + d.getConfig().toPrettyString());
      }
      System.out.println();
    }
  } else {
    System.out.println("Registry has no devices.");
  }
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;

const request = {
  parent: registryName
};

client.projects.locations.registries.devices.list(request, (err, data) => {
  if (err) {
    console.log('Could not list devices');
    console.log(err);
  } else {
    console.log('Current devices in registry:', data['devices']);
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;

/**
 * List all devices in the registry.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function list_devices(
    $registryId,
    $projectId,
    $location = 'us-central1'
) {
    print('Listing devices' . PHP_EOL);

    // Instantiate a client.
    $deviceManager = new DeviceManagerClient();

    // Format the full registry path
    $registryName = $deviceManager->registryName($projectId, $location, $registryId);

    // Call the API
    $devices = $deviceManager->listDevices($registryName);

    // Print the result
    foreach ($devices->iterateAllElements() as $device) {
        printf('Device: %s : %s' . PHP_EOL,
            $device->getNumId(),
            $device->getId());
    }
}

Python

This sample uses the Google API Client Library for Python.
def list_devices(
        service_account_json, project_id, cloud_region, registry_id):
    """List all devices in the registry."""
    print('Listing devices')
    registry_path = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)
    client = get_client(service_account_json)
    devices = client.projects().locations().registries().devices(
            ).list(parent=registry_path).execute().get('devices', [])

    for device in devices:
            print('Device: {} : {}'.format(
                    device.get('numId'),
                    device.get('id')))

    return devices

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to list devices from"

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
resource = "projects/#{project_id}/locations/#{location_id}/registries/#{registry_id}"

# List the devices in the provided region
response = iot_client.list_project_location_registry_devices(
  resource
)

puts "Devices:"
if response.devices && response.devices.any?
  response.devices.each { |device| puts "\t#{device.id}" }
else
  puts "\tNo device registries found in this region for your project."
end

The following sample shows how to retrieve a device and its metadata from a device registry:

C#

public static object GetDevice(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
    {
        var device = cloudIot.Projects.Locations.Registries.Devices.Get(name).Execute();
        Console.WriteLine("Device: ");
        Console.WriteLine($"{device.Id}");
        Console.WriteLine($"\tBlocked: {device.Blocked == true}");
        Console.WriteLine($"\tConfig version: {device.Config.Version}");
        Console.WriteLine($"\tFirst Credential Expiry: {device.Credentials.First().ExpirationTime}");
        Console.WriteLine($"\tLast State Time:{device.LastStateTime}");
        Console.WriteLine($"\tName: {device.Name}");
        Console.WriteLine($"\tState:{device.State}");
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go

// 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, registry, device)
response, err := client.Projects.Locations.Registries.Devices.Get(path).Do()
if err != nil {
	return nil, err
}

fmt.Println("\tId: ", response.Id)
for _, credential := range response.Credentials {
	fmt.Println("\t\tCredential Expire: ", credential.ExpirationTime)
	fmt.Println("\t\tCredential Type: ", credential.PublicKey.Format)
	fmt.Println("\t\t--------")
}
fmt.Println("\tLast Config Ack: ", response.LastConfigAckTime)
fmt.Println("\tLast Config Send: ", response.LastConfigSendTime)
fmt.Println("\tLast Event Time: ", response.LastEventTime)
fmt.Println("\tLast Heartbeat Time: ", response.LastHeartbeatTime)
fmt.Println("\tLast State Time: ", response.LastStateTime)
fmt.Println("\tNumId: ", response.NumId)

return response, err

Java

/** Retrieves device metadata from a registry. **/
public static Device getDevice(String deviceId, String projectId, String cloudRegion,
                               String registryName) throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(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 " + devicePath);
  return service.projects().locations().registries().devices().get(devicePath).execute();
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const deviceId = 'my-device';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;
const request = {
  name: `${registryName}/devices/${deviceId}`
};

client.projects.locations.registries.devices.get(request, (err, data) => {
  if (err) {
    console.log('Could not find device:', deviceId);
    console.log(err);
  } else {
    console.log('Found device:', deviceId);
    console.log(data);
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;
use Google\Cloud\Iot\V1\PublicKeyFormat;

/**
 * Retrieve the device with the given id.
 *
 * @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(
    $registryId,
    $deviceId,
    $projectId,
    $location = 'us-central1'
) {
    print('Getting device' . PHP_EOL);

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

    $device = $deviceManager->getDevice($deviceName);

    $formats = [
        PublicKeyFormat::UNSPECIFIED_PUBLIC_KEY_FORMAT => 'unspecified',
        PublicKeyFormat::RSA_X509_PEM => 'RSA_X509_PEM',
        PublicKeyFormat::ES256_PEM => 'ES256_PEM',
        PublicKeyFormat::RSA_PEM => 'RSA_PEM',
        PublicKeyFormat::ES256_X509_PEM => 'ES256_X509_PEM',
    ];

    printf('ID: %s' . PHP_EOL, $device->getId());
    printf('Name: %s' . PHP_EOL, $device->getName());
    foreach ($device->getCredentials() as $credential) {
        print('Certificate:' . PHP_EOL);
        printf('    Format: %s' . PHP_EOL,
            $formats[$credential->getPublicKey()->getFormat()]);
        printf('    Expiration: %s' . PHP_EOL,
            $credential->getExpirationTime()->toDateTime()->format('Y-m-d H:i:s'));
    }
    printf('Data: %s' . PHP_EOL, $device->getConfig()->getBinaryData());
    printf('Version: %s' . PHP_EOL, $device->getConfig()->getVersion());
    printf('Update Time: %s' . PHP_EOL,
        $device->getConfig()->getCloudUpdateTime()->toDateTime()->format('Y-m-d H:i:s'));
}

Python

This sample uses the Google API Client Library for Python.
def get_device(
        service_account_json, project_id, cloud_region, registry_id,
        device_id):
    """Retrieve the device with the given id."""
    print('Getting device')
    client = get_client(service_account_json)
    registry_name = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)

    device_name = '{}/devices/{}'.format(registry_name, device_id)
    devices = client.projects().locations().registries().devices()
    device = devices.get(name=device_name).execute()

    print('Id : {}'.format(device.get('id')))
    print('Name : {}'.format(device.get('name')))
    print('Credentials:')
    if device.get('credentials') is not None:
        for credential in device.get('credentials'):
            keyinfo = credential.get('publicKey')
            print('\tcertificate: \n{}'.format(keyinfo.get('key')))
            print('\tformat : {}'.format(keyinfo.get('format')))
            print('\texpiration: {}'.format(credential.get('expirationTime')))

    print('Config:')
    print('\tdata: {}'.format(device.get('config').get('data')))
    print('\tversion: {}'.format(device.get('config').get('version')))
    print('\tcloudUpdateTime: {}'.format(device.get('config').get(
            'cloudUpdateTime')))

    return device

Ruby

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

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 devices in the provided region
device = iot_client.get_project_location_registry_device(
  resource
)

puts "Device: #{device.id}"
puts "\tBlocked: #{device.blocked}"
puts "\tLast Event Time: #{device.last_event_time}"
puts "\tLast State Time: #{device.last_state_time}"
puts "\tName: #{device.name}"
puts "\tCertificate formats:"
if device.credentials
  device.credentials.each { |cert| puts "\t\t#{cert.public_key.format}"}
else
  puts "\t\tNo certificates for device"
end

The following sample shows how to retrieve device state from a device registry:

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

// 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, registry, device)
response, err := client.Projects.Locations.Registries.Devices.States.List(path).Do()
if err != nil {
	return nil, err
}

fmt.Println("Successfully retrieved device states!")

for _, state := range response.DeviceStates {
	fmt.Println(state.UpdateTime, " : ", state.BinaryData)
}

Java

/** Retrieves device metadata from a registry. **/
public static List<DeviceState> getDeviceStates(
    String deviceId, String projectId, String cloudRegion, String registryName)
    throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(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

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const deviceId = 'my-device';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;
const request = {
  name: `${registryName}/devices/${deviceId}`
};

client.projects.locations.registries.devices.states.list(request,
  (err, data) => {
    if (err) {
      console.log('Could not find device:', deviceId);
      console.log(err);
    } else {
      console.log('State:', data);
    }
  });

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

This sample uses the Google API Client Library for Python.
def get_state(
        service_account_json, project_id, cloud_region, registry_id,
        device_id):
    """Retrieve a device's state blobs."""
    client = get_client(service_account_json)
    registry_name = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)

    device_name = '{}/devices/{}'.format(registry_name, device_id)
    devices = client.projects().locations().registries().devices()
    state = devices.states().list(name=device_name, numStates=5).execute()

    print('State: {}\n'.format(state))

    return state

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
res = iot_client.list_project_location_registry_device_states(
  resource
)
if res.device_states
  res.device_states.each do |state|
    puts "#{state.update_time}: #{state.binary_data}"
  end
else
  puts "No state messages"
end

See the Device Management Samples for more code samples.

Deleting devices and registries

You can delete devices and registries using GCP Console, the API, or gcloud. To delete a registry, first delete all the devices within it.

Console

To delete a device:

  1. Go to the Device registries page in GCP Console.

    Go to the Device registries page

  2. Click the ID of the registry for the device.

  3. Click the ID of the device to go to the Device details page.

  4. Click the trash can icon on the Device details page in Cloud Platform Console.

To delete a registry:

  1. Go to the Device registries page in GCP Console.

    Go to the Device registries page

  2. Click the ID of the registry for the device.

  3. Click the trash can icon on the Registry details page in Cloud Platform Console.

gcloud

To delete a device, run the gcloud iot devices delete command:

gcloud iot devices delete DEVICE_ID \
  --project=PROJECT_ID \
  --registry=REGISTRY_ID \
  --region=REGION

To delete a registry, run the gcloud iot registries delete command:

gcloud iot registries delete REGISTRY_ID \
  --project=PROJECT_ID \
  --region=REGION

API

Use the following methods to delete devices and registries:

The following sample shows how to delete a device from a registry:

C#

public static object DeleteDevice(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
    {
        var res = cloudIot.Projects.Locations.Registries.Devices.Delete(name).Execute();
        Console.WriteLine($"Removed device: {deviceId}");
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go

// 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, registry, deviceID)
response, err := client.Projects.Locations.Registries.Devices.Delete(path).Do()
if err != nil {
	return nil, err
}

fmt.Println("Deleted device!")

Java

/** Delete the given device from the registry. */
public static void deleteDevice(String deviceId, String projectId, String cloudRegion,
                                String registryName)
    throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(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("Deleting device " + devicePath);
  service.projects().locations().registries().devices().delete(devicePath).execute();
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;
const request = {
  name: `${registryName}/devices/${deviceId}`
};

client.projects.locations.registries.devices.delete(request, (err, data) => {
  if (err) {
    console.log('Could not delete device:', deviceId);
    console.log(err);
  } else {
    console.log('Successfully deleted device:', deviceId);
    console.log(data);
    if (cb) {
      cb();
    }
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;

/**
 * Delete the device with the given id.
 *
 * @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 delete_device(
    $registryId,
    $deviceId,
    $projectId,
    $location = 'us-central1'
) {
    print('Deleting Device' . PHP_EOL);

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

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

    printf('Deleted %s' . PHP_EOL, $deviceName);
}

Python

This sample uses the Google API Client Library for Python.
def delete_device(
        service_account_json, project_id, cloud_region, registry_id,
        device_id):
    """Delete the device with the given id."""
    print('Delete device')
    client = get_client(service_account_json)
    registry_name = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)

    device_name = '{}/devices/{}'.format(registry_name, device_id)

    devices = client.projects().locations().registries().devices()
    return devices.delete(name=device_name).execute()

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region the registry is located in"
# registry_id = "The registry to create a device in"
# device_id   = "The identifier of the device to create"

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}"
device_path = "#{parent}/registries/#{registry_id}/devices/#{device_id}"

# Create the device
res = iot_client.delete_project_location_registry_device(
  device_path
)

puts "Deleted device."

The following sample shows how to delete a registry:

C#

public static object DeleteRegistry(string projectId, string cloudRegion, string registryId)
{
    var cloudIot = CreateAuthorizedClient();
    // The resource name of the location associated with the key rings.
    var name = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";

    try
    {
        var registry = cloudIot.Projects.Locations.Registries.Delete(name).Execute();
    }
    catch (Google.GoogleApiException e)
    {
        Console.WriteLine(e.Message);
        if (e.Error != null) return e.Error.Code;
        return -1;
    }
    return 0;
}

Go

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

name := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
response, err := client.Projects.Locations.Registries.Delete(name).Do()
if err != nil {
	return nil, err
}

fmt.Println("Deleted registry")

Java

/** Delete this registry from Cloud IoT. */
public static void deleteRegistry(String cloudRegion, String projectId, String registryName)
    throws GeneralSecurityException, IOException {
  GoogleCredential credential =
      GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
  JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
  HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential);
  final CloudIot service = new CloudIot.Builder(
      GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init)
      .setApplicationName(APP_NAME).build();

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

  System.out.println("Deleting: " + registryPath);
  service.projects().locations().registries().delete(registryPath).execute();
}

Node.js

// Client retrieved in callback
// getClient(serviceAccountJson, function(client) {...});
// const cloudRegion = 'us-central1';
// const projectId = 'adjective-noun-123';
// const registryId = 'my-registry';
const parentName = `projects/${projectId}/locations/${cloudRegion}`;
const registryName = `${parentName}/registries/${registryId}`;
const request = {
  name: registryName
};

client.projects.locations.registries.delete(request, (err, data) => {
  if (err) {
    console.log('Could not delete registry');
    console.log(err);
  } else {
    console.log('Successfully deleted registry');
    console.log(data);
  }
});

PHP

use Google\Cloud\Iot\V1\DeviceManagerClient;

/**
 * Deletes the specified registry.
 *
 * @param string $registryId IOT Device Registry ID
 * @param string $projectId Google Cloud project ID
 * @param string $location (Optional) Google Cloud region
 */
function delete_registry(
    $registryId,
    $projectId,
    $location = 'us-central1'
) {
    // Instantiate a client.
    $deviceManager = new DeviceManagerClient();

    // Format the full registry path
    $registryName = $deviceManager->registryName($projectId, $location, $registryId);

    $deviceManager->deleteDeviceRegistry($registryName);

    printf('Deleted Registry %s' . PHP_EOL, $registryId);
}

Python

This sample uses the Google API Client Library for Python.
def delete_registry(
       service_account_json, project_id, cloud_region, registry_id):
    """Deletes the specified registry."""
    print('Delete registry')
    client = get_client(service_account_json)
    registry_name = 'projects/{}/locations/{}/registries/{}'.format(
            project_id, cloud_region, registry_id)

    registries = client.projects().locations().registries()
    return registries.delete(name=registry_name).execute()

Ruby

# project_id  = "Your Google Cloud project ID"
# location_id = "The Cloud region that you created the registry in"
# registry_id = "The Google Cloud IoT Core device registry identifier"

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
resource = "projects/#{project_id}/locations/#{location_id}/registries/#{registry_id}"

result = iot_client.delete_project_location_registry(resource)
puts "Deleted registry: #{registry_id}"

See the Registry Management Samples and Device Management Samples for more code samples.

What's next

Send feedback about...

Google Cloud Internet of Things Core