From 7bf211a5329301d5736b9268c8905e894501cc7e Mon Sep 17 00:00:00 2001 From: Steven Kuhn Date: Mon, 21 Aug 2023 10:16:36 -0500 Subject: [PATCH] Add ability to publish commands by device ID via Meadow.Cloud --- .../CloudServices/CommandService.cs | 32 +++++++++++++++++++ .../Commands/Cloud/Command/PublishCommand.cs | 29 +++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/Meadow.CLI.Core/CloudServices/CommandService.cs b/Meadow.CLI.Core/CloudServices/CommandService.cs index e6ae5f4d..dc306b95 100644 --- a/Meadow.CLI.Core/CloudServices/CommandService.cs +++ b/Meadow.CLI.Core/CloudServices/CommandService.cs @@ -50,5 +50,37 @@ public async Task PublishCommandForCollection( throw new MeadowCloudException(message); } } + + public async Task PublishCommandForDevices( + string[] deviceIds, + string commandName, + JsonDocument? arguments = null, + int qualityOfService = 0, + string? host = null, + CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(host)) + { + host = _config[Constants.MEADOW_CLOUD_HOST_CONFIG_NAME]; + } + + var httpClient = await GetAuthenticatedHttpClient(cancellationToken); + + var payload = new + { + deviceIds, + commandName, + args = arguments, + qos = qualityOfService + }; + var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"); + var response = await httpClient.PostAsync($"{host}/api/devices/commands", content, cancellationToken); + + if (!response.IsSuccessStatusCode) + { + var message = await response.Content.ReadAsStringAsync(); + throw new MeadowCloudException(message); + } + } } } diff --git a/Meadow.CLI/Commands/Cloud/Command/PublishCommand.cs b/Meadow.CLI/Commands/Cloud/Command/PublishCommand.cs index 8b7118e6..29ad93fd 100644 --- a/Meadow.CLI/Commands/Cloud/Command/PublishCommand.cs +++ b/Meadow.CLI/Commands/Cloud/Command/PublishCommand.cs @@ -7,6 +7,7 @@ using Meadow.CLI.Core.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using System.Linq; using System.Text.Json; using System.Threading.Tasks; @@ -38,9 +39,12 @@ public PublishCommand(ILoggerFactory loggerFactory, CommandService commandServic [CommandParameter(0, Description = "The name of the command", IsRequired = true, Name = "COMMAND_NAME")] public string CommandName { get; set; } - [CommandOption("collectionId", 'c', Description = "The target collection for publishing the command", IsRequired = true)] + [CommandOption("collectionId", 'c', Description = "The target collection for publishing the command")] public string CollectionId { get; set; } + [CommandOption("deviceIds", 'd', Description = "The target devices for publishing the command")] + public string[] DeviceIds { get; set; } + [CommandOption("args", 'a', Description = "The arguments for the command as a JSON string", Converter = typeof(JsonDocumentBindingConverter))] public JsonDocument Arguments { get; set; } @@ -52,6 +56,16 @@ public PublishCommand(ILoggerFactory loggerFactory, CommandService commandServic public async ValueTask ExecuteAsync(IConsole console) { + if (string.IsNullOrWhiteSpace(CollectionId) && (DeviceIds == null || DeviceIds.Length == 0)) + { + throw new CommandException("Either a collection ID (-c|--collectionId) or a list of device IDs (-d|--deviceIds) must be specified.", showHelp: true); + } + + if (!string.IsNullOrWhiteSpace(CollectionId) && (DeviceIds != null && DeviceIds.Length > 0)) + { + throw new CommandException("Cannot specify both a collection ID (-c|--collectionId) and list of device IDs (-d|--deviceIds). Only one is allowed.", showHelp: true); + } + var cancellationToken = console.RegisterCancellationHandler(); await Task.Yield(); @@ -65,7 +79,18 @@ public async ValueTask ExecuteAsync(IConsole console) try { _logger.LogInformation($"Publishing '{CommandName}' command to Meadow.Cloud. Please wait..."); - await _commandService.PublishCommandForCollection(CollectionId, CommandName, Arguments, (int)QualityOfService, Host, cancellationToken); + if (!string.IsNullOrWhiteSpace(CollectionId)) + { + await _commandService.PublishCommandForCollection(CollectionId, CommandName, Arguments, (int)QualityOfService, Host, cancellationToken); + } + else if (DeviceIds.Any()) + { + await _commandService.PublishCommandForDevices(DeviceIds, CommandName, Arguments, (int)QualityOfService, Host, cancellationToken); + } + else + { + throw new CommandException("Cannot specify both a collection ID (-c|--collectionId) and list of device IDs (-d|--deviceIds). Only one is allowed."); + } _logger.LogInformation("Publish command successful."); } catch (MeadowCloudAuthException ex)