Initial commit
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RobotNet10.RobotApp.Data;
|
||||
using RobotNet10.RobotApp.Shared.DockStation;
|
||||
using RobotNet10.Shared.Enum;
|
||||
using RobotNet10.Shared.Numbers;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace RobotNet10.RobotApp.Controllers;
|
||||
|
||||
[Route("api/dock-station-config")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class DockStationConfigController(ApplicationDbContext dbContext) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<List<DockStationConfigSummaryDto>>> GetAll()
|
||||
{
|
||||
var configs = await dbContext.DockStationConfigs
|
||||
.Include(d => d.MarkerEntries)
|
||||
.OrderByDescending(d => d.UpdatedAt)
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(configs.Select(MapToSummaryDto).ToList());
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
public async Task<ActionResult<DockStationConfigDto>> GetById(Guid id)
|
||||
{
|
||||
var config = await dbContext.DockStationConfigs
|
||||
.Include(d => d.MarkerEntries)
|
||||
.FirstOrDefaultAsync(d => d.Id == id);
|
||||
|
||||
if (config is null) return NotFound();
|
||||
return Ok(MapToDto(config));
|
||||
}
|
||||
|
||||
[HttpGet("station/{stationId}")]
|
||||
public async Task<ActionResult<DockStationConfigDto>> GetByStationId(string stationId)
|
||||
{
|
||||
var config = await dbContext.DockStationConfigs
|
||||
.Include(d => d.MarkerEntries)
|
||||
.FirstOrDefaultAsync(d => d.StationId == stationId);
|
||||
|
||||
if (config is null) return NotFound();
|
||||
return Ok(MapToDto(config));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<DockStationConfigDto>> Create(
|
||||
[FromBody] CreateDockStationConfigRequest request)
|
||||
{
|
||||
if (await dbContext.DockStationConfigs.AnyAsync(d => d.StationId == request.StationId))
|
||||
return BadRequest($"StationId '{request.StationId}' already exists.");
|
||||
|
||||
var entity = new DockStationConfig
|
||||
{
|
||||
StationId = request.StationId,
|
||||
ConfigName = request.ConfigName ?? string.Empty,
|
||||
Description = request.Description ?? string.Empty,
|
||||
X = request.X,
|
||||
Y = request.Y,
|
||||
Yaw = request.Yaw,
|
||||
Width = request.Width,
|
||||
Length = request.Length,
|
||||
IsActive = request.IsActive,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
UpdatedAt = DateTime.UtcNow,
|
||||
MarkerEntries = request.MarkerEntries.Select(MapFromEntryDto).ToList()
|
||||
};
|
||||
|
||||
dbContext.DockStationConfigs.Add(entity);
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
return CreatedAtAction(nameof(GetById), new { id = entity.Id }, MapToDto(entity));
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
public async Task<ActionResult<DockStationConfigDto>> Update(
|
||||
Guid id, [FromBody] UpdateDockStationConfigRequest request)
|
||||
{
|
||||
var entity = await dbContext.DockStationConfigs
|
||||
.Include(d => d.MarkerEntries)
|
||||
.FirstOrDefaultAsync(d => d.Id == id);
|
||||
|
||||
if (entity is null) return NotFound();
|
||||
|
||||
if (request.StationId is not null)
|
||||
{
|
||||
if (request.StationId != entity.StationId &&
|
||||
await dbContext.DockStationConfigs.AnyAsync(d => d.StationId == request.StationId))
|
||||
return BadRequest($"StationId '{request.StationId}' already exists.");
|
||||
entity.StationId = request.StationId;
|
||||
}
|
||||
if (request.ConfigName is not null) entity.ConfigName = request.ConfigName;
|
||||
if (request.Description is not null) entity.Description = request.Description;
|
||||
if (request.X.HasValue) entity.X = request.X.Value;
|
||||
if (request.Y.HasValue) entity.Y = request.Y.Value;
|
||||
if (request.Yaw.HasValue) entity.Yaw = request.Yaw.Value;
|
||||
if (request.Width.HasValue) entity.Width = request.Width.Value;
|
||||
if (request.Length.HasValue) entity.Length = request.Length.Value;
|
||||
if (request.IsActive.HasValue) entity.IsActive = request.IsActive.Value;
|
||||
entity.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
if (request.MarkerEntries is not null)
|
||||
{
|
||||
dbContext.DockStationMarkerEntries.RemoveRange(entity.MarkerEntries);
|
||||
entity.MarkerEntries = request.MarkerEntries.Select(MapFromEntryDto).ToList();
|
||||
}
|
||||
|
||||
await dbContext.SaveChangesAsync();
|
||||
return Ok(MapToDto(entity));
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var entity = await dbContext.DockStationConfigs.FindAsync(id);
|
||||
if (entity is null) return NotFound();
|
||||
|
||||
dbContext.DockStationConfigs.Remove(entity);
|
||||
await dbContext.SaveChangesAsync();
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
#region Mapping Helpers
|
||||
|
||||
private static DockStationConfigDto MapToDto(DockStationConfig entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
StationId = entity.StationId,
|
||||
ConfigName = entity.ConfigName,
|
||||
Description = entity.Description,
|
||||
X = entity.X,
|
||||
Y = entity.Y,
|
||||
Yaw = entity.Yaw,
|
||||
Width = entity.Width,
|
||||
Length = entity.Length,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
UpdatedAt = entity.UpdatedAt,
|
||||
IsActive = entity.IsActive,
|
||||
MarkerEntries = entity.MarkerEntries?.Select(MapToEntryDto).ToList() ?? []
|
||||
};
|
||||
|
||||
private static DockStationConfigSummaryDto MapToSummaryDto(DockStationConfig entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
StationId = entity.StationId,
|
||||
ConfigName = entity.ConfigName,
|
||||
Description = entity.Description,
|
||||
IsActive = entity.IsActive,
|
||||
MarkerEntryCount = entity.MarkerEntries?.Count ?? 0,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
UpdatedAt = entity.UpdatedAt
|
||||
};
|
||||
|
||||
private static DockStationMarkerEntryDto MapToEntryDto(DockStationMarkerEntry entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
MarkerId = entity.MarkerId,
|
||||
Type = (MarkerType)entity.Type,
|
||||
Priority = entity.Priority,
|
||||
DeviceId = entity.DeviceId,
|
||||
Code = entity.Code,
|
||||
ReferencePoints = DeserializeReferencePoints(entity.ReferencePointsJson)
|
||||
};
|
||||
|
||||
private static DockStationMarkerEntry MapFromEntryDto(DockStationMarkerEntryDto dto) => new()
|
||||
{
|
||||
MarkerId = dto.MarkerId,
|
||||
Type = (int)dto.Type,
|
||||
Priority = dto.Priority,
|
||||
DeviceId = dto.DeviceId ?? string.Empty,
|
||||
Code = dto.Code ?? string.Empty,
|
||||
ReferencePointsJson = JsonSerializer.Serialize(dto.ReferencePoints ?? [])
|
||||
};
|
||||
|
||||
private static List<Vector2> DeserializeReferencePoints(string? json)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json)) return [];
|
||||
try { return JsonSerializer.Deserialize<List<Vector2>>(json) ?? []; }
|
||||
catch { return []; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace RobotNet10.RobotApp.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class LogsManagerController(Services.Logger<LogsManagerController> Logger) : ControllerBase
|
||||
{
|
||||
private readonly string LoggerDirectory = Path.Combine(AppContext.BaseDirectory, "logs");
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<string>> GetLogs([FromQuery(Name = "date")] DateTime date)
|
||||
{
|
||||
string temp = "";
|
||||
try
|
||||
{
|
||||
string fileName = $"{date:yyyy-MM-dd}.log";
|
||||
string path = Path.Combine(LoggerDirectory, fileName);
|
||||
if (!Path.GetFullPath(path).StartsWith(Path.GetFullPath(LoggerDirectory)))
|
||||
{
|
||||
Logger.Warning($"GetLogs: Invalid path detected.");
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!System.IO.File.Exists(path))
|
||||
{
|
||||
Logger.Warning($"GetLogs: Log file not found for date {date:d} - {path}.");
|
||||
return [];
|
||||
}
|
||||
|
||||
temp = Path.Combine(LoggerDirectory, $"{Guid.NewGuid()}.log");
|
||||
System.IO.File.Copy(path, temp);
|
||||
|
||||
return await System.IO.File.ReadAllLinesAsync(temp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Warning($"GetLogs: System error occurred - {ex.Message}");
|
||||
return [];
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (System.IO.File.Exists(temp)) System.IO.File.Delete(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RobotNet10.RobotApp.Client.Shared.SLAM;
|
||||
using RobotNet10.RobotApp.Shared;
|
||||
using RobotNet10.RobotApp.SLAM;
|
||||
|
||||
namespace RobotNet10.RobotApp.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// API Controller for map management operations
|
||||
/// </summary>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class MapsController(ISLAMService slamService, ILogger<MapsController> logger) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Get map info by name
|
||||
/// </summary>
|
||||
/// <param name="mapName">Name of the map</param>
|
||||
/// <returns>MapInfoDto if found, NotFound otherwise</returns>
|
||||
[HttpGet("{mapName}")]
|
||||
public ActionResult<MapInfoDto> GetMapInfo(string mapName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mapInfo = slamService.GetMapInfo(mapName);
|
||||
if (mapInfo == null)
|
||||
{
|
||||
logger.LogWarning("MapsController: Map not found: {MapName}", mapName);
|
||||
return NotFound($"Map '{mapName}' not found");
|
||||
}
|
||||
|
||||
return Ok(MapMapInfoToDto(mapInfo));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "MapsController: Failed to get map info: {MapName}", mapName);
|
||||
return StatusCode(500, "Failed to get map info");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get map image by name
|
||||
/// </summary>
|
||||
/// <param name="mapName">Name of the map</param>
|
||||
/// <returns>PNG image file</returns>
|
||||
[HttpGet("{mapName}/image")]
|
||||
public IActionResult GetMapImage(string mapName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var imagePath = slamService.GetMapImagePath(mapName);
|
||||
if (imagePath == null)
|
||||
{
|
||||
logger.LogWarning("MapsController: Map image not found: {MapName}", mapName);
|
||||
return NotFound($"Map image for '{mapName}' not found");
|
||||
}
|
||||
|
||||
var contentType = imagePath.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
|
||||
? "image/png"
|
||||
: "image/jpeg";
|
||||
|
||||
var fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
return File(fileStream, contentType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "MapsController: Failed to get map image: {MapName}", mapName);
|
||||
return StatusCode(500, "Failed to get map image");
|
||||
}
|
||||
}
|
||||
|
||||
private static MapInfoDto MapMapInfoToDto(MapInfo mapInfo)
|
||||
{
|
||||
return new MapInfoDto
|
||||
{
|
||||
Name = mapInfo.Name,
|
||||
CreatedDate = mapInfo.CreatedDate,
|
||||
Resolution = mapInfo.Resolution,
|
||||
Width = mapInfo.Size.Width,
|
||||
Height = mapInfo.Size.Height,
|
||||
TrajectoryNodeCount = mapInfo.TrajectoryNodeCount,
|
||||
OriginX = mapInfo.Origin.Position.X,
|
||||
OriginY = mapInfo.Origin.Position.Y,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user