using System.Reflection; using Com.Ctrip.Framework.Apollo; using Sln.Wcs; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using NeoSmart.Caching.Sqlite; using Newtonsoft.Json; using Sln.Wcs.HoistDispatcher; using Sln.Wcs.Model.Domain; using Sln.Wcs.Plc; using Sln.Wcs.Repository; using Sln.Wcs.Repository.service; using Sln.Wcs.Serilog; using ZiggyCreatures.Caching.Fusion; using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson; var builder = WebApplication.CreateBuilder(args); var basePath = AppContext.BaseDirectory; // ---- 配置 ---- var localConfig = new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build(); var apolloConfigSection = localConfig.GetSection("apollo"); builder.Services.AddSingleton(localConfig); var configProvider = new UpdateableConfigProvider(); configProvider.Set("PLC参数", ""); var apolloConfig = new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddApollo(apolloConfigSection) .AddDefault() .Add(configProvider) .Build(); builder.Services.Remove(new ServiceDescriptor(typeof(IConfiguration), localConfig)); builder.Services.AddSingleton(apolloConfig); // ---- DI 扫描 ---- var assemblies = new[] { Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Common.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Cache.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Repository.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Plc.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistSdk.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistAdapter.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistDispatcher.dll")), }; builder.Services.Scan(scan => scan.FromAssemblies(assemblies) .AddClasses().AsImplementedInterfaces().AsSelf().WithTransientLifetime()); builder.Services.AddSingleton(typeof(SerilogHelper)); builder.Services.AddSqlSugarSetup(); builder.Services.AddPlcSetup(); // builder.Services.AddFusionCache() // .WithSerializer(new FusionCacheNewtonsoftJsonSerializer()) // .WithDistributedCache(new SqliteCache(new SqliteCacheOptions { CachePath = apolloConfig["cachePath"]! })); // ---- Swagger ---- builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => c.SwaggerDoc("v1", new OpenApiInfo { Title = "Hoist Engine API", Version = "v1" })); var app = builder.Build(); // ---- 启动初始化 ---- var sp = app.Services; sp.UseSerilogExtensions(); var log = sp.GetRequiredService(); log.Info($"HoistServer 启动, 日志:{apolloConfig["logPath"]}"); var deviceInfoService = sp.GetRequiredService(); var list = deviceInfoService.GetDeviceInfos(x => x.isFlag == 1).ToList(); configProvider.Set("PLC参数", JsonConvert.SerializeObject(list)); log.Info($"PLC参数已加载, 共{list.Count}台设备"); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Hoist Engine v1"); c.RoutePrefix = "swagger"; }); // ---- HoistDispatchHub 四个方法 ---- var hub = sp.GetRequiredService(); var api = app.MapGroup("/api"); // 1. ReceivePallet api.MapPost("/hoist/receive-pallet", (ReceivePalletRequest req, IBaseDeviceInfoService devSvc) => { var device = devSvc.Query(x => x.deviceType == 2 && x.isFlag == 1) .FirstOrDefault(d => d.hostCode == req.HostCode); if (device == null) return Results.Ok(new { success = false, msg = "设备不存在" }); var detail = new LiveTaskDetail { taskCode = req.TaskCode, palletBarcode = req.PalletBarcode, startPoint = req.StartPoint, endPoint = req.EndPoint, deviceType = 2, taskStatus = 1 }; hub.ReceivePallet(detail, device); return Results.Ok(new { success = true }); }); // 2. TaskRun api.MapPost("/hoist/task-run", (TaskRunRequest req, IBaseDeviceInfoService devSvc) => { var device = devSvc.Query(x => x.deviceType == 2 && x.isFlag == 1) .FirstOrDefault(d => d.hostCode == req.HostCode); if (device == null) return Results.Ok(new { success = false, msg = "设备不存在" }); device.deviceSerialNo = req.SerialNo; hub.TaskRun(device); return Results.Ok(new { success = true }); }); // 3. TaskDispatch api.MapPost("/task/dispatch", (TaskDispatchRequest req, IBaseDeviceInfoService devSvc) => { var device = devSvc.Query(x => x.deviceType == 2 && x.isFlag == 1) .FirstOrDefault(d => d.hostCode == req.HostCode); if (device == null) return Results.Ok(new { success = false, msg = "设备不存在" }); var detail = new LiveTaskDetail { taskCode = req.TaskCode, startPoint = req.StartPoint, endPoint = req.EndPoint, deviceType = 2, taskStatus = 1 }; hub.TaskDispatch(device, detail); return Results.Ok(new { success = true }); }); // 4. GetFreeHoistAsync api.MapGet("/hoist/free", async (string hostCode) => { var d = await hub.GetFreeHoistAsync(hostCode); return Results.Ok(new { found = d != null, d?.deviceCode, d?.deviceName }); }); api.MapGet("/health", () => Results.Ok(new { time = DateTime.Now, status = "ok" })); log.Info("HoistServer 就绪: http://localhost:5100/swagger"); app.Run(); record ReceivePalletRequest(string HostCode, int SerialNo, string TaskCode, string PalletBarcode, string StartPoint, string EndPoint); record TaskRunRequest(string HostCode, int SerialNo); record TaskDispatchRequest(string HostCode, int SerialNo, string TaskCode, string StartPoint, string EndPoint);