first commit -push
This commit is contained in:
108
RobotNet.MapManager/Services/LoggerController.cs
Normal file
108
RobotNet.MapManager/Services/LoggerController.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
namespace RobotNet.MapManager.Services;
|
||||
|
||||
public class LoggerController<T>(ILogger<T> Logger)
|
||||
{
|
||||
public event Action? LoggerUpdate;
|
||||
public void Write(string message, LogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case LogLevel.Trace:
|
||||
Logger.LogTrace("{mes}", message);
|
||||
break;
|
||||
case LogLevel.Debug:
|
||||
Logger.LogDebug("{mes}", message);
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
Logger.LogInformation("{mes}", message);
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
Logger.LogWarning("{mes}", message);
|
||||
break;
|
||||
case LogLevel.Error:
|
||||
Logger.LogError("{mes}", message);
|
||||
break;
|
||||
case LogLevel.Critical:
|
||||
Logger.LogCritical("{mes}", message);
|
||||
break;
|
||||
}
|
||||
LoggerUpdate?.Invoke();
|
||||
}
|
||||
|
||||
public void Write(string message)
|
||||
{
|
||||
Write(message, LogLevel.Information);
|
||||
}
|
||||
|
||||
public async Task WriteAsync(string message)
|
||||
{
|
||||
var write = Task.Run(() => Write(message));
|
||||
await write.WaitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public async Task TraceAsync(string message)
|
||||
{
|
||||
var write = Task.Run(() => Write(message, LogLevel.Trace));
|
||||
await write.WaitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public async Task DebugAsync(string message)
|
||||
{
|
||||
var write = Task.Run(() => Write(message, LogLevel.Debug));
|
||||
await write.WaitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public async Task InfoAsync(string message)
|
||||
{
|
||||
var write = Task.Run(() => Write(message, LogLevel.Information));
|
||||
await write.WaitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public async Task WarningAsync(string message)
|
||||
{
|
||||
var write = Task.Run(() => Write(message, LogLevel.Warning));
|
||||
await write.WaitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public async Task ErrorAsync(string message)
|
||||
{
|
||||
var write = Task.Run(() => Write(message, LogLevel.Error));
|
||||
await write.WaitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public async Task CriticalAsync(string message)
|
||||
{
|
||||
var write = Task.Run(() => Write(message, LogLevel.Critical));
|
||||
await write.WaitAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public void Trace(string message)
|
||||
{
|
||||
Write(message, LogLevel.Trace);
|
||||
}
|
||||
|
||||
public void Debug(string message)
|
||||
{
|
||||
Write(message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
public void Info(string message)
|
||||
{
|
||||
Write(message, LogLevel.Information);
|
||||
}
|
||||
|
||||
public void Warning(string message)
|
||||
{
|
||||
Write(message, LogLevel.Warning);
|
||||
}
|
||||
|
||||
public void Error(string message)
|
||||
{
|
||||
Write(message, LogLevel.Error);
|
||||
}
|
||||
|
||||
public void Critical(string message)
|
||||
{
|
||||
Write(message, LogLevel.Critical);
|
||||
}
|
||||
}
|
||||
140
RobotNet.MapManager/Services/MapEditorStorageRepository.cs
Normal file
140
RobotNet.MapManager/Services/MapEditorStorageRepository.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using Minio;
|
||||
using Minio.DataModel.Args;
|
||||
using Minio.Exceptions;
|
||||
|
||||
namespace RobotNet.MapManager.Services;
|
||||
|
||||
public class MapEditorStorageRepository
|
||||
{
|
||||
private class MinioOption
|
||||
{
|
||||
public bool UsingLocal { get; set; }
|
||||
public string? Endpoint { get; set; }
|
||||
public string? User { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public string? Bucket { get; set; }
|
||||
}
|
||||
|
||||
private readonly IMinioClient MinioClient;
|
||||
private readonly MinioOption MinioOptions = new();
|
||||
public MapEditorStorageRepository(IConfiguration configuration)
|
||||
{
|
||||
configuration.Bind("MinIO", MinioOptions);
|
||||
MinioClient = new MinioClient()
|
||||
.WithEndpoint(MinioOptions.Endpoint)
|
||||
.WithCredentials(MinioOptions.User, MinioOptions.Password)
|
||||
.WithSSL(false)
|
||||
.Build();
|
||||
}
|
||||
|
||||
public async Task<(bool, string)> UploadAsync(string path, string objectName, Stream data, long size, string contentType, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!MinioOptions.UsingLocal)
|
||||
{
|
||||
var beArgs = new BucketExistsArgs().WithBucket(MinioOptions.Bucket);
|
||||
bool found = await MinioClient.BucketExistsAsync(beArgs, cancellationToken).ConfigureAwait(false);
|
||||
if (!found)
|
||||
{
|
||||
var mbArgs = new MakeBucketArgs()
|
||||
.WithBucket(MinioOptions.Bucket);
|
||||
await MinioClient.MakeBucketAsync(mbArgs, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
var getListBucketsTask = await MinioClient.ListBucketsAsync(cancellationToken);
|
||||
var putObjectArgs = new PutObjectArgs()
|
||||
.WithBucket(MinioOptions.Bucket)
|
||||
.WithObject($"{path}/{objectName}")
|
||||
.WithObjectSize(size)
|
||||
.WithStreamData(data)
|
||||
.WithContentType(contentType);
|
||||
await MinioClient.PutObjectAsync(putObjectArgs, cancellationToken).ConfigureAwait(false);
|
||||
return (true, "");
|
||||
}
|
||||
|
||||
var mapImageFolder = string.IsNullOrEmpty(MinioOptions.Bucket) ? "MapImages" : MinioOptions.Bucket;
|
||||
if (!Directory.Exists(mapImageFolder)) Directory.CreateDirectory(mapImageFolder);
|
||||
var folderPath = Path.Combine(mapImageFolder, path);
|
||||
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
|
||||
var pathLocal = Path.Combine(folderPath, $"{objectName}.png");
|
||||
if (File.Exists($"{pathLocal}.bk")) File.Delete($"{pathLocal}.bk");
|
||||
if (File.Exists(pathLocal)) File.Move(pathLocal, $"{pathLocal}.bk");
|
||||
using (Stream fileStream = new FileStream(pathLocal, FileMode.Create))
|
||||
{
|
||||
await data.CopyToAsync(fileStream, cancellationToken);
|
||||
}
|
||||
return (true, "");
|
||||
}
|
||||
catch (MinioException ex)
|
||||
{
|
||||
return (false, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public (bool usingLocal, string url) GetUrl(string path, string objectName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!MinioOptions.UsingLocal)
|
||||
{
|
||||
var presignedGetObjectArgs = new PresignedGetObjectArgs()
|
||||
.WithBucket(MinioOptions.Bucket)
|
||||
.WithObject($"{path}/{objectName}")
|
||||
.WithExpiry(60 * 60 * 24);
|
||||
var url = MinioClient.PresignedGetObjectAsync(presignedGetObjectArgs);
|
||||
url.Wait();
|
||||
return (false, url.Result);
|
||||
}
|
||||
var mapImageFolder = string.IsNullOrEmpty(MinioOptions.Bucket) ? "MapImages" : MinioOptions.Bucket;
|
||||
if (Directory.Exists(mapImageFolder))
|
||||
{
|
||||
var folderPath = Path.Combine(mapImageFolder, path);
|
||||
if (Directory.Exists(folderPath))
|
||||
{
|
||||
var pathLocal = Path.Combine(folderPath, $"{objectName}.png");
|
||||
if (File.Exists(pathLocal))
|
||||
{
|
||||
return (true, pathLocal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (true, "");
|
||||
}
|
||||
catch (MinioException ex)
|
||||
{
|
||||
return (false, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<(bool, string)> DeleteAsync(string path, string objectName, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!MinioOptions.UsingLocal)
|
||||
{
|
||||
var removeObjectArgs = new RemoveObjectArgs()
|
||||
.WithBucket(MinioOptions.Bucket)
|
||||
.WithObject($"{path}/{objectName}");
|
||||
await MinioClient.RemoveObjectAsync(removeObjectArgs, cancellationToken).ConfigureAwait(false);
|
||||
return (true, "");
|
||||
}
|
||||
var mapImageFolder = string.IsNullOrEmpty(MinioOptions.Bucket) ? "MapImages" : MinioOptions.Bucket;
|
||||
if (Directory.Exists(mapImageFolder))
|
||||
{
|
||||
var folderPath = Path.Combine(mapImageFolder, path);
|
||||
if (Directory.Exists(folderPath))
|
||||
{
|
||||
var pathLocal = Path.Combine(folderPath, $"{objectName}.png");
|
||||
if (File.Exists(pathLocal)) File.Delete(pathLocal);
|
||||
if (File.Exists($"{pathLocal}.bk")) File.Delete($"{pathLocal}.bk");
|
||||
}
|
||||
}
|
||||
return (true, "");
|
||||
}
|
||||
catch (MinioException ex)
|
||||
{
|
||||
return (false, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
161
RobotNet.MapManager/Services/ServerHelper.cs
Normal file
161
RobotNet.MapManager/Services/ServerHelper.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using RobotNet.MapManager.Data;
|
||||
using RobotNet.MapShares.Dtos;
|
||||
using RobotNet.MapShares.Enums;
|
||||
|
||||
namespace RobotNet.MapManager.Services;
|
||||
|
||||
public class ServerHelper
|
||||
{
|
||||
public static Edge CreateEdge(Map map, Guid startNodeId, Guid endNodeId, TrajectoryDegree trajectoryDegree, double cpX1 = 0, double cpY1 = 0, double cpX2 = 0, double cpY2 = 0)
|
||||
{
|
||||
return new Edge()
|
||||
{
|
||||
MapId = map.Id,
|
||||
StartNodeId = startNodeId,
|
||||
EndNodeId = endNodeId,
|
||||
TrajectoryDegree = trajectoryDegree,
|
||||
DirectionAllowed = map.EdgeDirectionAllowedDefault,
|
||||
RotationAllowed = map.EdgeRotationAllowedDefault,
|
||||
MaxSpeed = trajectoryDegree == TrajectoryDegree.One ? map.EdgeStraightMaxSpeedDefault : map.EdgeCurveMaxSpeedDefault,
|
||||
MaxRotationSpeed = map.EdgeMaxRotationSpeedDefault,
|
||||
MaxHeight = map.EdgeMaxHeightDefault,
|
||||
MinHeight = map.EdgeMinHeightDefault,
|
||||
Actions = "[]",
|
||||
AllowedDeviationXy = map.EdgeAllowedDeviationXyDefault,
|
||||
AllowedDeviationTheta = map.EdgeAllowedDeviationThetaDefault,
|
||||
ControlPoint1X = cpX1,
|
||||
ControlPoint1Y = cpY1,
|
||||
ControlPoint2X = cpX2,
|
||||
ControlPoint2Y = cpY2,
|
||||
};
|
||||
}
|
||||
|
||||
public static Node CreateNode(Map map, double x, double y)
|
||||
{
|
||||
return new Node()
|
||||
{
|
||||
MapId = map.Id,
|
||||
Name = map.NodeNameAutoGenerate ? $"{map.NodeNameTemplateDefault}{++map.NodeCount}" : string.Empty,
|
||||
X = x,
|
||||
Y = y,
|
||||
Theta = 0,
|
||||
AllowedDeviationXy = map.NodeAllowedDeviationXyDefault,
|
||||
AllowedDeviationTheta = map.NodeAllowedDeviationThetaDefault,
|
||||
Actions = "[]",
|
||||
};
|
||||
}
|
||||
|
||||
public static EdgeDto CreateEdgeDto(Edge edge, Node startNode, Node endNode)
|
||||
{
|
||||
return new EdgeDto()
|
||||
{
|
||||
Id = edge.Id,
|
||||
MapId = edge.MapId,
|
||||
StartNodeId = edge.StartNodeId,
|
||||
EndNodeId = edge.EndNodeId,
|
||||
TrajectoryDegree = edge.TrajectoryDegree,
|
||||
ControlPoint1X = edge.ControlPoint1X,
|
||||
ControlPoint1Y = edge.ControlPoint1Y,
|
||||
ControlPoint2X = edge.ControlPoint2X,
|
||||
ControlPoint2Y = edge.ControlPoint2Y,
|
||||
DirectionAllowed = edge.DirectionAllowed,
|
||||
RotationAllowed = edge.RotationAllowed,
|
||||
MaxSpeed = edge.MaxSpeed,
|
||||
MaxRotationSpeed = edge.MaxRotationSpeed,
|
||||
MaxHeight = edge.MaxHeight,
|
||||
MinHeight = edge.MinHeight,
|
||||
Actions = edge.Actions,
|
||||
AllowedDeviationXy = edge.AllowedDeviationXy,
|
||||
AllowedDeviationTheta = edge.AllowedDeviationTheta,
|
||||
StartNode = new NodeDto()
|
||||
{
|
||||
Id = startNode.Id,
|
||||
Name = startNode.Name,
|
||||
MapId = startNode.MapId,
|
||||
Theta = startNode.Theta,
|
||||
X = startNode.X,
|
||||
Y = startNode.Y,
|
||||
Actions = startNode.Actions,
|
||||
AllowedDeviationXy = startNode.AllowedDeviationXy,
|
||||
AllowedDeviationTheta = startNode.AllowedDeviationTheta,
|
||||
},
|
||||
EndNode = new NodeDto()
|
||||
{
|
||||
Id = endNode.Id,
|
||||
Name = endNode.Name,
|
||||
MapId = endNode.MapId,
|
||||
Theta = endNode.Theta,
|
||||
X = endNode.X,
|
||||
Y = endNode.Y,
|
||||
AllowedDeviationXy = endNode.AllowedDeviationXy,
|
||||
AllowedDeviationTheta = endNode.AllowedDeviationTheta,
|
||||
Actions = endNode.Actions,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public static NodeDto CreateNodeDto(Node node)
|
||||
{
|
||||
return new NodeDto()
|
||||
{
|
||||
Id = node.Id,
|
||||
Name = node.Name,
|
||||
MapId = node.MapId,
|
||||
Theta = node.Theta,
|
||||
X = node.X,
|
||||
Y = node.Y,
|
||||
AllowedDeviationXy = node.AllowedDeviationXy,
|
||||
AllowedDeviationTheta = node.AllowedDeviationTheta,
|
||||
Actions = node.Actions,
|
||||
};
|
||||
}
|
||||
|
||||
public static Edge? GetClosesEdge(double x, double y, IEnumerable<Node> nodes, IEnumerable<Edge> edges, double allowDistance)
|
||||
{
|
||||
double minDistance = double.MaxValue;
|
||||
Edge? edgeResult = null;
|
||||
foreach (var edge in edges)
|
||||
{
|
||||
if (edge is not null)
|
||||
{
|
||||
var startNode = nodes.FirstOrDefault(n => n.Id == edge.StartNodeId);
|
||||
var endNode = nodes.FirstOrDefault(n => n.Id == edge.EndNodeId);
|
||||
if (startNode is null || endNode is null) continue;
|
||||
var distance = DistanceToSegment(x, y, startNode.X, startNode.Y, endNode.X, endNode.Y);
|
||||
if (distance < minDistance)
|
||||
{
|
||||
minDistance = distance;
|
||||
edgeResult = edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (minDistance > allowDistance) return null;
|
||||
return edgeResult;
|
||||
}
|
||||
|
||||
private static double DistanceToSegment(double x, double y, double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
|
||||
double segmentLengthSquared = dx * dx + dy * dy;
|
||||
|
||||
double t;
|
||||
if (segmentLengthSquared == 0)
|
||||
{
|
||||
t = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = ((x - x1) * dx + (y - y1) * dy) / segmentLengthSquared;
|
||||
t = Math.Max(0, Math.Min(1, t));
|
||||
}
|
||||
|
||||
double nearestX = x1 + t * dx;
|
||||
double nearestY = y1 + t * dy;
|
||||
|
||||
double distanceSquared = (x - nearestX) * (x - nearestX) + (y - nearestY) * (y - nearestY);
|
||||
|
||||
return Math.Sqrt(distanceSquared);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user