Initial commit
This commit is contained in:
238
srcs/RobotNet10/FleetManager/RobotNet10.FleetManager/Program.cs
Normal file
238
srcs/RobotNet10/FleetManager/RobotNet10.FleetManager/Program.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MudBlazor.Services;
|
||||
using NLog.Web;
|
||||
using RobotNet10.CustomConfiguration.Extensions;
|
||||
using RobotNet10.FleetManager.Client;
|
||||
using RobotNet10.FleetManager.Components;
|
||||
using RobotNet10.FleetManager.Components.Account;
|
||||
using RobotNet10.FleetManager.Data;
|
||||
using RobotNet10.FleetManager.Events;
|
||||
using RobotNet10.FleetManager.Hubs;
|
||||
using RobotNet10.FleetManager.Script;
|
||||
using RobotNet10.FleetManager.Services;
|
||||
using RobotNet10.FleetManager.Services.ConfigManager;
|
||||
using RobotNet10.FleetManager.Services.OpenACS;
|
||||
using RobotNet10.FleetManager.Services.RobotConnections;
|
||||
using RobotNet10.FleetManager.Services.RobotManager;
|
||||
using RobotNet10.FleetManager.Services.Script;
|
||||
using RobotNet10.FleetManager.Services.TrafficControl;
|
||||
using RobotNet10.FleetManager.Services.TrafficControl.ACS;
|
||||
using RobotNet10.FleetManager.Services.TrafficControl.Services;
|
||||
using RobotNet10.GlobalPathPlanner;
|
||||
using RobotNet10.MapManager.Extensions;
|
||||
using RobotNet10.ScriptEngine;
|
||||
using RobotNet10.ScriptEngine.Helpers;
|
||||
using RobotNet10.StorageManager;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Host.UseNLog();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents()
|
||||
.AddInteractiveWebAssemblyComponents()
|
||||
.AddAuthenticationStateSerialization();
|
||||
|
||||
builder.Services.AddCascadingAuthenticationState();
|
||||
builder.Services.AddScoped<IdentityRedirectManager>();
|
||||
builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
|
||||
|
||||
builder.Services.AddAuthentication()
|
||||
.AddBearerToken(IdentityConstants.BearerScheme);
|
||||
|
||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
|
||||
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString));
|
||||
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
||||
|
||||
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
|
||||
{
|
||||
options.SignIn.RequireConfirmedAccount = true;
|
||||
options.Lockout.AllowedForNewUsers = false;
|
||||
options.Password.RequireNonAlphanumeric = false;
|
||||
options.Password.RequireUppercase = false;
|
||||
options.Password.RequireLowercase = false;
|
||||
options.Password.RequireDigit = false;
|
||||
})
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddSignInManager()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
|
||||
|
||||
var mapConnectionString = builder.Configuration.GetConnectionString("MapEditorConnection") ?? throw new InvalidOperationException("Connection string 'MapEditorConnection' not found.");
|
||||
builder.Services.AddMapManager(builder.Configuration, options => options.UseSqlServer(mapConnectionString, b => b.MigrationsAssembly("RobotNet10.FleetManager").UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)), "LayoutImage");
|
||||
|
||||
builder.Services.AddMudServices();
|
||||
builder.Services.AddNavigationMenu(builder.Configuration["APP_VERSION"] ?? "dev");
|
||||
builder.Services.AddControllers();
|
||||
|
||||
// Register VDA5050 Event Bus (must be registered before services that use it)
|
||||
builder.Services.AddSingleton<IRobotEventBus, RobotEventBus>();
|
||||
|
||||
// Register StorageConfig for RobotModelImages
|
||||
builder.Services.Configure<StorageConfig>("RobotModelImages", options =>
|
||||
{
|
||||
builder.Configuration.GetSection("RobotModelImage").Bind(options);
|
||||
});
|
||||
|
||||
// Register Robot Management Services (with event bus for cache invalidation)
|
||||
builder.Services.AddScoped<IRobotModelService, RobotModelService>();
|
||||
builder.Services.AddScoped<IRobotService, RobotService>();
|
||||
builder.Services.AddScoped<IRobotModelImageStorageService, RobotModelImageStorageService>();
|
||||
builder.Services.AddScoped<IRobotModelMapService, RobotModelMapService>();
|
||||
|
||||
// Register SignalR Hub Context as BackgroundService (broadcasts at 1Hz)
|
||||
builder.Services.AddSingleton<RobotStateHubContext>();
|
||||
builder.Services.AddHostedService(sp => sp.GetRequiredService<RobotStateHubContext>());
|
||||
|
||||
// Register Logger service (factory pattern)
|
||||
builder.Services.AddSingleton(typeof(RobotNet10.FleetManager.Services.Logger<>));
|
||||
|
||||
// Register ConfigManager
|
||||
builder.Services.AddSingleton<IConnectionConfig, ConnectionConfig>();
|
||||
builder.Services.AddSingleton<ITrafficConfig, TrafficConfig>();
|
||||
builder.Services.AddSingleton<IACSTrafficConfig, ACSTrafficConfig>();
|
||||
|
||||
// Register OpenACS Services
|
||||
builder.Services.AddSingleton<TrafficACS>();
|
||||
builder.Services.AddSingleton<OpenACSPublisher>();
|
||||
builder.Services.AddHostedService(sp => sp.GetRequiredService<OpenACSPublisher>());
|
||||
|
||||
// Register ACS Order Control
|
||||
builder.Services.AddSingleton<IOrderControlService, OrderACSControl>();
|
||||
|
||||
// Note: IRobotEventBus is registered above with Robot Management Services
|
||||
|
||||
// Register VDA5050 RobotConnections Service
|
||||
builder.Services.AddSingleton<IRobotConnectionsService, RobotConnectionsService>();
|
||||
|
||||
// Register VDA5050 RobotManager Service
|
||||
builder.Services.AddSingleton<RobotManagerService>();
|
||||
builder.Services.AddSingleton<IRobotManagerService>(sp => sp.GetRequiredService<RobotManagerService>());
|
||||
builder.Services.AddHostedService(sp => sp.GetRequiredService<RobotManagerService>());
|
||||
|
||||
// Register Path Planner Factory
|
||||
builder.Services.AddSingleton<IPathPlannerFactory, PathPlannerFactory>();
|
||||
|
||||
// Register TrafficControl Sub-Services (order matters due to dependencies)
|
||||
// 1. RouteStorageService - No dependencies
|
||||
builder.Services.AddSingleton<IRouteStorageService, RouteStorageService>();
|
||||
|
||||
// 2. PriorityService - Only needs Logger
|
||||
builder.Services.AddSingleton<IPriorityService, PriorityService>();
|
||||
|
||||
// 3. RobotInfoService - Needs IServiceScopeFactory, IRobotManagerService, IRobotEventBus
|
||||
builder.Services.AddSingleton<IRobotInfoService, RobotInfoService>();
|
||||
|
||||
// 4. EdgeReservationService - Needs INodeService, IEdgeService, IServiceScopeFactory, IRobotInfoService
|
||||
builder.Services.AddSingleton<IEdgeReservationService, EdgeReservationService>();
|
||||
|
||||
// 5. OrderUpdateService - Needs IRobotManagerService
|
||||
builder.Services.AddSingleton<IOrderUpdateService, OrderUpdateService>();
|
||||
|
||||
// 6. ConflictDetectionService - Needs many services
|
||||
builder.Services.AddSingleton<IConflictDetectionService, ConflictDetectionService>();
|
||||
|
||||
// 7. ConflictResolutionService - Needs many services
|
||||
builder.Services.AddSingleton<IConflictResolutionService, ConflictResolutionService>();
|
||||
|
||||
// 8. BaseHorizonManagementService - Needs many services
|
||||
builder.Services.AddSingleton<IBaseHorizonManagementService, BaseHorizonManagementService>();
|
||||
|
||||
// 9. RoutePlanningService - Needs many services
|
||||
builder.Services.AddSingleton<IRoutePlanningService, RoutePlanningService>();
|
||||
|
||||
// Register TrafficControl Service (Orchestrator) - Must be registered after all sub-services
|
||||
builder.Services.AddSingleton<TrafficControlService>();
|
||||
builder.Services.AddSingleton<ITrafficControlService , TrafficControlService>(sp => sp.GetRequiredService<TrafficControlService>());
|
||||
//builder.Services.AddHostedService(sp => sp.GetRequiredService<TrafficControlService>());
|
||||
|
||||
// Add SignalR
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
// Add Custom Configuration
|
||||
builder.Services.AddCustomConfiguration(builder.Configuration, "StorageConfig");
|
||||
|
||||
var scriptConnectionString = builder.Configuration.GetConnectionString("ScriptEngineConnection") ?? throw new InvalidOperationException("Connection string 'ScriptEngineConnection' not found.");
|
||||
builder.Services.AddScriptEngine<ScriptEngineResource>(options => options.UseSqlServer(scriptConnectionString, b => b.MigrationsAssembly("RobotNet10.FleetManager")));
|
||||
|
||||
// Add Script Services
|
||||
builder.Services.AddSingleton<IRobotManager, ScriptRobotmanager>();
|
||||
builder.Services.AddSingleton<ILayoutManager, ScriptLayoutManager>();
|
||||
|
||||
#if DEBUG
|
||||
var dllPath = builder.Configuration["ScriptEngine:RuntimeDllFolder"] ?? "dlls";
|
||||
if (!Directory.Exists(dllPath))
|
||||
{
|
||||
Directory.CreateDirectory(dllPath);
|
||||
}
|
||||
var netCoreDir = Path.GetDirectoryName(typeof(object).Assembly.Location);
|
||||
if (!string.IsNullOrEmpty(netCoreDir))
|
||||
{
|
||||
var coreSrc = Path.Combine(netCoreDir, "System.Private.CoreLib.dll");
|
||||
var runtimeSrc = Path.Combine(netCoreDir, "System.Runtime.dll");
|
||||
var linqSrc = Path.Combine(netCoreDir, "System.Linq.Expressions.dll");
|
||||
var scriptSrc = typeof(RobotNet10.Script.ILogger).Assembly.Location;
|
||||
var fleetSrc = typeof(RobotNet10.FleetManager.Script.IRobot).Assembly.Location;
|
||||
|
||||
var coreDest = Path.Combine(dllPath, "System.Private.CoreLib.dll");
|
||||
var runtimeDest = Path.Combine(dllPath, "System.Runtime.dll");
|
||||
var linqDest = Path.Combine(dllPath, "System.Linq.Expressions.dll");
|
||||
var scriptDest = Path.Combine(dllPath, "RobotNet10.Script.dll");
|
||||
var fleetDest = Path.Combine(dllPath, "RobotNet10.FleetManager.Script.dll");
|
||||
|
||||
if (!File.Exists(coreDest)) File.Copy(coreSrc, coreDest);
|
||||
if (!File.Exists(runtimeDest)) File.Copy(runtimeSrc, runtimeDest);
|
||||
if (!File.Exists(linqDest)) File.Copy(linqSrc, linqDest);
|
||||
|
||||
File.Copy(scriptSrc, scriptDest, true);
|
||||
File.Copy(fleetSrc, fleetDest, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
await app.Services.SeedApplicationDbAsync();
|
||||
await app.Services.SeedScriptEngineDbAsync();
|
||||
await app.Services.SeedMapManagerAsync();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseWebAssemblyDebugging();
|
||||
app.UseMigrationsEndPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapStaticAssets();
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(RobotNet10.FleetManager.Client._Imports).Assembly);
|
||||
|
||||
// Map API controllers
|
||||
app.MapControllers();
|
||||
|
||||
// Map SignalR Hubs
|
||||
app.MapHub<RobotStateHub>("/hubs/robot-state");
|
||||
|
||||
// Add additional endpoints required by the Identity /Account Razor components.
|
||||
app.MapAdditionalIdentityEndpoints();
|
||||
|
||||
app.MapScriptEngineHubs();
|
||||
|
||||
app.Run();
|
||||
Reference in New Issue
Block a user