diff --git a/server/Program.cs b/server/Program.cs index 80f8ebb..1c4b39c 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -1,5 +1,3 @@ -using System.Reflection; -using Microsoft.OpenApi.Models; using Newtonsoft.Json; using NLog; using NLog.Web; @@ -15,6 +13,7 @@ try { var builder = WebApplication.CreateBuilder(args); + // Services Settings // Add services to the container. builder.Services.AddControllersWithViews(); @@ -32,27 +31,32 @@ try }); // Add Swagger - builder.Services.AddSwaggerGen(options => + builder.Services.AddControllers(); + builder.Services.AddOpenApiDocument(options => { - options.SwaggerDoc("v1", new OpenApiInfo + options.PostProcess = document => { - Title = "FPGA Web Lab API", - Description = "Use FPGA in the cloud", - Version = "v1" - }); - // Generate Doc and Example - options.IncludeXmlComments(Assembly.GetExecutingAssembly()); - // var executingAssembly = Assembly.GetExecutingAssembly(); - // var xmlFilename = $"{executingAssembly.GetName().Name}.xml"; - // options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); - // var referencedProjectsXmlDocPaths = - // executingAssembly.GetReferencedAssemblies() - // .Where(assembly => assembly.Name != null && assembly.Name.StartsWith("server", StringComparison.InvariantCultureIgnoreCase)) - // .Select(assembly => Path.Combine(AppContext.BaseDirectory, $"{assembly.Name}.xml")) - // .Where(path => File.Exists(path)); - // foreach (var xmlDocPath in referencedProjectsXmlDocPaths) options.IncludeXmlComments(xmlDocPath); + document.Info = new NSwag.OpenApiInfo + { + Version = "v1", + Title = "FPGA Web Lab API", + Description = "Use FPGA in the cloud", + // TermsOfService = "https://example.com/terms", + // Contact = new NSwag.OpenApiContact + // { + // Name = "Example Contact", + // Url = "https://example.com/contact" + // }, + // License = new NSwag.OpenApiLicense + // { + // Name = "Example License", + // Url = "https://example.com/license" + // } + }; + }; }); + // Application Settings var app = builder.Build(); // Configure the HTTP request pipeline. app.UseExceptionHandler("/Home/Error"); @@ -61,20 +65,12 @@ try app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); - app.UseAuthorization(); - app.MapControllerRoute( - name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); - // if (app.Environment.IsDevelopment()) // { - app.UseSwagger(); - app.UseSwaggerUI(c => - { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "FPAG WebLab API V1"); - }); + app.UseOpenApi(); + app.UseSwaggerUi(); // } // Setup Program @@ -83,15 +79,7 @@ try // Router // API Get app.MapGet("/", () => Results.Redirect("/swagger")); - app.MapGet("/api/GetRecvDataArray", Router.API.GetRecvDataArray); - // API Post - app.MapPost("/api/SendString", Router.API.SendString); - app.MapPost("/api/SendBytes", Router.API.SendBytes); - app.MapPost("/api/SendAddrPackage", Router.API.SendAddrPackage); - app.MapPost("/api/SendDataPackage", Router.API.SendDataPackage); - // API Jtag - app.MapPost("/api/jtag/RunCommand", Router.API.Jtag.RunCommand); - app.MapGet("/api/jtag/GetIDCode", Router.API.Jtag.GetDeviceIDCode); + app.MapControllers(); app.Run("http://localhost:5000"); } diff --git a/server/server.csproj b/server/server.csproj index a903e41..dca031e 100644 --- a/server/server.csproj +++ b/server/server.csproj @@ -18,7 +18,7 @@ - + diff --git a/server/src/Controllers.cs b/server/src/Controllers.cs new file mode 100644 index 0000000..d563152 --- /dev/null +++ b/server/src/Controllers.cs @@ -0,0 +1,186 @@ +using System.Net; +using Common; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using WebProtocol; + +namespace server.Controllers; + +/// +/// UDP API +/// +[ApiController] +[Route("api/[controller]")] +public class UDPController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + private const string LOCALHOST = "127.0.0.1"; + + /// + /// 页面 + /// + [HttpGet] + public string Index() + { + return "This is UDP Controller"; + } + + /// + /// 发送字符串 + /// + /// IPV4 或者 IPV6 地址 + /// 设备端口号 + /// 发送的文本 + /// 发送成功 + /// 发送失败 + [HttpPost("SendString")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendString(string address = LOCALHOST, int port = 1234, string text = "Hello Server!") + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendStringAsync(endPoint, [text]); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + /// + /// 发送二进制数据 + /// + /// IPV4 或者 IPV6 地址 + /// 设备端口号 + /// 16进制文本 + [HttpPost("SendBytes")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendBytes(string address, int port, string bytes) + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendBytesAsync(endPoint, Number.StringToBytes(bytes)); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + + /// + /// 发送地址包 + /// + /// IP地址 + /// UDP 端口号 + /// 地址包选项 + [HttpPost("SendAddrPackage")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendAddrPackage( + string address, + int port, + [FromBody] SendAddrPackOptions opts) + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts)); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + /// + /// 发送数据包 + /// + /// IP地址 + /// UDP 端口号 + /// 16进制数据 + [HttpPost("SendDataPackage")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendDataPackage(string address, int port, string data) + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendDataPackAsync(endPoint, + new WebProtocol.SendDataPackage(Number.StringToBytes(data))); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + /// + /// 获取指定IP地址接受的数据列表 + /// + /// IP地址 + [HttpGet("GetRecvDataArray")] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask GetRecvDataArray(string address) + { + var ret = await MsgBus.UDPServer.GetDataArrayAsync(address); + + if (ret.HasValue) + { + var dataJson = JsonConvert.SerializeObject(ret.Value); + logger.Debug($"Get Receive Successfully: {dataJson}"); + + return TypedResults.Ok(ret.Value); + } + else + { + logger.Debug("Get Receive Failed"); + return TypedResults.InternalServerError(); + } + } + +} + +/// +/// Jtag API +/// +[ApiController] +[Route("api/[controller]")] +public class JtagController : ControllerBase +{ + /// + /// 页面 + /// + [HttpGet] + public string Index() + { + return "This is Jtag Controller"; + } + /// + /// 执行一个Jtag命令 + /// + /// 设备地址 + /// 设备端口 + /// 16进制设备目的地址(Jtag) + /// 16进制命令 + [HttpPost("RunCommand")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask RunCommand(string address, int port, string hexDevAddr, string hexCmd) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.RunCommand(Convert.ToUInt32(hexDevAddr, 16), Convert.ToUInt32(hexCmd, 16)); + + if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } + else { return TypedResults.InternalServerError(ret.Error); } + } + + + /// + /// 获取Jtag ID Code + /// + /// 设备地址 + /// 设备端口 + [HttpGet("GetDeviceIDCode")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask GetDeviceIDCode(string address, int port) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.ReadIDCode(); + + if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } + else { return TypedResults.InternalServerError(ret.Error); } + } +} diff --git a/server/src/JtagController.cs b/server/src/JtagClient.cs similarity index 99% rename from server/src/JtagController.cs rename to server/src/JtagClient.cs index 3146ef1..5fb6e4e 100644 --- a/server/src/JtagController.cs +++ b/server/src/JtagClient.cs @@ -3,7 +3,7 @@ using Common; using DotNext; using WebProtocol; -namespace JtagController; +namespace JtagClient; /// /// Global Constant Jtag Address diff --git a/server/src/Router.cs b/server/src/Router.cs deleted file mode 100644 index 34d92ac..0000000 --- a/server/src/Router.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System.Net; -using Common; -using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json; -using WebProtocol; - -namespace Router -{ - /// - /// Custom Web Http Response - /// - public class Response - { - /// - /// 是否成功执行 - /// - public bool IsSuccess { get; set; } - - /// - /// 数据 - /// - public object? Data { get; set; } - - /// - /// 转换为Json格式的字符串 - /// - /// Json字符串 - public override string ToString() - { - return JsonConvert.SerializeObject(this); - } - } - - /// - /// Web API - /// - class API - { - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - private const string LOCALHOST = "127.0.0.1"; - - /// - /// 发送字符串 - /// - /// IPV4 或者 IPV6 地址 - /// 设备端口号 - /// Text for send - [HttpPost("{address}/{port}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public static async ValueTask SendString(string address, int port, string text) - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendStringAsync(endPoint, [text]); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - /// - /// 发送二进制数据 - /// - /// IPV4 或者 IPV6 地址 - /// 设备端口号 - /// 16进制文本 - [HttpPost("{address}/{port}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public static async ValueTask SendBytes(string address, int port, string bytes) - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendBytesAsync(endPoint, Number.StringToBytes(bytes)); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - - /// - /// 发送地址包 - /// - /// IP地址 - /// UDP 端口号 - /// 地址包选项 - [HttpPost("{address}/{port}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public static async ValueTask SendAddrPackage( - string address, - int port, - [FromBody] SendAddrPackOptions opts) - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts)); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - [HttpPost("{address}/{port}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public static async ValueTask SendDataPackage(string address, int port, string data) - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendDataPackAsync(endPoint, - new WebProtocol.SendDataPackage(Number.StringToBytes(data))); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - [HttpGet("{address}")] - [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public static async ValueTask GetRecvDataArray(string address) - { - var ret = await MsgBus.UDPServer.GetDataArrayAsync(address); - - if (ret.HasValue) - { - var dataJson = JsonConvert.SerializeObject(ret.Value); - logger.Debug($"Get Receive Successfully: {dataJson}"); - - return TypedResults.Ok(ret.Value); - } - else - { - logger.Debug("Get Receive Failed"); - return TypedResults.InternalServerError(); - } - } - - public class Jtag - { - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - /// - /// 执行一个Jtag命令 - /// - /// 设备地址 - /// 设备端口 - /// 16进制设备目的地址(Jtag) - /// 16进制命令 - [HttpPost] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public static async ValueTask RunCommand(string address, int port, string hexDevAddr, string hexCmd) - { - var jtagCtrl = new JtagController.Jtag(address, port); - var ret = await jtagCtrl.RunCommand(Convert.ToUInt32(hexDevAddr, 16), Convert.ToUInt32(hexCmd, 16)); - - if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } - else { return TypedResults.InternalServerError(ret.Error); } - } - - - /// - /// 获取Jtag ID Code - /// - /// 设备地址 - /// 设备端口 - [HttpGet] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public static async ValueTask GetDeviceIDCode(string address, int port) - { - var jtagCtrl = new JtagController.Jtag(address, port); - var ret = await jtagCtrl.ReadIDCode(); - - if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } - else { return TypedResults.InternalServerError(ret.Error); } - } - - - } - } -} diff --git a/server/src/UdpServer.cs b/server/src/UdpServer.cs index e4eb4ff..1295bbe 100644 --- a/server/src/UdpServer.cs +++ b/server/src/UdpServer.cs @@ -2,7 +2,6 @@ using System.Net; using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Text; -using System.Threading.Tasks; using DotNext; using DotNext.Threading; using Newtonsoft.Json;