In this lab you will learn how to send commands to IoT devices using Cloud IoT Core Console and configure java sample code so that an IoT Core device subscribes to the command topic.
Commands are transitory, one-time directives sent to devices that are connected to Cloud IoT Core and subscribed to the commands topic.
Compared to device configurations, commands are faster and can be sent at large-volume to many devices simultaneously. Some examples include:
gcloud
command-line.You will be opening multiple browser windows to observe graphical actions. Having a large monitor will be beneficial, but not required.
From the Navigation menu, select IoT Core:
Click Create a device registry:
Create a device registry with the following values:
Field | Value |
Registry ID | my-registry |
Region | us-central1 |
Protocol | MQTT |
Default telemetry topic | Create a topic Append my-device-events to the name and click Create. |
Device state topic | Use the default value |
Add CA certificate | Ignore |
Click Create.
Later in the lab you will generate an RSA public/private key pair that will authenticate your MQTT device when it connects to Google Cloud.
In this section, you will create 3 virtual devices. The new virtual devices will be used for sending commands from the Google Cloud Shell.
Field | Value |
Device ID | mqtt-device-1 |
Device Communication | Allow |
Authentication | Default value (for now) |
Public Key format | Default value (for now) |
Public Key value | Default value (for now) |
Device metadata | Default value |
Click the back arrow at the top of the screen to see the devices listed on the Devices page:
Then click Start Cloud Shell.
openssl req -x509 -newkey rsa:2048 -keyout rsa_private.pem -nodes -out \
rsa_cert.pem -subj "/CN=unused"
openssl pkcs8 -topk8 -inform PEM -outform DER -in rsa_private.pem \
-nocrypt > rsa_private_pkcs8
rsa_cert.pem
file in the editor, or use this command:cat rsa_cert.pem
rsa_cert.pem
to the clipboard, include -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.Go back to the Console and click on the name of the first device.
On the Edit Device page, click Add public key.
Enter the following values:
Field | Value |
Input method | Enter manually |
Public key format | RS256_X509 |
Public key value | Paste contents of rsa_cert.pem |
Public key expiration date | Default value |
Your screen should look like this:
Click Add.
Repeat these steps for the other two MQTT devices.
In Cloud Shell, set a PROJECT_ID variable, replacing <your-project-id> with the Project ID for this lab:
PROJECT_ID=<your-project-id>
Congratulations, you have set up Cloud Pub/Sub, created your device registry, and added multiple MQTT devices to the registry!
In Cloud Shell, clone the repo containing the mqtt example sample:
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
Go into the manager
folder:
cd java-docs-samples/iot/api-client/codelab/manager
Next, install the libraries and build the sample with Maven:
mvn clean compile assembly:single
If the build was successful, check if the libraries and sample installed properly by running the MqttExample script without passing any parameters:
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo"
If the dependencies installed successfully, the program will print the following messages. For example:
Missing required options: project_id, registry_id, device_id, private_key_file, algorithm
Now that you have the program libraries installed, it's time to connect a single device to Cloud IoT Core.
cp ~/rsa_private_pkcs8 .
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-1 \ -private_key_file=rsa_private_pkcs8 \ -algorithm=RS256"
If you see the following output, the device is successfully subscribed to config topic.
If you see any WARNING or ERROR messages, please check the following:
Now, you will edit the MqttCommandsDemo.java
file to add code which will get the device subscribed to the command topic.
java-docs-samples
folder, then go to the iot/api-client/codelab/manager/src/main/java/com/example/cloud/iot/examples
directory.MqttCommandsDemo.java
file. String commandTopic = String.format("/devices/%s/commands/#", deviceId); System.out.println(String.format("Listening on %s", commandTopic)); client.subscribe(commandTopic, 1);
mvn clean compile assembly:single
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-1 \ -private_key_file=rsa_private_pkcs8 \ -algorithm=RS256"
Payload: <your-sent-command>
Make sure you send the command while the sample is running.
Now it's time to do more than printing out the command. Next, respond to a command by changing the color of the terminal.
MqttCommandsDemo.java
file, search for "begin command respond" /* Responding to a command message. 1) checking if it is a valid color. 2) If GUI thread already running, restart. */ if (isValidColor(data, mainBgColor)) { mainBgColor = getColor((String) data.get("color")); if (mGUIthread != null && mGUIthread.isAlive()) mGUIthread.stop(); mGUIthread = new Thread( () -> { try { startGui(mainScreen, mainBgColor); } catch (IOException e) { e.printStackTrace(); } }); mGUIthread.start(); }
mvn clean compile assembly:single
The code you just added will change the background color of the terminal as soon as a command with JSON string is received.
Choose to use either the Console or Cloud Shell to complete this next part.
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-1 \ -private_key_file=rsa_private_pkcs8 \ -algorithm=RS256"
{color: BLUE}
gcloud
command line to change the color of your terminalmvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-1 \ -private_key_file=rsa_private_pkcs8 \ -algorithm=RS256"
gcloud iot devices commands send --command-data={color:blue} --device=mqtt-device-1 --region=us-central1 --registry=my-registry
When you have multiple MQTT devices listening for commands, sending 1 command to all of them can make a simultaneous change. For example, you can control the colors of 100 lights in a large office using IoT Core commands, or orchestrate lights, heating, and cooling systems in a factory.
For this lab, you will change the color of all MQTT devices terminals at the same time.
First, disable tmux integration so you can use Cloud Shell in multiple tabs.
Next you will need 3 new browser tabs where you will run your current Cloud Shell link. To do this:
Align the browser tabs so you can see all three at the same time. Each browser tab will be one of the devices you've created. Be sure to run all of the connection commands in each tab.
PROJECT_ID="${DEVSHELL_PROJECT_ID:-Cloud Shell}"
manager
folder:cd java-docs-samples/iot/api-client/codelab/manager
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-1 \ -private_key_file=rsa_private_pkcs8 \
-algorithm=RS256"
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-2 \ -private_key_file=rsa_private_pkcs8 \ -algorithm=RS256"
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-3 \ -private_key_file=rsa_private_pkcs8 \ -algorithm=RS256"
If the sample is built successfully, the following section will show up with the output of the MQTT device that is being subscribed to commands and config topics, and starting to publish events messages:
Starting mqtt demo: Listening on /devices/device-ec/commands/# Listening on /devices/device-ec/config
Now you have configured all MQTT devices to connect to the command topic, next you will send commands to all devices at once.
Make sure you place three browser windows with cloud shell vertically or horizontally parallel to see color changes at the same time.
manager
folder of the sample:cd java-docs-samples/iot/api-client/codelab/manager/
Run the following commands in the new Cloud Shell terminal to simultaneously change the background of all the terminals:
color=<your-chosen-color>
gcloud
command-line script file for each MQTT device for sending a command:for deviceId in 1 2 3 do echo "gcloud iot devices commands send --command-data={color:$color} --device=mqtt-device-$deviceId --region=us-central1 --registry=my-registry" > device-send-command-script-$deviceId.sh # grants each file execution permission chmod u+x device-send-command-script-$deviceId.sh done
gcloud
scripts async to trigger all at once:#call 3 scripts async ./device-send-command-script-1.sh & ./device-send-command-script-2.sh & ./device-send-command-script-3.sh &
4. Switch back to the tab in which the sample is running
When you end the lab all your resources and your project will be cleaned up and discarded for you. You should know how to clean up resources yourself to save on cost and to be a good cloud citizen.
Run the following:
#Removing used script files for deviceId in 1 2 3 do rm ./device-send-command-script-$deviceId.sh done
The default wait time of the sample is 120 seconds, and the number of messages to be published is 100. You can change this by adding the parameters num_messages and wait_time.
For example:
mvn exec:java \ -Dexec.mainClass="com.example.cloud.iot.examples.MqttCommandsDemo" \ -Dexec.args="-project_id=$PROJECT_ID \ -registry_id=my-registry \ -cloud_region=us-central1 \ -device_id=mqtt-device-1 \ -private_key_file=rsa_private_pkcs8 \ -wait_time=15 \ <desired time in seconds> -num_messages=10 \ <num of event msgs> -algorithm=RS256"
In this lab, you have learned: