1- /**
2- * Copyright 2017, Google, Inc.
3- *
4- * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5- * except in compliance with the License. You may obtain a copy of the License at
6- *
7- * <p>http://www.apache.org/licenses/LICENSE-2.0
8- *
9- * <p>Unless required by applicable law or agreed to in writing, software distributed under the
10- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11- * express or implied. See the License for the specific language governing permissions and
12- * limitations under the License.
13- */
1+ /*
2+ Copyright 2017, Google, Inc.
3+
4+ Licensed under the Apache License, Version 2.0 (the "License");
5+ you may not use this file except in compliance with the License.
6+ You may obtain a copy of the License at
7+
8+ http://www.apache.org/licenses/LICENSE-2.0
9+
10+ Unless required by applicable law or agreed to in writing, software
11+ distributed under the License is distributed on an "AS IS" BASIS,
12+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ See the License for the specific language governing permissions and
14+ limitations under the License.
15+ */
16+
1417
1518package com .google .cloud .iot .examples ;
1619
20+ // [START cloudiotcore_http_imports]
1721import io .jsonwebtoken .JwtBuilder ;
1822import io .jsonwebtoken .Jwts ;
1923import io .jsonwebtoken .SignatureAlgorithm ;
24+ import java .io .IOException ;
25+ import java .io .UnsupportedEncodingException ;
2026import java .net .HttpURLConnection ;
27+ import java .net .ProtocolException ;
2128import java .net .URL ;
2229import java .nio .file .Files ;
2330import java .nio .file .Paths ;
2431import java .security .KeyFactory ;
2532import java .security .spec .PKCS8EncodedKeySpec ;
2633import java .util .Base64 ;
2734import org .joda .time .DateTime ;
35+ import org .json .JSONException ;
2836import org .json .JSONObject ;
37+ // [END cloudiotcore_http_imports]
2938
3039/**
3140 * Java sample of connecting to Google Cloud IoT Core vice via HTTP, using JWT.
3948 * folder.
4049 */
4150public class HttpExample {
42- /** Create a Cloud IoT Core JWT for the given project id, signed with the given private key. */
51+ // [START cloudiotcore_http_createjwt]
52+ /** Create a RSA-based JWT for the given project id, signed with the given private key. */
4353 private static String createJwtRsa (String projectId , String privateKeyFile ) throws Exception {
4454 DateTime now = new DateTime ();
4555 // 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
5868 return jwtBuilder .signWith (SignatureAlgorithm .RS256 , kf .generatePrivate (spec )).compact ();
5969 }
6070
71+ /** Create an ES-based JWT for the given project id, signed with the given private key. */
6172 private static String createJwtEs (String projectId , String privateKeyFile ) throws Exception {
6273 DateTime now = new DateTime ();
6374 // Create a JWT to authenticate this device. The device will be disconnected after the token
@@ -75,28 +86,62 @@ private static String createJwtEs(String projectId, String privateKeyFile) throw
7586
7687 return jwtBuilder .signWith (SignatureAlgorithm .ES256 , kf .generatePrivate (spec )).compact ();
7788 }
89+ // [END cloudiotcore_http_createjwt]
7890
79- public static void main (String [] args ) throws Exception {
80- HttpExampleOptions options = HttpExampleOptions .fromFlags (args );
81- if (options == null ) {
82- // Could not parse the flags.
83- System .exit (1 );
84- }
85-
91+ // [START cloudiotcore_http_publishmessage]
92+ /** Publish an event or state message using Cloud IoT Core via the HTTP API. */
93+ public static void publishMessage (String payload , String urlPath , String messageType ,
94+ String token , String projectId , String cloudRegion , String registryId , String deviceId )
95+ throws UnsupportedEncodingException , IOException , JSONException , ProtocolException {
8696 // Build the resource path of the device that is going to be authenticated.
8797 String devicePath =
8898 String .format (
8999 "projects/%s/locations/%s/registries/%s/devices/%s" ,
90- options .projectId , options .cloudRegion , options .registryId , options .deviceId );
100+ projectId , cloudRegion , registryId , deviceId );
101+ String urlSuffix = messageType .equals ("event" ) ? "publishEvent" : "setState" ;
91102
92- // This describes the operation that is going to be perform with the device .
93- String urlSuffix = options . messageType . equals ( "event" ) ? "publishEvent" : "setState" ;
103+ // Data sent through the wire has to be base64 encoded .
104+ Base64 . Encoder encoder = Base64 . getEncoder () ;
94105
95- String urlPath =
96- String .format (
97- "%s/%s/%s:%s" , options .httpBridgeAddress , options .apiVersion , devicePath , urlSuffix );
106+ String encPayload = encoder .encodeToString (payload .getBytes ("UTF-8" ));
107+
108+
109+ urlPath = urlPath + devicePath + ":" + urlSuffix ;
98110 URL url = new URL (urlPath );
99- System .out .format ("Using URL: '%s'\n " , urlPath );
111+ HttpURLConnection httpCon = (HttpURLConnection ) url .openConnection ();
112+ httpCon .setDoOutput (true );
113+ httpCon .setRequestMethod ("POST" );
114+
115+ // Add headers.
116+ httpCon .setRequestProperty ("authorization" , String .format ("Bearer %s" , token ));
117+ httpCon .setRequestProperty ("content-type" , "application/json; charset=UTF-8" );
118+ httpCon .setRequestProperty ("cache-control" , "no-cache" );
119+
120+ // Add post data. The data sent depends on whether we're updating state or publishing events.
121+ JSONObject data = new JSONObject ();
122+ if (messageType .equals ("event" )) {
123+ data .put ("binary_data" , encPayload );
124+ } else {
125+ JSONObject state = new JSONObject ();
126+ state .put ("binary_data" , encPayload );
127+ data .put ("state" , state );
128+ }
129+ httpCon .getOutputStream ().write (data .toString ().getBytes ("UTF-8" ));
130+ httpCon .getOutputStream ().close ();
131+
132+ System .out .println (httpCon .getResponseCode ());
133+ System .out .println (httpCon .getResponseMessage ());
134+ }
135+ // [END cloudiotcore_http_publishmessage]
136+
137+ // [START cloudiotcore_http_run]
138+ /** Parse arguments and publish messages. */
139+ public static void main (String [] args ) throws Exception {
140+ HttpExampleOptions options = HttpExampleOptions .fromFlags (args );
141+ if (options == null ) {
142+ // Could not parse the flags.
143+ System .exit (1 );
144+ }
100145
101146 // Create the corresponding JWT depending on the selected algorithm.
102147 String token ;
@@ -109,41 +154,18 @@ public static void main(String[] args) throws Exception {
109154 "Invalid algorithm " + options .algorithm + ". Should be one of 'RS256' or 'ES256'." );
110155 }
111156
112- // Data sent through the wire has to be base64 encoded.
113- Base64 .Encoder encoder = Base64 .getEncoder ();
114-
115157 // Publish numMessages messages to the HTTP bridge.
116158 for (int i = 1 ; i <= options .numMessages ; ++i ) {
117159 String payload = String .format ("%s/%s-payload-%d" , options .registryId , options .deviceId , i );
118160 System .out .format (
119161 "Publishing %s message %d/%d: '%s'\n " ,
120162 options .messageType , i , options .numMessages , payload );
121- String encPayload = encoder .encodeToString (payload .getBytes ("UTF-8" ));
122163
123- HttpURLConnection httpCon = (HttpURLConnection ) url .openConnection ();
124- httpCon .setDoOutput (true );
125- httpCon .setRequestMethod ("POST" );
126-
127- // Adding headers.
128- httpCon .setRequestProperty ("Authorization" , String .format ("Bearer %s" , token ));
129- httpCon .setRequestProperty ("Content-Type" , "application/json; charset=UTF-8" );
130-
131- // Adding the post data. The structure of the data send depends on whether it is event or a
132- // state message.
133- JSONObject data = new JSONObject ();
134- if (options .messageType .equals ("event" )) {
135- data .put ("binary_data" , encPayload );
136- } else {
137- JSONObject state = new JSONObject ();
138- state .put ("binary_data" , encPayload );
139- data .put ("state" , state );
140- }
141- httpCon .getOutputStream ().write (data .toString ().getBytes ("UTF-8" ));
142- httpCon .getOutputStream ().close ();
164+ String urlPath = String .format ("%s/%s/" , options .httpBridgeAddress , options .apiVersion );
165+ System .out .format ("Using URL: '%s'\n " , urlPath );
143166
144- // This will perform the connection as well.
145- System .out .println (httpCon .getResponseCode ());
146- System .out .println (httpCon .getResponseMessage ());
167+ publishMessage (payload , urlPath , options .messageType , token , options .projectId ,
168+ options .cloudRegion , options .registryId , options .deviceId );
147169
148170 if (options .messageType .equals ("event" )) {
149171 // Frequently send event payloads (every second)
@@ -155,4 +177,5 @@ public static void main(String[] args) throws Exception {
155177 }
156178 System .out .println ("Finished loop successfully. Goodbye!" );
157179 }
180+ // [END cloudiotcore_http_run]
158181}
0 commit comments