Compare commits
8 Commits
7daad2dfaf
...
b006c5b197
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b006c5b197 | ||
|
|
4ceec9abd5 | ||
|
|
1289a6c331 | ||
|
|
f1a7be15f2 | ||
| d2cf86f34e | |||
|
|
d4af3b8707 | ||
| 909e147be1 | |||
| dc837e5488 |
66
.dockerignore
Normal file
66
.dockerignore
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Build artifacts
|
||||||
|
**/bin/
|
||||||
|
**/obj/
|
||||||
|
**/out/
|
||||||
|
|
||||||
|
# Visual Studio files
|
||||||
|
**/.vs/
|
||||||
|
**/.vscode/
|
||||||
|
**/*.user
|
||||||
|
**/*.suo
|
||||||
|
**/*.userosscache
|
||||||
|
**/*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
**/.user
|
||||||
|
**/.suo
|
||||||
|
**/.userosscache
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# NuGet packages
|
||||||
|
**/packages/
|
||||||
|
**/*.nupkg
|
||||||
|
**/*.snupkg
|
||||||
|
|
||||||
|
# Test results
|
||||||
|
**/[Tt]est[Rr]esult*/
|
||||||
|
**/[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# Docker files
|
||||||
|
Dockerfile*
|
||||||
|
docker-compose*
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Data and logs (will be mounted as volumes)
|
||||||
|
data/
|
||||||
|
logs/
|
||||||
|
|
||||||
57
Dockerfile
Normal file
57
Dockerfile
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Stage 1: Build
|
||||||
|
# Note: Project files specify net10.0, but using .NET 9.0 based on package versions (9.0.9)
|
||||||
|
# Adjust version if needed: 8.0 (LTS), 9.0 (current), or future 10.0
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy solution file
|
||||||
|
COPY RobotApp.sln .
|
||||||
|
|
||||||
|
# Copy project files
|
||||||
|
COPY RobotApp/RobotApp.csproj RobotApp/
|
||||||
|
COPY RobotApp.Client/RobotApp.Client.csproj RobotApp.Client/
|
||||||
|
COPY RobotApp.Common.Shares/RobotApp.Common.Shares.csproj RobotApp.Common.Shares/
|
||||||
|
COPY RobotApp.VDA5050/RobotApp.VDA5050.csproj RobotApp.VDA5050/
|
||||||
|
|
||||||
|
# Restore dependencies
|
||||||
|
RUN dotnet restore RobotApp.sln
|
||||||
|
|
||||||
|
# Copy all source files
|
||||||
|
COPY RobotApp/ RobotApp/
|
||||||
|
COPY RobotApp.Client/ RobotApp.Client/
|
||||||
|
COPY RobotApp.Common.Shares/ RobotApp.Common.Shares/
|
||||||
|
COPY RobotApp.VDA5050/ RobotApp.VDA5050/
|
||||||
|
|
||||||
|
RUN rm -rf ./RobotApp/RobotApp/bin
|
||||||
|
RUN rm -rf ./RobotApp/RobotApp/obj
|
||||||
|
RUN rm -rf ./RobotApp.Client/RobotApp.Client/bin
|
||||||
|
RUN rm -rf ./RobotApp.Client/RobotApp.Client/obj
|
||||||
|
RUN rm -rf ./RobotApp.Common.Shares/RobotApp.Common.Shares/bin
|
||||||
|
RUN rm -rf ./RobotApp.Common.Shares/RobotApp.Common.Shares/obj
|
||||||
|
RUN rm -rf ./RobotApp.VDA5050/RobotApp.VDA5050/bin
|
||||||
|
RUN rm -rf ./RobotApp.VDA5050/RobotApp.VDA5050/obj
|
||||||
|
|
||||||
|
# Build the solution
|
||||||
|
WORKDIR /src/RobotApp
|
||||||
|
RUN dotnet build -c Release -o /app/build
|
||||||
|
|
||||||
|
# Stage 2: Publish
|
||||||
|
FROM build AS publish
|
||||||
|
WORKDIR /src/RobotApp
|
||||||
|
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
# Copy published files
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish ./
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
#ENV ASPNETCORE_URLS=http://+:8080
|
||||||
|
ENV ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
|
||||||
|
# Run the application
|
||||||
|
ENTRYPOINT ["dotnet", "RobotApp.dll"]
|
||||||
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
@using MudBlazor
|
@using MudBlazor
|
||||||
|
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
@attribute [Authorize]
|
|
||||||
|
|
||||||
@inject RobotStateClient RobotStateClient
|
@inject RobotStateClient RobotStateClient
|
||||||
@rendermode InteractiveWebAssemblyNoPrerender
|
@rendermode InteractiveWebAssemblyNoPrerender
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
@page "/logs"
|
@page "/logs"
|
||||||
@rendermode InteractiveWebAssemblyNoPrerender
|
@rendermode InteractiveWebAssemblyNoPrerender
|
||||||
@attribute [Authorize]
|
|
||||||
|
|
||||||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
@using RobotApp.Client.Models
|
@using RobotApp.Client.Models
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
@rendermode InteractiveWebAssemblyNoPrerender
|
@rendermode InteractiveWebAssemblyNoPrerender
|
||||||
|
|
||||||
@attribute [Authorize]
|
|
||||||
|
|
||||||
<PageTitle>Map Manager</PageTitle>
|
<PageTitle>Map Manager</PageTitle>
|
||||||
|
|
||||||
<div class="d-flex w-100 h-100 p-2 overflow-hidden flex-row">
|
<div class="d-flex w-100 h-100 p-2 overflow-hidden flex-row">
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
<!-- Radius -->
|
@* <!-- Radius -->
|
||||||
<MudItem xs="6">
|
<MudItem xs="6">
|
||||||
<MudNumericField T="double"
|
<MudNumericField T="double"
|
||||||
Value="@edge.Radius"
|
Value="@edge.Radius"
|
||||||
|
|
@ -127,7 +127,7 @@
|
||||||
Apply Curve (generate node)
|
Apply Curve (generate node)
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
}
|
} *@
|
||||||
|
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</ChildContent>
|
</ChildContent>
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,6 @@
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField @bind-Value="Node.NodeId" Label="Node ID" Required="true" />
|
<MudTextField @bind-Value="Node.NodeId" Label="Node ID" Required="true" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
|
||||||
<MudNumericField T="int" @bind-Value="Node.SequenceId" Label="Sequence ID" Required="true" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudSwitch T="bool" @bind-Checked="Node.Released" Label="Released" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="6">
|
<MudItem xs="6">
|
||||||
<MudNumericField T="double" @bind-Value="Node.NodePosition.X" Label="X" />
|
<MudNumericField T="double" @bind-Value="Node.NodePosition.X" Label="X" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,15 @@
|
||||||
Import JSON
|
Import JSON
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
|
||||||
|
<!-- CANCEL -->
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Error"
|
||||||
|
StartIcon="@Icons.Material.Filled.Cancel"
|
||||||
|
Disabled="@DisableCancel"
|
||||||
|
OnClick="OnCancel">
|
||||||
|
Cancel
|
||||||
|
</MudButton>
|
||||||
|
|
||||||
<!-- SEND -->
|
<!-- SEND -->
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="@SendButtonColor"
|
Color="@SendButtonColor"
|
||||||
|
|
@ -37,8 +46,10 @@
|
||||||
|
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
<MudTextField Value="@OrderJson"
|
<MudTextField Value="@OrderJson"
|
||||||
ReadOnly
|
T="string"
|
||||||
|
ValueChanged="OrderJsonChange"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
|
Immediate=true
|
||||||
Lines="50"
|
Lines="50"
|
||||||
Style="font-family: 'Roboto Mono', Consolas, monospace;
|
Style="font-family: 'Roboto Mono', Consolas, monospace;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
|
|
@ -51,10 +62,14 @@
|
||||||
[Parameter] public string OrderJson { get; set; } = "";
|
[Parameter] public string OrderJson { get; set; } = "";
|
||||||
[Parameter] public bool Copied { get; set; }
|
[Parameter] public bool Copied { get; set; }
|
||||||
[Parameter] public bool? SendSuccess { get; set; }
|
[Parameter] public bool? SendSuccess { get; set; }
|
||||||
|
[Parameter] public bool DisableCancel { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public EventCallback<string> OrderJsonChanged { get; set; }
|
||||||
|
|
||||||
[Parameter] public EventCallback OnCopy { get; set; }
|
[Parameter] public EventCallback OnCopy { get; set; }
|
||||||
[Parameter] public EventCallback OnSend { get; set; }
|
[Parameter] public EventCallback OnSend { get; set; }
|
||||||
[Parameter] public EventCallback OnImport { get; set; }
|
[Parameter] public EventCallback OnImport { get; set; }
|
||||||
|
[Parameter] public EventCallback OnCancel { get; set; }
|
||||||
|
|
||||||
private string SendButtonText =>
|
private string SendButtonText =>
|
||||||
SendSuccess switch
|
SendSuccess switch
|
||||||
|
|
@ -79,4 +94,11 @@
|
||||||
false => Icons.Material.Filled.Error,
|
false => Icons.Material.Filled.Error,
|
||||||
_ => Icons.Material.Filled.Send
|
_ => Icons.Material.Filled.Send
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private void OrderJsonChange(string value)
|
||||||
|
{
|
||||||
|
OrderJson = value;
|
||||||
|
OrderJsonChanged.InvokeAsync(OrderJson);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
@page "/robot-order"
|
@page "/robot-order"
|
||||||
|
|
||||||
@attribute [Authorize]
|
|
||||||
@rendermode InteractiveWebAssemblyNoPrerender
|
@rendermode InteractiveWebAssemblyNoPrerender
|
||||||
|
|
||||||
@using System.Text.Json
|
@using System.Text.Json
|
||||||
|
|
@ -8,6 +7,7 @@
|
||||||
|
|
||||||
@inject IJSRuntime JS
|
@inject IJSRuntime JS
|
||||||
@inject IDialogService DialogService
|
@inject IDialogService DialogService
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
@inject HttpClient Http
|
@inject HttpClient Http
|
||||||
|
|
||||||
<MudMainContent Class="pa-0 ma-0">
|
<MudMainContent Class="pa-0 ma-0">
|
||||||
|
|
@ -46,13 +46,13 @@
|
||||||
|
|
||||||
<!-- ================= RIGHT ================= -->
|
<!-- ================= RIGHT ================= -->
|
||||||
<MudItem xs="12" md="5" Class="h-100">
|
<MudItem xs="12" md="5" Class="h-100">
|
||||||
<JsonOutputPanel OrderJson="@OrderJson"
|
<JsonOutputPanel @bind-OrderJson="@OrderJson"
|
||||||
Copied="@copied"
|
Copied="@copied"
|
||||||
SendSuccess="@sendSuccess"
|
SendSuccess="@sendSuccess"
|
||||||
OnCopy="CopyJsonToClipboard"
|
OnCopy="CopyJsonToClipboard"
|
||||||
OnSend="SendOrderToServer"
|
OnSend="SendOrderToServer"
|
||||||
OnImport="OpenImportDialog" />
|
OnImport="OpenImportDialog"
|
||||||
|
OnCancel="CancelOrder" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
|
|
@ -66,7 +66,6 @@
|
||||||
private string OrderJson = ""; // 🔥 CACHE JSON (QUAN TRỌNG)
|
private string OrderJson = ""; // 🔥 CACHE JSON (QUAN TRỌNG)
|
||||||
private bool copied;
|
private bool copied;
|
||||||
private bool? sendSuccess;
|
private bool? sendSuccess;
|
||||||
private bool sending;
|
|
||||||
private CancellationTokenSource? _copyCts;
|
private CancellationTokenSource? _copyCts;
|
||||||
|
|
||||||
// ================= INIT =================
|
// ================= INIT =================
|
||||||
|
|
@ -227,7 +226,7 @@
|
||||||
sendSuccess = response.IsSuccessStatusCode;
|
sendSuccess = response.IsSuccessStatusCode;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
sendSuccess = false;
|
sendSuccess = false;
|
||||||
}
|
}
|
||||||
|
|
@ -246,6 +245,35 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async Task CancelOrder()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var res = await Http.PostAsync("/api/order/cancel", null);
|
||||||
|
|
||||||
|
sendSuccess = null; // reset trạng thái SEND
|
||||||
|
copied = false;
|
||||||
|
|
||||||
|
if (res.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
Snackbar.Add(
|
||||||
|
"⛔ Order đã huỷ",
|
||||||
|
Severity.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Snackbar.Add(
|
||||||
|
"❌ Huỷ order thất bại",
|
||||||
|
Severity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Snackbar.Add(
|
||||||
|
$"❌ Lỗi: {ex.Message}",
|
||||||
|
Severity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async Task CopyJsonToClipboard()
|
async Task CopyJsonToClipboard()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
@page "/robot-config"
|
@page "/robot-config"
|
||||||
@rendermode InteractiveWebAssemblyNoPrerender
|
@rendermode InteractiveWebAssemblyNoPrerender
|
||||||
@attribute [Authorize]
|
|
||||||
|
|
||||||
@inject HttpClient Http
|
@inject HttpClient Http
|
||||||
@inject ISnackbar Snackbar
|
@inject ISnackbar Snackbar
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
@page "/robot-monitor"
|
@page "/robot-monitor"
|
||||||
@rendermode InteractiveWebAssemblyNoPrerender
|
@rendermode InteractiveWebAssemblyNoPrerender
|
||||||
@attribute [Authorize]
|
|
||||||
@inject RobotApp.Client.Services.RobotMonitorService MonitorService
|
@inject RobotApp.Client.Services.RobotMonitorService MonitorService
|
||||||
@implements IAsyncDisposable
|
@implements IAsyncDisposable
|
||||||
|
|
||||||
|
|
@ -40,3 +39,5 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,3 +59,4 @@ window.robotMonitor = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
@rendermode InteractiveServer
|
@rendermode InteractiveServer
|
||||||
|
|
||||||
@attribute [Authorize]
|
|
||||||
|
|
||||||
@inject NavigationManager Nav
|
@inject NavigationManager Nav
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ namespace RobotApp.Controllers;
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
//[Authorize]
|
||||||
|
[AllowAnonymous]
|
||||||
public class FileController(Services.Logger<FileController> Logger) : ControllerBase
|
public class FileController(Services.Logger<FileController> Logger) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly string certificatesPath = "MqttCertificates";
|
private readonly string certificatesPath = "MqttCertificates";
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace RobotApp.Controllers;
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
|
//[Authorize]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public class ImagesController(Services.Logger<ImagesController> Logger) : ControllerBase
|
public class ImagesController(Services.Logger<ImagesController> Logger) : ControllerBase
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ namespace RobotApp.Controllers;
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
//[Authorize]
|
||||||
|
[AllowAnonymous]
|
||||||
public class LogsManagerController(Services.Logger<LogsManagerController> Logger) : ControllerBase
|
public class LogsManagerController(Services.Logger<LogsManagerController> Logger) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly string LoggerDirectory = "logs";
|
private readonly string LoggerDirectory = "logs";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using RobotApp.Services.Robot;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using RobotApp.Interfaces;
|
||||||
using RobotApp.VDA5050.Order;
|
using RobotApp.VDA5050.Order;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
|
|
@ -7,30 +8,31 @@ namespace RobotApp.Controllers;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/order")]
|
[Route("api/order")]
|
||||||
public class OrderController : ControllerBase
|
//[Authorize]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public class OrderController(IOrder robotOrderController, IInstantActions instantActions) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly RobotOrderController robotOrderController;
|
|
||||||
|
|
||||||
public OrderController(RobotOrderController robotOrderController)
|
|
||||||
{
|
|
||||||
this.robotOrderController = robotOrderController;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult SendOrder([FromBody] OrderMsg order)
|
public IActionResult SendOrder([FromBody] OrderMsg order)
|
||||||
{
|
{
|
||||||
Console.WriteLine("===== ORDER RECEIVED =====");
|
|
||||||
Console.WriteLine(JsonSerializer.Serialize(order, new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
WriteIndented = true
|
|
||||||
}));
|
|
||||||
|
|
||||||
robotOrderController.UpdateOrder(order);
|
robotOrderController.UpdateOrder(order);
|
||||||
|
|
||||||
return Ok(new
|
return Ok(new
|
||||||
{
|
{
|
||||||
success = true,
|
success = true,
|
||||||
message = "Order received"
|
message = "Order received"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
[HttpPost("cancel")]
|
||||||
|
public IActionResult CancelOrder()
|
||||||
|
{
|
||||||
|
robotOrderController.StopOrder();
|
||||||
|
instantActions.StopOrderAction();
|
||||||
|
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
success = true,
|
||||||
|
message = "Order and actions have been cancelled"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ namespace RobotApp.Controllers;
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
//[Authorize]
|
||||||
|
[AllowAnonymous]
|
||||||
public class RobotConfigsController(Services.Logger<RobotConfigsController> Logger, ApplicationDbContext AppDb, RobotConfiguration RobotConfiguration) : ControllerBase
|
public class RobotConfigsController(Services.Logger<RobotConfigsController> Logger, ApplicationDbContext AppDb, RobotConfiguration RobotConfiguration) : ControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ public static class ApplicationDbExtensions
|
||||||
VDA5050EnableTls = false,
|
VDA5050EnableTls = false,
|
||||||
VDA5050UserName = "robotics",
|
VDA5050UserName = "robotics",
|
||||||
VDA5050Password = "robotics",
|
VDA5050Password = "robotics",
|
||||||
VDA5050TopicPrefix = "uagv/v2"
|
VDA5050TopicPrefix = "uagv/v2",
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
CreatedAt = DateTime.Now,
|
CreatedAt = DateTime.Now,
|
||||||
UpdatedAt = DateTime.Now,
|
UpdatedAt = DateTime.Now,
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,4 @@ public class RobotMonitorHub : Hub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,22 @@
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"workingDirectory": "$(TargetDir)",
|
"workingDirectory": "$(TargetDir)",
|
||||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
//"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||||
"applicationUrl": "http://localhost:5229",
|
"applicationUrl": "http://localhost:5229",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
|
||||||
"workingDirectory": "$(TargetDir)",
|
|
||||||
//"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
|
||||||
"applicationUrl": "https://0.0.0.0:7150;http://localhost:5229",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//"https": {
|
||||||
|
// "commandName": "Project",
|
||||||
|
// "dotnetRunMessages": true,
|
||||||
|
// "launchBrowser": true,
|
||||||
|
// "workingDirectory": "$(TargetDir)",
|
||||||
|
// //"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||||
|
// "applicationUrl": "https://0.0.0.0:7150;http://localhost:5229",
|
||||||
|
// "environmentVariables": {
|
||||||
|
// "ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -195,17 +195,6 @@ public class MQTTClient : IAsyncDisposable
|
||||||
arg.Chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
|
arg.Chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
|
||||||
|
|
||||||
var isValid = arg.Chain.Build((X509Certificate2)arg.Certificate);
|
var isValid = arg.Chain.Build((X509Certificate2)arg.Certificate);
|
||||||
|
|
||||||
if (isValid)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Broker CERTIFICATE VALID");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine("Broker CERTIFICATE INVALID");
|
|
||||||
foreach (var status in arg.Chain.ChainStatus)
|
|
||||||
Console.WriteLine($" -> Chain error: {status.Status} - {status.StatusInformation}");
|
|
||||||
}
|
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ public class MQTTClientCertificatesProvider(string? CerFile, string? KeyFile) :
|
||||||
var cert = X509Certificate2.CreateFromPem(File.ReadAllText(certLocal), File.ReadAllText(keyLocal));
|
var cert = X509Certificate2.CreateFromPem(File.ReadAllText(certLocal), File.ReadAllText(keyLocal));
|
||||||
var pfxBytes = cert.Export(X509ContentType.Pfx);
|
var pfxBytes = cert.Export(X509ContentType.Pfx);
|
||||||
var pfxCert = X509CertificateLoader.LoadPkcs12(pfxBytes, "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
|
var pfxCert = X509CertificateLoader.LoadPkcs12(pfxBytes, "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
|
||||||
Console.WriteLine($"Client cert loaded: {pfxCert.Subject}, HasPrivateKey: {pfxCert.HasPrivateKey}, PrivateKey Type: {pfxCert.GetRSAPrivateKey()?.GetType()}");
|
|
||||||
return [pfxCert];
|
return [pfxCert];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,6 @@ public abstract class RobotAction(IServiceProvider serviceProvider) : IDisposabl
|
||||||
|
|
||||||
protected virtual Task StopAction()
|
protected virtual Task StopAction()
|
||||||
{
|
{
|
||||||
Console.WriteLine($"StopAction {Type}");
|
|
||||||
Status = ActionStatus.FAILED;
|
Status = ActionStatus.FAILED;
|
||||||
ResultDescription = "Action bị hủy bỏ.";
|
ResultDescription = "Action bị hủy bỏ.";
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
|
||||||
|
|
@ -169,15 +169,11 @@ public class RobotStatePublisher : BackgroundService
|
||||||
isConnected, // payload only bool
|
isConnected, // payload only bool
|
||||||
stoppingToken
|
stoppingToken
|
||||||
);
|
);
|
||||||
|
|
||||||
Console.WriteLine(
|
|
||||||
$"[RobotStatePublisher] Robot connection changed → {(isConnected ? "ONLINE" : "OFFLINE")}"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -158,14 +158,12 @@ public class SimulationNavigation : INavigation, IDisposable
|
||||||
|
|
||||||
public void Pause()
|
public void Pause()
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Nav Pause");
|
|
||||||
ResumeState = State;
|
ResumeState = State;
|
||||||
NavState = NavigationState.Paused;
|
NavState = NavigationState.Paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resume()
|
public void Resume()
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Nav Resume");
|
|
||||||
NavState = ResumeState;
|
NavState = ResumeState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
35
docker-compose.yaml
Normal file
35
docker-compose.yaml
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
robotapp:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: robotapp
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://+:8080
|
||||||
|
- ConnectionStrings__DefaultConnection=Data Source=/app/data/robot.db
|
||||||
|
volumes:
|
||||||
|
# Persist database
|
||||||
|
- ./data:/app/data
|
||||||
|
# Persist maps
|
||||||
|
- ./maps:/app/maps
|
||||||
|
# Persist logs (if needed)
|
||||||
|
- ./logs:/app/logs
|
||||||
|
networks:
|
||||||
|
- robotapp-network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8080 || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
robotapp-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user