From 7c52f6bbb64d0b4eeafc350a2365fbfecabefb19 Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Wed, 21 Dec 2022 16:48:41 +0100 Subject: [PATCH 01/16] Added GetActionSequenceAsync for dashboard query --- .../Controllers/DashboardController.cs | 25 +++++++++++++++- .../Responses/actionSequenceREsponse.cs | 29 +++++++++++++++++++ .../Services/Abstract/IDashboardService.cs | 2 ++ .../Services/DashboardService.cs | 28 +++++++++++++++++- 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 src/RedisInterface/Responses/actionSequenceREsponse.cs diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index 8db0746e..b3e07c69 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -1,4 +1,5 @@ using System.Net; +using Amazon.SecretsManager.Model; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Middleware.Common; @@ -48,7 +49,7 @@ public async Task GetTaskRobotResponseAsync([FromQuery] Paginatio [HttpGet("locations")] [ProducesResponseType(typeof(PagedResponse>), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] - public async Task GetCloudRobotStatusesAsync([FromQuery] PaginationFilter filter) + public async Task GetLocationStatusesAsync([FromQuery] PaginationFilter filter) { try { @@ -65,5 +66,27 @@ public async Task GetCloudRobotStatusesAsync([FromQuery] Paginati return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); } } + + /// + /// Return to the cascading grid the action sequence for all tasks + /// + /// + [HttpGet("actionSequence")] + [ProducesResponseType(typeof(actionSequenceResponse), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] + public async Task GetActionSequenceAsync() + { + try + { + List actionsAndTask = await _dashboardService.GetActionSequenceAsync(); + return Ok(actionsAndTask); + } + catch (Exception ex) + { + int statusCode = (int)HttpStatusCode.InternalServerError; + _logger.LogError(ex, "An error occurred:"); + return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); + } + } } } diff --git a/src/RedisInterface/Responses/actionSequenceREsponse.cs b/src/RedisInterface/Responses/actionSequenceREsponse.cs new file mode 100644 index 00000000..1d54dffe --- /dev/null +++ b/src/RedisInterface/Responses/actionSequenceREsponse.cs @@ -0,0 +1,29 @@ +using System.Text.Json.Serialization; + +namespace Middleware.RedisInterface.Responses +{ + public record actionSequenceResponse + { + [JsonPropertyName("TaskName")] + public string TaskName { get; set; } + + [JsonPropertyName("TaskId")] + public Guid TaskId { get; set; } + + [JsonPropertyName("Actions")] + public List Actions { get; set; } + + public actionSequenceResponse() + { + + } + + public actionSequenceResponse(string taskName, Guid taskId, List actions) + { + TaskName = taskName; + TaskId = taskId; + Actions = actions; + } + } + +} diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index 2795f0b3..8e7b4545 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -22,5 +22,7 @@ public interface IDashboardService /// First: A list of
/// Second: Total number of records Task, int>> GetLocationsStatusListAsync(PaginationFilter filter); + + Task> GetActionSequenceAsync(); } } diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index c5046b57..cbd83b9a 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -1,9 +1,11 @@ -using Middleware.Common; +using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Middleware.Common; using Middleware.Common.Enums; using Middleware.Common.Helpers; using Middleware.Common.Repositories; using Middleware.Common.Repositories.Abstract; using Middleware.RedisInterface.Responses; +using System.Threading.Tasks; namespace Middleware.RedisInterface.Services { @@ -110,5 +112,29 @@ public async Task, int>> GetRobotStatusListAsync(P } return new (filter.FilterResult(responses), responses.Count); } + + /// + /// Get all action sequences with only actions list names + /// + /// + public async Task> GetActionSequenceAsync() + { + var tasks = await _taskRepository.GetAllAsync(); + var responses = new List(); + + foreach (var tempTask in tasks) + { + List tempNamesActions = new List(); + List actions = tempTask.ActionSequence; + foreach (var action in actions) tempNamesActions.Add(action.Name); + var response = new actionSequenceResponse( + tempTask.Name, + tempTask.Id, + tempNamesActions + ); + responses.Add(response); + } + return responses; + } } } From 55a2cff80f38354b10ba0872896935e2becd09e9 Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Tue, 27 Dec 2022 13:16:35 +0100 Subject: [PATCH 02/16] Added GetOnboardingItemTypesAsync --- src/Common/Models/RobotModel.cs | 1 + .../Controllers/DashboardController.cs | 24 ++++++++++++++++++- .../Services/Abstract/IDashboardService.cs | 2 ++ .../Services/DashboardService.cs | 24 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Common/Models/RobotModel.cs b/src/Common/Models/RobotModel.cs index c9753c52..7cd2cd99 100644 --- a/src/Common/Models/RobotModel.cs +++ b/src/Common/Models/RobotModel.cs @@ -191,4 +191,5 @@ public RosTopicModel GetTopicModelFromRobot(string topicName) { return GetAllRobotTopics().Where(t => t.Name == topicName).FirstOrDefault(); } + } diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index b3e07c69..83670bbd 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -68,7 +68,7 @@ public async Task GetLocationStatusesAsync([FromQuery] Pagination } /// - /// Return to the cascading grid the action sequence for all tasks + /// Return to the cascading grid the action sequence names for all tasks /// /// [HttpGet("actionSequence")] @@ -88,5 +88,27 @@ public async Task GetActionSequenceAsync() return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); } } + + /// + /// Return to the onboarding types names + /// + /// + [HttpGet("onboardingTypes")] + [ProducesResponseType(typeof(actionSequenceResponse), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] + public async Task GetOnboardingItemTypesAsync() + { + try + { + List onboardingTypes = await _dashboardService.GetOnboardingItemNamesAsync(); + return Ok(onboardingTypes); + } + catch (Exception ex) + { + int statusCode = (int)HttpStatusCode.InternalServerError; + _logger.LogError(ex, "An error occurred:"); + return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); + } + } } } diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index 8e7b4545..d7667e83 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -24,5 +24,7 @@ public interface IDashboardService Task, int>> GetLocationsStatusListAsync(PaginationFilter filter); Task> GetActionSequenceAsync(); + + Task> GetOnboardingItemNamesAsync(); } } diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index cbd83b9a..fa4d69f5 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -2,6 +2,7 @@ using Middleware.Common; using Middleware.Common.Enums; using Middleware.Common.Helpers; +using Middleware.Common.Models; using Middleware.Common.Repositories; using Middleware.Common.Repositories.Abstract; using Middleware.RedisInterface.Responses; @@ -136,5 +137,28 @@ public async Task> GetActionSequenceAsync() } return responses; } + + /// + /// Gets a list of onboarding item types. + /// + /// + public async Task> GetOnboardingItemNamesAsync() + { + List tempOnboardItemTypes = new List(); + var cloud = new CloudModel(); + var edge = new EdgeModel(); + var robot = new RobotModel(); + var instance = new InstanceModel(); + var action = new Middleware.Common.Models.ActionModel(); + var task = new Middleware.Common.Models.TaskModel(); + tempOnboardItemTypes.Add(cloud.GetType().ToString()); + tempOnboardItemTypes.Add(edge.GetType().ToString()); + tempOnboardItemTypes.Add(robot.GetType().ToString()); + tempOnboardItemTypes.Add(instance.GetType().ToString()); + tempOnboardItemTypes.Add(action.GetType().ToString()); + tempOnboardItemTypes.Add(task.GetType().ToString()); + + return tempOnboardItemTypes; + } } } From 40c89b3bcfe0dda722de964524e755c4ac748f9c Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Tue, 27 Dec 2022 14:14:11 +0100 Subject: [PATCH 03/16] Added missing dashboard endpoints --- src/Common/Models/InstanceModel.cs | 3 + .../Controllers/DashboardController.cs | 66 ++++++++++++++++++- .../Responses/NetAppsDetailsResponse.cs | 35 ++++++++++ src/RedisInterface/Responses/RobotResponse.cs | 44 +++++++++++++ .../Services/Abstract/IDashboardService.cs | 4 ++ .../Services/DashboardService.cs | 58 +++++++++++++++- 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 src/RedisInterface/Responses/NetAppsDetailsResponse.cs create mode 100644 src/RedisInterface/Responses/RobotResponse.cs diff --git a/src/Common/Models/InstanceModel.cs b/src/Common/Models/InstanceModel.cs index 6596a5f6..2f0dbf6d 100644 --- a/src/Common/Models/InstanceModel.cs +++ b/src/Common/Models/InstanceModel.cs @@ -62,6 +62,9 @@ public class InstanceModel : BaseModel [JsonPropertyName("MinimumNumCores")] public int MinimumNumCores { get; set; } // Compulsory field + [JsonPropertyName("OnboardedTime")] + public DateTime OnboardedTime { get; set; } // Compulsory field + /// /// Onboarding validation of the instance data object. /// diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index 83670bbd..c4bba3b8 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -24,6 +24,11 @@ public DashboardController(IDashboardService dashboardService, ILogger + /// Basic control grid for robot-tasks + /// + /// + /// [HttpGet("tasks")] [ProducesResponseType(typeof(PagedResponse>), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] @@ -46,6 +51,11 @@ public async Task GetTaskRobotResponseAsync([FromQuery] Paginatio } + /// + /// Basic control grid for edge and cloud + /// + /// + /// [HttpGet("locations")] [ProducesResponseType(typeof(PagedResponse>), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] @@ -90,7 +100,7 @@ public async Task GetActionSequenceAsync() } /// - /// Return to the onboarding types names + /// Return the onboarding types names => Drop down menu. /// /// [HttpGet("onboardingTypes")] @@ -110,5 +120,59 @@ public async Task GetOnboardingItemTypesAsync() return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); } } + + /// + /// Basic control grid for netApps + /// + /// + /// + [HttpGet("netApps")] + [ProducesResponseType(typeof(PagedResponse>), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] + public async Task GetNetAppsDataAsync([FromQuery] PaginationFilter filter) + { + try + { + var route = Request.Path.Value; + (var data, int count) = await _dashboardService.GetNetAppsDataListAsync(filter); + + var pagedResponse = data.ToPagedResponse(filter, count, _uriService, route); + return Ok(pagedResponse); + } + catch (Exception ex) + { + int statusCode = (int)HttpStatusCode.InternalServerError; + _logger.LogError(ex, "An error occurred:"); + return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); + } + } + + /// + /// Basic control grid for robots along + /// + /// + /// + [HttpGet("robots")] + [ProducesResponseType(typeof(PagedResponse>), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] + public async Task GetRobotsAsync([FromQuery] PaginationFilter filter) + { + try + { + var route = Request.Path.Value; + (var data, int count) = await _dashboardService.GetRobotsDataAsync(filter); + + var pagedResponse = data.ToPagedResponse(filter, count, _uriService, route); + return Ok(pagedResponse); + } + catch (Exception ex) + { + int statusCode = (int)HttpStatusCode.InternalServerError; + _logger.LogError(ex, "An error occurred:"); + return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); + } + } + + } } diff --git a/src/RedisInterface/Responses/NetAppsDetailsResponse.cs b/src/RedisInterface/Responses/NetAppsDetailsResponse.cs new file mode 100644 index 00000000..540f23c2 --- /dev/null +++ b/src/RedisInterface/Responses/NetAppsDetailsResponse.cs @@ -0,0 +1,35 @@ +using System.Text.Json.Serialization; + +namespace Middleware.RedisInterface.Responses +{ + public record NetAppsDetailsResponse + { + [JsonPropertyName("NetAppName")] + public string NetAppName { get; set; } + + [JsonPropertyName("NetAppFamily")] + public string NetAppFamily { get; set; } + + [JsonPropertyName("ROSVersion")] + public int ROSVersion { get; set; } + + [JsonPropertyName("ROSDistro")] + public string ROSDistro { get; set; } + + [JsonPropertyName("OnboardedTime")] + public DateTime OnboardedTime { get; set; } + + public NetAppsDetailsResponse() + { + } + public NetAppsDetailsResponse(string netAppName, string netAppFamily, int rosVersion, string rosDistro , DateTime onboardedTime) + { + NetAppName = netAppName; + NetAppFamily = netAppFamily; + ROSVersion = rosVersion; + ROSDistro = rosDistro; + OnboardedTime = onboardedTime; + + } + } +} diff --git a/src/RedisInterface/Responses/RobotResponse.cs b/src/RedisInterface/Responses/RobotResponse.cs new file mode 100644 index 00000000..1bb0e410 --- /dev/null +++ b/src/RedisInterface/Responses/RobotResponse.cs @@ -0,0 +1,44 @@ +using System.Text.Json.Serialization; + +namespace Middleware.RedisInterface.Responses +{ + public record RobotResponse + { + [JsonPropertyName("RobotId")] + public Guid RobotId { get; set; } + + [JsonPropertyName("RobotName")] + public string RobotName { get; set; } + + [JsonPropertyName("Status")] + public string Status { get; set; } + + [JsonPropertyName("OnboardedTime")] + public DateTime OnboardedTime { get; set; } + + [JsonPropertyName("ROSVersion")] + public int ROSVersion { get; set; } + + [JsonPropertyName("ROSDistro")] + public string ROSDistro { get; set; } + + [JsonPropertyName("Company")] + public string Company { get; set; } + + public RobotResponse() + { + + } + public RobotResponse(Guid robotId, string robotName, string status, DateTime onboardedTime, int rosVersion,string rosDistro, string company) + { + RobotId = robotId; + RobotName = robotName; + Status = status; + OnboardedTime = onboardedTime; + ROSVersion = rosVersion; + ROSDistro = rosDistro; + Company = company; + } + + } +} diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index d7667e83..785f0483 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -26,5 +26,9 @@ public interface IDashboardService Task> GetActionSequenceAsync(); Task> GetOnboardingItemNamesAsync(); + + Task, int>> GetNetAppsDataListAsync(PaginationFilter filter); + + Task, int>> GetRobotsDataAsync(PaginationFilter filter); } } diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index fa4d69f5..da658dbc 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -6,6 +6,7 @@ using Middleware.Common.Repositories; using Middleware.Common.Repositories.Abstract; using Middleware.RedisInterface.Responses; +using System.Runtime.InteropServices; using System.Threading.Tasks; namespace Middleware.RedisInterface.Services @@ -35,6 +36,32 @@ public DashboardService(IRobotRepository robotRepository, _robotRepository = robotRepository; } + /// + /// Basic control grid backend for netApps. + /// + /// + /// + public async Task, int>> GetNetAppsDataListAsync(PaginationFilter filter) + { + var instances = await _instanceRepository.GetAllAsync(); + var instanceResponse = new List(); + foreach (var netApp in instances) + { + var netAppTemp = new NetAppsDetailsResponse(netApp.Name, + netApp.InstanceFamily, + netApp.RosVersion, + netApp.ROSDistro, + netApp.OnboardedTime); + instanceResponse.Add(netAppTemp); + } + return new(filter.FilterResult(instanceResponse), instanceResponse.Count); + } + + /// + /// Basic control grid backend for edge and clouds + /// + /// + /// public async Task, int>> GetLocationsStatusListAsync(PaginationFilter filter) { var locations = new List(); @@ -86,6 +113,11 @@ public async Task, int>> GetLocationsStatusLi return new (filter.FilterResult(locations), locations.Count); } + /// + /// Basic control grid backend for robot-tasks + /// + /// + /// public async Task, int>> GetRobotStatusListAsync(PaginationFilter filter) { var robots = await _robotRepository.GetAllAsync(); @@ -115,7 +147,7 @@ public async Task, int>> GetRobotStatusListAsync(P } /// - /// Get all action sequences with only actions list names + /// Get all action sequences with only actions list names /// /// public async Task> GetActionSequenceAsync() @@ -160,5 +192,29 @@ public async Task> GetOnboardingItemNamesAsync() return tempOnboardItemTypes; } + + /// + /// Gets a list of robots with some of their data. + /// + /// + public async Task, int>> GetRobotsDataAsync(PaginationFilter filter) + { + var robots = await _robotRepository.GetAllAsync(); + var robotsResponse = new List(); + foreach (var robot in robotsResponse) + { + var netAppTemp = new RobotResponse(robot.RobotId, + robot.RobotName, + robot.Status, + robot.OnboardedTime, + robot.ROSVersion, + robot.ROSDistro, + robot.Company); + robotsResponse.Add(netAppTemp); + } + return new(filter.FilterResult(robotsResponse), robotsResponse.Count); + } + + } } From aa12188f6ea75d1984bb6cbc2fb1efb13be8fc5d Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Wed, 4 Jan 2023 11:20:03 +0100 Subject: [PATCH 04/16] Fixes suggested in pull request #88 --- .../ExtensionMethods/StringExtensions.cs | 10 +++++++ .../Controllers/DashboardController.cs | 6 ++--- src/RedisInterface/Responses/RobotResponse.cs | 8 +++--- .../Responses/actionSequenceREsponse.cs | 6 ++--- .../Services/Abstract/IDashboardService.cs | 2 +- .../Services/DashboardService.cs | 27 ++++++------------- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/Common/ExtensionMethods/StringExtensions.cs b/src/Common/ExtensionMethods/StringExtensions.cs index db4934a2..9476c065 100644 --- a/src/Common/ExtensionMethods/StringExtensions.cs +++ b/src/Common/ExtensionMethods/StringExtensions.cs @@ -11,4 +11,14 @@ public static string SanitizeAsK8SYaml(this string str) { return str.Replace("\\n", "\n"); } + + public static string TrimSuffix(this string s, string suffix) + { + if (s.EndsWith(suffix)) + { + return s.Substring(0, s.Length - suffix.Length); + } + + return s; + } } \ No newline at end of file diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index c4bba3b8..467e1a0a 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -82,13 +82,13 @@ public async Task GetLocationStatusesAsync([FromQuery] Pagination /// /// [HttpGet("actionSequence")] - [ProducesResponseType(typeof(actionSequenceResponse), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ActionSequenceResponse), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] public async Task GetActionSequenceAsync() { try { - List actionsAndTask = await _dashboardService.GetActionSequenceAsync(); + List actionsAndTask = await _dashboardService.GetActionSequenceAsync(); return Ok(actionsAndTask); } catch (Exception ex) @@ -104,7 +104,7 @@ public async Task GetActionSequenceAsync() /// /// [HttpGet("onboardingTypes")] - [ProducesResponseType(typeof(actionSequenceResponse), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ActionSequenceResponse), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] public async Task GetOnboardingItemTypesAsync() { diff --git a/src/RedisInterface/Responses/RobotResponse.cs b/src/RedisInterface/Responses/RobotResponse.cs index 1bb0e410..2ff1d1ae 100644 --- a/src/RedisInterface/Responses/RobotResponse.cs +++ b/src/RedisInterface/Responses/RobotResponse.cs @@ -22,14 +22,14 @@ public record RobotResponse [JsonPropertyName("ROSDistro")] public string ROSDistro { get; set; } - [JsonPropertyName("Company")] - public string Company { get; set; } + [JsonPropertyName("Manufacturer")] + public string Manufacturer { get; set; } public RobotResponse() { } - public RobotResponse(Guid robotId, string robotName, string status, DateTime onboardedTime, int rosVersion,string rosDistro, string company) + public RobotResponse(Guid robotId, string robotName, string status, DateTime onboardedTime, int rosVersion,string rosDistro, string manufacturer) { RobotId = robotId; RobotName = robotName; @@ -37,7 +37,7 @@ public RobotResponse(Guid robotId, string robotName, string status, DateTime onb OnboardedTime = onboardedTime; ROSVersion = rosVersion; ROSDistro = rosDistro; - Company = company; + Manufacturer = manufacturer; } } diff --git a/src/RedisInterface/Responses/actionSequenceREsponse.cs b/src/RedisInterface/Responses/actionSequenceREsponse.cs index 1d54dffe..c43d1803 100644 --- a/src/RedisInterface/Responses/actionSequenceREsponse.cs +++ b/src/RedisInterface/Responses/actionSequenceREsponse.cs @@ -2,7 +2,7 @@ namespace Middleware.RedisInterface.Responses { - public record actionSequenceResponse + public record ActionSequenceResponse { [JsonPropertyName("TaskName")] public string TaskName { get; set; } @@ -13,12 +13,12 @@ public record actionSequenceResponse [JsonPropertyName("Actions")] public List Actions { get; set; } - public actionSequenceResponse() + public ActionSequenceResponse() { } - public actionSequenceResponse(string taskName, Guid taskId, List actions) + public ActionSequenceResponse(string taskName, Guid taskId, List actions) { TaskName = taskName; TaskId = taskId; diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index 785f0483..0ef2b906 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -23,7 +23,7 @@ public interface IDashboardService /// Second: Total number of records Task, int>> GetLocationsStatusListAsync(PaginationFilter filter); - Task> GetActionSequenceAsync(); + Task> GetActionSequenceAsync(); Task> GetOnboardingItemNamesAsync(); diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index da658dbc..def7d72d 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -8,6 +8,7 @@ using Middleware.RedisInterface.Responses; using System.Runtime.InteropServices; using System.Threading.Tasks; +using Middleware.Common.ExtensionMethods; namespace Middleware.RedisInterface.Services { @@ -150,17 +151,17 @@ public async Task, int>> GetRobotStatusListAsync(P /// Get all action sequences with only actions list names /// /// - public async Task> GetActionSequenceAsync() + public async Task> GetActionSequenceAsync() { var tasks = await _taskRepository.GetAllAsync(); - var responses = new List(); + var responses = new List(); foreach (var tempTask in tasks) { List tempNamesActions = new List(); List actions = tempTask.ActionSequence; foreach (var action in actions) tempNamesActions.Add(action.Name); - var response = new actionSequenceResponse( + var response = new ActionSequenceResponse( tempTask.Name, tempTask.Id, tempNamesActions @@ -176,21 +177,9 @@ public async Task> GetActionSequenceAsync() /// public async Task> GetOnboardingItemNamesAsync() { - List tempOnboardItemTypes = new List(); - var cloud = new CloudModel(); - var edge = new EdgeModel(); - var robot = new RobotModel(); - var instance = new InstanceModel(); - var action = new Middleware.Common.Models.ActionModel(); - var task = new Middleware.Common.Models.TaskModel(); - tempOnboardItemTypes.Add(cloud.GetType().ToString()); - tempOnboardItemTypes.Add(edge.GetType().ToString()); - tempOnboardItemTypes.Add(robot.GetType().ToString()); - tempOnboardItemTypes.Add(instance.GetType().ToString()); - tempOnboardItemTypes.Add(action.GetType().ToString()); - tempOnboardItemTypes.Add(task.GetType().ToString()); - - return tempOnboardItemTypes; + var types = new Type[] { typeof(CloudModel), typeof(EdgeModel), typeof(RobotModel), typeof(InstanceModel) }; + var typeNames = types.Select(t => t.Name.TrimSuffix("Model")).ToList(); + return typeNames; } /// @@ -209,7 +198,7 @@ public async Task, int>> GetRobotsDataAsync(Pagination robot.OnboardedTime, robot.ROSVersion, robot.ROSDistro, - robot.Company); + robot.Manufacturer); robotsResponse.Add(netAppTemp); } return new(filter.FilterResult(robotsResponse), robotsResponse.Count); From 9911932bf40323b2aebf0bae487d6b92baf88c0f Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Wed, 4 Jan 2023 13:10:36 +0100 Subject: [PATCH 05/16] GetOnboardingItemNames added missing names --- src/RedisInterface/Controllers/DashboardController.cs | 2 +- src/RedisInterface/Services/Abstract/IDashboardService.cs | 2 +- src/RedisInterface/Services/DashboardService.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index 467e1a0a..43730081 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -110,7 +110,7 @@ public async Task GetOnboardingItemTypesAsync() { try { - List onboardingTypes = await _dashboardService.GetOnboardingItemNamesAsync(); + List onboardingTypes = await _dashboardService.GetOnboardingItemNames(); return Ok(onboardingTypes); } catch (Exception ex) diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index 0ef2b906..2a83348f 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -25,7 +25,7 @@ public interface IDashboardService Task> GetActionSequenceAsync(); - Task> GetOnboardingItemNamesAsync(); + Task> GetOnboardingItemNames(); Task, int>> GetNetAppsDataListAsync(PaginationFilter filter); diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index def7d72d..56cfbefc 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -175,9 +175,9 @@ public async Task> GetActionSequenceAsync() /// Gets a list of onboarding item types. /// /// - public async Task> GetOnboardingItemNamesAsync() + public List GetOnboardingItemNames() { - var types = new Type[] { typeof(CloudModel), typeof(EdgeModel), typeof(RobotModel), typeof(InstanceModel) }; + var types = new Type[] { typeof(CloudModel), typeof(EdgeModel), typeof(RobotModel), typeof(InstanceModel), typeof(TaskModel), typeof(ActionModel) }; var typeNames = types.Select(t => t.Name.TrimSuffix("Model")).ToList(); return typeNames; } From 8c9b45ac88feeb1b14a704ae1abe98fd3a637397 Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Wed, 4 Jan 2023 13:57:04 +0100 Subject: [PATCH 06/16] fixes to the dashboard endpoint --- src/RedisInterface/Controllers/DashboardController.cs | 2 +- src/RedisInterface/Services/Abstract/IDashboardService.cs | 2 +- src/RedisInterface/Services/DashboardService.cs | 6 +----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index 43730081..1cd20815 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -110,7 +110,7 @@ public async Task GetOnboardingItemTypesAsync() { try { - List onboardingTypes = await _dashboardService.GetOnboardingItemNames(); + List onboardingTypes = _dashboardService.GetOnboardingItemNames(); return Ok(onboardingTypes); } catch (Exception ex) diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index 2a83348f..161d4b41 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -25,7 +25,7 @@ public interface IDashboardService Task> GetActionSequenceAsync(); - Task> GetOnboardingItemNames(); + List GetOnboardingItemNames(); Task, int>> GetNetAppsDataListAsync(PaginationFilter filter); diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index 56cfbefc..e852a0ee 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -1,13 +1,9 @@ -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Middleware.Common; +using Middleware.Common; using Middleware.Common.Enums; -using Middleware.Common.Helpers; using Middleware.Common.Models; using Middleware.Common.Repositories; using Middleware.Common.Repositories.Abstract; using Middleware.RedisInterface.Responses; -using System.Runtime.InteropServices; -using System.Threading.Tasks; using Middleware.Common.ExtensionMethods; namespace Middleware.RedisInterface.Services From 0d8c08ce5784e9527d0b1e77a8a9950f5581454b Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Mon, 9 Jan 2023 11:41:22 +0100 Subject: [PATCH 07/16] fixes to GetRobotsDataAsync in DashboardService --- src/Common/Models/RobotModel.cs | 3 +++ src/RedisInterface/Services/DashboardService.cs | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Common/Models/RobotModel.cs b/src/Common/Models/RobotModel.cs index 7cd2cd99..e7a53577 100644 --- a/src/Common/Models/RobotModel.cs +++ b/src/Common/Models/RobotModel.cs @@ -97,6 +97,9 @@ public class RobotModel : BaseModel [JsonPropertyName("LastUpdatedTime")] public DateTime LastUpdatedTime { get; set; } + [JsonPropertyName("OnboardedTime")] + public DateTime OnboardedTime { get; set; } + /// /// Onboarding validation of the robot data object. /// diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index e852a0ee..9f3100fa 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -155,7 +155,7 @@ public async Task> GetActionSequenceAsync() foreach (var tempTask in tasks) { List tempNamesActions = new List(); - List actions = tempTask.ActionSequence; + List actions = tempTask.ActionSequence; foreach (var action in actions) tempNamesActions.Add(action.Name); var response = new ActionSequenceResponse( tempTask.Name, @@ -186,14 +186,14 @@ public async Task, int>> GetRobotsDataAsync(Pagination { var robots = await _robotRepository.GetAllAsync(); var robotsResponse = new List(); - foreach (var robot in robotsResponse) + foreach (var robot in robots) { - var netAppTemp = new RobotResponse(robot.RobotId, - robot.RobotName, - robot.Status, + var netAppTemp = new RobotResponse(robot.Id, + robot.Name, + robot.RobotStatus, robot.OnboardedTime, - robot.ROSVersion, - robot.ROSDistro, + robot.RosVersion, + robot.RosDistro, robot.Manufacturer); robotsResponse.Add(netAppTemp); } From 75702df39aa5fd09b32667f7b0ea695415121b39 Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Wed, 11 Jan 2023 14:05:38 +0100 Subject: [PATCH 08/16] Fixed GetActionSequenceAsync --- .../Services/DashboardService.cs | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index 9f3100fa..7673376d 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -16,6 +16,7 @@ public class DashboardService : IDashboardService private readonly IEdgeRepository _edgeRepository; private readonly ICloudRepository _cloudRepository; private readonly IInstanceRepository _instanceRepository; + private readonly IActionRepository _actionRepository; public DashboardService(IRobotRepository robotRepository, @@ -23,7 +24,8 @@ public DashboardService(IRobotRepository robotRepository, IActionPlanRepository actionPlanRepository, IEdgeRepository edgeRepository, ICloudRepository cloudRepository, - IInstanceRepository instanceRepository) + IInstanceRepository instanceRepository, + IActionRepository actionRepository) { _instanceRepository = instanceRepository; _cloudRepository = cloudRepository; @@ -31,6 +33,7 @@ public DashboardService(IRobotRepository robotRepository, _actionPlanRepository = actionPlanRepository; _taskRepository = taskRepository; _robotRepository = robotRepository; + _actionRepository = actionRepository; } /// @@ -152,17 +155,22 @@ public async Task> GetActionSequenceAsync() var tasks = await _taskRepository.GetAllAsync(); var responses = new List(); - foreach (var tempTask in tasks) + foreach (var taskTemp in tasks) { List tempNamesActions = new List(); - List actions = tempTask.ActionSequence; - foreach (var action in actions) tempNamesActions.Add(action.Name); + List action = await _taskRepository.GetRelation(taskTemp.Id, "EXTENDS"); + foreach(RelationModel actionTemp in action) + { + var actionModelTemp = await _actionRepository.GetByIdAsync(actionTemp.PointsTo.Id); + tempNamesActions.Add(actionModelTemp.Name); + } var response = new ActionSequenceResponse( - tempTask.Name, - tempTask.Id, + taskTemp.Name, + taskTemp.Id, tempNamesActions ); responses.Add(response); + //tempNamesActions.Clear(); } return responses; } From 1a3ac7367ac65aabe001c33187733a47501f0a27 Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Thu, 12 Jan 2023 13:17:24 +0100 Subject: [PATCH 09/16] endpoint to retreive graph GetGraphAsync() --- .../Repositories/Abstract/IBaseRepository.cs | 2 + src/Common/Repositories/BaseRepository.cs | 47 +++++++++++++++++++ .../Controllers/DashboardController.cs | 23 +++++++++ .../Services/Abstract/IDashboardService.cs | 2 + .../Services/DashboardService.cs | 12 +++++ 5 files changed, 86 insertions(+) diff --git a/src/Common/Repositories/Abstract/IBaseRepository.cs b/src/Common/Repositories/Abstract/IBaseRepository.cs index a0ac9411..8ebe0282 100644 --- a/src/Common/Repositories/Abstract/IBaseRepository.cs +++ b/src/Common/Repositories/Abstract/IBaseRepository.cs @@ -57,4 +57,6 @@ public interface IBaseRepository where T : class Task DeleteGraphModelAsync(GraphEntityModel model); Task DeleteRelationAsync(RelationModel relation); + + Task> GetAllRelations(); } \ No newline at end of file diff --git a/src/Common/Repositories/BaseRepository.cs b/src/Common/Repositories/BaseRepository.cs index 1f784ab7..b4de12ef 100644 --- a/src/Common/Repositories/BaseRepository.cs +++ b/src/Common/Repositories/BaseRepository.cs @@ -314,6 +314,53 @@ public virtual async Task AddGraphAsync(GraphEntityModel model) return resultSet != null && resultSet.Metrics.NodesCreated == 1; } + /// + /// Return all RelationModels to recreate the graph. + /// + /// + public virtual async Task> GetAllRelations() + { + List relationModels = new List(); + string query = "MATCH (x) RETURN x"; + ResultSet resultSet = await RedisGraph.Query(GraphName, query); + + for (int i = 0; i < resultSet.Results.Count; i++) + { + var res = resultSet.Results.ElementAt(i); + if (i % 2 == 0) + { + foreach (RedisGraphResult node in res.Value) + { + + var relationModel = new RelationModel + { + RelationName = "relationName" + }; + if (node is Node nd) + { + SetGraphModelValues(relationModel.InitiatesFrom, nd); + } + + relationModels.Add(relationModel); + } + } + else + { + foreach (RedisGraphResult node in res.Value) + { + var idxTmp = res.Value.IndexOf(node); + var relationModel = relationModels[idxTmp]; + if (node is Node nd) + { + SetGraphModelValues(relationModel.PointsTo, nd); + } + } + } + } + return relationModels; + + } + /// /// Creating a new relation between two models /// diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index 1cd20815..d9dc42c9 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -173,6 +173,29 @@ public async Task GetRobotsAsync([FromQuery] PaginationFilter fil } } + /// + /// Return the Graph + /// + /// + [HttpGet("/dashboard/graph/")] + [ProducesResponseType(typeof(ActionSequenceResponse), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] + public async Task GetGraphAsync() + { + try + { + List onboardingTypes = _dashboardService.GetOnboardingItemNames(); + + return Ok(onboardingTypes); + } + catch (Exception ex) + { + int statusCode = (int)HttpStatusCode.InternalServerError; + _logger.LogError(ex, "An error occurred:"); + return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); + } + } + } } diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index 161d4b41..b4ea82fa 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -30,5 +30,7 @@ public interface IDashboardService Task, int>> GetNetAppsDataListAsync(PaginationFilter filter); Task, int>> GetRobotsDataAsync(PaginationFilter filter); + + Task, int>> GetAllRelationModelsAsync(PaginationFilter filter); } } diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index 7673376d..6fe2e69e 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -208,6 +208,18 @@ public async Task, int>> GetRobotsDataAsync(Pagination return new(filter.FilterResult(robotsResponse), robotsResponse.Count); } + /// + /// Get all relationModels possible to reconstruct the graph + /// + /// + /// + public async Task, int>> GetAllRelationModelsAsync(PaginationFilter filter) + { + List relations = await _robotRepository.GetAllRelations(); + + return null; + } + } } From fc2a8fa381e55043f351f48ed6fae69bad23268f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bratu=C5=9B?= Date: Thu, 12 Jan 2023 14:55:11 +0100 Subject: [PATCH 10/16] Added the retrieval of all relations from graph --- .../Repositories/Abstract/IBaseRepository.cs | 2 +- src/Common/Repositories/BaseRepository.cs | 42 +-------- .../Controllers/DashboardController.cs | 18 ++-- src/RedisInterface/Responses/GraphResponse.cs | 16 ++++ .../Services/Abstract/IDashboardService.cs | 2 +- .../Services/DashboardService.cs | 90 ++++++++++++++----- 6 files changed, 98 insertions(+), 72 deletions(-) create mode 100644 src/RedisInterface/Responses/GraphResponse.cs diff --git a/src/Common/Repositories/Abstract/IBaseRepository.cs b/src/Common/Repositories/Abstract/IBaseRepository.cs index 8ebe0282..2a4f94a2 100644 --- a/src/Common/Repositories/Abstract/IBaseRepository.cs +++ b/src/Common/Repositories/Abstract/IBaseRepository.cs @@ -58,5 +58,5 @@ public interface IBaseRepository where T : class Task DeleteRelationAsync(RelationModel relation); - Task> GetAllRelations(); + Task>> GetAllRelations(); } \ No newline at end of file diff --git a/src/Common/Repositories/BaseRepository.cs b/src/Common/Repositories/BaseRepository.cs index b4de12ef..01836d63 100644 --- a/src/Common/Repositories/BaseRepository.cs +++ b/src/Common/Repositories/BaseRepository.cs @@ -318,46 +318,12 @@ public virtual async Task AddGraphAsync(GraphEntityModel model) /// Return all RelationModels to recreate the graph. /// /// - public virtual async Task> GetAllRelations() + public virtual async Task>> GetAllRelations() { - List relationModels = new List(); - string query = "MATCH (x) RETURN x"; + string query = "MATCH (n) OPTIONAL MATCH (n)-[r]-(m) RETURN n, type(r) as r, m"; ResultSet resultSet = await RedisGraph.Query(GraphName, query); - - for (int i = 0; i < resultSet.Results.Count; i++) - { - var res = resultSet.Results.ElementAt(i); - if (i % 2 == 0) - { - foreach (RedisGraphResult node in res.Value) - { - - var relationModel = new RelationModel - { - RelationName = "relationName" - }; - if (node is Node nd) - { - SetGraphModelValues(relationModel.InitiatesFrom, nd); - } - - relationModels.Add(relationModel); - } - } - else - { - foreach (RedisGraphResult node in res.Value) - { - var idxTmp = res.Value.IndexOf(node); - var relationModel = relationModels[idxTmp]; - if (node is Node nd) - { - SetGraphModelValues(relationModel.PointsTo, nd); - } - } - } - } - return relationModels; + + return resultSet?.Results; } diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index d9dc42c9..41a80e13 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -1,6 +1,4 @@ using System.Net; -using Amazon.SecretsManager.Model; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Middleware.Common; using Middleware.Common.Helpers; @@ -48,7 +46,7 @@ public async Task GetTaskRobotResponseAsync([FromQuery] Paginatio _logger.LogError(ex, "An error occurred:"); return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); } - + } /// @@ -110,7 +108,7 @@ public async Task GetOnboardingItemTypesAsync() { try { - List onboardingTypes = _dashboardService.GetOnboardingItemNames(); + List onboardingTypes = _dashboardService.GetOnboardingItemNames(); return Ok(onboardingTypes); } catch (Exception ex) @@ -177,16 +175,16 @@ public async Task GetRobotsAsync([FromQuery] PaginationFilter fil /// Return the Graph /// /// - [HttpGet("/dashboard/graph/")] - [ProducesResponseType(typeof(ActionSequenceResponse), (int)HttpStatusCode.OK)] + [HttpGet("dashboard/graph")] + [ProducesResponseType(typeof(GraphResponse), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] public async Task GetGraphAsync() { try { - List onboardingTypes = _dashboardService.GetOnboardingItemNames(); - - return Ok(onboardingTypes); + var relations = await _dashboardService.GetAllRelationModelsAsync(); + + return Ok(relations); } catch (Exception ex) { @@ -195,7 +193,5 @@ public async Task GetGraphAsync() return StatusCode(statusCode, new ApiResponse(statusCode, $"An error has occurred: {ex.Message}")); } } - - } } diff --git a/src/RedisInterface/Responses/GraphResponse.cs b/src/RedisInterface/Responses/GraphResponse.cs new file mode 100644 index 00000000..a2c3d33c --- /dev/null +++ b/src/RedisInterface/Responses/GraphResponse.cs @@ -0,0 +1,16 @@ +using Middleware.Common.Models; + +namespace Middleware.RedisInterface.Responses; + +public class GraphResponse +{ + public List Entities { get; set; } + + public List Relations { get; set; } +} +public class SimpleRelation +{ + public Guid OriginatingId { get; set; } + public string RelationName { get; set; } + public Guid PointsToId { get; set; } +} diff --git a/src/RedisInterface/Services/Abstract/IDashboardService.cs b/src/RedisInterface/Services/Abstract/IDashboardService.cs index b4ea82fa..bc2b5fe6 100644 --- a/src/RedisInterface/Services/Abstract/IDashboardService.cs +++ b/src/RedisInterface/Services/Abstract/IDashboardService.cs @@ -31,6 +31,6 @@ public interface IDashboardService Task, int>> GetRobotsDataAsync(PaginationFilter filter); - Task, int>> GetAllRelationModelsAsync(PaginationFilter filter); + Task GetAllRelationModelsAsync(); } } diff --git a/src/RedisInterface/Services/DashboardService.cs b/src/RedisInterface/Services/DashboardService.cs index 6fe2e69e..50d9dded 100644 --- a/src/RedisInterface/Services/DashboardService.cs +++ b/src/RedisInterface/Services/DashboardService.cs @@ -5,12 +5,15 @@ using Middleware.Common.Repositories.Abstract; using Middleware.RedisInterface.Responses; using Middleware.Common.ExtensionMethods; +using Microsoft.AspNetCore.Http; +using StackExchange.Redis; +using System.Reflection.Metadata.Ecma335; namespace Middleware.RedisInterface.Services { public class DashboardService : IDashboardService { - private readonly IRobotRepository _robotRepository; + private readonly IRobotRepository _robotRepository; private readonly ITaskRepository _taskRepository; private readonly IActionPlanRepository _actionPlanRepository; private readonly IEdgeRepository _edgeRepository; @@ -19,10 +22,10 @@ public class DashboardService : IDashboardService private readonly IActionRepository _actionRepository; - public DashboardService(IRobotRepository robotRepository, - ITaskRepository taskRepository, - IActionPlanRepository actionPlanRepository, - IEdgeRepository edgeRepository, + public DashboardService(IRobotRepository robotRepository, + ITaskRepository taskRepository, + IActionPlanRepository actionPlanRepository, + IEdgeRepository edgeRepository, ICloudRepository cloudRepository, IInstanceRepository instanceRepository, IActionRepository actionRepository) @@ -66,11 +69,11 @@ public async Task, int>> GetLocationsStatusLi { var locations = new List(); var clouds = await _cloudRepository.GetAllAsync(); - + foreach (var cloud in clouds) { - var locatedInstances = - await _cloudRepository.GetRelation(cloud.Id,"LOCATED_AT",RelationDirection.Incoming); + var locatedInstances = + await _cloudRepository.GetRelation(cloud.Id, "LOCATED_AT", RelationDirection.Incoming); int noOfContainers = 0; foreach (var item in locatedInstances) @@ -79,11 +82,11 @@ public async Task, int>> GetLocationsStatusLi noOfContainers += instanceContainers.Count; } - var location = new LocationStatusResponse(cloud.Name, - cloud.LastUpdatedTime, - cloud.CloudStatus, - cloud.IsOnline, - noOfContainers > 0, + var location = new LocationStatusResponse(cloud.Name, + cloud.LastUpdatedTime, + cloud.CloudStatus, + cloud.IsOnline, + noOfContainers > 0, noOfContainers); locations.Add(location); } @@ -110,7 +113,7 @@ public async Task, int>> GetLocationsStatusLi noOfContainers); locations.Add(location); } - return new (filter.FilterResult(locations), locations.Count); + return new(filter.FilterResult(locations), locations.Count); } /// @@ -140,10 +143,10 @@ public async Task, int>> GetRobotStatusListAsync(P ap.TaskStartedAt, ap.Status == "completed" ? ap.LastStatusChange : null, robot.RobotStatus); - + responses.Add(response); } - return new (filter.FilterResult(responses), responses.Count); + return new(filter.FilterResult(responses), responses.Count); } /// @@ -159,7 +162,7 @@ public async Task> GetActionSequenceAsync() { List tempNamesActions = new List(); List action = await _taskRepository.GetRelation(taskTemp.Id, "EXTENDS"); - foreach(RelationModel actionTemp in action) + foreach (RelationModel actionTemp in action) { var actionModelTemp = await _actionRepository.GetByIdAsync(actionTemp.PointsTo.Id); tempNamesActions.Add(actionModelTemp.Name); @@ -213,13 +216,58 @@ public async Task, int>> GetRobotsDataAsync(Pagination /// /// /// - public async Task, int>> GetAllRelationModelsAsync(PaginationFilter filter) + public async Task GetAllRelationModelsAsync() { - List relations = await _robotRepository.GetAllRelations(); + Dictionary> resultSet = await _robotRepository.GetAllRelations(); - return null; - } + var entities = new List(); + var relations = new List(); + foreach (RedisGraphResult node in resultSet["n"]) + { + var entity = new GraphEntityModel(); + if (node is not Node nd) + continue; + + RedisValue? id = null, name = null, type = null; + var props = nd.Properties; + if (props.ContainsKey("ID")) + id = props["ID"]; + if (props.ContainsKey("Type")) + type = props["Type"]; + if (props.ContainsKey("Name")) + name = props["Name"]; + + if (id == null || (id != null && Guid.TryParse(id?.ToString(), out _)) == false) + continue; + + entity.Id = Guid.Parse(id?.ToString()); + entity.Type = type?.ToString(); + entity.Name = name?.ToString(); + entities.Add(entity); + } + var entityIds = entities.Select(e => e.Id.ToString()).ToList(); + + for (int i = 0; i < resultSet["n"].Count; i++) + { + var initiatesId = (resultSet["n"][i] as Node).Properties["ID"].ToString(); + var type = resultSet["r"][i].GetType(); + var relationName = (resultSet["r"][i] as ScalarResult).Value?.ToString(); + if (relationName is null || entityIds.Contains(initiatesId) == false) + continue; + var pointsTo = (resultSet["m"][i] as Node)?.Properties["ID"].ToString(); + relations.Add( + new SimpleRelation + { + OriginatingId = Guid.Parse(initiatesId), + PointsToId = Guid.Parse(pointsTo), + RelationName = relationName + }); + } + var response = new GraphResponse() { Entities = entities, Relations = relations }; + + return response; + } } } From 88f793b2330462525b9de29047b66e27e2fb013e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bratu=C5=9B?= Date: Thu, 12 Jan 2023 15:02:43 +0100 Subject: [PATCH 11/16] Changes to types and endpoint names --- src/RedisInterface/Controllers/DashboardController.cs | 4 ++-- src/RedisInterface/Responses/LocationStatusResponse.cs | 2 +- src/RedisInterface/Responses/NetAppsDetailsResponse.cs | 2 +- src/RedisInterface/Responses/RobotResponse.cs | 2 +- src/RedisInterface/Responses/TaskRobotResponse.cs | 2 +- src/RedisInterface/Responses/actionSequenceREsponse.cs | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index 41a80e13..ff34c436 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -79,7 +79,7 @@ public async Task GetLocationStatusesAsync([FromQuery] Pagination /// Return to the cascading grid the action sequence names for all tasks /// /// - [HttpGet("actionSequence")] + [HttpGet("tasks/actions")] [ProducesResponseType(typeof(ActionSequenceResponse), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] public async Task GetActionSequenceAsync() @@ -101,7 +101,7 @@ public async Task GetActionSequenceAsync() /// Return the onboarding types names => Drop down menu. /// /// - [HttpGet("onboardingTypes")] + [HttpGet("types")] [ProducesResponseType(typeof(ActionSequenceResponse), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] public async Task GetOnboardingItemTypesAsync() diff --git a/src/RedisInterface/Responses/LocationStatusResponse.cs b/src/RedisInterface/Responses/LocationStatusResponse.cs index 2f717bc4..89365134 100644 --- a/src/RedisInterface/Responses/LocationStatusResponse.cs +++ b/src/RedisInterface/Responses/LocationStatusResponse.cs @@ -5,7 +5,7 @@ namespace Middleware.RedisInterface.Responses; public class LocationStatusResponse { [JsonPropertyName("lastUpdatedTime")] - public DateTime LastUpdatedTime { get; set; } + public DateTime? LastUpdatedTime { get; set; } [JsonPropertyName("name")] public string Name { get; set; } diff --git a/src/RedisInterface/Responses/NetAppsDetailsResponse.cs b/src/RedisInterface/Responses/NetAppsDetailsResponse.cs index 540f23c2..35e07eca 100644 --- a/src/RedisInterface/Responses/NetAppsDetailsResponse.cs +++ b/src/RedisInterface/Responses/NetAppsDetailsResponse.cs @@ -17,7 +17,7 @@ public record NetAppsDetailsResponse public string ROSDistro { get; set; } [JsonPropertyName("OnboardedTime")] - public DateTime OnboardedTime { get; set; } + public DateTime? OnboardedTime { get; set; } public NetAppsDetailsResponse() { diff --git a/src/RedisInterface/Responses/RobotResponse.cs b/src/RedisInterface/Responses/RobotResponse.cs index 2ff1d1ae..649d25dc 100644 --- a/src/RedisInterface/Responses/RobotResponse.cs +++ b/src/RedisInterface/Responses/RobotResponse.cs @@ -14,7 +14,7 @@ public record RobotResponse public string Status { get; set; } [JsonPropertyName("OnboardedTime")] - public DateTime OnboardedTime { get; set; } + public DateTime? OnboardedTime { get; set; } [JsonPropertyName("ROSVersion")] public int ROSVersion { get; set; } diff --git a/src/RedisInterface/Responses/TaskRobotResponse.cs b/src/RedisInterface/Responses/TaskRobotResponse.cs index 6d7aa4cf..571e6e47 100644 --- a/src/RedisInterface/Responses/TaskRobotResponse.cs +++ b/src/RedisInterface/Responses/TaskRobotResponse.cs @@ -17,7 +17,7 @@ public record TaskRobotResponse public Guid TaskId { get; set; } [JsonPropertyName("taskStartTime")] - public DateTime TaskStartTime { get; set; } + public DateTime? TaskStartTime { get; set; } [JsonPropertyName("taskCompletedTime")] public DateTime? TaskCompletedTime { get; set; } diff --git a/src/RedisInterface/Responses/actionSequenceREsponse.cs b/src/RedisInterface/Responses/actionSequenceREsponse.cs index c43d1803..5608a052 100644 --- a/src/RedisInterface/Responses/actionSequenceREsponse.cs +++ b/src/RedisInterface/Responses/actionSequenceREsponse.cs @@ -4,13 +4,13 @@ namespace Middleware.RedisInterface.Responses { public record ActionSequenceResponse { - [JsonPropertyName("TaskName")] + [JsonPropertyName("taskName")] public string TaskName { get; set; } - [JsonPropertyName("TaskId")] + [JsonPropertyName("taskId")] public Guid TaskId { get; set; } - [JsonPropertyName("Actions")] + [JsonPropertyName("actions")] public List Actions { get; set; } public ActionSequenceResponse() From 0de6d80fc9ac3dc7f5ca83cdabe7075eb8935898 Mon Sep 17 00:00:00 2001 From: adrianLIrobotics Date: Mon, 16 Jan 2023 11:54:39 +0100 Subject: [PATCH 12/16] Fix for issue #95 --- src/Common/Models/TaskPlannerInputModel.cs | 16 +++++- .../Controllers/DashboardController.cs | 2 +- src/TaskPlanner/Controllers/PlanController.cs | 11 ++++ .../Abstract/IRedisInterfaceClientService.cs | 16 ++++++ src/TaskPlanner/Services/ActionPlanner.cs | 50 +++++++++++-------- .../Services/RedisInterfaceClientService.cs | 30 +++++++++++ 6 files changed, 103 insertions(+), 22 deletions(-) diff --git a/src/Common/Models/TaskPlannerInputModel.cs b/src/Common/Models/TaskPlannerInputModel.cs index 68ba30a2..97b4e83b 100644 --- a/src/Common/Models/TaskPlannerInputModel.cs +++ b/src/Common/Models/TaskPlannerInputModel.cs @@ -1,4 +1,5 @@ -using System.Text.Json.Serialization; +using Microsoft.Extensions.Logging; +using System.Text.Json.Serialization; namespace Middleware.Common.Models { @@ -24,5 +25,18 @@ public class TaskPlannerInputModel [JsonPropertyName("Questions")] public List Questions { get; set; } + + public bool IsValid() + { + if ((RobotId == Guid.Empty) | (Id == Guid.Empty)) + { + return false; + } + else + { + return true; + } + + } } } diff --git a/src/RedisInterface/Controllers/DashboardController.cs b/src/RedisInterface/Controllers/DashboardController.cs index ff34c436..5fd4ea47 100644 --- a/src/RedisInterface/Controllers/DashboardController.cs +++ b/src/RedisInterface/Controllers/DashboardController.cs @@ -175,7 +175,7 @@ public async Task GetRobotsAsync([FromQuery] PaginationFilter fil /// Return the Graph /// /// - [HttpGet("dashboard/graph")] + [HttpGet("graph")] [ProducesResponseType(typeof(GraphResponse), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.InternalServerError)] public async Task GetGraphAsync() diff --git a/src/TaskPlanner/Controllers/PlanController.cs b/src/TaskPlanner/Controllers/PlanController.cs index 2a016767..3129bc14 100644 --- a/src/TaskPlanner/Controllers/PlanController.cs +++ b/src/TaskPlanner/Controllers/PlanController.cs @@ -37,6 +37,16 @@ public PlanController(IActionPlanner actionPlanner, IApiClientBuilder builder, public async Task> GetPlan([FromBody] TaskPlannerInputModel inputModel, bool dryRun = false) { + if (inputModel == null) + { + return BadRequest("Parameters were not specified."); + } + + if (inputModel.IsValid() == false) + { + return BadRequest(new ApiResponse((int)HttpStatusCode.BadRequest, "Parameters were not specified or wrongly specified.")); + } + Guid id = inputModel.Id; //task id bool lockResource = inputModel.LockResourceReUse; Guid robotId = inputModel.RobotId; //robot id @@ -53,6 +63,7 @@ public async Task> GetPlan([FromBody] TaskPlannerInputMo // call resource planner for resources ResourcePlanner.TaskModel tmpTaskSend = _mapper.Map(plan); ResourcePlanner.RobotModel tmpRobotSend = _mapper.Map(robot2); + ResourcePlanner.ResourceInput resourceInput = new ResourcePlanner.ResourceInput { Robot = tmpRobotSend, diff --git a/src/TaskPlanner/Services/Abstract/IRedisInterfaceClientService.cs b/src/TaskPlanner/Services/Abstract/IRedisInterfaceClientService.cs index 83ec000a..43902863 100644 --- a/src/TaskPlanner/Services/Abstract/IRedisInterfaceClientService.cs +++ b/src/TaskPlanner/Services/Abstract/IRedisInterfaceClientService.cs @@ -10,6 +10,7 @@ public interface IRedisInterfaceClientService /// /// Unique identifier of /// Complete action plan + /// Task ActionPlanGetByIdAsync(Guid id); /// /// Get by its id @@ -139,4 +140,19 @@ Task AddRelationAsync(TSource source, TDirection dire /// /// Task GetCloudByNameAsync(string name, CancellationToken token); + + /// + /// Get instance data by its id + /// + /// + /// + Task InstanceGetByIdAsync(Guid id); + + /// + /// Get instance data by its id + /// + /// + /// + /// + Task InstanceGetByIdAsync(Guid id, CancellationToken token); } \ No newline at end of file diff --git a/src/TaskPlanner/Services/ActionPlanner.cs b/src/TaskPlanner/Services/ActionPlanner.cs index 2d7a279c..286f0e89 100644 --- a/src/TaskPlanner/Services/ActionPlanner.cs +++ b/src/TaskPlanner/Services/ActionPlanner.cs @@ -8,6 +8,8 @@ using Middleware.TaskPlanner.ApiReference; using Middleware.Common.Repositories.Abstract; using Middleware.TaskPlanner.Exceptions; +using Middleware.Common.Repositories; +using System.Threading.Tasks; namespace Middleware.TaskPlanner.Services { @@ -16,6 +18,7 @@ public class ActionPlanner : IActionPlanner { private readonly IMapper _mapper; private readonly IRedisInterfaceClientService _redisInterfaceClient; + public List ActionSequence { get; set; } public DateTime CurrentTime { get; set; } public string InferingProcess { get; set; } @@ -26,7 +29,6 @@ public ActionPlanner(IApiClientBuilder apiBuilder, IMapper mapper, IRedisInterfa { _redisInterfaceClient = redisInterfaceClient; _mapper = mapper; - InferingProcess = ""; //Predefined actionsequence by id or IA infering based on new task. } @@ -147,9 +149,25 @@ protected async Task> getMarkovianCandidates(List failed return FinalCandidates; } - protected void CheckInstanceByRobotRosDistro(RobotModel robot, ActionModel actionItem) + /// + /// Validation of robot and netApp match. + /// + /// + /// + /// + /// + protected async void validateRobotVsNetApp(RobotModel robot, ActionModel actionItem) { - foreach (InstanceModel instance in actionItem.Services) + var instances = new List(); + List relations = await _redisInterfaceClient.GetRelationAsync(actionItem, "NEEDS"); + foreach(RelationModel tempRelation in relations) + { + var instanceTemp = await _redisInterfaceClient.InstanceGetByIdAsync(tempRelation.PointsTo.Id); + instances.Add(instanceTemp); + } + + // Check if the netApp ROS distro is equal to the ROS distro of robot. + foreach (InstanceModel instance in instances) { if (instance.RosVersion != robot.RosVersion) { @@ -161,20 +179,11 @@ protected void CheckInstanceByRobotRosDistro(RobotModel robot, ActionModel actio throw new IncorrectROSVersionException(); } } - } - /// - /// Check that the robot can run the netApp from HW, sensor & actuators perspective - /// - /// - /// - /// - protected void CheckInstanceByRobotHw(RobotModel robot, ActionModel actionItem) - { //Check if the instances (netApps) support the robot attributes, sensors and specifications. int numSensors = robot.Sensors.Count; int countTemp = 0; - foreach (InstanceModel instance in actionItem.Services) + foreach (InstanceModel instance in instances) { if (instance.InstanceFamily == "ComputerVision") { @@ -195,7 +204,7 @@ protected void CheckInstanceByRobotHw(RobotModel robot, ActionModel actionItem) } } - if (numSensors == countTemp) + if (countTemp == 0) { throw new InvalidOperationException("The robot does not have any proper sensors to feed the neccesary data to the netApp."); } @@ -236,7 +245,11 @@ public async Task> InferActionSequence(Guid current replanedCompleteActionSeqBK.AddRange(replanedCompleteActionSeq); robot.Questions.AddRange(DialogueTemp); //Append the questions-answers to the robot - // + + if (ContextKnown == false) + { + throw new NotImplementedException(); + } TaskModel task = await _redisInterfaceClient.TaskGetByIdAsync(currentTaskId); //Get action plan from Redis bool alreadyExist = task != null; //Check if CurrentTask is inside Redis model task.ActionPlanId = Guid.NewGuid();//Generate automatic new Guid for plan ID. @@ -284,11 +297,8 @@ public async Task> InferActionSequence(Guid current //Call to retrieve specific action ActionModel actionItem = await _redisInterfaceClient.ActionGetByIdAsync(actionId); - // Check if the robot have the proper ROS distro and version. - CheckInstanceByRobotRosDistro(robot, actionItem); - - // Check if the robot have the neccesary sensors and actuators for the netapp to correctly function. - CheckInstanceByRobotHw(robot, actionItem); + // Validate robot and netApp match. + validateRobotVsNetApp(robot, actionItem); //If the partial or complete replan was not activated, add the action to the action sequence. --> Normal plan // PLAN ESTRATEGY A: diff --git a/src/TaskPlanner/Services/RedisInterfaceClientService.cs b/src/TaskPlanner/Services/RedisInterfaceClientService.cs index e1b1a827..25ac75ff 100644 --- a/src/TaskPlanner/Services/RedisInterfaceClientService.cs +++ b/src/TaskPlanner/Services/RedisInterfaceClientService.cs @@ -205,6 +205,36 @@ public async Task> GetRelationAsync(TSource source, } } + public async Task InstanceGetByIdAsync(Guid id) + { + return await InstanceGetByIdAsync(id, CancellationToken.None); + } + + public async Task InstanceGetByIdAsync(Guid id, CancellationToken token) + { + if (id == default) + throw new ArgumentNullException(nameof(id)); + string url = $"/api/v1/instance/{id}"; + try + { + var result = await _httpClient.GetAsync(url, token); + + if (result.IsSuccessStatusCode == false) + { + throw new InvalidOperationException(); + } + var body = await result.Content.ReadAsStringAsync(token); + var instance = JsonConvert.DeserializeObject(body); + return instance; + } + catch (Exception ex) + { + _logger.LogError(ex, "There was en error while calling for the instance with id: {id}", id); + throw; + } + } + + public async Task ActionGetByIdAsync(Guid id) { return await ActionGetByIdAsync(id, CancellationToken.None); From 1988f98e03e724a8b11ee5ceb8839b60ffe6f374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bratu=C5=9B?= Date: Tue, 17 Jan 2023 16:21:37 +0100 Subject: [PATCH 13/16] Added required mappings updates api spec, fixed critical error --- src/Common/Models/GraphEntityModel.cs | 6 + src/Orchestrator/OrchestratorSpec.json | 57 +- src/RedisInterface/RedisInterfaceSpec.json | 876 +++++++++++++++++-- src/ResourcePlanner/ResourcePlannerSpec.json | 19 + src/TaskPlanner/Config/AutoMapperConfig.cs | 16 +- src/TaskPlanner/Services/ActionPlanner.cs | 46 +- src/TaskPlanner/TaskPlannerSpec.json | 21 + 7 files changed, 933 insertions(+), 108 deletions(-) diff --git a/src/Common/Models/GraphEntityModel.cs b/src/Common/Models/GraphEntityModel.cs index 894dacae..2e5170fa 100644 --- a/src/Common/Models/GraphEntityModel.cs +++ b/src/Common/Models/GraphEntityModel.cs @@ -28,6 +28,12 @@ public GraphEntityModel(Guid id, RedisDbIndexEnum dbIndex) Id = id; Type = dbIndex.ToString().ToUpper(); } + public GraphEntityModel(Guid id, string name, string type) + { + Id = id; + Name = name; + Type = type; + } public GraphEntityModel(Guid id, string name, Type type) { diff --git a/src/Orchestrator/OrchestratorSpec.json b/src/Orchestrator/OrchestratorSpec.json index 3148f597..b465eb01 100644 --- a/src/Orchestrator/OrchestratorSpec.json +++ b/src/Orchestrator/OrchestratorSpec.json @@ -1029,6 +1029,10 @@ "RobotId": { "type": "string", "format": "uuid" + }, + "TaskStartedAt": { + "type": "string", + "format": "date-time" } }, "additionalProperties": false @@ -1044,14 +1048,14 @@ "type": "string", "nullable": true }, - "dof": { + "number": { "type": "integer", "format": "int32" }, "nodes": { "type": "array", "items": { - "$ref": "#/components/schemas/ROSNodeModel" + "type": "string" }, "nullable": true } @@ -1073,6 +1077,10 @@ "type": "string", "format": "date-time", "readOnly": true + }, + "isError": { + "type": "boolean", + "readOnly": true } }, "additionalProperties": false @@ -1212,6 +1220,10 @@ "MinimumNumCores": { "type": "integer", "format": "int32" + }, + "OnboardedTime": { + "type": "string", + "format": "date-time" } }, "additionalProperties": false @@ -1367,6 +1379,30 @@ "type": "string", "nullable": true }, + "RosVersion": { + "type": "integer", + "format": "int32" + }, + "RosDistro": { + "type": "string", + "nullable": true + }, + "MaximumPayload": { + "type": "integer", + "format": "int64" + }, + "MaximumTranslationalVelocity": { + "type": "integer", + "format": "int64" + }, + "MaximumRotationalVelocity": { + "type": "integer", + "format": "int64" + }, + "RobotWeight": { + "type": "integer", + "format": "int64" + }, "ROSRepo": { "type": "string", "format": "uri", @@ -1396,7 +1432,7 @@ "type": "string", "nullable": true }, - "CurrentTaskID": { + "currentTaskId": { "type": "string", "format": "uuid" }, @@ -1452,10 +1488,6 @@ "type": "integer", "format": "int64" }, - "VirtualRam": { - "type": "integer", - "format": "int64" - }, "StorageDisk": { "type": "integer", "format": "int64" @@ -1470,6 +1502,14 @@ "$ref": "#/components/schemas/DialogueModel" }, "nullable": true + }, + "LastUpdatedTime": { + "type": "string", + "format": "date-time" + }, + "OnboardedTime": { + "type": "string", + "format": "date-time" } }, "additionalProperties": false @@ -1575,6 +1615,9 @@ "description": { "type": "string", "nullable": true + }, + "enabled": { + "type": "boolean" } }, "additionalProperties": false diff --git a/src/RedisInterface/RedisInterfaceSpec.json b/src/RedisInterface/RedisInterfaceSpec.json index f36027b1..00099dcb 100644 --- a/src/RedisInterface/RedisInterfaceSpec.json +++ b/src/RedisInterface/RedisInterfaceSpec.json @@ -3652,6 +3652,354 @@ } } }, + "/api/v1/Dashboard/locations": { + "get": { + "tags": [ + "Dashboard" + ], + "parameters": [ + { + "name": "PageNumber", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "PageSize", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/LocationStatusResponseListPagedResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/LocationStatusResponseListPagedResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/LocationStatusResponseListPagedResponse" + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + } + } + }, + "/api/v1/Dashboard/tasks/actions": { + "get": { + "tags": [ + "Dashboard" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ActionSequenceResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActionSequenceResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ActionSequenceResponse" + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + } + } + }, + "/api/v1/Dashboard/types": { + "get": { + "tags": [ + "Dashboard" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ActionSequenceResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActionSequenceResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ActionSequenceResponse" + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + } + } + }, + "/api/v1/Dashboard/netApps": { + "get": { + "tags": [ + "Dashboard" + ], + "parameters": [ + { + "name": "PageNumber", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "PageSize", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/NetAppsDetailsResponseListPagedResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/NetAppsDetailsResponseListPagedResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/NetAppsDetailsResponseListPagedResponse" + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + } + } + }, + "/api/v1/Dashboard/robots": { + "get": { + "tags": [ + "Dashboard" + ], + "parameters": [ + { + "name": "PageNumber", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "PageSize", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/RobotResponseListPagedResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/RobotResponseListPagedResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/RobotResponseListPagedResponse" + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + } + } + }, + "/api/v1/Dashboard/graph": { + "get": { + "tags": [ + "Dashboard" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/GraphResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/GraphResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/GraphResponse" + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + } + } + }, "/api/v1/Edge": { "get": { "tags": [ @@ -8494,6 +8842,27 @@ "type": "object", "additionalProperties": false }, + "ActionSequenceResponse": { + "type": "object", + "properties": { + "taskName": { + "type": "string", + "nullable": true + }, + "taskId": { + "type": "string", + "format": "uuid" + }, + "actions": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + }, "ActivePolicy": { "type": "object", "properties": { @@ -8616,6 +8985,13 @@ "MacAddress": { "type": "string", "nullable": true + }, + "LastUpdatedTime": { + "type": "string", + "format": "date-time" + }, + "IsOnline": { + "type": "boolean" } }, "additionalProperties": false @@ -8719,149 +9095,362 @@ "format": "uri", "nullable": true }, - "MacAddress": { - "type": "string", + "MacAddress": { + "type": "string", + "nullable": true + }, + "CPU": { + "type": "integer", + "format": "int32" + }, + "RAM": { + "type": "integer", + "format": "int32" + }, + "VirtualRam": { + "type": "integer", + "format": "int32" + }, + "DiskStorage": { + "type": "integer", + "format": "int64" + }, + "NumberOfCores": { + "type": "integer", + "format": "int32" + }, + "LastUpdatedTime": { + "type": "string", + "format": "date-time" + }, + "IsOnline": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "GraphEntityModel": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "type": { + "type": "string", + "nullable": true + }, + "name": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "GraphResponse": { + "type": "object", + "properties": { + "entities": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GraphEntityModel" + }, + "nullable": true + }, + "relations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimpleRelation" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "InstanceModel": { + "type": "object", + "properties": { + "relations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RelationModel" + }, + "nullable": true + }, + "Id": { + "type": "string", + "format": "uuid" + }, + "Name": { + "type": "string", + "nullable": true + }, + "ServiceInstanceId": { + "type": "string", + "format": "uuid" + }, + "ServiceType": { + "type": "string", + "nullable": true + }, + "IsReusable": { + "type": "boolean", + "nullable": true + }, + "DesiredStatus": { + "type": "string", + "nullable": true + }, + "ServiceUrl": { + "type": "string", + "nullable": true + }, + "RosTopicsPub": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RosTopicModel" + }, + "nullable": true + }, + "RosTopicsSub": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RosTopicModel" + }, + "nullable": true + }, + "ROSVersion": { + "type": "integer", + "format": "int32" + }, + "ROSDistro": { + "type": "string", + "nullable": true + }, + "Tags": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "InstanceFamily": { + "type": "string", + "nullable": true + }, + "SuccessRate": { + "type": "integer", + "format": "int32" + }, + "ServiceStatus": { + "type": "string", + "nullable": true + }, + "MinimumRam": { + "type": "integer", + "format": "int32" + }, + "MinimumNumCores": { + "type": "integer", + "format": "int32" + }, + "OnboardedTime": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false + }, + "KeyValuePair": { + "type": "object", + "properties": { + "key": { + "type": "string", + "nullable": true + }, + "value": { + "nullable": true + } + }, + "additionalProperties": false + }, + "LocationStatusResponse": { + "type": "object", + "properties": { + "lastUpdatedTime": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "name": { + "type": "string", + "nullable": true + }, + "isOnline": { + "type": "boolean" + }, + "isBusy": { + "type": "boolean" + }, + "numberOfRunningContainers": { + "type": "integer", + "format": "int32" + }, + "status": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "LocationStatusResponseListPagedResponse": { + "type": "object", + "properties": { + "statusCode": { + "type": "integer", + "format": "int32", + "readOnly": true + }, + "message": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "timeStamp": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "isError": { + "type": "boolean", + "readOnly": true + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LocationStatusResponse" + }, "nullable": true }, - "CPU": { + "pageNumber": { "type": "integer", "format": "int32" }, - "RAM": { + "pageSize": { "type": "integer", "format": "int32" }, - "VirtualRam": { + "firstPage": { "type": "integer", "format": "int32" }, - "DiskStorage": { - "type": "integer", - "format": "int64" + "lastPage": { + "type": "string", + "format": "uri", + "nullable": true }, - "NumberOfCores": { + "totalPages": { "type": "integer", "format": "int32" - } - }, - "additionalProperties": false - }, - "GraphEntityModel": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid" }, - "type": { + "nextPage": { "type": "string", + "format": "uri", "nullable": true }, - "name": { + "previousPage": { "type": "string", + "format": "uri", "nullable": true } }, "additionalProperties": false }, - "InstanceModel": { + "NetAppsDetailsResponse": { "type": "object", "properties": { - "relations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RelationModel" - }, - "nullable": true - }, - "Id": { + "NetAppName": { "type": "string", - "format": "uuid" + "nullable": true }, - "Name": { + "NetAppFamily": { "type": "string", "nullable": true }, - "ServiceInstanceId": { - "type": "string", - "format": "uuid" + "ROSVersion": { + "type": "integer", + "format": "int32" }, - "ServiceType": { + "ROSDistro": { "type": "string", "nullable": true }, - "IsReusable": { - "type": "boolean", + "OnboardedTime": { + "type": "string", + "format": "date-time", "nullable": true + } + }, + "additionalProperties": false + }, + "NetAppsDetailsResponseListPagedResponse": { + "type": "object", + "properties": { + "statusCode": { + "type": "integer", + "format": "int32", + "readOnly": true }, - "DesiredStatus": { + "message": { "type": "string", - "nullable": true + "nullable": true, + "readOnly": true }, - "ServiceUrl": { + "timeStamp": { "type": "string", - "nullable": true + "format": "date-time", + "readOnly": true }, - "RosTopicsPub": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RosTopicModel" - }, - "nullable": true + "isError": { + "type": "boolean", + "readOnly": true }, - "RosTopicsSub": { + "data": { "type": "array", "items": { - "$ref": "#/components/schemas/RosTopicModel" + "$ref": "#/components/schemas/NetAppsDetailsResponse" }, "nullable": true }, - "ROSVersion": { + "pageNumber": { "type": "integer", "format": "int32" }, - "ROSDistro": { - "type": "string", - "nullable": true - }, - "Tags": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true - }, - "InstanceFamily": { - "type": "string", - "nullable": true + "pageSize": { + "type": "integer", + "format": "int32" }, - "SuccessRate": { + "firstPage": { "type": "integer", "format": "int32" }, - "ServiceStatus": { + "lastPage": { "type": "string", + "format": "uri", "nullable": true }, - "MinimumRam": { + "totalPages": { "type": "integer", "format": "int32" }, - "MinimumNumCores": { - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "KeyValuePair": { - "type": "object", - "properties": { - "key": { + "nextPage": { "type": "string", + "format": "uri", "nullable": true }, - "value": { + "previousPage": { + "type": "string", + "format": "uri", "nullable": true } }, @@ -9136,6 +9725,112 @@ "$ref": "#/components/schemas/DialogueModel" }, "nullable": true + }, + "LastUpdatedTime": { + "type": "string", + "format": "date-time" + }, + "OnboardedTime": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false + }, + "RobotResponse": { + "type": "object", + "properties": { + "RobotId": { + "type": "string", + "format": "uuid" + }, + "RobotName": { + "type": "string", + "nullable": true + }, + "Status": { + "type": "string", + "nullable": true + }, + "OnboardedTime": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "ROSVersion": { + "type": "integer", + "format": "int32" + }, + "ROSDistro": { + "type": "string", + "nullable": true + }, + "Manufacturer": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "RobotResponseListPagedResponse": { + "type": "object", + "properties": { + "statusCode": { + "type": "integer", + "format": "int32", + "readOnly": true + }, + "message": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "timeStamp": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "isError": { + "type": "boolean", + "readOnly": true + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RobotResponse" + }, + "nullable": true + }, + "pageNumber": { + "type": "integer", + "format": "int32" + }, + "pageSize": { + "type": "integer", + "format": "int32" + }, + "firstPage": { + "type": "integer", + "format": "int32" + }, + "lastPage": { + "type": "string", + "format": "uri", + "nullable": true + }, + "totalPages": { + "type": "integer", + "format": "int32" + }, + "nextPage": { + "type": "string", + "format": "uri", + "nullable": true + }, + "previousPage": { + "type": "string", + "format": "uri", + "nullable": true } }, "additionalProperties": false @@ -9190,6 +9885,24 @@ }, "additionalProperties": false }, + "SimpleRelation": { + "type": "object", + "properties": { + "originatingId": { + "type": "string", + "format": "uuid" + }, + "relationName": { + "type": "string", + "nullable": true + }, + "pointsToId": { + "type": "string", + "format": "uuid" + } + }, + "additionalProperties": false + }, "TaskModel": { "type": "object", "properties": { @@ -9284,7 +9997,8 @@ }, "taskStartTime": { "type": "string", - "format": "date-time" + "format": "date-time", + "nullable": true }, "taskCompletedTime": { "type": "string", diff --git a/src/ResourcePlanner/ResourcePlannerSpec.json b/src/ResourcePlanner/ResourcePlannerSpec.json index 8a1aa851..d524f909 100644 --- a/src/ResourcePlanner/ResourcePlannerSpec.json +++ b/src/ResourcePlanner/ResourcePlannerSpec.json @@ -332,6 +332,10 @@ "type": "string", "format": "date-time", "readOnly": true + }, + "isError": { + "type": "boolean", + "readOnly": true } }, "additionalProperties": false @@ -471,6 +475,10 @@ "MinimumNumCores": { "type": "integer", "format": "int32" + }, + "OnboardedTime": { + "type": "string", + "format": "date-time" } }, "additionalProperties": false @@ -703,6 +711,14 @@ "$ref": "#/components/schemas/DialogueModel" }, "nullable": true + }, + "LastUpdatedTime": { + "type": "string", + "format": "date-time" + }, + "OnboardedTime": { + "type": "string", + "format": "date-time" } }, "additionalProperties": false @@ -766,6 +782,9 @@ "description": { "type": "string", "nullable": true + }, + "enabled": { + "type": "boolean" } }, "additionalProperties": false diff --git a/src/TaskPlanner/Config/AutoMapperConfig.cs b/src/TaskPlanner/Config/AutoMapperConfig.cs index b44a770e..4462bb95 100644 --- a/src/TaskPlanner/Config/AutoMapperConfig.cs +++ b/src/TaskPlanner/Config/AutoMapperConfig.cs @@ -1,6 +1,6 @@ using Middleware.Common.Models; using Middleware.Common.Responses; -using KeyValuePair = Middleware.Common.Models.KeyValuePair; + namespace Middleware.TaskPlanner.Config; @@ -21,14 +21,24 @@ public static IServiceCollection ConfigureAutoMapper(this IServiceCollection ser cfg.CreateMap().ReverseMap(); cfg.CreateMap().ReverseMap(); cfg.CreateMap().ReverseMap(); - //cfg.CreateMap().ReverseMap(); + // Resource Planner cfg.CreateMap().ReverseMap(); cfg.CreateMap().ReverseMap(); cfg.CreateMap().ReverseMap(); cfg.CreateMap().ReverseMap(); cfg.CreateMap().ReverseMap(); - //cfg.CreateMap().ReverseMap(); + + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); + cfg.CreateMap().ReverseMap(); }); return services; diff --git a/src/TaskPlanner/Services/ActionPlanner.cs b/src/TaskPlanner/Services/ActionPlanner.cs index 286f0e89..c2378179 100644 --- a/src/TaskPlanner/Services/ActionPlanner.cs +++ b/src/TaskPlanner/Services/ActionPlanner.cs @@ -156,11 +156,11 @@ protected async Task> getMarkovianCandidates(List failed /// /// /// - protected async void validateRobotVsNetApp(RobotModel robot, ActionModel actionItem) + protected async Task ValidateRobotVsNetApp(RobotModel robot, ActionModel actionItem) { var instances = new List(); List relations = await _redisInterfaceClient.GetRelationAsync(actionItem, "NEEDS"); - foreach(RelationModel tempRelation in relations) + foreach (RelationModel tempRelation in relations) { var instanceTemp = await _redisInterfaceClient.InstanceGetByIdAsync(tempRelation.PointsTo.Id); instances.Add(instanceTemp); @@ -215,28 +215,41 @@ protected async void validateRobotVsNetApp(RobotModel robot, ActionModel actionI /// /// /// - /// + /// /// /// TaskModel - public async Task> InferActionSequence(Guid currentTaskId, bool ContextKnown, bool resourceLock, List DialogueTemp, Guid robotId) + public async Task> InferActionSequence(Guid currentTaskId, bool ContextKnown, bool resourceLock, List dialogueTemp, Guid robotId) { List tempTask = new List(); List tempReplanedCompleteActionSeq = new List(); + if (dialogueTemp is null) + dialogueTemp = new(); // modify the existing plan with the candidates - return await InferActionSequence(currentTaskId, ContextKnown, resourceLock, DialogueTemp, robotId, tempTask, tempReplanedCompleteActionSeq); + return await InferActionSequence(currentTaskId, ContextKnown, resourceLock, dialogueTemp, robotId, tempTask, tempReplanedCompleteActionSeq); } /// /// Get predefined action sequence from knowledge graph given TaskId or provide partial or full replan. /// /// /// - /// + /// /// /// /// TaskModel - public async Task> InferActionSequence(Guid currentTaskId, bool ContextKnown, bool resourceLock, List DialogueTemp, Guid robotId, List candidatesToRePlan, List replanedCompleteActionSeq) + public async Task> InferActionSequence(Guid currentTaskId, + bool contextKnown, + bool resourceLock, + List dialogueTemp, + Guid robotId, + List candidatesToRePlan, + List replanedCompleteActionSeq) { + if (dialogueTemp == null) + throw new ArgumentException($"{nameof(dialogueTemp)} cannot be null", nameof(dialogueTemp)); + if (robotId == Guid.Empty) + throw new ArgumentException($"{nameof(robotId)} cannot be empty", nameof(robotId)); + //Load the robot asking for a plan from redis to middleware for infering action sequence. RobotModel robot = await _redisInterfaceClient.RobotGetByIdAsync(robotId); @@ -244,9 +257,9 @@ public async Task> InferActionSequence(Guid current List replanedCompleteActionSeqBK = new List(); replanedCompleteActionSeqBK.AddRange(replanedCompleteActionSeq); - robot.Questions.AddRange(DialogueTemp); //Append the questions-answers to the robot - - if (ContextKnown == false) + robot.Questions.AddRange(dialogueTemp); //Append the questions-answers to the robot + + if (contextKnown == false) { throw new NotImplementedException(); } @@ -281,7 +294,7 @@ public async Task> InferActionSequence(Guid current // according to the StackOverflow this should work, if not let's map objects in the list one by one List relations = await _redisInterfaceClient.GetRelationAsync(task, "EXTENDS"); //returns x and y --> taskId and ActionID - //Here is the list of the Ids of actions retrieved from the relation + List actionGuids = relations.Select(r => r.PointsTo.Id).ToList(); foreach (Guid actionId in actionGuids) //Iterate over the pre-defined action sequence of the knowledge redis graph. @@ -292,13 +305,12 @@ public async Task> InferActionSequence(Guid current // REPLAN ESTRATEGY B: change the failed actions to others and add the not failed actions. // REPLAN ESTRATEGY C: only add to action sequence new alternative actions and NOT succeded actions. // - ///////////////////////////////////////////////////////////////////////////////////////////////////////////// - - //Call to retrieve specific action + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ActionModel actionItem = await _redisInterfaceClient.ActionGetByIdAsync(actionId); - // Validate robot and netApp match. - validateRobotVsNetApp(robot, actionItem); + + + //await ValidateRobotVsNetApp(robot, actionItem); //If the partial or complete replan was not activated, add the action to the action sequence. --> Normal plan // PLAN ESTRATEGY A: @@ -310,7 +322,7 @@ public async Task> InferActionSequence(Guid current // Some partial or complete replan was requested. else { - //Check if the action is a candidatesToRePlan and later on find a better instance (netApp). + if (replanedCompleteActionSeq.Count == 0) { // Check if any of the candidatesToRePlan actions is the same to the old predefined action. diff --git a/src/TaskPlanner/TaskPlannerSpec.json b/src/TaskPlanner/TaskPlannerSpec.json index 0a828328..96a8cb08 100644 --- a/src/TaskPlanner/TaskPlannerSpec.json +++ b/src/TaskPlanner/TaskPlannerSpec.json @@ -171,6 +171,16 @@ "tags": [ "RePlan" ], + "parameters": [ + { + "name": "dryRun", + "in": "query", + "schema": { + "type": "boolean", + "default": false + } + } + ], "requestBody": { "content": { "application/json": { @@ -295,6 +305,10 @@ "type": "string", "format": "date-time", "readOnly": true + }, + "isError": { + "type": "boolean", + "readOnly": true } }, "additionalProperties": false @@ -434,6 +448,10 @@ "MinimumNumCores": { "type": "integer", "format": "int32" + }, + "OnboardedTime": { + "type": "string", + "format": "date-time" } }, "additionalProperties": false @@ -488,6 +506,9 @@ "description": { "type": "string", "nullable": true + }, + "enabled": { + "type": "boolean" } }, "additionalProperties": false From 155ceec0205728fb68e98329acb1356c14986c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bratu=C5=9B?= Date: Wed, 18 Jan 2023 13:43:11 +0100 Subject: [PATCH 14/16] Fixed required changes for the pull request --- src/Common/Models/TaskPlannerInputModel.cs | 10 +------ src/RedisInterface/Responses/GraphResponse.cs | 8 +----- .../Responses/NetAppsDetailsResponse.cs | 28 +++++++++---------- src/RedisInterface/Responses/RobotResponse.cs | 28 +++++++++---------- .../Responses/SimpleRelation.cs | 8 ++++++ 5 files changed, 38 insertions(+), 44 deletions(-) create mode 100644 src/RedisInterface/Responses/SimpleRelation.cs diff --git a/src/Common/Models/TaskPlannerInputModel.cs b/src/Common/Models/TaskPlannerInputModel.cs index 97b4e83b..ed12fcfb 100644 --- a/src/Common/Models/TaskPlannerInputModel.cs +++ b/src/Common/Models/TaskPlannerInputModel.cs @@ -28,15 +28,7 @@ public class TaskPlannerInputModel public bool IsValid() { - if ((RobotId == Guid.Empty) | (Id == Guid.Empty)) - { - return false; - } - else - { - return true; - } - + return RobotId != Guid.Empty && Id != Guid.Empty; } } } diff --git a/src/RedisInterface/Responses/GraphResponse.cs b/src/RedisInterface/Responses/GraphResponse.cs index a2c3d33c..92e4c93a 100644 --- a/src/RedisInterface/Responses/GraphResponse.cs +++ b/src/RedisInterface/Responses/GraphResponse.cs @@ -7,10 +7,4 @@ public class GraphResponse public List Entities { get; set; } public List Relations { get; set; } -} -public class SimpleRelation -{ - public Guid OriginatingId { get; set; } - public string RelationName { get; set; } - public Guid PointsToId { get; set; } -} +} \ No newline at end of file diff --git a/src/RedisInterface/Responses/NetAppsDetailsResponse.cs b/src/RedisInterface/Responses/NetAppsDetailsResponse.cs index 35e07eca..ce782259 100644 --- a/src/RedisInterface/Responses/NetAppsDetailsResponse.cs +++ b/src/RedisInterface/Responses/NetAppsDetailsResponse.cs @@ -4,30 +4,30 @@ namespace Middleware.RedisInterface.Responses { public record NetAppsDetailsResponse { - [JsonPropertyName("NetAppName")] - public string NetAppName { get; set; } + [JsonPropertyName("name")] + public string Name { get; set; } - [JsonPropertyName("NetAppFamily")] - public string NetAppFamily { get; set; } + [JsonPropertyName("family")] + public string Family { get; set; } - [JsonPropertyName("ROSVersion")] - public int ROSVersion { get; set; } + [JsonPropertyName("rosVersion")] + public int RosVersion { get; set; } - [JsonPropertyName("ROSDistro")] - public string ROSDistro { get; set; } + [JsonPropertyName("rosDistro")] + public string RosDistro { get; set; } - [JsonPropertyName("OnboardedTime")] + [JsonPropertyName("onboardedTime")] public DateTime? OnboardedTime { get; set; } public NetAppsDetailsResponse() { } - public NetAppsDetailsResponse(string netAppName, string netAppFamily, int rosVersion, string rosDistro , DateTime onboardedTime) + public NetAppsDetailsResponse(string name, string family, int rosVersion, string rosDistro , DateTime onboardedTime) { - NetAppName = netAppName; - NetAppFamily = netAppFamily; - ROSVersion = rosVersion; - ROSDistro = rosDistro; + Name = name; + Family = family; + RosVersion = rosVersion; + RosDistro = rosDistro; OnboardedTime = onboardedTime; } diff --git a/src/RedisInterface/Responses/RobotResponse.cs b/src/RedisInterface/Responses/RobotResponse.cs index 649d25dc..c6105f85 100644 --- a/src/RedisInterface/Responses/RobotResponse.cs +++ b/src/RedisInterface/Responses/RobotResponse.cs @@ -4,11 +4,11 @@ namespace Middleware.RedisInterface.Responses { public record RobotResponse { - [JsonPropertyName("RobotId")] - public Guid RobotId { get; set; } + [JsonPropertyName("Id")] + public Guid Id { get; set; } - [JsonPropertyName("RobotName")] - public string RobotName { get; set; } + [JsonPropertyName("Name")] + public string Name { get; set; } [JsonPropertyName("Status")] public string Status { get; set; } @@ -16,27 +16,27 @@ public record RobotResponse [JsonPropertyName("OnboardedTime")] public DateTime? OnboardedTime { get; set; } - [JsonPropertyName("ROSVersion")] - public int ROSVersion { get; set; } + [JsonPropertyName("rosVersion")] + public int RosVersion { get; set; } - [JsonPropertyName("ROSDistro")] - public string ROSDistro { get; set; } + [JsonPropertyName("rosDistro")] + public string RosDistro { get; set; } - [JsonPropertyName("Manufacturer")] + [JsonPropertyName("manufacturer")] public string Manufacturer { get; set; } public RobotResponse() { } - public RobotResponse(Guid robotId, string robotName, string status, DateTime onboardedTime, int rosVersion,string rosDistro, string manufacturer) + public RobotResponse(Guid id, string name, string status, DateTime onboardedTime, int rosVersion,string rosDistro, string manufacturer) { - RobotId = robotId; - RobotName = robotName; + Id = id; + Name = name; Status = status; OnboardedTime = onboardedTime; - ROSVersion = rosVersion; - ROSDistro = rosDistro; + RosVersion = rosVersion; + RosDistro = rosDistro; Manufacturer = manufacturer; } diff --git a/src/RedisInterface/Responses/SimpleRelation.cs b/src/RedisInterface/Responses/SimpleRelation.cs new file mode 100644 index 00000000..9c5d9862 --- /dev/null +++ b/src/RedisInterface/Responses/SimpleRelation.cs @@ -0,0 +1,8 @@ +namespace Middleware.RedisInterface.Responses; + +public class SimpleRelation +{ + public Guid OriginatingId { get; set; } + public string RelationName { get; set; } + public Guid PointsToId { get; set; } +} From f9442e9cc4f1255655d946cc4b23b12a9107c384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bratu=C5=9B?= Date: Wed, 18 Jan 2023 13:44:17 +0100 Subject: [PATCH 15/16] Updated RedisInterface spec --- src/RedisInterface/RedisInterfaceSpec.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/RedisInterface/RedisInterfaceSpec.json b/src/RedisInterface/RedisInterfaceSpec.json index 00099dcb..493aeb7e 100644 --- a/src/RedisInterface/RedisInterfaceSpec.json +++ b/src/RedisInterface/RedisInterfaceSpec.json @@ -9369,23 +9369,23 @@ "NetAppsDetailsResponse": { "type": "object", "properties": { - "NetAppName": { + "name": { "type": "string", "nullable": true }, - "NetAppFamily": { + "family": { "type": "string", "nullable": true }, - "ROSVersion": { + "rosVersion": { "type": "integer", "format": "int32" }, - "ROSDistro": { + "rosDistro": { "type": "string", "nullable": true }, - "OnboardedTime": { + "onboardedTime": { "type": "string", "format": "date-time", "nullable": true @@ -9740,11 +9740,11 @@ "RobotResponse": { "type": "object", "properties": { - "RobotId": { + "Id": { "type": "string", "format": "uuid" }, - "RobotName": { + "Name": { "type": "string", "nullable": true }, @@ -9757,15 +9757,15 @@ "format": "date-time", "nullable": true }, - "ROSVersion": { + "rosVersion": { "type": "integer", "format": "int32" }, - "ROSDistro": { + "rosDistro": { "type": "string", "nullable": true }, - "Manufacturer": { + "manufacturer": { "type": "string", "nullable": true } From 3726dfa64cde6fb8fcfb61f65ca77084e9081e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Bratu=C5=9B?= Date: Wed, 18 Jan 2023 15:42:08 +0100 Subject: [PATCH 16/16] Changed default values for parameters add error messages --- src/Common/Models/TaskPlannerInputModel.cs | 13 +++++++++---- src/TaskPlanner/Controllers/PlanController.cs | 4 ++++ src/TaskPlanner/Services/ActionPlanner.cs | 4 +--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Common/Models/TaskPlannerInputModel.cs b/src/Common/Models/TaskPlannerInputModel.cs index ed12fcfb..81e1b8b8 100644 --- a/src/Common/Models/TaskPlannerInputModel.cs +++ b/src/Common/Models/TaskPlannerInputModel.cs @@ -9,8 +9,10 @@ public class TaskPlannerInputModel public Guid RobotId { get; set; } [JsonPropertyName("LockResourceReUse")] - public bool LockResourceReUse { get; set; } - + public bool LockResourceReUse { get; set; } //TODO: check only the instances that are avialable in the local middleware + /// + /// only change the instance placement in the existing plan during a replan + /// [JsonPropertyName("ReplanActionPlannerLocked")] public bool ReplanActionPlannerLocked { get; set; } @@ -19,9 +21,12 @@ public class TaskPlannerInputModel [JsonPropertyName("TaskDescription")] public String TaskDescription { get; set; } - + + /// + /// Use the hardcoded action plan if true, use the semantic planning if false + /// [JsonPropertyName("ContextKnown")] - public bool ContextKnown { get; set; } + public bool ContextKnown { get; set; } = true; [JsonPropertyName("Questions")] public List Questions { get; set; } diff --git a/src/TaskPlanner/Controllers/PlanController.cs b/src/TaskPlanner/Controllers/PlanController.cs index 3129bc14..86ef5475 100644 --- a/src/TaskPlanner/Controllers/PlanController.cs +++ b/src/TaskPlanner/Controllers/PlanController.cs @@ -42,6 +42,10 @@ public async Task> GetPlan([FromBody] TaskPlannerInputMo return BadRequest("Parameters were not specified."); } + if (inputModel.ContextKnown == false) + { + return BadRequest(new ApiResponse((int)HttpStatusCode.BadRequest, "Semmantic planning is not yet available.")); + } if (inputModel.IsValid() == false) { return BadRequest(new ApiResponse((int)HttpStatusCode.BadRequest, "Parameters were not specified or wrongly specified.")); diff --git a/src/TaskPlanner/Services/ActionPlanner.cs b/src/TaskPlanner/Services/ActionPlanner.cs index c2378179..c8ee34e8 100644 --- a/src/TaskPlanner/Services/ActionPlanner.cs +++ b/src/TaskPlanner/Services/ActionPlanner.cs @@ -308,9 +308,7 @@ public async Task> InferActionSequence(Guid current ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ActionModel actionItem = await _redisInterfaceClient.ActionGetByIdAsync(actionId); - - - //await ValidateRobotVsNetApp(robot, actionItem); + await ValidateRobotVsNetApp(robot, actionItem); //If the partial or complete replan was not activated, add the action to the action sequence. --> Normal plan // PLAN ESTRATEGY A: