Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 820c29a

Browse filesBrowse files
authored
Iot commands beta (GoogleCloudPlatform#1746)
* Adds beta example for Cloud IoT Core device commands
1 parent 59a5073 commit 820c29a
Copy full SHA for 820c29a

File tree

Expand file treeCollapse file tree

15 files changed

+3053
-0
lines changed
Filter options
Expand file treeCollapse file tree

15 files changed

+3053
-0
lines changed
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Cloud IoT Core Python Samples
2+
This folder contains Python samples that demonstrate an overview of the
3+
commands beta feature.
4+
5+
## Quickstart
6+
1. Install the Cloud SDK as described in [the device manager guide](https://cloud.google.com/iot/docs/device_manager_guide).
7+
2. Create a PubSub topic:
8+
9+
gcloud beta pubsub topics create projects/my-iot-project/topics/device-events
10+
11+
3. Create a registry:
12+
13+
gcloud iot registries create my-registry \
14+
--project=my-iot-project \
15+
--region=us-central1 \
16+
--event-notification-config=topic=projects/intense-wavelet-343/topics/device-events
17+
18+
4. Use the `generate_keys.sh` script to generate your signing keys:
19+
20+
<path-to>/python-docs-samples/iot/api-client/generate_keys.sh
21+
22+
5. Register a device:
23+
24+
gcloud iot devices create my-python-device \
25+
--project=my-iot-project \
26+
--region=us-central1 \
27+
--registry=my-registry \
28+
--public-key path=rsa_cert.pem,type=rs256
29+
30+
6. Connect a virtual device using the sample app in the `receive` folder.
31+
7. While the virtual device is connected, send a commmand using the sample app in the `send` folder.
+108Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
.. This file is automatically generated. Do not edit this file directly.
2+
3+
Google Cloud IoT Core Python Samples
4+
===============================================================================
5+
6+
.. image:: https://gstatic.com/cloudssh/images/open-btn.png
7+
:target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=iot/api-client/mqtt_example/README.rst
8+
9+
10+
This directory contains samples for Google Cloud IoT Core. `Google Cloud IoT Core`_ allows developers to easily integrate Publish and Subscribe functionality with devices and programmatically manage device authorization.
11+
Before you run the sample, you must retrieve the Google root certificate. For example, ``wget https://pki.goog/roots.pem`` or ``curl https://pki.goog/roots.pem > roots.pem``.
12+
The following example runs the sample using the project ID ``blue-jet-123`` and the device name ``my-python-device``::
13+
14+
python receive.py \
15+
--registry_id=my-registry \
16+
--project_id=blue-jet-123 \
17+
--device_id=my-python-device \
18+
--algorithm=RS256 \
19+
--private_key_file=../rsa_private.pem
20+
21+
22+
23+
24+
.. _Google Cloud IoT Core: https://cloud.google.com/iot/docs
25+
26+
Setup
27+
-------------------------------------------------------------------------------
28+
29+
30+
Install Dependencies
31+
++++++++++++++++++++
32+
33+
#. Install `pip`_ and `virtualenv`_ if you do not already have them. You may want to refer to the `Python Development Environment Setup Guide`_ for Google Cloud Platform for instructions.
34+
35+
.. _Python Development Environment Setup Guide:
36+
https://cloud.google.com/python/setup
37+
38+
#. Create a virtualenv. Samples are compatible with Python 2.7 and 3.4+.
39+
40+
.. code-block:: bash
41+
42+
$ virtualenv env
43+
$ source env/bin/activate
44+
45+
#. Install the dependencies needed to run the samples.
46+
47+
.. code-block:: bash
48+
49+
$ pip install -r requirements.txt
50+
51+
.. _pip: https://pip.pypa.io/
52+
.. _virtualenv: https://virtualenv.pypa.io/
53+
54+
Samples
55+
-------------------------------------------------------------------------------
56+
57+
MQTT Device Client Example
58+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
59+
60+
.. image:: https://gstatic.com/cloudssh/images/open-btn.png
61+
:target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=iot/api-client/mqtt_example/receive.py;iot/api-client/mqtt_example/README.rst
62+
63+
64+
65+
66+
To run this sample:
67+
68+
.. code-block:: bash
69+
70+
$ python receive.py
71+
72+
usage: receive.py [-h] [--project_id PROJECT_ID] --registry_id REGISTRY_ID
73+
--device_id DEVICE_ID --private_key_file PRIVATE_KEY_FILE
74+
--algorithm {RS256,ES256} [--cloud_region CLOUD_REGION]
75+
[--ca_certs CA_CERTS]
76+
[--mqtt_bridge_hostname MQTT_BRIDGE_HOSTNAME]
77+
[--mqtt_bridge_port {8883,443}]
78+
[--jwt_expires_minutes JWT_EXPIRES_MINUTES]
79+
80+
Example Google Cloud IoT Core MQTT device connection code.
81+
82+
optional arguments:
83+
-h, --help show this help message and exit
84+
--project_id PROJECT_ID
85+
GCP cloud project name
86+
--registry_id REGISTRY_ID
87+
Cloud IoT Core registry id
88+
--device_id DEVICE_ID
89+
Cloud IoT Core device id
90+
--private_key_file PRIVATE_KEY_FILE
91+
Path to private key file.
92+
--algorithm {RS256,ES256}
93+
Which encryption algorithm to use to generate the JWT.
94+
--cloud_region CLOUD_REGION
95+
GCP cloud region
96+
--ca_certs CA_CERTS CA root from https://pki.google.com/roots.pem
97+
--mqtt_bridge_hostname MQTT_BRIDGE_HOSTNAME
98+
MQTT bridge hostname.
99+
--mqtt_bridge_port {8883,443}
100+
MQTT bridge port.
101+
--jwt_expires_minutes JWT_EXPIRES_MINUTES
102+
Expiration time, in minutes, for JWT tokens.
103+
104+
105+
106+
107+
108+
.. _Google Cloud SDK: https://cloud.google.com/sdk/
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# This file is used to generate README.rst
2+
3+
product:
4+
name: Google Cloud IoT Core
5+
short_name: Cloud IoT Core
6+
url: https://cloud.google.com/iot/docs
7+
description: >
8+
`Google Cloud IoT Core`_ allows developers to easily integrate Publish and
9+
Subscribe functionality with devices and programmatically manage device
10+
authorization.
11+
12+
Before you run the sample, you must retrieve the Google root certificate.
13+
For example, ``wget https://pki.goog/roots.pem`` or
14+
``curl https://pki.goog/roots.pem > roots.pem``.
15+
16+
The following example runs the sample using the project ID ``blue-jet-123``
17+
and the device name ``my-python-device``::
18+
19+
python receive.py \
20+
--registry_id=my-registry \
21+
--project_id=blue-jet-123 \
22+
--device_id=my-python-device \
23+
--algorithm=RS256 \
24+
--private_key_file=../rsa_private.pem
25+
26+
setup:
27+
- install_deps
28+
29+
samples:
30+
- name: MQTT Device Client Example
31+
file: receive.py
32+
show_help: True
33+
34+
cloud_client_library: false
35+
36+
folder: iot/api-client/mqtt_example
+220Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2018 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
"""Python sample for connecting to Google Cloud IoT Core via MQTT, using JWT.
17+
This example connects to Google Cloud IoT Core via MQTT, using a JWT for device
18+
authentication. After connecting, by default the device publishes 100 messages
19+
to the device's MQTT topic at a rate of one per second, and then exits.
20+
Before you run the sample, you must follow the instructions in the README
21+
for this sample.
22+
"""
23+
24+
# [START iot_mqtt_includes]
25+
import argparse
26+
import datetime
27+
import os
28+
import ssl
29+
import time
30+
31+
import jwt
32+
import paho.mqtt.client as mqtt
33+
# [END iot_mqtt_includes]
34+
35+
# The initial backoff time after a disconnection occurs, in seconds.
36+
minimum_backoff_time = 1
37+
38+
# The maximum backoff time before giving up, in seconds.
39+
MAXIMUM_BACKOFF_TIME = 32
40+
41+
# Whether to wait with exponential backoff before publishing.
42+
should_backoff = False
43+
44+
45+
# [START iot_mqtt_jwt]
46+
def create_jwt(project_id, private_key_file, algorithm):
47+
"""Creates a JWT (https://jwt.io) to establish an MQTT connection.
48+
Args:
49+
project_id: The cloud project ID this device belongs to
50+
private_key_file: A path to a file containing either an RSA256 or
51+
ES256 private key.
52+
algorithm: The encryption algorithm to use. Either 'RS256' or 'ES256'
53+
Returns:
54+
A str for the JWT from the given project id and private key path,
55+
set to expire in 60 minutes. After 60 minutes, your client will be
56+
disconnected, and a new JWT will have to be generated.
57+
Raises:
58+
ValueError: If the private_key_file does not contain a known key.
59+
"""
60+
61+
token = {
62+
# The time that the token was issued at
63+
'iat': datetime.datetime.utcnow(),
64+
# The time the token expires.
65+
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=60),
66+
# The audience field should always be set to the GCP project id.
67+
'aud': project_id
68+
}
69+
70+
# Read the private key file.
71+
with open(private_key_file, 'r') as f:
72+
private_key = f.read()
73+
74+
print('Creating JWT using {} from private key file {}'.format(
75+
algorithm, private_key_file))
76+
77+
return jwt.encode(token, private_key, algorithm=algorithm)
78+
# [END iot_mqtt_jwt]
79+
80+
81+
# [START iot_mqtt_config]
82+
def error_str(rc):
83+
"""Convert a Paho error to a human readable string."""
84+
return '{}: {}'.format(rc, mqtt.error_string(rc))
85+
86+
87+
def on_connect(unused_client, unused_userdata, unused_flags, rc):
88+
"""Callback for when a device connects."""
89+
print('on_connect', mqtt.connack_string(rc))
90+
91+
# After a successful connect, reset backoff time and stop backing off.
92+
global should_backoff
93+
global minimum_backoff_time
94+
should_backoff = False
95+
minimum_backoff_time = 1
96+
97+
98+
def on_disconnect(unused_client, unused_userdata, rc):
99+
"""Paho callback for when a device disconnects."""
100+
print('on_disconnect', error_str(rc))
101+
102+
# Since a disconnect occurred, the next loop iteration will wait with
103+
# exponential backoff.
104+
global should_backoff
105+
should_backoff = True
106+
107+
108+
def on_publish(unused_client, unused_userdata, unused_mid):
109+
"""Paho callback when a message is sent to the broker."""
110+
print('on_publish')
111+
112+
113+
def on_message(unused_client, unused_userdata, message):
114+
"""Callback when the device receives a message on a subscription."""
115+
payload = str(message.payload)
116+
print('Received message \'{}\' on topic \'{}\' with Qos {}'.format(
117+
payload, message.topic, str(message.qos)))
118+
119+
120+
def get_client(
121+
project_id, cloud_region, registry_id, device_id, private_key_file,
122+
algorithm, ca_certs, mqtt_bridge_hostname, mqtt_bridge_port):
123+
"""Create our MQTT client. The client_id is a unique string that identifies
124+
this device. For Google Cloud IoT Core, it must be in the format below."""
125+
client_id = 'projects/{}/locations/{}/registries/{}/devices/{}'.format(
126+
project_id, cloud_region, registry_id, device_id)
127+
client = mqtt.Client(client_id=client_id)
128+
129+
password = create_jwt(project_id, private_key_file, algorithm)
130+
131+
# With Google Cloud IoT Core, the username field is ignored, and the
132+
# password field is used to transmit a JWT to authorize the device.
133+
client.username_pw_set(username='unused', password=password)
134+
135+
# Enable SSL/TLS support.
136+
client.tls_set(ca_certs=ca_certs, tls_version=ssl.PROTOCOL_TLSv1_2)
137+
138+
# Register message callbacks. https://eclipse.org/paho/clients/python/docs/
139+
# describes additional callbacks that Paho supports. In this example, the
140+
# callbacks just print to standard out.
141+
client.on_connect = on_connect
142+
client.on_publish = on_publish
143+
client.on_disconnect = on_disconnect
144+
client.on_message = on_message
145+
146+
# Connect to the Google MQTT bridge.
147+
print('Connecting with id: {} and pass: {}'.format(client_id, password))
148+
client.connect(mqtt_bridge_hostname, mqtt_bridge_port)
149+
150+
# This is the topic that the device will receive configuration updates on.
151+
mqtt_command_topic = '/devices/{}/commands/#'.format(device_id)
152+
153+
# Subscribe to the config topic.
154+
print('Subscribing to {}'.format(mqtt_command_topic))
155+
client.subscribe(mqtt_command_topic, qos=1)
156+
157+
return client
158+
# [END iot_mqtt_config]
159+
160+
161+
if __name__ == '__main__':
162+
# [START iot_mqtt_run]
163+
"""Parse command line arguments."""
164+
parser = argparse.ArgumentParser(description=(
165+
'Example Google Cloud IoT Core MQTT device connection code.'))
166+
parser.add_argument(
167+
'--project_id',
168+
default=os.environ.get('GOOGLE_CLOUD_PROJECT'),
169+
help='GCP cloud project name')
170+
parser.add_argument(
171+
'--registry_id', required=True, help='Cloud IoT Core registry id')
172+
parser.add_argument(
173+
'--device_id', required=True, help='Cloud IoT Core device id')
174+
parser.add_argument(
175+
'--private_key_file',
176+
required=True, help='Path to private key file.')
177+
parser.add_argument(
178+
'--algorithm',
179+
choices=('RS256', 'ES256'),
180+
required=True,
181+
help='Which encryption algorithm to use to generate the JWT.')
182+
parser.add_argument(
183+
'--cloud_region', default='us-central1', help='GCP cloud region')
184+
parser.add_argument(
185+
'--ca_certs',
186+
default='roots.pem',
187+
help=('CA root from https://pki.google.com/roots.pem'))
188+
parser.add_argument(
189+
'--mqtt_bridge_hostname',
190+
default='mqtt.googleapis.com',
191+
help='MQTT bridge hostname.')
192+
parser.add_argument(
193+
'--mqtt_bridge_port',
194+
choices=(8883, 443),
195+
default=8883,
196+
type=int,
197+
help='MQTT bridge port.')
198+
parser.add_argument(
199+
'--jwt_expires_minutes',
200+
default=20,
201+
type=int,
202+
help=('Expiration time, in minutes, for JWT tokens.'))
203+
204+
args = parser.parse_args()
205+
206+
# Add any JWT refresh logic here
207+
client = get_client(
208+
args.project_id, args.cloud_region, args.registry_id, args.device_id,
209+
args.private_key_file, args.algorithm, args.ca_certs,
210+
args.mqtt_bridge_hostname, args.mqtt_bridge_port)
211+
212+
# Wait two minutes for commands, for production you may want while True
213+
for i in range(1, 120):
214+
# Process network events.
215+
client.loop()
216+
print('Sleeping...')
217+
time.sleep(1)
218+
219+
print('Finished.')
220+
# [END iot_mqtt_run]

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.