From 455971de7d6019e99296e121110a3b5ad1cfd6a5 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Tue, 26 Sep 2017 16:46:49 -0700 Subject: [PATCH 1/6] Updates instructions for jar installation --- iot/api-client/manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot/api-client/manager/README.md b/iot/api-client/manager/README.md index daf4c47125a..76859c74809 100644 --- a/iot/api-client/manager/README.md +++ b/iot/api-client/manager/README.md @@ -10,7 +10,7 @@ PubSub topic for Cloud IoT as described in [the parent README](../README.md). Manually install [the provided client library](https://cloud.google.com/iot/resources/java/cloud-iot-core-library.jar) for Cloud IoT Core to Maven: - mvn install:install-file -Dfile=cloud-iot-core-library.jar -DgroupId=com.example.apis \ + mvn install:install-file -Dfile=cloud-iot-core-library.jar -DgroupId=com.google.apis \ -DartifactId=google-api-services-cloudiot -Dversion=v1beta1-rev20170926-1.22.0-SNAPSHOT \ -Dpackaging=jar From cd4aca36192fa583a54cf3cd18865a84cb61ec04 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Thu, 28 Sep 2017 08:50:39 -0700 Subject: [PATCH 2/6] Uses published client library --- iot/api-client/manager/README.md | 8 -------- iot/api-client/manager/pom.xml | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/iot/api-client/manager/README.md b/iot/api-client/manager/README.md index 76859c74809..4a5fdbe4d04 100644 --- a/iot/api-client/manager/README.md +++ b/iot/api-client/manager/README.md @@ -6,14 +6,6 @@ Note that before you can run the sample, you must configure a Google Cloud PubSub topic for Cloud IoT as described in [the parent README](../README.md). ## Setup - -Manually install [the provided client library](https://cloud.google.com/iot/resources/java/cloud-iot-core-library.jar) -for Cloud IoT Core to Maven: - - mvn install:install-file -Dfile=cloud-iot-core-library.jar -DgroupId=com.google.apis \ - -DartifactId=google-api-services-cloudiot -Dversion=v1beta1-rev20170926-1.22.0-SNAPSHOT \ - -Dpackaging=jar - Run the following command to install the libraries and build the sample with Maven: diff --git a/iot/api-client/manager/pom.xml b/iot/api-client/manager/pom.xml index 8c060ff5f91..59f142d84e3 100644 --- a/iot/api-client/manager/pom.xml +++ b/iot/api-client/manager/pom.xml @@ -40,7 +40,7 @@ com.google.apis google-api-services-cloudiot - v1beta1-rev20170926-1.22.0-SNAPSHOT + v1-rev20170922-1.22.0 com.google.cloud From 9b219f452814c5245f40b5b9beafdd9520b3eac9 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Fri, 6 Oct 2017 13:52:45 -0700 Subject: [PATCH 3/6] Adds HTTP snippets, fixes headers for HTTP/2, adds cache-control header, fixes checkstyle warnings. --- .../cloud/iot/examples/HttpExample.java | 131 ++++++++++-------- 1 file changed, 76 insertions(+), 55 deletions(-) diff --git a/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java b/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java index d7dd27fa482..5de22b85f94 100644 --- a/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java +++ b/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java @@ -1,23 +1,30 @@ -/** - * Copyright 2017, Google, Inc. - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ +/* + Copyright 2017, Google, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + package com.google.cloud.iot.examples; +// [START cloudiotcore_http_imports] import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; +import java.net.ProtocolException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; @@ -25,7 +32,9 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import org.joda.time.DateTime; +import org.json.JSONException; import org.json.JSONObject; +// [END cloudiotcore_http_imports] /** * Java sample of connecting to Google Cloud IoT Core vice via HTTP, using JWT. @@ -39,7 +48,8 @@ * folder. */ public class HttpExample { - /** Create a Cloud IoT Core JWT for the given project id, signed with the given private key. */ + // [START cloudiotcore_http_createjwt] + /** Create a RSA-based JWT for the given project id, signed with the given private key. */ private static String createJwtRsa(String projectId, String privateKeyFile) throws Exception { DateTime now = new DateTime(); // Create a JWT to authenticate this device. The device will be disconnected after the token @@ -58,6 +68,7 @@ private static String createJwtRsa(String projectId, String privateKeyFile) thro return jwtBuilder.signWith(SignatureAlgorithm.RS256, kf.generatePrivate(spec)).compact(); } + /** Create an ES-based JWT for the given project id, signed with the given private key. */ private static String createJwtEs(String projectId, String privateKeyFile) throws Exception { DateTime now = new DateTime(); // Create a JWT to authenticate this device. The device will be disconnected after the token @@ -75,28 +86,60 @@ private static String createJwtEs(String projectId, String privateKeyFile) throw return jwtBuilder.signWith(SignatureAlgorithm.ES256, kf.generatePrivate(spec)).compact(); } + // [END cloudiotcore_http_createjwt] - public static void main(String[] args) throws Exception { - HttpExampleOptions options = HttpExampleOptions.fromFlags(args); - if (options == null) { - // Could not parse the flags. - System.exit(1); - } - + // [START cloudiotcore_http_publishmessage] + /** Publish an event or state message using Cloud IoT Core via the HTTP API. */ + public static void publishMessage(String payload, String urlPath, String messageType, + String token, String projectId, String cloudRegion, String registryId, String deviceId) + throws UnsupportedEncodingException, IOException, JSONException, ProtocolException { // Build the resource path of the device that is going to be authenticated. String devicePath = String.format( "projects/%s/locations/%s/registries/%s/devices/%s", - options.projectId, options.cloudRegion, options.registryId, options.deviceId); + projectId, cloudRegion, registryId, deviceId); + String urlSuffix = messageType.equals("event") ? "publishEvent" : "setState"; - // This describes the operation that is going to be perform with the device. - String urlSuffix = options.messageType.equals("event") ? "publishEvent" : "setState"; + // Data sent through the wire has to be base64 encoded. + Base64.Encoder encoder = Base64.getEncoder(); + + String encPayload = encoder.encodeToString(payload.getBytes("UTF-8")); - String urlPath = - String.format( - "%s/%s/%s:%s", options.httpBridgeAddress, options.apiVersion, devicePath, urlSuffix); URL url = new URL(urlPath); - System.out.format("Using URL: '%s'\n", urlPath); + HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); + httpCon.setDoOutput(true); + httpCon.setRequestMethod("POST"); + + // Add headers. + httpCon.setRequestProperty("authorization", String.format("Bearer %s", token)); + httpCon.setRequestProperty("content-type", "application/json; charset=UTF-8"); + httpCon.setRequestProperty("cache-control", "no-cache"); + + // Add post data. The data sent depends on whether we're updating state or publishing events. + JSONObject data = new JSONObject(); + if (messageType.equals("event")) { + data.put("binary_data", encPayload); + } else { + JSONObject state = new JSONObject(); + state.put("binary_data", encPayload); + data.put("state", state); + } + httpCon.getOutputStream().write(data.toString().getBytes("UTF-8")); + httpCon.getOutputStream().close(); + + System.out.println(httpCon.getResponseCode()); + System.out.println(httpCon.getResponseMessage()); + } + // [END cloudiotcore_http_publishmessage] + + // [START cloudiotcore_http_run] + /** Parse arguments and publish messages. */ + public static void main(String[] args) throws Exception { + HttpExampleOptions options = HttpExampleOptions.fromFlags(args); + if (options == null) { + // Could not parse the flags. + System.exit(1); + } // Create the corresponding JWT depending on the selected algorithm. String token; @@ -109,41 +152,18 @@ public static void main(String[] args) throws Exception { "Invalid algorithm " + options.algorithm + ". Should be one of 'RS256' or 'ES256'."); } - // Data sent through the wire has to be base64 encoded. - Base64.Encoder encoder = Base64.getEncoder(); - // Publish numMessages messages to the HTTP bridge. for (int i = 1; i <= options.numMessages; ++i) { String payload = String.format("%s/%s-payload-%d", options.registryId, options.deviceId, i); System.out.format( "Publishing %s message %d/%d: '%s'\n", options.messageType, i, options.numMessages, payload); - String encPayload = encoder.encodeToString(payload.getBytes("UTF-8")); - - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - httpCon.setRequestMethod("POST"); - // Adding headers. - httpCon.setRequestProperty("Authorization", String.format("Bearer %s", token)); - httpCon.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); - - // Adding the post data. The structure of the data send depends on whether it is event or a - // state message. - JSONObject data = new JSONObject(); - if (options.messageType.equals("event")) { - data.put("binary_data", encPayload); - } else { - JSONObject state = new JSONObject(); - state.put("binary_data", encPayload); - data.put("state", state); - } - httpCon.getOutputStream().write(data.toString().getBytes("UTF-8")); - httpCon.getOutputStream().close(); + String urlPath = String.format("%s/%s/", options.httpBridgeAddress, options.apiVersion); + System.out.format("Using URL: '%s'\n", urlPath); - // This will perform the connection as well. - System.out.println(httpCon.getResponseCode()); - System.out.println(httpCon.getResponseMessage()); + publishMessage(payload, urlPath, options.messageType, token, options.projectId, + options.cloudRegion, options.registryId, options.deviceId); if (options.messageType.equals("event")) { // Frequently send event payloads (every second) @@ -155,4 +175,5 @@ public static void main(String[] args) throws Exception { } System.out.println("Finished loop successfully. Goodbye!"); } + // [END cloudiotcore_http_run] } From 0dd39e82ce8ca27b70d0c0022b802a3ef91c1487 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Fri, 6 Oct 2017 14:41:13 -0700 Subject: [PATCH 4/6] Fixes patch and adds tests --- .../iot/examples/DeviceRegistryExample.java | 81 +++++++++++-------- .../example/cloud/iot/examples/ManagerIT.java | 51 ++++++++++++ 2 files changed, 100 insertions(+), 32 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 9e63932fe49..bf01220d896 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 @@ -80,6 +80,8 @@ */ public class DeviceRegistryExample { + static final String APP_NAME = "DeviceRegistryExample"; + /** Creates a topic and grants the IoT service account access. */ public static Topic createIotTopic(String projectId, String topicId) throws Exception { // Create a new topic @@ -111,8 +113,9 @@ public static void createRegistry(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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + 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; @@ -137,8 +140,9 @@ 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; String registryPath = projectPath + "/registries/" + registryName; @@ -154,8 +158,9 @@ public static void listDevices(String projectId, String cloudRegion, String regi GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -193,8 +198,9 @@ public static void createDeviceWithEs256(String deviceId, String publicKeyFilePa GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -233,8 +239,9 @@ public static void createDeviceWithRs256(String deviceId, String certificateFile GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -276,8 +283,9 @@ public static void createDeviceWithNoAuth(String deviceId, String projectId, Str GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -306,8 +314,9 @@ public static void deleteDevice(String deviceId, String projectId, String cloudR GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -324,8 +333,9 @@ public static Device getDevice(String deviceId, String projectId, String cloudRe GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -343,8 +353,9 @@ public static List getDeviceStates( GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -365,8 +376,9 @@ public static DeviceRegistry getRegistry( GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -381,8 +393,9 @@ public static void listDeviceConfigs( GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -414,8 +427,9 @@ 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; @@ -451,8 +465,9 @@ public static void modifyCloudToDeviceConfig(String deviceId, String configData, GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -480,8 +495,9 @@ public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -505,7 +521,7 @@ public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, .registries() .devices() .patch(devicePath, device) - .setFields("credentials") + .setUpdateMask("credentials") .execute(); System.out.println("Patched device is " + patchedDevice.toPrettyString()); @@ -520,8 +536,9 @@ public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, - init); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryName; @@ -545,7 +562,7 @@ public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, .registries() .devices() .patch(devicePath, device) - .setFields("credentials") + .setUpdateMask("credentials") .execute(); System.out.println("Patched device is " + patchedDevice.toPrettyString()); 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 3716bb2517c..f163a2eafba 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 @@ -59,6 +59,57 @@ public void tearDown() throws Exception { System.setOut(null); } + @Test + public void testPatchRsa() throws Exception { + final String deviceName = "patchme-device-rsa"; + 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); + + String got = bout.toString(); + Assert.assertTrue(got.contains("Created device: {")); + } finally { + DeviceRegistryExample.deleteDevice(deviceName, 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 testPatchEs() throws Exception { + final String deviceName = "patchme-device-es"; + 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); + + String got = bout.toString(); + Assert.assertTrue(got.contains("Created device: {")); + } finally { + DeviceRegistryExample.deleteDevice(deviceName, 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 testCreateDeleteUnauthDevice() throws Exception { final String deviceName = "noauth-device"; From 6a60c8f1eff233077dee50921cefe9c3efe872e4 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Fri, 6 Oct 2017 15:36:15 -0700 Subject: [PATCH 5/6] Prefer mvn:exec when accessing Cloud client library. --- iot/api-client/manager/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/iot/api-client/manager/README.md b/iot/api-client/manager/README.md index 4a5fdbe4d04..70fa6a6984c 100644 --- a/iot/api-client/manager/README.md +++ b/iot/api-client/manager/README.md @@ -54,10 +54,11 @@ run the sample as: Create a PubSub topic, `hello-java`, for the project, `blue-jet-123`: - java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ - com.example.cloud.iot.examples.DeviceRegistryExample \ - -project_id=blue-jet-123 -pubsub_topic=hello-java - -command=create-iot-topic + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.DeviceRegistryExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -command=create-iot-topic \ + -pubsub_topic=hello-java " Create an ES device: From 30b57d14bb7b03c24b2ce49898f09e35509919e7 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Mon, 9 Oct 2017 12:46:12 -0700 Subject: [PATCH 6/6] Fixes URL for HTTP example and adds snippets for MQTT. --- iot/api-client/http_example/README.md | 25 +++++++++++++++---- .../cloud/iot/examples/HttpExample.java | 2 ++ .../cloud/iot/examples/MqttExample.java | 12 ++++++++- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/iot/api-client/http_example/README.md b/iot/api-client/http_example/README.md index 079a72c81f5..825640f7d58 100644 --- a/iot/api-client/http_example/README.md +++ b/iot/api-client/http_example/README.md @@ -20,11 +20,12 @@ The following command summarizes the sample usage: ``` mvn exec:java \ -Dexec.mainClass="com.google.cloud.iot.examples.HttpExample" \ - -Dexec.args="-project_id=my-iot-project \ - -registry_id=my-registry \ - -device_id=my-device \ - -private_key_file=rsa_private_pkcs8 \ - -algorithm=RS256" + -Dexec.args="-project_id= \ + -registry_id= \ + -device_id= \ + -private_key_file= \ + -message_type= \ + -algorithm=" ``` For example, if your project ID is `blue-jet-123`, your service account @@ -42,6 +43,20 @@ provided in the parent folder, you can run the sample as: -algorithm=RS256" ``` +To publish state messages, run the sample as follows: + +``` + mvn exec:java \ + -Dexec.mainClass="com.google.cloud.iot.examples.HttpExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_id=my-registry \ + -device_id=my-java-device \ + -private_key_file=../rsa_private_pkcs8 \ + -message_type=state \ + -algorithm=RS256" +``` + + ## Reading the messages written by the sample client 1. Create a subscription to your topic. diff --git a/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java b/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java index 5de22b85f94..361f076c60f 100644 --- a/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java +++ b/iot/api-client/http_example/src/main/java/com/google/cloud/iot/examples/HttpExample.java @@ -105,6 +105,8 @@ public static void publishMessage(String payload, String urlPath, String message String encPayload = encoder.encodeToString(payload.getBytes("UTF-8")); + + urlPath = urlPath + devicePath + ":" + urlSuffix; URL url = new URL(urlPath); HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); httpCon.setDoOutput(true); diff --git a/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExample.java b/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExample.java index c74b38b0330..5c21f7aceda 100644 --- a/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExample.java +++ b/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExample.java @@ -14,6 +14,7 @@ package com.google.cloud.iot.examples; +// [START cloudiotcore_mqtt_imports] import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; @@ -26,6 +27,7 @@ import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.joda.time.DateTime; +// [END cloudiotcore_mqtt_imports] /** * Java sample of connecting to Google Cloud IoT Core vice via MQTT, using JWT. @@ -52,7 +54,8 @@ * */ public class MqttExample { - /** Create a Cloud IoT Core JWT for the given project id, signed with the given private key. */ + // [START cloudiotcore_mqtt_createjwt] + /** Create a Cloud IoT Core JWT for the given project id, signed with the given RSA key. */ private static String createJwtRsa(String projectId, String privateKeyFile) throws Exception { DateTime now = new DateTime(); // Create a JWT to authenticate this device. The device will be disconnected after the token @@ -71,6 +74,7 @@ private static String createJwtRsa(String projectId, String privateKeyFile) thro return jwtBuilder.signWith(SignatureAlgorithm.RS256, kf.generatePrivate(spec)).compact(); } + /** Create a Cloud IoT Core JWT for the given project id, signed with the given ES key. */ private static String createJwtEs(String projectId, String privateKeyFile) throws Exception { DateTime now = new DateTime(); // Create a JWT to authenticate this device. The device will be disconnected after the token @@ -88,8 +92,11 @@ private static String createJwtEs(String projectId, String privateKeyFile) throw return jwtBuilder.signWith(SignatureAlgorithm.ES256, kf.generatePrivate(spec)).compact(); } + // [END cloudiotcore_mqtt_createjwt] + /** Parse arguments, configure MQTT, and publish messages. */ public static void main(String[] args) throws Exception { + // [START cloudiotcore_mqtt_configuremqtt] MqttExampleOptions options = MqttExampleOptions.fromFlags(args); if (options == null) { // Could not parse. @@ -131,7 +138,9 @@ public static void main(String[] args) throws Exception { throw new IllegalArgumentException( "Invalid algorithm " + options.algorithm + ". Should be one of 'RS256' or 'ES256'."); } + // [END cloudiotcore_mqtt_configuremqtt] + // [START cloudiotcore_mqtt_publish] // Create a client, and connect to the Google MQTT bridge. MqttClient client = new MqttClient(mqttServerAddress, mqttClientId, new MemoryPersistence()); try { @@ -171,5 +180,6 @@ public static void main(String[] args) throws Exception { client.disconnect(); } System.out.println("Finished loop successfully. Goodbye!"); + // [END cloudiotcore_mqtt_publish] } }