-
Notifications
You must be signed in to change notification settings - Fork 2k
Final additions in private beta #489
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
e47f4c3
e670a34
4c83c85
d4ecd50
915d197
02fa580
562e952
9e8af84
7682821
ddc4231
930b9fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/> | ||
|
||
# Google Cloud IoT Core NodeJS HTTP example | ||
|
||
This sample app publishes messages to Cloud Pub/Sub or states using the HTTP | ||
bridge provided as part of Google Cloud IoT Core. | ||
|
||
Note that before you can run this sample, you must register a device as | ||
described in the parent README. | ||
|
||
# Setup | ||
|
||
Run the following command to install the library dependencies for NodeJS: | ||
|
||
npm install | ||
|
||
# Running the sample | ||
|
||
The following command summarizes the sample usage: | ||
|
||
Usage: cloudiot_http_example_nodejs [options] | ||
|
||
Example Google Cloud IoT Core HTTP device connection code. | ||
|
||
Options: | ||
|
||
-h, --help output usage information | ||
--project_id <project_id> GCP cloud project name. | ||
--registry_id <registry_id> Cloud IoT Core registry id. | ||
--device_id <device_id> Cloud IoT Core device id. | ||
--private_key_file <key_file> Path to private key file. | ||
--algorithm <algorithm> Encryption algorithm to generate the JWT. Either RS256 or ES256 | ||
--cloud_region [region] GCP cloud region | ||
--num_messages [num] Number of messages to publish. | ||
--http_bridge_address [address] HTTP bridge address. | ||
--message_type [events|state] The message type to publish. | ||
|
||
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 shell script provided in the parent folder, you can | ||
run the sample as: | ||
|
||
node cloudiot_http_example_nodejs.js \ | ||
--project_id=blue-jet-123 \ | ||
--registry_id=my-registry \ | ||
--device_id=my-node-device \ | ||
--private_key_file=../rsa_private.pem \ | ||
--algorithm=RS256 | ||
|
||
# Reading Cloud Pub/Sub 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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
const jwt = require('jsonwebtoken'); | ||
const request = require('request'); | ||
|
||
console.log('Google Cloud IoT Core HTTP example.'); | ||
var argv = require(`yargs`) | ||
.options({ | ||
project_id: { | ||
default: process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT, | ||
description: 'The Project ID to use. Defaults to the value of the GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variables.', | ||
requiresArg: true, | ||
type: 'string' | ||
}, | ||
cloud_region: { | ||
default: 'us-central1', | ||
description: 'GCP cloud region.', | ||
requiresArg: true, | ||
type: 'string' | ||
}, | ||
registry_id: { | ||
description: 'Cloud IoT registry ID.', | ||
requiresArg: true, | ||
demandOption: true, | ||
type: 'string' | ||
}, | ||
device_id: { | ||
description: 'Cloud IoT device ID.', | ||
requiresArg: true, | ||
demandOption: true, | ||
type: 'string' | ||
}, | ||
private_key_file: { | ||
description: 'Path to private key file.', | ||
requiresArg: true, | ||
demandOption: true, | ||
type: 'string' | ||
}, | ||
algorithm: { | ||
description: 'Encryption algorithm to generate the JWT.', | ||
requiresArg: true, | ||
demandOption: true, | ||
choices: ['RS256', 'ES256'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the target user of this sample is expected to be familiar with JWT, or node already prints allowed choices, then please ignore my comment: It might help to print the allowed choices in the help/description message. |
||
type: 'string' | ||
}, | ||
num_messages: { | ||
default: 100, | ||
description: 'Number of messages to publish.', | ||
requiresArg: true, | ||
type: 'number' | ||
}, | ||
http_bridge_address: { | ||
default: 'cloudiot-device.googleapis.com', | ||
description: 'HTTP bridge address.', | ||
requiresArg: true, | ||
type: 'string' | ||
}, | ||
message_type: { | ||
default: 'events', | ||
description: 'Message type to publish.', | ||
requiresArg: true, | ||
choices: ['events', 'state'], | ||
type: 'string' | ||
} | ||
}) | ||
.example(`node $0 cloudiot_http_example_nodejs.js --project_id=blue-jet-123 --registry_id=my-registry --device_id=my-node-device --private_key_file=../rsa_private.pem --algorithm=RS256`) | ||
.wrap(120) | ||
.recommendCommands() | ||
.epilogue(`For more information, see https://cloud.google.com/iot-core/docs`) | ||
.help() | ||
.strict() | ||
.argv; | ||
|
||
// Create a Cloud IoT Core JWT for the given project ID, signed with the given | ||
// private key. | ||
function createJwt (projectId, privateKeyFile, algorithm) { | ||
// Create a JWT to authenticate this device. The device will be disconnected | ||
// after the token expires, and will have to reconnect with a new token. The | ||
// audience field should always be set to the GCP project ID. | ||
const token = { | ||
'iat': parseInt(Date.now() / 1000), | ||
'exp': parseInt(Date.now() / 1000) + 20 * 60, // 20 minutes | ||
'aud': projectId | ||
}; | ||
const privateKey = fs.readFileSync(privateKeyFile); | ||
return jwt.sign(token, privateKey, { algorithm: algorithm }); | ||
} | ||
|
||
// Publish numMessages message asynchronously, starting from message | ||
// messageCount. Telemetry events are published at a rate of 1 per second and | ||
// states at a rate of 1 every 2 seconds. | ||
function publishAsync (messageCount, numMessages) { | ||
const payload = `${argv.registry_id}/${argv.device_id}-payload-${messageCount}`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checked in duplicate versions of the same sample, will clean up after dinner. |
||
console.log('Publishing message:', payload); | ||
const binaryData = Buffer.from(payload).toString('base64'); | ||
const postData = argv.message_type === 'events' ? { | ||
binary_data: binaryData | ||
} : { | ||
state: { | ||
binary_data: binaryData | ||
} | ||
}; | ||
const options = { | ||
url: url, | ||
headers: { | ||
'Authorization': 'Bearer ' + authToken | ||
}, | ||
json: true, | ||
body: postData | ||
}; | ||
const delayMs = argv.message_type === 'events' ? 1000 : 2000; | ||
request.post(options, function (error, response, body) { | ||
if (error) { | ||
return console.error('Received error: ', error); | ||
} | ||
console.log('Received response: '); | ||
console.dir(response); | ||
if (messageCount < numMessages) { | ||
// If we have published fewer than numMessage messages, publish payload | ||
// messageCount + 1. | ||
setTimeout(function () { | ||
publishAsync(messageCount + 1, numMessages); | ||
}, delayMs); | ||
} | ||
}); | ||
} | ||
|
||
// A unique string that identifies this device. For Google Cloud IoT Core, it | ||
// must be in the format below. | ||
const devicePath = `projects/${argv.project_id}/locations/${argv.cloud_region}/registries/${argv.registry_id}/devices/${argv.device_id}`; | ||
|
||
// The request path, set accordingly depending on the message type. | ||
const pathSuffix = argv.message_type === 'events' | ||
? ':publishEvent' : ':setState'; | ||
const url = `https://${argv.http_bridge_address}/v1beta1/${devicePath}${pathSuffix}`; | ||
const authToken = createJwt(argv.project_id, argv.private_key_file, argv.algorithm); | ||
|
||
// Publish messages. | ||
publishAsync(1, argv.num_messages); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "nodejs-docs-samples-iot-http-example", | ||
"version": "0.0.1", | ||
"description": "HTTP Example for Google Cloud IoT Core using NodeJS.", | ||
"main": "cloudiot_http_example_nodejs.js", | ||
"dependencies": { | ||
"yargs": "8.0.2", | ||
"jsonwebtoken": "7.4.1", | ||
"request": "2.82.0" | ||
}, | ||
"devDependencies": {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what "Cloud Pub/Sub or states" means.