@@ -319,12 +319,12 @@ private static void printCommandHelp() {
319319 System .out .println (" application/json - subscribe to commands with JSON payload" );
320320 System .out .println (" application/cbor - subscribe to commands with CBOR payload" );
321321 System .out .println (" for any other value, subscribe to a generic topic" );
322- System .out .println (" update-command-execution <executionId> <status> [< reason-code>] [< reason-description>]" );
322+ System .out .println (" update-command-execution <executionId> <status> [reason-code=<value >] [reason-description=<value>] [result=<key>:<value>;<key>:<value >]" );
323323 System .out .println (" updates a command execution with a new status" );
324324 System .out .println (" <status> can be one of the following:" );
325325 System .out .println (" IN_PROGRESS, SUCCEEDED, REJECTED, FAILED, TIMED_OUT" );
326- System .out .println (" < reason-code> and < reason-description> may be optionally provided for" );
327- System .out .println (" the REJECTED, FAILED, or TIMED_OUT statuses \n " );
326+ System .out .println (" reason-code and reason-description may be optionally provided for any status " );
327+ System .out .println (" result is a semicolon-separated list of key:value pairs; if a value is true/false it is treated as boolean, otherwise as string \n " );
328328 System .out .println (" Miscellaneous commands:" );
329329 System .out .println (" list-streams list all open streaming operations" );
330330 System .out .println (" close-stream <streamID>" );
@@ -426,39 +426,86 @@ private static void handleGetCommandExecution(ApplicationContext context, String
426426 GetCommandExecutionRequest getCommandExecutionRequest = GetCommandExecutionRequest .builder ()
427427 .executionId (commandExecutionId )
428428 .targetArn (commandExecutionContext .deviceArn )
429+ .includeResult (true )
429430 .build ();
430431 GetCommandExecutionResponse getCommandExecutionResponse = context .controlPlaneClient .getCommandExecution (getCommandExecutionRequest );
431432 System .out .printf ("Status of command execution '%s' is %s\n " , commandExecutionId , getCommandExecutionResponse .status ());
432433 if (getCommandExecutionResponse .statusReason () != null ) {
433434 System .out .printf (" Reason code: %s\n " , getCommandExecutionResponse .statusReason ().reasonCode ());
434435 System .out .printf (" Reason description: %s\n " , getCommandExecutionResponse .statusReason ().reasonDescription ());
435436 }
437+ if (getCommandExecutionResponse .hasResult ()) {
438+ System .out .println (" Result:" );
439+ getCommandExecutionResponse .result ().forEach ((key , value ) -> {
440+ if (value .b () != null ) {
441+ System .out .printf (" %s: %s (boolean)\n " , key , value .b ());
442+ } else if (value .s () != null ) {
443+ System .out .printf (" %s: %s (string)\n " , key , value .s ());
444+ }
445+ });
446+ }
436447 } catch (Exception ex ) {
437448 handleOperationException ("get-command-execution" , ex , context );
438449 }
439450 }
440451
452+ private static Map <String , String > parseKeyValueArgs (String input ) {
453+ Pattern pattern = Pattern .compile ("(\\ S+?)=([^\\ s\" ]*(?:\" [^\" ]*\" [^\\ s\" ]*)*)" );
454+ Matcher matcher = pattern .matcher (input );
455+
456+ Map <String , String > result = new HashMap <>();
457+
458+ while (matcher .find ()) {
459+ String key = matcher .group (1 );
460+ String value = matcher .group (2 );
461+ result .put (key , value );
462+ }
463+
464+ return result ;
465+ }
466+
467+ private static HashMap <String , software .amazon .awssdk .iot .iotcommands .model .CommandExecutionResult > parseResult (String resultStr ) {
468+ HashMap <String , software .amazon .awssdk .iot .iotcommands .model .CommandExecutionResult > result = new HashMap <>();
469+
470+ Pattern pattern = Pattern .compile ("([^;:]*):([^;\" ]*(?:\" [^\" ]*\" [^;\" ]*)*)" );
471+ Matcher matcher = pattern .matcher (resultStr );
472+
473+ while (matcher .find ()) {
474+ String key = matcher .group (1 );
475+ String value = matcher .group (2 ).replaceAll ("^\" |\" $" , "" );
476+
477+ software .amazon .awssdk .iot .iotcommands .model .CommandExecutionResult entry =
478+ new software .amazon .awssdk .iot .iotcommands .model .CommandExecutionResult ();
479+
480+ /* NOTE: CommandExecutionResult also supports binary data via the `bin` member, which is not demonstrated in this
481+ * sample. */
482+ if (value .equalsIgnoreCase ("true" ) || value .equalsIgnoreCase ("false" )) {
483+ entry .b = Boolean .parseBoolean (value );
484+ } else {
485+ entry .s = value ;
486+ }
487+
488+ result .put (key , entry );
489+ }
490+
491+ return result ;
492+ }
493+
441494 private static void handleUpdateCommandExecution (ApplicationContext context , String arguments ) {
442- String [] argumentSplit = arguments .trim ().split (" " , 4 );
443- if (argumentSplit .length < 2 ) {
495+ String [] parts = arguments .trim ().split (" " , 3 );
496+ if (parts .length < 2 ) {
444497 printCommandHelp ();
445498 return ;
446499 }
447500
448- String commandExecutionId = argumentSplit [0 ];
501+ String commandExecutionId = parts [0 ];
449502 if (!context .activeCommandExecutions .containsKey (commandExecutionId )) {
450503 System .out .printf ("Failed to update command execution status: unknown command execution ID '%s'\n " , commandExecutionId );
451504 return ;
452505 }
453506
454- String statusStr = argumentSplit [1 ];
455-
456- String reasonCode = null ;
457- String reasonDescription = null ;
458- if (argumentSplit .length > 3 ) {
459- reasonCode = argumentSplit [2 ];
460- reasonDescription = argumentSplit [3 ];
461- }
507+ String statusStr = parts [1 ];
508+ Map <String , String > kvArgs = parseKeyValueArgs (parts .length > 2 ? parts [2 ] : "" );
462509
463510 try {
464511 CommandExecutionContext commandExecutionContext = context .activeCommandExecutions .get (commandExecutionId );
@@ -467,10 +514,18 @@ private static void handleUpdateCommandExecution(ApplicationContext context, Str
467514 request .deviceType = commandExecutionContext .deviceType ;
468515 request .deviceId = commandExecutionContext .deviceId ;
469516 request .status = CommandExecutionStatus .valueOf (statusStr );
470- if (reasonCode != null && reasonDescription != null ) {
517+
518+ String reasonCode = kvArgs .get ("reason-code" );
519+ String reasonDescription = kvArgs .get ("reason-description" );
520+ if (reasonCode != null || reasonDescription != null ) {
471521 request .statusReason = new StatusReason ();
472522 request .statusReason .reasonCode = reasonCode ;
473- request .statusReason .reasonDescription = reasonDescription ;
523+ request .statusReason .reasonDescription = reasonDescription .replaceAll ("^\" |\" $" , "" );
524+ }
525+
526+ String resultStr = kvArgs .get ("result" );
527+ if (resultStr != null ) {
528+ request .result = parseResult (resultStr );
474529 }
475530
476531 UpdateCommandExecutionResponse response = context .commandsClient .updateCommandExecution (request ).get ();
0 commit comments