Skip to content

Merge cmd features #1275

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

Merged
merged 5 commits into from
Dec 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions iot/api-client/manager/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-cloudiot</artifactId>
<version>v1-rev20170922-1.22.0</version>
<version>v1-rev49-1.25.0</version>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
Expand All @@ -81,7 +81,7 @@
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.22.0</version>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import com.google.api.services.cloudiot.v1.model.ListDeviceStatesResponse;
import com.google.api.services.cloudiot.v1.model.ModifyCloudToDeviceConfigRequest;
import com.google.api.services.cloudiot.v1.model.PublicKeyCredential;
import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceRequest;
import com.google.api.services.cloudiot.v1.model.SendCommandToDeviceResponse;
import com.google.api.services.cloudiot.v1.model.SetIamPolicyRequest;
import com.google.cloud.Role;
import com.google.cloud.pubsub.v1.TopicAdminClient;
Expand Down Expand Up @@ -721,6 +723,42 @@ public static void setIamPermissions(
}
// [END iot_set_iam_policy]

/** Send a command to a device. **/
// [START send_command]
public static void sendCommand(
String deviceId, String projectId, String cloudRegion, String registryName, String data)
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);

SendCommandToDeviceRequest req = new SendCommandToDeviceRequest();

// 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);
System.out.printf("Sending command to %s\n", devicePath);

SendCommandToDeviceResponse res =
service
.projects()
.locations()
.registries()
.devices()
.sendCommandToDevice(devicePath, req).execute();

System.out.println("Command response: " + res.toString());
}
// [END send_command]

/** Entry poit for CLI. */
public static void main(String[] args) throws Exception {
DeviceRegistryExampleOptions options = DeviceRegistryExampleOptions.fromFlags(args);
Expand Down Expand Up @@ -822,6 +860,11 @@ public static void main(String[] args) throws Exception {
options.member, options.role);
}
break;
case "send-command":
System.out.println("Sending command to device:");
sendCommand(options.deviceId, options.projectId, options.cloudRegion, options.registryName,
options.commandData);
break;
default:
String header = "Cloud IoT Core Commandline Example (Device / Registry management): \n\n";
String footer = "\nhttps://cloud.google.com/iot-core";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class DeviceRegistryExampleOptions {
String rsaCertificateFile = "rsa_cert.pem";
String cloudRegion = "us-central1";
String command = "help";
String commandData = "Specify with --data";
String configuration = "Specify with -configuration";
String deviceId; // Default to UUID?
String pubsubTopic;
Expand All @@ -43,14 +44,6 @@ public class DeviceRegistryExampleOptions {
/** Construct an DeviceRegistryExampleOptions class from command line flags. */
public static DeviceRegistryExampleOptions fromFlags(String[] args) {
// Required arguments
options.addOption(
Option.builder()
.type(String.class)
.longOpt("pubsub_topic")
.hasArg()
.desc("Pub/Sub topic to create registry in.")
.required()
.build());
options.addOption(
Option.builder()
.type(String.class)
Expand All @@ -74,11 +67,19 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) {
+ "\n\tpatch-device-es"
+ "\n\tpatch-device-rsa"
+ "\n\tset-config"
+ "\n\tset-iam-permissions")
+ "\n\tset-iam-permissions"
+ "\n\tsend-command")
.required()
.build());

// Optional arguments.
options.addOption(
Option.builder()
.type(String.class)
.longOpt("pubsub_topic")
.hasArg()
.desc("Pub/Sub topic to create registry in.")
.build());
options.addOption(
Option.builder()
.type(String.class)
Expand Down Expand Up @@ -121,6 +122,13 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) {
.hasArg()
.desc("Name for your Device.")
.build());
options.addOption(
Option.builder()
.type(String.class)
.longOpt("data")
.hasArg()
.desc("The command data (string or JSON) to send to the specified device.")
.build());
options.addOption(
Option.builder()
.type(String.class)
Expand Down Expand Up @@ -162,6 +170,16 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) {
throw new ParseException("Invalid command, showing help.");
}

if (commandLine.hasOption("cloud_region")) {
res.cloudRegion = commandLine.getOptionValue("cloud_region");
}
if (commandLine.hasOption("data")) {
res.commandData = commandLine.getOptionValue("data");
}
if (commandLine.hasOption("device_id")) {
res.deviceId = commandLine.getOptionValue("device_id");
}

if (commandLine.hasOption("project_id")) {
res.projectId = commandLine.getOptionValue("project_id");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ public void deliveryComplete(IMqttDeliveryToken token) {
String configTopic = String.format("/devices/%s/config", deviceId);
client.subscribe(configTopic, 1);

String commandTopic = String.format("/devices/%s/commands/#", deviceId);
client.subscribe(commandTopic, 1);

client.setCallback(mCallback);
}
// [END iot_mqtt_configcallback]
Expand Down Expand Up @@ -275,12 +278,21 @@ public static void main(String[] args) throws Exception {
}
}

// Wait for commands to arrive for about two minutes.
for (int i = 1; i <= options.waitTime; ++i) {
System.out.print(".");
Thread.sleep(1000);
}
System.out.println("");


// Disconnect the client if still connected, and finish the run.
if (client.isConnected()) {
client.disconnect();
}

System.out.println("Finished loop successfully. Goodbye!");
client.close();
// [END iot_mqtt_publish]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class MqttExampleOptions {
String mqttBridgeHostname = "mqtt.googleapis.com";
short mqttBridgePort = 8883;
String messageType = "event";
int waitTime = 120;

/** Construct an MqttExampleOptions class from command line flags. */
public static MqttExampleOptions fromFlags(String[] args) {
Expand Down Expand Up @@ -125,6 +126,13 @@ public static MqttExampleOptions fromFlags(String[] args) {
.hasArg()
.desc("Indicates whether the message is a telemetry event or a device state message")
.build());
options.addOption(
Option.builder()
.type(Number.class)
.longOpt("wait_time")
.hasArg()
.desc("Wait time (in seconds) for commands.")
.build());

CommandLineParser parser = new DefaultParser();
CommandLine commandLine;
Expand All @@ -137,6 +145,9 @@ public static MqttExampleOptions fromFlags(String[] args) {
res.deviceId = commandLine.getOptionValue("device_id");
res.privateKeyFile = commandLine.getOptionValue("private_key_file");
res.algorithm = commandLine.getOptionValue("algorithm");
if (commandLine.hasOption("wait_time")) {
res.waitTime = ((Number) commandLine.getParsedOptionValue("wait_time")).intValue();
}
if (commandLine.hasOption("cloud_region")) {
res.cloudRegion = commandLine.getOptionValue("cloud_region");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,61 @@ public void testMqttDeviceConfig() throws Exception {
}
}

@Test
public void testMqttDeviceCommand() throws Exception {
final String deviceName = "rsa-device-mqtt-commands";
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);

// Device bootstrapped, time to connect and run.
String[] testArgs = {
"-project_id=" + PROJECT_ID,
"-registry_id=" + REGISTRY_ID,
"-cloud_region=" + CLOUD_REGION,
"-device_id=" + deviceName,
"-private_key_file=" + PKCS_PATH,
"-wait_time=" + 10,
"-algorithm=RS256"
};

Thread deviceThread = new Thread() {
public void run() {
try {
com.example.cloud.iot.examples.MqttExample.main(testArgs);
} catch (Exception e) {
// TODO: Fail
System.out.println("Failure on Exception");
}
}
};
deviceThread.start();

Thread.sleep(500); // Give the device a chance to connect
com.example.cloud.iot.examples.DeviceRegistryExample.sendCommand(
deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID, "me want cookie!");

deviceThread.join();
// End device test.

// Assertions
String got = bout.toString();
System.out.println(got);
Assert.assertTrue(got.contains("Finished loop successfully."));
Assert.assertTrue(got.contains("me want cookie"));
Assert.assertFalse(got.contains("Failure on Exception"));

// 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";
Expand Down