From bb373d192e423e74a2699425fd050e12a28fbfac Mon Sep 17 00:00:00 2001 From: Mike Ganbold Date: Wed, 6 Feb 2019 14:55:34 -0800 Subject: [PATCH 1/6] gateway crud update --- iot/api-client/manager/README.md | 49 +- iot/api-client/manager/pom.xml | 4 +- .../iot/examples/DeviceRegistryExample.java | 792 ++++++++++++++---- .../DeviceRegistryExampleOptions.java | 81 +- .../example/cloud/iot/examples/ManagerIT.java | 252 +++--- 5 files changed, 859 insertions(+), 319 deletions(-) diff --git a/iot/api-client/manager/README.md b/iot/api-client/manager/README.md index 02271d0bbba..ad694c3c2b2 100644 --- a/iot/api-client/manager/README.md +++ b/iot/api-client/manager/README.md @@ -16,7 +16,7 @@ the sample every time you run it. Run the following command to install the libraries and build the sample with Maven: -mvn clean compile assembly:single + mvn clean compile assembly:single ## Running the sample @@ -166,6 +166,53 @@ Patch a device with RSA: -device_id=java-device-0 \ -command=patch-device-rsa" +Create a gateway: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -public_key_file ../rsa_cert.pem \ + -gateway_id=java-gateway-0 \ + -command=create-gateway" + +Bind a device to a gateway: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -gateway_id=java-gateway-0 \ + -device_id=java-device-0 \ + -command=bind-device-to-gateway" + +Unbind a device to a gateway: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -gateway_id=java-gateway-0 \ + -device_id=java-device-0 \ + -command=unbind-device-from-gateway" + +List gateways in a registry. + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -command=list-gateways" + +List devices bound to a gateway. + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -gateway_id=your-gateway-id \ + -command=list-devices-for-gateway" + # Cloud IoT Core Java HTTP example diff --git a/iot/api-client/manager/pom.xml b/iot/api-client/manager/pom.xml index e58b8b56ae1..3ea79c6a314 100644 --- a/iot/api-client/manager/pom.xml +++ b/iot/api-client/manager/pom.xml @@ -61,7 +61,7 @@ com.google.apis google-api-services-cloudiot - v1-rev49-1.25.0 + v1-rev20181120-1.27.0 com.google.cloud @@ -71,7 +71,7 @@ com.google.oauth-client google-oauth-client - 1.22.0 + 1.23.0 com.google.guava diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java index 381d8bbefce..3d530dc96fb 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -24,19 +24,7 @@ import com.google.api.client.util.Charsets; import com.google.api.services.cloudiot.v1.CloudIot; import com.google.api.services.cloudiot.v1.CloudIotScopes; -import com.google.api.services.cloudiot.v1.model.Device; -import com.google.api.services.cloudiot.v1.model.DeviceConfig; -import com.google.api.services.cloudiot.v1.model.DeviceCredential; -import com.google.api.services.cloudiot.v1.model.DeviceRegistry; -import com.google.api.services.cloudiot.v1.model.DeviceState; -import com.google.api.services.cloudiot.v1.model.EventNotificationConfig; -import com.google.api.services.cloudiot.v1.model.GetIamPolicyRequest; -import com.google.api.services.cloudiot.v1.model.ListDeviceStatesResponse; -import com.google.api.services.cloudiot.v1.model.ModifyCloudToDeviceConfigRequest; -import com.google.api.services.cloudiot.v1.model.PublicKeyCredential; -import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceRequest; -import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceResponse; -import com.google.api.services.cloudiot.v1.model.SetIamPolicyRequest; +import com.google.api.services.cloudiot.v1.model.*; import com.google.cloud.Role; import com.google.cloud.pubsub.v1.TopicAdminClient; import com.google.common.io.Files; @@ -46,12 +34,16 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; import org.apache.commons.cli.HelpFormatter; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; /** * Example of using Cloud IoT device manager API to administer devices, registries and projects. @@ -66,9 +58,9 @@ * *

Before running the example, we have to create private and public keys, as described in * cloud.google.com/iot. Since we are interacting with the device manager, we will only use the - * public keys. The private keys are used to sign JWTs to authenticate devices. See the - * MQTT client example - * for more information. + * public keys. The private keys are used to sign JWTs to authenticate devices. See the MQTT + * client example for more information. * *

Finally, compile and run the example with: * @@ -114,16 +106,17 @@ public static Topic createIotTopic(String projectId, String topicId) throws Exce // [START iot_create_registry] /** Create a registry for Cloud IoT. */ - public static void createRegistry(String cloudRegion, String projectId, String registryName, - String pubsubTopicPath) + 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 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; @@ -136,8 +129,8 @@ public static void createRegistry(String cloudRegion, String projectId, String r registry.setEventNotificationConfigs(notificationConfigs); registry.setId(registryName); - DeviceRegistry reg = service.projects().locations().registries().create(projectPath, - registry).execute(); + DeviceRegistry reg = + service.projects().locations().registries().create(projectPath, registry).execute(); System.out.println("Created registry: " + reg.getName()); } // [END iot_create_registry] @@ -150,12 +143,14 @@ public static void deleteRegistry(String cloudRegion, String projectId, String r 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 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); + 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(); @@ -164,18 +159,20 @@ public static void deleteRegistry(String cloudRegion, String projectId, String r // [START iot_list_devices] /** Print all of the devices in this registry to standard out. */ - public static void listDevices(String projectId, String cloudRegion, String registryName) throws - GeneralSecurityException, IOException { + 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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); List devices = service @@ -205,26 +202,32 @@ public static void listDevices(String projectId, String cloudRegion, String regi // [START iot_create_es_device] /** Create a device that is authenticated using ES256. */ - public static void createDeviceWithEs256(String deviceId, String publicKeyFilePath, - String projectId, String cloudRegion, String registryName) + 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 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); + 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(); + DeviceCredential devCredential = new DeviceCredential(); devCredential.setPublicKey(publicKeyCredential); System.out.println("Creating device with id: " + deviceId); @@ -247,20 +250,25 @@ public static void createDeviceWithEs256(String deviceId, String publicKeyFilePa // [START iot_create_rsa_device] /** Create a device that is authenticated using RS256. */ - public static void createDeviceWithRs256(String deviceId, String certificateFilePath, - String projectId, String cloudRegion, - String registryName) + 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 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); + 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); @@ -294,19 +302,20 @@ public static void createDeviceWithRs256(String deviceId, String certificateFile *

This is a valid way to construct a device, however until it is patched with a credential the * device will not be able to connect to Cloud IoT. */ - public static void createDeviceWithNoAuth(String deviceId, String projectId, String cloudRegion, - String registryName) + public static void createDeviceWithNoAuth( + 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 CloudIot service = + new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) + .setApplicationName(APP_NAME) + .build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; + final String registryPath = + "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; System.out.println("Creating device with id: " + deviceId); Device device = new Device(); @@ -327,19 +336,22 @@ public static void createDeviceWithNoAuth(String deviceId, String projectId, Str // [START iot_delete_device] /** Delete the given device from the registry. */ - public static void deleteDevice(String deviceId, String projectId, String cloudRegion, - String registryName) + 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 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); + 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(); @@ -347,19 +359,23 @@ public static void deleteDevice(String deviceId, String projectId, String cloudR // [END iot_delete_device] // [START iot_get_device] - /** Retrieves device metadata from a registry. **/ - public static Device getDevice(String deviceId, String projectId, String cloudRegion, - String registryName) throws GeneralSecurityException, IOException { + /** 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 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); + 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(); @@ -367,7 +383,7 @@ public static Device getDevice(String deviceId, String projectId, String cloudRe // [END iot_get_device] // [START iot_get_device_state] - /** Retrieves device metadata from a registry. **/ + /** Retrieves device metadata from a registry. * */ public static List getDeviceStates( String deviceId, String projectId, String cloudRegion, String registryName) throws GeneralSecurityException, IOException { @@ -375,29 +391,27 @@ public static List getDeviceStates( 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 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); + 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(); + ListDeviceStatesResponse resp = + service.projects().locations().registries().devices().states().list(devicePath).execute(); return resp.getDeviceStates(); } // [END iot_get_device_state] // [START iot_get_registry] - /** Retrieves registry metadata from a project. **/ + /** Retrieves registry metadata from a project. * */ public static DeviceRegistry getRegistry( String projectId, String cloudRegion, String registryName) throws GeneralSecurityException, IOException { @@ -405,12 +419,14 @@ public static DeviceRegistry getRegistry( 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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); return service.projects().locations().registries().get(registryPath).execute(); } @@ -425,12 +441,15 @@ public static void listDeviceConfigs( 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 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); + final String devicePath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); System.out.println("Listing device configs for " + devicePath); List deviceConfigs = @@ -460,9 +479,10 @@ public static void listRegistries(String projectId, String cloudRegion) 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 CloudIot service = + new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) + .setApplicationName(APP_NAME) + .build(); final String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; @@ -477,7 +497,7 @@ public static void listRegistries(String projectId, String cloudRegion) if (registries != null) { System.out.println("Found " + registries.size() + " registries"); - for (DeviceRegistry r: registries) { + for (DeviceRegistry r : registries) { System.out.println("Id: " + r.getId()); System.out.println("Name: " + r.getName()); if (r.getMqttConfig() != null) { @@ -493,19 +513,26 @@ public static void listRegistries(String projectId, String cloudRegion) // [START iot_patch_es] /** Patch the device to add an ES256 key for authentication. */ - public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, String projectId, - String cloudRegion, String registryName) + public static void patchEs256ForAuth( + 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 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); + 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); @@ -534,20 +561,26 @@ public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, // [START iot_patch_rsa] /** Patch the device to add an RSA256 key for authentication. */ - public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, String projectId, - String cloudRegion, - String registryName) + 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 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); + 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); @@ -577,19 +610,26 @@ public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, // [START iot_set_device_config] /** Set a device configuration to the specified data (string, JSON) and version (0 for latest). */ public static void setDeviceConfiguration( - String deviceId, String projectId, String cloudRegion, String registryName, - String data, long version) + String deviceId, + String projectId, + String cloudRegion, + String registryName, + String data, + long version) 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 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); + final String devicePath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); ModifyCloudToDeviceConfigRequest req = new ModifyCloudToDeviceConfigRequest(); req.setVersionToUpdate(version); @@ -605,7 +645,8 @@ public static void setDeviceConfiguration( .locations() .registries() .devices() - .modifyCloudToDeviceConfig(devicePath, req).execute(); + .modifyCloudToDeviceConfig(devicePath, req) + .execute(); System.out.println("Updated: " + config.getVersion()); } @@ -613,26 +654,28 @@ public static void setDeviceConfiguration( // [START iot_get_iam_policy] /** Retrieves IAM permissions for the given registry. */ - public static void getIamPermissions( - String projectId, String cloudRegion, String registryName) + public static void getIamPermissions(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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); com.google.api.services.cloudiot.v1.model.Policy policy = service .projects() .locations() .registries() - .getIamPolicy(registryPath, new GetIamPolicyRequest()).execute(); + .getIamPolicy(registryPath, new GetIamPolicyRequest()) + .execute(); System.out.println("Policy ETAG: " + policy.getEtag()); @@ -653,29 +696,30 @@ public static void getIamPermissions( // [START iot_set_iam_policy] /** Sets IAM permissions for the given registry. */ public static void setIamPermissions( - String projectId, String cloudRegion, String registryName, - String member, String role) + String projectId, String cloudRegion, String registryName, String member, String role) 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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); com.google.api.services.cloudiot.v1.model.Policy policy = service .projects() .locations() .registries() - .getIamPolicy(registryPath, new GetIamPolicyRequest()).execute(); + .getIamPolicy(registryPath, new GetIamPolicyRequest()) + .execute(); - List bindings = - policy.getBindings(); + List bindings = policy.getBindings(); boolean addNewRole = true; if (bindings != null) { @@ -705,15 +749,10 @@ public static void setIamPermissions( policy.setBindings(bindings); SetIamPolicyRequest req = new SetIamPolicyRequest().setPolicy(policy); - policy = - service - .projects() - .locations() - .registries() - .setIamPolicy(registryPath, req).execute(); + policy = service.projects().locations().registries().setIamPolicy(registryPath, req).execute(); System.out.println("Policy ETAG: " + policy.getEtag()); - for (com.google.api.services.cloudiot.v1.model.Binding binding: policy.getBindings()) { + for (com.google.api.services.cloudiot.v1.model.Binding binding : policy.getBindings()) { System.out.println(String.format("Role: %s", binding.getRole())); System.out.println("Binding members: "); for (String mem : binding.getMembers()) { @@ -723,7 +762,7 @@ public static void setIamPermissions( } // [END iot_set_iam_policy] - /** Send a command to a device. **/ + /** Send a command to a device. * */ // [START send_command] public static void sendCommand( String deviceId, String projectId, String cloudRegion, String registryName, String data) @@ -732,12 +771,15 @@ public static void sendCommand( 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 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); + final String devicePath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); SendCommandToDeviceRequest req = new SendCommandToDeviceRequest(); @@ -753,12 +795,334 @@ public static void sendCommand( .locations() .registries() .devices() - .sendCommandToDevice(devicePath, req).execute(); + .sendCommandToDevice(devicePath, req) + .execute(); System.out.println("Command response: " + res.toString()); } // [END send_command] + public static void bindDeviceToGateway( + String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) + throws GeneralSecurityException, IOException { + // [START bind_device_to_gateway] + createDevice(projectId, cloudRegion, registryName, deviceId); + + 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); + + BindDeviceToGatewayRequest request = new BindDeviceToGatewayRequest(); + request.setDeviceId(deviceId); + request.setGatewayId(gatewayId); + + BindDeviceToGatewayResponse response = + service + .projects() + .locations() + .registries() + .bindDeviceToGateway(registryPath, request) + .execute(); + + System.out.println(String.format("Device bound: %s", response.toPrettyString())); + // [END bind_device_to_gateway] + } + + public static void unbindDeviceFromGateway( + String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) + throws GeneralSecurityException, IOException { + // [START unbind_device_from_gateway] + 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); + + UnbindDeviceFromGatewayRequest request = new UnbindDeviceFromGatewayRequest(); + request.setDeviceId(deviceId); + request.setGatewayId(gatewayId); + + UnbindDeviceFromGatewayResponse response = + service + .projects() + .locations() + .registries() + .unbindDeviceFromGateway(registryPath, request) + .execute(); + + System.out.println(String.format("Device unbound: %s", response.toPrettyString())); + // [END unbind_device_from_gateway] + } + + public static void sendDataFromDevice( + MqttClient client, String deviceId, String messageType, String data) throws MqttException { + // [START send_data_from_bound_device] + if (!messageType.equals("events") && !messageType.equals("state")) { + System.err.println("Invalid message type, must ether be 'state' or events'"); + return; + } + final String dataTopic = String.format("/devices/%s/%s", deviceId, messageType); + MqttMessage message = new MqttMessage(data.getBytes()); + message.setQos(1); + client.publish(dataTopic, message); + System.out.println("Data sent"); + // [END send_data_from_bound_device] + } + + public static void attachDeviceToGateway(MqttClient client, String deviceId) + throws MqttException { + // [START attach_device] + final String attachTopic = String.format("/devices/%s/attach", deviceId); + System.out.println(String.format("Attaching: %s", attachTopic)); + String attachPayload = "{}"; + MqttMessage message = new MqttMessage(attachPayload.getBytes()); + message.setQos(1); + client.publish(attachTopic, message); + // [END attach_device] + } + + /** Detaches a bound device from the Gateway. */ + public static void detachDeviceFromGateway(MqttClient client, String deviceId) + throws MqttException { + // [START detach_device] + final String detachTopic = String.format("/devices/%s/detach", deviceId); + System.out.println(String.format("Detaching: %s", detachTopic)); + String attachPayload = "{}"; + MqttMessage message = new MqttMessage(attachPayload.getBytes()); + message.setQos(1); + client.publish(detachTopic, message); + // [END detach_device] + } + + /** Create a device to bind to a gateway. */ + public static void createDevice( + String projectId, String cloudRegion, String registryName, String deviceId) + throws GeneralSecurityException, IOException { + // [START create_device] + 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 devices = + service + .projects() + .locations() + .registries() + .devices() + .list(registryPath) + .setFieldMask("config,gatewayConfig") + .execute() + .getDevices(); + + if (devices != null) { + System.out.println("Found " + devices.size() + " devices"); + for (Device d : devices) { + if ((d.getId() != null && d.getId().equals(deviceId)) + || (d.getName() != null && d.getName().equals(deviceId))) { + System.out.println("Device exists, skipping."); + return; + } + } + } + + System.out.println("Creating device with id: " + deviceId); + Device device = new Device(); + device.setId(deviceId); + + GatewayConfig gwConfig = new GatewayConfig(); + gwConfig.setGatewayType("NON_GATEWAY"); + gwConfig.setGatewayAuthMethod("ASSOCIATION_ONLY"); + + device.setGatewayConfig(gwConfig); + Device createdDevice = + service + .projects() + .locations() + .registries() + .devices() + .create(registryPath, device) + .execute(); + + System.out.println("Created device: " + createdDevice.toPrettyString()); + // [END create_device] + } + + /** Create a gateway to bind devices to. */ + public static void createGateway( + String projectId, + String cloudRegion, + String registryName, + String gatewayId, + String certificateFilePath, + String algorithm) + throws GeneralSecurityException, IOException { + // [START create_gateway] + 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("Creating gateway with id: " + gatewayId); + Device device = new Device(); + device.setId(gatewayId); + + GatewayConfig gwConfig = new GatewayConfig(); + gwConfig.setGatewayType("GATEWAY"); + gwConfig.setGatewayAuthMethod("ASSOCIATION_ONLY"); + + String keyFormat = "RSA_X509_PEM"; + if (algorithm == "ES256") { + keyFormat = "ES256_PEM"; + } + + PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); + + byte[] keyBytes = java.nio.file.Files.readAllBytes(Paths.get(certificateFilePath)); + publicKeyCredential.setKey(new String(keyBytes)); + publicKeyCredential.setFormat(keyFormat); + DeviceCredential deviceCredential = new DeviceCredential(); + deviceCredential.setPublicKey(publicKeyCredential); + + device.setGatewayConfig(gwConfig); + device.setCredentials(Arrays.asList(deviceCredential)); + Device createdDevice = + service + .projects() + .locations() + .registries() + .devices() + .create(registryPath, device) + .execute(); + + System.out.println("Created gateway: " + createdDevice.toPrettyString()); + // [END create_gateway] + } + + public static void listGateways(String projectId, String cloudRegion, String registryName) + throws IOException, GeneralSecurityException { + // [START list_gateways] + 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 devices = + service + .projects() + .locations() + .registries() + .devices() + .list(registryPath) + .setFieldMask("config,gatewayConfig") + .execute() + .getDevices(); + + if (devices != null) { + System.out.println("Found " + devices.size() + " devices"); + for (Device d : devices) { + if (d.getGatewayConfig() != null + && d.getGatewayConfig().getGatewayType() != null + && d.getGatewayConfig().getGatewayType().equals("GATEWAY")) { + 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.getGatewayConfig().toPrettyString()); + } + System.out.println(); + } + } + } else { + System.out.println("Registry has no devices."); + } + // [END list_gateways] + } + + /** List devices bound to a gateway. */ + public static void listDevicesForGateway( + String projectId, String cloudRegion, String registryName, String gatewayId) + throws IOException, GeneralSecurityException { + // [START list_devices_for_gateway] + 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 gatewayPath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, gatewayId); + + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); + + List deviceNumIds = + service + .projects() + .locations() + .registries() + .devices() + .list(registryPath) + .setGatewayListOptionsAssociationsGatewayId(gatewayId) + .execute() + .getDevices(); + + if (deviceNumIds != null) { + System.out.println("Found " + deviceNumIds.size() + " devices"); + for (Device device : deviceNumIds) { + System.out.println(String.format("ID: %s", device.getId())); + } + } else { + System.out.println("Gateway has no bound devices."); + } + // [END list_devices_for_gateway] + } + /** Entry poit for CLI. */ public static void main(String[] args) throws Exception { DeviceRegistryExampleOptions options = DeviceRegistryExampleOptions.fromFlags(args); @@ -768,34 +1132,61 @@ public static void main(String[] args) throws Exception { } switch (options.command) { + case "bind-device-to-gateway": + System.out.println("Binding device to gateway:"); + bindDeviceToGateway( + options.projectId, + options.cloudRegion, + options.registryName, + options.deviceId, + options.gatewayId); + break; + case "create-gateway": + System.out.println("Creating Gateway:"); + createGateway( + options.projectId, + options.cloudRegion, + options.registryName, + options.gatewayId, + options.publicKeyFile, + options.algorithm); + break; case "create-iot-topic": System.out.println("Create IoT Topic:"); createIotTopic(options.projectId, options.pubsubTopic); break; case "create-es": System.out.println("Create ES Device:"); - createDeviceWithEs256(options.deviceId, options.ecPublicKeyFile, options.projectId, - options.cloudRegion, options.registryName); + createDeviceWithEs256( + options.deviceId, + options.ecPublicKeyFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "create-rsa": System.out.println("Create RSA Device:"); - createDeviceWithRs256(options.deviceId, options.rsaCertificateFile, options.projectId, - options.cloudRegion, options.registryName); + createDeviceWithRs256( + options.deviceId, + options.rsaCertificateFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "create-unauth": System.out.println("Create Unauth Device"); - createDeviceWithNoAuth(options.deviceId, options.projectId, options.cloudRegion, - options.registryName); + createDeviceWithNoAuth( + options.deviceId, options.projectId, options.cloudRegion, options.registryName); break; case "create-registry": System.out.println("Create registry"); - createRegistry(options.cloudRegion, options.projectId, options.registryName, - options.pubsubTopic); + createRegistry( + options.cloudRegion, options.projectId, options.registryName, options.pubsubTopic); break; case "delete-device": System.out.println("Delete device"); - deleteDevice(options.deviceId, options.projectId, options.cloudRegion, - options.registryName); + deleteDevice( + options.deviceId, options.projectId, options.cloudRegion, options.registryName); break; case "delete-registry": System.out.println("Delete registry"); @@ -803,9 +1194,10 @@ public static void main(String[] args) throws Exception { break; case "get-device": System.out.println("Get device"); - System.out.println(getDevice(options.deviceId, options.projectId, options.cloudRegion, - options.registryName) - .toPrettyString()); + System.out.println( + getDevice( + options.deviceId, options.projectId, options.cloudRegion, options.registryName) + .toPrettyString()); break; case "get-iam-permissions": System.out.println("Get iam permissions"); @@ -813,42 +1205,65 @@ public static void main(String[] args) throws Exception { break; case "get-device-state": System.out.println("Get device state"); - List states = getDeviceStates(options.deviceId, options.projectId, - options.cloudRegion, options.registryName); - for (DeviceState state: states) { + List states = + getDeviceStates( + options.deviceId, options.projectId, options.cloudRegion, options.registryName); + for (DeviceState state : states) { System.out.println(state.toPrettyString()); } break; case "get-registry": System.out.println("Get registry"); - System.out.println(getRegistry(options.projectId, options.cloudRegion, - options.registryName)); + System.out.println( + getRegistry(options.projectId, options.cloudRegion, options.registryName)); break; case "list-devices": System.out.println("List devices"); listDevices(options.projectId, options.cloudRegion, options.registryName); break; + case "list-gateways": + System.out.println("Listing gateways:"); + listGateways(options.projectId, options.cloudRegion, options.registryName); + break; + case "list-devices-for-gateway": + System.out.println("Listing devices for gateway:"); + listDevicesForGateway( + options.projectId, options.cloudRegion, options.registryName, options.gatewayId); + break; case "list-registries": System.out.println("List registries"); listRegistries(options.projectId, options.cloudRegion); break; case "patch-device-es": System.out.println("Patch device with ES"); - patchEs256ForAuth(options.deviceId, options.ecPublicKeyFile, options.projectId, - options.cloudRegion, options.registryName); + patchEs256ForAuth( + options.deviceId, + options.ecPublicKeyFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "patch-device-rsa": System.out.println("Patch device with RSA"); - patchRsa256ForAuth(options.deviceId, options.rsaCertificateFile, options.projectId, - options.cloudRegion, options.registryName); + patchRsa256ForAuth( + options.deviceId, + options.rsaCertificateFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "set-config": if (options.deviceId == null) { System.out.println("Specify device_id for the device you are updating."); } else { System.out.println("Setting device configuration"); - setDeviceConfiguration(options.deviceId, options.projectId, options.cloudRegion, - options.registryName, options.configuration, options.version); + setDeviceConfiguration( + options.deviceId, + options.projectId, + options.cloudRegion, + options.registryName, + options.configuration, + options.version); } break; case "set-iam-permissions": @@ -856,13 +1271,21 @@ public static void main(String[] args) throws Exception { System.out.println("Specify member and role for the policy you are updating."); } else { System.out.println("Setting iam permissions"); - setIamPermissions(options.projectId, options.cloudRegion, options.registryName, - options.member, options.role); + setIamPermissions( + options.projectId, + options.cloudRegion, + options.registryName, + options.member, + options.role); } break; case "send-command": System.out.println("Sending command to device:"); - sendCommand(options.deviceId, options.projectId, options.cloudRegion, options.registryName, + sendCommand( + options.deviceId, + options.projectId, + options.cloudRegion, + options.registryName, options.commandData); break; default: @@ -870,8 +1293,7 @@ public static void main(String[] args) throws Exception { String footer = "\nhttps://cloud.google.com/iot-core"; HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("DeviceRegistryExample", header, options.options, footer, - true); + formatter.printHelp("DeviceRegistryExample", header, options.options, footer, true); break; } } diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java index e5079065f92..8dd754df6ea 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java @@ -26,6 +26,7 @@ /** Command line options for the Device Manager example. */ public class DeviceRegistryExampleOptions { + String algorithm; String projectId; String ecPublicKeyFile = "ec_public.pem"; String rsaCertificateFile = "rsa_cert.pem"; @@ -34,7 +35,9 @@ public class DeviceRegistryExampleOptions { String commandData = "Specify with --data"; String configuration = "Specify with -configuration"; String deviceId; // Default to UUID? + String gatewayId; String pubsubTopic; + String publicKeyFile; String registryName; String member; String role; @@ -51,28 +54,40 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc( "Command to run:" - + "\n\tcreate-iot-topic" // TODO: Descriptions or too verbose? - + "\n\tcreate-rsa" - + "\n\tcreate-es" - + "\n\tcreate-unauth" - + "\n\tcreate-registry" - + "\n\tdelete-device" - + "\n\tdelete-registry" - + "\n\tget-device" - + "\n\tget-device-state" - + "\n\tget-iam-permissions" - + "\n\tget-registry" - + "\n\tlist-devices" - + "\n\tlist-registries" - + "\n\tpatch-device-es" - + "\n\tpatch-device-rsa" - + "\n\tset-config" - + "\n\tset-iam-permissions" - + "\n\tsend-command") + + "\n\tbind-device-to-gateway" + + "\n\tcreate-gateway" + + "\n\tcreate-iot-topic" // TODO: Descriptions or too verbose? + + "\n\tcreate-rsa" + + "\n\tcreate-es" + + "\n\tcreate-unauth" + + "\n\tcreate-registry" + + "\n\tdelete-device" + + "\n\tdelete-registry" + + "\n\tget-device" + + "\n\tget-device-state" + + "\n\tget-iam-permissions" + + "\n\tget-registry" + + "\n\tlist-devices" + + "\n\tlist-registries" + + "\n\tlist-gateways" + + "\n\tlist-devices-for-gateway" + + "\n\tpatch-device-es" + + "\n\tpatch-device-rsa" + + "\n\tset-config" + + "\n\tset-iam-permissions" + + "\n\tsend-command" + + "\n\tunbind-device-from-gateway") .required() .build()); // Optional arguments. + options.addOption( + Option.builder() + .type(String.class) + .longOpt("algorithm") + .hasArg() + .desc("Algorithm used for public/private keys.") + .build()); options.addOption( Option.builder() .type(String.class) @@ -108,6 +123,13 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc("GCP cloud project name.") .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("public_key_file") + .hasArg() + .desc("Public key file used for registering devices and gateways.") + .build()); options.addOption( Option.builder() .type(String.class) @@ -122,6 +144,13 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc("Name for your Device.") .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("gateway_id") + .hasArg() + .desc("The identifier for the Gateway.") + .build()); options.addOption( Option.builder() .type(String.class) @@ -170,6 +199,9 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { throw new ParseException("Invalid command, showing help."); } + if (commandLine.hasOption("algorithm")) { + res.algorithm = commandLine.getOptionValue("algorithm"); + } if (commandLine.hasOption("cloud_region")) { res.cloudRegion = commandLine.getOptionValue("cloud_region"); } @@ -179,7 +211,9 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { if (commandLine.hasOption("device_id")) { res.deviceId = commandLine.getOptionValue("device_id"); } - + if (commandLine.hasOption("gateway_id")) { + res.gatewayId = commandLine.getOptionValue("gateway_id"); + } if (commandLine.hasOption("project_id")) { res.projectId = commandLine.getOptionValue("project_id"); } else { @@ -195,7 +229,9 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { } else { // TODO: Get from environment variable } - + if (commandLine.hasOption("public_key_file")) { + res.publicKeyFile = commandLine.getOptionValue("public_key_file"); + } if (commandLine.hasOption("ec_public_key_file")) { res.ecPublicKeyFile = commandLine.getOptionValue("ec_public_key_file"); } @@ -230,11 +266,10 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { String footer = "\nhttps://cloud.google.com/iot-core"; HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("DeviceRegistryExample", header, options, footer, - true); + formatter.printHelp("DeviceRegistryExample", header, options, footer, true); System.err.println(e.getMessage()); return null; } } -} \ No newline at end of file +} diff --git a/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java index 576c9a42f85..1d67cf84f1e 100644 --- a/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java +++ b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java @@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import org.eclipse.paho.client.mqttv3.MqttClient; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -29,7 +30,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - /** Tests for iot "Management" sample. */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") @@ -48,7 +48,6 @@ public class ManagerIT { private static final String MEMBER = "group:dpebot@google.com"; private static final String ROLE = "roles/viewer"; - private static Topic topic; @Before @@ -66,15 +65,13 @@ public void tearDown() throws Exception { @Test public void testPatchRsa() throws Exception { final String deviceName = "patchme-device-rsa"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); try { DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceRegistryExample.createDeviceWithNoAuth(deviceName, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); - DeviceRegistryExample.patchRsa256ForAuth(deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); + DeviceRegistryExample.createDeviceWithNoAuth( + deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.patchRsa256ForAuth( + deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); String got = bout.toString(); Assert.assertTrue(got.contains("Created device: {")); @@ -91,16 +88,14 @@ public void testPatchRsa() throws Exception { @Test public void testPatchEs() throws Exception { final String deviceName = "patchme-device-es"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); try { DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceRegistryExample.createDeviceWithNoAuth(deviceName, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); - DeviceRegistryExample.patchEs256ForAuth(deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); + DeviceRegistryExample.createDeviceWithNoAuth( + deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.patchEs256ForAuth( + deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); String got = bout.toString(); Assert.assertTrue(got.contains("Created device: {")); @@ -117,9 +112,7 @@ public void testPatchEs() throws Exception { @Test public void testCreateDeleteUnauthDevice() throws Exception { final String deviceName = "noauth-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithNoAuth(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -137,12 +130,10 @@ public void testCreateDeleteUnauthDevice() throws Exception { @Test public void testCreateDeleteEsDevice() throws Exception { final String deviceName = "es-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceRegistryExample.createDeviceWithEs256(deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); + DeviceRegistryExample.createDeviceWithEs256( + deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); DeviceRegistryExample.getDeviceStates(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); String got = bout.toString(); @@ -158,9 +149,7 @@ public void testCreateDeleteEsDevice() throws Exception { @Test public void testCreateDeleteRsaDevice() throws Exception { final String deviceName = "rsa-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -179,9 +168,7 @@ public void testCreateDeleteRsaDevice() throws Exception { @Test public void testCreateGetDevice() throws Exception { final String deviceName = "rsa-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -201,14 +188,12 @@ public void testCreateGetDevice() throws Exception { @Test public void testCreateConfigureDevice() throws Exception { final String deviceName = "rsa-device-config"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceRegistryExample.setDeviceConfiguration(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID, - "some-test-data", 0L); + DeviceRegistryExample.setDeviceConfiguration( + deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID, "some-test-data", 0L); String got = bout.toString(); Assert.assertTrue(got.contains("Updated: 2")); @@ -220,13 +205,10 @@ public void testCreateConfigureDevice() throws Exception { } } - @Test public void testCreateListDevices() throws Exception { final String deviceName = "rsa-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -245,9 +227,7 @@ public void testCreateListDevices() throws Exception { @Test public void testCreateGetRegistry() throws Exception { - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.getRegistry(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -262,9 +242,7 @@ public void testCreateGetRegistry() throws Exception { @Test public void testGetIam() throws Exception { - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.getIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -279,9 +257,7 @@ public void testGetIam() throws Exception { @Test public void testSetIam() throws Exception { - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.setIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, MEMBER, ROLE); DeviceRegistryExample.getIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -300,9 +276,7 @@ public void testSetIam() throws Exception { @Test public void testHttpDeviceEvent() throws Exception { final String deviceName = "rsa-device-http-event"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -337,9 +311,7 @@ public void testHttpDeviceEvent() throws Exception { @Test public void testHttpDeviceState() throws Exception { final String deviceName = "rsa-device-http-state"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -374,9 +346,7 @@ public void testHttpDeviceState() throws Exception { @Test public void testHttpDeviceConfig() throws Exception { final String deviceName = "rsa-device-http-state"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -409,14 +379,11 @@ public void testHttpDeviceConfig() throws Exception { } } - // MQTT device tests @Test public void testMqttDeviceConfig() throws Exception { final String deviceName = "rsa-device-mqtt-config"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -424,13 +391,13 @@ public void testMqttDeviceConfig() throws Exception { // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-message_type=events", - "-num_messages=1", - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-message_type=events", + "-num_messages=1", + "-algorithm=RS256" }; com.example.cloud.iot.examples.MqttExample.main(testArgs); // End device test. @@ -451,34 +418,33 @@ public void testMqttDeviceConfig() throws Exception { @Test public void testMqttDeviceCommand() throws Exception { final String deviceName = "rsa-device-mqtt-commands"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-cloud_region=" + CLOUD_REGION, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-wait_time=" + 10, - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-cloud_region=" + CLOUD_REGION, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-wait_time=" + 10, + "-algorithm=RS256" }; - Thread deviceThread = new Thread() { - public void run() { - try { - com.example.cloud.iot.examples.MqttExample.main(testArgs); - } catch (Exception e) { - // TODO: Fail - System.out.println("Failure on Exception"); - } - } - }; + Thread deviceThread = + new Thread() { + public void run() { + try { + com.example.cloud.iot.examples.MqttExample.main(testArgs); + } catch (Exception e) { + // TODO: Fail + System.out.println("Failure on Exception"); + } + } + }; deviceThread.start(); Thread.sleep(500); // Give the device a chance to connect @@ -506,9 +472,7 @@ public void run() { @Test public void testMqttDeviceEvents() throws Exception { final String deviceName = "rsa-device-mqtt-events"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -516,13 +480,13 @@ public void testMqttDeviceEvents() throws Exception { // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-message_type=events", - "-num_messages=1", - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-message_type=events", + "-num_messages=1", + "-algorithm=RS256" }; com.example.cloud.iot.examples.MqttExample.main(testArgs); // End device test. @@ -530,7 +494,7 @@ public void testMqttDeviceEvents() throws Exception { // Assertions String got = bout.toString(); // - //Finished loop successfully. Goodbye! + // Finished loop successfully. Goodbye! Assert.assertTrue(got.contains("Publishing events message 1")); Assert.assertTrue(got.contains("Finished loop successfully. Goodbye!")); @@ -546,9 +510,7 @@ public void testMqttDeviceEvents() throws Exception { @Test public void testMqttDeviceState() throws Exception { final String deviceName = "rsa-device-mqtt-state"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -556,12 +518,12 @@ public void testMqttDeviceState() throws Exception { // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-message_type=state", - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-message_type=state", + "-algorithm=RS256" }; com.example.cloud.iot.examples.MqttExample.main(testArgs); // End device test. @@ -578,4 +540,78 @@ public void testMqttDeviceState() throws Exception { topicAdminClient.deleteTopic(topic.getNameAsTopicName()); } } + + // Manager tests + @Test + public void testCreateGateway() throws Exception { + final String gatewayName = "rsa-create-gateway"; + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); + DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); + DeviceRegistryExample.createGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); + + // Assertions + String got = bout.toString(); + System.out.println(got); + Assert.assertTrue(got.contains("Created gateway:")); + + // Clean up + DeviceRegistryExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.deleteTopic(topic.getNameAsTopicName()); + } + } + + @Test + public void testListGateways() throws Exception { + final String gatewayName = "rsa-list-gateway"; + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); + DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); + DeviceRegistryExample.createGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); + DeviceRegistryExample.listGateways(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + + // Assertions + String got = bout.toString(); + System.out.println(got); + Assert.assertTrue(got.contains("Found 1 devices")); + Assert.assertTrue(got.contains(String.format("Id: %s", gatewayName))); + + // Clean up + DeviceRegistryExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.deleteTopic(topic.getNameAsTopicName()); + } + } + + @Test + public void testBindDeviceToGatewayAndUnbind() throws Exception { + final String gatewayName = "rsa-bind-gateway"; + final String deviceName = "rsa-bind-device"; + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); + DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); + DeviceRegistryExample.createGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); + DeviceRegistryExample.createDevice(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName); + DeviceRegistryExample.bindDeviceToGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); + DeviceRegistryExample.unbindDeviceFromGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); + + // Assertions + String got = bout.toString(); + System.out.println(got); + Assert.assertTrue(got.contains("Device bound: ")); + Assert.assertTrue(got.contains("Device unbound: ")); + + // Clean up + DeviceRegistryExample.deleteDevice(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.deleteTopic(topic.getNameAsTopicName()); + } + } } From 57fe9eebc4678943e1684cafcd37af29c5759e0a Mon Sep 17 00:00:00 2001 From: Mike Ganbold Date: Wed, 6 Feb 2019 14:55:34 -0800 Subject: [PATCH 2/6] gateway crud update --- iot/api-client/manager/README.md | 49 +- iot/api-client/manager/pom.xml | 4 +- .../iot/examples/DeviceRegistryExample.java | 791 ++++++++++++++---- .../DeviceRegistryExampleOptions.java | 81 +- .../example/cloud/iot/examples/ManagerIT.java | 252 +++--- 5 files changed, 867 insertions(+), 310 deletions(-) diff --git a/iot/api-client/manager/README.md b/iot/api-client/manager/README.md index 02271d0bbba..ad694c3c2b2 100644 --- a/iot/api-client/manager/README.md +++ b/iot/api-client/manager/README.md @@ -16,7 +16,7 @@ the sample every time you run it. Run the following command to install the libraries and build the sample with Maven: -mvn clean compile assembly:single + mvn clean compile assembly:single ## Running the sample @@ -166,6 +166,53 @@ Patch a device with RSA: -device_id=java-device-0 \ -command=patch-device-rsa" +Create a gateway: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -public_key_file ../rsa_cert.pem \ + -gateway_id=java-gateway-0 \ + -command=create-gateway" + +Bind a device to a gateway: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -gateway_id=java-gateway-0 \ + -device_id=java-device-0 \ + -command=bind-device-to-gateway" + +Unbind a device to a gateway: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -gateway_id=java-gateway-0 \ + -device_id=java-device-0 \ + -command=unbind-device-from-gateway" + +List gateways in a registry. + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -command=list-gateways" + +List devices bound to a gateway. + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_name=your-registry \ + -gateway_id=your-gateway-id \ + -command=list-devices-for-gateway" + # Cloud IoT Core Java HTTP example diff --git a/iot/api-client/manager/pom.xml b/iot/api-client/manager/pom.xml index e58b8b56ae1..3ea79c6a314 100644 --- a/iot/api-client/manager/pom.xml +++ b/iot/api-client/manager/pom.xml @@ -61,7 +61,7 @@ com.google.apis google-api-services-cloudiot - v1-rev49-1.25.0 + v1-rev20181120-1.27.0 com.google.cloud @@ -71,7 +71,7 @@ com.google.oauth-client google-oauth-client - 1.22.0 + 1.23.0 com.google.guava diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java index 381d8bbefce..89e951a62e1 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -24,19 +24,24 @@ import com.google.api.client.util.Charsets; import com.google.api.services.cloudiot.v1.CloudIot; import com.google.api.services.cloudiot.v1.CloudIotScopes; +import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayRequest; +import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayResponse; import com.google.api.services.cloudiot.v1.model.Device; import com.google.api.services.cloudiot.v1.model.DeviceConfig; import com.google.api.services.cloudiot.v1.model.DeviceCredential; import com.google.api.services.cloudiot.v1.model.DeviceRegistry; import com.google.api.services.cloudiot.v1.model.DeviceState; import com.google.api.services.cloudiot.v1.model.EventNotificationConfig; -import com.google.api.services.cloudiot.v1.model.GetIamPolicyRequest; +import com.google.api.services.cloudiot.v1.model.PublicKeyCredential; import com.google.api.services.cloudiot.v1.model.ListDeviceStatesResponse; import com.google.api.services.cloudiot.v1.model.ModifyCloudToDeviceConfigRequest; -import com.google.api.services.cloudiot.v1.model.PublicKeyCredential; -import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceRequest; -import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceResponse; +import com.google.api.services.cloudiot.v1.model.GatewayConfig; +import com.google.api.services.cloudiot.v1.model.GetIamPolicyRequest; import com.google.api.services.cloudiot.v1.model.SetIamPolicyRequest; +import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceResponse; +import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceRequest; +import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayRequest; +import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayResponse; import com.google.cloud.Role; import com.google.cloud.pubsub.v1.TopicAdminClient; import com.google.common.io.Files; @@ -46,12 +51,16 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; import org.apache.commons.cli.HelpFormatter; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; /** * Example of using Cloud IoT device manager API to administer devices, registries and projects. @@ -66,9 +75,9 @@ * *

Before running the example, we have to create private and public keys, as described in * cloud.google.com/iot. Since we are interacting with the device manager, we will only use the - * public keys. The private keys are used to sign JWTs to authenticate devices. See the - * MQTT client example - * for more information. + * public keys. The private keys are used to sign JWTs to authenticate devices. See the MQTT + * client example for more information. * *

Finally, compile and run the example with: * @@ -114,16 +123,17 @@ public static Topic createIotTopic(String projectId, String topicId) throws Exce // [START iot_create_registry] /** Create a registry for Cloud IoT. */ - public static void createRegistry(String cloudRegion, String projectId, String registryName, - String pubsubTopicPath) + 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 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; @@ -136,8 +146,8 @@ public static void createRegistry(String cloudRegion, String projectId, String r registry.setEventNotificationConfigs(notificationConfigs); registry.setId(registryName); - DeviceRegistry reg = service.projects().locations().registries().create(projectPath, - registry).execute(); + DeviceRegistry reg = + service.projects().locations().registries().create(projectPath, registry).execute(); System.out.println("Created registry: " + reg.getName()); } // [END iot_create_registry] @@ -150,12 +160,14 @@ public static void deleteRegistry(String cloudRegion, String projectId, String r 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 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); + 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(); @@ -164,18 +176,20 @@ public static void deleteRegistry(String cloudRegion, String projectId, String r // [START iot_list_devices] /** Print all of the devices in this registry to standard out. */ - public static void listDevices(String projectId, String cloudRegion, String registryName) throws - GeneralSecurityException, IOException { + 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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); List devices = service @@ -205,26 +219,32 @@ public static void listDevices(String projectId, String cloudRegion, String regi // [START iot_create_es_device] /** Create a device that is authenticated using ES256. */ - public static void createDeviceWithEs256(String deviceId, String publicKeyFilePath, - String projectId, String cloudRegion, String registryName) + 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 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); + 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(); + DeviceCredential devCredential = new DeviceCredential(); devCredential.setPublicKey(publicKeyCredential); System.out.println("Creating device with id: " + deviceId); @@ -247,20 +267,25 @@ public static void createDeviceWithEs256(String deviceId, String publicKeyFilePa // [START iot_create_rsa_device] /** Create a device that is authenticated using RS256. */ - public static void createDeviceWithRs256(String deviceId, String certificateFilePath, - String projectId, String cloudRegion, - String registryName) + 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 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); + 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); @@ -294,19 +319,20 @@ public static void createDeviceWithRs256(String deviceId, String certificateFile *

This is a valid way to construct a device, however until it is patched with a credential the * device will not be able to connect to Cloud IoT. */ - public static void createDeviceWithNoAuth(String deviceId, String projectId, String cloudRegion, - String registryName) + public static void createDeviceWithNoAuth( + 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 CloudIot service = + new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) + .setApplicationName(APP_NAME) + .build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; + final String registryPath = + "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; System.out.println("Creating device with id: " + deviceId); Device device = new Device(); @@ -327,19 +353,22 @@ public static void createDeviceWithNoAuth(String deviceId, String projectId, Str // [START iot_delete_device] /** Delete the given device from the registry. */ - public static void deleteDevice(String deviceId, String projectId, String cloudRegion, - String registryName) + 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 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); + 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(); @@ -347,19 +376,23 @@ public static void deleteDevice(String deviceId, String projectId, String cloudR // [END iot_delete_device] // [START iot_get_device] - /** Retrieves device metadata from a registry. **/ - public static Device getDevice(String deviceId, String projectId, String cloudRegion, - String registryName) throws GeneralSecurityException, IOException { + /** 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 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); + 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(); @@ -367,7 +400,7 @@ public static Device getDevice(String deviceId, String projectId, String cloudRe // [END iot_get_device] // [START iot_get_device_state] - /** Retrieves device metadata from a registry. **/ + /** Retrieves device metadata from a registry. * */ public static List getDeviceStates( String deviceId, String projectId, String cloudRegion, String registryName) throws GeneralSecurityException, IOException { @@ -375,29 +408,27 @@ public static List getDeviceStates( 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 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); + 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(); + ListDeviceStatesResponse resp = + service.projects().locations().registries().devices().states().list(devicePath).execute(); return resp.getDeviceStates(); } // [END iot_get_device_state] // [START iot_get_registry] - /** Retrieves registry metadata from a project. **/ + /** Retrieves registry metadata from a project. * */ public static DeviceRegistry getRegistry( String projectId, String cloudRegion, String registryName) throws GeneralSecurityException, IOException { @@ -405,12 +436,14 @@ public static DeviceRegistry getRegistry( 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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); return service.projects().locations().registries().get(registryPath).execute(); } @@ -425,12 +458,15 @@ public static void listDeviceConfigs( 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 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); + final String devicePath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); System.out.println("Listing device configs for " + devicePath); List deviceConfigs = @@ -460,9 +496,10 @@ public static void listRegistries(String projectId, String cloudRegion) 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 CloudIot service = + new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) + .setApplicationName(APP_NAME) + .build(); final String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; @@ -477,7 +514,7 @@ public static void listRegistries(String projectId, String cloudRegion) if (registries != null) { System.out.println("Found " + registries.size() + " registries"); - for (DeviceRegistry r: registries) { + for (DeviceRegistry r : registries) { System.out.println("Id: " + r.getId()); System.out.println("Name: " + r.getName()); if (r.getMqttConfig() != null) { @@ -493,19 +530,26 @@ public static void listRegistries(String projectId, String cloudRegion) // [START iot_patch_es] /** Patch the device to add an ES256 key for authentication. */ - public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, String projectId, - String cloudRegion, String registryName) + public static void patchEs256ForAuth( + 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 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); + 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); @@ -534,20 +578,26 @@ public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, // [START iot_patch_rsa] /** Patch the device to add an RSA256 key for authentication. */ - public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, String projectId, - String cloudRegion, - String registryName) + 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 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); + 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); @@ -577,19 +627,26 @@ public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, // [START iot_set_device_config] /** Set a device configuration to the specified data (string, JSON) and version (0 for latest). */ public static void setDeviceConfiguration( - String deviceId, String projectId, String cloudRegion, String registryName, - String data, long version) + String deviceId, + String projectId, + String cloudRegion, + String registryName, + String data, + long version) 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 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); + final String devicePath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); ModifyCloudToDeviceConfigRequest req = new ModifyCloudToDeviceConfigRequest(); req.setVersionToUpdate(version); @@ -605,7 +662,8 @@ public static void setDeviceConfiguration( .locations() .registries() .devices() - .modifyCloudToDeviceConfig(devicePath, req).execute(); + .modifyCloudToDeviceConfig(devicePath, req) + .execute(); System.out.println("Updated: " + config.getVersion()); } @@ -613,26 +671,28 @@ public static void setDeviceConfiguration( // [START iot_get_iam_policy] /** Retrieves IAM permissions for the given registry. */ - public static void getIamPermissions( - String projectId, String cloudRegion, String registryName) + public static void getIamPermissions(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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); com.google.api.services.cloudiot.v1.model.Policy policy = service .projects() .locations() .registries() - .getIamPolicy(registryPath, new GetIamPolicyRequest()).execute(); + .getIamPolicy(registryPath, new GetIamPolicyRequest()) + .execute(); System.out.println("Policy ETAG: " + policy.getEtag()); @@ -653,29 +713,30 @@ public static void getIamPermissions( // [START iot_set_iam_policy] /** Sets IAM permissions for the given registry. */ public static void setIamPermissions( - String projectId, String cloudRegion, String registryName, - String member, String role) + String projectId, String cloudRegion, String registryName, String member, String role) 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 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); + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); com.google.api.services.cloudiot.v1.model.Policy policy = service .projects() .locations() .registries() - .getIamPolicy(registryPath, new GetIamPolicyRequest()).execute(); + .getIamPolicy(registryPath, new GetIamPolicyRequest()) + .execute(); - List bindings = - policy.getBindings(); + List bindings = policy.getBindings(); boolean addNewRole = true; if (bindings != null) { @@ -705,15 +766,10 @@ public static void setIamPermissions( policy.setBindings(bindings); SetIamPolicyRequest req = new SetIamPolicyRequest().setPolicy(policy); - policy = - service - .projects() - .locations() - .registries() - .setIamPolicy(registryPath, req).execute(); + policy = service.projects().locations().registries().setIamPolicy(registryPath, req).execute(); System.out.println("Policy ETAG: " + policy.getEtag()); - for (com.google.api.services.cloudiot.v1.model.Binding binding: policy.getBindings()) { + for (com.google.api.services.cloudiot.v1.model.Binding binding : policy.getBindings()) { System.out.println(String.format("Role: %s", binding.getRole())); System.out.println("Binding members: "); for (String mem : binding.getMembers()) { @@ -723,7 +779,7 @@ public static void setIamPermissions( } // [END iot_set_iam_policy] - /** Send a command to a device. **/ + /** Send a command to a device. * */ // [START send_command] public static void sendCommand( String deviceId, String projectId, String cloudRegion, String registryName, String data) @@ -732,12 +788,15 @@ public static void sendCommand( 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 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); + final String devicePath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); SendCommandToDeviceRequest req = new SendCommandToDeviceRequest(); @@ -753,12 +812,334 @@ public static void sendCommand( .locations() .registries() .devices() - .sendCommandToDevice(devicePath, req).execute(); + .sendCommandToDevice(devicePath, req) + .execute(); System.out.println("Command response: " + res.toString()); } // [END send_command] + public static void bindDeviceToGateway( + String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) + throws GeneralSecurityException, IOException { + // [START bind_device_to_gateway] + createDevice(projectId, cloudRegion, registryName, deviceId); + + 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); + + BindDeviceToGatewayRequest request = new BindDeviceToGatewayRequest(); + request.setDeviceId(deviceId); + request.setGatewayId(gatewayId); + + BindDeviceToGatewayResponse response = + service + .projects() + .locations() + .registries() + .bindDeviceToGateway(registryPath, request) + .execute(); + + System.out.println(String.format("Device bound: %s", response.toPrettyString())); + // [END bind_device_to_gateway] + } + + public static void unbindDeviceFromGateway( + String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) + throws GeneralSecurityException, IOException { + // [START unbind_device_from_gateway] + 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); + + UnbindDeviceFromGatewayRequest request = new UnbindDeviceFromGatewayRequest(); + request.setDeviceId(deviceId); + request.setGatewayId(gatewayId); + + UnbindDeviceFromGatewayResponse response = + service + .projects() + .locations() + .registries() + .unbindDeviceFromGateway(registryPath, request) + .execute(); + + System.out.println(String.format("Device unbound: %s", response.toPrettyString())); + // [END unbind_device_from_gateway] + } + + public static void sendDataFromDevice( + MqttClient client, String deviceId, String messageType, String data) throws MqttException { + // [START send_data_from_bound_device] + if (!messageType.equals("events") && !messageType.equals("state")) { + System.err.println("Invalid message type, must ether be 'state' or events'"); + return; + } + final String dataTopic = String.format("/devices/%s/%s", deviceId, messageType); + MqttMessage message = new MqttMessage(data.getBytes()); + message.setQos(1); + client.publish(dataTopic, message); + System.out.println("Data sent"); + // [END send_data_from_bound_device] + } + + public static void attachDeviceToGateway(MqttClient client, String deviceId) + throws MqttException { + // [START attach_device] + final String attachTopic = String.format("/devices/%s/attach", deviceId); + System.out.println(String.format("Attaching: %s", attachTopic)); + String attachPayload = "{}"; + MqttMessage message = new MqttMessage(attachPayload.getBytes()); + message.setQos(1); + client.publish(attachTopic, message); + // [END attach_device] + } + + /** Detaches a bound device from the Gateway. */ + public static void detachDeviceFromGateway(MqttClient client, String deviceId) + throws MqttException { + // [START detach_device] + final String detachTopic = String.format("/devices/%s/detach", deviceId); + System.out.println(String.format("Detaching: %s", detachTopic)); + String attachPayload = "{}"; + MqttMessage message = new MqttMessage(attachPayload.getBytes()); + message.setQos(1); + client.publish(detachTopic, message); + // [END detach_device] + } + + /** Create a device to bind to a gateway. */ + public static void createDevice( + String projectId, String cloudRegion, String registryName, String deviceId) + throws GeneralSecurityException, IOException { + // [START create_device] + 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 devices = + service + .projects() + .locations() + .registries() + .devices() + .list(registryPath) + .setFieldMask("config,gatewayConfig") + .execute() + .getDevices(); + + if (devices != null) { + System.out.println("Found " + devices.size() + " devices"); + for (Device d : devices) { + if ((d.getId() != null && d.getId().equals(deviceId)) + || (d.getName() != null && d.getName().equals(deviceId))) { + System.out.println("Device exists, skipping."); + return; + } + } + } + + System.out.println("Creating device with id: " + deviceId); + Device device = new Device(); + device.setId(deviceId); + + GatewayConfig gwConfig = new GatewayConfig(); + gwConfig.setGatewayType("NON_GATEWAY"); + gwConfig.setGatewayAuthMethod("ASSOCIATION_ONLY"); + + device.setGatewayConfig(gwConfig); + Device createdDevice = + service + .projects() + .locations() + .registries() + .devices() + .create(registryPath, device) + .execute(); + + System.out.println("Created device: " + createdDevice.toPrettyString()); + // [END create_device] + } + + /** Create a gateway to bind devices to. */ + public static void createGateway( + String projectId, + String cloudRegion, + String registryName, + String gatewayId, + String certificateFilePath, + String algorithm) + throws GeneralSecurityException, IOException { + // [START create_gateway] + 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("Creating gateway with id: " + gatewayId); + Device device = new Device(); + device.setId(gatewayId); + + GatewayConfig gwConfig = new GatewayConfig(); + gwConfig.setGatewayType("GATEWAY"); + gwConfig.setGatewayAuthMethod("ASSOCIATION_ONLY"); + + String keyFormat = "RSA_X509_PEM"; + if (algorithm == "ES256") { + keyFormat = "ES256_PEM"; + } + + PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); + + byte[] keyBytes = java.nio.file.Files.readAllBytes(Paths.get(certificateFilePath)); + publicKeyCredential.setKey(new String(keyBytes)); + publicKeyCredential.setFormat(keyFormat); + DeviceCredential deviceCredential = new DeviceCredential(); + deviceCredential.setPublicKey(publicKeyCredential); + + device.setGatewayConfig(gwConfig); + device.setCredentials(Arrays.asList(deviceCredential)); + Device createdDevice = + service + .projects() + .locations() + .registries() + .devices() + .create(registryPath, device) + .execute(); + + System.out.println("Created gateway: " + createdDevice.toPrettyString()); + // [END create_gateway] + } + + public static void listGateways(String projectId, String cloudRegion, String registryName) + throws IOException, GeneralSecurityException { + // [START list_gateways] + 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 devices = + service + .projects() + .locations() + .registries() + .devices() + .list(registryPath) + .setFieldMask("config,gatewayConfig") + .execute() + .getDevices(); + + if (devices != null) { + System.out.println("Found " + devices.size() + " devices"); + for (Device d : devices) { + if (d.getGatewayConfig() != null + && d.getGatewayConfig().getGatewayType() != null + && d.getGatewayConfig().getGatewayType().equals("GATEWAY")) { + 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.getGatewayConfig().toPrettyString()); + } + System.out.println(); + } + } + } else { + System.out.println("Registry has no devices."); + } + // [END list_gateways] + } + + /** List devices bound to a gateway. */ + public static void listDevicesForGateway( + String projectId, String cloudRegion, String registryName, String gatewayId) + throws IOException, GeneralSecurityException { + // [START list_devices_for_gateway] + 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 gatewayPath = + String.format( + "projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, gatewayId); + + final String registryPath = + String.format( + "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); + + List deviceNumIds = + service + .projects() + .locations() + .registries() + .devices() + .list(registryPath) + .setGatewayListOptionsAssociationsGatewayId(gatewayId) + .execute() + .getDevices(); + + if (deviceNumIds != null) { + System.out.println("Found " + deviceNumIds.size() + " devices"); + for (Device device : deviceNumIds) { + System.out.println(String.format("ID: %s", device.getId())); + } + } else { + System.out.println("Gateway has no bound devices."); + } + // [END list_devices_for_gateway] + } + /** Entry poit for CLI. */ public static void main(String[] args) throws Exception { DeviceRegistryExampleOptions options = DeviceRegistryExampleOptions.fromFlags(args); @@ -768,34 +1149,61 @@ public static void main(String[] args) throws Exception { } switch (options.command) { + case "bind-device-to-gateway": + System.out.println("Binding device to gateway:"); + bindDeviceToGateway( + options.projectId, + options.cloudRegion, + options.registryName, + options.deviceId, + options.gatewayId); + break; + case "create-gateway": + System.out.println("Creating Gateway:"); + createGateway( + options.projectId, + options.cloudRegion, + options.registryName, + options.gatewayId, + options.publicKeyFile, + options.algorithm); + break; case "create-iot-topic": System.out.println("Create IoT Topic:"); createIotTopic(options.projectId, options.pubsubTopic); break; case "create-es": System.out.println("Create ES Device:"); - createDeviceWithEs256(options.deviceId, options.ecPublicKeyFile, options.projectId, - options.cloudRegion, options.registryName); + createDeviceWithEs256( + options.deviceId, + options.ecPublicKeyFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "create-rsa": System.out.println("Create RSA Device:"); - createDeviceWithRs256(options.deviceId, options.rsaCertificateFile, options.projectId, - options.cloudRegion, options.registryName); + createDeviceWithRs256( + options.deviceId, + options.rsaCertificateFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "create-unauth": System.out.println("Create Unauth Device"); - createDeviceWithNoAuth(options.deviceId, options.projectId, options.cloudRegion, - options.registryName); + createDeviceWithNoAuth( + options.deviceId, options.projectId, options.cloudRegion, options.registryName); break; case "create-registry": System.out.println("Create registry"); - createRegistry(options.cloudRegion, options.projectId, options.registryName, - options.pubsubTopic); + createRegistry( + options.cloudRegion, options.projectId, options.registryName, options.pubsubTopic); break; case "delete-device": System.out.println("Delete device"); - deleteDevice(options.deviceId, options.projectId, options.cloudRegion, - options.registryName); + deleteDevice( + options.deviceId, options.projectId, options.cloudRegion, options.registryName); break; case "delete-registry": System.out.println("Delete registry"); @@ -803,9 +1211,10 @@ public static void main(String[] args) throws Exception { break; case "get-device": System.out.println("Get device"); - System.out.println(getDevice(options.deviceId, options.projectId, options.cloudRegion, - options.registryName) - .toPrettyString()); + System.out.println( + getDevice( + options.deviceId, options.projectId, options.cloudRegion, options.registryName) + .toPrettyString()); break; case "get-iam-permissions": System.out.println("Get iam permissions"); @@ -813,42 +1222,65 @@ public static void main(String[] args) throws Exception { break; case "get-device-state": System.out.println("Get device state"); - List states = getDeviceStates(options.deviceId, options.projectId, - options.cloudRegion, options.registryName); - for (DeviceState state: states) { + List states = + getDeviceStates( + options.deviceId, options.projectId, options.cloudRegion, options.registryName); + for (DeviceState state : states) { System.out.println(state.toPrettyString()); } break; case "get-registry": System.out.println("Get registry"); - System.out.println(getRegistry(options.projectId, options.cloudRegion, - options.registryName)); + System.out.println( + getRegistry(options.projectId, options.cloudRegion, options.registryName)); break; case "list-devices": System.out.println("List devices"); listDevices(options.projectId, options.cloudRegion, options.registryName); break; + case "list-gateways": + System.out.println("Listing gateways:"); + listGateways(options.projectId, options.cloudRegion, options.registryName); + break; + case "list-devices-for-gateway": + System.out.println("Listing devices for gateway:"); + listDevicesForGateway( + options.projectId, options.cloudRegion, options.registryName, options.gatewayId); + break; case "list-registries": System.out.println("List registries"); listRegistries(options.projectId, options.cloudRegion); break; case "patch-device-es": System.out.println("Patch device with ES"); - patchEs256ForAuth(options.deviceId, options.ecPublicKeyFile, options.projectId, - options.cloudRegion, options.registryName); + patchEs256ForAuth( + options.deviceId, + options.ecPublicKeyFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "patch-device-rsa": System.out.println("Patch device with RSA"); - patchRsa256ForAuth(options.deviceId, options.rsaCertificateFile, options.projectId, - options.cloudRegion, options.registryName); + patchRsa256ForAuth( + options.deviceId, + options.rsaCertificateFile, + options.projectId, + options.cloudRegion, + options.registryName); break; case "set-config": if (options.deviceId == null) { System.out.println("Specify device_id for the device you are updating."); } else { System.out.println("Setting device configuration"); - setDeviceConfiguration(options.deviceId, options.projectId, options.cloudRegion, - options.registryName, options.configuration, options.version); + setDeviceConfiguration( + options.deviceId, + options.projectId, + options.cloudRegion, + options.registryName, + options.configuration, + options.version); } break; case "set-iam-permissions": @@ -856,13 +1288,21 @@ public static void main(String[] args) throws Exception { System.out.println("Specify member and role for the policy you are updating."); } else { System.out.println("Setting iam permissions"); - setIamPermissions(options.projectId, options.cloudRegion, options.registryName, - options.member, options.role); + setIamPermissions( + options.projectId, + options.cloudRegion, + options.registryName, + options.member, + options.role); } break; case "send-command": System.out.println("Sending command to device:"); - sendCommand(options.deviceId, options.projectId, options.cloudRegion, options.registryName, + sendCommand( + options.deviceId, + options.projectId, + options.cloudRegion, + options.registryName, options.commandData); break; default: @@ -870,8 +1310,7 @@ public static void main(String[] args) throws Exception { String footer = "\nhttps://cloud.google.com/iot-core"; HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("DeviceRegistryExample", header, options.options, footer, - true); + formatter.printHelp("DeviceRegistryExample", header, options.options, footer, true); break; } } diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java index e5079065f92..8dd754df6ea 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java @@ -26,6 +26,7 @@ /** Command line options for the Device Manager example. */ public class DeviceRegistryExampleOptions { + String algorithm; String projectId; String ecPublicKeyFile = "ec_public.pem"; String rsaCertificateFile = "rsa_cert.pem"; @@ -34,7 +35,9 @@ public class DeviceRegistryExampleOptions { String commandData = "Specify with --data"; String configuration = "Specify with -configuration"; String deviceId; // Default to UUID? + String gatewayId; String pubsubTopic; + String publicKeyFile; String registryName; String member; String role; @@ -51,28 +54,40 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc( "Command to run:" - + "\n\tcreate-iot-topic" // TODO: Descriptions or too verbose? - + "\n\tcreate-rsa" - + "\n\tcreate-es" - + "\n\tcreate-unauth" - + "\n\tcreate-registry" - + "\n\tdelete-device" - + "\n\tdelete-registry" - + "\n\tget-device" - + "\n\tget-device-state" - + "\n\tget-iam-permissions" - + "\n\tget-registry" - + "\n\tlist-devices" - + "\n\tlist-registries" - + "\n\tpatch-device-es" - + "\n\tpatch-device-rsa" - + "\n\tset-config" - + "\n\tset-iam-permissions" - + "\n\tsend-command") + + "\n\tbind-device-to-gateway" + + "\n\tcreate-gateway" + + "\n\tcreate-iot-topic" // TODO: Descriptions or too verbose? + + "\n\tcreate-rsa" + + "\n\tcreate-es" + + "\n\tcreate-unauth" + + "\n\tcreate-registry" + + "\n\tdelete-device" + + "\n\tdelete-registry" + + "\n\tget-device" + + "\n\tget-device-state" + + "\n\tget-iam-permissions" + + "\n\tget-registry" + + "\n\tlist-devices" + + "\n\tlist-registries" + + "\n\tlist-gateways" + + "\n\tlist-devices-for-gateway" + + "\n\tpatch-device-es" + + "\n\tpatch-device-rsa" + + "\n\tset-config" + + "\n\tset-iam-permissions" + + "\n\tsend-command" + + "\n\tunbind-device-from-gateway") .required() .build()); // Optional arguments. + options.addOption( + Option.builder() + .type(String.class) + .longOpt("algorithm") + .hasArg() + .desc("Algorithm used for public/private keys.") + .build()); options.addOption( Option.builder() .type(String.class) @@ -108,6 +123,13 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc("GCP cloud project name.") .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("public_key_file") + .hasArg() + .desc("Public key file used for registering devices and gateways.") + .build()); options.addOption( Option.builder() .type(String.class) @@ -122,6 +144,13 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc("Name for your Device.") .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("gateway_id") + .hasArg() + .desc("The identifier for the Gateway.") + .build()); options.addOption( Option.builder() .type(String.class) @@ -170,6 +199,9 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { throw new ParseException("Invalid command, showing help."); } + if (commandLine.hasOption("algorithm")) { + res.algorithm = commandLine.getOptionValue("algorithm"); + } if (commandLine.hasOption("cloud_region")) { res.cloudRegion = commandLine.getOptionValue("cloud_region"); } @@ -179,7 +211,9 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { if (commandLine.hasOption("device_id")) { res.deviceId = commandLine.getOptionValue("device_id"); } - + if (commandLine.hasOption("gateway_id")) { + res.gatewayId = commandLine.getOptionValue("gateway_id"); + } if (commandLine.hasOption("project_id")) { res.projectId = commandLine.getOptionValue("project_id"); } else { @@ -195,7 +229,9 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { } else { // TODO: Get from environment variable } - + if (commandLine.hasOption("public_key_file")) { + res.publicKeyFile = commandLine.getOptionValue("public_key_file"); + } if (commandLine.hasOption("ec_public_key_file")) { res.ecPublicKeyFile = commandLine.getOptionValue("ec_public_key_file"); } @@ -230,11 +266,10 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { String footer = "\nhttps://cloud.google.com/iot-core"; HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("DeviceRegistryExample", header, options, footer, - true); + formatter.printHelp("DeviceRegistryExample", header, options, footer, true); System.err.println(e.getMessage()); return null; } } -} \ No newline at end of file +} diff --git a/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java index 576c9a42f85..1d67cf84f1e 100644 --- a/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java +++ b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java @@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import org.eclipse.paho.client.mqttv3.MqttClient; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -29,7 +30,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; - /** Tests for iot "Management" sample. */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") @@ -48,7 +48,6 @@ public class ManagerIT { private static final String MEMBER = "group:dpebot@google.com"; private static final String ROLE = "roles/viewer"; - private static Topic topic; @Before @@ -66,15 +65,13 @@ public void tearDown() throws Exception { @Test public void testPatchRsa() throws Exception { final String deviceName = "patchme-device-rsa"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); try { DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceRegistryExample.createDeviceWithNoAuth(deviceName, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); - DeviceRegistryExample.patchRsa256ForAuth(deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); + DeviceRegistryExample.createDeviceWithNoAuth( + deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.patchRsa256ForAuth( + deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); String got = bout.toString(); Assert.assertTrue(got.contains("Created device: {")); @@ -91,16 +88,14 @@ public void testPatchRsa() throws Exception { @Test public void testPatchEs() throws Exception { final String deviceName = "patchme-device-es"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); try { DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceRegistryExample.createDeviceWithNoAuth(deviceName, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); - DeviceRegistryExample.patchEs256ForAuth(deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); + DeviceRegistryExample.createDeviceWithNoAuth( + deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.patchEs256ForAuth( + deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); String got = bout.toString(); Assert.assertTrue(got.contains("Created device: {")); @@ -117,9 +112,7 @@ public void testPatchEs() throws Exception { @Test public void testCreateDeleteUnauthDevice() throws Exception { final String deviceName = "noauth-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithNoAuth(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -137,12 +130,10 @@ public void testCreateDeleteUnauthDevice() throws Exception { @Test public void testCreateDeleteEsDevice() throws Exception { final String deviceName = "es-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceRegistryExample.createDeviceWithEs256(deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, - REGISTRY_ID); + DeviceRegistryExample.createDeviceWithEs256( + deviceName, ES_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); DeviceRegistryExample.getDeviceStates(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); String got = bout.toString(); @@ -158,9 +149,7 @@ public void testCreateDeleteEsDevice() throws Exception { @Test public void testCreateDeleteRsaDevice() throws Exception { final String deviceName = "rsa-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -179,9 +168,7 @@ public void testCreateDeleteRsaDevice() throws Exception { @Test public void testCreateGetDevice() throws Exception { final String deviceName = "rsa-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -201,14 +188,12 @@ public void testCreateGetDevice() throws Exception { @Test public void testCreateConfigureDevice() throws Exception { final String deviceName = "rsa-device-config"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceRegistryExample.setDeviceConfiguration(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID, - "some-test-data", 0L); + DeviceRegistryExample.setDeviceConfiguration( + deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID, "some-test-data", 0L); String got = bout.toString(); Assert.assertTrue(got.contains("Updated: 2")); @@ -220,13 +205,10 @@ public void testCreateConfigureDevice() throws Exception { } } - @Test public void testCreateListDevices() throws Exception { final String deviceName = "rsa-device"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -245,9 +227,7 @@ public void testCreateListDevices() throws Exception { @Test public void testCreateGetRegistry() throws Exception { - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.getRegistry(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -262,9 +242,7 @@ public void testCreateGetRegistry() throws Exception { @Test public void testGetIam() throws Exception { - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.getIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -279,9 +257,7 @@ public void testGetIam() throws Exception { @Test public void testSetIam() throws Exception { - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.setIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, MEMBER, ROLE); DeviceRegistryExample.getIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -300,9 +276,7 @@ public void testSetIam() throws Exception { @Test public void testHttpDeviceEvent() throws Exception { final String deviceName = "rsa-device-http-event"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -337,9 +311,7 @@ public void testHttpDeviceEvent() throws Exception { @Test public void testHttpDeviceState() throws Exception { final String deviceName = "rsa-device-http-state"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -374,9 +346,7 @@ public void testHttpDeviceState() throws Exception { @Test public void testHttpDeviceConfig() throws Exception { final String deviceName = "rsa-device-http-state"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -409,14 +379,11 @@ public void testHttpDeviceConfig() throws Exception { } } - // MQTT device tests @Test public void testMqttDeviceConfig() throws Exception { final String deviceName = "rsa-device-mqtt-config"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -424,13 +391,13 @@ public void testMqttDeviceConfig() throws Exception { // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-message_type=events", - "-num_messages=1", - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-message_type=events", + "-num_messages=1", + "-algorithm=RS256" }; com.example.cloud.iot.examples.MqttExample.main(testArgs); // End device test. @@ -451,34 +418,33 @@ public void testMqttDeviceConfig() throws Exception { @Test public void testMqttDeviceCommand() throws Exception { final String deviceName = "rsa-device-mqtt-commands"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-cloud_region=" + CLOUD_REGION, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-wait_time=" + 10, - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-cloud_region=" + CLOUD_REGION, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-wait_time=" + 10, + "-algorithm=RS256" }; - Thread deviceThread = new Thread() { - public void run() { - try { - com.example.cloud.iot.examples.MqttExample.main(testArgs); - } catch (Exception e) { - // TODO: Fail - System.out.println("Failure on Exception"); - } - } - }; + Thread deviceThread = + new Thread() { + public void run() { + try { + com.example.cloud.iot.examples.MqttExample.main(testArgs); + } catch (Exception e) { + // TODO: Fail + System.out.println("Failure on Exception"); + } + } + }; deviceThread.start(); Thread.sleep(500); // Give the device a chance to connect @@ -506,9 +472,7 @@ public void run() { @Test public void testMqttDeviceEvents() throws Exception { final String deviceName = "rsa-device-mqtt-events"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -516,13 +480,13 @@ public void testMqttDeviceEvents() throws Exception { // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-message_type=events", - "-num_messages=1", - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-message_type=events", + "-num_messages=1", + "-algorithm=RS256" }; com.example.cloud.iot.examples.MqttExample.main(testArgs); // End device test. @@ -530,7 +494,7 @@ public void testMqttDeviceEvents() throws Exception { // Assertions String got = bout.toString(); // - //Finished loop successfully. Goodbye! + // Finished loop successfully. Goodbye! Assert.assertTrue(got.contains("Publishing events message 1")); Assert.assertTrue(got.contains("Finished loop successfully. Goodbye!")); @@ -546,9 +510,7 @@ public void testMqttDeviceEvents() throws Exception { @Test public void testMqttDeviceState() throws Exception { final String deviceName = "rsa-device-mqtt-state"; - topic = DeviceRegistryExample.createIotTopic( - PROJECT_ID, - TOPIC_ID); + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); DeviceRegistryExample.createDeviceWithRs256( deviceName, RSA_PATH, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); @@ -556,12 +518,12 @@ public void testMqttDeviceState() throws Exception { // Device bootstrapped, time to connect and run. String[] testArgs = { - "-project_id=" + PROJECT_ID, - "-registry_id=" + REGISTRY_ID, - "-device_id=" + deviceName, - "-private_key_file=" + PKCS_PATH, - "-message_type=state", - "-algorithm=RS256" + "-project_id=" + PROJECT_ID, + "-registry_id=" + REGISTRY_ID, + "-device_id=" + deviceName, + "-private_key_file=" + PKCS_PATH, + "-message_type=state", + "-algorithm=RS256" }; com.example.cloud.iot.examples.MqttExample.main(testArgs); // End device test. @@ -578,4 +540,78 @@ public void testMqttDeviceState() throws Exception { topicAdminClient.deleteTopic(topic.getNameAsTopicName()); } } + + // Manager tests + @Test + public void testCreateGateway() throws Exception { + final String gatewayName = "rsa-create-gateway"; + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); + DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); + DeviceRegistryExample.createGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); + + // Assertions + String got = bout.toString(); + System.out.println(got); + Assert.assertTrue(got.contains("Created gateway:")); + + // Clean up + DeviceRegistryExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.deleteTopic(topic.getNameAsTopicName()); + } + } + + @Test + public void testListGateways() throws Exception { + final String gatewayName = "rsa-list-gateway"; + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); + DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); + DeviceRegistryExample.createGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); + DeviceRegistryExample.listGateways(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + + // Assertions + String got = bout.toString(); + System.out.println(got); + Assert.assertTrue(got.contains("Found 1 devices")); + Assert.assertTrue(got.contains(String.format("Id: %s", gatewayName))); + + // Clean up + DeviceRegistryExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.deleteTopic(topic.getNameAsTopicName()); + } + } + + @Test + public void testBindDeviceToGatewayAndUnbind() throws Exception { + final String gatewayName = "rsa-bind-gateway"; + final String deviceName = "rsa-bind-device"; + topic = DeviceRegistryExample.createIotTopic(PROJECT_ID, TOPIC_ID); + DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); + DeviceRegistryExample.createGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); + DeviceRegistryExample.createDevice(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName); + DeviceRegistryExample.bindDeviceToGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); + DeviceRegistryExample.unbindDeviceFromGateway( + PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); + + // Assertions + String got = bout.toString(); + System.out.println(got); + Assert.assertTrue(got.contains("Device bound: ")); + Assert.assertTrue(got.contains("Device unbound: ")); + + // Clean up + DeviceRegistryExample.deleteDevice(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + topicAdminClient.deleteTopic(topic.getNameAsTopicName()); + } + } } From 12c2deddfdb3b91684aa7776dd387ee116dfd5cb Mon Sep 17 00:00:00 2001 From: Mike Ganbold Date: Wed, 6 Feb 2019 16:04:36 -0800 Subject: [PATCH 3/6] removed another merge conflict --- .../com/example/cloud/iot/examples/DeviceRegistryExample.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java index 94c65488580..17c717bd8c6 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -24,7 +24,6 @@ import com.google.api.client.util.Charsets; import com.google.api.services.cloudiot.v1.CloudIot; import com.google.api.services.cloudiot.v1.CloudIotScopes; -<<<<<<< HEAD import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayRequest; import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayResponse; import com.google.api.services.cloudiot.v1.model.Device; @@ -43,9 +42,6 @@ import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceRequest; import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayRequest; import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayResponse; -======= -import com.google.api.services.cloudiot.v1.model.*; ->>>>>>> dec906eda63efa1f76dec2cd35b4155a6351c3ed import com.google.cloud.Role; import com.google.cloud.pubsub.v1.TopicAdminClient; import com.google.common.io.Files; From 274e50f824a76fe338255afe22306166d93f9504 Mon Sep 17 00:00:00 2001 From: Mike Ganbold Date: Wed, 6 Feb 2019 16:04:36 -0800 Subject: [PATCH 4/6] emoved another merge conflict --- .../iot/examples/DeviceRegistryExample.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java index 94c65488580..9117859dcb8 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -24,7 +24,6 @@ import com.google.api.client.util.Charsets; import com.google.api.services.cloudiot.v1.CloudIot; import com.google.api.services.cloudiot.v1.CloudIotScopes; -<<<<<<< HEAD import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayRequest; import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayResponse; import com.google.api.services.cloudiot.v1.model.Device; @@ -33,19 +32,16 @@ import com.google.api.services.cloudiot.v1.model.DeviceRegistry; import com.google.api.services.cloudiot.v1.model.DeviceState; import com.google.api.services.cloudiot.v1.model.EventNotificationConfig; -import com.google.api.services.cloudiot.v1.model.PublicKeyCredential; -import com.google.api.services.cloudiot.v1.model.ListDeviceStatesResponse; -import com.google.api.services.cloudiot.v1.model.ModifyCloudToDeviceConfigRequest; import com.google.api.services.cloudiot.v1.model.GatewayConfig; import com.google.api.services.cloudiot.v1.model.GetIamPolicyRequest; -import com.google.api.services.cloudiot.v1.model.SetIamPolicyRequest; -import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceResponse; +import com.google.api.services.cloudiot.v1.model.ListDeviceStatesResponse; +import com.google.api.services.cloudiot.v1.model.ModifyCloudToDeviceConfigRequest; +import com.google.api.services.cloudiot.v1.model.PublicKeyCredential; import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceRequest; +import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceResponse; +import com.google.api.services.cloudiot.v1.model.SetIamPolicyRequest; import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayRequest; import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayResponse; -======= -import com.google.api.services.cloudiot.v1.model.*; ->>>>>>> dec906eda63efa1f76dec2cd35b4155a6351c3ed import com.google.cloud.Role; import com.google.cloud.pubsub.v1.TopicAdminClient; import com.google.common.io.Files; @@ -1249,7 +1245,7 @@ public static void main(String[] args) throws Exception { case "list-devices-for-gateway": System.out.println("Listing devices for gateway:"); listDevicesForGateway( - options.projectId, options.cloudRegion, options.registryName, options.gatewayId); + options.projectId, options.cloudRegion, options.registryName, options.gatewayId); break; case "list-registries": From c865114f8103ce4fad3fbd92d7333e4c6a74692a Mon Sep 17 00:00:00 2001 From: Mike Ganbold Date: Thu, 7 Feb 2019 11:52:42 -0800 Subject: [PATCH 5/6] added helpful message to messageType --- .../com/example/cloud/iot/examples/DeviceRegistryExample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java index 9117859dcb8..a25418ae2b1 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -891,7 +891,7 @@ public static void sendDataFromDevice( MqttClient client, String deviceId, String messageType, String data) throws MqttException { // [START send_data_from_bound_device] if (!messageType.equals("events") && !messageType.equals("state")) { - System.err.println("Invalid message type, must ether be 'state' or events'"); + System.err.println(String.format("%s is invalid message type, must ether be 'state' or events'", messageType)); return; } final String dataTopic = String.format("/devices/%s/%s", deviceId, messageType); From 662f6f80e46d40c282704cc038362a211b6d6a6b Mon Sep 17 00:00:00 2001 From: Mike Ganbold Date: Thu, 7 Feb 2019 11:52:42 -0800 Subject: [PATCH 6/6] added helpful message to messageType --- .../com/example/cloud/iot/examples/DeviceRegistryExample.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java index 9117859dcb8..6ef506df169 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -891,7 +891,9 @@ public static void sendDataFromDevice( MqttClient client, String deviceId, String messageType, String data) throws MqttException { // [START send_data_from_bound_device] if (!messageType.equals("events") && !messageType.equals("state")) { - System.err.println("Invalid message type, must ether be 'state' or events'"); + System.err.println( + String.format( + "%s is invalid message type, must ether be 'state' or events'", messageType)); return; } final String dataTopic = String.format("/devices/%s/%s", deviceId, messageType);