Skip to content

Commit

Permalink
Move refactored functions to separate service
Browse files Browse the repository at this point in the history
  • Loading branch information
aeshub committed Oct 26, 2023
1 parent 5310d01 commit 5dbbbb9
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 136 deletions.
32 changes: 15 additions & 17 deletions backend/api/Controllers/MissionSchedulingController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Api.Controllers.Models;
using Api.Database.Models;
using Api.Services;
using Api.Services.ActionServices;
using Api.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -18,6 +19,7 @@ public class MissionSchedulingController : ControllerBase
private readonly IMapService _mapService;
private readonly IMissionDefinitionService _missionDefinitionService;
private readonly IMissionRunService _missionRunService;
private readonly IMissionSchedulingService _missionSchedulingService;
private readonly IRobotService _robotService;
private readonly ISourceService _sourceService;
private readonly IStidService _stidService;
Expand All @@ -32,7 +34,8 @@ public MissionSchedulingController(
ILogger<MissionSchedulingController> logger,
IMapService mapService,
IStidService stidService,
ISourceService sourceService
ISourceService sourceService,
IMissionSchedulingService missionSchedulingService
)
{
_missionDefinitionService = missionDefinitionService;
Expand All @@ -44,6 +47,8 @@ ISourceService sourceService
_mapService = mapService;
_stidService = stidService;
_sourceService = sourceService;
_missionDefinitionService = missionDefinitionService;
_missionSchedulingService = missionSchedulingService;
_logger = logger;
}

Expand Down Expand Up @@ -194,7 +199,8 @@ [FromBody] ScheduledMissionQuery scheduledMissionQuery
{
source = new Source
{
SourceId = $"{echoMission.Id}", Type = MissionSourceType.Echo
SourceId = $"{echoMission.Id}",
Type = MissionSourceType.Echo
};
}
else
Expand Down Expand Up @@ -269,31 +275,23 @@ [FromBody] CustomMissionQuery customMissionQuery
)
{
var robot = await _robotService.ReadById(customMissionQuery.RobotId);
if (robot is null)
{
return NotFound($"Could not find robot with id {customMissionQuery.RobotId}");
}
if (robot is null) { return NotFound($"Could not find robot with id {customMissionQuery.RobotId}"); }

var installationResults = await _echoService.GetEchoPlantInfos();
if (installationResults == null)
{
return NotFound("Unable to retrieve plant information from Echo");
}
if (installationResults == null) { return NotFound("Unable to retrieve plant information from Echo"); }

var installationResult = installationResults.FirstOrDefault(installation => installation.PlantCode.ToUpperInvariant() == customMissionQuery.InstallationCode.ToUpperInvariant());
if (installationResult == null)
{
return NotFound($"Could not find installation with id {customMissionQuery.InstallationCode}");
}
var installationResult =
installationResults.FirstOrDefault(installation => installation.PlantCode.ToUpperInvariant() == customMissionQuery.InstallationCode.ToUpperInvariant());
if (installationResult == null) { return NotFound($"Could not find installation with id {customMissionQuery.InstallationCode}"); }

var missionTasks = customMissionQuery.Tasks.Select(task => new MissionTask(task)).ToList();

MissionDefinition? customMissionDefinition;
try { customMissionDefinition = await _missionDefinitionService.FindExistingOrCreateCustomMissionDefinition(customMissionQuery, missionTasks); }
try { customMissionDefinition = await _missionSchedulingService.FindExistingOrCreateCustomMissionDefinition(customMissionQuery, missionTasks); }
catch (SourceException e) { return StatusCode(StatusCodes.Status502BadGateway, e.Message); }

MissionRun? newMissionRun;
try { newMissionRun = await _customMissionService.QueueCustomMissionRun(customMissionQuery, customMissionDefinition.Id, robot.Id, missionTasks); }
try { newMissionRun = await _missionSchedulingService.QueueCustomMissionRun(customMissionQuery, customMissionDefinition.Id, robot.Id, missionTasks); }
catch (Exception e) when (e is RobotNotFoundException or MissionNotFoundException) { return NotFound(e.Message); }

return CreatedAtAction(nameof(Create), new
Expand Down
8 changes: 7 additions & 1 deletion backend/api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Api.Mqtt;
using Api.Options;
using Api.Services;
using Api.Services.ActionServices;
using Azure.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
Expand Down Expand Up @@ -37,7 +38,7 @@
}
else
{
Console.WriteLine($"NO KEYVAULT IN CONFIG");
Console.WriteLine("NO KEYVAULT IN CONFIG");
}
}

Expand All @@ -62,15 +63,20 @@
builder.Services.AddScoped<IDefaultLocalizationPoseService, DefaultLocalizationPoseService>();
builder.Services.AddScoped<ISourceService, SourceService>();
builder.Services.AddScoped<IRobotModelService, RobotModelService>();
builder.Services.AddScoped<IMissionSchedulingService, MissionSchedulingService>();

bool useInMemoryDatabase = builder.Configuration
.GetSection("Database")
.GetValue<bool>("UseInMemoryDatabase");

if (useInMemoryDatabase)
{
builder.Services.AddScoped<ITimeseriesService, TimeseriesServiceSqlLite>();
}
else
{
builder.Services.AddScoped<ITimeseriesService, TimeseriesService>();
}
builder.Services.AddScoped<RobotController>();
builder.Services.AddScoped<ICustomMissionService, CustomMissionService>();

Expand Down
134 changes: 134 additions & 0 deletions backend/api/Services/ActionServices/MissionSchedulingService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using Api.Controllers.Models;
using Api.Database.Models;
using Api.Utilities;
namespace Api.Services.ActionServices
{
public interface IMissionSchedulingService
{
public Task<MissionDefinition> FindExistingOrCreateCustomMissionDefinition(CustomMissionQuery customMissionQuery, List<MissionTask> missionTasks);

public Task<MissionRun> QueueCustomMissionRun(CustomMissionQuery customMissionQuery, string missionDefinitionId, string robotId, IList<MissionTask> missionTasks);
}

public class MissionSchedulingService : IMissionSchedulingService
{
private readonly IAreaService _areaService;
private readonly ICustomMissionService _customMissionService;
private readonly ILogger<MissionSchedulingService> _logger;
private readonly IMapService _mapService;
private readonly IMissionDefinitionService _missionDefinitionService;
private readonly IMissionRunService _missionRunService;
private readonly IRobotService _robotService;
private readonly ISourceService _sourceService;

public MissionSchedulingService(
ILogger<MissionSchedulingService> logger,
ICustomMissionService customMissionService,
IAreaService areaService,
ISourceService sourceService,
IMissionDefinitionService missionDefinitionService,
IMissionRunService missionRunService,
IRobotService robotService,
IMapService mapService
)
{
_logger = logger;
_customMissionService = customMissionService;
_areaService = areaService;
_sourceService = sourceService;
_missionDefinitionService = missionDefinitionService;
_missionRunService = missionRunService;
_robotService = robotService;
_mapService = mapService;
}

public async Task<MissionDefinition> FindExistingOrCreateCustomMissionDefinition(CustomMissionQuery customMissionQuery, List<MissionTask> missionTasks)
{
Area? area = null;
if (customMissionQuery.AreaName != null) { area = await _areaService.ReadByInstallationAndName(customMissionQuery.InstallationCode, customMissionQuery.AreaName); }

var source = await _sourceService.CheckForExistingCustomSource(missionTasks);

MissionDefinition? existingMissionDefinition = null;
if (source == null)
{
try
{
string sourceUrl = await _customMissionService.UploadSource(missionTasks);
source = new Source
{
SourceId = sourceUrl,
Type = MissionSourceType.Custom
};
}
catch (Exception e)
{
{
string errorMessage = $"Unable to upload source for mission {customMissionQuery.Name}";
_logger.LogError(e, "{Message}", errorMessage);
throw new SourceException(errorMessage);
}
}
}
else
{
var missionDefinitions = await _missionDefinitionService.ReadBySourceId(source.SourceId);
if (missionDefinitions.Count > 0) { existingMissionDefinition = missionDefinitions.First(); }
}

var customMissionDefinition = existingMissionDefinition ?? new MissionDefinition
{
Id = Guid.NewGuid().ToString(),
Source = source,
Name = customMissionQuery.Name,
InspectionFrequency = customMissionQuery.InspectionFrequency,
InstallationCode = customMissionQuery.InstallationCode,
Area = area
};

if (existingMissionDefinition == null) { await _missionDefinitionService.Create(customMissionDefinition); }

return customMissionDefinition;
}

public async Task<MissionRun> QueueCustomMissionRun(CustomMissionQuery customMissionQuery, string missionDefinitionId, string robotId, IList<MissionTask> missionTasks)
{
var missionDefinition = await _missionDefinitionService.ReadById(missionDefinitionId);
if (missionDefinition is null)
{
string errorMessage = $"The mission definition with ID {missionDefinition} could not be found";
_logger.LogError("{Message}", errorMessage);
throw new MissionNotFoundException(errorMessage);
}

var robot = await _robotService.ReadById(robotId);
if (robot is null)
{
string errorMessage = $"The robot with ID {robotId} could not be found";
_logger.LogError("{Message}", errorMessage);
throw new RobotNotFoundException(errorMessage);
}

var scheduledMission = new MissionRun
{
Name = customMissionQuery.Name,
Description = customMissionQuery.Description,
MissionId = missionDefinition.Id,
Comment = customMissionQuery.Comment,
Robot = robot,
Status = MissionStatus.Pending,
DesiredStartTime = customMissionQuery.DesiredStartTime ?? DateTimeOffset.UtcNow,
Tasks = missionTasks,
InstallationCode = customMissionQuery.InstallationCode,
Area = missionDefinition.Area,
Map = new MapMetadata()
};

await _mapService.AssignMapToMission(scheduledMission);

if (scheduledMission.Tasks.Any()) { scheduledMission.CalculateEstimatedDuration(); }

return await _missionRunService.Create(scheduledMission);
}
}
}
62 changes: 1 addition & 61 deletions backend/api/Services/CustomMissionService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using Api.Controllers.Models;
using Api.Database.Models;
using Api.Options;
using Api.Utilities;
using Microsoft.Extensions.Options;
namespace Api.Services
{
Expand All @@ -15,36 +13,18 @@ public interface ICustomMissionService

Task<List<MissionTask>?> GetMissionTasksFromSourceId(string id);

public Task<MissionRun> QueueCustomMissionRun(CustomMissionQuery customMissionQuery, string missionDefinitionId, string robotId, IList<MissionTask> missionTasks);

string CalculateHashFromTasks(IList<MissionTask> tasks);
}

public class CustomMissionService : ICustomMissionService
{
private readonly IBlobService _blobService;
private readonly ILogger<CustomMissionService> _logger;
private readonly IMapService _mapService;
private readonly IMissionDefinitionService _missionDefinitionService;
private readonly IMissionRunService _missionRunService;
private readonly IRobotService _robotService;
private readonly IOptions<StorageOptions> _storageOptions;

public CustomMissionService(
ILogger<CustomMissionService> logger,
IOptions<StorageOptions> storageOptions,
IBlobService blobService,
IMissionDefinitionService missionDefinitionService,
IMissionRunService missionRunService,
IRobotService robotService, IMapService mapService)
public CustomMissionService(IOptions<StorageOptions> storageOptions, IBlobService blobService)
{
_logger = logger;
_storageOptions = storageOptions;
_blobService = blobService;
_missionDefinitionService = missionDefinitionService;
_missionRunService = missionRunService;
_robotService = robotService;
_mapService = mapService;
}

public async Task<string> UploadSource(List<MissionTask> tasks)
Expand Down Expand Up @@ -90,45 +70,5 @@ public string CalculateHashFromTasks(IList<MissionTask> tasks)
byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes(json));
return BitConverter.ToString(hash).Replace("-", "", StringComparison.CurrentCulture).ToUpperInvariant();
}

public async Task<MissionRun> QueueCustomMissionRun(CustomMissionQuery customMissionQuery, string missionDefinitionId, string robotId, IList<MissionTask> missionTasks)
{
var missionDefinition = await _missionDefinitionService.ReadById(missionDefinitionId);
if (missionDefinition is null)
{
string errorMessage = $"The mission definition with ID {missionDefinition} could not be found";
_logger.LogError("{Message}", errorMessage);
throw new MissionNotFoundException(errorMessage);
}

var robot = await _robotService.ReadById(robotId);
if (robot is null)
{
string errorMessage = $"The robot with ID {robotId} could not be found";
_logger.LogError("{Message}", errorMessage);
throw new RobotNotFoundException(errorMessage);
}

var scheduledMission = new MissionRun
{
Name = customMissionQuery.Name,
Description = customMissionQuery.Description,
MissionId = missionDefinition.Id,
Comment = customMissionQuery.Comment,
Robot = robot,
Status = MissionStatus.Pending,
DesiredStartTime = customMissionQuery.DesiredStartTime ?? DateTimeOffset.UtcNow,
Tasks = missionTasks,
InstallationCode = customMissionQuery.InstallationCode,
Area = missionDefinition.Area,
Map = new MapMetadata()
};

await _mapService.AssignMapToMission(scheduledMission);

if (scheduledMission.Tasks.Any()) { scheduledMission.CalculateEstimatedDuration(); }

return await _missionRunService.Create(scheduledMission);
}
}
}
Loading

0 comments on commit 5dbbbb9

Please sign in to comment.