From 7ce7079128b05605daa36c9b2bdf2cf926515fb7 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Fri, 22 Dec 2017 11:38:02 -0800 Subject: [PATCH] IoT MQTT Tests (#966) * Adds MQTT device tests and example of configuration retrieval * Fixes compilation * Changes RSA certs to not expire, updates manager with setConfig, adds tests. * Updates MQTT client dependency to use latest version from Maven central. * Removes unused scripts and updates sample quickstart instructions. * Updates flaky tests in vision beta. --- iot/api-client/README.md | 34 +---- iot/api-client/manager/README.md | 53 +++++++ iot/api-client/manager/pom.xml | 5 + iot/api-client/manager/resources/rsa_cert.pem | 32 ++-- .../manager/resources/rsa_private.pem | 52 +++---- .../manager/resources/rsa_private_pkcs8 | Bin 1218 -> 1216 bytes .../iot/examples/DeviceRegistryExample.java | 143 ++++++++++-------- .../DeviceRegistryExampleOptions.java | 28 +++- .../cloud/iot/examples/MqttExample.java | 40 ++++- .../iot/examples/MqttExampleOptions.java | 2 +- .../example/cloud/iot/examples/ManagerIT.java | 143 ++++++++++++++++++ iot/api-client/mqtt_example/README.md | 52 ------- iot/api-client/mqtt_example/pom.xml | 69 --------- iot/api-client/scripts/README.md | 33 ---- iot/api-client/scripts/pom.xml | 76 ---------- .../example/pubsub/AddCloudIotService.java | 56 ------- .../java/com/example/vision/DetectIT.java | 3 +- 17 files changed, 401 insertions(+), 420 deletions(-) rename iot/api-client/{mqtt_example/src/main/java/com/google => manager/src/main/java/com/example}/cloud/iot/examples/MqttExample.java (87%) rename iot/api-client/{mqtt_example/src/main/java/com/google => manager/src/main/java/com/example}/cloud/iot/examples/MqttExampleOptions.java (99%) delete mode 100644 iot/api-client/mqtt_example/README.md delete mode 100644 iot/api-client/mqtt_example/pom.xml delete mode 100644 iot/api-client/scripts/README.md delete mode 100644 iot/api-client/scripts/pom.xml delete mode 100644 iot/api-client/scripts/src/main/java/com/example/pubsub/AddCloudIotService.java diff --git a/iot/api-client/README.md b/iot/api-client/README.md index 4aca24a872b..d2e5f139e41 100644 --- a/iot/api-client/README.md +++ b/iot/api-client/README.md @@ -4,35 +4,17 @@ Google Cloud IoT Core platform. ## Quickstart -1. Install the gCloud CLI as described in [the Cloud IoT Core documentation](https://cloud.google.com/iot/docs/how-tos/getting-started#set_up_the_google_cloud_sdk_and_gcloud). -2. Create a PubSub topic: - - gcloud beta pubsub topics create projects/my-iot-project/topics/device-events - -3. Add the special account `cloud-iot@system.gserviceaccount.com` with the role `Publisher` to that -PubSub topic from the [Cloud Developer Console](https://console.cloud.google.com) -or by using the helper script in the [/scripts](./scripts) folder. - -4. Create a registry: - - gcloud beta iot registries create my-registry \ - --project=my-iot-project \ - --region=us-central1 \ - --event-pubsub-topic=projects/my-iot-project/topics/device-events - -5. Use the [`generate_keys.sh`](generate_keys.sh) script to generate your signing keys: +1. From the [Google Cloud IoT Core section](https://console.cloud.google.com/iot/) + of the Google Cloud console, create a device registry. +2. Use the [`generate_keys.sh`](generate_keys.sh) script to generate your signing keys: ./generate_keys.sh -6. Create a device. +3. Add a device using the file `rsa_cert.pem`, specifying RS256_X509 and using the + text copy of the public key starting with the ----START---- block of the certificate. - gcloud beta iot devices create my-java-device \ - --project=my-iot-project \ - --region=us-central1 \ - --registry=my-registry \ - --public-key path=rsa_cert.pem,type=rs256 + cat rsa_cert.pem -7. Connect a sample device using the sample app in the [`mqtt_example`](./mqtt_example) folder. -8. Learn how to manage devices programatically with the sample app in the -`manager` folder. +4. Connect a device using the HTTP or MQTT device samples in the [manager](./manager) folder. +5. Programmattically control device configuration and using the device manager sample in the [manager](./manager) folder. diff --git a/iot/api-client/manager/README.md b/iot/api-client/manager/README.md index 1935be2cf4e..721fabd3abd 100644 --- a/iot/api-client/manager/README.md +++ b/iot/api-client/manager/README.md @@ -211,3 +211,56 @@ To publish state messages, run the sample as follows: gcloud beta pubsub subscriptions pull --auto-ack \ projects/my-iot-project/subscriptions/my-subscription ``` + +# Cloud IoT Core Java MQTT example + +This sample app publishes data to Cloud Pub/Sub using the MQTT bridge provided +as part of Google Cloud IoT Core. + +Note that before you can run the sample, you must configure a Google Cloud +PubSub topic for Cloud IoT Core and register a device as described in the +[parent README](../README.md). + +## Setup + +Run the following command to install the dependencies using Maven: + + mvn clean compile + +## Running the sample + +The following command summarizes the sample usage: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.MqttExample" \ + -Dexec.args="-project_id=my-iot-project \ + -registry_id=my-registry \ + -device_id=my-device \ + -private_key_file=rsa_private_pkcs8 \ + -algorithm=RS256" + +For example, if your project ID is `blue-jet-123`, your service account +credentials are stored in your home folder in creds.json and you have generated +your credentials using the [`generate_keys.sh`](../generate_keys.sh) script +provided in the parent folder, you can run the sample as: + + mvn exec:java \ + -Dexec.mainClass="com.example.cloud.iot.examples.MqttExample" \ + -Dexec.args="-project_id=blue-jet-123 \ + -registry_id=my-registry \ + -device_id=my-device \ + -private_key_file=../rsa_private_pkcs8 \ + -algorithm=RS256" + +## Reading the messages written by the sample client + +1. Create a subscription to your topic. + + gcloud beta pubsub subscriptions create \ + projects/your-project-id/subscriptions/my-subscription \ + --topic device-events + +2. Read messages published to the topic + + gcloud beta pubsub subscriptions pull --auto-ack \ + projects/my-iot-project/subscriptions/my-subscription diff --git a/iot/api-client/manager/pom.xml b/iot/api-client/manager/pom.xml index df8573e75ad..1e11014988a 100644 --- a/iot/api-client/manager/pom.xml +++ b/iot/api-client/manager/pom.xml @@ -37,6 +37,11 @@ + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.0 + org.json json diff --git a/iot/api-client/manager/resources/rsa_cert.pem b/iot/api-client/manager/resources/rsa_cert.pem index 53cdf27f607..2ea46d003ae 100644 --- a/iot/api-client/manager/resources/rsa_cert.pem +++ b/iot/api-client/manager/resources/rsa_cert.pem @@ -1,18 +1,18 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/iot/api-client/manager/resources/rsa_private.pem b/iot/api-client/manager/resources/rsa_private.pem index bcab9fb0092..463c8e6897c 100644 --- a/iot/api-client/manager/resources/rsa_private.pem +++ b/iot/api-client/manager/resources/rsa_private.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdWhkFaxeyeXKe -2Sa2pfuzIGH5jmiuDq+bETmVRSMRuNL3o1hyxMAH+Pch1h8yXacWLqrwg4gSnLfo -SRIVCbTyjB8miabCZ0IhLHG4Bs+3Yz2Bf4sNiNQU3Z68mkUBMPQxg8tlYJR/xK9w -nQv14jF0lGqqBO3I9Pu6AHN4PpBAnos7PIM8B2mLDFkltvoZx0/Sa9yImk01RlO0 -QGhkNS60AXdD8PQZaE94b5L5A1v7PqVUmyqQXQHKO4BaniNOc9zMXg7EklYWSpOR -VK9ExYV7IAo/3G8p41cHim3QuKbxAAEEt0Cd7zm1v9W0PQLSDUcCaOd7DWO/HwGF -F29z82NZAgMBAAECggEBAKMHcfhQqRJ1apteWqoZ1ClZR2/zmFviSypN5HhxhGPQ -Gen0b/ePu9PjZbmRKEcDPUYUNyiP58+1h6pY7y15icE+vM64gY8bWFRwlI0yzxhF -yo4vby4XwgRgOkK06O/4q1IwvMS8/oKgTYsG0EFYSI6RpYH1wWDKNwEGxgUhJ0O/ -YxTlFpEObuBg+aILeEemU6+QoULwNgfCqVUEkbSZFy5Z9D66PdRoiLum6FmwICBd -rChr06ACqCxuiFhMb1VoHPinIvJNZeLClUGShi9R/hgUZfZxddpNKDtEjZGFWgNw -dVpDFbpVLsqiV+B2TlfX10u9RnWoVi5r8Iv3gMdpqqUCgYEA82c9rm/fEi7fp03U -Y5C1z1YX/7UP+bbsOEZi6BsnJOSptbnBt0g4Ph0TRIbWsAAjd9psU3rSK73U8kso -6xCRe05RzhXWbnl80TUGQpLFcAlZd7R6eXe9kESGu+sheIXGcRJnzM6CFykerkhV -nGp29t/sQBVggqBm7/o8oJg1cLcCgYEA6M608xHaMr1Xw+hEdYqAnxJ4nLwG5Gja -T5NyeGyuJnPP9ullza/n2mOm6ujznzD3JGLqhixR4TI3h2vQ7oMDtkbytRFmishW -rrW59OM3hohvdd0GMfI4boNCyEBMc1s1855nqHprpje+l3S9HuPUHYI4KXlQzz4o -fqCoWHSonG8CgYEAjYhO2Yu7jnsrGcGr6mlPDszlD49dRrsTCHYFNSn0zQMZm83z -0ntwGM4XUhWF6Llr5llf+/rDEyRDGtCRbn4n2idkcg1Irtx9s7i9dyCZJdiJ6Y1M -Wi1CUQ1HuyWyRL6k8ULekLzT8Fu8t2LgRR+zJUJ3wZusjshuksRTVJ6tFGkCgYBl -VxWNeYfx7ln1/XVPdSroE7JNB8w4QSxG13hM04I7Ws58PL0D/D6A4kAWobDq6vWp -8SUFouVBkgp5+ITKTl2fSuL7zsdEQlD5XEHGR+IzvdBHDh9UPowyDxFS+ipNTLb/ -hUS6IhAaGsnsQ/TPLX14Guc3pod2rygRdv3RA3ciIQKBgEhWmdwDjB3c8/7c/vhV -gU+OYziQPHJb7IYrvCxAMym+lM6SVAR62vDSkGBwZdgnr4X1LwO9/qbV+eOR07hv -KhDQ9AX10y1t7FHybZMatvr0l283/BVanXonq7ihzrWjDnZU97N05gIj6Ew4EHy7 -EGgOLKa63rYJQK4WLwP4mMEF +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCzaWesYabNF5KP +yhMfrzBHvlZajIHLMx7E9hwUxSQRvAvq3IbmEuH1RsfqBTuG5zQsloQlNcNGEXhx +Ov56JywmfzNM5kVmf9ZB5B2N6O2K9NKmO/BcsFR5T6PDQNPAZPzXfT7BpQo++WEh +4S7lzHQUlJy8L2Xzc9m866XoTbvqSyo1kwyl2TOn/1iGJbAoQ7+0jjKZqZmaOx/+ +CIlOj3r79+f7qdetwANUvAz6SrKiz5tl/ia9LPiVAw9B2f2W82P4rGJEwpaFONMw +C2kTOb+6nWJLLNNfGS1ULknjYU1tpBrqff/oyeULAIDT2Cvb/lTeONX9lpHGhsju +129YE01bAgMBAAECggEAdA0CWqbv1kohK5FyvVP8zut3wCqS6nWuuYjYsTa0FiSl +MM5lE/2y241lUyL/VkvHm+/gmpEkNvamCdg3M5yTGnO9I0jwK1UVqpl75Id+4Btt +BspOuCX2/mFddLdCQXkRc/I33dp7vjBhfCDEzTBrBcT7fV7Le6a8eU+Uiad+nhXa +9kIZxQdavaFtHUW8ltuJHfG0BCsQ7saQlmTTV7JS3gPd3VgftDZslM+4a1ac1Uoc ++ADDTURCdkIiari168bWBE060T5O3FLFo+H4W3cTuylUQwPEmOOVqj3MP1oRM8CV +IXARL2KRi6TT4oXcm2ntEZxtiN3Oo9icqV0/FlzhAQKBgQDkAXfHHpAr23DxVEpP +uSIYM7ASFETC+w7IX2qcjAQX1uTUG/2sRuzpaoZe9VoaUZNdnXgQXOBhNkQlgHgm +8LQhN+CFlQZAbqvLvj46UjNwBxwISQW4Qd904VuJuC4ew+OsA8ZxWe/BrbDU8zHM +Vu1eSu89BrQB15CNQmkDkhIACwKBgQDJcI+zcPV0Lcf5JnA2LrttqosFMJ0XAlvV ++KLLNG13oGuPWW2sROvtpHiPFO/FzX9hR3NSocNjwj0Y7QlULr7KfPK1nLHBa1Os +DFnKVLb9UUIqDsMCAzupY3zc4fh7Jw9FfIveLYf0nDjSuTeyp8Mt93m4bmLhFgBs +dKs9546p8QKBgCE+AYubbiOmy9Gzm14CPPFQX+RS5i+TUPVvy+hlFZewMg6mwhZj +BNmHOW4Q0YEy0Yx9j+q6z8/8jHT3RQ1QXMLXFboEHzQ3rn53DzWLlIpJzxF6LAZQ +PFcbIDB1FOxRXRlQN5eBKE6Rl02E44bKSbNMs5KvLoFyP1YJD6yAmHU/AoGAe6dz +Lu26XvTzeogT/c62E13LNQZgiA1UnoagOCkYwYRiQn7dChDM2vZJY1uwzDWXafnY +WvMd5BEKPFDVly2SxO3qd32WyGq/1C9ItyFFqz7EZNjm8EdXymVd8qFsTPzvLPKF +UX+Vo5x6bTBxdmPxNjhiKcrpO86rt+fubnPEaaECgYBn2dFS/G7kUs0ybH2JZTp3 +Y68lnY3mzfQCX4J83I81aAXU+IhHK7n1hegVGP47dVZ2iizaib+ubX0JCaa0pwHe +K/geI+vcK7WNa3LKXL70OmZO0ToscdUC5jVKFCohmDo9+oecOndQ8OkjLkZMiBDG +oOwoxIvf1KkQ7VyFYgnOBA== -----END PRIVATE KEY----- diff --git a/iot/api-client/manager/resources/rsa_private_pkcs8 b/iot/api-client/manager/resources/rsa_private_pkcs8 index c197093331958fc6a30f474ddb17204c7b5a0643..d0a9c8ba0ac6d18403e80f7c580d83cd92c2ff81 100644 GIT binary patch literal 1216 zcmV;x1V8&Qf&{z*0RS)!1_>&LNQUrrZ9p8q5=T`0)hbn0JCXltYN0j z7m|<46CbZIN4{2CjDgED9>n$>6vZSFybJ2whUOCC^+w0)1v`f4G%S{cB{joF5qNPr z{(2`YCVw+b=0#?I)qYJ0JcCiB6At`}gPj zsn@N*15~^W`bx5*&zoibCcP~9l>-k!+5MLDWB9CMM8cMZIMXl-X%jiWx}9Q6EYn{Z zEmST^<6%v0q#Ejd|LDo(3jl!A*el!qRNgq%{g#o&hRE*MZ&(veTLJ?C009Dm0RVIj z0$Qf;)=D8Ok#fCL{Lbrlz$%jJb*{OH*s(UW79^!G&Sew*vfGViQzHLXOUIk<;F^&n zHuk0o*f%qrlNxiqBS`QoRTZk4d*p|H;2UiQ%1*c?_WogAbhko5c@cB+H{IHMzA#~Y zAjHiuYX!vneO}9Zro4Gil!>Q)o)y~mLK(#eTD_rd9YwsB+ld|Vv;->`X(g_Qq;-*n+yiMTEv!{e+2#&KEi!L6{= z^D)d;?OsanJqEM^*N}}uX#+Pg?j}-64&3|D>b5fzhW5PWc?Fm#azRG;^wVbiRYg4QYS;|zl z{ZT?H4#NTiJE>!Q+~N3pCl5t@i{34V^qe@-xi_+>!!7rDxNc(M765E?t3BtAsqq4V zfFV8si<@pErpwW@n_dDu@lapnQsys{Q1x%i=w%g`urdy&!WLr$*@ro95Yd4$(TshM z>blR*{ET$>MGa6~!q*kL1Rpdvu6}n9HH(yrNzV~_ECx_KR~sNObrkGTT^Ud}mw_lw zk(W(`2Y)t&`Eb@g>f0d)0dTlUqc4P52IASTv={wG=x99F|bHr(( z0)c>M+0jz`ZsbzUGHiW`Wjc3buO*$0=FRj1UxIwxk2Poo)cA-;E4lTB=oJ|LJ9Soe ziY(fRzpib42??gOrvct8_#Pwc+$*(>YjVn5zVtd~PSH9nan%CmHA)mJA(%Qn`iGo4 ecTn)@BQ8cvh!Do0>?p*G-_)rP?OcUo3C;u=8cRU{ literal 1218 zcmV;z1U>sOf&{(-0RS)!1_>&LNQUrs4#*Aqyhl|0)hbn0Nq*{1#1_w zd2*iFCbp&fvmjylj%cn9ubUA$l|>^FxYGBdSaQU`2l)3P)*mumrxq@%@PmjFoVVyn z5)}!w@{AuQiKfD5LLn@1xCYO+V?BX?iw%g>6y2V@nneLH^f80WWnh$l#IJCj3-#hL zbd+kU1ntQ5`?>&gcs`Ioo{Kv?gFFXmiws#Mw)z>zPtt4Lh?-3`MpLvvXk;}mv;lWR z@bnpIPk3*V`2$<~KBZKfDv(_P$~%Bso+D0k+{|7M#FADPN|TXPuSCU#dmsuw+;1u4 zR|kr1(72}Y009KIK%MV7wZGN0Jp$4VM*?W)dktg19|46IZ*%iwSpowA009Dm0RaG` z2XXjNsSGW^+kGs?3Wx0_kM*}@Z6gMc3 z=g+l=s#xzWd5OV3yw13Rj~iH2aFmTQ&lp9@jxTR67s3Q!IzqJQ@A#`yFucUP{(_)Q ziw4j^SV)eMrGfRqV9GZE2F3*;Cqutu6y+9?4sPIJ`JxMWN2XJ+kfB2GHV49~RRoc= znHMfu^gg;h)M$virs!F)ARt|=C~MQ80;nu*h*(T-RcIXery}xAW#Yn>L6U|qQT`Yd zW%hA(+D#}sM2(S!S_5!(T0<4ORW8b+SKxL|SJ&4|y+(DYRxWGsi}!%XX{x0Hfq?+? zXFaZO-x4n0r%lvjkhRZN7yq>n`L^shMq=n2CnV&lwYkB!NH{(n6GVpAumB@>+H6yL z(ks2x@=GY|5RrRMQO*_CZh3ssH3mYG#c&B(ceHwWcfF8AhP&$_c!kDs5@*cLf)^_8P@f}m#a`aGbRHE_2Afq?+%&b0Fp+A_UY!{|hHih!RIc$~Zj5WWUEkaQZN4q7mM82f)Lf(+P z)9_oow_@N$AG0Mwcfp&ij>vA3#8XtBtrTejfq-RK6^(g^@$Omm{dG@uD(DlkO$W?4 zK`chscudoRJ6g_sJiP<_K7ist7NM}}>h-DdB?Y48L6Qo2_=L(%U7t$g`_9KiLQwf! zLB>boGriD94j)uLj4}@qQu-=QOt$}pM7kmn8XC#$L-fxreRvw@H>QVnuP70A{m}z= zA|V2SfJj!E+yjgq-1Gk2{`ggaPmW_akUVl*?1n46EI>0UzLd_AR0Mk3@Y0ZAaAnvh zuZ8t51HJyH)%oL*)3|Rc5YY4m_0uhF>{0S devices = service @@ -202,8 +204,8 @@ public static void createDeviceWithEs256(String deviceId, String publicKeyFilePa GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + 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); @@ -243,8 +245,8 @@ public static void createDeviceWithRs256(String deviceId, String certificateFile GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + 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); @@ -318,10 +320,9 @@ public static void deleteDevice(String deviceId, String projectId, String cloudR GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; + final String devicePath = String.format("projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); - final String devicePath = registryPath + "/devices/" + deviceId; System.out.println("Deleting device " + devicePath); service.projects().locations().registries().devices().delete(devicePath).execute(); } @@ -337,10 +338,9 @@ public static Device getDevice(String deviceId, String projectId, String cloudRe GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" - + registryName; + final String devicePath = String.format("projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); - String devicePath = registryPath + "/devices/" + deviceId; System.out.println("Retrieving device " + devicePath); return service.projects().locations().registries().devices().get(devicePath).execute(); } @@ -357,14 +357,19 @@ public static List getDeviceStates( GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" - + registryName; + final String devicePath = String.format("projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); - String devicePath = registryPath + "/devices/" + deviceId; System.out.println("Retrieving device states " + devicePath); - ListDeviceStatesResponse resp = service.projects().locations().registries().devices().states() + ListDeviceStatesResponse resp = service + .projects() + .locations() + .registries() + .devices() + .states() .list(devicePath).execute(); + return resp.getDeviceStates(); } @@ -380,8 +385,9 @@ public static DeviceRegistry getRegistry( GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; + final String registryPath = String.format("projects/%s/locations/%s/registries/%s", + projectId, cloudRegion, registryName); + return service.projects().locations().registries().get(registryPath).execute(); } @@ -397,10 +403,9 @@ public static void listDeviceConfigs( GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; + final String devicePath = String.format("projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); - final String devicePath = registryPath + "/devices/" + deviceId; System.out.println("Listing device configs for " + devicePath); List deviceConfigs = service @@ -457,36 +462,6 @@ public static void listRegistries(String projectId, String cloudRegion) } } - /** Modify the latest cloud to device config for the given device, with the config data. */ - public static void modifyCloudToDeviceConfig(String deviceId, String configData, String projectId, - String cloudRegion, String registryName) - throws GeneralSecurityException, IOException { - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = new CloudIot.Builder( - GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) - .setApplicationName(APP_NAME).build(); - - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; - final String devicePath = registryPath + "/devices/" + deviceId; - ModifyCloudToDeviceConfigRequest request = new ModifyCloudToDeviceConfigRequest(); - request.setVersionToUpdate(0L); // 0L indicates update all versions - request.setBinaryData(DatatypeConverter.printBase64Binary(configData.getBytes(Charsets.UTF_8))); - DeviceConfig config = - service - .projects() - .locations() - .registries() - .devices() - .modifyCloudToDeviceConfig(devicePath, request) - .execute(); - - System.out.println("Created device config: " + config.toPrettyString()); - } - /** Patch the device to add an ES256 key for authentication. */ public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, String projectId, String cloudRegion, String registryName) @@ -499,10 +474,9 @@ public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; + final String devicePath = String.format("projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); - final String devicePath = registryPath + "/devices/" + deviceId; PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8); publicKeyCredential.setKey(key); @@ -540,10 +514,9 @@ public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) .setApplicationName(APP_NAME).build(); - final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion - + "/registries/" + registryName; + final String devicePath = String.format("projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); - final String devicePath = registryPath + "/devices/" + deviceId; PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8); publicKeyCredential.setKey(key); @@ -568,6 +541,41 @@ public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, System.out.println("Patched device is " + patchedDevice.toPrettyString()); } + /** 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) + throws GeneralSecurityException, IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); + JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); + HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); + final CloudIot service = new CloudIot.Builder( + GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init) + .setApplicationName(APP_NAME).build(); + + final String devicePath = String.format("projects/%s/locations/%s/registries/%s/devices/%s", + projectId, cloudRegion, registryName, deviceId); + + ModifyCloudToDeviceConfigRequest req = new ModifyCloudToDeviceConfigRequest(); + req.setVersionToUpdate(version); + + // Data sent through the wire has to be base64 encoded. + Base64.Encoder encoder = Base64.getEncoder(); + String encPayload = encoder.encodeToString(data.getBytes("UTF-8")); + req.setBinaryData(encPayload); + + DeviceConfig config = + service + .projects() + .locations() + .registries() + .devices() + .modifyCloudToDeviceConfig(devicePath, req).execute(); + + System.out.println("Updated: " + config.getVersion()); + } + /** Entry poit for CLI. */ public static void main(String[] args) throws Exception { DeviceRegistryExampleOptions options = DeviceRegistryExampleOptions.fromFlags(args); @@ -647,9 +655,22 @@ public static void main(String[] args) throws Exception { 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); + } + break; default: - System.out.println("You entered: " + options.command); - System.out.println("Wrong, wrong, wrong. Usage is like this:"); // TODO: + String header = "Cloud IoT Core Commandline Example (Device / Registry management): \n\n"; + String footer = "\nhttps://cloud.google.com/iot-core"; + + HelpFormatter formatter = new HelpFormatter(); + 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 cc3e5de8ef7..4da7f79f39b 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 @@ -29,13 +29,15 @@ public class DeviceRegistryExampleOptions { String rsaCertificateFile = "rsa_cert.pem"; String cloudRegion = "us-central1"; String command = "help"; + String configuration = "Specify with -configuration"; String deviceId; // Default to UUID? String pubsubTopic; String registryName; + long version = 0; + static final Options options = new Options(); /** Construct an DeviceRegistryExampleOptions class from command line flags. */ public static DeviceRegistryExampleOptions fromFlags(String[] args) { - Options options = new Options(); // Required arguments options.addOption( Option.builder() @@ -65,7 +67,8 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { + "\n\tlist-devices" + "\n\tlist-registries" + "\n\tpatch-device-es" - + "\n\tpatch-device-rsa") + + "\n\tpatch-device-rsa" + + "\n\tset-config") .required() .build()); @@ -112,6 +115,20 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc("Name for your Device.") .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("configuration") + .hasArg() + .desc("The configuration (string or JSON) to set the specified device to.") + .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("version") + .hasArg() + .desc("The configuration version to send on the device (0 is latest).") + .build()); CommandLineParser parser = new DefaultParser(); CommandLine commandLine; @@ -156,6 +173,13 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { if (commandLine.hasOption("device_id")) { res.deviceId = commandLine.getOptionValue("device_id"); } + if (commandLine.hasOption("configuration")) { + res.configuration = commandLine.getOptionValue("configuration"); + } + if (commandLine.hasOption("version")) { + res.version = new Long(commandLine.getOptionValue("version")).longValue(); + } + return res; } catch (ParseException e) { String header = "Cloud IoT Core Commandline Example (Device / Registry management): \n\n"; diff --git a/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java similarity index 87% rename from iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExample.java rename to iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java index 524a519abf1..7c7c6b5e42e 100644 --- a/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java @@ -12,7 +12,7 @@ * limitations under the License. */ -package com.google.cloud.iot.examples; +package com.example.cloud.iot.examples; // [START cloudiotcore_mqtt_imports] import io.jsonwebtoken.JwtBuilder; @@ -22,8 +22,11 @@ import java.nio.file.Paths; import java.security.KeyFactory; import java.security.spec.PKCS8EncodedKeySpec; +import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; +import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.joda.time.DateTime; @@ -94,6 +97,37 @@ private static String createJwtEs(String projectId, String privateKeyFile) throw } // [END cloudiotcore_mqtt_createjwt] + // [START cloudiotcore_mqtt_configcallback] + static MqttCallback mCallback; + + /** Attaches the callback used when configuration changes occur. */ + public static void attachCallback(MqttClient client, String deviceId) throws MqttException { + mCallback = new MqttCallback() { + @Override + public void connectionLost(Throwable cause) { + // Do nothing... + } + + @Override + public void messageArrived(String topic, MqttMessage message) throws Exception { + String payload = new String(message.getPayload()); + System.out.println("Payload : " + payload); + // TODO: Insert your parsing / handling of the configuration message here. + } + + @Override + public void deliveryComplete(IMqttDeliveryToken token) { + // Do nothing; + } + }; + + String configTopic = String.format("/devices/%s/config", deviceId); + client.subscribe(configTopic, 1); + + client.setCallback(mCallback); + } + // [END cloudiotcore_mqtt_configcallback] + /** Parse arguments, configure MQTT, and publish messages. */ public static void main(String[] args) throws Exception { // [START cloudiotcore_mqtt_configuremqtt] @@ -145,6 +179,7 @@ public static void main(String[] args) throws Exception { MqttClient client = new MqttClient(mqttServerAddress, mqttClientId, new MemoryPersistence()); try { client.connect(connectOptions); + attachCallback(client, options.deviceId); // Publish to the events or state topic based on the flag. String subTopic = options.messageType.equals("event") ? "events" : options.messageType; @@ -177,6 +212,9 @@ public static void main(String[] args) throws Exception { "Invalid algorithm " + options.algorithm + ". Should be one of 'RS256' or 'ES256'."); } + client.disconnect(); + client.connect(); + attachCallback(client, options.deviceId); } // Publish "payload" to the MQTT topic. qos=1 means at least once delivery. Cloud IoT Core diff --git a/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExampleOptions.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExampleOptions.java similarity index 99% rename from iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExampleOptions.java rename to iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExampleOptions.java index 2dd3c0b547a..43ae8e174e9 100644 --- a/iot/api-client/mqtt_example/src/main/java/com/google/cloud/iot/examples/MqttExampleOptions.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExampleOptions.java @@ -12,7 +12,7 @@ * limitations under the License. */ -package com.google.cloud.iot.examples; +package com.example.cloud.iot.examples; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; 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 8aeeff5fdce..815f957926e 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 @@ -195,6 +195,29 @@ public void testCreateGetDevice() throws Exception { } } + @Test + public void testCreateConfigureDevice() throws Exception { + final String deviceName = "rsa-device-config"; + 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); + + String got = bout.toString(); + Assert.assertTrue(got.contains("Updated: 2")); + + 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 testCreateListDevices() throws Exception { final String deviceName = "rsa-device"; @@ -235,6 +258,8 @@ public void testCreateGetRegistry() throws Exception { } } + // HTTP device tests + @Test public void testHttpDeviceEvent() throws Exception { final String deviceName = "rsa-device-http-event"; @@ -252,6 +277,7 @@ public void testHttpDeviceEvent() throws Exception { "-registry_id=" + REGISTRY_ID, "-device_id=" + deviceName, "-private_key_file=" + PKCS_PATH, + "-num_messages=1", "-message_type=event", "-algorithm=RS256" }; @@ -288,6 +314,7 @@ public void testHttpDeviceState() throws Exception { "-registry_id=" + REGISTRY_ID, "-device_id=" + deviceName, "-private_key_file=" + PKCS_PATH, + "-num_messages=1", "-message_type=state", "-algorithm=RS256" }; @@ -324,6 +351,7 @@ public void testHttpDeviceConfig() throws Exception { "-registry_id=" + REGISTRY_ID, "-device_id=" + deviceName, "-private_key_file=" + PKCS_PATH, + "-num_messages=1", "-message_type=event", "-algorithm=RS256" }; @@ -343,4 +371,119 @@ public void testHttpDeviceConfig() throws Exception { topicAdminClient.deleteTopic(topic.getNameAsTopicName()); } } + + + // MQTT device tests + @Test + public void testMqttDeviceConfig() throws Exception { + final String deviceName = "rsa-device-mqtt-config"; + 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.listDevices(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + + // 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" + }; + com.example.cloud.iot.examples.MqttExample.main(testArgs); + // End device test. + + // Assertions + String got = bout.toString(); + System.out.println(got); + Assert.assertTrue(got.contains("Payload :")); + + // Clean up + 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 testMqttDeviceEvents() throws Exception { + final String deviceName = "rsa-device-mqtt-events"; + 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.listDevices(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + + // 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" + }; + com.example.cloud.iot.examples.MqttExample.main(testArgs); + // End device test. + + // Assertions + String got = bout.toString(); + // + //Finished loop successfully. Goodbye! + + Assert.assertTrue(got.contains("Publishing events message 1")); + Assert.assertTrue(got.contains("Finished loop successfully. Goodbye!")); + + // Clean up + 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 testMqttDeviceState() throws Exception { + final String deviceName = "rsa-device-mqtt-state"; + 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.listDevices(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); + + // 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" + }; + com.example.cloud.iot.examples.MqttExample.main(testArgs); + // End device test. + + // Assertions + String got = bout.toString(); + Assert.assertTrue(got.contains("Publishing state message 1")); + Assert.assertTrue(got.contains("Finished loop successfully. Goodbye!")); + + // Clean up + 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()); + } + } } diff --git a/iot/api-client/mqtt_example/README.md b/iot/api-client/mqtt_example/README.md deleted file mode 100644 index 969813330a9..00000000000 --- a/iot/api-client/mqtt_example/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# Cloud IoT Core Java MQTT example - -This sample app publishes data to Cloud Pub/Sub using the MQTT bridge provided -as part of Google Cloud IoT Core. - -Note that before you can run the sample, you must configure a Google Cloud -PubSub topic for Cloud IoT Core and register a device as described in the -[parent README](../README.md). - -## Setup - -Run the following command to install the dependencies using Maven: - - mvn clean compile - -## Running the sample - -The following command summarizes the sample usage: - - mvn exec:java \ - -Dexec.mainClass="com.google.cloud.iot.examples.MqttExample" \ - -Dexec.args="-project_id=my-iot-project \ - -registry_id=my-registry \ - -device_id=my-device \ - -private_key_file=rsa_private_pkcs8 \ - -algorithm=RS256" - -For example, if your project ID is `blue-jet-123`, your service account -credentials are stored in your home folder in creds.json and you have generated -your credentials using the [`generate_keys.sh`](../generate_keys.sh) script -provided in the parent folder, you can run the sample as: - - mvn exec:java \ - -Dexec.mainClass="com.google.cloud.iot.examples.MqttExample" \ - -Dexec.args="-project_id=blue-jet-123 \ - -registry_id=my-registry \ - -device_id=my-device \ - -private_key_file=../rsa_private_pkcs8 \ - -algorithm=RS256" - -## Reading the messages written by the sample client - -1. Create a subscription to your topic. - - gcloud beta pubsub subscriptions create \ - projects/your-project-id/subscriptions/my-subscription \ - --topic device-events - -2. Read messages published to the topic - - gcloud beta pubsub subscriptions pull --auto-ack \ - projects/my-iot-project/subscriptions/my-subscription diff --git a/iot/api-client/mqtt_example/pom.xml b/iot/api-client/mqtt_example/pom.xml deleted file mode 100644 index 90cfdaa7396..00000000000 --- a/iot/api-client/mqtt_example/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - com.google.cloud.iot.examples - cloudiot-mqtt-example - jar - 1.0 - cloudiot-mqtt-example - http://maven.apache.org - - - 1.7 - 1.7 - - - - - doc-samples - com.google.cloud - 1.0.0 - ../../../ - - - - - Eclipse Paho Repo - https://repo.eclipse.org/content/repositories/paho-releases/ - - - - - - org.eclipse.paho - org.eclipse.paho.client.mqttv3 - 1.0.2 - - - io.jsonwebtoken - jjwt - 0.7.0 - - - joda-time - joda-time - 2.1 - - - commons-cli - commons-cli - 1.3 - - - - diff --git a/iot/api-client/scripts/README.md b/iot/api-client/scripts/README.md deleted file mode 100644 index d15c79466f3..00000000000 --- a/iot/api-client/scripts/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Getting Started with Cloud Pub/Sub and the Google Cloud Client libraries - -[Google Cloud IoT Core](https://cloud.google.com/iot-core/) -is a fully-managed, globally distributed solution for managing devices and -sending / receiving messages from devices. - -This script manages the [Google Cloud Pub/Sub][pubsub] project associated with -your Google Cloud IoT Core project to grant permissions to the protocol bridge. - -Create your PubSub topic noting the project ID and topic ID, then build and run -the sample to configure your topic. - -[pubsub]: https://cloud.google.com/pubsub/ - -#### Setup - -* Install [Maven](http://maven.apache.org/) -* Build your project with: - - mvn clean compile assembly:single - -#### Running the script - -The following code will run the helper script: - - java -cp target/pubsub-policy-helper-1.0.0-jar-with-dependencies.jar \ - com.example.pubsub.AddCloudIotService - -For example, the following example will configure the `device-events` topic -for the `my-iot-project` project. - - java -cp target/pubsub-policy-helper-1.0.0-jar-with-dependencies.jar \ - com.example.pubsub.AddCloudIotService device-events my-iot-project diff --git a/iot/api-client/scripts/pom.xml b/iot/api-client/scripts/pom.xml deleted file mode 100644 index 5dd299974e6..00000000000 --- a/iot/api-client/scripts/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - 4.0.0 - com.example.pubsub - pubsub-policy-helper - jar - - - - doc-samples - com.google.cloud - 1.0.0 - ../../.. - - - - 1.8 - 1.8 - UTF-8 - 0.20.0-beta - - - - - - maven-assembly-plugin - - - - com.example.pubsub.AddCloudIotService - - - - jar-with-dependencies - - - - - - - - - com.google.cloud - google-cloud-pubsub - ${pubsub.version} - - - - - junit - junit - 4.12 - test - - - com.google.truth - truth - 0.32 - test - - - diff --git a/iot/api-client/scripts/src/main/java/com/example/pubsub/AddCloudIotService.java b/iot/api-client/scripts/src/main/java/com/example/pubsub/AddCloudIotService.java deleted file mode 100644 index 5e1e68e0537..00000000000 --- a/iot/api-client/scripts/src/main/java/com/example/pubsub/AddCloudIotService.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - 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.example.pubsub; - -// [START cloudiotcore_add_service_account] -// Imports the Google Cloud client library -import com.google.cloud.Identity; -import com.google.cloud.Role; -import com.google.cloud.pubsub.v1.TopicAdminClient; -import com.google.iam.v1.Binding; -import com.google.iam.v1.Policy; -import com.google.pubsub.v1.TopicName; - -public class AddCloudIotService { - - public static void main(String... args) throws Exception { - if (args.length < 2) { - System.out.printf("Usage:\n java %s \n\n", - AddCloudIotService.class.getCanonicalName()); - return; - } - - String topicId = args[0]; - String projectId = args[1]; // Could make optional, use: ServiceOptions.getDefaultProjectId(); - - try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { - String topicName = TopicName.create(projectId, topicId).toString(); - Policy policy = topicAdminClient.getIamPolicy(topicName); - // add role -> members binding - Binding binding = - Binding.newBuilder() - .setRole(Role.editor().toString()) - .addMembers(Identity.serviceAccount("cloud-iot@system.gserviceaccount.com") - .toString()) - .build(); - // Add Cloud IoT Core service account. - Policy updatedPolicy = Policy.newBuilder(policy).addBindings(binding).build(); - topicAdminClient.setIamPolicy(topicName, updatedPolicy); - } - } -} -// [END cloudiotcore_add_service_account] diff --git a/vision/beta/cloud-client/src/test/java/com/example/vision/DetectIT.java b/vision/beta/cloud-client/src/test/java/com/example/vision/DetectIT.java index d0833c58a86..211186a6243 100644 --- a/vision/beta/cloud-client/src/test/java/com/example/vision/DetectIT.java +++ b/vision/beta/cloud-client/src/test/java/com/example/vision/DetectIT.java @@ -283,7 +283,8 @@ public void testDetectWebEntitiesIncludeGeoResults() throws Exception { // Assert String got = bout.toString(); - assertThat(got).contains("Zepra"); + // Note: entities and labels can change over time. + assertThat(got).contains("Tel Aviv"); } @Test